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