diff --git a/CHANGELOG.md b/CHANGELOG.md index c0e512e..009ccd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # rollup changelog +## 0.25.1 + +* Throw error if namespace is called ([#446](https://github.com/rollup/rollup/issues/446)) +* Prevent shadowing bug in ES6 output ([#441](https://github.com/rollup/rollup/pull/441)) +* Prevent `var exports.foo` ([#426](https://github.com/rollup/rollup/issues/426)) +* Prevent double export of aliased symbols ([#438](https://github.com/rollup/rollup/issues/438)) +* Provide more informative error if Rollup is used in-browser without appropriate `resolveId`/`load` hooks ([#275](https://github.com/rollup/rollup/issues/275)) +* Use `_interopDefault` function to DRY out code with many external dependencies, in CommonJS output ([#458](https://github.com/rollup/rollup/pull/458)) + ## 0.25.0 * **breaking** Module order is determined according to spec, rather than in a way designed to prevent runtime errors. Rollup will warn if it detects runtime errors are likely ([#435](https://github.com/rollup/rollup/issues/435)) diff --git a/package.json b/package.json index 34e7ed8..1d8bdc0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rollup", - "version": "0.25.0", + "version": "0.25.1", "description": "Next-generation ES6 module bundler", "main": "dist/rollup.js", "jsnext:main": "src/rollup.js", diff --git a/src/Bundle.js b/src/Bundle.js index 5f9a8a9..754ad8f 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -63,7 +63,7 @@ export default class Bundle { this.onwarn = options.onwarn || makeOnwarn(); // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles - [ 'module', 'exports' ].forEach( global => this.assumedGlobals[ global ] = true ); + [ 'module', 'exports', '_interopDefault' ].forEach( global => this.assumedGlobals[ global ] = true ); } build () { @@ -360,7 +360,6 @@ export default class Bundle { }); } - return ordered; } } diff --git a/src/Declaration.js b/src/Declaration.js index 6b6996d..8c61bd2 100644 --- a/src/Declaration.js +++ b/src/Declaration.js @@ -135,6 +135,7 @@ export class SyntheticDefaultDeclaration { export class SyntheticNamespaceDeclaration { constructor ( module ) { + this.isNamespace = true; this.module = module; this.name = null; @@ -221,9 +222,10 @@ export class ExternalDeclaration { constructor ( module, name ) { this.module = module; this.name = name; + this.safeName = null; this.isExternal = true; - this.safeName = null; + this.isNamespace = name === '*'; } addAlias () { diff --git a/src/finalisers/cjs.js b/src/finalisers/cjs.js index 3a56ac9..c71f59d 100644 --- a/src/finalisers/cjs.js +++ b/src/finalisers/cjs.js @@ -3,17 +3,25 @@ import getExportBlock from './shared/getExportBlock.js'; export default function cjs ( bundle, magicString, { exportMode }, options ) { let intro = options.useStrict === false ? `` : `'use strict';\n\n`; + const hasDefaultImport = bundle.externalModules.some( mod => mod.declarations.default); + + if (hasDefaultImport) { + intro += `function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; }\n\n`; + } + // TODO handle empty imports, once they're supported const importBlock = bundle.externalModules .map( module => { - let requireStatement = `var ${module.name} = require('${module.id}');`; - if ( module.declarations.default ) { - requireStatement += '\n' + ( module.exportsNames ? `var ${module.name}__default = ` : `${module.name} = ` ) + - `'default' in ${module.name} ? ${module.name}['default'] : ${module.name};`; + if (module.exportsNames) { + return `var ${module.name} = require('${module.id}');` + + `\nvar ${module.name}__default = _interopDefault(${module.name});`; + } else { + return `var ${module.name} = _interopDefault(require('${module.id}'));`; + } + } else { + return `var ${module.name} = require('${module.id}');`; } - - return requireStatement; }) .join( '\n' ); diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 4753d1b..70c36fe 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -16,6 +16,8 @@ function addJsExtensionIfNecessary ( file ) { } export function resolveId ( importee, importer ) { + if ( typeof process === 'undefined' ) throw new Error( `It looks like you're using Rollup in a non-Node.js environment. This means you must supply a plugin with custom resolveId and load functions. See https://github.com/rollup/rollup/wiki/Plugins for more information` ); + // absolute paths are left untouched if ( isAbsolute( importee ) ) return addJsExtensionIfNecessary( importee ); diff --git a/src/utils/error.js b/src/utils/error.js new file mode 100644 index 0000000..5c0a703 --- /dev/null +++ b/src/utils/error.js @@ -0,0 +1,9 @@ +export default function error ( props ) { + const err = new Error( props.message ); + + Object.keys( props ).forEach( key => { + err[ key ] = props[ key ]; + }); + + throw err; +} diff --git a/src/utils/run.js b/src/utils/run.js index bf35a73..4470305 100644 --- a/src/utils/run.js +++ b/src/utils/run.js @@ -3,6 +3,8 @@ import modifierNodes, { isModifierNode } from '../ast/modifierNodes.js'; import isReference from '../ast/isReference.js'; import flatten from '../ast/flatten'; import pureFunctions from './pureFunctions.js'; +import getLocation from './getLocation.js'; +import error from './error.js'; function call ( callee, scope, statement, strongDependencies ) { while ( callee.type === 'ParenthesizedExpression' ) callee = callee.expression; @@ -11,7 +13,19 @@ function call ( callee, scope, statement, strongDependencies ) { const declaration = scope.findDeclaration( callee.name ) || statement.module.trace( callee.name ); - if ( declaration ) return declaration.run( strongDependencies ); + if ( declaration ) { + if ( declaration.isNamespace ) { + error({ + message: `Cannot call a namespace ('${callee.name}')`, + file: statement.module.id, + pos: callee.start, + loc: getLocation( statement.module.code, callee.start ) + }); + } + + return declaration.run( strongDependencies ); + } + return !pureFunctions[ callee.name ]; } diff --git a/test/form/external-imports-custom-names/_expected/cjs.js b/test/form/external-imports-custom-names/_expected/cjs.js index e83d17d..8f6506e 100644 --- a/test/form/external-imports-custom-names/_expected/cjs.js +++ b/test/form/external-imports-custom-names/_expected/cjs.js @@ -1,8 +1,9 @@ 'use strict'; -var $ = require('jquery'); -$ = 'default' in $ ? $['default'] : $; +function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; } + +var $ = _interopDefault(require('jquery')); $( function () { $( 'body' ).html( '