Skip to content

Commit

Permalink
fix(ast): walk missing nodes (#471)
Browse files Browse the repository at this point in the history
Fix ast.Walk missing out:
* DotExpressions.Identifier
* LabelledStatement.Label

Fixes #299
  • Loading branch information
stevenh authored Nov 29, 2022
1 parent 8d121dc commit 93fb47c
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
2 changes: 2 additions & 0 deletions ast/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func Walk(v Visitor, n Node) {
case *DotExpression:
if n != nil {
Walk(v, n.Left)
Walk(v, n.Identifier)
}
case *EmptyExpression:
case *EmptyStatement:
Expand Down Expand Up @@ -134,6 +135,7 @@ func Walk(v Visitor, n Node) {
}
case *LabelledStatement:
if n != nil {
Walk(v, n.Label)
Walk(v, n.Statement)
}
case *NewExpression:
Expand Down
57 changes: 35 additions & 22 deletions ast/walk_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package ast_test

import (
"log"
"testing"

"github.com/robertkrimen/otto/ast"
"github.com/robertkrimen/otto/file"
"github.com/robertkrimen/otto/parser"
"github.com/stretchr/testify/require"
)

type walker struct {
stack []ast.Node
source string
shift file.Idx
stack []ast.Node
source string
shift file.Idx
seen map[ast.Node]struct{}
duplicate int
}

// push and pop below are to prove the symmetry of Enter/Exit calls
Expand All @@ -38,18 +40,25 @@ func (w *walker) pop(n ast.Node) {

func (w *walker) Enter(n ast.Node) ast.Visitor {
w.push(n)
if _, ok := w.seen[n]; ok {
// Skip items we've already seen which occurs due to declarations.
w.duplicate++
return w
}

w.seen[n] = struct{}{}

if id, ok := n.(*ast.Identifier); ok && id != nil {
idx := n.Idx0() + w.shift - 1
s := w.source[:idx] + "new_" + w.source[idx:]
s := w.source[:idx] + "IDENT_" + w.source[idx:]
w.source = s
w.shift += 4
w.shift += 6
}
if v, ok := n.(*ast.VariableExpression); ok && v != nil {
idx := n.Idx0() + w.shift - 1
s := w.source[:idx] + "varnew_" + w.source[idx:]
s := w.source[:idx] + "VAR_" + w.source[idx:]
w.source = s
w.shift += 7
w.shift += 4
}

return w
Expand All @@ -60,23 +69,27 @@ func (w *walker) Exit(n ast.Node) {
}

func TestVisitorRewrite(t *testing.T) {
source := `var b = function() {test(); try {} catch(e) {} var test = "test(); var test = 1"} // test`
source := `var b = function() {
test();
try {} catch(e) {}
var test = "test(); var test = 1"
} // test`
program, err := parser.ParseFile(nil, "", source, 0)
if err != nil {
log.Fatal(err)
}

w := &walker{source: source}
require.NoError(t, err)

w := &walker{
source: source,
seen: make(map[ast.Node]struct{}),
}
ast.Walk(w, program)

xformed := `var varnew_b = function() {new_test(); try {} catch(new_e) {} var varnew_test = "test(); var test = 1"} // test`
xformed := `var VAR_b = function() {
IDENT_test();
try {} catch(IDENT_e) {}
var VAR_test = "test(); var test = 1"
} // test`

if w.source != xformed {
t.Errorf("source is `%s` not `%s`", w.source, xformed)
}

if len(w.stack) != 0 {
t.Errorf("stack should be empty, but is length: %d", len(w.stack))
}
require.Equal(t, xformed, w.source)
require.Len(t, w.stack, 0)
require.Equal(t, w.duplicate, 0)
}

0 comments on commit 93fb47c

Please sign in to comment.