/
NamespaceVariable.ts
133 lines (113 loc) · 4.35 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
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;
reexportedNamespaces: string[] = [];
private reexportedNamespaceVariables: 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.reexportedNamespaces) {
this.reexportedNamespaceVariables.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.reexportedNamespaces.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()}`;
});
const objectCreate = this.reexportedNamespaceVariables.length;
if (!objectCreate) members.unshift(`${t}__proto__:${_}null`);
if (options.namespaceToStringTag) {
members.unshift(`${t}[Symbol.toStringTag]:${_}'Module'`);
}
const name = this.getName();
let output = `{${n}${members.join(`,${n}`)}${n}}`;
if (this.reexportedNamespaceVariables.length) {
output = `Object.assign(Object.create(null), ${this.reexportedNamespaceVariables
.map((v) => v.getName())
.join(', ')}, ${output}${
this.syntheticNamedExports ? ', ' + this.module.getDefaultExport().getName() : ''
})`;
if (!options.freeze) output = '*#__PURE__*/' + output;
} else if (this.syntheticNamedExports) {
output = `Object.assign(${output}, ${this.module.getDefaultExport().getName()})`;
if (!options.freeze) output = '*#__PURE__*/' + output;
}
if (options.freeze) {
output = `/*#__PURE__*/Object.freeze(${output})`;
}
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;