From 83a5a0c612b7ca97529720f8a35117957d4cb9a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Fri, 3 Nov 2023 07:18:17 +0900 Subject: [PATCH] fix(es/compat): Handle private names from class properties pass (#8090) **Related issue:** - Closes #7561 - https://github.com/vercel/next.js/issues/56612 --- Cargo.lock | 1 + crates/swc/src/builder.rs | 4 +- .../issues-7xxx/7561/es2019/input/.swcrc | 19 + .../issues-7xxx/7561/es2019/input/1.js | 7 + .../issues-7xxx/7561/es2019/output/1.js | 15 + .../issues-7xxx/7561/es2021/input/.swcrc | 19 + .../issues-7xxx/7561/es2021/input/1.js | 7 + .../issues-7xxx/7561/es2021/output/1.js | 15 + .../issues-7xxx/7561/es2022/input/.swcrc | 19 + .../issues-7xxx/7561/es2022/input/1.js | 7 + .../issues-7xxx/7561/es2022/output/1.js | 6 + ...privateNameFieldCallExpression.1.normal.js | 5 +- ...eNameStaticFieldCallExpression.1.normal.js | 4 +- crates/swc_ecma_compat_es2020/Cargo.toml | 1 + .../src/optional_chaining.rs | 462 +---- .../src/class_properties/mod.rs | 34 +- .../src/class_properties/private_field.rs | 130 +- crates/swc_ecma_compat_es2022/src/lib.rs | 7 +- .../src/optional_chaining_impl.rs | 470 ++++++ .../src/static_blocks.rs | 6 +- crates/swc_ecma_preset_env/src/lib.rs | 4 +- .../swc_ecma_transforms/tests/decorators.rs | 591 +++++-- .../tests/es2015_function_name.rs | 26 +- .../tests/es2015_classes.rs/issue_1959_1.js | 4 +- .../tests/es2015_classes.rs/issue_1959_2.js | 4 +- .../es2022_class_properties.rs/issue_8003.js | 4 +- .../private_optional_chain_call.js | 3 +- .../regression_6153.js | 2 +- .../class-properties/issue-7561/input.js | 7 + .../class-properties/issue-7561/output.js | 13 + .../tests/classes/create-super-1/output.js | 4 +- .../tests/classes/issue-1959/1/output.js | 18 + .../tests/classes/issue-1959/2/output.js | 18 + .../tests/es2015_classes.rs | 78 +- .../tests/es2015_generator.rs | 19 +- .../tests/es2015_new_target.rs | 11 +- .../tests/es2017_async_to_generator.rs | 48 +- .../tests/es2020_optional_chaining.rs | 28 +- .../tests/es2022_class_properties.rs | 1480 ++++++++++++++--- .../tests/es2022_private_in_object.rs | 18 +- .../tests/es2022_static_blocks.rs | 14 +- .../issue-7559/output.js | 12 +- .../optional-chaining/issue-7561/input.js | 7 + .../optional-chaining/issue-7561/output.js | 13 + .../private-field-call/input.js | 9 + .../private-field-call/output.js | 17 + .../tests/simplify.rs | 9 +- .../tests/simplify_dce.rs | 9 +- .../tests/simplify_inlining.rs | 6 +- .../tests/decorators.rs | 6 +- .../benches/compat.rs | 95 +- .../tests/strip.rs | 11 +- 52 files changed, 2723 insertions(+), 1103 deletions(-) create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/1.js create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/1.js create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/.swcrc create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/1.js create mode 100644 crates/swc/tests/fixture/issues-7xxx/7561/es2022/output/1.js create mode 100644 crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs create mode 100644 crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/input.js create mode 100644 crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/output.js create mode 100644 crates/swc_ecma_transforms_compat/tests/classes/issue-1959/1/output.js create mode 100644 crates/swc_ecma_transforms_compat/tests/classes/issue-1959/2/output.js create mode 100644 crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/input.js create mode 100644 crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/output.js create mode 100644 crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/input.js create mode 100644 crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/output.js diff --git a/Cargo.lock b/Cargo.lock index b677cbb794df..2abeb6f2b809 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4316,6 +4316,7 @@ dependencies = [ "swc_atoms", "swc_common", "swc_ecma_ast", + "swc_ecma_compat_es2022", "swc_ecma_parser", "swc_ecma_transforms_base", "swc_ecma_transforms_testing", diff --git a/crates/swc/src/builder.rs b/crates/swc/src/builder.rs index e335ee6fd386..5a58cb4c8b49 100644 --- a/crates/swc/src/builder.rs +++ b/crates/swc/src/builder.rs @@ -223,8 +223,10 @@ impl<'a, 'b, P: swc_ecma_visit::Fold> PassBuilder<'a, 'b, P> { set_public_fields: assumptions.set_public_class_fields, no_document_all: assumptions.no_document_all, static_blocks_mark: Mark::new(), + pure_getter: assumptions.pure_getters, } - } + }, + self.unresolved_mark ), should_enable(self.target, EsVersion::Es2022) ), diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/.swcrc new file mode 100644 index 000000000000..b57ec4d34985 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/.swcrc @@ -0,0 +1,19 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": false + }, + "target": "es2019", + "loose": false, + "minify": { + "compress": false, + "mangle": false + } + }, + "module": { + "type": "commonjs" + }, + "minify": false, + "isModule": false +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/1.js new file mode 100644 index 000000000000..8a79d38839e4 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/input/1.js @@ -0,0 +1,7 @@ +class Foo { + #x; + + test() { + this?.y.#x + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js new file mode 100644 index 000000000000..b25065e0344a --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js @@ -0,0 +1,15 @@ +var _class_private_field_get = require("@swc/helpers/_/_class_private_field_get"); +var _class_private_field_init = require("@swc/helpers/_/_class_private_field_init"); +var _x = /*#__PURE__*/ new WeakMap(); +class Foo { + test() { + var _this, _this_y; + (_this = this) === null || _this === void 0 ? void 0 : _class_private_field_get._(_this_y = _this.y, _x); + } + constructor(){ + _class_private_field_init._(this, _x, { + writable: true, + value: void 0 + }); + } +} diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/.swcrc new file mode 100644 index 000000000000..af433717fb75 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/.swcrc @@ -0,0 +1,19 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": false + }, + "target": "es2021", + "loose": false, + "minify": { + "compress": false, + "mangle": false + } + }, + "module": { + "type": "commonjs" + }, + "minify": false, + "isModule": false +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/1.js new file mode 100644 index 000000000000..8a79d38839e4 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/input/1.js @@ -0,0 +1,7 @@ +class Foo { + #x; + + test() { + this?.y.#x + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js new file mode 100644 index 000000000000..b25065e0344a --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js @@ -0,0 +1,15 @@ +var _class_private_field_get = require("@swc/helpers/_/_class_private_field_get"); +var _class_private_field_init = require("@swc/helpers/_/_class_private_field_init"); +var _x = /*#__PURE__*/ new WeakMap(); +class Foo { + test() { + var _this, _this_y; + (_this = this) === null || _this === void 0 ? void 0 : _class_private_field_get._(_this_y = _this.y, _x); + } + constructor(){ + _class_private_field_init._(this, _x, { + writable: true, + value: void 0 + }); + } +} diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/.swcrc b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/.swcrc new file mode 100644 index 000000000000..fcba662501f3 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/.swcrc @@ -0,0 +1,19 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": false + }, + "target": "es2022", + "loose": false, + "minify": { + "compress": false, + "mangle": false + } + }, + "module": { + "type": "commonjs" + }, + "minify": false, + "isModule": false +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/1.js new file mode 100644 index 000000000000..8a79d38839e4 --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/input/1.js @@ -0,0 +1,7 @@ +class Foo { + #x; + + test() { + this?.y.#x + } +} \ No newline at end of file diff --git a/crates/swc/tests/fixture/issues-7xxx/7561/es2022/output/1.js b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/output/1.js new file mode 100644 index 000000000000..ef5849e04d4d --- /dev/null +++ b/crates/swc/tests/fixture/issues-7xxx/7561/es2022/output/1.js @@ -0,0 +1,6 @@ +class Foo { + #x; + test() { + this?.y.#x; + } +} diff --git a/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js b/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js index 7c272bb63a77..b6b737e7bc90 100644 --- a/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/privateNameFieldCallExpression.1.normal.js @@ -5,10 +5,9 @@ import { _ as _class_private_field_set } from "@swc/helpers/_/_class_private_fie var _fieldFunc = /*#__PURE__*/ new WeakMap(), _fieldFunc2 = /*#__PURE__*/ new WeakMap(); class A { test() { - var _class_private_field_get1; - var _this_getInstance; + var _this, _this1, _ref, _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); + (_this = _class_private_field_get(_ref = _this1 = this, _fieldFunc)) === null || _this === void 0 ? void 0 : _this.call(_this1); 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 11b16b455782..1dfb02539139 100644 --- a/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js +++ b/crates/swc/tests/tsc-references/privateNameStaticFieldCallExpression.1.normal.js @@ -2,9 +2,9 @@ import { _ as _class_static_private_field_spec_get } from "@swc/helpers/_/_class_static_private_field_spec_get"; class A { test() { - var _class_static_private_field_spec_get1; + var _this; _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); + (_this = _class_static_private_field_spec_get(A, A, _fieldFunc)) === null || _this === void 0 ? void 0 : _this.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_compat_es2020/Cargo.toml b/crates/swc_ecma_compat_es2020/Cargo.toml index 52e77705d03a..ddd7658c59da 100644 --- a/crates/swc_ecma_compat_es2020/Cargo.toml +++ b/crates/swc_ecma_compat_es2020/Cargo.toml @@ -17,6 +17,7 @@ serde = { version = "1.0.188", features = ["derive"] } swc_atoms = { version = "0.6.0", path = "../swc_atoms" } swc_common = { version = "0.33.2", path = "../swc_common" } swc_ecma_ast = { version = "0.110.2", path = "../swc_ecma_ast" } +swc_ecma_compat_es2022 = { version = "0.1.9", path = "../swc_ecma_compat_es2022" } swc_ecma_transforms_base = { version = "0.134.13", path = "../swc_ecma_transforms_base" } swc_ecma_utils = { version = "0.124.11", path = "../swc_ecma_utils" } swc_ecma_visit = { version = "0.96.2", path = "../swc_ecma_visit" } diff --git a/crates/swc_ecma_compat_es2020/src/optional_chaining.rs b/crates/swc_ecma_compat_es2020/src/optional_chaining.rs index 034907e4a294..66c74a203cdf 100644 --- a/crates/swc_ecma_compat_es2020/src/optional_chaining.rs +++ b/crates/swc_ecma_compat_es2020/src/optional_chaining.rs @@ -1,26 +1,16 @@ -use std::mem; - use serde::Deserialize; -use swc_common::{util::take::Take, Mark, SyntaxContext, DUMMY_SP}; -use swc_ecma_ast::*; -use swc_ecma_utils::{ - alias_ident_for, prepend_stmt, quote_ident, undefined, ExprFactory, StmtLike, -}; -use swc_ecma_visit::{as_folder, noop_visit_mut_type, Fold, VisitMut, VisitMutWith}; +use swc_common::Mark; +use swc_ecma_compat_es2022::optional_chaining_impl::optional_chaining_impl; +use swc_ecma_visit::{as_folder, Fold, VisitMut}; pub fn optional_chaining(c: Config, unresolved_mark: Mark) -> impl Fold + VisitMut { - as_folder(OptChaining { - c, - unresolved: SyntaxContext::empty().apply_mark(unresolved_mark), - ..Default::default() - }) -} - -#[derive(Default)] -struct OptChaining { - vars: Vec, - unresolved: SyntaxContext, - c: Config, + as_folder(optional_chaining_impl( + swc_ecma_compat_es2022::optional_chaining_impl::Config { + no_document_all: c.no_document_all, + pure_getter: c.pure_getter, + }, + unresolved_mark, + )) } #[derive(Debug, Clone, Copy, Default, Deserialize)] @@ -31,435 +21,3 @@ pub struct Config { #[serde(default)] pub pure_getter: bool, } - -impl VisitMut for OptChaining { - noop_visit_mut_type!(); - - fn visit_mut_block_stmt_or_expr(&mut self, expr: &mut BlockStmtOrExpr) { - if let BlockStmtOrExpr::Expr(e) = expr { - let mut stmt = BlockStmt { - span: DUMMY_SP, - stmts: vec![Stmt::Return(ReturnStmt { - span: DUMMY_SP, - arg: Some(e.take()), - })], - }; - stmt.visit_mut_with(self); - - // If there are optional chains in this expression, then the visitor will have - // injected an VarDecl statement and we need to transform into a - // block. If not, then we can keep the expression. - match &mut stmt.stmts[..] { - [Stmt::Return(ReturnStmt { arg: Some(e), .. })] => { - *expr = BlockStmtOrExpr::Expr(e.take()) - } - _ => *expr = BlockStmtOrExpr::BlockStmt(stmt), - } - } else { - expr.visit_mut_children_with(self); - } - } - - fn visit_mut_expr(&mut self, e: &mut Expr) { - match e { - // foo?.bar -> foo == null ? void 0 : foo.bar - Expr::OptChain(v) => { - let data = self.gather(v.take(), vec![]); - *e = self.construct(data, false); - } - - Expr::Unary(UnaryExpr { - arg, - op: op!("delete"), - .. - }) => { - match &mut **arg { - // delete foo?.bar -> foo == null ? true : delete foo.bar - Expr::OptChain(v) => { - let data = self.gather(v.take(), vec![]); - *e = self.construct(data, true); - } - _ => e.visit_mut_children_with(self), - } - } - - e => e.visit_mut_children_with(self), - } - } - - fn visit_mut_pat(&mut self, n: &mut Pat) { - // The default initializer of an assignment pattern must not leak the memo - // variable into the enclosing scope. - // function(a, b = a?.b) {} -> function(a, b = (() => var _a; …)()) {} - let Pat::Assign(a) = n else { - n.visit_mut_children_with(self); - return; - }; - - let uninit = self.vars.take(); - a.right.visit_mut_with(self); - - // If we found an optional chain, we need to transform into an arrow IIFE to - // capture the memo variable. - if !self.vars.is_empty() { - let stmts = vec![ - Stmt::Decl(Decl::Var(Box::new(VarDecl { - span: DUMMY_SP, - declare: false, - kind: VarDeclKind::Var, - decls: mem::take(&mut self.vars), - }))), - Stmt::Return(ReturnStmt { - span: DUMMY_SP, - arg: Some(a.right.take()), - }), - ]; - a.right = Box::new(Expr::Call(CallExpr { - span: DUMMY_SP, - callee: Expr::Arrow(ArrowExpr { - span: DUMMY_SP, - params: vec![], - body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { - span: DUMMY_SP, - stmts, - })), - is_async: false, - is_generator: false, - type_params: Default::default(), - return_type: Default::default(), - }) - .as_callee(), - args: vec![], - type_args: Default::default(), - })); - } - - self.vars = uninit; - a.left.visit_mut_with(self); - } - - fn visit_mut_module_items(&mut self, n: &mut Vec) { - self.visit_mut_stmt_like(n); - } - - fn visit_mut_stmts(&mut self, n: &mut Vec) { - self.visit_mut_stmt_like(n); - } -} - -#[derive(Debug, Clone)] -enum Memo { - Cache(Ident), - Raw(Box), -} - -impl Memo { - fn into_expr(self) -> Expr { - match self { - Memo::Cache(i) => Expr::Ident(i), - Memo::Raw(e) => *e, - } - } -} - -#[derive(Debug)] -enum Gathering { - Call(CallExpr), - Member(MemberExpr), - OptCall(CallExpr, Memo), - OptMember(MemberExpr, Memo), -} - -impl OptChaining { - /// Transforms the left-nested structure into a flat vec. The obj/callee - /// of every node in the chain will be Invalid, to be replaced with a - /// constructed node in the construct step. - /// The top member/call will be first, and the deepest obj/callee will be - /// last. - fn gather( - &mut self, - v: OptChainExpr, - mut chain: Vec, - ) -> (Expr, usize, Vec) { - let mut current = v; - let mut count = 0; - loop { - let OptChainExpr { - optional, mut base, .. - } = current; - - if optional { - count += 1; - } - - let next; - match &mut *base { - OptChainBase::Member(m) => { - next = m.obj.take(); - m.prop.visit_mut_with(self); - chain.push(if optional { - Gathering::OptMember(m.take(), self.memoize(&next, false)) - } else { - Gathering::Member(m.take()) - }); - } - - OptChainBase::Call(c) => { - next = c.callee.take(); - c.args.visit_mut_with(self); - // I don't know why c is an OptCall instead of a CallExpr. - chain.push(if optional { - Gathering::OptCall(c.take().into(), self.memoize(&next, true)) - } else { - Gathering::Call(c.take().into()) - }); - } - } - - match *next { - Expr::OptChain(next) => { - current = next; - } - mut base => { - base.visit_mut_children_with(self); - return (base, count, chain); - } - } - } - } - - /// Constructs a rightward nested conditional expression out of our - /// flattened chain. - fn construct(&mut self, data: (Expr, usize, Vec), is_delete: bool) -> Expr { - let (mut current, count, chain) = data; - - // Stores partially constructed CondExprs for us to assemble later on. - let mut committed_cond = Vec::with_capacity(count); - - // Stores the memo used to construct an optional chain, so that it can be used - // as the this context of an optional call: - // foo?.bar?.() -> - // (_foo = foo) == null - // ? void 0 - // : (_foo_bar = _foo.bar) == null - // ? void 0 : _foo_bar.call(_foo) - let mut ctx = None; - - // In the first pass, we construct a "current" node and several committed - // CondExprs. The conditionals will have an invalid alt, waiting for the - // second pass to properly construct them. - // We reverse iterate so that we can construct a rightward conditional - // `(_a = a) == null ? void 0 : (_a_b = _a.b) == null ? void 0 : _a_b.c` - // instead of a leftward one - // `(_a_b = (_a = a) == null ? void 0 : _a.b) == null ? void 0 : _a_b.c` - for v in chain.into_iter().rev() { - current = match v { - Gathering::Call(mut c) => { - c.callee = current.as_callee(); - ctx = None; - Expr::Call(c) - } - Gathering::Member(mut m) => { - m.obj = Box::new(current); - ctx = None; - Expr::Member(m) - } - Gathering::OptCall(mut c, memo) => { - let mut call = false; - - // foo.bar?.() -> (_foo_bar == null) ? void 0 : _foo_bar.call(foo) - match &mut current { - Expr::Member(m) => { - call = true; - let this = ctx.unwrap_or_else(|| { - let this = self.memoize(&m.obj, true); - - match &this { - Memo::Cache(i) => { - m.obj = Box::new(Expr::Assign(AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: i.clone().into(), - right: m.obj.take(), - })); - this - } - Memo::Raw(_) => this, - } - }); - c.args.insert(0, this.into_expr().as_arg()); - } - Expr::SuperProp(s) => { - call = true; - c.args.insert(0, ThisExpr { span: s.obj.span }.as_arg()); - } - _ => {} - } - - committed_cond.push(CondExpr { - span: DUMMY_SP, - test: init_and_eq_null_or_undefined(&memo, current, self.c.no_document_all), - cons: if is_delete { - true.into() - } else { - undefined(DUMMY_SP) - }, - alt: Take::dummy(), - }); - c.callee = if call { - memo.into_expr() - .make_member(quote_ident!("call")) - .as_callee() - } else { - memo.into_expr().as_callee() - }; - ctx = None; - Expr::Call(c) - } - Gathering::OptMember(mut m, memo) => { - committed_cond.push(CondExpr { - span: DUMMY_SP, - test: init_and_eq_null_or_undefined(&memo, current, self.c.no_document_all), - cons: if is_delete { - true.into() - } else { - undefined(DUMMY_SP) - }, - alt: Take::dummy(), - }); - ctx = Some(memo.clone()); - m.obj = memo.into_expr().into(); - Expr::Member(m) - } - }; - } - - // At this point, `current` is the right-most expression `_a_b.c` in `a?.b?.c` - if is_delete { - current = Expr::Unary(UnaryExpr { - span: DUMMY_SP, - op: op!("delete"), - arg: Box::new(current), - }); - } - - // We now need to reverse iterate the conditionals to construct out tree. - for mut cond in committed_cond.into_iter().rev() { - cond.alt = Box::new(current); - current = Expr::Cond(cond) - } - current - } - - fn should_memo(&self, expr: &Expr, is_call: bool) -> bool { - fn is_simple_member(e: &Expr) -> bool { - match e { - Expr::Ident(_) => true, - Expr::SuperProp(s) if !s.prop.is_computed() => true, - Expr::Member(m) if !m.prop.is_computed() => is_simple_member(&m.obj), - _ => false, - } - } - - match expr { - Expr::Ident(i) if i.span.ctxt != self.unresolved => false, - _ => { - if is_call && self.c.pure_getter { - !is_simple_member(expr) - } else { - true - } - } - } - } - - fn memoize(&mut self, expr: &Expr, is_call: bool) -> Memo { - if self.should_memo(expr, is_call) { - let memo = alias_ident_for(expr, "_this"); - self.vars.push(VarDeclarator { - span: DUMMY_SP, - name: memo.clone().into(), - init: None, - definite: false, - }); - Memo::Cache(memo) - } else { - Memo::Raw(Box::new(expr.to_owned())) - } - } - - fn visit_mut_stmt_like(&mut self, stmts: &mut Vec) - where - T: Send + Sync + StmtLike + VisitMutWith, - Vec: VisitMutWith, - { - let uninit = self.vars.take(); - for stmt in stmts.iter_mut() { - stmt.visit_mut_with(self); - } - - if !self.vars.is_empty() { - prepend_stmt( - stmts, - T::from_stmt( - VarDecl { - span: DUMMY_SP, - declare: false, - kind: VarDeclKind::Var, - decls: mem::take(&mut self.vars), - } - .into(), - ), - ); - } - - self.vars = uninit; - } -} - -fn init_and_eq_null_or_undefined(i: &Memo, init: Expr, no_document_all: bool) -> Box { - let lhs = match i { - Memo::Cache(i) => Box::new(Expr::Assign(AssignExpr { - span: DUMMY_SP, - op: op!("="), - left: PatOrExpr::Pat(i.clone().into()), - right: Box::new(init), - })), - Memo::Raw(e) => e.to_owned(), - }; - - if no_document_all { - return Box::new(Expr::Bin(BinExpr { - span: DUMMY_SP, - left: lhs, - op: op!("=="), - right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), - })); - } - - let null_cmp = Box::new(Expr::Bin(BinExpr { - span: DUMMY_SP, - left: lhs, - op: op!("==="), - right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), - })); - - let left_expr = match i { - Memo::Cache(i) => Box::new(i.clone().into()), - Memo::Raw(e) => e.to_owned(), - }; - - let void_cmp = Box::new(Expr::Bin(BinExpr { - span: DUMMY_SP, - left: left_expr, - op: op!("==="), - right: undefined(DUMMY_SP), - })); - - Box::new(Expr::Bin(BinExpr { - span: DUMMY_SP, - left: null_cmp, - op: op!("||"), - right: void_cmp, - })) -} diff --git a/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs b/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs index c83ebc23160a..b6228442d68b 100644 --- a/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs +++ b/crates/swc_ecma_compat_es2022/src/class_properties/mod.rs @@ -43,12 +43,17 @@ mod used_name; /// # Impl note /// /// We use custom helper to handle export default class -pub fn class_properties(cm: Option, config: Config) -> impl Fold + VisitMut { +pub fn class_properties( + cm: Option, + config: Config, + unresolved_mark: Mark, +) -> impl Fold + VisitMut { as_folder(ClassProperties { c: config, cm, private: PrivateRecord::new(), extra: ClassExtra::default(), + unresolved_mark, }) } @@ -58,6 +63,7 @@ pub struct Config { pub set_public_fields: bool, pub constant_super: bool, pub no_document_all: bool, + pub pure_getter: bool, pub static_blocks_mark: Mark, } @@ -68,6 +74,7 @@ impl Default for Config { set_public_fields: false, constant_super: false, no_document_all: false, + pure_getter: false, static_blocks_mark: Mark::new(), } } @@ -78,6 +85,7 @@ struct ClassProperties { c: Config, cm: Option, private: PrivateRecord, + unresolved_mark: Mark, } #[derive(Default)] @@ -551,7 +559,12 @@ impl ClassProperties { span: c_span, mut expr, }) if should_create_vars_for_method_names && !is_literal(&*expr) => { - vars.extend(visit_private_in_expr(&mut expr, &self.private, self.c)); + vars.extend(visit_private_in_expr( + &mut expr, + &self.private, + self.c, + self.unresolved_mark, + )); expr.visit_mut_with(&mut ClassNameTdzFolder { class_name: &class_ident, @@ -598,6 +611,7 @@ impl ClassProperties { &mut key.expr, &self.private, self.c, + self.unresolved_mark, )); let (ident, aliased) = if let Expr::Ident(i) = &*key.expr { if used_key_names.contains(&i.sym) { @@ -626,7 +640,12 @@ impl ClassProperties { value.visit_mut_with(&mut NewTargetInProp); - vars.extend(visit_private_in_expr(&mut value, &self.private, self.c)); + vars.extend(visit_private_in_expr( + &mut value, + &self.private, + self.c, + self.unresolved_mark, + )); if prop.is_static { if let (Some(super_class), None) = (&mut class.super_class, &super_ident) { @@ -706,7 +725,12 @@ impl ClassProperties { in_pat: false, }); } - vars.extend(visit_private_in_expr(&mut *value, &self.private, self.c)); + vars.extend(visit_private_in_expr( + &mut *value, + &self.private, + self.c, + self.unresolved_mark, + )); } prop.value.visit_with(&mut UsedNameCollector { @@ -945,6 +969,7 @@ impl ClassProperties { vars: vec![], private_access_type: Default::default(), c: self.c, + unresolved_mark: self.unresolved_mark, }); let mut extra_stmts = extra_inits.into_init_static(class_ident.clone()); @@ -956,6 +981,7 @@ impl ClassProperties { vars: vec![], private_access_type: Default::default(), c: self.c, + unresolved_mark: self.unresolved_mark, }); self.private.pop(); diff --git a/crates/swc_ecma_compat_es2022/src/class_properties/private_field.rs b/crates/swc_ecma_compat_es2022/src/class_properties/private_field.rs index a25c2c57a883..1aff17a60e09 100644 --- a/crates/swc_ecma_compat_es2022/src/class_properties/private_field.rs +++ b/crates/swc_ecma_compat_es2022/src/class_properties/private_field.rs @@ -9,14 +9,12 @@ use swc_common::{ }; use swc_ecma_ast::*; use swc_ecma_transforms_base::helper; -use swc_ecma_utils::{ - alias_ident_for, alias_if_required, opt_chain_test, prepend_stmt, quote_ident, undefined, - ExprFactory, -}; +use swc_ecma_utils::{alias_ident_for, alias_if_required, prepend_stmt, quote_ident, ExprFactory}; use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; use swc_trace_macro::swc_trace; use super::Config; +use crate::optional_chaining_impl::optional_chaining_impl; pub(super) struct Private { pub mark: Mark, @@ -171,6 +169,7 @@ pub(super) struct PrivateAccessVisitor<'a> { pub private: &'a PrivateRecord, pub private_access_type: PrivateAccessType, pub c: Config, + pub unresolved_mark: Mark, } macro_rules! take_vars { @@ -213,6 +212,36 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> { take_vars!(visit_mut_constructor, Constructor); fn visit_mut_expr(&mut self, e: &mut Expr) { + if let Expr::OptChain(opt) = e { + let is_private_access = match &*opt.base { + OptChainBase::Member(MemberExpr { + prop: MemberProp::PrivateName(..), + .. + }) => true, + OptChainBase::Call(OptCall { callee, .. }) => matches!( + &**callee, + Expr::Member(MemberExpr { + prop: MemberProp::PrivateName(..), + .. + }) + ), + _ => false, + }; + + if is_private_access { + let mut v = optional_chaining_impl( + crate::optional_chaining_impl::Config { + no_document_all: self.c.no_document_all, + pure_getter: self.c.pure_getter, + }, + self.unresolved_mark, + ); + e.visit_mut_with(&mut v); + assert!(!e.is_opt_chain(), "optional chaining should be removed"); + self.vars.extend(v.take_vars()); + } + } + if self.c.private_as_properties { if let Expr::Member(MemberExpr { span, @@ -434,102 +463,11 @@ impl<'a> VisitMut for PrivateAccessVisitor<'a> { } } - Expr::OptChain(OptChainExpr { - base, - optional, - span, - }) if match &**base { - OptChainBase::Call(call) => call.callee.is_member(), - _ => false, - } => - { - let call = match &mut **base { - OptChainBase::Call(call) => call, - _ => unreachable!(), - }; - - let mut callee = call.callee.take().member().unwrap(); - callee.visit_mut_with(self); - call.args.visit_mut_with(self); - - 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(); - let call = OptCall { - span: *span, - 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); - } - } - Expr::Member(member_expr) => { member_expr.visit_mut_children_with(self); *e = self.visit_mut_private_get(member_expr, None).0; } - Expr::OptChain(OptChainExpr { base, span, .. }) - if matches!( - &**base, - OptChainBase::Member(MemberExpr { - prop: MemberProp::PrivateName(..), - .. - },) - ) => - { - let member = match &mut **base { - OptChainBase::Member( - member @ MemberExpr { - prop: MemberProp::PrivateName(..), - .. - }, - ) => member, - _ => { - unreachable!() - } - }; - member.visit_mut_children_with(self); - let (ident, aliased) = alias_if_required(&member.obj, "_ref"); - if aliased { - self.vars.push(VarDeclarator { - span: DUMMY_SP, - name: ident.clone().into(), - init: None, - definite: false, - }); - } - let (expr, _) = self.visit_mut_private_get(member, None); - *e = Expr::Cond(CondExpr { - span: *span, - test: Box::new(opt_chain_test( - Box::new(ident.clone().into()), - Box::new(ident.into()), - *span, - self.c.no_document_all, - )), - cons: undefined(DUMMY_SP), - alt: Box::new(expr), - }) - } _ => e.visit_mut_children_with(self), }; } @@ -557,12 +495,14 @@ pub(super) fn visit_private_in_expr( expr: &mut Expr, private: &PrivateRecord, config: Config, + unresolved_mark: Mark, ) -> Vec { let mut priv_visitor = PrivateAccessVisitor { private, vars: vec![], private_access_type: Default::default(), c: config, + unresolved_mark, }; expr.visit_mut_with(&mut priv_visitor); diff --git a/crates/swc_ecma_compat_es2022/src/lib.rs b/crates/swc_ecma_compat_es2022/src/lib.rs index 70f9939df4be..2611710a02e7 100644 --- a/crates/swc_ecma_compat_es2022/src/lib.rs +++ b/crates/swc_ecma_compat_es2022/src/lib.rs @@ -1,6 +1,6 @@ #![allow(clippy::vec_box)] -use swc_common::{chain, comments::Comments}; +use swc_common::{chain, comments::Comments, Mark}; use swc_ecma_compat_common::regexp::{self, regexp}; use swc_ecma_visit::Fold; @@ -10,10 +10,11 @@ pub use self::{ }; pub mod class_properties; +pub mod optional_chaining_impl; pub mod private_in_object; pub mod static_blocks; -pub fn es2022(cm: Option, config: Config) -> impl Fold { +pub fn es2022(cm: Option, config: Config, unresolved_mark: Mark) -> impl Fold { chain!( regexp(regexp::Config { dot_all_regex: true, @@ -25,7 +26,7 @@ pub fn es2022(cm: Option, config: Config) -> impl Fold { unicode_regex: false, }), static_blocks(config.class_properties.static_blocks_mark), - class_properties(cm, config.class_properties), + class_properties(cm, config.class_properties, unresolved_mark), private_in_object(), ) } diff --git a/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs b/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs new file mode 100644 index 000000000000..2ab7eddc021f --- /dev/null +++ b/crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs @@ -0,0 +1,470 @@ +use std::mem; + +use swc_common::{util::take::Take, Mark, SyntaxContext, DUMMY_SP}; +use swc_ecma_ast::*; +use swc_ecma_utils::{ + alias_ident_for, prepend_stmt, quote_ident, undefined, ExprFactory, StmtLike, +}; +use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith}; + +/// Not a public API and may break any time. Don't use it directly. +pub fn optional_chaining_impl(c: Config, unresolved_mark: Mark) -> OptionalChaining { + OptionalChaining { + c, + unresolved_ctxt: SyntaxContext::empty().apply_mark(unresolved_mark), + ..Default::default() + } +} + +#[derive(Default)] +pub struct OptionalChaining { + vars: Vec, + unresolved_ctxt: SyntaxContext, + c: Config, +} + +impl OptionalChaining { + pub fn take_vars(&mut self) -> Vec { + mem::take(&mut self.vars) + } +} + +/// Not a public API and may break any time. Don't use it directly. +#[derive(Debug, Clone, Copy, Default)] +pub struct Config { + pub no_document_all: bool, + pub pure_getter: bool, +} + +impl VisitMut for OptionalChaining { + noop_visit_mut_type!(); + + fn visit_mut_block_stmt_or_expr(&mut self, expr: &mut BlockStmtOrExpr) { + if let BlockStmtOrExpr::Expr(e) = expr { + let mut stmt = BlockStmt { + span: DUMMY_SP, + stmts: vec![Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(e.take()), + })], + }; + stmt.visit_mut_with(self); + + // If there are optional chains in this expression, then the visitor will have + // injected an VarDecl statement and we need to transform into a + // block. If not, then we can keep the expression. + match &mut stmt.stmts[..] { + [Stmt::Return(ReturnStmt { arg: Some(e), .. })] => { + *expr = BlockStmtOrExpr::Expr(e.take()) + } + _ => *expr = BlockStmtOrExpr::BlockStmt(stmt), + } + } else { + expr.visit_mut_children_with(self); + } + } + + fn visit_mut_expr(&mut self, e: &mut Expr) { + match e { + // foo?.bar -> foo == null ? void 0 : foo.bar + Expr::OptChain(v) => { + let data = self.gather(v.take(), vec![]); + *e = self.construct(data, false); + } + + Expr::Unary(UnaryExpr { + arg, + op: op!("delete"), + .. + }) => { + match &mut **arg { + // delete foo?.bar -> foo == null ? true : delete foo.bar + Expr::OptChain(v) => { + let data = self.gather(v.take(), vec![]); + *e = self.construct(data, true); + } + _ => e.visit_mut_children_with(self), + } + } + + e => e.visit_mut_children_with(self), + } + } + + fn visit_mut_pat(&mut self, n: &mut Pat) { + // The default initializer of an assignment pattern must not leak the memo + // variable into the enclosing scope. + // function(a, b = a?.b) {} -> function(a, b = (() => var _a; …)()) {} + let Pat::Assign(a) = n else { + n.visit_mut_children_with(self); + return; + }; + + let uninit = self.vars.take(); + a.right.visit_mut_with(self); + + // If we found an optional chain, we need to transform into an arrow IIFE to + // capture the memo variable. + if !self.vars.is_empty() { + let stmts = vec![ + Stmt::Decl(Decl::Var(Box::new(VarDecl { + span: DUMMY_SP, + declare: false, + kind: VarDeclKind::Var, + decls: mem::take(&mut self.vars), + }))), + Stmt::Return(ReturnStmt { + span: DUMMY_SP, + arg: Some(a.right.take()), + }), + ]; + a.right = Box::new(Expr::Call(CallExpr { + span: DUMMY_SP, + callee: Expr::Arrow(ArrowExpr { + span: DUMMY_SP, + params: vec![], + body: Box::new(BlockStmtOrExpr::BlockStmt(BlockStmt { + span: DUMMY_SP, + stmts, + })), + is_async: false, + is_generator: false, + type_params: Default::default(), + return_type: Default::default(), + }) + .as_callee(), + args: vec![], + type_args: Default::default(), + })); + } + + self.vars = uninit; + a.left.visit_mut_with(self); + } + + fn visit_mut_module_items(&mut self, n: &mut Vec) { + self.visit_mut_stmt_like(n); + } + + fn visit_mut_stmts(&mut self, n: &mut Vec) { + self.visit_mut_stmt_like(n); + } +} + +#[derive(Debug, Clone)] +enum Memo { + Cache(Ident), + Raw(Box), +} + +impl Memo { + fn into_expr(self) -> Expr { + match self { + Memo::Cache(i) => Expr::Ident(i), + Memo::Raw(e) => *e, + } + } +} + +#[derive(Debug)] +enum Gathering { + Call(CallExpr), + Member(MemberExpr), + OptCall(CallExpr, Memo), + OptMember(MemberExpr, Memo), +} + +impl OptionalChaining { + /// Transforms the left-nested structure into a flat vec. The obj/callee + /// of every node in the chain will be Invalid, to be replaced with a + /// constructed node in the construct step. + /// The top member/call will be first, and the deepest obj/callee will be + /// last. + fn gather( + &mut self, + v: OptChainExpr, + mut chain: Vec, + ) -> (Expr, usize, Vec) { + let mut current = v; + let mut count = 0; + loop { + let OptChainExpr { + optional, mut base, .. + } = current; + + if optional { + count += 1; + } + + let next; + match &mut *base { + OptChainBase::Member(m) => { + next = m.obj.take(); + m.prop.visit_mut_with(self); + chain.push(if optional { + Gathering::OptMember(m.take(), self.memoize(&next, false)) + } else { + Gathering::Member(m.take()) + }); + } + + OptChainBase::Call(c) => { + next = c.callee.take(); + c.args.visit_mut_with(self); + // I don't know why c is an OptCall instead of a CallExpr. + chain.push(if optional { + Gathering::OptCall(c.take().into(), self.memoize(&next, true)) + } else { + Gathering::Call(c.take().into()) + }); + } + } + + match *next { + Expr::OptChain(next) => { + current = next; + } + mut base => { + base.visit_mut_children_with(self); + return (base, count, chain); + } + } + } + } + + /// Constructs a rightward nested conditional expression out of our + /// flattened chain. + fn construct(&mut self, data: (Expr, usize, Vec), is_delete: bool) -> Expr { + let (mut current, count, chain) = data; + + // Stores partially constructed CondExprs for us to assemble later on. + let mut committed_cond = Vec::with_capacity(count); + + // Stores the memo used to construct an optional chain, so that it can be used + // as the this context of an optional call: + // foo?.bar?.() -> + // (_foo = foo) == null + // ? void 0 + // : (_foo_bar = _foo.bar) == null + // ? void 0 : _foo_bar.call(_foo) + let mut ctx = None; + + // In the first pass, we construct a "current" node and several committed + // CondExprs. The conditionals will have an invalid alt, waiting for the + // second pass to properly construct them. + // We reverse iterate so that we can construct a rightward conditional + // `(_a = a) == null ? void 0 : (_a_b = _a.b) == null ? void 0 : _a_b.c` + // instead of a leftward one + // `(_a_b = (_a = a) == null ? void 0 : _a.b) == null ? void 0 : _a_b.c` + for v in chain.into_iter().rev() { + current = match v { + Gathering::Call(mut c) => { + c.callee = current.as_callee(); + ctx = None; + Expr::Call(c) + } + Gathering::Member(mut m) => { + m.obj = Box::new(current); + ctx = None; + Expr::Member(m) + } + Gathering::OptCall(mut c, memo) => { + let mut call = false; + + // foo.bar?.() -> (_foo_bar == null) ? void 0 : _foo_bar.call(foo) + match &mut current { + Expr::Member(m) => { + call = true; + let this = ctx.unwrap_or_else(|| { + let this = self.memoize(&m.obj, true); + + match &this { + Memo::Cache(i) => { + m.obj = Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: op!("="), + left: i.clone().into(), + right: m.obj.take(), + })); + this + } + Memo::Raw(_) => this, + } + }); + c.args.insert(0, this.into_expr().as_arg()); + } + Expr::SuperProp(s) => { + call = true; + c.args.insert(0, ThisExpr { span: s.obj.span }.as_arg()); + } + _ => {} + } + + committed_cond.push(CondExpr { + span: DUMMY_SP, + test: init_and_eq_null_or_undefined(&memo, current, self.c.no_document_all), + cons: if is_delete { + true.into() + } else { + undefined(DUMMY_SP) + }, + alt: Take::dummy(), + }); + c.callee = if call { + memo.into_expr() + .make_member(quote_ident!("call")) + .as_callee() + } else { + memo.into_expr().as_callee() + }; + ctx = None; + Expr::Call(c) + } + Gathering::OptMember(mut m, memo) => { + committed_cond.push(CondExpr { + span: DUMMY_SP, + test: init_and_eq_null_or_undefined(&memo, current, self.c.no_document_all), + cons: if is_delete { + true.into() + } else { + undefined(DUMMY_SP) + }, + alt: Take::dummy(), + }); + ctx = Some(memo.clone()); + m.obj = memo.into_expr().into(); + Expr::Member(m) + } + }; + } + + // At this point, `current` is the right-most expression `_a_b.c` in `a?.b?.c` + if is_delete { + current = Expr::Unary(UnaryExpr { + span: DUMMY_SP, + op: op!("delete"), + arg: Box::new(current), + }); + } + + // We now need to reverse iterate the conditionals to construct out tree. + for mut cond in committed_cond.into_iter().rev() { + cond.alt = Box::new(current); + current = Expr::Cond(cond) + } + current + } + + fn should_memo(&self, expr: &Expr, is_call: bool) -> bool { + fn is_simple_member(e: &Expr) -> bool { + match e { + Expr::This(..) => true, + Expr::Ident(_) => true, + Expr::SuperProp(s) if !s.prop.is_computed() => true, + Expr::Member(m) if !m.prop.is_computed() => is_simple_member(&m.obj), + _ => false, + } + } + + match expr { + Expr::Ident(i) if i.span.ctxt != self.unresolved_ctxt => false, + _ => { + if is_call && self.c.pure_getter { + !is_simple_member(expr) + } else { + true + } + } + } + } + + fn memoize(&mut self, expr: &Expr, is_call: bool) -> Memo { + if self.should_memo(expr, is_call) { + let memo = alias_ident_for(expr, "_this"); + self.vars.push(VarDeclarator { + span: DUMMY_SP, + name: memo.clone().into(), + init: None, + definite: false, + }); + Memo::Cache(memo) + } else { + Memo::Raw(Box::new(expr.to_owned())) + } + } + + fn visit_mut_stmt_like(&mut self, stmts: &mut Vec) + where + T: Send + Sync + StmtLike + VisitMutWith, + Vec: VisitMutWith, + { + let uninit = self.vars.take(); + for stmt in stmts.iter_mut() { + stmt.visit_mut_with(self); + } + + if !self.vars.is_empty() { + prepend_stmt( + stmts, + T::from_stmt( + VarDecl { + span: DUMMY_SP, + declare: false, + kind: VarDeclKind::Var, + decls: mem::take(&mut self.vars), + } + .into(), + ), + ); + } + + self.vars = uninit; + } +} + +fn init_and_eq_null_or_undefined(i: &Memo, init: Expr, no_document_all: bool) -> Box { + let lhs = match i { + Memo::Cache(i) => Box::new(Expr::Assign(AssignExpr { + span: DUMMY_SP, + op: op!("="), + left: PatOrExpr::Pat(i.clone().into()), + right: Box::new(init), + })), + Memo::Raw(e) => e.to_owned(), + }; + + if no_document_all { + return Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: lhs, + op: op!("=="), + right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), + })); + } + + let null_cmp = Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: lhs, + op: op!("==="), + right: Box::new(Expr::Lit(Lit::Null(Null { span: DUMMY_SP }))), + })); + + let left_expr = match i { + Memo::Cache(i) => Box::new(i.clone().into()), + Memo::Raw(e) => e.to_owned(), + }; + + let void_cmp = Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: left_expr, + op: op!("==="), + right: undefined(DUMMY_SP), + })); + + Box::new(Expr::Bin(BinExpr { + span: DUMMY_SP, + left: null_cmp, + op: op!("||"), + right: void_cmp, + })) +} diff --git a/crates/swc_ecma_compat_es2022/src/static_blocks.rs b/crates/swc_ecma_compat_es2022/src/static_blocks.rs index 9bc46f5ab33a..291083caa379 100644 --- a/crates/swc_ecma_compat_es2022/src/static_blocks.rs +++ b/crates/swc_ecma_compat_es2022/src/static_blocks.rs @@ -9,8 +9,10 @@ struct ClassStaticBlock { mark: Mark, } -pub fn static_blocks(mark: Mark) -> impl Fold + VisitMut { - as_folder(ClassStaticBlock { mark }) +pub fn static_blocks(static_block_mark: Mark) -> impl Fold + VisitMut { + as_folder(ClassStaticBlock { + mark: static_block_mark, + }) } #[swc_trace] diff --git a/crates/swc_ecma_preset_env/src/lib.rs b/crates/swc_ecma_preset_env/src/lib.rs index b715b4f231a9..c43c8ca90ab5 100644 --- a/crates/swc_ecma_preset_env/src/lib.rs +++ b/crates/swc_ecma_preset_env/src/lib.rs @@ -147,7 +147,9 @@ where constant_super: loose || assumptions.constant_super, no_document_all: loose || assumptions.no_document_all, static_blocks_mark, - } + pure_getter: loose || assumptions.pure_getters, + }, + unresolved_mark ) ); let pass = add!(pass, PrivatePropertyInObject, es2022::private_in_object()); diff --git a/crates/swc_ecma_transforms/tests/decorators.rs b/crates/swc_ecma_transforms/tests/decorators.rs index 0e205424319e..7c874bc0120e 100644 --- a/crates/swc_ecma_transforms/tests/decorators.rs +++ b/crates/swc_ecma_transforms/tests/decorators.rs @@ -37,10 +37,18 @@ fn syntax(decorators_before_export: bool) -> Syntax { } fn tr(t: &Tester) -> impl Fold { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( + resolver(unresolved_mark, top_level_mark, true), decorators(Default::default()), class_fields_use_set(true), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), ) } @@ -74,7 +82,8 @@ fn simple_strip(t: &Tester, config: Config) -> impl Fold { class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ) ) } @@ -1612,13 +1621,23 @@ expect(el).toEqual(Object.defineProperty({ // legacy_class_constructors_return_new_constructor test_exec!( syntax(true), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_constructors_return_new_constructor_exec, r#" function dec(cls){ @@ -1641,13 +1660,23 @@ expect(typeof Parent.prototype.child).toBe("function"); // legacy_class_prototype_methods_numeric_props test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_methods_numeric_props_exec, r#" function dec(target, name, descriptor) { @@ -1669,13 +1698,23 @@ test_exec!( // I tested using typescript playground and node js ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_static_properties_mutate_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -1784,13 +1823,23 @@ expect(Example._).toBe("__8__"); // legacy_class_static_methods_string_props test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_static_methods_string_props_exec, r#" function dec(target, name, descriptor) { @@ -1811,13 +1860,23 @@ class Example { test_exec!( ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_properties_string_literal_properties_exec, r#" function dec(target, name, descriptor) { @@ -1858,13 +1917,23 @@ test_exec!( // I tested on typescript playground ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_methods_mutate_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -1991,13 +2060,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_properties_numeric_props_exec, r#" function dec(target, name, descriptor){ @@ -2018,13 +2097,23 @@ const inst = { test_exec!( ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_properties_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2135,13 +2224,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_properties_string_props_exec, r#" function dec(target, name, descriptor){ @@ -2163,13 +2262,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_properties_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2276,13 +2385,23 @@ expect(inst._).toBe("__8__"); // legacy_class_prototype_methods_string_props test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_methods_string_props_exec, r#" function dec(target, name, descriptor) { @@ -2302,13 +2421,23 @@ class Example { // legacy_class_prototype_methods_return_descriptor test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_methods_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2437,13 +2566,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_ordering_reverse_order_exec, r#" const calls = []; @@ -2481,13 +2620,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_methods_numeric_props_exec, r#" function dec(target, name, descriptor){ @@ -2510,13 +2659,23 @@ test_exec!( // I tested using typescript playground and node js ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_static_properties_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2630,13 +2789,23 @@ test_exec!( // below correctly. ignore, syntax(true), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_export_default_exec, r#" const calls = []; @@ -2660,13 +2829,23 @@ expect(calls).toEqual(["Foo"]); // legacy_class_ordering_reverse_order test_exec!( syntax(true), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_ordering_reverse_order_exec, r#" const calls = []; @@ -2707,13 +2886,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(true), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_methods_mutate_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2836,13 +3025,23 @@ expect(inst._()).toBe("__8__"); // legacy_class_static_methods_return_descriptor test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_static_methods_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -2968,13 +3167,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_methods_return_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -3099,13 +3308,23 @@ test_exec!( // Legacy decorator for object literals ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_object_methods_string_props_exec, r#" function dec(target, name, descriptor){ @@ -3128,13 +3347,23 @@ const inst = { test_exec!( ignore, syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_prototype_properties_child_classes_properties_exec, r#" function dec(target, name, descriptor){ @@ -3171,13 +3400,23 @@ expect(inst.prop2).toBe("__4__"); // legacy_class_static_methods_mutate_descriptor test_exec!( syntax(false), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + ) + }, legacy_class_static_methods_mutate_descriptor_exec, r#" function dec(target, name, descriptor) { @@ -3381,14 +3620,24 @@ test!( // See: https://github.com/swc-project/swc/issues/421 ignore, Default::default(), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()) + ) + }, decorators_legacy_interop_local_define_property, r#" function dec() {} diff --git a/crates/swc_ecma_transforms/tests/es2015_function_name.rs b/crates/swc_ecma_transforms/tests/es2015_function_name.rs index bfb259acd1f3..619219de2c39 100644 --- a/crates/swc_ecma_transforms/tests/es2015_function_name.rs +++ b/crates/swc_ecma_transforms/tests/es2015_function_name.rs @@ -528,14 +528,24 @@ test!( // See: https://github.com/swc-project/swc/issues/421 ignore, syntax(), - |t| chain!( - decorators(decorators::Config { - legacy: true, - ..Default::default() - }), - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + decorators(decorators::Config { + legacy: true, + ..Default::default() + }), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + ) + }, decorators_legacy_interop_strict, r#" function dec() {} diff --git a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_1.js b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_1.js index 88c5e1107aaa..8171525c4845 100644 --- a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_1.js +++ b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_1.js @@ -1,6 +1,6 @@ -var Extended = /*#__PURE__*/ function(Base) { +var Extended = /*#__PURE__*/ function(Base1) { "use strict"; - _inherits(Extended, Base); + _inherits(Extended, Base1); var _super = _create_super(Extended); function Extended() { _class_call_check(this, Extended); diff --git a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_2.js b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_2.js index 6689c6ed55a0..0f2025bba1ef 100644 --- a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_2.js +++ b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2015_classes.rs/issue_1959_2.js @@ -1,6 +1,6 @@ -var Extended = /*#__PURE__*/ function(Base) { +var Extended = /*#__PURE__*/ function(Base1) { "use strict"; - _inherits(Extended, Base); + _inherits(Extended, Base1); var _super = _create_super(Extended); function Extended() { _class_call_check(this, Extended); diff --git a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/issue_8003.js b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/issue_8003.js index 92b0f095b3ad..a5788dc3acaf 100644 --- a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/issue_8003.js +++ b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/issue_8003.js @@ -1,8 +1,8 @@ var _priv = /*#__PURE__*/ 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); + var _this, _this1, _ref; + (_this = _class_private_field_get(_ref = _this1 = this, _priv)) === null || _this === void 0 ? void 0 : _this.call(_this1); } constructor(){ _class_private_field_init(this, _priv, { diff --git a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/private_optional_chain_call.js b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/private_optional_chain_call.js index 46d4dabd3a9e..76226fc4e535 100644 --- a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/private_optional_chain_call.js +++ b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/private_optional_chain_call.js @@ -1,7 +1,8 @@ var _fieldFunc = /*#__PURE__*/ new WeakMap(); class A { test() { - _class_private_field_get(this, _fieldFunc)?.call(this); + var _this, _this1, _ref; + (_this = _class_private_field_get(_ref = _this1 = this, _fieldFunc)) === null || _this === void 0 ? void 0 : _this.call(_this1); } constructor(){ _class_private_field_init(this, _fieldFunc, { diff --git a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/regression_6153.js b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/regression_6153.js index 016c6616c53b..94c3519b0d9a 100644 --- a/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/regression_6153.js +++ b/crates/swc_ecma_transforms_compat/tests/__swc_snapshots__/tests/es2022_class_properties.rs/regression_6153.js @@ -27,7 +27,7 @@ }); (function() { class Baz { - constructor(force){ + constructor(force1){ var _this = this; _define_property(this, "fn", function() { return console.log(_this); diff --git a/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/input.js b/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/input.js new file mode 100644 index 000000000000..1bedd2a42410 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/input.js @@ -0,0 +1,7 @@ +class Foo { + #x; + + test() { + this?.y.#x; + } +} diff --git a/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/output.js b/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/output.js new file mode 100644 index 000000000000..50460f0adc17 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/class-properties/issue-7561/output.js @@ -0,0 +1,13 @@ +var _x = /*#__PURE__*/ new WeakMap(); +class Foo { + test() { + var _this, _this_y; + (_this = this) === null || _this === void 0 ? void 0 : _class_private_field_get(_this_y = _this.y, _x); + } + constructor(){ + _class_private_field_init(this, _x, { + writable: true, + value: void 0 + }); + } +} diff --git a/crates/swc_ecma_transforms_compat/tests/classes/create-super-1/output.js b/crates/swc_ecma_transforms_compat/tests/classes/create-super-1/output.js index ccc0f8fd604e..71e043656a71 100644 --- a/crates/swc_ecma_transforms_compat/tests/classes/create-super-1/output.js +++ b/crates/swc_ecma_transforms_compat/tests/classes/create-super-1/output.js @@ -1,6 +1,6 @@ -let Foo = /*#__PURE__*/ function(UnknownNativeClass) { +let Foo = /*#__PURE__*/ function(UnknownNativeClass1) { "use strict"; - _inherits(Foo, UnknownNativeClass); + _inherits(Foo, UnknownNativeClass1); var _super = _create_super(Foo); function Foo() { _class_call_check(this, Foo); diff --git a/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/1/output.js b/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/1/output.js new file mode 100644 index 000000000000..7860d8bb9fee --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/1/output.js @@ -0,0 +1,18 @@ +let Extended = /*#__PURE__*/ function(Base1) { + "use strict"; + _inherits(Extended, Base1); + var _super = _create_super(Extended); + function Extended() { + _class_call_check(this, Extended); + return _super.apply(this, arguments); + } + _create_class(Extended, [ + { + key: "getNext", + value: function getNext() { + return _get(_get_prototype_of(Extended.prototype), "getNext", this).call(this, 114514) + 114514; + } + } + ]); + return Extended; +}(Base); diff --git a/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/2/output.js b/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/2/output.js new file mode 100644 index 000000000000..b8bbc10e7f2e --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/classes/issue-1959/2/output.js @@ -0,0 +1,18 @@ +let Extended = /*#__PURE__*/ function(Base1) { + "use strict"; + _inherits(Extended, Base1); + var _super = _create_super(Extended); + function Extended() { + _class_call_check(this, Extended); + return _super.apply(this, arguments); + } + _create_class(Extended, [ + { + key: "getNext", + value: function getNext() { + return _get(_get_prototype_of(Extended.prototype), "getNext", this).call(this, 114514); + } + } + ]); + return Extended; +}(Base); diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_classes.rs b/crates/swc_ecma_transforms_compat/tests/es2015_classes.rs index bdbe92fc9493..ff739a0ab6a6 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2015_classes.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2015_classes.rs @@ -3940,10 +3940,16 @@ test!( test!( syntax(), |t| { - let unresolved_mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); chain!( - es2022::es2022(Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + es2022::es2022( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), es2018::es2018(Default::default()), es2017::es2017( Default::default(), @@ -3967,11 +3973,21 @@ test!( test!( syntax(), |t| { - let global_mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); chain!( - class_properties(Some(t.comments.clone()), Default::default()), - es2015::es2015(global_mark, Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + es2015::es2015( + unresolved_mark, + Some(t.comments.clone()), + Default::default() + ), ) }, issue_1660_5, @@ -4005,11 +4021,21 @@ test!( test!( syntax(), |t| { - let global_mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); chain!( - class_properties(Some(t.comments.clone()), Default::default()), - es2015::es2015(global_mark, Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + es2015::es2015( + unresolved_mark, + Some(t.comments.clone()), + Default::default() + ), ) }, issue_1959_1, @@ -4025,11 +4051,21 @@ test!( test!( syntax(), |t| { - let global_mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); chain!( - class_properties(Some(t.comments.clone()), Default::default()), - es2015::es2015(global_mark, Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + es2015::es2015( + unresolved_mark, + Some(t.comments.clone()), + Default::default() + ), ) }, issue_1959_2, @@ -4048,8 +4084,16 @@ fn exec(input: PathBuf) { compare_stdout( Default::default(), |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - class_properties(Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), classes(Some(t.comments.clone()), Default::default()) ) }, @@ -4064,8 +4108,16 @@ fn fixture(input: PathBuf) { test_fixture( Default::default(), &|t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - class_properties(Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), classes(Some(t.comments.clone()), Default::default()) ) }, diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs b/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs index 0329194458b2..9ff3c3ecf1d7 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2015_generator.rs @@ -1406,14 +1406,25 @@ test!( test!( Syntax::default(), |t| { - let mark = Mark::fresh(Mark::root()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - es2022(Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + es2022( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), es2021(), es2018(Default::default()), - es2017(Default::default(), Some(t.comments.clone()), mark), + es2017( + Default::default(), + Some(t.comments.clone()), + unresolved_mark + ), es2016(), - es2015::(mark, None, Default::default()), + es2015::(unresolved_mark, None, Default::default()), ) }, issue_1799_5, diff --git a/crates/swc_ecma_transforms_compat/tests/es2015_new_target.rs b/crates/swc_ecma_transforms_compat/tests/es2015_new_target.rs index 9aa4952357ed..544687340258 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2015_new_target.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2015_new_target.rs @@ -2,7 +2,7 @@ use std::{fs::read_to_string, path::PathBuf}; use serde::Deserialize; use swc_common::{chain, Mark}; -use swc_ecma_transforms_base::pass::noop; +use swc_ecma_transforms_base::resolver; use swc_ecma_transforms_compat::{ es2015::{arrow, classes, new_target::new_target}, es2022::class_properties, @@ -11,7 +11,10 @@ use swc_ecma_transforms_testing::{exec_tr, parse_options, test, test_fixture, Te use swc_ecma_visit::Fold; fn get_passes(t: &Tester, plugins: &[PluginConfig]) -> Box { - let mut pass: Box = Box::new(noop()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + let mut pass: Box = Box::new(resolver(unresolved_mark, top_level_mark, true)); for plugin in plugins { let (name, option) = match plugin { @@ -45,7 +48,9 @@ fn get_passes(t: &Tester, plugins: &[PluginConfig]) -> Box { private_as_properties: loose, no_document_all: loose, static_blocks_mark: Mark::new(), - } + pure_getter: loose, + }, + unresolved_mark, ) )); } diff --git a/crates/swc_ecma_transforms_compat/tests/es2017_async_to_generator.rs b/crates/swc_ecma_transforms_compat/tests/es2017_async_to_generator.rs index a9dcdf821cd8..070cf6fe8063 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2017_async_to_generator.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2017_async_to_generator.rs @@ -1362,10 +1362,20 @@ test!( test_exec!( Syntax::default(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, issue_1341_1_exec, " class A { @@ -1400,10 +1410,20 @@ test!( test_exec!( Syntax::default(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, issue_1341_2_exec, " class A { @@ -2068,7 +2088,11 @@ fn exec(input: PathBuf) { chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), async_to_generator( Default::default(), Some(t.comments.clone()), @@ -2091,7 +2115,11 @@ fn exec_regenerator(input: PathBuf) { chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), async_to_generator( Default::default(), Some(t.comments.clone()), diff --git a/crates/swc_ecma_transforms_compat/tests/es2020_optional_chaining.rs b/crates/swc_ecma_transforms_compat/tests/es2020_optional_chaining.rs index 9ea91d1f27af..3485ff5826f7 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2020_optional_chaining.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2020_optional_chaining.rs @@ -3,7 +3,10 @@ use std::{fs::read_to_string, path::PathBuf}; use swc_common::{chain, Mark}; use swc_ecma_parser::Syntax; use swc_ecma_transforms_base::resolver; -use swc_ecma_transforms_compat::es2020::{optional_chaining, optional_chaining::Config}; +use swc_ecma_transforms_compat::{ + es2020::{optional_chaining, optional_chaining::Config}, + es2022::class_properties, +}; use swc_ecma_transforms_testing::{compare_stdout, test, test_exec, test_fixture}; use swc_ecma_visit::Fold; @@ -275,11 +278,19 @@ fn fixture(input: PathBuf) { test_fixture( Default::default(), - &|_| { + &|t| { let unresolved_mark = Mark::new(); let top_level_mark = Mark::new(); chain!( resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + swc_ecma_transforms_compat::es2022::class_properties::Config { + private_as_properties: false, + ..Default::default() + }, + unresolved_mark + ), optional_chaining(Default::default(), unresolved_mark) ) }, @@ -295,11 +306,22 @@ fn fixture_loose(input: PathBuf) { test_fixture( Default::default(), - &|_| { + &|t| { let unresolved_mark = Mark::new(); let top_level_mark = Mark::new(); chain!( resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + swc_ecma_transforms_compat::es2022::class_properties::Config { + private_as_properties: false, + pure_getter: true, + no_document_all: true, + + ..Default::default() + }, + unresolved_mark + ), optional_chaining( Config { no_document_all: true, 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 93be1bb4bcd2..e4f90f0a3b81 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs @@ -13,7 +13,7 @@ use swc_ecma_transforms_compat::{ es2022::class_properties, es3::reserved_words, }; -use swc_ecma_transforms_testing::{compare_stdout, test, test_exec, Tester}; +use swc_ecma_transforms_testing::{compare_stdout, test, test_exec, test_fixture, Tester}; use swc_ecma_visit::Fold; fn syntax() -> Syntax { @@ -27,7 +27,11 @@ fn tr(t: &Tester) -> impl Fold { chain!( resolver(unresolved_mark, top_level_mark, false), function_name(), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), classes(Some(t.comments.clone()), Default::default()), block_scoping(unresolved_mark), reserved_words(false), @@ -117,7 +121,11 @@ test!( chain!( resolver(unresolved_mark, top_level_mark, false), function_name(), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), ) }, private_class_method, @@ -1758,7 +1766,11 @@ test!( chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()) + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ) ) }, issue_308, @@ -1782,7 +1794,11 @@ test!( chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), classes(Some(t.comments.clone()), Default::default()) ) }, @@ -1806,7 +1822,11 @@ test!( chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), block_scoping(unresolved_mark) ) }, @@ -1827,10 +1847,20 @@ class foo { // public_regression_t7364 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, public_regression_t7364, r#" class MyClass { @@ -1857,10 +1887,20 @@ export default class MyClass3 { // private_regression_t6719 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_regression_t6719, r#" function withContext(ComposedComponent) { @@ -1925,10 +1965,20 @@ function withContext(ComposedComponent) { // private_reevaluated test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_reevaluated, r#" function classFactory() { @@ -1960,10 +2010,20 @@ function classFactory() { // private_static test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_static, r#" class Foo { @@ -1988,11 +2048,21 @@ expect(Foo.test()).toBe("foo") // private_destructuring_object_pattern_1 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_destructuring_object_pattern_1, r#" class Foo { @@ -2009,10 +2079,20 @@ class Foo { // private_static_inherited test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_static_inherited, r#" class Base { @@ -2051,7 +2131,19 @@ class Sub2 extends Base {} // private_destructuring_object_pattern_1_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_destructuring_object_pattern_1_exec, r#" class Foo { @@ -2078,10 +2170,20 @@ expect(foo.z).toBe('bar'); // private_static_undefined test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_static_undefined, r#" class Foo { @@ -2102,11 +2204,21 @@ class Foo { // private_destructuring_array_pattern test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_destructuring_array_pattern, r#" class Foo { @@ -2123,10 +2235,20 @@ class Foo { // private_regression_t2983 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_regression_t2983, r#" call(class { @@ -2145,8 +2267,15 @@ test!( syntax(), |t| { let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - class_properties(Some(t.comments.clone()), Default::default()), + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), async_to_generator( Default::default(), Some(t.comments.clone()), @@ -2181,11 +2310,21 @@ export default class MyClass3 { // private_destructuring_array_pattern_1 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_destructuring_array_pattern_1, r#" class Foo { @@ -2202,7 +2341,19 @@ class Foo { // regression_8882_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, regression_8882_exec, r#" const classes = []; @@ -2233,7 +2384,19 @@ for(let i=0; i<= 10; ++i) { test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ), + ) + }, regression_8882_exec_2, r#" const classes = []; @@ -2264,7 +2427,19 @@ for(let i=0; i<= 10; ++i) { test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_field_reinitialized, r#" class Base { @@ -2393,10 +2568,20 @@ expect(() => new Derived(foo)).toThrow() // private_static_export test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_static_export, r#" export class MyClass { @@ -2413,10 +2598,20 @@ export default class MyClass2 { // static_property_tdz_edgest_case test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()) + ) + }, static_property_tdz_edgest_case, r#" class A { @@ -2428,10 +2623,20 @@ class A { test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()) + ) + }, static_property_tdz_false_alarm, r#" class A { @@ -2443,10 +2648,20 @@ static A = 123; // regression_6153 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - arrow(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + arrow(Mark::new()) + ) + }, regression_6153, r#" () => { @@ -2484,10 +2699,20 @@ var qux = function() { // regression_7371 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - arrow(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + arrow(unresolved_mark), + ) + }, regression_7371, r#" "use strict"; @@ -2595,7 +2820,19 @@ new ComputedField(); test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_optional_chain_call, r#" class A { @@ -2610,7 +2847,19 @@ class A { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_optional_chain_member, r#" class MyClass { @@ -2625,11 +2874,21 @@ class MyClass { // private_canonical test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_canonical, r#" class Point { @@ -2659,7 +2918,19 @@ class Point { // regression_8882 test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, regression_8882, r#" const classes = []; @@ -2689,11 +2960,21 @@ for(let i = 0; i <= 10; ++i){ // private_destructuring_array_pattern_3 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_destructuring_array_pattern_3, r#" class Foo { @@ -2708,7 +2989,19 @@ class Foo { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, staic_private_destructuring_array_pattern, r#" class A { @@ -2723,7 +3016,19 @@ class A { // public_static_super_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, public_static_super_exec, r#" class A { @@ -2748,11 +3053,21 @@ expect(getPropA()).toBe(1); // private_destructuring_array_pattern_2 test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, private_destructuring_array_pattern_2, r#" class Foo { @@ -2768,10 +3083,20 @@ class Foo { // private_non_block_arrow_func test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_non_block_arrow_func, r#" export default param => @@ -2792,7 +3117,19 @@ export default param => // regression_8110 test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, regression_8110, r#" const field = Symbol('field'); @@ -2807,7 +3144,19 @@ class A { // public_computed_without_block_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, public_computed_without_block_exec, r#" const createClass = (k) => class { [k()] = 2 }; @@ -2821,12 +3170,22 @@ expect(instance.foo).toBe(2); // private_instance test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - exponentiation(), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()), - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + exponentiation(), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()), + ) + }, private_instance, r#" class Foo { @@ -2839,10 +3198,20 @@ class Foo { // static_property_tdz_general test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()) + ) + }, static_property_tdz_general, r#" class C { @@ -2855,10 +3224,20 @@ class C { // public_native_classes test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, public_native_classes, r#" class Foo { @@ -2888,10 +3267,20 @@ test!( // Seems useless, while being hard to implement. ignore, syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_static_infer_name, r#" var Foo = class { @@ -2910,7 +3299,11 @@ test!( chain!( resolver(unresolved_mark, top_level_mark, false), - class_properties(Some(t.comments.clone()), Default::default()) + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ) ) }, regression_7951, @@ -2927,10 +3320,20 @@ export class Foo extends Bar { // private_native_classes test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + block_scoping(Mark::new()) + ) + }, private_native_classes, r#" class Foo { @@ -2952,11 +3355,21 @@ class Foo { // public_computed_without_block test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, public_computed_without_block, r#" const createClass = (k) => class { [k()] = 2 }; @@ -2967,7 +3380,19 @@ const createClass = (k) => class { [k()] = 2 }; // private_destructuring_array_pattern_2_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_destructuring_array_pattern_2_exec, r#" class Foo { @@ -2992,11 +3417,21 @@ expect(foo.getClient()).toEqual(['bar', 'baz', 'quu']); // public_static_super test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - classes(Some(t.comments.clone()), Default::default()), - block_scoping(Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + classes(Some(t.comments.clone()), Default::default()), + block_scoping(Mark::new()) + ) + }, public_static_super, r#" class A { @@ -3015,7 +3450,19 @@ class B extends A { // private_destructuring_array_pattern_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_destructuring_array_pattern_exec, r#" class Foo { @@ -3039,7 +3486,19 @@ expect(foo.getClient()).toBe('bar'); // private_destructuring_array_pattern_1_exec test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, private_destructuring_array_pattern_1_exec, r#" class Foo { @@ -3065,7 +3524,19 @@ expect(foo.y).toBe('bar'); test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1306_1, r#" class Animal { @@ -3084,7 +3555,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1306_2, r#" class Animal { @@ -3103,7 +3586,19 @@ class Animal { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_1, " class Foo { @@ -3118,7 +3613,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_2, " class Test { @@ -3213,7 +3720,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_3, " class Test { @@ -3242,7 +3761,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_4, " class Test { @@ -3264,7 +3795,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_5, " class Test { @@ -3278,7 +3821,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1333_6, " class Test { @@ -3292,7 +3847,19 @@ test!( test!( syntax(), - |t| { class_properties(Some(t.comments.clone()), Default::default()) }, + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1660_1, " console.log(class { run() { } }); @@ -3301,7 +3868,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_3055_1, " export class Node { @@ -3321,7 +3900,19 @@ export class Node { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_3618, " class MyClass { @@ -3335,10 +3926,20 @@ class MyClass { test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, issue_1694_1, " class MyClass { @@ -3354,10 +3955,20 @@ test!( test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, issue_1694_2, " class MyClass { @@ -3373,10 +3984,20 @@ class MyClass { test!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + async_to_generator(Default::default(), Some(t.comments.clone()), Mark::new()) + ) + }, issue_1702_1, " class Foo { @@ -3400,7 +4021,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1711_1, " class Foo { @@ -3418,7 +4051,19 @@ test!( test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1742_1, " class Foo { @@ -3442,10 +4087,20 @@ test_exec!( test_exec!( syntax(), - |t| chain!( - class_properties(Some(t.comments.clone()), Default::default()), - template_literal(Default::default()) - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + template_literal(Default::default()) + ) + }, issue_1742_2, " class Foo { @@ -3469,7 +4124,19 @@ test_exec!( test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, new_target_in_class_prop, " class Foo { @@ -3486,7 +4153,19 @@ expect(foo.baz).toBe(undefined); test_exec!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, class_field_evalutaion_order, " class Foo { @@ -3503,7 +4182,19 @@ expect(() => new Foo()).not.toThrow(); test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1742_3, " class Foo { @@ -3527,7 +4218,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1869_1, " class TestClass { @@ -3546,7 +4249,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_1869_2, " var _class; @@ -3564,7 +4279,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_2021_1, " class Item extends Component { @@ -3579,7 +4306,19 @@ test!( test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_3229_1, " class A { @@ -3595,7 +4334,19 @@ class A { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_3229_2, " class A { @@ -3612,7 +4363,19 @@ class A { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_3368, " class A { @@ -3632,7 +4395,19 @@ class A { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, nested_class_in_arrow, " const a = () => class { @@ -3648,7 +4423,19 @@ const a = () => class { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_2481, " class Foo { @@ -3662,7 +4449,19 @@ class Foo { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_4473, " var test1 = class X { @@ -3680,13 +4479,22 @@ function a() { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - constant_super: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + constant_super: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, constant_super_complex_super, " class A extends class B {} { @@ -3697,13 +4505,22 @@ class A extends class B {} { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - constant_super: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + constant_super: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, constant_super_field, " class A extends B { @@ -3715,13 +4532,22 @@ class A extends B { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - no_document_all: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + no_document_all: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, private_optional_chain_member_loose, r#" class MyClass { @@ -3735,13 +4561,22 @@ class MyClass { test_exec!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - set_public_fields: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + set_public_fields: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, set_public_fields_initialization_order, r#" const actualOrder = []; @@ -3787,13 +4622,22 @@ expect(inst[9]).toBe(15); test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - set_public_fields: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + set_public_fields: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, set_public_fields_computed, r#" const foo = "foo"; @@ -3837,7 +4681,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ) ) }, @@ -3859,13 +4704,22 @@ class Foo { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - set_public_fields: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + set_public_fields: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, set_public_static_undefined, r#" class Foo { @@ -3876,13 +4730,22 @@ class Foo { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - private_as_properties: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + private_as_properties: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, private_as_properties_basic, r#" class Cl { @@ -3913,13 +4776,22 @@ class Cl { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - private_as_properties: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + private_as_properties: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, private_as_properties_static, r#" class Cl { @@ -3932,13 +4804,22 @@ class Cl { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - private_as_properties: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + private_as_properties: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, private_as_properties_getter_only, r#" class Cl { @@ -3958,14 +4839,23 @@ class Cl { test!( syntax(), - |t| class_properties( - Some(t.comments.clone()), - class_properties::Config { - private_as_properties: true, - set_public_fields: true, - ..Default::default() - } - ), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + class_properties::Config { + private_as_properties: true, + set_public_fields: true, + ..Default::default() + }, + unresolved_mark, + ) + ) + }, loose_update, r#" class Cl { @@ -4020,7 +4910,19 @@ class Cl { test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, set_only_getter, r#" class Cl { @@ -4048,7 +4950,19 @@ const cl = new Cl(); test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, get_only_setter, r#" class Cl { @@ -4070,14 +4984,61 @@ fn exec(input: PathBuf) { let src = read_to_string(input).unwrap(); compare_stdout( Default::default(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, &src, ); } +#[testing::fixture("tests/class-properties/**/input.js")] +fn fixture(input: PathBuf) { + test_fixture( + Default::default(), + &|t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ) + ) + }, + &input, + &input.with_file_name("output.js"), + Default::default(), + ); +} + test!( syntax(), - |t| class_properties(Some(t.comments.clone()), Default::default()), + |t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + chain!( + resolver(unresolved_mark, top_level_mark, true), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark, + ) + ) + }, issue_6305, "class x { static #x = super.x = 0 }" ); @@ -4085,10 +5046,17 @@ test!( test!( syntax(), |t| { - let unresolved = Mark::new(); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - class_properties(Some(t.comments.clone()), Default::default()), - optional_chaining(Default::default(), unresolved) + resolver(unresolved_mark, top_level_mark, false), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), + optional_chaining(Default::default(), unresolved_mark) ) }, issue_8003, diff --git a/crates/swc_ecma_transforms_compat/tests/es2022_private_in_object.rs b/crates/swc_ecma_transforms_compat/tests/es2022_private_in_object.rs index 5374e5f04580..3d3c6ecf2eda 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2022_private_in_object.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2022_private_in_object.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use serde::Deserialize; use swc_common::{chain, Mark}; -use swc_ecma_transforms_base::pass::noop; +use swc_ecma_transforms_base::resolver; use swc_ecma_transforms_compat::{ es2015::classes, es2022::{class_properties, private_in_object}, @@ -33,7 +33,11 @@ fn fixture(input: PathBuf) { test_fixture( Default::default(), &|t| { - let mut pass: Box = Box::new(noop()); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + + let mut pass: Box = + Box::new(resolver(unresolved_mark, top_level_mark, false)); let mut class_props = false; @@ -60,9 +64,11 @@ fn fixture(input: PathBuf) { constant_super: loose, no_document_all: loose, private_as_properties: loose, + pure_getter: loose, static_blocks_mark: Mark::new(), - } - ) + }, + unresolved_mark + ), )); } } @@ -79,8 +85,10 @@ fn fixture(input: PathBuf) { constant_super: loose, no_document_all: loose, private_as_properties: loose, + pure_getter: loose, static_blocks_mark: Mark::new(), - } + }, + unresolved_mark, ) )); } diff --git a/crates/swc_ecma_transforms_compat/tests/es2022_static_blocks.rs b/crates/swc_ecma_transforms_compat/tests/es2022_static_blocks.rs index a0bde2dd3563..470db89d1fb3 100644 --- a/crates/swc_ecma_transforms_compat/tests/es2022_static_blocks.rs +++ b/crates/swc_ecma_transforms_compat/tests/es2022_static_blocks.rs @@ -1,7 +1,8 @@ use std::path::PathBuf; -use swc_common::chain; +use swc_common::{chain, Mark}; use swc_ecma_parser::Syntax; +use swc_ecma_transforms_base::resolver; use swc_ecma_transforms_compat::es2022::{class_properties, static_blocks}; use swc_ecma_transforms_testing::test_fixture; use swc_ecma_visit::Fold; @@ -14,14 +15,21 @@ fn fixture(input: PathBuf) { test_fixture( Syntax::Es(Default::default()), &|t| { + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + let config = class_properties::Config::default(); let pass: Box = if input.to_string_lossy().contains("class-properties") { Box::new(chain!( + resolver(unresolved_mark, top_level_mark, false), static_blocks(config.static_blocks_mark), - class_properties(Some(t.comments.clone()), config) + class_properties(Some(t.comments.clone()), config, unresolved_mark) )) } else { - Box::new(static_blocks(config.static_blocks_mark)) + Box::new(chain!( + resolver(unresolved_mark, top_level_mark, false), + static_blocks(config.static_blocks_mark) + )) }; pass }, diff --git a/crates/swc_ecma_transforms_compat/tests/optional-chaining-loose/issue-7559/output.js b/crates/swc_ecma_transforms_compat/tests/optional-chaining-loose/issue-7559/output.js index 7d45f49e1ced..2eee8f654ce8 100644 --- a/crates/swc_ecma_transforms_compat/tests/optional-chaining-loose/issue-7559/output.js +++ b/crates/swc_ecma_transforms_compat/tests/optional-chaining-loose/issue-7559/output.js @@ -1,7 +1,13 @@ +var _x = /*#__PURE__*/ new WeakMap(); class Foo { - #x; test() { - var _this; - (_this = this) == null ? void 0 : _this.y.#x; + var _this, _this_y; + (_this = this) == null ? void 0 : _class_private_field_get(_this_y = _this.y, _x); + } + constructor(){ + _class_private_field_init(this, _x, { + writable: true, + value: void 0 + }); } } diff --git a/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/input.js b/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/input.js new file mode 100644 index 000000000000..8a79d38839e4 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/input.js @@ -0,0 +1,7 @@ +class Foo { + #x; + + test() { + this?.y.#x + } +} \ No newline at end of file diff --git a/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/output.js b/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/output.js new file mode 100644 index 000000000000..50460f0adc17 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/optional-chaining/issue-7561/output.js @@ -0,0 +1,13 @@ +var _x = /*#__PURE__*/ new WeakMap(); +class Foo { + test() { + var _this, _this_y; + (_this = this) === null || _this === void 0 ? void 0 : _class_private_field_get(_this_y = _this.y, _x); + } + constructor(){ + _class_private_field_init(this, _x, { + writable: true, + value: void 0 + }); + } +} diff --git a/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/input.js b/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/input.js new file mode 100644 index 000000000000..a754e387b018 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/input.js @@ -0,0 +1,9 @@ +// @target: es2015 + +class A { + #fieldFunc = function () { this.x = 10; }; + x = 1; + test() { + this.#fieldFunc?.(); + } +} diff --git a/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/output.js b/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/output.js new file mode 100644 index 000000000000..ea4f18424568 --- /dev/null +++ b/crates/swc_ecma_transforms_compat/tests/optional-chaining/private-field-call/output.js @@ -0,0 +1,17 @@ +// @target: es2015 +var _fieldFunc = /*#__PURE__*/ new WeakMap(); +class A { + test() { + var _this, _this1, _ref; + (_this = _class_private_field_get(_ref = _this1 = this, _fieldFunc)) === null || _this === void 0 ? void 0 : _this.call(_this1); + } + constructor(){ + _class_private_field_init(this, _fieldFunc, { + writable: true, + value: function() { + this.x = 10; + } + }); + _define_property(this, "x", 1); + } +} diff --git a/crates/swc_ecma_transforms_optimization/tests/simplify.rs b/crates/swc_ecma_transforms_optimization/tests/simplify.rs index bde83c6b01bb..0708e4bbf56c 100644 --- a/crates/swc_ecma_transforms_optimization/tests/simplify.rs +++ b/crates/swc_ecma_transforms_optimization/tests/simplify.rs @@ -506,7 +506,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), dce(Default::default(), unresolved_mark), inlining(Default::default()) @@ -553,7 +554,11 @@ test!( decorators(Default::default()), resolver(unresolved_mark, top_level_mark, false), strip(top_level_mark), - class_properties(Some(t.comments.clone()), Default::default()), + class_properties( + Some(t.comments.clone()), + Default::default(), + unresolved_mark + ), Repeat::new(chain!( expr_simplifier(unresolved_mark, Default::default()), inlining::inlining(Default::default()), diff --git a/crates/swc_ecma_transforms_optimization/tests/simplify_dce.rs b/crates/swc_ecma_transforms_optimization/tests/simplify_dce.rs index e9293531389b..67b759edf3ae 100644 --- a/crates/swc_ecma_transforms_optimization/tests/simplify_dce.rs +++ b/crates/swc_ecma_transforms_optimization/tests/simplify_dce.rs @@ -477,7 +477,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), tr() ) @@ -516,7 +517,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), tr(), ) @@ -598,7 +600,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), tr(), ) diff --git a/crates/swc_ecma_transforms_optimization/tests/simplify_inlining.rs b/crates/swc_ecma_transforms_optimization/tests/simplify_inlining.rs index 89072667236d..05bb75dd9a53 100644 --- a/crates/swc_ecma_transforms_optimization/tests/simplify_inlining.rs +++ b/crates/swc_ecma_transforms_optimization/tests/simplify_inlining.rs @@ -2072,7 +2072,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), inlining(Default::default()) ) @@ -2110,7 +2111,8 @@ test!( class_properties::Config { set_public_fields: true, ..Default::default() - } + }, + unresolved_mark ), inlining(Default::default()) ) diff --git a/crates/swc_ecma_transforms_proposal/tests/decorators.rs b/crates/swc_ecma_transforms_proposal/tests/decorators.rs index 9f0383b2f415..9b070918c741 100644 --- a/crates/swc_ecma_transforms_proposal/tests/decorators.rs +++ b/crates/swc_ecma_transforms_proposal/tests/decorators.rs @@ -142,7 +142,8 @@ fn create_pass(comments: Rc, input: &Path) -> Box, input: &Path) -> Box { add!(swc_ecma_transforms_compat::es2022::class_properties( Some(comments.clone()), - Default::default() + Default::default(), + unresolved_mark )); continue; } diff --git a/crates/swc_ecma_transforms_typescript/benches/compat.rs b/crates/swc_ecma_transforms_typescript/benches/compat.rs index 705cb879aca8..ba6f612bdaad 100644 --- a/crates/swc_ecma_transforms_typescript/benches/compat.rs +++ b/crates/swc_ecma_transforms_typescript/benches/compat.rs @@ -21,7 +21,7 @@ fn module(cm: Lrc) -> Module { parser.parse_module().map_err(|_| ()).unwrap() } -fn run(b: &mut Bencher, tr: impl Fn() -> V) +fn run(b: &mut Bencher, tr: impl Fn(Mark) -> V) where V: Fold, { @@ -37,7 +37,7 @@ where let module = module.clone(); helpers::HELPERS.set(&Default::default(), || { - let mut tr = tr(); + let mut tr = tr(unresolved_mark); black_box(module.fold_with(&mut tr)); }); @@ -64,7 +64,7 @@ fn base(b: &mut Bencher) { m } } - run(b, || Noop); + run(b, |_| Noop); } fn common_typescript(b: &mut Bencher) { @@ -89,7 +89,7 @@ fn common_typescript(b: &mut Bencher) { } fn common_reserved_word(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::reserved_words::reserved_words() }); } @@ -132,16 +132,17 @@ fn single_tr_group(c: &mut Criterion) { } fn es2020(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { swc_ecma_transforms_compat::es2022( Some(SingleThreadedComments::default()), Default::default(), + unresolved_mark, ) }); } fn es2020_nullish_coalescing(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2020::nullish_coalescing( swc_ecma_transforms_compat::es2020::nullish_coalescing::Config { no_document_all: false, @@ -151,38 +152,42 @@ fn es2020_nullish_coalescing(b: &mut Bencher) { } fn es2020_optional_chaining(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2020::optional_chaining(Default::default(), Mark::new()) }); } fn es2022_class_properties(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { swc_ecma_transforms_compat::es2022::class_properties( Some(SingleThreadedComments::default()), Default::default(), + unresolved_mark, ) }); } fn es2018(b: &mut Bencher) { - run(b, || swc_ecma_transforms_compat::es2018(Default::default())); + run( + b, + |_| swc_ecma_transforms_compat::es2018(Default::default()), + ); } fn es2018_object_rest_spread(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2018::object_rest_spread(Default::default()) }); } fn es2019_optional_catch_binding(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2019::optional_catch_binding() }); } fn es2017(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2017( Default::default(), Some(SingleThreadedComments::default()), @@ -192,7 +197,7 @@ fn es2017(b: &mut Bencher) { } fn es2017_async_to_generator(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2017::async_to_generator( Default::default(), Some(SingleThreadedComments::default()), @@ -202,17 +207,17 @@ fn es2017_async_to_generator(b: &mut Bencher) { } fn es2016(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2016); + run(b, |_| swc_ecma_transforms_compat::es2016()); } fn es2016_exponentiation(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2016::exponentiation); + run(b, |_| swc_ecma_transforms_compat::es2016::exponentiation()); } fn es2015(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { swc_ecma_transforms_compat::es2015( - Mark::fresh(Mark::root()), + unresolved_mark, Some(SingleThreadedComments::default()), Default::default(), ) @@ -220,23 +225,26 @@ fn es2015(b: &mut Bencher) { } fn es2015_arrow(b: &mut Bencher) { - run(b, || swc_ecma_transforms_compat::es2015::arrow(Mark::new())); + run( + b, + |_| swc_ecma_transforms_compat::es2015::arrow(Mark::new()), + ); } fn es2015_block_scoped_fn(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::block_scoped_functions() }); } fn es2015_block_scoping(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::block_scoping(Mark::new()) }); } fn es2015_classes(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::classes( Some(SingleThreadedComments::default()), Default::default(), @@ -245,68 +253,72 @@ fn es2015_classes(b: &mut Bencher) { } fn es2015_computed_props(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::computed_properties(Default::default()) }); } fn es2015_destructuring(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::destructuring(Default::default()) }); } fn es2015_duplicate_keys(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::duplicate_keys); + run(b, |_| swc_ecma_transforms_compat::es2015::duplicate_keys()); } fn es2015_parameters(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::parameters(Default::default(), Mark::new()) }); } fn es2015_fn_name(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::function_name); + run(b, |_| swc_ecma_transforms_compat::es2015::function_name()); } fn es2015_for_of(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::for_of(Default::default()) }); } fn es2015_instanceof(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::instance_of); + run(b, |_| swc_ecma_transforms_compat::es2015::instance_of()); } fn es2015_shorthand_property(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::shorthand); + run(b, |_| swc_ecma_transforms_compat::es2015::shorthand()); } fn es2015_spread(b: &mut Bencher) { - run(b, || { + run(b, |_| { swc_ecma_transforms_compat::es2015::spread(Default::default()) }); } fn es2015_sticky_regex(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::sticky_regex); + run(b, |_| swc_ecma_transforms_compat::es2015::sticky_regex()); } fn es2015_typeof_symbol(b: &mut Bencher) { - run(b, swc_ecma_transforms_compat::es2015::typeof_symbol); + run(b, |_| swc_ecma_transforms_compat::es2015::typeof_symbol()); } fn es3(b: &mut Bencher) { - run(b, || swc_ecma_transforms_compat::es3(Default::default())); + run(b, |_| swc_ecma_transforms_compat::es3(Default::default())); } fn full_es2016(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { let cmt = SingleThreadedComments::default(); chain!( - swc_ecma_transforms_compat::es2022(Some(cmt.clone()), Default::default()), + swc_ecma_transforms_compat::es2022( + Some(cmt.clone()), + Default::default(), + unresolved_mark + ), swc_ecma_transforms_compat::es2019(), swc_ecma_transforms_compat::es2018(Default::default()), swc_ecma_transforms_compat::es2017(Default::default(), Some(cmt), Mark::new()), @@ -316,10 +328,14 @@ fn full_es2016(b: &mut Bencher) { } fn full_es2017(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { let cmt = SingleThreadedComments::default(); chain!( - swc_ecma_transforms_compat::es2022(Some(cmt.clone()), Default::default()), + swc_ecma_transforms_compat::es2022( + Some(cmt.clone()), + Default::default(), + unresolved_mark + ), swc_ecma_transforms_compat::es2019(), swc_ecma_transforms_compat::es2018(Default::default()), swc_ecma_transforms_compat::es2017(Default::default(), Some(cmt), Mark::new()), @@ -328,11 +344,12 @@ fn full_es2017(b: &mut Bencher) { } fn full_es2018(b: &mut Bencher) { - run(b, || { + run(b, |unresolved_mark| { chain!( swc_ecma_transforms_compat::es2022( Some(SingleThreadedComments::default()), - Default::default() + Default::default(), + unresolved_mark ), swc_ecma_transforms_compat::es2019(), swc_ecma_transforms_compat::es2018(Default::default()), diff --git a/crates/swc_ecma_transforms_typescript/tests/strip.rs b/crates/swc_ecma_transforms_typescript/tests/strip.rs index 3d17cd8bd3ae..af74e111a2b8 100644 --- a/crates/swc_ecma_transforms_typescript/tests/strip.rs +++ b/crates/swc_ecma_transforms_typescript/tests/strip.rs @@ -46,16 +46,21 @@ fn tr_config( } fn properties(t: &Tester, loose: bool) -> impl Fold { - let mark = Mark::new(); + let static_blocks_mark = Mark::new(); + let unresolved_mark = Mark::new(); + let top_level_mark = Mark::new(); + chain!( - static_blocks(mark), + resolver(unresolved_mark, top_level_mark, false), + static_blocks(static_blocks_mark), class_properties( Some(t.comments.clone()), class_properties::Config { - static_blocks_mark: mark, + static_blocks_mark, set_public_fields: loose, ..Default::default() }, + unresolved_mark ) ) }