(list []js.IStmt, blockType blockType)
| 168 | } |
| 169 | |
| 170 | func optimizeStmtList(list []js.IStmt, blockType blockType) []js.IStmt { |
| 171 | // merge expression statements as well as if/else statements followed by flow control statements |
| 172 | if len(list) == 0 { |
| 173 | return list |
| 174 | } |
| 175 | j := 0 // write index |
| 176 | for i := 0; i < len(list); i++ { // read index |
| 177 | if ifStmt, ok := list[i].(*js.IfStmt); ok && !isEmptyStmt(ifStmt.Else) { |
| 178 | // if(a)return b;else c => if(a)b; c |
| 179 | if unary, ok := ifStmt.Cond.(*js.UnaryExpr); ok && unary.Op == js.NotToken && isFlowStmt(lastStmt(ifStmt.Else)) { |
| 180 | ifStmt.Cond = unary.X |
| 181 | ifStmt.Body, ifStmt.Else = ifStmt.Else, ifStmt.Body |
| 182 | } |
| 183 | if isFlowStmt(lastStmt(ifStmt.Body)) { |
| 184 | // if body ends in flow statement (return, throw, break, continue), we can remove the else statement and put its body in the current scope |
| 185 | if blockStmt, ok := ifStmt.Else.(*js.BlockStmt); ok { |
| 186 | blockStmt.Scope.Unscope() |
| 187 | list = append(list[:i+1], append(blockStmt.List, list[i+1:]...)...) |
| 188 | } else { |
| 189 | list = append(list[:i+1], append([]js.IStmt{ifStmt.Else}, list[i+1:]...)...) |
| 190 | } |
| 191 | ifStmt.Else = nil |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | list[i] = optimizeStmt(list[i]) |
| 196 | |
| 197 | if _, ok := list[i].(*js.EmptyStmt); ok { |
| 198 | k := i + 1 |
| 199 | for ; k < len(list); k++ { |
| 200 | if _, ok := list[k].(*js.EmptyStmt); !ok { |
| 201 | break |
| 202 | } |
| 203 | } |
| 204 | list = append(list[:i], list[k:]...) |
| 205 | i-- |
| 206 | continue |
| 207 | } |
| 208 | |
| 209 | if 0 < i { |
| 210 | // merge expression statements with expression, return, and throw statements |
| 211 | if left, ok := list[i-1].(*js.ExprStmt); ok { |
| 212 | if right, ok := list[i].(*js.ExprStmt); ok { |
| 213 | right.Value = commaExpr(left.Value, right.Value) |
| 214 | j-- |
| 215 | } else if returnStmt, ok := list[i].(*js.ReturnStmt); ok && returnStmt.Value != nil { |
| 216 | returnStmt.Value = commaExpr(left.Value, returnStmt.Value) |
| 217 | j-- |
| 218 | } else if throwStmt, ok := list[i].(*js.ThrowStmt); ok { |
| 219 | throwStmt.Value = commaExpr(left.Value, throwStmt.Value) |
| 220 | j-- |
| 221 | } else if forStmt, ok := list[i].(*js.ForStmt); ok { |
| 222 | // TODO: only merge lhs expression that don't have 'in' or 'of' keywords (slow to check?) |
| 223 | if forStmt.Init == nil { |
| 224 | forStmt.Init = left.Value |
| 225 | j-- |
| 226 | } else if decl, ok := forStmt.Init.(*js.VarDecl); ok && len(decl.List) == 0 { |
| 227 | forStmt.Init = left.Value |
no test coverage detected
searching dependent graphs…