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 138 139 140 141 142 143 144 | 1x 1x 1x 1x 1x 1x 1x 2x 19x 19x 4x 28x 4x 4x 11x 11x 11x 4x 4x 4x 11x 11x 24x 11x 11x 19x 19x 19x 17x 97x 2x 632x 95x 95x 72x 68x 4x 19x 72x 72x 72x 1x 71x 66x 66x 63x 3x 2x 5x 5x 3x 3x | "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.collapseNamedExports = collapseNamedExports; exports.getDefaultExportName = getDefaultExportName; require("source-map-support/register"); var _core = require("@babel/core"); var th = _interopRequireWildcard(require("./templates")); var ast = _interopRequireWildcard(require("./ast")); function _interopRequireWildcard(obj) { Eif (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } /** * Collapse named exports onto the default export so that the default export can be returned directly, * so that exports can be easily used by code that does not include an import interop. * This includes the following: * - Ignore named exports that already exist on the default export and which reference the same identifer. * - If possible, assign any remaining exports to the default export. * - This cannot be done if there is a naming conflict. * * In order to determine what properties the default export already has, the plugin will scan the * top level of the program to find any assignments, including Object.assign() and _extend() calls. * It does this recursively in the case of those method calls. * * If there are any named exports left, they get returned, so the main plugin can check the opts * and decide if an error should be thrown. */ function collapseNamedExports(programNode, defaultExport, namedExports, opts) { namedExports = filterOutExportsWhichAlreadyMatchPropsOnDefault(programNode, defaultExport, namedExports); if (!namedExports.length || opts.noExportExtend) { return { filteredExports: namedExports, newDefaultExportIdentifier: null }; } if (namedExports.some(exp => exp.conflict)) { return { filteredExports: namedExports, conflictingExports: namedExports.filter(exp => exp.conflict), newDefaultExportIdentifier: null }; } let exportVariableName = getDefaultExportName(defaultExport); let newDefaultExportIdentifier = null; if (!exportVariableName) { // Something anonymous (literal, anon function, etc...) programNode.body.push(th.buildTempExport({ VALUE: defaultExport })); newDefaultExportIdentifier = th.exportsIdentifier; exportVariableName = newDefaultExportIdentifier.name; } const id = _core.types.identifier(exportVariableName); for (const namedExport of namedExports) { programNode.body.push(th.buildAssign({ OBJECT: id, NAME: namedExport.key, VALUE: namedExport.value })); } return { filteredExports: [], conflictingExports: [], newDefaultExportIdentifier: newDefaultExportIdentifier }; } function getDefaultExportName(defaultExport) { return defaultExport.name || ast.getIdName(defaultExport); } function filterOutExportsWhichAlreadyMatchPropsOnDefault(programNode, defaultExport, namedExports) { namedExports = [...namedExports]; // Shallow clone for safe splicing const defaultObjectProperties = ast.findPropertiesOfNode(programNode, defaultExport); // Loop through the default object's props and see if it already has a matching definition of the named exports. // If the definition matches, we can ignore the named export. If the definition does not match, mark it as a conflict. if (defaultObjectProperties) { for (const defaultExportProperty of defaultObjectProperties) { if (!defaultExportProperty.key) { // i.e. SpreadProperty continue; } const matchingNamedExportIndex = namedExports.findIndex(namedExport => namedExport.key.name === defaultExportProperty.key.name); // get the index for splicing const matchingNamedExport = namedExports[matchingNamedExportIndex]; if (matchingNamedExport && !matchingNamedExport.conflict) { if (areSame(defaultExportProperty, matchingNamedExport)) { namedExports.splice(matchingNamedExportIndex, 1); } else { matchingNamedExport.conflict = true; } } } } return namedExports; } function areSame(defaultExportProperty, matchingNamedExport) { const defaultExportValue = defaultExportProperty.value; const declaration = matchingNamedExport.declaration; // i.e. 'export const a = 1' or 'export let a = b' if (!defaultExportValue) { // i.e. object method return false; // always a conflict } else if (_core.types.isIdentifier(defaultExportValue)) { const valueName = defaultExportValue.name; if (valueName === matchingNamedExport.value.name) { // Same identifier reference. Safe to ignore return true; } else if (declaration && _core.types.isIdentifier(declaration.init) && declaration.init.name === valueName) { // i.e. 'export let a = b', and default value for a is 'b'. return true; } } else Eif (_core.types.isLiteral(defaultExportValue)) { // i.e. { a: 1 } or { a: '1' } // See if the original declaration for the matching export was for the same literal if (_core.types.isLiteral(declaration.init) && declaration.init.value === defaultExportValue.value) { // i.e. 'export const a = 1' // Same literal. Safe to ignore return true; } } // Either a conflicting value or no value at all (i.e. method) return false; } |