Skip to content

Commit

Permalink
JS: only parse Left-Hand Side expression for for-in and for-of, fixes…
Browse files Browse the repository at this point in the history
… fuzz test
  • Loading branch information
tdewolff committed Dec 11, 2023
1 parent 69c7837 commit bdeebdd
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 34 deletions.
71 changes: 37 additions & 34 deletions js/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,26 +356,17 @@ func (p *Parser) parseStmt(allowDeclaration bool) (stmt IStmt) {
}
init = varDecl
} else if p.tt != SemicolonToken {
init = p.parseExpression(OpExpr)
init = p.parseExpression(OpLHS)
}
p.in = true

if p.tt == SemicolonToken {
var cond, post IExpr
if p.tt == InToken {
if await {
p.fail("for statement", OfToken)
return
}
p.next()
if p.tt != SemicolonToken {
cond = p.parseExpression(OpExpr)
}
if !p.consume("for statement", SemicolonToken) {
return
}
if p.tt != CloseParenToken {
post = p.parseExpression(OpExpr)
}
value := p.parseExpression(OpExpr)
if !p.consume("for statement", CloseParenToken) {
return
}
Expand All @@ -387,21 +378,13 @@ func (p *Parser) parseStmt(allowDeclaration bool) (stmt IStmt) {
} else {
p.next()
}
if init == nil {
varDecl := &VarDecl{TokenType: VarToken, Scope: p.scope, InFor: true}
p.scope.Func.VarDecls = append(p.scope.Func.VarDecls, varDecl)
init = varDecl
} else if varDecl, ok := init.(*VarDecl); ok {
varDecl.InFor = true
}
stmt = &ForStmt{init, cond, post, body}
} else if p.tt == InToken {
if await {
p.fail("for statement", OfToken)
return
if varDecl, ok := init.(*VarDecl); ok {
varDecl.InForInOf = true
}
stmt = &ForInStmt{init, value, body}
} else if p.tt == OfToken {
p.next()
value := p.parseExpression(OpExpr)
value := p.parseExpression(OpAssign)
if !p.consume("for statement", CloseParenToken) {
return
}
Expand All @@ -416,10 +399,29 @@ func (p *Parser) parseStmt(allowDeclaration bool) (stmt IStmt) {
if varDecl, ok := init.(*VarDecl); ok {
varDecl.InForInOf = true
}
stmt = &ForInStmt{init, value, body}
} else if p.tt == OfToken {
stmt = &ForOfStmt{await, init, value, body}
} else {
init = p.parseExpressionSuffix(init, OpExpr, OpLHS)
if p.tt != SemicolonToken {
p.fail("for statement", InToken, OfToken, SemicolonToken)
return
}

var cond, post IExpr
if await {
p.fail("for statement", OfToken)
return
}
p.next()
value := p.parseExpression(OpAssign)
if p.tt != SemicolonToken {
cond = p.parseExpression(OpExpr)
}
if !p.consume("for statement", SemicolonToken) {
return
}
if p.tt != CloseParenToken {
post = p.parseExpression(OpExpr)
}
if !p.consume("for statement", CloseParenToken) {
return
}
Expand All @@ -431,13 +433,14 @@ func (p *Parser) parseStmt(allowDeclaration bool) (stmt IStmt) {
} else {
p.next()
}
if varDecl, ok := init.(*VarDecl); ok {
varDecl.InForInOf = true
if init == nil {
varDecl := &VarDecl{TokenType: VarToken, Scope: p.scope, InFor: true}
p.scope.Func.VarDecls = append(p.scope.Func.VarDecls, varDecl)
init = varDecl
} else if varDecl, ok := init.(*VarDecl); ok {
varDecl.InFor = true
}
stmt = &ForOfStmt{await, init, value, body}
} else {
p.fail("for statement", InToken, OfToken, SemicolonToken)
return
stmt = &ForStmt{init, cond, post, body}
}
p.exitScope(parent)
case SwitchToken:
Expand Down
1 change: 1 addition & 0 deletions js/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func TestParse(t *testing.T) {
{"for (a in b) {}", "Stmt(for a in b Stmt({ }))"},
{"for (a = b;;) {}", "Stmt(for (a=b) ; ; Stmt({ }))"},
{"for (var [a] in b) {}", "Stmt(for Decl(var Binding([ Binding(a) ])) in b Stmt({ }))"},
{"for(async of b);", "Stmt(for async of b Stmt({ }))"},
{"throw 5", "Stmt(throw 5)"},
{"try {} catch {b}", "Stmt(try Stmt({ }) catch Stmt({ Stmt(b) }))"},
{"try {} finally {c}", "Stmt(try Stmt({ }) finally Stmt({ Stmt(c) }))"},
Expand Down

0 comments on commit bdeebdd

Please sign in to comment.