/
NamespaceVariable.ts
137 lines (116 loc) · 4.23 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
import Module, { AstContext } from '../../Module';
import { RenderOptions } from '../../utils/renderHelpers';
import { RESERVED_NAMES } from '../../utils/reservedNames';
import { getSystemExportStatement } from '../../utils/systemJsRendering';
import Identifier from '../nodes/Identifier';
import { ObjectPath, UNKNOWN_PATH } from '../utils/PathTracker';
import Variable from './Variable';
export default class NamespaceVariable extends Variable {
context: AstContext;
isNamespace!: true;
module: Module;
private memberVariables: { [name: string]: Variable } | null = null;
private mergedNamespaces: Variable[] = [];
private referencedEarly = false;
private references: Identifier[] = [];
private syntheticNamedExports: boolean | string;
constructor(context: AstContext, syntheticNamedExports: boolean | string) {
super(context.getModuleName());
this.context = context;
this.module = context.module;
this.syntheticNamedExports = syntheticNamedExports;
}
addReference(identifier: Identifier) {
this.references.push(identifier);
this.name = identifier.name;
}
deoptimizePath(path: ObjectPath) {
const memberVariables = this.getMemberVariables();
const memberPath = path.length <= 1 ? UNKNOWN_PATH : path.slice(1);
const key = path[0];
if (typeof key === 'string') {
memberVariables[key]?.deoptimizePath(memberPath);
} else {
for (const key of Object.keys(memberVariables)) {
memberVariables[key].deoptimizePath(memberPath);
}
}
}
getMemberVariables(): { [name: string]: Variable } {
if (this.memberVariables) {
return this.memberVariables;
}
const memberVariables: { [name: string]: Variable } = Object.create(null);
for (const name of this.context.getExports().concat(this.context.getReexports())) {
if (name[0] !== '*' && name !== this.module.info.syntheticNamedExports) {
const exportedVariable = this.context.traceExport(name);
if (exportedVariable) {
memberVariables[name] = exportedVariable;
}
}
}
return (this.memberVariables = memberVariables);
}
include() {
this.included = true;
this.context.includeAllExports();
}
prepareNamespace(mergedNamespaces: Variable[]) {
this.mergedNamespaces = mergedNamespaces;
const moduleExecIndex = this.context.getModuleExecIndex();
for (const identifier of this.references) {
if (identifier.context.getModuleExecIndex() <= moduleExecIndex) {
this.referencedEarly = true;
break;
}
}
}
renderBlock(options: RenderOptions) {
const _ = options.compact ? '' : ' ';
const n = options.compact ? '' : '\n';
const t = options.indent;
const memberVariables = this.getMemberVariables();
const members = Object.keys(memberVariables).map(name => {
const original = 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'`);
}
const needsObjectAssign = this.mergedNamespaces.length > 0 || this.syntheticNamedExports;
if (!needsObjectAssign) members.unshift(`${t}__proto__:${_}null`);
let output = `{${n}${members.join(`,${n}`)}${n}}`;
if (needsObjectAssign) {
const assignmentArgs: string[] = ['/*#__PURE__*/Object.create(null)'];
if (this.mergedNamespaces.length > 0) {
assignmentArgs.push(...this.mergedNamespaces.map(variable => variable.getName()));
}
if (this.syntheticNamedExports) {
assignmentArgs.push(this.module.getSyntheticNamespace().getName());
}
if (members.length > 0) {
assignmentArgs.push(output);
}
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' && options.exportNamesByVariable.has(this)) {
output += `${n}${getSystemExportStatement([this], options)};`;
}
return output;
}
renderFirst() {
return this.referencedEarly;
}
}
NamespaceVariable.prototype.isNamespace = true;