diff --git a/CHANGELOG.md b/CHANGELOG.md index 153e62b..d00d4f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # rollup changelog +## 0.8.3 + +* Correctly rename functions that have arguments with the same name ([#32](https://github.com/rollup/rollup/issues/32)) +* Ensure unused default exports are given a legal name ([#33](https://github.com/rollup/rollup/issues/33)) + +## 0.8.2 + +* Support `moduleId` and `moduleName` via CLI ([#24](https://github.com/rollup/rollup/issues/24)) + ## 0.8.1 * Anonymous functions that are exported as default are converted to named function declarations for correct hoisting, rather than being bound to functions ([#29](https://github.com/rollup/rollup/issues/29)) diff --git a/bin/runRollup.js b/bin/runRollup.js index 0ace1ee..748ec1a 100644 --- a/bin/runRollup.js +++ b/bin/runRollup.js @@ -39,7 +39,9 @@ function bundle ( options, method ) { }).then( function ( bundle ) { var generateOptions = { dest: options.output, - format: options.format + format: options.format, + moduleId: options.id, + moduleName: options.name }; if ( options.output ) { diff --git a/package.json b/package.json index d6c6f18..24ae592 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "0.8.1", + "version": "0.8.3", "description": "Next-generation ES6 module bundler", "main": "dist/rollup.js", "jsnext:main": "src/rollup.js", diff --git a/src/Module.js b/src/Module.js index bb2adce..96f20fd 100644 --- a/src/Module.js +++ b/src/Module.js @@ -13,6 +13,14 @@ import makeLegalIdentifier from './utils/makeLegalIdentifier'; const emptyArrayPromise = Promise.resolve([]); +function deconflict ( name, names ) { + while ( name in names ) { + name = `_${name}`; + } + + return name; +} + export default class Module { constructor ({ path, source, bundle }) { this.source = source; @@ -251,13 +259,9 @@ export default class Module { getCanonicalName ( localName ) { // Special case - if ( localName === 'default' && this.exports.default && this.exports.default.isModified ) { + if ( localName === 'default' && ( this.exports.default.isModified || !this.suggestedNames.default ) ) { let canonicalName = makeLegalIdentifier( this.path.replace( dirname( this.bundle.entryModule.path ) + '/', '' ).replace( /\.js$/, '' ) ); - while ( this.definitions[ canonicalName ] ) { - canonicalName = `_${canonicalName}`; - } - - return canonicalName; + return deconflict( canonicalName, this.definitions ); } if ( this.suggestedNames[ localName ] ) { @@ -472,11 +476,7 @@ export default class Module { // deconflict anonymous default exports with this module's definitions const shouldDeconflict = this.exports.default && this.exports.default.isAnonymous; - if ( shouldDeconflict ) { - while ( suggestion in this.definitions ) { - suggestion = `_${suggestion}`; - } - } + if ( shouldDeconflict ) suggestion = deconflict( suggestion, this.definitions ); if ( !this.suggestedNames[ defaultOrBatch ] ) { this.suggestedNames[ defaultOrBatch ] = makeLegalIdentifier( suggestion ); diff --git a/src/Statement.js b/src/Statement.js index 1ed2c46..9a1933f 100644 --- a/src/Statement.js +++ b/src/Statement.js @@ -315,15 +315,20 @@ export default class Statement { let newNames = blank(); let hasReplacements; - keys( names ).forEach( key => { - if ( !scope.declarations[ key ] ) { - newNames[ key ] = names[ key ]; + // special case = function foo ( foo ) {...} + if ( node.id && names[ node.id.name ] && scope.declarations[ node.id.name ] ) { + magicString.overwrite( node.id.start, node.id.end, names[ node.id.name ] ); + } + + keys( names ).forEach( name => { + if ( !scope.declarations[ name ] ) { + newNames[ name ] = names[ name ]; hasReplacements = true; } }); deshadowList.forEach( name => { - if ( ~scope.declarations[ name ] ) { + if ( ~scope.declarations[ name ] ) { // TODO is this right? no indexOf? newNames[ name ] = name + '$$'; // TODO better mechanism hasReplacements = true; } diff --git a/test/cli/module-name/_config.js b/test/cli/module-name/_config.js new file mode 100644 index 0000000..49c1fa4 --- /dev/null +++ b/test/cli/module-name/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'generates UMD export with correct moduleName', + command: 'rollup main.js --format umd --name myBundle' +} diff --git a/test/cli/module-name/_expected.js b/test/cli/module-name/_expected.js new file mode 100644 index 0000000..b5aa08a --- /dev/null +++ b/test/cli/module-name/_expected.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.myBundle = factory(); +}(this, function () { 'use strict'; + + var main = 42; + + return main; + +})); diff --git a/test/cli/module-name/main.js b/test/cli/module-name/main.js new file mode 100644 index 0000000..7a4e8a7 --- /dev/null +++ b/test/cli/module-name/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/function/rename-default-export/_config.js b/test/function/rename-default-export/_config.js new file mode 100644 index 0000000..24953e4 --- /dev/null +++ b/test/function/rename-default-export/_config.js @@ -0,0 +1,9 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'avoids SyntaxError with default token (#33)', + exports: function ( exports ) { + assert.equal( exports.foo, 42 ); + assert.equal( exports.bar, 42 ); + } +}; diff --git a/test/function/rename-default-export/bar.js b/test/function/rename-default-export/bar.js new file mode 100644 index 0000000..c435404 --- /dev/null +++ b/test/function/rename-default-export/bar.js @@ -0,0 +1,3 @@ +import { baz } from './baz'; + +export default baz; diff --git a/test/function/rename-default-export/baz.js b/test/function/rename-default-export/baz.js new file mode 100644 index 0000000..bc91852 --- /dev/null +++ b/test/function/rename-default-export/baz.js @@ -0,0 +1,5 @@ +function Baz () {} + +export var baz = 42; + +export default Baz( baz ); diff --git a/test/function/rename-default-export/foo.js b/test/function/rename-default-export/foo.js new file mode 100644 index 0000000..c435404 --- /dev/null +++ b/test/function/rename-default-export/foo.js @@ -0,0 +1,3 @@ +import { baz } from './baz'; + +export default baz; diff --git a/test/function/rename-default-export/main.js b/test/function/rename-default-export/main.js new file mode 100644 index 0000000..4725a8f --- /dev/null +++ b/test/function/rename-default-export/main.js @@ -0,0 +1,7 @@ +import foo from './foo'; +import bar from './bar'; + +export { + foo, + bar +}; diff --git a/test/function/renamed-arguments/_config.js b/test/function/renamed-arguments/_config.js new file mode 100644 index 0000000..2baa9bc --- /dev/null +++ b/test/function/renamed-arguments/_config.js @@ -0,0 +1,10 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'function arguments are renamed as appropriate (#32)', + exports: function ( exports ) { + var obj = {}; + assert.strictEqual( exports.foo(), 42 ); + assert.strictEqual( exports.bar( obj ), obj ); + } +}; diff --git a/test/function/renamed-arguments/bar.js b/test/function/renamed-arguments/bar.js new file mode 100644 index 0000000..dd7341d --- /dev/null +++ b/test/function/renamed-arguments/bar.js @@ -0,0 +1,5 @@ +function thing ( thing ) { + return thing; +} + +export default thing; diff --git a/test/function/renamed-arguments/foo.js b/test/function/renamed-arguments/foo.js new file mode 100644 index 0000000..77994ee --- /dev/null +++ b/test/function/renamed-arguments/foo.js @@ -0,0 +1,5 @@ +function thing () { + return 42; +} + +export default thing; diff --git a/test/function/renamed-arguments/main.js b/test/function/renamed-arguments/main.js new file mode 100644 index 0000000..4725a8f --- /dev/null +++ b/test/function/renamed-arguments/main.js @@ -0,0 +1,7 @@ +import foo from './foo'; +import bar from './bar'; + +export { + foo, + bar +}; diff --git a/test/test.js b/test/test.js index 28bf18f..02a92d3 100644 --- a/test/test.js +++ b/test/test.js @@ -295,6 +295,20 @@ describe( 'rollup', function () { unintendedError ? done( unintendedError ) : done(); } + + else if ( config.result ) { + try { + config.result( code ); + } catch ( err ) { + done( err ); + } + } + + else { + var expected = sander.readFileSync( '_expected.js' ).toString(); + assert.equal( code.trim(), expected.trim() ); + done(); + } }); }); });