Skip to content

Commit

Permalink
Fixed compilation of falsy 'while' loops. Fixes #220.
Browse files Browse the repository at this point in the history
  • Loading branch information
dop251 committed Oct 21, 2020
1 parent bf18fe8 commit bf9dcfb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 30 deletions.
27 changes: 27 additions & 0 deletions compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,3 +462,30 @@ func (c *compiler) checkIdentifierLName(name unistring.String, offset int) {
c.throwSyntaxError(offset, "Assignment to eval or arguments is not allowed in strict mode")
}
}

// Enter a 'dummy' compilation mode. Any code produced after this method is called will be discarded after
// leaveFunc is called with no additional side effects. This is useful for compiling code inside a
// constant falsy condition 'if' branch or a loop (i.e 'if (false) { ... } or while (false) { ... }).
// Such code should not be included in the final compilation result as it's never called, but it must
// still produce compilation errors if there are any.
func (c *compiler) enterDummyMode() (leaveFunc func()) {
savedBlock, savedBlockStart, savedProgram := c.block, c.blockStart, c.p
if savedBlock != nil {
c.block = &block{
typ: savedBlock.typ,
label: savedBlock.label,
}
}
c.p = &Program{}
c.newScope()
return func() {
c.block, c.blockStart, c.p = savedBlock, savedBlockStart, savedProgram
c.popScope()
}
}

func (c *compiler) compileStatementDummy(statement ast.Statement) {
leave := c.enterDummyMode()
c.compileStatement(statement, false)
leave()
}
26 changes: 8 additions & 18 deletions compiler_stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,12 @@ func (c *compiler) compileLabeledForStatement(v *ast.ForStatement, needResult bo
if r.ToBoolean() {
testConst = true
} else {
// TODO: Properly implement dummy compilation (no garbage in block, scope, etc..)
/*
p := c.p
c.p = &program{}
c.compileStatement(v.Body, false)
if v.Update != nil {
c.compileExpression(v.Update).emitGetter(false)
}
c.p = p*/
leave := c.enterDummyMode()
c.compileStatement(v.Body, false)
if v.Update != nil {
c.compileExpression(v.Update).emitGetter(false)
}
leave()
goto end
}
} else {
Expand Down Expand Up @@ -398,10 +395,7 @@ func (c *compiler) compileLabeledWhileStatement(v *ast.WhileStatement, needResul
if t.ToBoolean() {
testTrue = true
} else {
p := c.p
c.p = &Program{}
c.compileStatement(v.Body, false)
c.p = p
c.compileStatementDummy(v.Body)
goto end
}
} else {
Expand Down Expand Up @@ -605,11 +599,7 @@ func (c *compiler) compileIfStatement(v *ast.IfStatement, needResult bool) {
c.p = p
}
} else {
// TODO: Properly implement dummy compilation (no garbage in block, scope, etc..)
p := c.p
c.p = &Program{}
c.compileStatement(v.Consequent, false)
c.p = p
c.compileStatementDummy(v.Consequent)
if v.Alternate != nil {
c.compileStatement(v.Alternate, needResult)
} else {
Expand Down
55 changes: 43 additions & 12 deletions compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2097,25 +2097,56 @@ func TestTryEmptyCatchStackLeak(t *testing.T) {
testScript1(SCRIPT, _undefined, t)
}

// FIXME
/*
func TestFalsyLoopBreak(t *testing.T) {
const SCRIPT = `
while(false) {
break;
}
for(;false;) {
break;
}
undefined;
`
MustCompile("", SCRIPT, false)
}

func TestFalsyLoopBreakWithResult(t *testing.T) {
const SCRIPT = `
while(false) {
break;
}
`
testScript1(SCRIPT, _undefined, t)
}

func TestDummyCompile(t *testing.T) {
const SCRIPT = `
'use strict';
'use strict';
for (;false;) {
eval = 1;
}
`

for (;false;) {
eval = 1;
_, err := Compile("", SCRIPT, false)
if err == nil {
t.Fatal("expected error")
}
}

func TestDummyCompileForUpdate(t *testing.T) {
const SCRIPT = `
'use strict';
for (;false;eval=1) {
}
`
defer func() {
if recover() == nil {
t.Fatal("Expected panic")
}
}()

testScript1(SCRIPT, _undefined, t)
}*/
_, err := Compile("", SCRIPT, false)
if err == nil {
t.Fatal("expected error")
}
}

func BenchmarkCompile(b *testing.B) {
f, err := os.Open("testdata/S15.10.2.12_A1_T1.js")
Expand Down

0 comments on commit bf9dcfb

Please sign in to comment.