/
ExportDefaultVariable.ts
92 lines (82 loc) · 2.94 KB
/
ExportDefaultVariable.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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import type { AstContext } from '../../Module';
import ClassDeclaration from '../nodes/ClassDeclaration';
import type ExportDefaultDeclaration from '../nodes/ExportDefaultDeclaration';
import FunctionDeclaration from '../nodes/FunctionDeclaration';
import Identifier, { type IdentifierWithVariable } from '../nodes/Identifier';
import LocalVariable from './LocalVariable';
import UndefinedVariable from './UndefinedVariable';
import type Variable from './Variable';
export default class ExportDefaultVariable extends LocalVariable {
hasId = false;
private originalId: IdentifierWithVariable | null = null;
private originalVariable: Variable | null = null;
constructor(
name: string,
exportDefaultDeclaration: ExportDefaultDeclaration,
context: AstContext
) {
super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context);
const declaration = exportDefaultDeclaration.declaration;
if (
(declaration instanceof FunctionDeclaration || declaration instanceof ClassDeclaration) &&
declaration.id
) {
this.hasId = true;
this.originalId = declaration.id;
} else if (declaration instanceof Identifier) {
this.originalId = declaration as IdentifierWithVariable;
}
}
addReference(identifier: Identifier): void {
if (!this.hasId) {
this.name = identifier.name;
}
}
forbidName(name: string) {
const original = this.getOriginalVariable();
if (original === this) {
super.forbidName(name);
} else {
original.forbidName(name);
}
}
getAssignedVariableName(): string | null {
return (this.originalId && this.originalId.name) || null;
}
getBaseVariableName(): string {
const original = this.getOriginalVariable();
return original === this ? super.getBaseVariableName() : original.getBaseVariableName();
}
getDirectOriginalVariable(): Variable | null {
return this.originalId &&
(this.hasId ||
!(
this.originalId.isPossibleTDZ() ||
this.originalId.variable.isReassigned ||
this.originalId.variable instanceof UndefinedVariable ||
// this avoids a circular dependency
'syntheticNamespace' in this.originalId.variable
))
? this.originalId.variable
: null;
}
getName(getPropertyAccess: (name: string) => string): string {
const original = this.getOriginalVariable();
return original === this
? super.getName(getPropertyAccess)
: original.getName(getPropertyAccess);
}
getOriginalVariable(): Variable {
if (this.originalVariable) return this.originalVariable;
// eslint-disable-next-line @typescript-eslint/no-this-alias
let original: Variable | null = this;
let currentVariable: Variable;
const checkedVariables = new Set<Variable>();
do {
checkedVariables.add(original);
currentVariable = original;
original = (currentVariable as ExportDefaultVariable).getDirectOriginalVariable();
} while (original instanceof ExportDefaultVariable && !checkedVariables.has(original));
return (this.originalVariable = original || currentVariable);
}
}