1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = normalizeModuleAndLoadMetadata;
|
7 | exports.hasExports = hasExports;
|
8 | exports.isSideEffectImport = isSideEffectImport;
|
9 | exports.validateImportInteropOption = validateImportInteropOption;
|
10 |
|
11 | var _path = require("path");
|
12 |
|
13 | var _helperValidatorIdentifier = require("@babel/helper-validator-identifier");
|
14 |
|
15 | var _helperSplitExportDeclaration = require("@babel/helper-split-export-declaration");
|
16 |
|
17 | function hasExports(metadata) {
|
18 | return metadata.hasExports;
|
19 | }
|
20 |
|
21 | function isSideEffectImport(source) {
|
22 | return source.imports.size === 0 && source.importsNamespace.size === 0 && source.reexports.size === 0 && source.reexportNamespace.size === 0 && !source.reexportAll;
|
23 | }
|
24 |
|
25 | function validateImportInteropOption(importInterop) {
|
26 | if (typeof importInterop !== "function" && importInterop !== "none" && importInterop !== "babel" && importInterop !== "node") {
|
27 | throw new Error(`.importInterop must be one of "none", "babel", "node", or a function returning one of those values (received ${importInterop}).`);
|
28 | }
|
29 |
|
30 | return importInterop;
|
31 | }
|
32 |
|
33 | function resolveImportInterop(importInterop, source, filename) {
|
34 | if (typeof importInterop === "function") {
|
35 | return validateImportInteropOption(importInterop(source, filename));
|
36 | }
|
37 |
|
38 | return importInterop;
|
39 | }
|
40 |
|
41 | function normalizeModuleAndLoadMetadata(programPath, exportName, {
|
42 | importInterop,
|
43 | initializeReexports = false,
|
44 | lazy = false,
|
45 | esNamespaceOnly = false,
|
46 | filename
|
47 | }) {
|
48 | if (!exportName) {
|
49 | exportName = programPath.scope.generateUidIdentifier("exports").name;
|
50 | }
|
51 |
|
52 | const stringSpecifiers = new Set();
|
53 | nameAnonymousExports(programPath);
|
54 | const {
|
55 | local,
|
56 | source,
|
57 | hasExports
|
58 | } = getModuleMetadata(programPath, {
|
59 | initializeReexports,
|
60 | lazy
|
61 | }, stringSpecifiers);
|
62 | removeModuleDeclarations(programPath);
|
63 |
|
64 | for (const [, metadata] of source) {
|
65 | if (metadata.importsNamespace.size > 0) {
|
66 | metadata.name = metadata.importsNamespace.values().next().value;
|
67 | }
|
68 |
|
69 | const resolvedInterop = resolveImportInterop(importInterop, metadata.source, filename);
|
70 |
|
71 | if (resolvedInterop === "none") {
|
72 | metadata.interop = "none";
|
73 | } else if (resolvedInterop === "node" && metadata.interop === "namespace") {
|
74 | metadata.interop = "node-namespace";
|
75 | } else if (resolvedInterop === "node" && metadata.interop === "default") {
|
76 | metadata.interop = "node-default";
|
77 | } else if (esNamespaceOnly && metadata.interop === "namespace") {
|
78 | metadata.interop = "default";
|
79 | }
|
80 | }
|
81 |
|
82 | return {
|
83 | exportName,
|
84 | exportNameListName: null,
|
85 | hasExports,
|
86 | local,
|
87 | source,
|
88 | stringSpecifiers
|
89 | };
|
90 | }
|
91 |
|
92 | function getExportSpecifierName(path, stringSpecifiers) {
|
93 | if (path.isIdentifier()) {
|
94 | return path.node.name;
|
95 | } else if (path.isStringLiteral()) {
|
96 | const stringValue = path.node.value;
|
97 |
|
98 | if (!(0, _helperValidatorIdentifier.isIdentifierName)(stringValue)) {
|
99 | stringSpecifiers.add(stringValue);
|
100 | }
|
101 |
|
102 | return stringValue;
|
103 | } else {
|
104 | throw new Error(`Expected export specifier to be either Identifier or StringLiteral, got ${path.node.type}`);
|
105 | }
|
106 | }
|
107 |
|
108 | function assertExportSpecifier(path) {
|
109 | if (path.isExportSpecifier()) {
|
110 | return;
|
111 | } else if (path.isExportNamespaceSpecifier()) {
|
112 | throw path.buildCodeFrameError("Export namespace should be first transformed by `@babel/plugin-proposal-export-namespace-from`.");
|
113 | } else {
|
114 | throw path.buildCodeFrameError("Unexpected export specifier type");
|
115 | }
|
116 | }
|
117 |
|
118 | function getModuleMetadata(programPath, {
|
119 | lazy,
|
120 | initializeReexports
|
121 | }, stringSpecifiers) {
|
122 | const localData = getLocalExportMetadata(programPath, initializeReexports, stringSpecifiers);
|
123 | const sourceData = new Map();
|
124 |
|
125 | const getData = sourceNode => {
|
126 | const source = sourceNode.value;
|
127 | let data = sourceData.get(source);
|
128 |
|
129 | if (!data) {
|
130 | data = {
|
131 | name: programPath.scope.generateUidIdentifier((0, _path.basename)(source, (0, _path.extname)(source))).name,
|
132 | interop: "none",
|
133 | loc: null,
|
134 | imports: new Map(),
|
135 | importsNamespace: new Set(),
|
136 | reexports: new Map(),
|
137 | reexportNamespace: new Set(),
|
138 | reexportAll: null,
|
139 | lazy: false,
|
140 | source
|
141 | };
|
142 | sourceData.set(source, data);
|
143 | }
|
144 |
|
145 | return data;
|
146 | };
|
147 |
|
148 | let hasExports = false;
|
149 | programPath.get("body").forEach(child => {
|
150 | if (child.isImportDeclaration()) {
|
151 | const data = getData(child.node.source);
|
152 | if (!data.loc) data.loc = child.node.loc;
|
153 | child.get("specifiers").forEach(spec => {
|
154 | if (spec.isImportDefaultSpecifier()) {
|
155 | const localName = spec.get("local").node.name;
|
156 | data.imports.set(localName, "default");
|
157 | const reexport = localData.get(localName);
|
158 |
|
159 | if (reexport) {
|
160 | localData.delete(localName);
|
161 | reexport.names.forEach(name => {
|
162 | data.reexports.set(name, "default");
|
163 | });
|
164 | }
|
165 | } else if (spec.isImportNamespaceSpecifier()) {
|
166 | const localName = spec.get("local").node.name;
|
167 | data.importsNamespace.add(localName);
|
168 | const reexport = localData.get(localName);
|
169 |
|
170 | if (reexport) {
|
171 | localData.delete(localName);
|
172 | reexport.names.forEach(name => {
|
173 | data.reexportNamespace.add(name);
|
174 | });
|
175 | }
|
176 | } else if (spec.isImportSpecifier()) {
|
177 | const importName = getExportSpecifierName(spec.get("imported"), stringSpecifiers);
|
178 | const localName = spec.get("local").node.name;
|
179 | data.imports.set(localName, importName);
|
180 | const reexport = localData.get(localName);
|
181 |
|
182 | if (reexport) {
|
183 | localData.delete(localName);
|
184 | reexport.names.forEach(name => {
|
185 | data.reexports.set(name, importName);
|
186 | });
|
187 | }
|
188 | }
|
189 | });
|
190 | } else if (child.isExportAllDeclaration()) {
|
191 | hasExports = true;
|
192 | const data = getData(child.node.source);
|
193 | if (!data.loc) data.loc = child.node.loc;
|
194 | data.reexportAll = {
|
195 | loc: child.node.loc
|
196 | };
|
197 | } else if (child.isExportNamedDeclaration() && child.node.source) {
|
198 | hasExports = true;
|
199 | const data = getData(child.node.source);
|
200 | if (!data.loc) data.loc = child.node.loc;
|
201 | child.get("specifiers").forEach(spec => {
|
202 | assertExportSpecifier(spec);
|
203 | const importName = getExportSpecifierName(spec.get("local"), stringSpecifiers);
|
204 | const exportName = getExportSpecifierName(spec.get("exported"), stringSpecifiers);
|
205 | data.reexports.set(exportName, importName);
|
206 |
|
207 | if (exportName === "__esModule") {
|
208 | throw spec.get("exported").buildCodeFrameError('Illegal export "__esModule".');
|
209 | }
|
210 | });
|
211 | } else if (child.isExportNamedDeclaration() || child.isExportDefaultDeclaration()) {
|
212 | hasExports = true;
|
213 | }
|
214 | });
|
215 |
|
216 | for (const metadata of sourceData.values()) {
|
217 | let needsDefault = false;
|
218 | let needsNamed = false;
|
219 |
|
220 | if (metadata.importsNamespace.size > 0) {
|
221 | needsDefault = true;
|
222 | needsNamed = true;
|
223 | }
|
224 |
|
225 | if (metadata.reexportAll) {
|
226 | needsNamed = true;
|
227 | }
|
228 |
|
229 | for (const importName of metadata.imports.values()) {
|
230 | if (importName === "default") needsDefault = true;else needsNamed = true;
|
231 | }
|
232 |
|
233 | for (const importName of metadata.reexports.values()) {
|
234 | if (importName === "default") needsDefault = true;else needsNamed = true;
|
235 | }
|
236 |
|
237 | if (needsDefault && needsNamed) {
|
238 | metadata.interop = "namespace";
|
239 | } else if (needsDefault) {
|
240 | metadata.interop = "default";
|
241 | }
|
242 | }
|
243 |
|
244 | for (const [source, metadata] of sourceData) {
|
245 | if (lazy !== false && !(isSideEffectImport(metadata) || metadata.reexportAll)) {
|
246 | if (lazy === true) {
|
247 | metadata.lazy = !/\./.test(source);
|
248 | } else if (Array.isArray(lazy)) {
|
249 | metadata.lazy = lazy.indexOf(source) !== -1;
|
250 | } else if (typeof lazy === "function") {
|
251 | metadata.lazy = lazy(source);
|
252 | } else {
|
253 | throw new Error(`.lazy must be a boolean, string array, or function`);
|
254 | }
|
255 | }
|
256 | }
|
257 |
|
258 | return {
|
259 | hasExports,
|
260 | local: localData,
|
261 | source: sourceData
|
262 | };
|
263 | }
|
264 |
|
265 | function getLocalExportMetadata(programPath, initializeReexports, stringSpecifiers) {
|
266 | const bindingKindLookup = new Map();
|
267 | programPath.get("body").forEach(child => {
|
268 | let kind;
|
269 |
|
270 | if (child.isImportDeclaration()) {
|
271 | kind = "import";
|
272 | } else {
|
273 | if (child.isExportDefaultDeclaration()) {
|
274 | child = child.get("declaration");
|
275 | }
|
276 |
|
277 | if (child.isExportNamedDeclaration()) {
|
278 | if (child.node.declaration) {
|
279 | child = child.get("declaration");
|
280 | } else if (initializeReexports && child.node.source && child.get("source").isStringLiteral()) {
|
281 | child.get("specifiers").forEach(spec => {
|
282 | assertExportSpecifier(spec);
|
283 | bindingKindLookup.set(spec.get("local").node.name, "block");
|
284 | });
|
285 | return;
|
286 | }
|
287 | }
|
288 |
|
289 | if (child.isFunctionDeclaration()) {
|
290 | kind = "hoisted";
|
291 | } else if (child.isClassDeclaration()) {
|
292 | kind = "block";
|
293 | } else if (child.isVariableDeclaration({
|
294 | kind: "var"
|
295 | })) {
|
296 | kind = "var";
|
297 | } else if (child.isVariableDeclaration()) {
|
298 | kind = "block";
|
299 | } else {
|
300 | return;
|
301 | }
|
302 | }
|
303 |
|
304 | Object.keys(child.getOuterBindingIdentifiers()).forEach(name => {
|
305 | bindingKindLookup.set(name, kind);
|
306 | });
|
307 | });
|
308 | const localMetadata = new Map();
|
309 |
|
310 | const getLocalMetadata = idPath => {
|
311 | const localName = idPath.node.name;
|
312 | let metadata = localMetadata.get(localName);
|
313 |
|
314 | if (!metadata) {
|
315 | const kind = bindingKindLookup.get(localName);
|
316 |
|
317 | if (kind === undefined) {
|
318 | throw idPath.buildCodeFrameError(`Exporting local "${localName}", which is not declared.`);
|
319 | }
|
320 |
|
321 | metadata = {
|
322 | names: [],
|
323 | kind
|
324 | };
|
325 | localMetadata.set(localName, metadata);
|
326 | }
|
327 |
|
328 | return metadata;
|
329 | };
|
330 |
|
331 | programPath.get("body").forEach(child => {
|
332 | if (child.isExportNamedDeclaration() && (initializeReexports || !child.node.source)) {
|
333 | if (child.node.declaration) {
|
334 | const declaration = child.get("declaration");
|
335 | const ids = declaration.getOuterBindingIdentifierPaths();
|
336 | Object.keys(ids).forEach(name => {
|
337 | if (name === "__esModule") {
|
338 | throw declaration.buildCodeFrameError('Illegal export "__esModule".');
|
339 | }
|
340 |
|
341 | getLocalMetadata(ids[name]).names.push(name);
|
342 | });
|
343 | } else {
|
344 | child.get("specifiers").forEach(spec => {
|
345 | const local = spec.get("local");
|
346 | const exported = spec.get("exported");
|
347 | const localMetadata = getLocalMetadata(local);
|
348 | const exportName = getExportSpecifierName(exported, stringSpecifiers);
|
349 |
|
350 | if (exportName === "__esModule") {
|
351 | throw exported.buildCodeFrameError('Illegal export "__esModule".');
|
352 | }
|
353 |
|
354 | localMetadata.names.push(exportName);
|
355 | });
|
356 | }
|
357 | } else if (child.isExportDefaultDeclaration()) {
|
358 | const declaration = child.get("declaration");
|
359 |
|
360 | if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
|
361 | getLocalMetadata(declaration.get("id")).names.push("default");
|
362 | } else {
|
363 | throw declaration.buildCodeFrameError("Unexpected default expression export.");
|
364 | }
|
365 | }
|
366 | });
|
367 | return localMetadata;
|
368 | }
|
369 |
|
370 | function nameAnonymousExports(programPath) {
|
371 | programPath.get("body").forEach(child => {
|
372 | if (!child.isExportDefaultDeclaration()) return;
|
373 | (0, _helperSplitExportDeclaration.default)(child);
|
374 | });
|
375 | }
|
376 |
|
377 | function removeModuleDeclarations(programPath) {
|
378 | programPath.get("body").forEach(child => {
|
379 | if (child.isImportDeclaration()) {
|
380 | child.remove();
|
381 | } else if (child.isExportNamedDeclaration()) {
|
382 | if (child.node.declaration) {
|
383 | child.node.declaration._blockHoist = child.node._blockHoist;
|
384 | child.replaceWith(child.node.declaration);
|
385 | } else {
|
386 | child.remove();
|
387 | }
|
388 | } else if (child.isExportDefaultDeclaration()) {
|
389 | const declaration = child.get("declaration");
|
390 |
|
391 | if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
|
392 | declaration._blockHoist = child.node._blockHoist;
|
393 | child.replaceWith(declaration);
|
394 | } else {
|
395 | throw declaration.buildCodeFrameError("Unexpected default expression export.");
|
396 | }
|
397 | } else if (child.isExportAllDeclaration()) {
|
398 | child.remove();
|
399 | }
|
400 | });
|
401 | }
|
402 |
|
403 |
|