Comparing version 0.6.4 to 0.7.0
@@ -32,3 +32,4 @@ const {createContext} = require("./lib/context"); | ||
map: options.sourceMap && context.s.generateMap({hires: true}), | ||
isTouched: true | ||
isTouched: true, | ||
context: context | ||
})); | ||
@@ -35,0 +36,0 @@ } |
@@ -19,12 +19,36 @@ const {walk} = require("estree-walker"); | ||
context.needDefaultObject = false; | ||
context.importedProperties = new Map; | ||
return {analyze}; | ||
function addImportedProperties(id, prop) { | ||
let names = context.importedProperties.get(id); | ||
if (!names) { | ||
names = []; | ||
context.importedProperties.set(id, names); | ||
} | ||
names.push(prop); | ||
} | ||
function analyzeDeclareImport(node) { | ||
const isTopLevel = context.topLevel.isTop(); | ||
const declarators = getDeclareImport(node); | ||
for (const declarator of declarators) { | ||
declarator.node.declarator = declarator; // we need this to work with siblings | ||
declarator.required.node.declarator = declarator; | ||
if (isTopLevel) { | ||
// don't define .declarator for nested requires? | ||
declarator.node.declarator = declarator; // we need this to work with siblings | ||
declarator.required.node.declarator = declarator; | ||
} | ||
declarator.required.node.required = declarator.required; | ||
declarator.required.node.rootPos = context.topLevel.get().start; | ||
context.requireNodes.push(declarator.required.node); | ||
declarator.node.shouldSkip = true; | ||
if (declarator.isSingleBinding && context.scope) { | ||
context.scope.setMeta(declarator.left.name, "importedFrom", declarator.required.value); | ||
} else if (declarator.property) { | ||
addImportedProperties(declarator.required.value, declarator.property.name); | ||
} else if (declarator.object) { | ||
for (const prop of declarator.object.properties) { | ||
addImportedProperties(declarator.required.value, prop.value.name); | ||
} | ||
} | ||
} | ||
@@ -35,3 +59,3 @@ } | ||
const declared = getDeclareExport(node); | ||
if (!declared) { | ||
if (!declared || !context.topLevel.isTop()) { | ||
return; | ||
@@ -198,2 +222,15 @@ } | ||
function analyzeMemberAccess(node) { | ||
if (!context.scope || | ||
node.type !== "MemberExpression" || | ||
node.object.type !== "Identifier" || | ||
node.property.type !== "Identifier") { | ||
return; | ||
} | ||
const importedFrom = context.scope.getMeta(node.object.name, "importedFrom"); | ||
if (importedFrom) { | ||
addImportedProperties(importedFrom, node.property.name); | ||
} | ||
} | ||
function analyze() { | ||
@@ -225,3 +262,3 @@ walk(context.ast, { | ||
function analyzeNode(node, parent) { | ||
if (node.type === "VariableDeclaration" && context.topLevel.isTop()) { | ||
if (node.type === "VariableDeclaration") { | ||
analyzeDeclareImport(node); | ||
@@ -233,3 +270,3 @@ analyzeDeclareExport(node); | ||
analyzeDynamicImport(node); | ||
analyzeRequire(node); | ||
analyzeRequire(node, parent); | ||
analyzeCallable(node); | ||
@@ -251,2 +288,3 @@ } else if (node.type === "Identifier" && isReference(node, parent)) { | ||
analyzeNestedExports(node); | ||
analyzeMemberAccess(node); | ||
} else if (node.type === "ThisExpression") { | ||
@@ -253,0 +291,0 @@ analyzeThisExpression(); |
function createExportWriter(context) { | ||
context.defaultExports = []; | ||
context.namedExports = new Map; | ||
context.objectExports = new Map; | ||
context.finalExportType = null; | ||
return {write}; | ||
@@ -12,3 +14,3 @@ | ||
if (context.moduleNodes.some(n => !n.exported && !n.nestedExports && !n.declared)) { | ||
return writeModuleWrapper(); | ||
return bindToSingleModule(); | ||
} | ||
@@ -19,2 +21,3 @@ for (const node of context.moduleNodes.concat(context.exportsNodes)) { | ||
node.nestedExports && node.nestedExports.name; | ||
// console.log(name); | ||
if (!name) { | ||
@@ -24,22 +27,46 @@ context.defaultExports.push(node); | ||
} | ||
let namedExport = context.namedExports.get(name); | ||
if (!namedExport) { | ||
namedExport = []; | ||
context.namedExports.set(name, namedExport); | ||
let nodes = context.namedExports.get(name); | ||
if (!nodes) { | ||
nodes = []; | ||
context.namedExports.set(name, nodes); | ||
} | ||
namedExport.push(node); | ||
nodes.push(node); | ||
} | ||
// single module.exports = ... | ||
// export object literal? | ||
if (isObjectMapExport()) { | ||
const node = context.defaultExports[0]; | ||
const {properties} = node.exported.object; | ||
let start = node.exported.leftMost.start; | ||
let nameInfo; | ||
for (let i = 0; i < properties.length; i++) { | ||
properties[i].rootPos = node.rootPos; | ||
nameInfo = { | ||
type: "objectProperty", | ||
start, | ||
node: properties[i], | ||
newLine: i > 0 | ||
}; | ||
const name = properties[i].key.name; | ||
let infos = context.objectExports.get(name); | ||
if (!infos) { | ||
infos = []; | ||
context.objectExports.set(name, infos); | ||
} | ||
infos.push(nameInfo); | ||
start = properties[i].value.end; | ||
} | ||
nameInfo.trim = [start, node.exported.statement.end]; | ||
} | ||
// sometimes it's impossible to use named exports | ||
if ( | ||
context.defaultExports.length > 1 || | ||
context.defaultExports.length === 1 && ( | ||
context.defaultExports[0].exported && context.defaultExports[0].exported.statement || | ||
context.defaultExports[0].declared | ||
) && !context.namedExports.size | ||
!isObjectMapExport() || | ||
context.hasDefaultComment(context.defaultExports[0]) | ||
) | ||
) { | ||
return writeModuleExport(); | ||
return bindToSingleExport(); | ||
} | ||
// export default | ||
if (context.defaultExports.length) { | ||
return writeDefaultExport(); | ||
} | ||
// export named | ||
@@ -49,9 +76,41 @@ return Promise.resolve(context.isExportPreferDefault()) | ||
if (preferDefault) { | ||
return writeDefaultExport(); | ||
return bindToSingleExport(); | ||
} | ||
return writeNamedExport(); | ||
return bindToNames(); | ||
}); | ||
} | ||
function writeModuleWrapper() { | ||
function isSingleLineExport() { | ||
if (context.defaultExports.length !== 1) { | ||
return false; | ||
} | ||
const node = context.defaultExports[0]; | ||
return node.exported && node.exported.statement || node.declared; | ||
} | ||
function isObjectMapExport() { | ||
if (!isSingleLineExport()) { | ||
return false; | ||
} | ||
const node = context.defaultExports[0]; | ||
if (node.declared || !node.exported.object) { | ||
// bind to a single reference | ||
return false; | ||
} | ||
const props = node.exported.object.properties; | ||
if (props.some(p => p.value.containThis)) { | ||
return false; | ||
} | ||
// some names are not exported in the object | ||
// FIXME: is this the correct behavior? | ||
const keys = new Set(props.map(p => p.key.name)); | ||
for (const k of context.namedExports.keys()) { | ||
if (!keys.has(k)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
function bindToSingleModule() { | ||
if ( | ||
@@ -93,23 +152,7 @@ context.moduleNodes.length && | ||
} | ||
context.finalExportType = "default"; | ||
} | ||
function writeModuleExport() { | ||
function bindToSingleLineExport() { | ||
const node = context.defaultExports[0]; | ||
if (node.exported && node.exported.object) { | ||
return Promise.resolve( | ||
context.hasDefaultComment(node) || | ||
node.exported.object.properties.some(p => p.value && p.value.containThis) || | ||
context.isExportPreferDefault() | ||
) | ||
.then(preferDefault => { | ||
if (preferDefault) { | ||
return writeModuleExportDefault(node); | ||
} | ||
return writeModuleExportObject(node); | ||
}); | ||
} | ||
return writeModuleExportDefault(node); | ||
} | ||
function writeModuleExportDefault(node) { | ||
if (node.declared) { | ||
@@ -157,24 +200,26 @@ // const foo = module.exports = ... | ||
} | ||
context.finalExportType = "default"; | ||
} | ||
function writeModuleExportObject(node) { | ||
const {properties} = node.exported.object; | ||
let start = node.exported.leftMost.start; | ||
for (let i = 0; i < properties.length; i++) { | ||
writeProperty( | ||
start, | ||
properties[i], | ||
i > 0 | ||
); | ||
start = properties[i].value.end; | ||
} | ||
// , ... } | ||
context.s.remove(start, node.exported.statement.end); | ||
} | ||
function writeProperty(start, property, newLine) { | ||
function writeProperty({ | ||
start, | ||
node: property, | ||
newLine, | ||
assignOnly = false, | ||
shareExport = false, | ||
kind = "const", | ||
trim | ||
}) { | ||
if (newLine) { | ||
context.s.appendLeft(start, "\n"); | ||
} | ||
if (property.value.type === "Identifier" || property.required) { | ||
const valuePrefix = property.method ? `function${property.generator ? "*" : ""} ` : ""; | ||
if (assignOnly) { | ||
context.s.overwrite( | ||
start, | ||
property.value.start, | ||
`_export_${property.key.name}_ = ${valuePrefix}`, | ||
{contentOnly: true} | ||
); | ||
} else if (!shareExport && (property.value.type === "Identifier" || property.required)) { | ||
// foo: bar | ||
@@ -193,7 +238,6 @@ context.s.overwrite( | ||
// foo: "not an identifier" | ||
const prefix = property.method ? `function${property.generator ? "*" : ""} ` : ""; | ||
context.s.overwrite( | ||
start, | ||
property.value.start, | ||
`const _export_${property.key.name}_ = ${prefix}`, | ||
`${kind} _export_${property.key.name}_ = ${valuePrefix}`, | ||
{contentOnly: true} | ||
@@ -207,45 +251,83 @@ ); | ||
context.s.appendLeft(property.value.end, ";"); | ||
if (trim) { | ||
context.s.remove(trim[0], trim[1]); | ||
} | ||
} | ||
function writeNamedExport() { | ||
function bindToNames() { | ||
// merge namedExports and objectExports | ||
const allExports = new Map; | ||
for (const [name, nodes] of context.namedExports) { | ||
if (!allExports.has(name)) { | ||
allExports.set(name, []); | ||
} | ||
allExports.get(name).push(...nodes.map(n => ({node: n, type: "name"}))); | ||
} | ||
for (const [name, infos] of context.objectExports) { | ||
if (!allExports.has(name)) { | ||
allExports.set(name, []); | ||
} | ||
allExports.get(name).push(...infos); | ||
} | ||
// names | ||
for (const [name, infos] of allExports) { | ||
let init = 0; | ||
let assignment = 0; | ||
let declared = 0; | ||
for (const node of nodes) { | ||
if (node.declared) { | ||
declared++; | ||
init++; | ||
assignment++; | ||
} else if (node.exported) { | ||
if (node.exported.statement) { | ||
for (const info of infos) { | ||
if (info.type === "name") { | ||
const node = info.node; | ||
if (node.declared) { | ||
declared++; | ||
init++; | ||
assignment++; | ||
} else if (node.exported) { | ||
if (node.exported.statement) { | ||
init++; | ||
} | ||
assignment++; | ||
} else if (node.nestedExports.node.isAssignment) { | ||
assignment++; | ||
} | ||
} else { | ||
init++; | ||
assignment++; | ||
} else if (node.nestedExports.node.isAssignment) { | ||
assignment++; | ||
} | ||
} | ||
if (init === 1 && (!declared || nodes.length === 1)) { | ||
for (const node of nodes) { | ||
if (node.declared) { | ||
writeNamedDeclare(node); | ||
} else if (node.exported && node.exported.statement) { | ||
writeNamedExports(node, assignment > 1 ? "let" : "const", nodes.length > 1); | ||
if (init === 1 && (!declared || infos.length === 1)) { | ||
for (const info of infos) { | ||
if (info.type === "name") { | ||
const node = info.node; | ||
if (node.declared) { | ||
writeNamedDeclare(node); | ||
} else if (node.exported && node.exported.statement) { | ||
writeNamedExports(node, assignment > 1 ? "let" : "const", infos.length > 1); | ||
} else { | ||
writeNestedExports(node); | ||
} | ||
} else { | ||
writeNestedExports(node); | ||
info.kind = assignment > 1 ? "let" : "const"; | ||
info.shareExport = infos.length > 1; | ||
writeProperty(info); | ||
} | ||
} | ||
} else { | ||
for (const node of nodes) { | ||
if (node.declared) { | ||
node.exported = node.declared.exported; | ||
for (const info of infos) { | ||
if (info.type === "name") { | ||
const node = info.node; | ||
if (node.declared) { | ||
node.exported = node.declared.exported; | ||
} | ||
writeNestedExports(node); | ||
} else { | ||
info.assignOnly = true; | ||
writeProperty(info); | ||
} | ||
writeNestedExports(node); | ||
} | ||
writeNamedInit(nodes.reduce((node, curr) => { | ||
return curr.rootPos < node.rootPos ? curr : node; | ||
}), name); | ||
const poses = infos.map(i => i.node.rootPos); | ||
writeNamedInit(Math.min(...poses), name); | ||
} | ||
} | ||
context.finalExportType = "named"; | ||
} | ||
@@ -322,3 +404,6 @@ | ||
function writeDefaultExport() { | ||
function bindToSingleExport() { | ||
if (isSingleLineExport() && !context.namedExports.size) { | ||
return bindToSingleLineExport(); | ||
} | ||
const nodes = context.moduleNodes.concat(context.exportsNodes); | ||
@@ -368,2 +453,3 @@ let init = 0; | ||
} | ||
context.finalExportType = "default"; | ||
} | ||
@@ -370,0 +456,0 @@ |
@@ -39,3 +39,2 @@ const {pathToName} = require("./util"); | ||
if (!node.declarator.isSingleBinding && preferDefault) { | ||
node.required = node.declarator.required; | ||
node.declarator.node.declarator = null; | ||
@@ -42,0 +41,0 @@ return writeRequire(node); |
@@ -35,3 +35,3 @@ const {attachScopes} = require("rollup-pluginutils"); | ||
let scope = rootScope; | ||
return {enter, leave, has, isRootVar, findFunction}; | ||
return {enter, leave, has, isRootVar, findFunction, setMeta, getMeta}; | ||
@@ -53,8 +53,3 @@ function enter(node) { | ||
function isRootVar(name) { | ||
// find declare scope | ||
let declareScope = scope; | ||
while (declareScope && !declareScope.declarations[name]) { | ||
declareScope = declareScope.parent; | ||
} | ||
return declareScope === rootScope; | ||
return findDeclaredScope(name) === rootScope; | ||
} | ||
@@ -73,2 +68,41 @@ | ||
} | ||
function findDeclaredScope(name) { | ||
let declareScope = scope; | ||
while (declareScope) { | ||
if (declareScope.declarations[name]) { | ||
break; | ||
} | ||
declareScope = declareScope.parent; | ||
} | ||
return declareScope; | ||
} | ||
function setMeta(varName, metaName, metaValue) { | ||
const declaredScope = findDeclaredScope(varName); | ||
if (!declaredScope) { | ||
throw new Error(`'${varName}' is not defined`); | ||
} | ||
if (!declaredScope._metas) { | ||
declaredScope._metas = {}; | ||
} | ||
if (!declaredScope._metas[varName]) { | ||
declaredScope._metas[varName] = {}; | ||
} | ||
declaredScope._metas[varName][metaName] = metaValue; | ||
} | ||
function getMeta(varName, metaName) { | ||
const declaredScope = findDeclaredScope(varName); | ||
if (!declaredScope) { | ||
return null; | ||
} | ||
if (!declaredScope._metas) { | ||
return null; | ||
} | ||
if (!declaredScope._metas[varName]) { | ||
return null; | ||
} | ||
return declaredScope._metas[varName][metaName]; | ||
} | ||
} | ||
@@ -221,4 +255,6 @@ | ||
if (dec.init.type === "CallExpression") { | ||
// ... = require("...") | ||
required = getRequireInfo(dec.init); | ||
} else if ( | ||
// ... = require("...").foo | ||
dec.init.type === "MemberExpression" && | ||
@@ -284,3 +320,3 @@ dec.init.object.type === "CallExpression" && | ||
for (const prop of node.properties) { | ||
if (prop.key.type !== "Identifier") { | ||
if (prop.key.type !== "Identifier" || prop.computed) { | ||
return; | ||
@@ -287,0 +323,0 @@ } |
{ | ||
"name": "cjs-es", | ||
"version": "0.6.4", | ||
"version": "0.7.0", | ||
"description": "Transform CommonJS module into ES module.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -316,2 +316,7 @@ cjs-es | ||
* 0.7.0 (Jun 13, 2019) | ||
- Add: collect import/exrpot information. | ||
- Change: export names when module exports object literal and uses nested exports. | ||
* 0.6.4 (Jun 6, 2019) | ||
@@ -318,0 +323,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55701
1388
439