/
NamespaceVariable.ts
138 lines (118 loc) · 4.44 KB
/
NamespaceVariable.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import Module, { AstContext } from '../../Module';
import { RenderOptions } from '../../utils/renderHelpers';
import { RESERVED_NAMES } from '../../utils/reservedNames';
import { InclusionContext } from '../ExecutionContext';
import Identifier from '../nodes/Identifier';
import { UNKNOWN_PATH } from '../utils/PathTracker';
import ExternalVariable from './ExternalVariable';
import Variable from './Variable';
export default class NamespaceVariable extends Variable {
context: AstContext;
isNamespace!: true;
memberVariables: { [name: string]: Variable } = Object.create(null);
module: Module;
private reexportedExternalNamespaces: string[] = [];
private reexportedExternalNamespaceVariables: ExternalVariable[] = [];
private referencedEarly = false;
private references: Identifier[] = [];
private syntheticNamedExports: boolean;
constructor(context: AstContext, syntheticNamedExports: boolean) {
super(context.getModuleName());
this.context = context;
this.module = context.module;
this.syntheticNamedExports = syntheticNamedExports;
}
addReference(identifier: Identifier) {
this.references.push(identifier);
this.name = identifier.name;
}
// This is only called if "UNKNOWN_PATH" is reassigned as in all other situations, either the
// build fails due to an illegal namespace reassignment or MemberExpression already forwards
// the reassignment to the right variable. This means we lost track of this variable and thus
// need to reassign all exports.
deoptimizePath() {
for (const key in this.memberVariables) {
this.memberVariables[key].deoptimizePath(UNKNOWN_PATH);
}
}
include(context: InclusionContext) {
if (!this.included) {
this.included = true;
for (const identifier of this.references) {
if (identifier.context.getModuleExecIndex() <= this.context.getModuleExecIndex()) {
this.referencedEarly = true;
break;
}
}
for (const name of this.reexportedExternalNamespaces) {
this.reexportedExternalNamespaceVariables.push(
this.context.includeExternalReexportNamespace(name)
);
}
if (this.context.preserveModules) {
for (const memberName of Object.keys(this.memberVariables))
this.memberVariables[memberName].include(context);
} else {
for (const memberName of Object.keys(this.memberVariables))
this.context.includeVariable(context, this.memberVariables[memberName]);
}
}
}
initialise() {
for (const name of this.context.getExports().concat(this.context.getReexports())) {
if (name[0] === '*' && name.length > 1) {
this.reexportedExternalNamespaces.push(name.slice(1));
} else {
this.memberVariables[name] = this.context.traceExport(name);
}
}
}
renderBlock(options: RenderOptions) {
const _ = options.compact ? '' : ' ';
const n = options.compact ? '' : '\n';
const t = options.indent;
const members = Object.keys(this.memberVariables).map(name => {
const original = this.memberVariables[name];
if (this.referencedEarly || original.isReassigned) {
return `${t}get ${name}${_}()${_}{${_}return ${original.getName()}${
options.compact ? '' : ';'
}${_}}`;
}
const safeName = RESERVED_NAMES[name] ? `'${name}'` : name;
return `${t}${safeName}: ${original.getName()}`;
});
if (options.namespaceToStringTag) {
members.unshift(`${t}[Symbol.toStringTag]:${_}'Module'`);
}
// TODO Lukas rename to reflect they are external
const hasExternalReexports = this.reexportedExternalNamespaceVariables.length > 0;
if (!hasExternalReexports) members.unshift(`${t}__proto__:${_}null`);
let output = `{${n}${members.join(`,${n}`)}${n}}`;
if (hasExternalReexports || this.syntheticNamedExports) {
const assignmentArgs = [output];
if (hasExternalReexports) {
assignmentArgs.unshift(
'/*#__PURE__*/Object.create(null)',
...this.reexportedExternalNamespaceVariables.map(variable => variable.getName())
);
}
if (this.syntheticNamedExports) {
assignmentArgs.push(this.module.getDefaultExport().getName());
}
output = `/*#__PURE__*/Object.assign(${assignmentArgs.join(`,${_}`)})`;
}
if (options.freeze) {
output = `/*#__PURE__*/Object.freeze(${output})`;
}
const name = this.getName();
output = `${options.varOrConst} ${name}${_}=${_}${output};`;
if (options.format === 'system' && this.exportName) {
output += `${n}exports('${this.exportName}',${_}${name});`;
}
return output;
}
renderFirst() {
return this.referencedEarly;
}
}
NamespaceVariable.prototype.isNamespace = true;