Skip to content

Commit

Permalink
fix(es/compat): Avoid reserved name for private method (#8949)
Browse files Browse the repository at this point in the history
**Description:**

Following development should follow babel/babel#16261 to avoid separate `WeakMap` for each individual private method


**Related issue:**

 - Closes #8948.
  • Loading branch information
Austaras authored May 13, 2024
1 parent 5125598 commit 7053bb1
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 18 deletions.
11 changes: 10 additions & 1 deletion crates/swc_ecma_ast/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ static RESSERVED_IN_STRICT_MODE: phf::Set<&str> = phf_set!(
"yield",
);

static RESSERVED_IN_STRICT_BIND: phf::Set<&str> = phf_set!("eval", "arguments",);

static RESERVED_IN_ES3: phf::Set<&str> = phf_set!(
"abstract",
"boolean",
Expand Down Expand Up @@ -457,12 +459,19 @@ pub trait IdentExt: AsRef<str> {
}

fn is_reserved_in_strict_bind(&self) -> bool {
["eval", "arguments"].contains(&self.as_ref())
RESSERVED_IN_STRICT_BIND.contains(self.as_ref())
}

fn is_reserved_in_es3(&self) -> bool {
RESERVED_IN_ES3.contains(self.as_ref())
}

fn is_reserved_in_any(&self) -> bool {
RESERVED.contains(self.as_ref())
|| RESSERVED_IN_STRICT_MODE.contains(self.as_ref())
|| RESSERVED_IN_STRICT_BIND.contains(self.as_ref())
|| RESERVED_IN_ES3.contains(self.as_ref())
}
}

impl IdentExt for Atom {}
Expand Down
16 changes: 9 additions & 7 deletions crates/swc_ecma_compat_es2022/src/class_properties/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use swc_common::{
collections::{AHashMap, AHashSet},
comments::Comments,
errors::HANDLER,
util::take::Take,
Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
collections::AHashMap, comments::Comments, errors::HANDLER, util::take::Take, Mark, Span,
Spanned, SyntaxContext, DUMMY_SP,
};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::{helper, perf::Check};
Expand Down Expand Up @@ -530,7 +527,6 @@ impl<C: Comments> ClassProperties<C> {
let mut super_ident = None;

class.body.visit_mut_with(&mut BrandCheckHandler {
names: &mut AHashSet::default(),
private: &self.private,
});

Expand Down Expand Up @@ -806,7 +802,13 @@ impl<C: Comments> ClassProperties<C> {
match method.kind {
MethodKind::Getter => format!("get_{}", method.key.id.sym).into(),
MethodKind::Setter => format!("set_{}", method.key.id.sym).into(),
MethodKind::Method => method.key.id.sym.clone(),
MethodKind::Method => {
if method.key.id.is_reserved_in_any() {
format!("__{}", method.key.id.sym).into()
} else {
method.key.id.sym.clone()
}
}
},
method
.span
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ use std::iter;

use swc_atoms::JsWord;
use swc_common::{
collections::{AHashMap, AHashSet},
errors::HANDLER,
util::take::Take,
Mark, Spanned, SyntaxContext, DUMMY_SP,
collections::AHashMap, errors::HANDLER, util::take::Take, Mark, Spanned, SyntaxContext,
DUMMY_SP,
};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::helper;
Expand Down Expand Up @@ -83,9 +81,6 @@ impl PrivateKind {
}

pub(super) struct BrandCheckHandler<'a> {
/// Private names used for brand checks.
pub names: &'a mut AHashSet<JsWord>,

pub private: &'a PrivateRecord,
}

Expand Down Expand Up @@ -117,8 +112,6 @@ impl VisitMut for BrandCheckHandler<'_> {
}
}

self.names.insert(n.id.sym.clone());

let (mark, kind, class_name) = self.private.get(&n.id);

if mark == Mark::root() {
Expand Down Expand Up @@ -596,7 +589,11 @@ impl<'a> PrivateAccessVisitor<'a> {
}

let method_name = Ident::new(
n.id.sym.clone(),
if n.id.is_reserved_in_any() {
format!("__{}", n.id.sym).into()
} else {
n.id.sym.clone()
},
n.id.span.with_ctxt(SyntaxContext::empty()).apply_mark(mark),
);
let ident = Ident::new(format!("_{}", n.id.sym).into(), n.id.span.apply_mark(mark));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var _switch = /*#__PURE__*/ _class_private_field_loose_key("_switch"), _bar = /*#__PURE__*/ _class_private_field_loose_key("_bar");
class TestCls {
foo() {
_class_private_field_loose_base(this, _bar)[_bar]();
_class_private_field_loose_base(this, _switch)[_switch]();
}
constructor(){
Object.defineProperty(this, _switch, {
value: __switch
});
Object.defineProperty(this, _bar, {
value: bar
});
}
}
function __switch() {
console.log("#switch called");
}
function bar() {
console.log("#bar called");
}
export { TestCls };
let a = new TestCls;
a.foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class TestCls {
foo() {
this.#bar();
this.#switch();
}
#switch() {
console.log("#switch called");
}

#bar() {
console.log("#bar called");
}
}

let a = new TestCls();
a.foo();
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
var _switch = /*#__PURE__*/ new WeakSet(), _bar = /*#__PURE__*/ new WeakSet();
class TestCls {
foo() {
_class_private_method_get(this, _bar, bar).call(this);
_class_private_method_get(this, _switch, __switch).call(this);
}
constructor(){
_class_private_method_init(this, _switch);
_class_private_method_init(this, _bar);
}
}
function __switch() {
console.log("#switch called");
}
function bar() {
console.log("#bar called");
}
let a = new TestCls();
a.foo();
40 changes: 40 additions & 0 deletions crates/swc_ecma_transforms_compat/tests/es2022_class_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4831,6 +4831,46 @@ class Cl {
"#
);

test!(
syntax(),
|t| {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();

chain!(
resolver(unresolved_mark, top_level_mark, false),
class_properties(
Some(t.comments.clone()),
class_properties::Config {
private_as_properties: true,
..Default::default()
},
unresolved_mark,
)
)
},
loose_keyword_method,
r##"
class TestCls{
foo(){
this.#bar()
this.#switch()
}
#switch(){
console.log("#switch called")
}
#bar(){
console.log("#bar called")
}
}
export {TestCls}
let a = new TestCls
a.foo()
"##
);

#[testing::fixture("tests/classes/**/exec.js")]
fn exec(input: PathBuf) {
let src = read_to_string(input).unwrap();
Expand Down

0 comments on commit 7053bb1

Please sign in to comment.