'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.collapseNamedExports = collapseNamedExports;
exports.extendDefaultExportWithNamedExports = extendDefaultExportWithNamedExports;
require('source-map-support/register');
var _babelTypes = require('babel-types');
var t = _interopRequireWildcard(_babelTypes);
var _templates = require('./templates');
var _ast = 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)) 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, defaultExportDeclaration, namedExports, opts) {
namedExports = [...namedExports];
namedExports = filterOutExportsWhichAlreadyMatchPropsOnDefault(programNode, defaultExportDeclaration, namedExports);
if (!namedExports.length) {
return [];
} else Iif (opts.noExportExtend) {
return namedExports;
} else {
return extendDefaultExportWithNamedExports(programNode, defaultExportDeclaration, namedExports);
}
}
function extendDefaultExportWithNamedExports(programNode, defaultExportDeclaration, namedExports) {
namedExports = [...namedExports]; // Shallow clone for safe splicing
const variableName = defaultExportDeclaration.name || (0, _ast.getIdName)(defaultExportDeclaration);
if (!variableName) {
// Something anonymous
return namedExports;
} else Iif (namedExports.some(exp => exp.conflict)) {
return namedExports.conflicts.filter(exp => exp.conflict);
}
const id = t.isIdentifier(defaultExportDeclaration) ? defaultExportDeclaration : t.identifier(variableName);
for (const namedExport of namedExports) {
programNode.body.push((0, _templates.buildAssign)({
OBJECT: id,
NAME: namedExport.key,
VALUE: namedExport.value
}));
}
return [];
}
function filterOutExportsWhichAlreadyMatchPropsOnDefault(programNode, defaultExportDeclaration, namedExports) {
namedExports = [...namedExports]; // Shallow clone for safe splicing
const defaultObjectProperties = (0, _ast.findPropertiesOfNode)(programNode, defaultExportDeclaration);
// 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 _ref of defaultObjectProperties) {
const { key, value } = _ref;
if (t.isIdentifier(value)) {
//let matchingNamedExportIndex = -1
const matchingNamedExportIndex = namedExports.findIndex(namedExport => namedExport.key.name === key.name);
const matchingNamedExport = namedExports[matchingNamedExportIndex];
if (matchingNamedExport) {
if (value.name === matchingNamedExport.value.name) {
// Safe to ignore
namedExports.splice(matchingNamedExportIndex, 1);
} else {
namedExports.conflict = true;
}
}
}
}
}
return namedExports;
} |