Browse Source

Fix unary operations on `this` (#2507)

<!---
Thank you for contributing to Boa! Please fill out the template below, and remove or add any
information as you feel necessary.
--->

This Pull Request fixes/closes #2416.

Previously, prefix increment and decrement operations on `this` caused a panic. This PR makes the parser issue a syntax error when the operand UnaryExpression is not simple (as mentioned in https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors).
pull/2510/head
Veera 2 years ago
parent
commit
f216a6dda9
  1. 17
      boa_engine/src/tests.rs
  2. 66
      boa_parser/src/parser/expression/update.rs

17
boa_engine/src/tests.rs

@ -2836,3 +2836,20 @@ fn spread_with_call() {
"#;
assert_eq!(&exec(scenario), r#""message""#);
}
#[test]
fn unary_operations_on_this() {
// https://tc39.es/ecma262/#sec-assignment-operators-static-semantics-early-errors
let mut context = Context::default();
let test_cases = [
("++this", "1:1"),
("--this", "1:1"),
("this++", "1:5"),
("this--", "1:5"),
];
for (case, pos) in &test_cases {
let string = forward(&mut context, case);
assert!(string.starts_with("Uncaught SyntaxError: "));
assert!(string.contains(pos));
}
}

66
boa_parser/src/parser/expression/update.rs

@ -21,9 +21,9 @@ use boa_ast::{
operator::{unary::UnaryOp, Unary},
Identifier,
},
Expression, Punctuator,
Expression, Position, Punctuator,
};
use boa_interner::{Interner, Sym};
use boa_interner::Interner;
use boa_profiler::Profiler;
use std::io::Read;
@ -56,6 +56,21 @@ impl UpdateExpression {
}
}
/// <https://tc39.es/ecma262/multipage/syntax-directed-operations.html#sec-static-semantics-assignmenttargettype>
/// This function checks if the target type is simple
fn is_simple(expr: &Expression, position: Position, strict: bool) -> ParseResult<bool> {
match expr {
Expression::Identifier(ident) => {
if strict {
check_strict_arguments_or_eval(*ident, position)?;
}
Ok(true)
}
Expression::PropertyAccess(_) => Ok(true),
_ => Ok(false),
}
}
impl<R> TokenParser<R> for UpdateExpression
where
R: Read,
@ -75,11 +90,12 @@ where
let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
if cursor.strict_mode() {
if let Expression::Identifier(ident) = target {
check_strict_arguments_or_eval(ident, position)?;
}
// https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors
if !is_simple(&target, position, cursor.strict_mode())? {
return Err(Error::lex(LexError::Syntax(
"Invalid left-hand side in assignment".into(),
position,
)));
}
return Ok(Unary::new(UnaryOp::IncrementPre, target).into());
@ -91,11 +107,12 @@ where
let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
if cursor.strict_mode() {
if let Expression::Identifier(ident) = target {
check_strict_arguments_or_eval(ident, position)?;
}
// https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors
if !is_simple(&target, position, cursor.strict_mode())? {
return Err(Error::lex(LexError::Syntax(
"Invalid left-hand side in assignment".into(),
position,
)));
}
return Ok(Unary::new(UnaryOp::DecrementPre, target).into());
@ -106,7 +123,6 @@ where
let lhs = LeftHandSideExpression::new(self.name, self.allow_yield, self.allow_await)
.parse(cursor, interner)?;
let strict = cursor.strict_mode();
if let Some(tok) = cursor.peek(0, interner)? {
let token_start = tok.span().start();
match tok.kind() {
@ -115,17 +131,7 @@ where
.next(interner)?
.expect("Punctuator::Inc token disappeared");
// https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors
let ok = match &lhs {
Expression::Identifier(_) if !strict => true,
Expression::Identifier(ident)
if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) =>
{
true
}
Expression::PropertyAccess(_) => true,
_ => false,
};
if !ok {
if !is_simple(&lhs, token_start, cursor.strict_mode())? {
return Err(Error::lex(LexError::Syntax(
"Invalid left-hand side in assignment".into(),
token_start,
@ -139,17 +145,7 @@ where
.next(interner)?
.expect("Punctuator::Dec token disappeared");
// https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors
let ok = match &lhs {
Expression::Identifier(_) if !strict => true,
Expression::Identifier(ident)
if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) =>
{
true
}
Expression::PropertyAccess(_) => true,
_ => false,
};
if !ok {
if !is_simple(&lhs, token_start, cursor.strict_mode())? {
return Err(Error::lex(LexError::Syntax(
"Invalid left-hand side in assignment".into(),
token_start,

Loading…
Cancel
Save