Skip to content

Commit 6076220

Browse files
committed
JS: merge more cases of var decl and for stmt
1 parent 99ec6e6 commit 6076220

File tree

3 files changed

+36
-22
lines changed

3 files changed

+36
-22
lines changed

js/js_test.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ func TestJS(t *testing.T) {
275275
{`var a;var b=6;a=7`, `var b=6,a=7`}, // swap declaration order to maintain definition order
276276
{`var a=5;var b=6;a=7`, `var a=5,b=6;a=7`},
277277
{`var a;var b=6;z=7`, `var b=6,a;z=7`},
278-
//{`for(var a=6,b=7;;);var c=8`, `for(var a=6,b=7,c=8;;);`},
279-
//{`while(b);var a=4;var b=5;`, `for(var a=4,b=5;b;);`},
280-
//{`for(var c;b;){let a=8};var a`, `for(var c,a;b;)let a=8`},
278+
{`for(var a=6,b=7;;);var c=8`, `for(var a=6,b=7,c=8;;);`},
279+
{`for(var c;b;){let a=8};var a`, `for(var c,a;b;)let a=8`},
280+
{`for(;b;){let a=8};var a;var b`, `for(var a,b;b;)let a=8`},
281281

282282
// function and method declarations
283283
{`function g(){return}`, `function g(){}`},
@@ -536,7 +536,11 @@ func TestJS(t *testing.T) {
536536
{`a={b(c){d}}`, `a={b(c){d}}`},
537537
{`a(b,...c)`, `a(b,...c)`},
538538
//{`'a b c'.split(' ')`, `['a','b','c']`}, // TODO?
539-
//{`!function(){var a}`, `!function(){}`}, // TODO? remove unused variables
539+
//{`!function(){var a}`, `!function(){}`}, // TODO: remove unused variables
540+
//{`const a=6;f(a)`, `f(6)`}, // TODO: inline single-use variables that are literals
541+
//{`let a="string";f(a)`, `f("string")`}, // TODO: inline single-use variables that are literals
542+
{`let a="string"`, `let a="string"`},
543+
//{`{let a="string"}`, ``}, // TODO: remove unused variables that are not in global scope
540544

541545
// merge expressions
542546
{`b=5;return a+b`, `return b=5,a+b`},
@@ -555,6 +559,7 @@ func TestJS(t *testing.T) {
555559
{`var a=b in c;for(;b;)c()`, `for(var a=(b in c);b;)c()`},
556560
{`var a=5;while(b)c()`, `for(var a=5;b;)c()`},
557561
{`let a=5;while(b)c()`, `let a=5;while(b)c()`},
562+
//{`var a;for(a=5;b;)c()`, `for(var a=5;b;)c()`}, // TODO
558563
{`a=5;for(var b=4;b;)c()`, `a=5;for(var b=4;b;)c()`},
559564
{`a=5;switch(b=4){}`, `switch(a=5,b=4){}`},
560565
{`a=5;with(b=4){}`, `with(a=5,b=4);`},

js/stmtlist.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,18 @@ func (m *jsMinifier) optimizeStmtList(list []js.IStmt, blockType blockType) []js
146146
j--
147147
}
148148
} else if left, ok := list[i-1].(*js.VarDecl); ok {
149-
if right, ok := list[i].(*js.VarDecl); ok && left.TokenType != js.VarToken && left.TokenType == right.TokenType {
150-
// merge const, let declarations
149+
if right, ok := list[i].(*js.VarDecl); ok && left.TokenType == right.TokenType {
150+
// merge const and let declarations
151151
right.List = append(left.List, right.List...)
152152
j--
153-
} else if forStmt, ok := list[i].(*js.ForStmt); ok && left.TokenType == js.VarToken && forStmt.Init == nil {
153+
} else if forStmt, ok := list[i].(*js.ForStmt); ok && left.TokenType == js.VarToken {
154154
// TODO: only merge statements that don't have 'in' or 'of' keywords (slow to check?)
155-
forStmt.Init = left
156-
j--
155+
if forStmt.Init == nil {
156+
forStmt.Init = left
157+
j--
158+
} else {
159+
// TODO: merge with expressions if they define the declarations
160+
}
157161
} else if whileStmt, ok := list[i].(*js.WhileStmt); ok && left.TokenType == js.VarToken {
158162
// TODO: only merge statements that don't have 'in' or 'of' keywords (slow to check?)
159163
var body js.BlockStmt

js/vars.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,19 +146,24 @@ func (m *jsMinifier) hoistVars(body *js.BlockStmt) *js.VarDecl {
146146
var decl *js.VarDecl
147147
if varDecl, ok := body.List[0].(*js.VarDecl); ok && varDecl.TokenType == js.VarToken {
148148
decl = varDecl
149-
//} else if forStmt, ok := body.List[0].(*js.ForStmt); ok && forStmt.Init != nil {
150-
// if varDecl, ok := forStmt.Init.(*js.VarDecl); ok && varDecl.TokenType == js.VarToken {
151-
// decl = varDecl
152-
// }
153-
//} else if whileStmt, ok := body.List[0].(*js.WhileStmt); ok {
154-
// decl = &js.VarDecl{js.VarToken, nil}
155-
// var forBody js.BlockStmt
156-
// if blockStmt, ok := whileStmt.Body.(*js.BlockStmt); ok {
157-
// forBody = *blockStmt
158-
// } else {
159-
// forBody.List = []js.IStmt{whileStmt.Body}
160-
// }
161-
// body.List[0] = &js.ForStmt{decl, whileStmt.Cond, nil, forBody}
149+
} else if forStmt, ok := body.List[0].(*js.ForStmt); ok {
150+
// TODO: only merge statements that don't have 'in' or 'of' keywords (slow to check?)
151+
if forStmt.Init == nil {
152+
decl = &js.VarDecl{js.VarToken, nil}
153+
forStmt.Init = decl
154+
} else if varDecl, ok := forStmt.Init.(*js.VarDecl); ok && varDecl.TokenType == js.VarToken {
155+
decl = varDecl
156+
}
157+
} else if whileStmt, ok := body.List[0].(*js.WhileStmt); ok {
158+
// TODO: only merge statements that don't have 'in' or 'of' keywords (slow to check?)
159+
decl = &js.VarDecl{js.VarToken, nil}
160+
var forBody js.BlockStmt
161+
if blockStmt, ok := whileStmt.Body.(*js.BlockStmt); ok {
162+
forBody = *blockStmt
163+
} else {
164+
forBody.List = []js.IStmt{whileStmt.Body}
165+
}
166+
body.List[0] = &js.ForStmt{decl, whileStmt.Cond, nil, forBody}
162167
}
163168
if decl != nil {
164169
// original declarations

0 commit comments

Comments
 (0)