• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Siubaak / sval / 14771539826

01 May 2025 07:10AM UTC coverage: 73.748% (+8.3%) from 65.487%
14771539826

push

github

Siubaak
[update] rollup -> vite

753 of 922 branches covered (81.67%)

Branch coverage included in aggregate %.

60 of 60 new or added lines in 12 files covered. (100.0%)

358 existing lines in 15 files now uncovered.

2545 of 3550 relevant lines covered (71.69%)

932.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.57
/src/evaluate/statement.ts
1
import { BREAK, CONTINUE, RETURN, AWAIT } from '../share/const.ts'
1✔
2
import { hoist, pattern, ForXHandler } from './helper.ts'
1✔
3
import { getAsyncIterator } from '../share/util.ts'
1✔
4
import Scope from '../scope/index.ts'
1✔
5
import evaluate from './index.ts'
1✔
6
import * as acorn from 'acorn'
7

8
export function* ExpressionStatement(node: acorn.ExpressionStatement, scope: Scope) {
1✔
9
  yield* evaluate(node.expression, scope)
193✔
10
}
190✔
11

12
export interface LabelOptions {
13
  label?: string
14
}
15

16
export interface BlockOptions {
17
  invasived?: boolean
18
  hoisted?: boolean
19
}
20

21
export function* BlockStatement(
1✔
22
  block: acorn.BlockStatement | acorn.StaticBlock,
92✔
23
  scope: Scope,
92✔
24
  options: BlockOptions & LabelOptions = {},
92✔
25
) {
92✔
26
  const {
92✔
27
    invasived = false,
92✔
28
    hoisted = false,
92✔
29
  } = options
92✔
30

31
  const subScope = invasived ? scope : new Scope(scope)
92✔
32

33
  if (!hoisted) {
92✔
34
    yield* hoist(block, subScope, { onlyBlock: true })
63✔
35
  }
63✔
36

37
  for (let i = 0; i < block.body.length; i++) {
92✔
38
    const result = yield* evaluate(block.body[i], subScope)
263✔
39
    if (result === BREAK) {
263!
40
      if (result.LABEL && result.LABEL === options.label) {
×
41
        // only labeled break to current block statement doesn't bubble up the result
42
        break
×
UNCOV
43
      }
×
44
      return result
×
UNCOV
45
    }
✔
46
    if (result === CONTINUE || result === RETURN) {
263✔
47
      return result
1✔
48
    }
1✔
49
  }
263✔
50
}
86✔
51

52
export function* EmptyStatement(): IterableIterator<any> {
1✔
53
  // No operation here
UNCOV
54
}
×
55

56
export function* DebuggerStatement(): IterableIterator<any> {
1✔
57
  debugger
×
UNCOV
58
}
×
59

60
export function* ReturnStatement(node: acorn.ReturnStatement, scope: Scope) {
1✔
61
  RETURN.RES = node.argument ? (yield* evaluate(node.argument, scope)) : undefined
1!
62
  return RETURN
1✔
63
}
1✔
64

65
export function* BreakStatement(node: acorn.BreakStatement) {
1✔
66
  BREAK.LABEL = node.label?.name
×
67
  return BREAK
×
UNCOV
68
}
×
69

70
export function* ContinueStatement(node: acorn.ContinueStatement) {
1✔
71
  CONTINUE.LABEL = node.label?.name
×
72
  return CONTINUE
×
UNCOV
73
}
×
74

75
export function* LabeledStatement(node: acorn.LabeledStatement, scope: Scope) {
1✔
76
  const label = node.label.name
×
77
  if (node.body.type === 'WhileStatement') {
×
78
    return yield* WhileStatement(node.body, scope, { label })
×
UNCOV
79
  }
×
80
  if (node.body.type === 'DoWhileStatement') {
×
81
    return yield* DoWhileStatement(node.body, scope, { label })
×
UNCOV
82
  }
×
83
  if (node.body.type === 'ForStatement') {
×
84
    return yield* ForStatement(node.body, scope, { label })
×
UNCOV
85
  }
×
86
  if (node.body.type === 'ForInStatement') {
×
87
    return yield* ForInStatement(node.body, scope, { label })
×
UNCOV
88
  }
×
89
  if (node.body.type === 'ForOfStatement') {
×
90
    return yield* ForOfStatement(node.body, scope, { label })
×
UNCOV
91
  }
×
92
  if (node.body.type === 'BlockStatement') {
×
93
    return yield* BlockStatement(node.body, scope, { label })
×
UNCOV
94
  }
×
95
  if (node.body.type === 'WithStatement') {
×
96
    return yield* WithStatement(node.body, scope, { label })
×
UNCOV
97
  }
×
98
  if (node.body.type === 'IfStatement') {
×
99
    return yield* IfStatement(node.body, scope, { label })
×
UNCOV
100
  }
×
101
  if (node.body.type === 'SwitchStatement') {
×
102
    return yield* SwitchStatement(node.body, scope, { label })
×
UNCOV
103
  }
×
104
  if (node.body.type === 'TryStatement') {
×
105
    return yield* TryStatement(node.body, scope, { label })
×
UNCOV
106
  }
×
107
  throw new SyntaxError(`${node.body.type} cannot be labeled`)
×
UNCOV
108
}
×
109

110
export function* WithStatement(node: acorn.WithStatement, scope: Scope, options: LabelOptions = {}) {
1✔
111
  const withScope = new Scope(scope)
1✔
112
  withScope.with(yield* evaluate(node.object, scope))
1✔
113
  const result = yield* evaluate(node.body, withScope)
1✔
114
  if (result === BREAK) {
1!
115
    if (result.LABEL && result.LABEL === options.label) {
×
116
      // only labeled break to current with statement doesn't bubble up the result
117
      return
×
UNCOV
118
    }
×
119
    return result
×
UNCOV
120
  }
×
121
  if (result === CONTINUE || result === RETURN) {
1!
122
    return result
×
UNCOV
123
  }
×
124
}
1✔
125

126
export function* IfStatement(node: acorn.IfStatement, scope: Scope, options: LabelOptions = {}) {
1✔
127
  let result
1✔
128

129
  if (yield* evaluate(node.test, scope)) {
1✔
130
    result = yield* evaluate(node.consequent, scope)
1✔
131
  } else {
1!
132
    result = yield* evaluate(node.alternate, scope)
×
UNCOV
133
  }
×
134

135
  if (result === BREAK) {
1!
136
    if (result.LABEL && result.LABEL === options.label) {
×
137
      // only labeled break to current if statement doesn't bubble up the result
138
      return
×
UNCOV
139
    }
×
140
    return result
×
UNCOV
141
  }
×
142
  if (result === CONTINUE || result === RETURN) {
1!
143
    return result
×
UNCOV
144
  }
×
145
}
1✔
146

147
export function* SwitchStatement(node: acorn.SwitchStatement, scope: Scope, options: LabelOptions = {}) {
1✔
148
  const discriminant = yield* evaluate(node.discriminant, scope)
×
149
  let matched = false
×
150
  for (let i = 0; i < node.cases.length; i++) {
×
151
    const eachCase = node.cases[i]
×
152
    if (
×
UNCOV
153
      !matched
×
154
      && (
UNCOV
155
        !eachCase.test  // default
×
UNCOV
156
        || (yield* evaluate(eachCase.test, scope)) === discriminant
×
157
      )
UNCOV
158
    ) {
×
159
      matched = true
×
UNCOV
160
    }
×
161
    if (matched) {
×
162
      const result = yield* SwitchCase(eachCase, scope)
×
163
      if (result === BREAK) {
×
164
        if (result.LABEL === options.label) {
×
165
          break
×
UNCOV
166
        }
×
167
        return result
×
UNCOV
168
      }
×
169
      if (result === CONTINUE || result === RETURN) {
×
170
        return result
×
UNCOV
171
      }
×
UNCOV
172
    }
×
UNCOV
173
  }
×
UNCOV
174
}
×
175

176
export function* SwitchCase(node: acorn.SwitchCase, scope: Scope) {
1✔
177
  for (let i = 0; i < node.consequent.length; i++) {
×
178
    const result = yield* evaluate(node.consequent[i], scope)
×
179
    if (result === BREAK || result === CONTINUE || result === RETURN) {
×
180
      return result
×
UNCOV
181
    }
×
UNCOV
182
  }
×
UNCOV
183
}
×
184

185
export function* ThrowStatement(node: acorn.ThrowStatement, scope: Scope) {
1✔
186
  throw yield* evaluate(node.argument, scope)
×
UNCOV
187
}
×
188

189
export function* TryStatement(node: acorn.TryStatement, scope: Scope, options: LabelOptions = {}) {
1✔
190
  let result
1✔
191

192
  try {
1✔
193
    result = yield* BlockStatement(node.block, scope)
1!
194
  } catch (err) {
1✔
195
    if (node.handler) {
1✔
196
      const subScope = new Scope(scope)
1✔
197
      const param = node.handler.param
1✔
198
      if (param) {
1✔
199
        if (param.type === 'Identifier') {
1✔
200
          const name = param.name
1✔
201
          subScope.var(name, err)
1✔
202
        } else {
1!
203
          yield* pattern(param, scope, { feed: err })
×
UNCOV
204
        }
×
205
      }
1✔
206
      result = yield* CatchClause(node.handler, subScope)
1✔
207
    } else {
1!
208
      throw err
×
UNCOV
209
    }
×
210
  } finally {
1✔
211
    if (node.finalizer) {
1!
212
      result = yield* BlockStatement(node.finalizer, scope)
×
UNCOV
213
    }
×
214
  }
1✔
215

216
  if (result === BREAK) {
1!
217
    if (result.LABEL && result.LABEL === options.label) {
×
218
      // only labeled break to current try statement doesn't bubble up the result
219
      return
×
UNCOV
220
    }
×
221
    return result
×
UNCOV
222
  }
×
223
  if (result === CONTINUE || result === RETURN) {
1!
224
    return result
×
UNCOV
225
  }
×
226
}
1✔
227

228
export function* CatchClause(node: acorn.CatchClause, scope: Scope) {
1✔
229
  return yield* BlockStatement(node.body, scope, { invasived: true })
1✔
230
}
1✔
231

232
export function* WhileStatement(node: acorn.WhileStatement, scope: Scope, options: LabelOptions = {}) {
1✔
233
  while (yield* evaluate(node.test, scope)) {
1✔
234
    const result = yield* evaluate(node.body, scope)
3✔
235
    if (result === BREAK) {
3!
236
      if (result.LABEL === options.label) {
×
237
        break
×
UNCOV
238
      }
×
239
      return result
×
240
    } else if (result === CONTINUE) {
3!
241
      if (result.LABEL === options.label) {
×
242
        continue
×
UNCOV
243
      }
×
244
      return result
×
245
    } else if (result === RETURN) {
3!
246
      return result
×
UNCOV
247
    }
×
248
  }
3✔
249
}
1✔
250

251
export function* DoWhileStatement(node: acorn.DoWhileStatement, scope: Scope, options: LabelOptions = {}) {
1✔
252
  do {
×
253
    const result = yield* evaluate(node.body, scope)
×
254
    if (result === BREAK) {
×
255
      if (result.LABEL === options.label) {
×
256
        break
×
UNCOV
257
      }
×
258
      return result
×
259
    } else if (result === CONTINUE) {
×
260
      if (result.LABEL === options.label) {
×
261
        continue
×
UNCOV
262
      }
×
263
      return result
×
264
    } else if (result === RETURN) {
×
265
      return result
×
UNCOV
266
    }
×
UNCOV
267
  } while (yield* evaluate(node.test, scope))
×
UNCOV
268
}
×
269

270
export function* ForStatement(node: acorn.ForStatement, scope: Scope, options: LabelOptions = {}) {
1✔
271
  const forScope = new Scope(scope)
×
272
  
273
  for (
×
UNCOV
274
    yield* evaluate(node.init, forScope);
×
UNCOV
275
    node.test ? (yield* evaluate(node.test, forScope)) : true;
×
UNCOV
276
    yield* evaluate(node.update, forScope)
×
UNCOV
277
  ) {
×
278
    const subScope = new Scope(forScope)
×
UNCOV
279
    let result: any
×
280
    if (node.body.type === 'BlockStatement') {
×
281
      result = yield* BlockStatement(node.body, subScope, { invasived: true })
×
UNCOV
282
    } else {
×
283
      result = yield* evaluate(node.body, subScope)
×
UNCOV
284
    }
×
285

286
    if (result === BREAK) {
×
287
      if (result.LABEL === options.label) {
×
288
        break
×
UNCOV
289
      }
×
290
      return result
×
291
    } else if (result === CONTINUE) {
×
292
      if (result.LABEL === options.label) {
×
293
        continue
×
UNCOV
294
      }
×
295
      return result
×
296
    } else if (result === RETURN) {
×
297
      return result
×
UNCOV
298
    }
×
UNCOV
299
  }
×
UNCOV
300
}
×
301

302
export function* ForInStatement(node: acorn.ForInStatement, scope: Scope, options: LabelOptions = {}) {
1✔
303
  for (const value in yield* evaluate(node.right, scope)) {
×
304
    const result = yield* ForXHandler(node, scope, { value })
×
305
    if (result === BREAK) {
×
306
      if (result.LABEL === options.label) {
×
307
        break
×
UNCOV
308
      }
×
309
      return result
×
310
    } else if (result === CONTINUE) {
×
311
      if (result.LABEL === options.label) {
×
312
        continue
×
UNCOV
313
      }
×
314
      return result
×
315
    } else if (result === RETURN) {
×
316
      return result
×
UNCOV
317
    }
×
UNCOV
318
  }
×
UNCOV
319
}
×
320

321
export function* ForOfStatement(node: acorn.ForOfStatement, scope: Scope, options: LabelOptions = {}): any {
1✔
322
  const right = yield* evaluate(node.right, scope)
18✔
323
  /*<remove>*/
324
  if (node.await) {
18✔
325
    const iterator = getAsyncIterator(right)
9✔
326
    let ret: any
9✔
327
    for (
9✔
328
      AWAIT.RES = iterator.next(), ret = yield AWAIT;
9✔
329
      !ret.done;
9✔
330
      AWAIT.RES = iterator.next(), ret = yield AWAIT
9✔
331
    ) {
28✔
332
      const result = yield* ForXHandler(node, scope, { value: ret.value })
28✔
333
      if (result === BREAK) {
28!
334
        if (result.LABEL === options.label) {
×
335
          break
×
UNCOV
336
        }
×
337
        return result
×
338
      } else if (result === CONTINUE) {
28!
339
        if (result.LABEL === options.label) {
×
340
          continue
×
UNCOV
341
        }
×
342
        return result
×
343
      } else if (result === RETURN) {
28!
344
        return result
×
UNCOV
345
      }
×
346
    }
28✔
347
  } else {
9✔
348
  /*</remove>*/
349
    for (const value of right) {
9✔
350
      const result = yield* ForXHandler(node, scope, { value })
26✔
351
      if (result === BREAK) {
26!
352
        if (result.LABEL === options.label) {
×
353
          break
×
UNCOV
354
        }
×
355
        return result
×
356
      } else if (result === CONTINUE) {
26✔
357
        if (result.LABEL === options.label) {
×
358
          continue
×
UNCOV
359
        }
×
360
        return result
×
361
      } else if (result === RETURN) {
24!
362
        return result
×
UNCOV
363
      }
×
364
    }
26✔
365
  /*<remove>*/
366
  }
7✔
367
  /*</remove>*/
368
}
18✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc