From ef4c65081000c1d0a756d0a72ac7eb40b8807244 Mon Sep 17 00:00:00 2001 From: mido Date: Tue, 27 Sep 2022 07:03:31 -0700 Subject: [PATCH 1/2] Fix if condition if one of the nodes is undefined while the operator is Or and the other the node evaluates to true --- compiler.go | 8 ++++++++ if_test.go | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/compiler.go b/compiler.go index e73293d..8e284ef 100644 --- a/compiler.go +++ b/compiler.go @@ -452,6 +452,9 @@ func (c *compiler) evalInfixExpression(node *ast.InfixExpression) (interface{}, lres, err := c.evalExpression(node.Left) if err != nil { + if _, ok := err.(*ErrUnknownIdentifier); ok { + return false, nil + } return nil, err } if node.Operator == "&&" { @@ -459,6 +462,11 @@ func (c *compiler) evalInfixExpression(node *ast.InfixExpression) (interface{}, return false, nil } } + if node.Operator == "||" { + if c.isTruthy(lres) { + return true, nil + } + } rres, err := c.evalExpression(node.Right) if err != nil { return nil, err diff --git a/if_test.go b/if_test.go index 4def490..8fefdea 100644 --- a/if_test.go +++ b/if_test.go @@ -260,3 +260,18 @@ func Test_Render_If_Variable_Not_Set(t *testing.T) { r.NoError(err) r.Equal("", s) } + +func Test_Render_If_Variable_Not_Set_But_Or_Condition_Is_True(t *testing.T) { + r := require.New(t) + type page struct { + PageTitle string + } + ctx := NewContext() + ctx.Set("path", "cart") + ctx.Set("paths", "cart") + input := `<%= if ( path == "pagePath" || (page && page.PageTitle != "cafe") || paths == "cart") { %>hi<%} %>` + + s, err := Render(input, ctx) + r.NoError(err) + r.Equal("hi", s) +} From 437d207e3a91ee97a0c3d90239427dbf94cd8113 Mon Sep 17 00:00:00 2001 From: mido Date: Tue, 27 Sep 2022 07:31:53 -0700 Subject: [PATCH 2/2] Return error when if condition contains and Or condition and a syntax error --- compiler.go | 18 +++++++++--------- if_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/compiler.go b/compiler.go index 8e284ef..7841ddc 100644 --- a/compiler.go +++ b/compiler.go @@ -453,25 +453,25 @@ func (c *compiler) evalInfixExpression(node *ast.InfixExpression) (interface{}, lres, err := c.evalExpression(node.Left) if err != nil { if _, ok := err.(*ErrUnknownIdentifier); ok { - return false, nil + lres = false + } else { + return nil, err } - return nil, err } if node.Operator == "&&" { if !c.isTruthy(lres) { return false, nil } } - if node.Operator == "||" { - if c.isTruthy(lres) { - return true, nil - } - } + rres, err := c.evalExpression(node.Right) if err != nil { - return nil, err + if _, ok := err.(*ErrUnknownIdentifier); !ok { + return nil, err + } else { + rres = false + } } - switch node.Operator { case "&&", "||": return c.boolsOperator(lres, rres, node.Operator) diff --git a/if_test.go b/if_test.go index 8fefdea..e788146 100644 --- a/if_test.go +++ b/if_test.go @@ -263,13 +263,52 @@ func Test_Render_If_Variable_Not_Set(t *testing.T) { func Test_Render_If_Variable_Not_Set_But_Or_Condition_Is_True(t *testing.T) { r := require.New(t) - type page struct { - PageTitle string - } ctx := NewContext() ctx.Set("path", "cart") ctx.Set("paths", "cart") - input := `<%= if ( path == "pagePath" || (page && page.PageTitle != "cafe") || paths == "cart") { %>hi<%} %>` + input := `<%= if ( paths == "cart" || (page && page.PageTitle != "cafe") || paths == "cart") { %>hi<%} %>` + + s, err := Render(input, ctx) + r.NoError(err) + r.Equal("hi", s) +} + +func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Includes_Syntax_Error_Last_Node(t *testing.T) { + r := require.New(t) + ctx := NewContext() + ctx.Set("paths", "cart") + input := `<%= if ( paths == "cart" || pages ^^^ ) { %>hi<%} %>` + + _, err := Render(input, ctx) + r.Error(err) +} + +func Test_Render_If_Variable_Not_Set_But_Or_Condition_While_Node_Is_True_Includes_Syntax_Error_First_Node(t *testing.T) { + r := require.New(t) + ctx := NewContext() + ctx.Set("paths", "cart") + input := `<%= if ( paths @#@# "cart" || pages) { %>hi<%} %>` + + _, err := Render(input, ctx) + r.Error(err) +} + +func Test_Render_If_Variable_Not_Set_But_Or_Condition_Left_Node_Is_True(t *testing.T) { + r := require.New(t) + ctx := NewContext() + ctx.Set("paths", "cart") + input := `<%= if ( paths == "cart" || pages ) { %>hi<%} %>` + + s, err := Render(input, ctx) + r.NoError(err) + r.Equal("hi", s) +} + +func Test_Render_If_Variable_Not_Set_But_Or_Condition_Right_Node_Is_True(t *testing.T) { + r := require.New(t) + ctx := NewContext() + ctx.Set("pages", "cart") + input := `<%= if ( paths == "cart" || pages ) { %>hi<%} %>` s, err := Render(input, ctx) r.NoError(err)