feat(syntax): export is_reserved_keyword and is_global_object method (#3384)

This commit is contained in:
Boshen 2024-05-22 04:58:04 +00:00
parent bb2221e4f4
commit e2dd8ac8fc
5 changed files with 97 additions and 26 deletions

View file

@ -4,7 +4,7 @@ use oxc_ast::ast::*;
use oxc_span::GetSpan;
use oxc_syntax::{
identifier::{LS, PS},
keyword::is_keyword,
keyword::is_reserved_keyword_or_global_object,
number::NumberBase,
operator::{BinaryOperator, UnaryOperator},
precedence::{GetPrecedence, Precedence},
@ -1735,17 +1735,19 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for AssignmentExpression<'a> {
let identifier_is_keyword = match &self.left {
AssignmentTarget::AssignmentTargetIdentifier(target) => {
is_keyword(target.name.as_str())
is_reserved_keyword_or_global_object(target.name.as_str())
}
AssignmentTarget::ComputedMemberExpression(expression) => match &expression.object {
Expression::Identifier(ident) => is_keyword(ident.name.as_str()),
Expression::Identifier(ident) => {
is_reserved_keyword_or_global_object(ident.name.as_str())
}
_ => false,
},
AssignmentTarget::StaticMemberExpression(expression) => {
is_keyword(expression.property.name.as_str())
is_reserved_keyword_or_global_object(expression.property.name.as_str())
}
AssignmentTarget::PrivateFieldExpression(expression) => {
is_keyword(expression.field.name.as_str())
is_reserved_keyword_or_global_object(expression.field.name.as_str())
}
_ => false,
};

View file

@ -23,5 +23,5 @@ fn undefined() {
test("try {} catch(undefined) {}", "try{}catch(undefined){}");
test("for (undefined in {}) {}", "for(undefined in {}){}");
test("undefined++", "undefined++;");
test("undefined += undefined;", "(undefined+=void 0);");
test("undefined += undefined;", "undefined+=void 0;");
}

View file

@ -1,13 +1,82 @@
#[rustfmt::skip]
pub fn is_keyword(s: &str) -> bool {
matches!(s, "as" | "do" | "if" | "in" | "is" | "of"
| "any" | "for" | "get" | "let" | "new" | "out" | "set" | "try" | "var"
| "case" | "else" | "enum" | "from" | "meta" | "null" | "this" | "true" | "type" | "void" | "with"
| "async" | "await" | "break" | "catch" | "class" | "const" | "false" | "infer" | "keyof" | "never" | "super" | "throw" | "using" | "while" | "yield"
| "assert" | "bigint" | "delete" | "export" | "global" | "import" | "module" | "number" | "object" | "public" | "return" | "static" | "string" | "switch" | "symbol" | "target" | "typeof" | "unique"
| "asserts" | "boolean" | "declare" | "default" | "extends" | "finally" | "package" | "private" | "require" | "unknown" | "abstract"
| "accessor" | "continue" | "debugger" | "function" | "override" | "readonly" | "interface" | "intrinsic" | "namespace" | "protected" | "satisfies" | "undefined"
| "implements" | "instanceof"
| "constructor"
)
use phf::{phf_set, Set};
#[inline]
pub fn is_reserved_keyword_or_global_object(s: &str) -> bool {
is_reserved_keyword(s) || is_reserved_keyword(s)
}
#[inline]
pub fn is_reserved_keyword(s: &str) -> bool {
RESERVED_KEYWORDS.contains(s)
}
/// Checks `Infinity`, `NaN`, `globalThis` and `undefined`
#[inline]
pub fn is_global_object(s: &str) -> bool {
GLOBAL_OBJECTS.contains(s)
}
/// Value properties of the global object
///
/// Reference: <https://tc39.es/ecma262/multipage/global-object.html#sec-value-properties-of-the-global-object>
pub const GLOBAL_OBJECTS: Set<&'static str> = phf_set! {
"Infinity",
"NaN",
"globalThis",
"undefined",
};
/// All reserved keywords, including keywords that are contextually disallowed as identifiers.
///
/// Reference: <https://tc39.es/ecma262/#prod-ReservedWord>
pub const RESERVED_KEYWORDS: Set<&'static str> = phf_set! {
// contextually disallowed as identifiers
"let",
"static",
// future reserved keywords
"implements",
"interface",
"package",
"private",
"protected",
"public",
// reserved word
"await",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"false",
"finally",
"for",
"function",
"if",
"import",
"in",
"instanceof",
"new",
"null",
"return",
"super",
"switch",
"this",
"throw",
"true",
"try",
"typeof",
"var",
"void",
"while",
"with",
"yield",
};

View file

@ -1132,9 +1132,9 @@ Invalid Character `[`
(430:43-430:55) ".prototype =" --> (217:45-217:57) ".prototype ="
(430:55-430:59) " new" --> (217:57-217:61) " new"
(430:59-431:0) " ComponentDummy();" --> (217:61-218:0) " ComponentDummy();"
(431:0-431:23) "\npureComponentPrototype" --> (218:0-218:26) "\n\t\t(pureComponentPrototype"
(431:23-431:37) ".constructor =" --> (218:26-218:40) ".constructor ="
(431:37-433:0) " PureComponent; // Avoid an extra prototype jump for these methods.\n" --> (218:40-219:0) " PureComponent);"
(431:0-431:23) "\npureComponentPrototype" --> (218:0-218:25) "\n\t\tpureComponentPrototype"
(431:23-431:37) ".constructor =" --> (218:25-218:39) ".constructor ="
(431:37-433:0) " PureComponent; // Avoid an extra prototype jump for these methods.\n" --> (218:39-219:0) " PureComponent;"
(433:0-433:8) "\n_assign" --> (219:0-219:10) "\n\t\t_assign"
(433:8-433:32) "(pureComponentPrototype," --> (219:10-219:34) "(pureComponentPrototype,"
(433:32-433:42) " Component" --> (219:34-219:44) " Component"
@ -5045,9 +5045,9 @@ Invalid Character `[`
(2246:58-2246:64) "(null," --> (1464:59-1464:65) "(null,"
(2246:64-2246:69) " type" --> (1464:65-1464:70) " type"
(2246:69-2247:2) ");\n " --> (1464:70-1465:0) ");"
(2247:2-2247:19) " validatedFactory" --> (1465:0-1465:21) "\n\t\t\t(validatedFactory"
(2247:19-2247:26) ".type =" --> (1465:21-1465:28) ".type ="
(2247:26-2249:2) " type;\n\n " --> (1465:28-1466:3) " type);\n\t\t"
(2247:2-2247:19) " validatedFactory" --> (1465:0-1465:20) "\n\t\t\tvalidatedFactory"
(2247:19-2247:26) ".type =" --> (1465:20-1465:27) ".type ="
(2247:26-2249:2) " type;\n\n " --> (1465:27-1466:3) " type;\n\t\t"
(2249:2-2250:4) " {\n " --> (1466:3-1467:0) "\t{"
(2250:4-2250:9) " if (" --> (1467:0-1467:10) "\n\t\t\t\tif ( "
(2250:9-2250:46) "!didWarnAboutDeprecatedCreateFactory)" --> (1467:10-1467:47) "!didWarnAboutDeprecatedCreateFactory)"

View file

@ -14,9 +14,9 @@ test = false
[dependencies]
oxc_linter = { workspace = true }
oxc_cli = { path = "../../crates/oxc_cli" }
oxc_cli = { path = "../../crates/oxc_cli" }
bpaf = { workspace = true, features = ["docgen"] }
bpaf = { workspace = true, features = ["docgen"] }
pico-args = { workspace = true }
serde_json = { workspace = true }
schemars = { workspace = true }