-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
BlockScope.ts
44 lines (42 loc) · 1.66 KB
/
BlockScope.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import type { AstContext } from '../../Module';
import { logRedeclarationError } from '../../utils/logs';
import type Identifier from '../nodes/Identifier';
import type { ExpressionEntity } from '../nodes/shared/Expression';
import { VariableKind } from '../nodes/shared/VariableKinds';
import type LocalVariable from '../variables/LocalVariable';
import ChildScope from './ChildScope';
export default class BlockScope extends ChildScope {
constructor(parent: ChildScope) {
super(parent, parent.context);
}
addDeclaration(
identifier: Identifier,
context: AstContext,
init: ExpressionEntity,
kind: VariableKind
): LocalVariable {
if (kind === VariableKind.var) {
const name = identifier.name;
const existingVariable =
this.hoistedVariables?.get(name) || (this.variables.get(name) as LocalVariable | undefined);
if (existingVariable) {
if (
existingVariable.kind === VariableKind.var ||
(kind === VariableKind.var && existingVariable.kind === VariableKind.parameter)
) {
existingVariable.addDeclaration(identifier, init);
return existingVariable;
}
return context.error(logRedeclarationError(name), identifier.start);
}
const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
// Necessary to make sure the init is deoptimized for conditional declarations.
// We cannot call deoptimizePath here.
declaredVariable.markInitializersForDeoptimization();
// We add the variable to this and all parent scopes to reliably detect conflicts
this.addHoistedVariable(name, declaredVariable);
return declaredVariable;
}
return super.addDeclaration(identifier, context, init, kind);
}
}