Comparing version 0.5.0 to 0.6.0
@@ -8,2 +8,3 @@ const {walk} = require("estree-walker"); | ||
getExportInfo, | ||
getLeftMost, | ||
getRequireInfo, | ||
@@ -44,13 +45,21 @@ getNestedExports | ||
declared.exported.left.shouldSkip = true; | ||
declared.exported.assignExpression.isAnalyzed = true; | ||
} | ||
function analyzeAssignExportTop(node) { | ||
const exported = analyzeAssignExport(node.expression); | ||
if (exported) { | ||
exported.statement = node; | ||
node.expression.isAnalyzed = true; | ||
} | ||
} | ||
function analyzeAssignExport(node) { | ||
if (node.expression.type !== "AssignmentExpression") { | ||
if (node.type !== "AssignmentExpression" || node.isAnalyzed) { | ||
return; | ||
} | ||
const exported = getExportInfo(node.expression); | ||
const exported = getExportInfo(node); | ||
if (!exported) { | ||
return; | ||
} | ||
exported.statement = node; | ||
exported.leftMost.exported = exported; | ||
@@ -63,3 +72,10 @@ exported.leftMost.rootPos = context.topLevel.get().start; | ||
} | ||
node.expression.left.shouldSkip = true; | ||
node.left.shouldSkip = true; | ||
if (node.right.type === "AssignmentExpression") { | ||
getLeftMost(node.right.left).parentAssign = exported.leftMost; | ||
} | ||
if (exported.leftMost.parentAssign) { | ||
exported.leftMost.parentAssign.childAssign = exported.leftMost; | ||
} | ||
return exported; | ||
} | ||
@@ -111,3 +127,3 @@ | ||
const nestedExports = getNestedExports(node); | ||
if (!nestedExports || !nestedExports.name || context.scope.has(nestedExports.leftMost.name)) { | ||
if (!nestedExports || context.scope.has(nestedExports.leftMost.name)) { | ||
return; | ||
@@ -146,6 +162,3 @@ } | ||
function analyzeReassign(node) { | ||
let left = node.left; | ||
while (left.type === "MemberExpression") { | ||
left = left.object; | ||
} | ||
const left = getLeftMost(node.left); | ||
if ( | ||
@@ -205,3 +218,3 @@ left.type === "Identifier" && | ||
} else if (node.type === "ExpressionStatement" && context.topLevel.isTop()) { | ||
analyzeAssignExport(node); | ||
analyzeAssignExportTop(node); | ||
} else if (node.type === "CallExpression") { | ||
@@ -221,2 +234,3 @@ analyzeDynamicImport(node); | ||
analyzeReassign(node); | ||
analyzeAssignExport(node); | ||
} else if (node.type === "ClassExpression" || node.type === "ClassDeclaration") { | ||
@@ -223,0 +237,0 @@ analyzeClass(node); |
function createExportWriter(context) { | ||
context.hasNonTopLevelExport = false; | ||
context.defaultExports = []; | ||
context.namedExports = new Map; | ||
@@ -11,7 +9,4 @@ return {write}; | ||
} | ||
const defaultExports = []; | ||
for (const node of context.moduleNodes.concat(context.exportsNodes)) { | ||
if (!node.exported && !node.declared && !node.nestedExports) { | ||
context.hasNonTopLevelExport = true; | ||
continue; | ||
} | ||
const name = node.exported && node.exported.name || | ||
@@ -21,3 +16,3 @@ node.declared && node.declared.exported.name || | ||
if (!name) { | ||
context.defaultExports.push(node); | ||
defaultExports.push(node); | ||
continue; | ||
@@ -33,12 +28,16 @@ } | ||
if ( | ||
context.hasNonTopLevelExport || | ||
context.namedExports.size && context.defaultExports.length || | ||
context.defaultExports.length > 1 // but why? | ||
defaultExports.length === 1 && ( | ||
defaultExports[0].exported && defaultExports[0].exported.statement || | ||
defaultExports[0].declared | ||
) && !context.namedExports.size | ||
) { | ||
return writeModuleExport(); | ||
} | ||
if (defaultExports.length) { | ||
if (context.moduleNodes.every(n => n.exported || n.nestedExports)) { | ||
return writeNestedModule(); | ||
} | ||
// hoist | ||
return writeHoistExport(); | ||
} | ||
if (context.defaultExports.length) { | ||
return writeModuleExport(); | ||
} | ||
return Promise.resolve(context.isExportPreferDefault()) | ||
@@ -206,3 +205,5 @@ .then(preferDefault => { | ||
} else if (node.exported) { | ||
init++; | ||
if (node.exported.statement) { | ||
init++; | ||
} | ||
assignment++; | ||
@@ -217,3 +218,3 @@ } else if (node.nestedExports.node.isAssignment) { | ||
writeNamedDeclare(node); | ||
} else if (node.exported) { | ||
} else if (node.exported && node.exported.statement) { | ||
writeNamedExports(node, assignment > 1 ? "let" : "const", nodes.length > 1); | ||
@@ -227,5 +228,3 @@ } else { | ||
if (node.declared) { | ||
node.nestedExports = node.declared.exported; | ||
} else if (node.exported) { | ||
node.nestedExports = node.exported; | ||
node.exported = node.declared.exported; | ||
} | ||
@@ -294,6 +293,7 @@ writeNestedExports(node); | ||
function writeNestedExports(node) { | ||
const target = node.nestedExports || node.exported; | ||
context.s.overwrite( | ||
node.nestedExports.node.start, | ||
node.nestedExports.node.end, | ||
`_export_${node.nestedExports.name}_`, | ||
target.node.start, | ||
target.node.end, | ||
`_export_${target.name}_`, | ||
{contentOnly: true} | ||
@@ -309,4 +309,80 @@ ); | ||
} | ||
function writeNestedModule() { | ||
const nodes = context.moduleNodes.concat(context.exportsNodes); | ||
let init = 0; | ||
let assignment = 0; | ||
for (const node of nodes) { | ||
if (node.exported) { | ||
if (node.exported.name) { | ||
continue; | ||
} | ||
if (node.exported.statement) { | ||
init++; | ||
} | ||
if (!node.parentAssign) { | ||
assignment++; | ||
} | ||
} else if ( | ||
node.nestedExports && node.nestedExports.node.isAssignment || | ||
node.isAssignment | ||
) { | ||
assignment++; | ||
} | ||
} | ||
if (init === 1) { | ||
for (const node of nodes) { | ||
if (node.exported && node.exported.statement) { | ||
writeNestedModuleDeclare(node, assignment === 1 ? "const" : "let"); | ||
} else if (!node.parentAssign) { | ||
writeNestedModuleNode(node); | ||
} | ||
} | ||
} else { | ||
const topIndex = nodes.reduce( | ||
(r, n) => n.rootPos < r ? n.rootPos : r, | ||
Infinity | ||
); | ||
const kind = assignment ? "let" : "const"; | ||
const defaultValue = assignment ? "" : " = {}"; | ||
context.s.appendRight( | ||
topIndex, | ||
`${kind} _module_exports_${defaultValue};\nexport default _module_exports_;\n` | ||
); | ||
for (const node of nodes) { | ||
if (!node.parentAssign) { | ||
writeNestedModuleNode(node); | ||
} | ||
} | ||
} | ||
} | ||
function writeNestedModuleDeclare(node, kind) { | ||
const target = node.childAssign || node; | ||
context.s.overwrite( | ||
node.exported.node.start, | ||
target.exported.assignExpression.left.end, | ||
`${kind} _module_exports_`, | ||
{contentOnly: true} | ||
); | ||
context.s.appendLeft(node.exported.statement.end, "\nexport default _module_exports_;"); | ||
} | ||
function writeNestedModuleNode(node) { | ||
let start, end; | ||
if (node.childAssign) { | ||
start = node.start; | ||
end = node.childAssign.exported.assignExpression.left.end; | ||
} else { | ||
const exported = node.exported || node.nestedExports; | ||
const target = exported ? | ||
(exported.name ? exported.node.object : exported.node) : | ||
node; | ||
start = target.start; | ||
end = target.end; | ||
} | ||
context.s.overwrite(start, end, "_module_exports_", {contentOnly: true}); | ||
} | ||
} | ||
module.exports = {createExportWriter}; |
@@ -73,3 +73,5 @@ const {attachScopes} = require("rollup-pluginutils"); | ||
for (const el of node.elements) { | ||
el.isAssignment = true; | ||
if (el) { | ||
el.isAssignment = true; | ||
} | ||
} | ||
@@ -82,3 +84,10 @@ } | ||
// extract export info from member expression. | ||
if (node.type !== "MemberExpression") { | ||
if (node.type === "Identifier" && node.name === "exports") { | ||
return { | ||
node, | ||
leftMost: node, | ||
moduleExports: node | ||
}; | ||
} | ||
if (node.type !== "MemberExpression" || node.computed) { | ||
return; | ||
@@ -108,2 +117,3 @@ } | ||
name: isNamed ? node.property.name : undefined, | ||
moduleExports: isModule ? (isNamed ? node.object : node) : undefined, | ||
leftMost: isModule && isNamed ? node.object.object : node.object | ||
@@ -113,3 +123,11 @@ }; | ||
function getLeftMost(node) { | ||
while (node.type === "MemberExpression") { | ||
node = node.object; | ||
} | ||
return node; | ||
} | ||
function getExportInfo(node) { | ||
// extract export info from assignment expression | ||
const exportInfo = getNestedExports(node.left); | ||
@@ -121,2 +139,3 @@ if (!exportInfo) { | ||
node: exportInfo.node, | ||
assignExpression: node, | ||
name: exportInfo.name, | ||
@@ -313,2 +332,3 @@ leftMost: exportInfo.leftMost, | ||
getDynamicImport, | ||
getLeftMost, | ||
getNestedExports, | ||
@@ -315,0 +335,0 @@ getExportInfo, |
{ | ||
"name": "cjs-es", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"description": "Transform CommonJS module into ES module.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -18,3 +18,3 @@ cjs-es | ||
There are more samples under `test/cases` folder. | ||
There are more examples under `test/cases` folder. | ||
@@ -118,3 +118,3 @@ Usage | ||
Also note that if you set `exportStyle` to `default`, all named exports would be hoisted: | ||
Also note that if you set `exportStyle` to `default`, all named exports would be merged into a namespace object: | ||
@@ -164,6 +164,7 @@ ```js | ||
```js | ||
function test(key) { | ||
exports[key] = "foo"; | ||
if (foo) { | ||
module.exports = () => "foo"; | ||
} else { | ||
module.exports = () => "bar"; | ||
} | ||
exports.foo = "FOO"; | ||
``` | ||
@@ -174,17 +175,20 @@ | ||
```js | ||
let _exports_ = {}; | ||
function test(key) { | ||
_exports_[key] = "foo"; | ||
let _module_exports_; | ||
export default _module_exports_; | ||
if (foo) { | ||
_module_exports_ = () => "foo"; | ||
} else { | ||
_module_exports_ = () => "bar"; | ||
} | ||
_exports_.foo = "FOO"; | ||
export default _exports_; | ||
``` | ||
In some cases, there is no need to hoist the export statement: | ||
#### Named export | ||
```js | ||
if (foo) { | ||
exports.foo = () => "foo"; | ||
} | ||
function test() { | ||
return exports.foo(); | ||
exports.foo = () => "bar"; | ||
} | ||
exports.foo = () => "foo"; | ||
``` | ||
@@ -195,7 +199,10 @@ | ||
```js | ||
let _export_foo_; | ||
export {_export_foo_ as foo}; | ||
if (foo) { | ||
_export_foo_ = () => "foo"; | ||
} | ||
function test() { | ||
return _export_foo_(); | ||
_export_foo_ = () => "bar"; | ||
} | ||
const _export_foo_ = () => "foo"; | ||
export {_export_foo_ as foo}; | ||
``` | ||
@@ -222,2 +229,52 @@ | ||
Use `module.exports`/`exports` at the same time | ||
----------------------------------------------- | ||
It is not a good idea to put `exports` everywhere, but it is a common pattern: | ||
```js | ||
if (foo) { | ||
exports = module.exports = () => "foo"; | ||
} else { | ||
module.exports = exports = () => "bar"; | ||
} | ||
exports.OK = "OK"; | ||
console.log(module.exports); | ||
``` | ||
All `module.export` and `exports` would be converted into a single reference: | ||
```js | ||
let _module_exports_; | ||
export default _module_exports_; | ||
if (foo) { | ||
_module_exports_ = () => "foo"; | ||
} else { | ||
_module_exports_ = () => "bar"; | ||
} | ||
_module_exports_.OK = "OK"; | ||
console.log(_module_exports_); | ||
``` | ||
Passing `module` around | ||
----------------------- | ||
It will generate a module wrapper in this case: | ||
```js | ||
var define = require('amdefine')(module); | ||
define(() => {}); | ||
``` | ||
Result: | ||
```js | ||
const _module_ = {exports: {}}; | ||
import _require_amdefine_ from "amdefine"; | ||
var define = _require_amdefine_(_module_); | ||
define(() => {}); | ||
export default _module_.exports; | ||
``` | ||
API reference | ||
@@ -266,2 +323,8 @@ ------------- | ||
* 0.6.0 (Sep 19, 2018) | ||
- Fix: computed properties are detected as named exports. | ||
- Fix: TypeError when analyzing empty array elements: `[, foo]`. | ||
- **Breaking: convert `exports` and `module.exports` to a single reference.** | ||
* 0.5.0 (Jul 19, 2018) | ||
@@ -268,0 +331,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
48883
1197
416