Comparing version 0.7.0 to 0.8.0
@@ -17,5 +17,5 @@ const {walk} = require("estree-walker"); | ||
context.exportsNodes = []; | ||
context.nonNamespaceIds = new Set; | ||
context.needDefaultObject = false; | ||
context.importedProperties = new Map; | ||
context.shouldImportDefault = new Set; | ||
return {analyze}; | ||
@@ -45,3 +45,3 @@ | ||
declarator.node.shouldSkip = true; | ||
if (declarator.isSingleBinding && context.scope) { | ||
if (declarator.isSingleBinding) { | ||
context.scope.setMeta(declarator.left.name, "importedFrom", declarator.required.value); | ||
@@ -109,3 +109,3 @@ } else if (declarator.property) { | ||
const imported = getDynamicImport(node); | ||
if (!imported || context.scope && context.scope.has("require")) { | ||
if (!imported || context.scope.has("require")) { | ||
return; | ||
@@ -121,3 +121,3 @@ } | ||
const required = getRequireInfo(node); | ||
if (!required || context.scope && context.scope.has("require")) { | ||
if (!required || context.scope.has("require")) { | ||
return; | ||
@@ -136,3 +136,3 @@ } | ||
function analyzeExports(node, parent) { | ||
if (node.name !== "exports" || context.scope && context.scope.has("exports")) { | ||
if (node.name !== "exports" || context.scope.has("exports")) { | ||
return; | ||
@@ -148,3 +148,3 @@ } | ||
function analyzeModule(node) { | ||
if (node.name !== "module" || context.scope && context.scope.has("module")) { | ||
if (node.name !== "module" || context.scope.has("module")) { | ||
return; | ||
@@ -172,9 +172,8 @@ } | ||
function analyzeCallable(node) { | ||
if ( | ||
node.callee.type === "Identifier" && | ||
(!context.scope || context.scope.isRootVar(node.callee.name)) | ||
) { | ||
context.nonNamespaceIds.add(node.callee.name); | ||
} else if (node.callee.type === "CallExpression") { | ||
node.callee.callable = true; | ||
node.callee.callable = true; | ||
if (node.callee.type === "Identifier") { | ||
const importedFrom = context.scope.getMeta(node.callee.name, "importedFrom"); | ||
if (importedFrom) { | ||
context.shouldImportDefault.add(importedFrom); | ||
} | ||
} | ||
@@ -184,7 +183,7 @@ } | ||
function analyzeTag(node) { | ||
if ( | ||
node.tag.type === "Identifier" && | ||
(!context.scope || context.scope.isRootVar(node.tag.name)) | ||
) { | ||
context.nonNamespaceIds.add(node.tag.name); | ||
if (node.tag.type === "Identifier") { | ||
const importedFrom = context.scope.getMeta(node.tag.name, "importedFrom"); | ||
if (importedFrom) { | ||
context.shouldImportDefault.add(importedFrom); | ||
} | ||
} | ||
@@ -195,7 +194,7 @@ } | ||
const left = getLeftMost(node.left); | ||
if ( | ||
left.type === "Identifier" && | ||
(!context.scope || context.scope.isRootVar(left.name)) | ||
) { | ||
context.nonNamespaceIds.add(left.name); | ||
if (left.type === "Identifier") { | ||
const importedFrom = context.scope.getMeta(left.name, "importedFrom"); | ||
if (importedFrom) { | ||
context.shouldImportDefault.add(importedFrom); | ||
} | ||
} | ||
@@ -205,8 +204,7 @@ } | ||
function analyzeClass(node) { | ||
if ( | ||
node.superClass && | ||
node.superClass.type === "Identifier" && | ||
(!context.scope || context.scope.isRootVar(node.superClass.name)) | ||
) { | ||
context.nonNamespaceIds.add(node.superClass.name); | ||
if (node.superClass && node.superClass.type === "Identifier") { | ||
const importedFrom = context.scope.getMeta(node.superClass.name, "importedFrom"); | ||
if (importedFrom) { | ||
context.shouldImportDefault.add(importedFrom); | ||
} | ||
} | ||
@@ -216,3 +214,3 @@ } | ||
function analyzeRequireId(node) { | ||
if (node.name === "require" && (!context.scope || !context.scope.has(node.name))) { | ||
if (node.name === "require" && !context.scope.has(node.name)) { | ||
context.warn("Unconverted `require`", node.start); | ||
@@ -223,7 +221,5 @@ } | ||
function analyzeThisExpression() { | ||
if (context.scope) { | ||
const fnNode = context.scope.findFunction(); | ||
if (fnNode) { | ||
fnNode.containThis = true; | ||
} | ||
const fnNode = context.scope.findFunction(); | ||
if (fnNode) { | ||
fnNode.containThis = true; | ||
} | ||
@@ -233,4 +229,3 @@ } | ||
function analyzeMemberAccess(node) { | ||
if (!context.scope || | ||
node.type !== "MemberExpression" || | ||
if (node.type !== "MemberExpression" || | ||
node.object.type !== "Identifier" || | ||
@@ -257,5 +252,3 @@ node.property.type !== "Identifier") { | ||
context.assignment.enter(node); | ||
if (context.scope) { | ||
context.scope.enter(node); | ||
} | ||
context.scope.enter(node); | ||
context.walkContext = this; | ||
@@ -265,5 +258,3 @@ analyzeNode(node, parent); | ||
leave(node) { | ||
if (context.scope) { | ||
context.scope.leave(node); | ||
} | ||
context.scope.leave(node); | ||
} | ||
@@ -270,0 +261,0 @@ }); |
@@ -52,3 +52,3 @@ const { | ||
context.topLevel = createTopLevelAnalyzer(); | ||
context.scope = options.nested ? createScopeAnalyzer(context.ast) : null; | ||
context.scope = createScopeAnalyzer(context.ast, !options.nested); | ||
context.assignment = createAssignmentAnalyzer(); | ||
@@ -55,0 +55,0 @@ context.walkContext = null; |
const {pathToName} = require("./util"); | ||
function createImportWriter(context) { | ||
context.hoistRequires = new Map; | ||
context.declaredRequires = []; | ||
context.finalImportType = {}; | ||
return {write}; | ||
function write() { | ||
return Promise.all(context.requireNodes.map(node => { | ||
if (node.declarator) { | ||
return writeDeclare(node); | ||
} | ||
const allImports = new Map; | ||
for (const node of context.requireNodes) { | ||
if (node.dynamicImported) { | ||
return writeDynamicImport(node); | ||
writeDynamicImport(node); | ||
continue; | ||
} | ||
if (node.topRequired) { | ||
return writeTopRequire(node); | ||
writeTopRequire(node); | ||
continue; | ||
} | ||
// node.required | ||
return writeRequire(node); | ||
})) | ||
.then(() => | ||
Promise.all([ | ||
writeDeclaredRequires(), | ||
writeHoistRequires() // hoist requires has to be sorted before writing. | ||
]) | ||
); | ||
const requireInfo = node.required || node.declarator.required; | ||
let nodes = allImports.get(requireInfo.value); | ||
if (!nodes) { | ||
nodes = []; | ||
allImports.set(requireInfo.value, nodes); | ||
} | ||
nodes.push(node); | ||
} | ||
return Promise.all([...allImports.entries()].map(writeImport)); | ||
} | ||
function writeDeclare(node) { | ||
function writeImport([id, nodes]) { | ||
return Promise.resolve( | ||
node.declarator.isSingleBinding && context.nonNamespaceIds.has(node.declarator.left.name) || | ||
context.hasDefaultComment(node) || | ||
context.isImportPreferDefault(node.declarator.required.value) | ||
context.shouldImportDefault.has(id) || | ||
nodes.some(n => n.callable || context.hasDefaultComment(n)) || | ||
context.isImportPreferDefault(id) | ||
) | ||
.then(preferDefault => { | ||
node.preferDefault = preferDefault; | ||
if (!node.declarator.isSingleBinding && preferDefault) { | ||
node.declarator.node.declarator = null; | ||
return writeRequire(node); | ||
context.finalImportType[id] = preferDefault ? "default" : "named"; | ||
if (nodes.length === 1 && nodes[0].declarator && | ||
(!preferDefault || nodes[0].declarator.isSingleBinding) | ||
) { | ||
return writeDeclaredRequires(nodes[0], preferDefault); | ||
} | ||
context.declaredRequires.push(node); | ||
return writeHoistRequires(id, nodes, preferDefault); | ||
}); | ||
} | ||
function writeDeclaredRequires() { | ||
for (const node of context.declaredRequires) { | ||
if (node.declarator.isSingleBinding) { | ||
// const foo = require("foo") | ||
if (node.preferDefault) { | ||
// import default | ||
context.s.appendRight( | ||
node.declarator.left.start, | ||
"import " | ||
); | ||
} else { | ||
// import named | ||
context.s.appendRight( | ||
node.declarator.left.start, | ||
"import * as " | ||
); | ||
} | ||
} else if (node.declarator.property) { | ||
// const foo = require("foo").foo; | ||
function writeDeclaredRequires(node, preferDefault) { | ||
if (node.declarator.isSingleBinding) { | ||
// const foo = require("foo") | ||
if (preferDefault) { | ||
// import default | ||
context.s.appendRight( | ||
node.declarator.left.start, | ||
`import {${node.declarator.property.name !== node.declarator.left.name ? `${node.declarator.property.name} as ` : ""}` | ||
"import " | ||
); | ||
context.s.appendLeft(node.declarator.left.end, "}"); | ||
} else { | ||
// const {foo, bar} | ||
// import named | ||
context.s.appendRight( | ||
node.declarator.object.start, | ||
"import " | ||
node.declarator.left.start, | ||
"import * as " | ||
); | ||
// foo: bar | ||
for (const prop of node.declarator.object.properties) { | ||
if (prop.key.end < prop.value.start) { | ||
context.s.overwrite( | ||
prop.key.end, | ||
prop.value.start, | ||
" as " | ||
); | ||
} | ||
} | ||
} else if (node.declarator.property) { | ||
// const foo = require("foo").foo; | ||
context.s.appendRight( | ||
node.declarator.left.start, | ||
`import {${node.declarator.property.name !== node.declarator.left.name ? `${node.declarator.property.name} as ` : ""}` | ||
); | ||
context.s.appendLeft(node.declarator.left.end, "}"); | ||
} else { | ||
// const {foo, bar} | ||
context.s.appendRight( | ||
node.declarator.object.start, | ||
"import " | ||
); | ||
// foo: bar | ||
for (const prop of node.declarator.object.properties) { | ||
if (prop.key.end < prop.value.start) { | ||
context.s.overwrite( | ||
prop.key.end, | ||
prop.value.start, | ||
" as " | ||
); | ||
} | ||
} | ||
} | ||
context.s.overwrite( | ||
node.declarator.left.end, | ||
node.declarator.required.start, | ||
" from " | ||
); | ||
if (!node.declarator.prev) { | ||
// first declarator | ||
context.s.remove(node.declarator.declaration.start, node.declarator.node.start); | ||
} else { | ||
// prev is other stuff | ||
context.s.overwrite( | ||
node.declarator.left.end, | ||
node.declarator.required.start, | ||
" from " | ||
node.declarator.prev.end, | ||
node.declarator.node.start, | ||
";\n", | ||
{contentOnly: true} | ||
); | ||
if (!node.declarator.prev) { | ||
// first declarator | ||
context.s.remove(node.declarator.declaration.start, node.declarator.node.start); | ||
} else if (node.declarator.prev.declarator) { | ||
// prev is declarator | ||
// pass | ||
} else { | ||
// prev is other stuff | ||
} | ||
if (node.declarator.next && !node.declarator.next.declarator) { | ||
// next is not declarator | ||
context.s.overwrite( | ||
node.declarator.required.end, | ||
node.declarator.next.start, | ||
`;\n${node.declarator.declaration.kind} ` | ||
); | ||
} else { | ||
// remove right parenthesis | ||
context.s.remove(node.declarator.required.end, node.declarator.right.end); | ||
} | ||
} | ||
function writeHoistRequires(id, requires, preferDefault) { | ||
// find top-most require | ||
const name = `_require_${pathToName(id)}_`; | ||
context.s.appendLeft( | ||
requires[0].rootPos, | ||
`import ${preferDefault ? "" : "* as "}${name} from ${JSON.stringify(id)};\n` | ||
); | ||
for (const node of requires) { | ||
context.s.overwrite( | ||
node.start, | ||
node.end, | ||
name, | ||
{contentOnly: true} | ||
); | ||
if (node.declarator && node.declarator.prev && node.declarator.prev.declarator) { | ||
context.s.overwrite( | ||
node.declarator.prev.end, | ||
node.declarator.node.start, | ||
";\n" | ||
`;\n${node.declarator.declaration.kind} `, | ||
{contentOnly: true} | ||
); | ||
} | ||
if (!node.declarator.next) { | ||
// last declarator | ||
context.s.remove(node.declarator.required.end, node.declarator.right.end); | ||
} else if (node.declarator.next.declarator) { | ||
// next is declarator | ||
context.s.overwrite( | ||
node.declarator.required.end, | ||
node.declarator.next.declarator.left.start, | ||
";\n" | ||
); | ||
} else { | ||
context.s.overwrite( | ||
node.declarator.required.end, | ||
node.declarator.next.start, | ||
`;\n${node.declarator.declaration.kind} ` | ||
); | ||
} | ||
} | ||
} | ||
function writeRequire(node) { | ||
// put them into a id->node map | ||
let arr = context.hoistRequires.get(node.required.value); | ||
if (!arr) { | ||
arr = []; | ||
context.hoistRequires.set(node.required.value, arr); | ||
} | ||
arr.push(node); | ||
} | ||
function writeHoistRequires() { | ||
return Promise.all([...context.hoistRequires.entries()].map(([id, requires]) => { | ||
// find top-most require | ||
let topNode = requires[0]; | ||
for (let i = 1; i < requires.length; i++) { | ||
if (topNode.start > requires[i].start) { | ||
topNode = requires[i]; | ||
} | ||
} | ||
return Promise.resolve( | ||
requires.some(n => n.callable || n.preferDefault) || | ||
context.hasDefaultComment(topNode) || | ||
context.isImportPreferDefault(id) | ||
// initialize the promise here to benefit from `.callable` and `hasDefaultComment` short circuit. | ||
) | ||
.then(preferDefault => { | ||
const name = `_require_${pathToName(id)}_`; | ||
context.s.appendLeft( | ||
topNode.rootPos, | ||
`import ${preferDefault ? "" : "* as "}${name} from ${JSON.stringify(id)};\n` | ||
); | ||
for (const node of requires) { | ||
context.s.overwrite( | ||
node.start, | ||
node.end, | ||
name, | ||
{contentOnly: true} | ||
); | ||
} | ||
}); | ||
})); | ||
} | ||
function writeDynamicImport(node) { | ||
@@ -170,0 +142,0 @@ context.s.overwrite(node.dynamicImported.start, node.callee.end, "import"); |
@@ -31,7 +31,5 @@ const {attachScopes} = require("rollup-pluginutils"); | ||
function createScopeAnalyzer(ast) { | ||
const rootScope = attachScopes(ast, "scope"); | ||
rootScope._node = ast; | ||
let scope = rootScope; | ||
return {enter, leave, has, isRootVar, findFunction, setMeta, getMeta}; | ||
function createScopeAnalyzer(ast, dummy) { | ||
let scope = dummy ? {} : attachScopes(ast, "scope"); | ||
return {enter, leave, has, findFunction, setMeta, getMeta}; | ||
@@ -44,2 +42,3 @@ function enter(node) { | ||
} | ||
function leave(node) { | ||
@@ -50,8 +49,6 @@ if (node.scope) { | ||
} | ||
function has(name) { | ||
return scope.contains(name); | ||
return scope.contains && scope.contains(name); | ||
} | ||
function isRootVar(name) { | ||
return findDeclaredScope(name) === rootScope; | ||
} | ||
@@ -71,2 +68,5 @@ function findFunction() { | ||
function findDeclaredScope(name) { | ||
if (dummy) { | ||
return scope; | ||
} | ||
let declareScope = scope; | ||
@@ -73,0 +73,0 @@ while (declareScope) { |
{ | ||
"name": "cjs-es", | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"description": "Transform CommonJS module into ES module.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -316,2 +316,7 @@ cjs-es | ||
* 0.8.0 (Jun 13, 2019) | ||
- Refactor scope analyzer and import writer. | ||
- Add: `context.finalImportType`. | ||
* 0.7.0 (Jun 13, 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
444
54588
1350