From 1bfc1584863fbabb77a3338553941c90a1a8196d Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 13:31:09 -0500 Subject: [PATCH 01/10] Fix unary operations on `this` --- boa_parser/src/parser/expression/update.rs | 45 +++++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 52fe12ba960..1fd3a487357 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -72,11 +72,28 @@ where cursor .next(interner)? .expect("Punctuator::Inc token disappeared"); - + let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - - if cursor.strict_mode() { + let strict = cursor.strict_mode(); + // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors + let ok = match &target { + Expression::Identifier(_) if !strict => true, + Expression::Identifier(ident) + if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => + { + true + } + Expression::PropertyAccess(_) => true, + _ => false, + }; + if !ok { + return Err(Error::lex(LexError::Syntax( + "Invalid left-hand side in assignment".into(), + position, + ))); + } + if strict { if let Expression::Identifier(ident) = target { check_strict_arguments_or_eval(ident, position)?; } @@ -91,8 +108,26 @@ where let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - - if cursor.strict_mode() { + let strict = cursor.strict_mode(); + // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors + let ok = match &target { + Expression::Identifier(_) if !strict => true, + Expression::Identifier(ident) + if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => + { + true + } + Expression::PropertyAccess(_) => true, + _ => false, + }; + + if !ok { + return Err(Error::lex(LexError::Syntax( + "Invalid left-hand side in assignment".into(), + position, + ))); + } + if strict { if let Expression::Identifier(ident) = target { check_strict_arguments_or_eval(ident, position)?; } From 715db2d188075216b5e362ea1d33bd9d48d3d040 Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 13:58:03 -0500 Subject: [PATCH 02/10] Replace variable name `ok` with `simple` --- boa_parser/src/parser/expression/update.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 1fd3a487357..e560b07344d 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -77,7 +77,7 @@ where .parse(cursor, interner)?; let strict = cursor.strict_mode(); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let ok = match &target { + let simple = match &target { Expression::Identifier(_) if !strict => true, Expression::Identifier(ident) if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => @@ -87,7 +87,7 @@ where Expression::PropertyAccess(_) => true, _ => false, }; - if !ok { + if !simple { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), position, @@ -110,7 +110,7 @@ where .parse(cursor, interner)?; let strict = cursor.strict_mode(); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let ok = match &target { + let simple = match &target { Expression::Identifier(_) if !strict => true, Expression::Identifier(ident) if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => @@ -121,7 +121,7 @@ where _ => false, }; - if !ok { + if !simple { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), position, @@ -150,7 +150,7 @@ where .next(interner)? .expect("Punctuator::Inc token disappeared"); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let ok = match &lhs { + let simple = match &lhs { Expression::Identifier(_) if !strict => true, Expression::Identifier(ident) if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => @@ -160,7 +160,7 @@ where Expression::PropertyAccess(_) => true, _ => false, }; - if !ok { + if !simple { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), token_start, @@ -174,7 +174,7 @@ where .next(interner)? .expect("Punctuator::Dec token disappeared"); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let ok = match &lhs { + let simple = match &lhs { Expression::Identifier(_) if !strict => true, Expression::Identifier(ident) if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => @@ -184,7 +184,7 @@ where Expression::PropertyAccess(_) => true, _ => false, }; - if !ok { + if !simple { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), token_start, From 5b1be0846f82f32be47cc9f0b88423ce5783192a Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 14:18:24 -0500 Subject: [PATCH 03/10] Skip rechecking eval/arguments --- boa_parser/src/parser/expression/update.rs | 33 +++++++--------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index e560b07344d..2b488ddd3bc 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -23,7 +23,7 @@ use boa_ast::{ }, Expression, Punctuator, }; -use boa_interner::{Interner, Sym}; +use boa_interner::Interner; use boa_profiler::Profiler; use std::io::Read; @@ -79,25 +79,20 @@ where // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors let simple = match &target { Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) - if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => - { + Expression::Identifier(ident) => { + check_strict_arguments_or_eval(*ident, position)?; true } Expression::PropertyAccess(_) => true, _ => false, }; + if !simple { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), position, ))); } - if strict { - if let Expression::Identifier(ident) = target { - check_strict_arguments_or_eval(ident, position)?; - } - } return Ok(Unary::new(UnaryOp::IncrementPre, target).into()); } @@ -112,9 +107,8 @@ where // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors let simple = match &target { Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) - if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => - { + Expression::Identifier(ident) => { + check_strict_arguments_or_eval(*ident, position)?; true } Expression::PropertyAccess(_) => true, @@ -127,11 +121,6 @@ where position, ))); } - if strict { - if let Expression::Identifier(ident) = target { - check_strict_arguments_or_eval(ident, position)?; - } - } return Ok(Unary::new(UnaryOp::DecrementPre, target).into()); } @@ -152,9 +141,8 @@ where // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors let simple = match &lhs { Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) - if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => - { + Expression::Identifier(ident) => { + check_strict_arguments_or_eval(*ident, token_start)?; true } Expression::PropertyAccess(_) => true, @@ -176,9 +164,8 @@ where // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors let simple = match &lhs { Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) - if ![Sym::EVAL, Sym::ARGUMENTS].contains(&ident.sym()) => - { + Expression::Identifier(ident) => { + check_strict_arguments_or_eval(*ident, token_start)?; true } Expression::PropertyAccess(_) => true, From 584f851d8acc07dffee9f3846eff1c042bcb75a5 Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 20:15:50 -0500 Subject: [PATCH 04/10] Remove redundant check for strict code --- boa_parser/src/parser/expression/update.rs | 68 +++++++--------------- 1 file changed, 21 insertions(+), 47 deletions(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 2b488ddd3bc..4d29113d55d 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -21,7 +21,7 @@ use boa_ast::{ operator::{unary::UnaryOp, Unary}, Identifier, }, - Expression, Punctuator, + Expression, Position, Punctuator, }; use boa_interner::Interner; use boa_profiler::Profiler; @@ -56,6 +56,21 @@ impl UpdateExpression { } } +#[inline] +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), + } +} + +// 74.54 impl TokenParser for UpdateExpression where R: Read, @@ -72,22 +87,11 @@ where cursor .next(interner)? .expect("Punctuator::Inc token disappeared"); - + let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - let strict = cursor.strict_mode(); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let simple = match &target { - Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) => { - check_strict_arguments_or_eval(*ident, position)?; - true - } - Expression::PropertyAccess(_) => true, - _ => false, - }; - - if !simple { + if !is_simple(&target, position, cursor.strict_mode())? { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), position, @@ -103,19 +107,8 @@ where let target = UnaryExpression::new(self.name, self.allow_yield, self.allow_await) .parse(cursor, interner)?; - let strict = cursor.strict_mode(); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let simple = match &target { - Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) => { - check_strict_arguments_or_eval(*ident, position)?; - true - } - Expression::PropertyAccess(_) => true, - _ => false, - }; - - if !simple { + if !is_simple(&target, position, cursor.strict_mode())? { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), position, @@ -130,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() { @@ -139,16 +131,7 @@ where .next(interner)? .expect("Punctuator::Inc token disappeared"); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let simple = match &lhs { - Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) => { - check_strict_arguments_or_eval(*ident, token_start)?; - true - } - Expression::PropertyAccess(_) => true, - _ => false, - }; - if !simple { + if !is_simple(&lhs, token_start, cursor.strict_mode())? { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), token_start, @@ -162,16 +145,7 @@ where .next(interner)? .expect("Punctuator::Dec token disappeared"); // https://tc39.es/ecma262/#sec-update-expressions-static-semantics-early-errors - let simple = match &lhs { - Expression::Identifier(_) if !strict => true, - Expression::Identifier(ident) => { - check_strict_arguments_or_eval(*ident, token_start)?; - true - } - Expression::PropertyAccess(_) => true, - _ => false, - }; - if !simple { + if !is_simple(&lhs, token_start, cursor.strict_mode())? { return Err(Error::lex(LexError::Syntax( "Invalid left-hand side in assignment".into(), token_start, From c2ff22945422efaa650a373b997b6831030234d2 Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 20:48:15 -0500 Subject: [PATCH 05/10] Remove inline annotation --- boa_parser/src/parser/expression/update.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 4d29113d55d..a428c9027b6 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -56,7 +56,6 @@ impl UpdateExpression { } } -#[inline] fn is_simple(expr: &Expression, position: Position, strict: bool) -> ParseResult { match expr { Expression::Identifier(ident) => { From 0eabc69fe2f4fee4ee8aa4aff709de89bface4f5 Mon Sep 17 00:00:00 2001 From: Veera Date: Mon, 26 Dec 2022 20:50:13 -0500 Subject: [PATCH 06/10] Cleanup --- boa_parser/src/parser/expression/update.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index a428c9027b6..12f285a3b0c 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -69,7 +69,6 @@ fn is_simple(expr: &Expression, position: Position, strict: bool) -> ParseResult } } -// 74.54 impl TokenParser for UpdateExpression where R: Read, From 5295c884ebf0a76d4c7e99e1d591e59862d463e3 Mon Sep 17 00:00:00 2001 From: Veera Date: Tue, 27 Dec 2022 11:58:35 -0500 Subject: [PATCH 07/10] Add a test --- boa_engine/src/tests.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/boa_engine/src/tests.rs b/boa_engine/src/tests.rs index 2c43e54240f..c09963ed7d3 100644 --- a/boa_engine/src/tests.rs +++ b/boa_engine/src/tests.rs @@ -2836,3 +2836,15 @@ 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)); + } +} From 52b96d2ee03bbcadd3cbca790705d4fda3de4947 Mon Sep 17 00:00:00 2001 From: Veera Date: Tue, 27 Dec 2022 18:00:19 -0500 Subject: [PATCH 08/10] Run `cargo fmt` --- boa_engine/src/tests.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/boa_engine/src/tests.rs b/boa_engine/src/tests.rs index c09963ed7d3..f27f7323041 100644 --- a/boa_engine/src/tests.rs +++ b/boa_engine/src/tests.rs @@ -2841,7 +2841,12 @@ fn spread_with_call() { 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")]; + 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: ")); From 60d7f00c117c9bbca3e1f4abc5c7bbce4ab60a5e Mon Sep 17 00:00:00 2001 From: Veera Date: Wed, 28 Dec 2022 11:27:33 -0500 Subject: [PATCH 09/10] Add link to spec explaining "simple" target type --- boa_parser/src/parser/expression/update.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index 12f285a3b0c..e8bce191359 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -56,6 +56,7 @@ impl UpdateExpression { } } +// https://tc39.es/ecma262/multipage/syntax-directed-operations.html#sec-static-semantics-assignmenttargettype fn is_simple(expr: &Expression, position: Position, strict: bool) -> ParseResult { match expr { Expression::Identifier(ident) => { From e0d9d9bd674c873d456fae0432b5b72fb53173b9 Mon Sep 17 00:00:00 2001 From: Veera Date: Wed, 28 Dec 2022 23:16:29 -0500 Subject: [PATCH 10/10] Format link to spec --- boa_parser/src/parser/expression/update.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/boa_parser/src/parser/expression/update.rs b/boa_parser/src/parser/expression/update.rs index e8bce191359..9f196fac3f1 100644 --- a/boa_parser/src/parser/expression/update.rs +++ b/boa_parser/src/parser/expression/update.rs @@ -56,7 +56,8 @@ 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 { match expr { Expression::Identifier(ident) => {