diff --git a/boa_engine/src/tests.rs b/boa_engine/src/tests.rs index 2c43e54240f..f27f7323041 100644 --- a/boa_engine/src/tests.rs +++ b/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)); + } +} diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 52fe12ba960..9f196fac3f1 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/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 { } } +/// +/// This function checks if the target type is simple +fn is_simple(expr: &Expression, position: Position, strict: bool) -> ParseResult { + match expr { + Expression::Identifier(ident) => { + if strict { + check_strict_arguments_or_eval(*ident, position)?; + } + Ok(true) + } + Expression::PropertyAccess(_) => Ok(true), + _ => Ok(false), + } +} + impl TokenParser 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,