1 | import { blank, keys } from './utils/object.js';
|
2 | import run from './utils/run.js';
|
3 |
|
4 | export default class Declaration {
|
5 | constructor ( node, isParam, statement ) {
|
6 | if ( node ) {
|
7 | if ( node.type === 'FunctionDeclaration' ) {
|
8 | this.isFunctionDeclaration = true;
|
9 | this.functionNode = node;
|
10 | } else if ( node.type === 'VariableDeclarator' && node.init && /FunctionExpression/.test( node.init.type ) ) {
|
11 | this.isFunctionDeclaration = true;
|
12 | this.functionNode = node.init;
|
13 | }
|
14 | }
|
15 |
|
16 | this.statement = statement;
|
17 | this.name = null;
|
18 | this.isParam = isParam;
|
19 |
|
20 | this.isReassigned = false;
|
21 | this.aliases = [];
|
22 |
|
23 | this.isUsed = false;
|
24 | }
|
25 |
|
26 | addAlias ( declaration ) {
|
27 | this.aliases.push( declaration );
|
28 | }
|
29 |
|
30 | addReference ( reference ) {
|
31 | reference.declaration = this;
|
32 | this.name = reference.name;
|
33 |
|
34 | if ( reference.isReassignment ) this.isReassigned = true;
|
35 | }
|
36 |
|
37 | render ( es6 ) {
|
38 | if ( es6 ) return this.name;
|
39 | if ( !this.isReassigned || !this.isExported ) return this.name;
|
40 |
|
41 | return `exports.${this.name}`;
|
42 | }
|
43 |
|
44 | run ( strongDependencies ) {
|
45 | if ( this.tested ) return this.hasSideEffects;
|
46 | this.tested = true;
|
47 |
|
48 | if ( !this.functionNode ) {
|
49 | this.hasSideEffects = true;
|
50 | } else {
|
51 | this.hasSideEffects = run( this.functionNode.body, this.functionNode._scope, this.statement, strongDependencies, false );
|
52 | }
|
53 |
|
54 | return this.hasSideEffects;
|
55 | }
|
56 |
|
57 | use () {
|
58 | if ( this.isUsed ) return;
|
59 |
|
60 | this.isUsed = true;
|
61 | if ( this.statement ) this.statement.mark();
|
62 |
|
63 | this.aliases.forEach( alias => alias.use() );
|
64 | }
|
65 | }
|
66 |
|
67 | export class SyntheticDefaultDeclaration {
|
68 | constructor ( node, statement, name ) {
|
69 | this.node = node;
|
70 | this.statement = statement;
|
71 | this.name = name;
|
72 |
|
73 | this.original = null;
|
74 | this.isExported = false;
|
75 | this.aliases = [];
|
76 | }
|
77 |
|
78 | addAlias ( declaration ) {
|
79 | this.aliases.push( declaration );
|
80 | }
|
81 |
|
82 | addReference ( reference ) {
|
83 |
|
84 | reference.declaration = this;
|
85 |
|
86 |
|
87 | if ( reference.name === 'default' ) return;
|
88 |
|
89 | this.name = reference.name;
|
90 | }
|
91 |
|
92 | bind ( declaration ) {
|
93 | this.original = declaration;
|
94 | }
|
95 |
|
96 | render () {
|
97 | return !this.original || this.original.isReassigned ?
|
98 | this.name :
|
99 | this.original.render();
|
100 | }
|
101 |
|
102 | run ( strongDependencies ) {
|
103 | if ( this.original ) {
|
104 | return this.original.run( strongDependencies );
|
105 | }
|
106 |
|
107 | if ( /FunctionExpression/.test( this.node.declaration.type ) ) {
|
108 | return run( this.node.declaration.body, this.statement.scope, this.statement, strongDependencies, false );
|
109 | }
|
110 | }
|
111 |
|
112 | use () {
|
113 | this.isUsed = true;
|
114 | this.statement.mark();
|
115 |
|
116 | if ( this.original ) this.original.use();
|
117 |
|
118 | this.aliases.forEach( alias => alias.use() );
|
119 | }
|
120 | }
|
121 |
|
122 | export class SyntheticNamespaceDeclaration {
|
123 | constructor ( module ) {
|
124 | this.module = module;
|
125 | this.name = null;
|
126 |
|
127 | this.needsNamespaceBlock = false;
|
128 | this.aliases = [];
|
129 |
|
130 | this.originals = blank();
|
131 | module.getExports().forEach( name => {
|
132 | this.originals[ name ] = module.traceExport( name );
|
133 | });
|
134 | }
|
135 |
|
136 | addAlias ( declaration ) {
|
137 | this.aliases.push( declaration );
|
138 | }
|
139 |
|
140 | addReference ( reference ) {
|
141 |
|
142 |
|
143 | if ( reference.parts.length ) {
|
144 | reference.name = reference.parts.shift();
|
145 |
|
146 | reference.end += reference.name.length + 1;
|
147 |
|
148 | const original = this.originals[ reference.name ];
|
149 |
|
150 |
|
151 | if ( !original ) {
|
152 | this.module.bundle.onwarn( `Export '${reference.name}' is not defined by '${this.module.id}'` );
|
153 | reference.isUndefined = true;
|
154 | return;
|
155 | }
|
156 |
|
157 | original.addReference( reference );
|
158 | return;
|
159 | }
|
160 |
|
161 |
|
162 |
|
163 |
|
164 | if ( !this.needsNamespaceBlock ) {
|
165 | this.needsNamespaceBlock = true;
|
166 | this.module.bundle.internalNamespaces.push( this );
|
167 | }
|
168 |
|
169 | reference.declaration = this;
|
170 | this.name = reference.name;
|
171 | }
|
172 |
|
173 | renderBlock ( indentString ) {
|
174 | const members = keys( this.originals ).map( name => {
|
175 | const original = this.originals[ name ];
|
176 |
|
177 | if ( original.isReassigned ) {
|
178 | return `${indentString}get ${name} () { return ${original.render()}; }`;
|
179 | }
|
180 |
|
181 | return `${indentString}${name}: ${original.render()}`;
|
182 | });
|
183 |
|
184 | return `var ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`;
|
185 | }
|
186 |
|
187 | render () {
|
188 | return this.name;
|
189 | }
|
190 |
|
191 | use () {
|
192 | keys( this.originals ).forEach( name => {
|
193 | this.originals[ name ].use();
|
194 | });
|
195 |
|
196 | this.aliases.forEach( alias => alias.use() );
|
197 | }
|
198 | }
|
199 |
|
200 | export class ExternalDeclaration {
|
201 | constructor ( module, name ) {
|
202 | this.module = module;
|
203 | this.name = name;
|
204 | this.isExternal = true;
|
205 | }
|
206 |
|
207 | addAlias () {
|
208 |
|
209 | }
|
210 |
|
211 | addReference ( reference ) {
|
212 | reference.declaration = this;
|
213 |
|
214 | if ( this.name === 'default' || this.name === '*' ) {
|
215 | this.module.suggestName( reference.name );
|
216 | }
|
217 | }
|
218 |
|
219 | render ( es6 ) {
|
220 | if ( this.name === '*' ) {
|
221 | return this.module.name;
|
222 | }
|
223 |
|
224 | if ( this.name === 'default' ) {
|
225 | return !es6 && this.module.exportsNames ?
|
226 | `${this.module.name}__default` :
|
227 | this.module.name;
|
228 | }
|
229 |
|
230 | return es6 ? this.name : `${this.module.name}.${this.name}`;
|
231 | }
|
232 |
|
233 | run () {
|
234 | return true;
|
235 | }
|
236 |
|
237 | use () {
|
238 |
|
239 | }
|
240 | }
|