Fix panic in property access parsing error.

This commit is contained in:
Stephen Chung 2021-01-31 18:44:50 +08:00
parent 7fc38d4cd2
commit 42058836ba
2 changed files with 30 additions and 20 deletions

View File

@ -15,6 +15,7 @@ Bug fixes
* Fixes compilation errors in `metadata` feature build. * Fixes compilation errors in `metadata` feature build.
* Stacking `!` operators now work properly. * Stacking `!` operators now work properly.
* Off-by-one error in `insert` method for arrays is fixed. * Off-by-one error in `insert` method for arrays is fixed.
* Invalid property access now throws the appropriate error instead of panics.
Breaking changes Breaking changes
---------------- ----------------

View File

@ -1083,9 +1083,7 @@ fn parse_primary(
match input.peek().unwrap().0 { match input.peek().unwrap().0 {
// Function call is allowed to have reserved keyword // Function call is allowed to have reserved keyword
Token::LeftParen | Token::Bang => { Token::LeftParen | Token::Bang => {
if s == KEYWORD_THIS { if is_keyword_function(&s) {
return Err(PERR::Reserved(s).into_err(settings.pos));
} else if is_keyword_function(&s) {
let var_name_def = Ident { let var_name_def = Ident {
name: state.get_interned_string(s), name: state.get_interned_string(s),
pos: settings.pos, pos: settings.pos,
@ -1213,13 +1211,21 @@ fn parse_primary(
// Property access // Property access
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
(expr, Token::Period) => { (expr, Token::Period) => {
// prevents capturing of the object properties as vars: xxx.<var> // Expression after dot must start with an identifier
match input.peek().unwrap() {
(Token::Identifier(_), _) => {
#[cfg(not(feature = "no_closure"))] #[cfg(not(feature = "no_closure"))]
if let (Token::Identifier(_), _) = input.peek().unwrap() { {
// Prevents capturing of the object properties as vars: xxx.<var>
state.allow_capture = false; state.allow_capture = false;
} }
}
(Token::Reserved(s), _) if is_keyword_function(s) => (),
(_, pos) => return Err(PERR::PropertyExpected.into_err(*pos)),
}
let rhs = parse_primary(input, state, lib, settings.level_up())?; let rhs = parse_primary(input, state, lib, settings.level_up())?;
make_dot_expr(state, expr, rhs, tail_pos)? make_dot_expr(state, expr, rhs, tail_pos)?
} }
// Unknown postfix operator // Unknown postfix operator
@ -1514,14 +1520,15 @@ fn make_dot_expr(
} }
// lhs.module::id - syntax error // lhs.module::id - syntax error
(_, Expr::Variable(x)) if x.1.is_some() => { (_, Expr::Variable(x)) if x.1.is_some() => {
return Err(PERR::PropertyExpected.into_err(x.1.unwrap().1[0].pos)); return Err(PERR::PropertyExpected.into_err(x.1.unwrap().1[0].pos))
} }
// lhs.prop // lhs.prop
(lhs, prop @ Expr::Property(_)) => { (lhs, prop @ Expr::Property(_)) => {
Expr::Dot(Box::new(BinaryExpr { lhs, rhs: prop }), op_pos) Expr::Dot(Box::new(BinaryExpr { lhs, rhs: prop }), op_pos)
} }
// lhs.dot_lhs.dot_rhs // lhs.dot_lhs.dot_rhs
(lhs, Expr::Dot(x, pos)) => { (lhs, Expr::Dot(x, pos)) => match x.lhs {
Expr::Variable(_) | Expr::Property(_) | Expr::FnCall(_, _) => {
let rhs = Expr::Dot( let rhs = Expr::Dot(
Box::new(BinaryExpr { Box::new(BinaryExpr {
lhs: x.lhs.into_property(state), lhs: x.lhs.into_property(state),
@ -1531,6 +1538,8 @@ fn make_dot_expr(
); );
Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos) Expr::Dot(Box::new(BinaryExpr { lhs, rhs }), op_pos)
} }
_ => unreachable!("invalid dot expression: {:?}", x.lhs),
},
// lhs.idx_lhs[idx_rhs] // lhs.idx_lhs[idx_rhs]
(lhs, Expr::Index(x, pos)) => { (lhs, Expr::Index(x, pos)) => {
let rhs = Expr::Index( let rhs = Expr::Index(
@ -1555,14 +1564,14 @@ fn make_dot_expr(
x.name, x.name x.name, x.name
), ),
) )
.into_err(pos)); .into_err(pos))
} }
// lhs.func!(...) // lhs.func!(...)
(_, Expr::FnCall(x, pos)) if x.capture => { (_, Expr::FnCall(x, pos)) if x.capture => {
return Err(PERR::MalformedCapture( return Err(PERR::MalformedCapture(
"method-call style does not support capturing".into(), "method-call style does not support capturing".into(),
) )
.into_err(pos)); .into_err(pos))
} }
// lhs.func(...) // lhs.func(...)
(lhs, func @ Expr::FnCall(_, _)) => { (lhs, func @ Expr::FnCall(_, _)) => {