LibJS: Add missing early errors in Rust parser
- Reject `true`, `false`, `null` as label identifiers - Reject generator declarations in if-statement bodies (not covered by Annex B) - Reject `await` as label in class static init blocks and modules - Reject `arguments` in class static initialization blocks - Reject generator shorthand without method body in object literals - Reject `get constructor()` / `set constructor()` in class bodies - Reject `super.#private` member access
This commit is contained in:
parent
71713017c5
commit
6029a3d40e
3 changed files with 56 additions and 10 deletions
|
|
@ -1081,6 +1081,13 @@ impl Parser<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#sec-class-definitions-static-semantics-early-errors
|
||||
// It is a Syntax Error if PropName of MethodDefinition is "constructor"
|
||||
// and SpecialMethod of MethodDefinition is true (getter/setter).
|
||||
if !is_static && (is_getter || is_setter) && key_value.as_deref() == Some(ctor_name) {
|
||||
self.syntax_error("Class constructor may not be an accessor");
|
||||
}
|
||||
|
||||
let method_kind = if is_constructor {
|
||||
MethodKind::Constructor
|
||||
} else if is_getter {
|
||||
|
|
|
|||
|
|
@ -202,13 +202,21 @@ impl Parser<'_> {
|
|||
// falsely flagging parameter names like `function f(arguments)`.
|
||||
if let ExpressionKind::Identifier(ref id) = expression.inner
|
||||
&& id.name == utf16!("arguments")
|
||||
&& !self.flags.strict_mode
|
||||
&& !self
|
||||
.scope_collector
|
||||
.has_declaration_in_current_function(&id.name)
|
||||
{
|
||||
self.scope_collector
|
||||
.set_contains_access_to_arguments_object_in_non_strict_mode();
|
||||
// https://tc39.es/ecma262/#sec-class-static-initialization-blocks
|
||||
// It is a Syntax Error if ContainsArguments of ClassStaticBlockBody is true.
|
||||
if self.flags.in_class_static_init_block {
|
||||
self.syntax_error(
|
||||
"'arguments' is not allowed in class static initialization blocks",
|
||||
);
|
||||
} else if !self.flags.strict_mode
|
||||
&& !self
|
||||
.scope_collector
|
||||
.has_declaration_in_current_function(&id.name)
|
||||
{
|
||||
self.scope_collector
|
||||
.set_contains_access_to_arguments_object_in_non_strict_mode();
|
||||
}
|
||||
}
|
||||
|
||||
if !should_continue {
|
||||
|
|
@ -918,6 +926,12 @@ impl Parser<'_> {
|
|||
TokenType::Period => {
|
||||
self.consume();
|
||||
if self.match_token(TokenType::PrivateIdentifier) {
|
||||
// https://tc39.es/ecma262/#sec-static-semantics-early-errors
|
||||
// It is a Syntax Error if MemberExpression is SuperProperty
|
||||
// and the PrivateIdentifier is present.
|
||||
if matches!(lhs.inner, ExpressionKind::Super) {
|
||||
self.syntax_error("Cannot access private field or method via 'super'");
|
||||
}
|
||||
// C++ uses rule_start (period position) for property identifiers.
|
||||
let id = self.parse_private_identifier(start);
|
||||
let property = self.expression(start, ExpressionKind::PrivateIdentifier(id));
|
||||
|
|
@ -1636,6 +1650,10 @@ impl Parser<'_> {
|
|||
if is_async {
|
||||
self.syntax_error("Expected function after async keyword");
|
||||
}
|
||||
// Generator shorthand requires a method body.
|
||||
if is_generator {
|
||||
self.syntax_error("Expected method after generator star");
|
||||
}
|
||||
|
||||
if is_getter || is_setter {
|
||||
let method_kind = if is_getter {
|
||||
|
|
|
|||
|
|
@ -269,7 +269,13 @@ impl Parser<'_> {
|
|||
let predicate = self.parse_expression_any();
|
||||
self.consume_token(TokenType::ParenClose);
|
||||
|
||||
let consequent = if !self.flags.strict_mode && self.match_token(TokenType::Function) {
|
||||
// https://tc39.es/ecma262/#sec-functiondeclarations-in-ifstatement-statement-clauses
|
||||
// Annex B allows FunctionDeclarations (but NOT GeneratorDeclarations) in
|
||||
// IfStatement bodies in sloppy mode.
|
||||
let consequent = if !self.flags.strict_mode
|
||||
&& self.match_token(TokenType::Function)
|
||||
&& self.next_token().token_type != TokenType::Asterisk
|
||||
{
|
||||
self.parse_function_declaration_as_block_statement(start)
|
||||
} else {
|
||||
self.parse_statement(false)
|
||||
|
|
@ -277,7 +283,10 @@ impl Parser<'_> {
|
|||
|
||||
let alternate = if self.match_token(TokenType::Else) {
|
||||
self.consume();
|
||||
if !self.flags.strict_mode && self.match_token(TokenType::Function) {
|
||||
if !self.flags.strict_mode
|
||||
&& self.match_token(TokenType::Function)
|
||||
&& self.next_token().token_type != TokenType::Asterisk
|
||||
{
|
||||
Some(Box::new(
|
||||
self.parse_function_declaration_as_block_statement(start),
|
||||
))
|
||||
|
|
@ -819,6 +828,14 @@ impl Parser<'_> {
|
|||
self.discard_saved_state();
|
||||
self.consume(); // consume :
|
||||
|
||||
// https://tc39.es/ecma262/#sec-labelled-statements
|
||||
// LabelIdentifier : Identifier (not ReservedWord)
|
||||
// `true`, `false`, and `null` are reserved words and cannot be labels.
|
||||
if token.token_type == TokenType::BoolLiteral || token.token_type == TokenType::NullLiteral
|
||||
{
|
||||
self.syntax_error("Reserved word cannot be used as a label");
|
||||
}
|
||||
|
||||
if self.flags.strict_mode
|
||||
&& (label == utf16!("let") || crate::parser::is_strict_reserved_word(&label))
|
||||
{
|
||||
|
|
@ -827,8 +844,12 @@ impl Parser<'_> {
|
|||
if self.flags.in_generator_function_context && label == utf16!("yield") {
|
||||
self.syntax_error("'yield' label is not allowed in generator function context");
|
||||
}
|
||||
if self.flags.await_expression_is_valid && label == utf16!("await") {
|
||||
self.syntax_error("'await' label is not allowed in async function context");
|
||||
if (self.flags.await_expression_is_valid
|
||||
|| self.flags.in_class_static_init_block
|
||||
|| self.program_type == crate::parser::ProgramType::Module)
|
||||
&& label == utf16!("await")
|
||||
{
|
||||
self.syntax_error("'await' is not allowed as a label in this context");
|
||||
}
|
||||
|
||||
if self.labels_in_scope.contains_key(label.as_slice()) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue