|
@@ -0,0 +1,346 @@
|
|
|
+"use strict";
|
|
|
+
|
|
|
+Object.defineProperty(exports, "__esModule", {
|
|
|
+ value: true
|
|
|
+});
|
|
|
+exports.hasExports = hasExports;
|
|
|
+exports.isSideEffectImport = isSideEffectImport;
|
|
|
+exports.default = normalizeModuleAndLoadMetadata;
|
|
|
+
|
|
|
+var _path = require("path");
|
|
|
+
|
|
|
+var _helperSplitExportDeclaration = _interopRequireDefault(require("@babel/helper-split-export-declaration"));
|
|
|
+
|
|
|
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
+
|
|
|
+function hasExports(metadata) {
|
|
|
+ return metadata.hasExports;
|
|
|
+}
|
|
|
+
|
|
|
+function isSideEffectImport(source) {
|
|
|
+ return source.imports.size === 0 && source.importsNamespace.size === 0 && source.reexports.size === 0 && source.reexportNamespace.size === 0 && !source.reexportAll;
|
|
|
+}
|
|
|
+
|
|
|
+function normalizeModuleAndLoadMetadata(programPath, exportName, {
|
|
|
+ noInterop = false,
|
|
|
+ loose = false,
|
|
|
+ lazy = false,
|
|
|
+ esNamespaceOnly = false
|
|
|
+} = {}) {
|
|
|
+ if (!exportName) {
|
|
|
+ exportName = programPath.scope.generateUidIdentifier("exports").name;
|
|
|
+ }
|
|
|
+
|
|
|
+ nameAnonymousExports(programPath);
|
|
|
+ const {
|
|
|
+ local,
|
|
|
+ source,
|
|
|
+ hasExports
|
|
|
+ } = getModuleMetadata(programPath, {
|
|
|
+ loose,
|
|
|
+ lazy
|
|
|
+ });
|
|
|
+ removeModuleDeclarations(programPath);
|
|
|
+
|
|
|
+ for (const [, metadata] of source) {
|
|
|
+ if (metadata.importsNamespace.size > 0) {
|
|
|
+ metadata.name = metadata.importsNamespace.values().next().value;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (noInterop) metadata.interop = "none";else if (esNamespaceOnly) {
|
|
|
+ if (metadata.interop === "namespace") {
|
|
|
+ metadata.interop = "default";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ exportName,
|
|
|
+ exportNameListName: null,
|
|
|
+ hasExports,
|
|
|
+ local,
|
|
|
+ source
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+function getModuleMetadata(programPath, {
|
|
|
+ loose,
|
|
|
+ lazy
|
|
|
+}) {
|
|
|
+ const localData = getLocalExportMetadata(programPath, loose);
|
|
|
+ const sourceData = new Map();
|
|
|
+
|
|
|
+ const getData = sourceNode => {
|
|
|
+ const source = sourceNode.value;
|
|
|
+ let data = sourceData.get(source);
|
|
|
+
|
|
|
+ if (!data) {
|
|
|
+ data = {
|
|
|
+ name: programPath.scope.generateUidIdentifier((0, _path.basename)(source, (0, _path.extname)(source))).name,
|
|
|
+ interop: "none",
|
|
|
+ loc: null,
|
|
|
+ imports: new Map(),
|
|
|
+ importsNamespace: new Set(),
|
|
|
+ reexports: new Map(),
|
|
|
+ reexportNamespace: new Set(),
|
|
|
+ reexportAll: null,
|
|
|
+ lazy: false
|
|
|
+ };
|
|
|
+ sourceData.set(source, data);
|
|
|
+ }
|
|
|
+
|
|
|
+ return data;
|
|
|
+ };
|
|
|
+
|
|
|
+ let hasExports = false;
|
|
|
+ programPath.get("body").forEach(child => {
|
|
|
+ if (child.isImportDeclaration()) {
|
|
|
+ const data = getData(child.node.source);
|
|
|
+ if (!data.loc) data.loc = child.node.loc;
|
|
|
+ child.get("specifiers").forEach(spec => {
|
|
|
+ if (spec.isImportDefaultSpecifier()) {
|
|
|
+ const localName = spec.get("local").node.name;
|
|
|
+ data.imports.set(localName, "default");
|
|
|
+ const reexport = localData.get(localName);
|
|
|
+
|
|
|
+ if (reexport) {
|
|
|
+ localData.delete(localName);
|
|
|
+ reexport.names.forEach(name => {
|
|
|
+ data.reexports.set(name, "default");
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (spec.isImportNamespaceSpecifier()) {
|
|
|
+ const localName = spec.get("local").node.name;
|
|
|
+ data.importsNamespace.add(localName);
|
|
|
+ const reexport = localData.get(localName);
|
|
|
+
|
|
|
+ if (reexport) {
|
|
|
+ localData.delete(localName);
|
|
|
+ reexport.names.forEach(name => {
|
|
|
+ data.reexportNamespace.add(name);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (spec.isImportSpecifier()) {
|
|
|
+ const importName = spec.get("imported").node.name;
|
|
|
+ const localName = spec.get("local").node.name;
|
|
|
+ data.imports.set(localName, importName);
|
|
|
+ const reexport = localData.get(localName);
|
|
|
+
|
|
|
+ if (reexport) {
|
|
|
+ localData.delete(localName);
|
|
|
+ reexport.names.forEach(name => {
|
|
|
+ data.reexports.set(name, importName);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else if (child.isExportAllDeclaration()) {
|
|
|
+ hasExports = true;
|
|
|
+ const data = getData(child.node.source);
|
|
|
+ if (!data.loc) data.loc = child.node.loc;
|
|
|
+ data.reexportAll = {
|
|
|
+ loc: child.node.loc
|
|
|
+ };
|
|
|
+ } else if (child.isExportNamedDeclaration() && child.node.source) {
|
|
|
+ hasExports = true;
|
|
|
+ const data = getData(child.node.source);
|
|
|
+ if (!data.loc) data.loc = child.node.loc;
|
|
|
+ child.get("specifiers").forEach(spec => {
|
|
|
+ if (!spec.isExportSpecifier()) {
|
|
|
+ throw spec.buildCodeFrameError("Unexpected export specifier type");
|
|
|
+ }
|
|
|
+
|
|
|
+ const importName = spec.get("local").node.name;
|
|
|
+ const exportName = spec.get("exported").node.name;
|
|
|
+ data.reexports.set(exportName, importName);
|
|
|
+
|
|
|
+ if (exportName === "__esModule") {
|
|
|
+ throw exportName.buildCodeFrameError('Illegal export "__esModule".');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else if (child.isExportNamedDeclaration() || child.isExportDefaultDeclaration()) {
|
|
|
+ hasExports = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ for (const metadata of sourceData.values()) {
|
|
|
+ let needsDefault = false;
|
|
|
+ let needsNamed = false;
|
|
|
+
|
|
|
+ if (metadata.importsNamespace.size > 0) {
|
|
|
+ needsDefault = true;
|
|
|
+ needsNamed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (metadata.reexportAll) {
|
|
|
+ needsNamed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const importName of metadata.imports.values()) {
|
|
|
+ if (importName === "default") needsDefault = true;else needsNamed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const importName of metadata.reexports.values()) {
|
|
|
+ if (importName === "default") needsDefault = true;else needsNamed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (needsDefault && needsNamed) {
|
|
|
+ metadata.interop = "namespace";
|
|
|
+ } else if (needsDefault) {
|
|
|
+ metadata.interop = "default";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const [source, metadata] of sourceData) {
|
|
|
+ if (lazy !== false && !(isSideEffectImport(metadata) || metadata.reexportAll)) {
|
|
|
+ if (lazy === true) {
|
|
|
+ metadata.lazy = !/\./.test(source);
|
|
|
+ } else if (Array.isArray(lazy)) {
|
|
|
+ metadata.lazy = lazy.indexOf(source) !== -1;
|
|
|
+ } else if (typeof lazy === "function") {
|
|
|
+ metadata.lazy = lazy(source);
|
|
|
+ } else {
|
|
|
+ throw new Error(`.lazy must be a boolean, string array, or function`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ hasExports,
|
|
|
+ local: localData,
|
|
|
+ source: sourceData
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+function getLocalExportMetadata(programPath, loose) {
|
|
|
+ const bindingKindLookup = new Map();
|
|
|
+ programPath.get("body").forEach(child => {
|
|
|
+ let kind;
|
|
|
+
|
|
|
+ if (child.isImportDeclaration()) {
|
|
|
+ kind = "import";
|
|
|
+ } else {
|
|
|
+ if (child.isExportDefaultDeclaration()) child = child.get("declaration");
|
|
|
+
|
|
|
+ if (child.isExportNamedDeclaration()) {
|
|
|
+ if (child.node.declaration) {
|
|
|
+ child = child.get("declaration");
|
|
|
+ } else if (loose && child.node.source && child.get("source").isStringLiteral()) {
|
|
|
+ child.node.specifiers.forEach(specifier => {
|
|
|
+ bindingKindLookup.set(specifier.local.name, "block");
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (child.isFunctionDeclaration()) {
|
|
|
+ kind = "hoisted";
|
|
|
+ } else if (child.isClassDeclaration()) {
|
|
|
+ kind = "block";
|
|
|
+ } else if (child.isVariableDeclaration({
|
|
|
+ kind: "var"
|
|
|
+ })) {
|
|
|
+ kind = "var";
|
|
|
+ } else if (child.isVariableDeclaration()) {
|
|
|
+ kind = "block";
|
|
|
+ } else {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Object.keys(child.getOuterBindingIdentifiers()).forEach(name => {
|
|
|
+ bindingKindLookup.set(name, kind);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ const localMetadata = new Map();
|
|
|
+
|
|
|
+ const getLocalMetadata = idPath => {
|
|
|
+ const localName = idPath.node.name;
|
|
|
+ let metadata = localMetadata.get(localName);
|
|
|
+
|
|
|
+ if (!metadata) {
|
|
|
+ const kind = bindingKindLookup.get(localName);
|
|
|
+
|
|
|
+ if (kind === undefined) {
|
|
|
+ throw idPath.buildCodeFrameError(`Exporting local "${localName}", which is not declared.`);
|
|
|
+ }
|
|
|
+
|
|
|
+ metadata = {
|
|
|
+ names: [],
|
|
|
+ kind
|
|
|
+ };
|
|
|
+ localMetadata.set(localName, metadata);
|
|
|
+ }
|
|
|
+
|
|
|
+ return metadata;
|
|
|
+ };
|
|
|
+
|
|
|
+ programPath.get("body").forEach(child => {
|
|
|
+ if (child.isExportNamedDeclaration() && (loose || !child.node.source)) {
|
|
|
+ if (child.node.declaration) {
|
|
|
+ const declaration = child.get("declaration");
|
|
|
+ const ids = declaration.getOuterBindingIdentifierPaths();
|
|
|
+ Object.keys(ids).forEach(name => {
|
|
|
+ if (name === "__esModule") {
|
|
|
+ throw declaration.buildCodeFrameError('Illegal export "__esModule".');
|
|
|
+ }
|
|
|
+
|
|
|
+ getLocalMetadata(ids[name]).names.push(name);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ child.get("specifiers").forEach(spec => {
|
|
|
+ const local = spec.get("local");
|
|
|
+ const exported = spec.get("exported");
|
|
|
+
|
|
|
+ if (exported.node.name === "__esModule") {
|
|
|
+ throw exported.buildCodeFrameError('Illegal export "__esModule".');
|
|
|
+ }
|
|
|
+
|
|
|
+ getLocalMetadata(local).names.push(exported.node.name);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (child.isExportDefaultDeclaration()) {
|
|
|
+ const declaration = child.get("declaration");
|
|
|
+
|
|
|
+ if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
|
|
|
+ getLocalMetadata(declaration.get("id")).names.push("default");
|
|
|
+ } else {
|
|
|
+ throw declaration.buildCodeFrameError("Unexpected default expression export.");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return localMetadata;
|
|
|
+}
|
|
|
+
|
|
|
+function nameAnonymousExports(programPath) {
|
|
|
+ programPath.get("body").forEach(child => {
|
|
|
+ if (!child.isExportDefaultDeclaration()) return;
|
|
|
+ (0, _helperSplitExportDeclaration.default)(child);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function removeModuleDeclarations(programPath) {
|
|
|
+ programPath.get("body").forEach(child => {
|
|
|
+ if (child.isImportDeclaration()) {
|
|
|
+ child.remove();
|
|
|
+ } else if (child.isExportNamedDeclaration()) {
|
|
|
+ if (child.node.declaration) {
|
|
|
+ child.node.declaration._blockHoist = child.node._blockHoist;
|
|
|
+ child.replaceWith(child.node.declaration);
|
|
|
+ } else {
|
|
|
+ child.remove();
|
|
|
+ }
|
|
|
+ } else if (child.isExportDefaultDeclaration()) {
|
|
|
+ const declaration = child.get("declaration");
|
|
|
+
|
|
|
+ if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration()) {
|
|
|
+ declaration._blockHoist = child.node._blockHoist;
|
|
|
+ child.replaceWith(declaration);
|
|
|
+ } else {
|
|
|
+ throw declaration.buildCodeFrameError("Unexpected default expression export.");
|
|
|
+ }
|
|
|
+ } else if (child.isExportAllDeclaration()) {
|
|
|
+ child.remove();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|