Skip to content

Commit

Permalink
fix(es/compat): Fix classes pass (#3107)
Browse files Browse the repository at this point in the history
swc_ecma_ast:
 - Add `Ident::verify_symbol`.

swc_ecma_transforms_compat:
 - Don't generate invalid identifiers. (Closes #3106)
  • Loading branch information
kdy1 authored Dec 24, 2021
1 parent d7a489a commit d923f89
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 6 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/swc_ecma_ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ serde = {version = "1.0.88", features = ["derive"]}
string_enum = {version = "0.3.1", path = "../string_enum"}
swc_atoms = {version = "0.2", path = "../swc_atoms"}
swc_common = {version = "0.15.0", path = "../swc_common"}
unicode-xid = "0.2"

[dev-dependencies]
serde_json = "1"
74 changes: 73 additions & 1 deletion crates/swc_ecma_ast/src/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use swc_atoms::{js_word, JsWord};
use swc_common::{
ast_node, util::take::Take, EqIgnoreSpan, Span, Spanned, SyntaxContext, DUMMY_SP,
};
use unicode_xid::UnicodeXID;

/// Identifer used as a pattern.
/// Identifier used as a pattern.
#[derive(Spanned, Clone, Debug, PartialEq, Eq, Hash, EqIgnoreSpan, Serialize, Deserialize)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct BindingIdent {
Expand Down Expand Up @@ -85,6 +86,77 @@ pub struct Ident {
pub optional: bool,
}

impl Ident {
/// Returns true if `c` is a valid character for an identifier start.
pub fn is_valid_start(c: char) -> bool {
c == '$' || c == '_' || c.is_ascii_alphabetic() || {
if c.is_ascii() {
false
} else {
UnicodeXID::is_xid_start(c)
}
}
}

/// Returns true if `c` is a valid character for an identifier part after
/// start.
pub fn is_valid_continue(c: char) -> bool {
c == '$' || c == '_' || c == '\u{200c}' || c == '\u{200d}' || c.is_ascii_alphanumeric() || {
if c.is_ascii() {
false
} else {
UnicodeXID::is_xid_continue(c)
}
}
}

/// Alternative for `toIdentifier` of babel.
///
/// Returns [Ok] if it's a valid identifier and [Err] if it's not valid.
/// The returned [Err] contains the valid symbol.
pub fn verify_symbol(s: &str) -> Result<(), String> {
if s.is_reserved() || s.is_reserved_in_strict_mode(true) || s.is_reserved_in_strict_bind() {
let mut buf = String::with_capacity(s.len() + 1);
buf.push('_');
buf.push_str(s);
return Err(buf);
}

{
let mut chars = s.chars();

if let Some(first) = chars.next() {
if Self::is_valid_start(first) {
if chars.all(Self::is_valid_continue) {
return Ok(());
}
}
}
}

let mut buf = String::with_capacity(s.len() + 2);
let mut has_start = false;

for c in s.chars() {
if !has_start && Self::is_valid_start(c) {
has_start = true;
buf.push(c);
continue;
}

if Self::is_valid_continue(c) {
buf.push(c);
}
}

if buf.is_empty() {
buf.push('_');
}

Err(buf)
}
}

/// See [Ident] for documentation.
pub type Id = (JsWord, SyntaxContext);

Expand Down
9 changes: 4 additions & 5 deletions crates/swc_ecma_transforms_compat/src/es2015/classes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -959,11 +959,10 @@ fn escape_keywords(mut e: Box<Expr>) -> Box<Expr> {
match &mut *e {
Expr::Fn(f) => {
if let Some(i) = &mut f.ident {
if i.is_reserved()
|| i.is_reserved_in_strict_mode(true)
|| i.is_reserved_in_strict_bind()
{
i.sym = format!("_{}", i.sym).into();
let sym = Ident::verify_symbol(&i.sym);

if let Err(new) = sym {
i.sym = new.into();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class ValidationStrategy {
static "object?"(value) {
return 1;
}

static "string!"(value) {
return 2;
}
}
console.log(ValidationStrategy.prototype['string!']);

1 comment on commit d923f89

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: d923f89 Previous: 4bb264d Ratio
full_es2015 218630662 ns/iter (± 11820818) 184696207 ns/iter (± 5919248) 1.18
full_es2016 179267692 ns/iter (± 9260659) 153820814 ns/iter (± 6148785) 1.17
full_es2017 184929757 ns/iter (± 13905304) 157317635 ns/iter (± 6161648) 1.18
full_es2018 183525219 ns/iter (± 12228732) 157241633 ns/iter (± 6307768) 1.17
full_es2019 184361774 ns/iter (± 15389514) 154599971 ns/iter (± 8131076) 1.19
full_es2020 181203203 ns/iter (± 15660779) 153648859 ns/iter (± 5903251) 1.18
full_es3 249169648 ns/iter (± 12966730) 211121587 ns/iter (± 13167561) 1.18
full_es5 232757995 ns/iter (± 15255831) 196094844 ns/iter (± 7641572) 1.19
parser 795682 ns/iter (± 31309) 685831 ns/iter (± 22848) 1.16

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.