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

Siubaak / sval / 12722229009

11 Jan 2025 07:10AM UTC coverage: 64.374% (-2.5%) from 66.826%
12722229009

push

github

Siubaak
[chore] fix coverage

1421 of 2299 branches covered (61.81%)

Branch coverage included in aggregate %.

1293 of 1917 relevant lines covered (67.45%)

1271.22 hits per line

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

49.64
/src/evaluate/declaration.ts
1
import { NOINIT, DEADZONE, PRIVATE, IMPORT, EXPORTS } from '../share/const'
2
import { define, getDptor, assign, hasOwn } from '../share/util'
3
import { pattern, createFunc, createClass } from './helper'
4
import { BlockStatement } from './statement'
5
import { VarKind } from '../scope/variable'
6
import * as acorn from 'acorn'
7
import Scope from '../scope'
8
import evaluate from '.'
9

10
export function* FunctionDeclaration(
11
  node: acorn.FunctionDeclaration,
12
  scope: Scope
13
): IterableIterator<any> {
14
  scope.func(node.id.name, createFunc(node, scope))
6✔
15
}
16

17
export interface VariableDeclarationOptions {
18
  hoist?: boolean
19
  onlyBlock?: boolean
20
  feed?: any
21
}
22

23
export function* VariableDeclaration(
24
  node: acorn.VariableDeclaration,
25
  scope: Scope,
26
  options: VariableDeclarationOptions = {},
49✔
27
) {
28
  for (let i = 0; i < node.declarations.length; i++) {
342✔
29
    yield* VariableDeclarator(node.declarations[i], scope, assign({ kind: node.kind }, options))
364✔
30
  }
31
}
32

33
export interface VariableDeclaratorOptions {
34
  kind?: VarKind
35
}
36

37
export function* VariableDeclarator(
38
  node: acorn.VariableDeclarator,
39
  scope: Scope,
40
  options: VariableDeclaratorOptions & VariableDeclarationOptions = {},
×
41
) {
42
  const { kind = 'var', hoist = false, onlyBlock = false, feed } = options
364!
43
  if (hoist) {
364✔
44
    if (onlyBlock || kind === 'var') {
146✔
45
      if (node.id.type === 'Identifier') {
106✔
46
        scope[kind](node.id.name, onlyBlock ? DEADZONE : kind === 'var' ? NOINIT : undefined)
88!
47
      } else {
48
        yield* pattern(node.id, scope, { kind, hoist, onlyBlock })
18✔
49
      }
50
    }
51
  } else {
52
    const hasFeed = 'feed' in options
218✔
53
    const value = hasFeed ? feed : yield* evaluate(node.init, scope)
218✔
54
    if (node.id.type === 'Identifier') {
218✔
55
      const name = node.id.name
200✔
56
      if (kind === 'var' && !node.init && !hasFeed) {
200✔
57
        scope.var(name, NOINIT)
10✔
58
      } else {
59
        scope[kind](name, value)
190✔
60
      }
61
      if (
200✔
62
        node.init
148✔
63
        && ['ClassExpression', 'FunctionExpression', 'ArrowFunctionExpression']
64
          .indexOf(node.init.type) !== -1
65
        && !value.name
66
      ) {
67
        define(value, 'name', {
18✔
68
          value: name,
69
          configurable: true
70
        })
71
      }
72
    } else {
73
      yield* pattern(node.id, scope, { kind, feed: value })
18✔
74
    }
75
  }
76
}
77

78
export function* ClassDeclaration(
79
  node: acorn.ClassDeclaration,
80
  scope: Scope
81
): IterableIterator<any> {
82
  scope.func(node.id.name, yield* createClass(node, scope))
×
83
}
84

85
export interface ClassOptions {
86
  klass?: any,
87
  superClass?: (...args: any[]) => void
88
}
89

90
export function* ClassBody(node: acorn.ClassBody, scope: Scope, options: ClassOptions = {}) {
×
91
  const { klass, superClass } = options
×
92

93
  for (let i = 0; i < node.body.length; i++) {
×
94
    const def = node.body[i]
×
95
    if (def.type === 'MethodDefinition') {
×
96
      yield* MethodDefinition(def, scope, { klass, superClass })
×
97
    } else if (def.type === 'PropertyDefinition' && def.static) {
×
98
      yield* PropertyDefinition(def, scope, { klass, superClass })
×
99
    } else if (def.type === 'StaticBlock') {
×
100
      yield* StaticBlock(def, scope, { klass, superClass })
×
101
    }
102
  }
103
}
104

105
export function* MethodDefinition(node: acorn.MethodDefinition, scope: Scope, options: ClassOptions = {}) {
×
106
  const { klass, superClass } = options
×
107

108
  let key: string
109
  let priv: boolean = false
×
110

111
  if (node.computed) {
×
112
    key = yield* evaluate(node.key, scope)
×
113
  } else if (node.key.type === 'Identifier') {
×
114
    key = node.key.name
×
115
  } else if (node.key.type === 'PrivateIdentifier') {
×
116
    key = node.key.name
×
117
    priv = true
×
118
  } else {
119
    throw new SyntaxError('Unexpected token')
×
120
  }
121

122
  let obj = node.static ? klass : klass.prototype
×
123

124
  if (priv) {
×
125
    if (!obj[PRIVATE]) {
×
126
      define(obj, PRIVATE, { value: {} })
×
127
    }
128
    obj = obj[PRIVATE]
×
129
  }
130

131
  const value = createFunc(node.value, scope, { superClass })
×
132

133
  switch (node.kind) {
×
134
    case 'constructor':
135
      break
×
136
    case 'method':
137
      define(obj, key, {
×
138
        value,
139
        writable: true,
140
        configurable: true,
141
      })
142
      break
×
143
    case 'get': {
144
      const oriDptor = getDptor(obj, key)
×
145
      define(obj, key, {
×
146
        get: value,
147
        set: oriDptor && oriDptor.set,
×
148
        configurable: true,
149
      })
150
      break
×
151
    }
152
    case 'set': {
153
      const oriDptor = getDptor(obj, key)
×
154
      define(obj, key, {
×
155
        get: oriDptor && oriDptor.get,
×
156
        set: value,
157
        configurable: true,
158
      })
159
      break
×
160
    }
161
    default:
162
      throw new SyntaxError('Unexpected token')
×
163
  } 
164
}
165

166
export function* PropertyDefinition(node: acorn.PropertyDefinition, scope: Scope, options: ClassOptions = {}) {
×
167
  const { klass, superClass } = options
×
168

169
  let key: string
170
  let priv: boolean = false
×
171

172
  if (node.computed) {
×
173
    key = yield* evaluate(node.key, scope)
×
174
  } else if (node.key.type === 'Identifier') {
×
175
    key = node.key.name
×
176
  } else if (node.key.type === 'PrivateIdentifier') {
×
177
    key = node.key.name
×
178
    priv = true
×
179
  } else {
180
    throw new SyntaxError('Unexpected token')
×
181
  }
182

183
  const subScope: Scope = new Scope(scope, true)
×
184
  subScope.const('this', klass)
×
185

186
  let obj = klass
×
187

188
  if (priv) {
×
189
    if (!obj[PRIVATE]) {
×
190
      define(obj, PRIVATE, { value: {} })
×
191
    }
192
    obj = obj[PRIVATE]
×
193
  }
194

195
  if (!node.value) {
×
196
    obj[key] = undefined
×
197
  } else if (node.value.type === 'FunctionExpression' || node.value.type === 'ArrowFunctionExpression') {
×
198
    obj[key] = createFunc(node.value, subScope, { superClass })
×
199
  } else {
200
    obj[key] = yield* evaluate(node.value, subScope)
×
201
  }
202
}
203

204
export function* StaticBlock(node: acorn.StaticBlock, scope: Scope, options: ClassOptions = {}) {
×
205
  const { klass } = options
×
206

207
  const subScope: Scope = new Scope(scope, true)
×
208
  subScope.const('this', klass)
×
209

210
  return yield* BlockStatement(node, subScope, { invasived: true })
×
211
}
212

213
export function* ImportDeclaration(node: acorn.ImportDeclaration, scope: Scope) {
214
  const globalScope = scope.global()
14✔
215

216
  const module = globalScope.find(IMPORT + node.source.value)
14✔
217
  let value: any
218
  if (module) {
14!
219
    const result = module.get()
14✔
220
    if (result) {
14!
221
      if (typeof result === 'function') {
14✔
222
        value = result()
4✔
223
      } else if (typeof result === 'object') {
10!
224
        value = result
10✔
225
      }
226
    }
227
  }
228

229
  if (!value || typeof value !== 'object') {
14!
230
    throw new TypeError(`Failed to resolve module specifier "${node.source.value}"`)
×
231
  }
232

233
  for (let i = 0; i < node.specifiers.length; i++) {
14✔
234
    const spec = node.specifiers[i]
16✔
235
    let name: string
236
    if (spec.type === 'ImportSpecifier') {
16✔
237
      name = spec.imported.type === 'Identifier'
2!
238
        ? spec.imported.name : spec.imported.value as string
239
    } else if (spec.type === 'ImportDefaultSpecifier') {
14✔
240
      name = 'default'
12✔
241
    } else if (spec.type === 'ImportNamespaceSpecifier') {
2!
242
      name = '*'
2✔
243
    }
244
    if (name !== '*' && !hasOwn(value, name)) {
16!
245
      throw new SyntaxError(`The requested module "${node.source.value}" does not provide an export named "${name}"`)
×
246
    }
247
    scope.var(spec.local.name, name === '*' ? assign({}, value) : value[name])
16✔
248
  }
249
}
250

251
export function* ExportDefaultDeclaration(node: acorn.ExportDefaultDeclaration, scope: Scope) {
252
  const globalScope = scope.global()
×
253

254
  let value: any
255
  if (node.declaration.type === 'FunctionDeclaration') {
×
256
    value = createFunc(node.declaration, scope)
×
257
    scope.func(node.declaration.id.name, value)
×
258
  } else if (node.declaration.type === 'ClassDeclaration') {
×
259
    value = yield* createClass(node.declaration, scope)
×
260
    scope.func(node.declaration.id.name, value)
×
261
  } else {
262
    value = yield* evaluate(node.declaration, scope)
×
263
  }
264

265
  const variable = globalScope.find(EXPORTS)
×
266
  if (variable) {
×
267
    const exports = variable.get()
×
268
    if (exports && typeof exports === 'object') {
×
269
      exports.default = value
×
270
    }
271
  }
272
}
273

274
export function* ExportNamedDeclaration(node: acorn.ExportNamedDeclaration, scope: Scope) {
275
  const globalScope = scope.global()
6✔
276

277
  if (node.declaration) {
6✔
278
    if (node.declaration.type === 'FunctionDeclaration') {
4✔
279
      const value = createFunc(node.declaration, scope)
2✔
280
      scope.func(node.declaration.id.name, value)
2✔
281
      const variable = globalScope.find(EXPORTS)
2✔
282
      if (variable) {
2!
283
        const exports = variable.get()
2✔
284
        if (exports && typeof exports === 'object') {
2!
285
          exports[node.declaration.id.name] = value
2✔
286
        }
287
      }
288
    } else if (node.declaration.type === 'ClassDeclaration') {
2!
289
      const value = yield* createClass(node.declaration, scope)
×
290
      scope.func(node.declaration.id.name, value)
×
291
      const variable = globalScope.find(EXPORTS)
×
292
      if (variable) {
×
293
        const exports = variable.get()
×
294
        if (exports && typeof exports === 'object') {
×
295
          exports[node.declaration.id.name] = value
×
296
        }
297
      }
298
    } else if (node.declaration.type === 'VariableDeclaration') {
2!
299
      yield* VariableDeclaration(node.declaration, scope)
2✔
300
      const variable = globalScope.find(EXPORTS)
2✔
301
      if (variable) {
2!
302
        const exports = variable.get()
2✔
303
        if (exports && typeof exports === 'object') {
2!
304
          for (let i = 0; i < node.declaration.declarations.length; i++) {
2✔
305
            const name = (node.declaration.declarations[i].id as acorn.Identifier).name
4✔
306
            const item = scope.find(name)
4✔
307
            if (item) {
4!
308
              exports[name] = item.get()
4✔
309
            }
310
          }
311
        }
312
      }
313
    }
314
  } else if (node.specifiers) {
2!
315
    const variable = globalScope.find(EXPORTS)
2✔
316
    if (variable) {
2!
317
      const exports = variable.get()
2✔
318
      if (exports && typeof exports === 'object') {
2!
319
        for (let i = 0; i < node.specifiers.length; i++) {
2✔
320
          const spec = node.specifiers[i]
2✔
321
          const name = spec.local.type === 'Identifier'
2!
322
            ? spec.local.name : spec.local.value as string
323
          const item = scope.find(name)
2✔
324
          if (item) {
2!
325
            exports[
2✔
326
              spec.exported.type === 'Identifier'
1!
327
                ? spec.exported.name : spec.exported.value as string
328
            ] = item.get()
329
          }
330
        }
331
      }
332
    }
333
  }
334
}
335

336
export function* ExportAllDeclaration(node: acorn.ExportAllDeclaration, scope: Scope) {
337
  const globalScope = scope.global()
2✔
338

339
  const module = globalScope.find(IMPORT + node.source.value)
2✔
340
  let value: any
341
  if (module) {
2!
342
    const result = module.get()
2✔
343
    if (result) {
2!
344
      if (typeof result === 'function') {
2!
345
        value = result()
2✔
346
      } else if (typeof result === 'object') {
×
347
        value = result
×
348
      }
349
    }
350
  }
351

352
  if (!value || typeof value !== 'object') {
2!
353
    throw new TypeError(`Failed to resolve module specifier "${node.source.value}"`)
×
354
  }
355

356
  const variable = globalScope.find(EXPORTS)
2✔
357
  if (variable) {
2!
358
    const exports = variable.get()
2✔
359
    if (exports && typeof exports === 'object') {
2!
360
      assign(exports, value)
2✔
361
    }
362
  }
363
}
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

© 2026 Coveralls, Inc