mirror of
https://github.com/swc-project/swc.git
synced 2024-10-04 04:07:18 +03:00
fix(es/compat): Handle private names from class properties pass (#8090)
**Related issue:** - Closes #7561 - https://github.com/vercel/next.js/issues/56612
This commit is contained in:
parent
407aa63cea
commit
83a5a0c612
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -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",
|
||||
|
@ -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)
|
||||
),
|
||||
|
@ -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
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
#x;
|
||||
|
||||
test() {
|
||||
this?.y.#x
|
||||
}
|
||||
}
|
15
crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js
Normal file
15
crates/swc/tests/fixture/issues-7xxx/7561/es2019/output/1.js
Normal file
@ -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
|
||||
});
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
#x;
|
||||
|
||||
test() {
|
||||
this?.y.#x
|
||||
}
|
||||
}
|
15
crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js
Normal file
15
crates/swc/tests/fixture/issues-7xxx/7561/es2021/output/1.js
Normal file
@ -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
|
||||
});
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
#x;
|
||||
|
||||
test() {
|
||||
this?.y.#x
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
class Foo {
|
||||
#x;
|
||||
test() {
|
||||
this?.y.#x;
|
||||
}
|
||||
}
|
@ -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))();
|
||||
|
@ -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))();
|
||||
|
@ -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" }
|
||||
|
@ -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<VarDeclarator>,
|
||||
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<ModuleItem>) {
|
||||
self.visit_mut_stmt_like(n);
|
||||
}
|
||||
|
||||
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
||||
self.visit_mut_stmt_like(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Memo {
|
||||
Cache(Ident),
|
||||
Raw(Box<Expr>),
|
||||
}
|
||||
|
||||
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<Gathering>,
|
||||
) -> (Expr, usize, Vec<Gathering>) {
|
||||
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<Gathering>), 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<T>(&mut self, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: Send + Sync + StmtLike + VisitMutWith<Self>,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
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<Expr> {
|
||||
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,
|
||||
}))
|
||||
}
|
||||
|
@ -43,12 +43,17 @@ mod used_name;
|
||||
/// # Impl note
|
||||
///
|
||||
/// We use custom helper to handle export default class
|
||||
pub fn class_properties<C: Comments>(cm: Option<C>, config: Config) -> impl Fold + VisitMut {
|
||||
pub fn class_properties<C: Comments>(
|
||||
cm: Option<C>,
|
||||
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: Comments> {
|
||||
c: Config,
|
||||
cm: Option<C>,
|
||||
private: PrivateRecord,
|
||||
unresolved_mark: Mark,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -551,7 +559,12 @@ impl<C: Comments> ClassProperties<C> {
|
||||
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<C: Comments> ClassProperties<C> {
|
||||
&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<C: Comments> ClassProperties<C> {
|
||||
|
||||
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<C: Comments> ClassProperties<C> {
|
||||
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<C: Comments> ClassProperties<C> {
|
||||
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<C: Comments> ClassProperties<C> {
|
||||
vars: vec![],
|
||||
private_access_type: Default::default(),
|
||||
c: self.c,
|
||||
unresolved_mark: self.unresolved_mark,
|
||||
});
|
||||
|
||||
self.private.pop();
|
||||
|
@ -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<VarDeclarator> {
|
||||
let mut priv_visitor = PrivateAccessVisitor {
|
||||
private,
|
||||
vars: vec![],
|
||||
private_access_type: Default::default(),
|
||||
c: config,
|
||||
unresolved_mark,
|
||||
};
|
||||
|
||||
expr.visit_mut_with(&mut priv_visitor);
|
||||
|
@ -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<C: Comments>(cm: Option<C>, config: Config) -> impl Fold {
|
||||
pub fn es2022<C: Comments>(cm: Option<C>, config: Config, unresolved_mark: Mark) -> impl Fold {
|
||||
chain!(
|
||||
regexp(regexp::Config {
|
||||
dot_all_regex: true,
|
||||
@ -25,7 +26,7 @@ pub fn es2022<C: Comments>(cm: Option<C>, 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(),
|
||||
)
|
||||
}
|
||||
|
470
crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs
Normal file
470
crates/swc_ecma_compat_es2022/src/optional_chaining_impl.rs
Normal file
@ -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<VarDeclarator>,
|
||||
unresolved_ctxt: SyntaxContext,
|
||||
c: Config,
|
||||
}
|
||||
|
||||
impl OptionalChaining {
|
||||
pub fn take_vars(&mut self) -> Vec<VarDeclarator> {
|
||||
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<ModuleItem>) {
|
||||
self.visit_mut_stmt_like(n);
|
||||
}
|
||||
|
||||
fn visit_mut_stmts(&mut self, n: &mut Vec<Stmt>) {
|
||||
self.visit_mut_stmt_like(n);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum Memo {
|
||||
Cache(Ident),
|
||||
Raw(Box<Expr>),
|
||||
}
|
||||
|
||||
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<Gathering>,
|
||||
) -> (Expr, usize, Vec<Gathering>) {
|
||||
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<Gathering>), 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<T>(&mut self, stmts: &mut Vec<T>)
|
||||
where
|
||||
T: Send + Sync + StmtLike + VisitMutWith<Self>,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
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<Expr> {
|
||||
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,
|
||||
}))
|
||||
}
|
@ -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]
|
||||
|
@ -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());
|
||||
|
@ -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() {}
|
||||
|
@ -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() {}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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, {
|
||||
|
@ -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, {
|
||||
|
@ -27,7 +27,7 @@
|
||||
});
|
||||
(function() {
|
||||
class Baz {
|
||||
constructor(force){
|
||||
constructor(force1){
|
||||
var _this = this;
|
||||
_define_property(this, "fn", function() {
|
||||
return console.log(_this);
|
||||
|
@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
#x;
|
||||
|
||||
test() {
|
||||
this?.y.#x;
|
||||
}
|
||||
}
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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);
|
@ -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);
|
@ -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())
|
||||
)
|
||||
},
|
||||
|
@ -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::<SingleThreadedComments>(mark, None, Default::default()),
|
||||
es2015::<SingleThreadedComments>(unresolved_mark, None, Default::default()),
|
||||
)
|
||||
},
|
||||
issue_1799_5,
|
||||
|
@ -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<dyn Fold> {
|
||||
let mut pass: Box<dyn Fold> = Box::new(noop());
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let mut pass: Box<dyn Fold> = 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<dyn Fold> {
|
||||
private_as_properties: loose,
|
||||
no_document_all: loose,
|
||||
static_blocks_mark: Mark::new(),
|
||||
}
|
||||
pure_getter: loose,
|
||||
},
|
||||
unresolved_mark,
|
||||
)
|
||||
));
|
||||
}
|
||||
|
@ -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()),
|
||||
|
@ -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,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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<dyn Fold> = Box::new(noop());
|
||||
let unresolved_mark = Mark::new();
|
||||
let top_level_mark = Mark::new();
|
||||
|
||||
let mut pass: Box<dyn Fold> =
|
||||
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,
|
||||
)
|
||||
));
|
||||
}
|
||||
|
@ -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<dyn Fold> = 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
|
||||
},
|
||||
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
class Foo {
|
||||
#x;
|
||||
|
||||
test() {
|
||||
this?.y.#x
|
||||
}
|
||||
}
|
@ -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
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
// @target: es2015
|
||||
|
||||
class A {
|
||||
#fieldFunc = function () { this.x = 10; };
|
||||
x = 1;
|
||||
test() {
|
||||
this.#fieldFunc?.();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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()),
|
||||
|
@ -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(),
|
||||
)
|
||||
|
@ -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())
|
||||
)
|
||||
|
@ -142,7 +142,8 @@ fn create_pass(comments: Rc<SingleThreadedComments>, input: &Path) -> Box<dyn Fo
|
||||
));
|
||||
add!(swc_ecma_transforms_compat::es2022::class_properties(
|
||||
Some(comments.clone()),
|
||||
Default::default()
|
||||
Default::default(),
|
||||
unresolved_mark
|
||||
));
|
||||
continue;
|
||||
}
|
||||
@ -150,7 +151,8 @@ fn create_pass(comments: Rc<SingleThreadedComments>, input: &Path) -> Box<dyn Fo
|
||||
"proposal-private-methods" => {
|
||||
add!(swc_ecma_transforms_compat::es2022::class_properties(
|
||||
Some(comments.clone()),
|
||||
Default::default()
|
||||
Default::default(),
|
||||
unresolved_mark
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ fn module(cm: Lrc<SourceMap>) -> Module {
|
||||
parser.parse_module().map_err(|_| ()).unwrap()
|
||||
}
|
||||
|
||||
fn run<V>(b: &mut Bencher, tr: impl Fn() -> V)
|
||||
fn run<V>(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()),
|
||||
|
@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user