Browse Source

Scripts should not be considered in a block (#1339)

* Scripts are not considered "in a block"

* Duplicate parameter names are now checked for functions

* Parameter names hashset now uses Box<str> instead of String

* Added duplicate parameter test
pull/1356/head
macmv 3 years ago committed by GitHub
parent
commit
b5d2ce828e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      boa/src/syntax/parser/function/mod.rs
  2. 12
      boa/src/syntax/parser/function/tests.rs
  3. 2
      boa/src/syntax/parser/mod.rs

13
boa/src/syntax/parser/function/mod.rs

@ -12,10 +12,7 @@ mod tests;
use crate::{ use crate::{
syntax::{ syntax::{
ast::{ ast::{node, Punctuator},
node::{self},
Punctuator,
},
lexer::{InputElement, TokenKind}, lexer::{InputElement, TokenKind},
parser::{ parser::{
expression::Initializer, expression::Initializer,
@ -25,7 +22,7 @@ use crate::{
}, },
BoaProfiler, BoaProfiler,
}; };
use std::io::Read; use std::{collections::HashSet, io::Read};
/// Formal parameters parsing. /// Formal parameters parsing.
/// ///
@ -66,6 +63,7 @@ where
cursor.set_goal(InputElement::RegExp); cursor.set_goal(InputElement::RegExp);
let mut params = Vec::new(); let mut params = Vec::new();
let mut param_names = HashSet::new();
if cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() if cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind()
== &TokenKind::Punctuator(Punctuator::CloseParen) == &TokenKind::Punctuator(Punctuator::CloseParen)
@ -76,6 +74,7 @@ where
loop { loop {
let mut rest_param = false; let mut rest_param = false;
let position = cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.span().start();
let next_param = match cursor.peek(0)? { let next_param = match cursor.peek(0)? {
Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Spread) => { Some(tok) if tok.kind() == &TokenKind::Punctuator(Punctuator::Spread) => {
rest_param = true; rest_param = true;
@ -83,7 +82,11 @@ where
} }
_ => FormalParameter::new(self.allow_yield, self.allow_await).parse(cursor)?, _ => FormalParameter::new(self.allow_yield, self.allow_await).parse(cursor)?,
}; };
if param_names.contains(next_param.name()) {
return Err(ParseError::general("duplicate parameter name", position));
}
param_names.insert(Box::from(next_param.name()));
params.push(next_param); params.push(next_param);
if cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind() if cursor.peek(0)?.ok_or(ParseError::AbruptEnd)?.kind()

12
boa/src/syntax/parser/function/tests.rs

@ -4,7 +4,7 @@ use crate::syntax::{
Identifier, Node, Return, Identifier, Node, Return,
}, },
ast::op::NumOp, ast::op::NumOp,
parser::tests::check_parser, parser::{tests::check_parser, Parser},
}; };
/// Checks basic function declaration parsing. /// Checks basic function declaration parsing.
@ -21,6 +21,16 @@ fn check_basic() {
); );
} }
/// Checks for duplicate parameter names.
#[test]
fn check_duplicates() {
let js = "function foo(a, a) {}";
let res = Parser::new(js.as_bytes(), false).parse_all();
dbg!(&res);
assert!(res.is_err());
}
/// Checks basic function declaration parsing with automatic semicolon insertion. /// Checks basic function declaration parsing with automatic semicolon insertion.
#[test] #[test]
fn check_basic_semicolon_insertion() { fn check_basic_semicolon_insertion() {

2
boa/src/syntax/parser/mod.rs

@ -153,6 +153,6 @@ where
type Output = StatementList; type Output = StatementList;
fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> { fn parse(self, cursor: &mut Cursor<R>) -> Result<Self::Output, ParseError> {
self::statement::StatementList::new(false, false, false, true, &[]).parse(cursor) self::statement::StatementList::new(false, false, false, false, &[]).parse(cursor)
} }
} }

Loading…
Cancel
Save