diff --git a/.eslintrc b/.eslintrc
index 6e5fb1a..0f98dff 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,23 +1,23 @@
{
- "rules": {
- "indent": [ 2, "tab", { "SwitchCase": 1 } ],
- "quotes": [ 2, "single" ],
- "linebreak-style": [ 2, "unix" ],
- "semi": [ 2, "always" ],
- "space-after-keywords": [ 2, "always" ],
- "space-before-blocks": [ 2, "always" ],
- "space-before-function-paren": [ 2, "always" ],
- "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
- "no-cond-assign": [ 0 ]
- },
- "env": {
- "es6": true,
- "browser": true,
- "mocha": true,
- "node": true
- },
- "extends": "eslint:recommended",
- "ecmaFeatures": {
- "modules": true
- }
+ "root": true,
+ "rules": {
+ "indent": [ 2, "tab", { "SwitchCase": 1 } ],
+ "semi": [ 2, "always" ],
+ "keyword-spacing": [ 2, { "before": true, "after": true } ],
+ "space-before-blocks": [ 2, "always" ],
+ "space-before-function-paren": [ 2, "always" ],
+ "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
+ "no-cond-assign": [ 0 ]
+ },
+ "env": {
+ "es6": true,
+ "browser": true,
+ "mocha": true,
+ "node": true
+ },
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "ecmaVersion": 6,
+ "sourceType": "module"
+ }
}
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..4964429
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.js eol=lf
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 009ccd4..03d0f1a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,87 @@
# rollup changelog
+## 0.26.6
+
+* Deconflict named imports from external modules in ES bundles ([#659](https://github.com/rollup/rollup/issues/659))
+* Support `options.preferConst` to generate `const` declarations for exports rather than `var` declarations ([#653](https://github.com/rollup/rollup/issues/653))
+
+## 0.26.5
+
+* Preserve `debugger` statements ([#664](https://github.com/rollup/rollup/issues/664))
+* Allow `options.external` to be a function ([#522](https://github.com/rollup/rollup/issues/522))
+
+## 0.26.4
+
+* Prevent plugin-provided external IDs being normalised ([#630](https://github.com/rollup/rollup/issues/630), [#633](https://github.com/rollup/rollup/issues/633))
+* Throw if module exports/re-exports the same name twice, or has multiple default exports ([#679](https://github.com/rollup/rollup/issues/679))
+* Warn about `eval` security issue ([#675]((https://github.com/rollup/rollup/issues/675)))
+
+
+## 0.26.3
+
+* Ensure reference is not incorrectly marked as a reassignment ([#648](https://github.com/rollup/rollup/issues/648))
+
+## 0.26.2
+
+* Sanity check output of `load` hook ([#607](https://github.com/rollup/rollup/issues/607))
+* Correct scoping for ID class expressions ([#626](https://github.com/rollup/rollup/issues/626))
+* Warn if named and default exports are used together in auto mode ([#587](https://github.com/rollup/rollup/issues/587))
+* Allow variable initialisers to be rewritten if necessary ([#632](https://github.com/rollup/rollup/issues/632))
+* Prevent double `var` with no-treeshake option ([#639](https://github.com/rollup/rollup/pull/639))
+
+## 0.26.1
+
+* Add `treeshake: false`/`--no-treeshake` option for debugging ([#505](https://github.com/rollup/rollup/issues/505))
+* Update build process to use Bublé ([#620](https://github.com/rollup/rollup/pull/620))
+
+## 0.26.0
+
+* Add `noConflict`/`--no-conflict` option for UMD builds ([#580](https://github.com/rollup/rollup/pull/580))
+* Normalise relative external paths ([#591](https://github.com/rollup/rollup/pull/591))
+* Report files causing transform errors ([#609](https://github.com/rollup/rollup/pull/609))
+* Handle sourcemap segments with a single member ([#619](https://github.com/rollup/rollup/pull/619))
+* Update dependencies
+
+## 0.25.8
+
+* Unixize entry path ([#586](https://github.com/rollup/rollup/pull/586))
+
+## 0.25.7
+
+* Expand deshadowed shorthand properties ([#575](https://github.com/rollup/rollup/issues/575))
+* Allow external files to be non-existent ([#532](https://github.com/rollup/rollup/issues/532))
+
+## 0.25.6
+
+* Fix a regression introduced by #566 ([#569](https://github.com/rollup/rollup/issues/569))
+* Prune dead conditional expressions more carefully ([#567](https://github.com/rollup/rollup/issues/567))
+
+## 0.25.5
+
+* Make sure shorthand destructuring assignments don't break ([#528](https://github.com/rollup/rollup/issues/528))
+* Allow 'exports' key ([#542](https://github.com/rollup/rollup/issues/542))
+* Ensure `foo. bar` where `foo` is a namespace import is rewritten correctly ([#566](https://github.com/rollup/rollup/issues/566))
+* Fix an edge case for exported globals (e.g. `export { document }`) ([#562](https://github.com/rollup/rollup/issues/562))
+
+## 0.25.4
+
+* Fix misnamed exports of default imports in ES bundles ([#513](https://github.com/rollup/rollup/issues/513))
+* CLI: warn on missing config ([#515](https://github.com/rollup/rollup/pull/515))
+* Detect side-effects in non-top-level member expression assignment ([#476](https://github.com/rollup/rollup/issues/476))
+* Don't remove computed property class keys ([#504](https://github.com/rollup/rollup/issues/504))
+* Augment existing global object rather than replacing ([#493](https://github.com/rollup/rollup/issues/493))
+* Don't fail on `export {}`, warn instead ([#486](https://github.com/rollup/rollup/issues/486))
+
+## 0.25.3
+
+* Handle non-objects and `null` in `_interopDefault` ([#474](https://github.com/rollup/rollup/issues/474))
+
+## 0.25.2
+
+* Skip dead branches of a conditional expression (#[465](https://github.com/rollup/rollup/pull/465))
+* Allow globals to be exported ([#472](https://github.com/rollup/rollup/pull/472))
+* Ensure reassigned exports are exported ([#484](https://github.com/rollup/rollup/issues/484))
+
## 0.25.1
* Throw error if namespace is called ([#446](https://github.com/rollup/rollup/issues/446))
diff --git a/README.md b/README.md
index c2a6077..6e02e51 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
-
+
@@ -17,8 +17,8 @@
-
-
+
+
Settings passed to config file (see example)
+--no-conflict Generate a noConflict method for UMD globals
--intro Content to insert at top of bundle (inside wrapper)
--outro Content to insert at end of bundle (inside wrapper)
--banner Content to insert at top of bundle (outside wrapper)
diff --git a/bin/runRollup.js b/bin/runRollup.js
index 5b665ed..220c378 100644
--- a/bin/runRollup.js
+++ b/bin/runRollup.js
@@ -59,6 +59,9 @@ module.exports = function ( command ) {
try {
var options = require( path.resolve( config ) );
+ if ( Object.keys( options ).length === 0 ) {
+ handleError({ code: 'MISSING_CONFIG' });
+ }
} catch ( err ) {
handleError( err );
}
@@ -79,12 +82,14 @@ var equivalents = {
format: 'format',
globals: 'globals',
id: 'moduleId',
+ indent: 'indent',
input: 'entry',
intro: 'intro',
name: 'moduleName',
output: 'dest',
outro: 'outro',
- sourcemap: 'sourceMap'
+ sourcemap: 'sourceMap',
+ treeshake: 'treeshake'
};
function execute ( options, command ) {
@@ -110,10 +115,13 @@ function execute ( options, command ) {
options.onwarn = options.onwarn || log;
options.external = external;
- options.indent = command.indent !== false;
+ options.noConflict = command.conflict === false;
+ delete command.conflict;
+
+ // Use any options passed through the CLI as overrides.
Object.keys( equivalents ).forEach( function ( cliOption ) {
- if ( command[ cliOption ] ) {
+ if ( command.hasOwnProperty( cliOption ) ) {
options[ equivalents[ cliOption ] ] = command[ cliOption ];
}
});
diff --git a/package.json b/package.json
index 1d8bdc0..be499e9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rollup",
- "version": "0.25.1",
+ "version": "0.26.6",
"description": "Next-generation ES6 module bundler",
"main": "dist/rollup.js",
"jsnext:main": "src/rollup.js",
@@ -9,7 +9,7 @@
},
"scripts": {
"pretest": "npm run build",
- "test": "mocha",
+ "test": "mocha --compilers js:buble/register",
"pretest-coverage": "npm run build",
"test-coverage": "rm -rf coverage/* && istanbul cover --report json node_modules/.bin/_mocha -- -u exports -R spec test/test.js",
"posttest-coverage": "remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.json -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.lcov -t lcovonly -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped -t html -b dist",
@@ -40,22 +40,23 @@
},
"homepage": "https://github.com/rollup/rollup",
"devDependencies": {
- "acorn": "^2.6.4",
+ "acorn": "^3.1.0",
"babel-core": "^5.8.32",
+ "buble": "^0.6.4",
"codecov.io": "^0.1.6",
- "console-group": "^0.1.2",
+ "console-group": "^0.2.0",
"es6-promise": "^3.0.2",
- "eslint": "^1.7.1",
+ "eslint": "^2.9.0",
"estree-walker": "^0.2.0",
"istanbul": "^0.4.0",
"magic-string": "^0.10.1",
"mocha": "^2.3.3",
- "remap-istanbul": "^0.4.0",
- "rollup": "^0.20.2",
- "rollup-plugin-babel": "^1.0.0",
- "rollup-plugin-npm": "^1.0.0",
+ "remap-istanbul": "^0.5.1",
+ "rollup": "^0.26.2",
+ "rollup-plugin-buble": "^0.6.0",
+ "rollup-plugin-node-resolve": "^1.5.0",
"rollup-plugin-replace": "^1.0.1",
- "sander": "^0.4.0",
+ "sander": "^0.5.0",
"source-map": "^0.5.3",
"sourcemap-codec": "^1.2.1",
"uglify-js": "^2.6.1"
@@ -63,7 +64,7 @@
"dependencies": {
"chalk": "^1.1.1",
"minimist": "^1.2.0",
- "source-map-support": "^0.3.2"
+ "source-map-support": "^0.4.0"
},
"files": [
"src",
diff --git a/rollup.config.js b/rollup.config.js
index 090c17b..521d614 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -1,6 +1,6 @@
import { readFileSync } from 'fs';
-import babel from 'rollup-plugin-babel';
-import npm from 'rollup-plugin-npm';
+import buble from 'rollup-plugin-buble';
+import npm from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
var pkg = JSON.parse( readFileSync( 'package.json', 'utf-8' ) );
@@ -22,7 +22,7 @@ export default {
entry: 'src/rollup.js',
format: 'cjs',
plugins: [
- babel({
+ buble({
include: [ 'src/**', 'node_modules/acorn/**' ]
}),
diff --git a/src/Bundle.js b/src/Bundle.js
index 754ad8f..95c0d10 100644
--- a/src/Bundle.js
+++ b/src/Bundle.js
@@ -1,7 +1,6 @@
-import Promise from 'es6-promise/lib/es6-promise/promise.js';
import MagicString from 'magic-string';
import first from './utils/first.js';
-import { blank, keys } from './utils/object.js';
+import { blank, forOwn, keys } from './utils/object.js';
import Module from './Module.js';
import ExternalModule from './ExternalModule.js';
import finalisers from './finalisers/index.js';
@@ -10,12 +9,13 @@ import { load, makeOnwarn, resolveId } from './utils/defaults.js';
import getExportMode from './utils/getExportMode.js';
import getIndentString from './utils/getIndentString.js';
import { unixizePath } from './utils/normalizePlatform.js';
+import { mapSequence } from './utils/promise.js';
import transform from './utils/transform.js';
import transformBundle from './utils/transformBundle.js';
import collapseSourcemaps from './utils/collapseSourcemaps.js';
import SOURCEMAPPING_URL from './utils/sourceMappingURL.js';
import callIfFunction from './utils/callIfFunction.js';
-import { isRelative, resolve } from './utils/path.js';
+import { dirname, isRelative, isAbsolute, relative, resolve } from './utils/path.js';
export default class Bundle {
constructor ( options ) {
@@ -27,11 +27,14 @@ export default class Bundle {
}
});
- this.entry = options.entry;
+ this.entry = unixizePath( options.entry );
+ this.entryId = null;
this.entryModule = null;
+ this.treeshake = options.treeshake !== false;
+
this.resolveId = first(
- [ id => ~this.external.indexOf( id ) ? false : null ]
+ [ id => this.isExternal( id ) ? false : null ]
.concat( this.plugins.map( plugin => plugin.resolveId ).filter( Boolean ) )
.concat( resolveId )
);
@@ -59,11 +62,19 @@ export default class Bundle {
this.assumedGlobals = blank();
- this.external = ensureArray( options.external ).map( id => id.replace( /[\/\\]/g, '/' ) );
+ if ( typeof options.external === 'function' ) {
+ this.isExternal = options.external;
+ } else {
+ const ids = ensureArray( options.external ).map( id => id.replace( /[\/\\]/g, '/' ) );
+ this.isExternal = id => ids.indexOf( id ) !== -1;
+ }
+
this.onwarn = options.onwarn || makeOnwarn();
// TODO strictly speaking, this only applies with non-ES6, non-default-only bundles
[ 'module', 'exports', '_interopDefault' ].forEach( global => this.assumedGlobals[ global ] = true );
+
+ this.varOrConst = options.preferConst ? 'const' : 'var';
}
build () {
@@ -71,7 +82,10 @@ export default class Bundle {
// modules it imports, and import those, until we have all
// of the entry module's dependencies
return this.resolveId( this.entry, undefined )
- .then( id => this.fetchModule( id, undefined ) )
+ .then( id => {
+ this.entryId = id;
+ return this.fetchModule( id, undefined );
+ })
.then( entryModule => {
this.entryModule = entryModule;
@@ -98,7 +112,7 @@ export default class Bundle {
settled = true;
this.modules.forEach( module => {
- if ( module.run() ) settled = false;
+ if ( module.run( this.treeshake ) ) settled = false;
});
}
@@ -130,15 +144,14 @@ export default class Bundle {
// ensure we don't shadow named external imports, if
// we're creating an ES6 bundle
- keys( module.declarations ).forEach( name => {
- const declaration = module.declarations[ name ];
+ forOwn( module.declarations, ( declaration, name ) => {
declaration.setSafeName( getSafeName( name ) );
});
});
this.modules.forEach( module => {
- keys( module.declarations ).forEach( originalName => {
- const declaration = module.declarations[ originalName ];
+ forOwn( module.declarations, ( declaration, originalName ) => {
+ if ( declaration.isGlobal ) return;
if ( originalName === 'default' ) {
if ( declaration.original && !declaration.original.isReassigned ) return;
@@ -162,6 +175,12 @@ export default class Bundle {
msg += `: ${err.message}`;
throw new Error( msg );
})
+ .then( source => {
+ if ( typeof source === 'string' ) return source;
+ if ( source && typeof source === 'object' && source.code ) return source;
+
+ throw new Error( `Error loading ${id}: load hook should return a string, a { code, map } object, or nothing/null` );
+ })
.then( source => transform( source, id, this.transformers ) )
.then( source => {
const { code, originalCode, ast, sourceMapChain } = source;
@@ -176,23 +195,39 @@ export default class Bundle {
}
fetchAllDependencies ( module ) {
- const promises = module.sources.map( source => {
+ return mapSequence( module.sources, source => {
return this.resolveId( source, module.id )
.then( resolvedId => {
- // If the `resolvedId` is supposed to be external, make it so.
- const forcedExternal = resolvedId && ~this.external.indexOf( resolvedId.replace( /[\/\\]/g, '/' ) );
+ let externalName;
+ if ( resolvedId ) {
+ // If the `resolvedId` is supposed to be external, make it so.
+ externalName = resolvedId.replace( /[\/\\]/g, '/' );
+ } else if ( isRelative( source ) ) {
+ // This could be an external, relative dependency, based on the current module's parent dir.
+ externalName = resolve( module.id, '..', source );
+ }
+ const forcedExternal = externalName && this.isExternal( externalName );
if ( !resolvedId || forcedExternal ) {
+ let normalizedExternal = source;
+
if ( !forcedExternal ) {
if ( isRelative( source ) ) throw new Error( `Could not resolve ${source} from ${module.id}` );
- if ( !~this.external.indexOf( source ) ) this.onwarn( `Treating '${source}' as external dependency` );
+ if ( !this.isExternal( source ) ) this.onwarn( `Treating '${source}' as external dependency` );
+ } else if ( resolvedId ) {
+ if ( isRelative(resolvedId) || isAbsolute(resolvedId) ) {
+ // Try to deduce relative path from entry dir if resolvedId is defined as a relative path.
+ normalizedExternal = this.getPathRelativeToEntryDirname( resolvedId );
+ } else {
+ normalizedExternal = resolvedId;
+ }
}
- module.resolvedIds[ source ] = source;
+ module.resolvedIds[ source ] = normalizedExternal;
- if ( !this.moduleById[ source ] ) {
- const module = new ExternalModule( source );
+ if ( !this.moduleById[ normalizedExternal ] ) {
+ const module = new ExternalModule( normalizedExternal );
this.externalModules.push( module );
- this.moduleById[ source ] = module;
+ this.moduleById[ normalizedExternal ] = module;
}
}
@@ -206,15 +241,26 @@ export default class Bundle {
}
});
});
+ }
+
+ getPathRelativeToEntryDirname ( resolvedId ) {
+ // Get a path relative to the resolved entry directory
+ const entryDirname = dirname( this.entryId );
+ const relativeToEntry = relative( entryDirname, resolvedId );
+
+ if ( isRelative( relativeToEntry )) {
+ return relativeToEntry;
+ }
- return Promise.all( promises );
+ // The path is missing the `./` prefix
+ return `./${relativeToEntry}`;
}
render ( options = {} ) {
const format = options.format || 'es6';
// Determine export mode - 'default', 'named', 'none'
- const exportMode = getExportMode( this, options.exports );
+ const exportMode = getExportMode( this, options.exports, options.moduleName );
let magicString = new MagicString.Bundle({ separator: '\n\n' });
let usedModules = [];
diff --git a/src/Declaration.js b/src/Declaration.js
index 8c61bd2..0601606 100644
--- a/src/Declaration.js
+++ b/src/Declaration.js
@@ -1,7 +1,9 @@
-import { blank, keys } from './utils/object.js';
+import { blank, forOwn, keys } from './utils/object.js';
import run from './utils/run.js';
import { SyntheticReference } from './Reference.js';
+const use = alias => alias.use();
+
export default class Declaration {
constructor ( node, isParam, statement ) {
if ( node ) {
@@ -68,7 +70,7 @@ export default class Declaration {
this.isUsed = true;
if ( this.statement ) this.statement.mark();
- this.aliases.forEach( alias => alias.use() );
+ this.aliases.forEach( use );
}
}
@@ -129,7 +131,44 @@ export class SyntheticDefaultDeclaration {
if ( this.original ) this.original.use();
- this.aliases.forEach( alias => alias.use() );
+ this.aliases.forEach( use );
+ }
+}
+
+export class SyntheticGlobalDeclaration {
+ constructor ( name ) {
+ this.name = name;
+ this.isExternal = true;
+ this.isGlobal = true;
+ this.isReassigned = false;
+
+ this.aliases = [];
+
+ this.isUsed = false;
+ }
+
+ addAlias ( declaration ) {
+ this.aliases.push( declaration );
+ }
+
+ addReference ( reference ) {
+ reference.declaration = this;
+ if ( reference.isReassignment ) this.isReassigned = true;
+ }
+
+ render () {
+ return this.name;
+ }
+
+ run () {
+ return true;
+ }
+
+ use () {
+ if ( this.isUsed ) return;
+ this.isUsed = true;
+
+ this.aliases.forEach( use );
}
}
@@ -156,9 +195,9 @@ export class SyntheticNamespaceDeclaration {
// if we have e.g. `foo.bar`, we can optimise
// the reference by pointing directly to `bar`
if ( reference.parts.length ) {
- reference.name = reference.parts.shift();
-
- reference.end += reference.name.length + 1; // TODO this is brittle
+ const ref = reference.parts.shift();
+ reference.name = ref.name;
+ reference.end = ref.end;
const original = this.originals[ reference.name ];
@@ -182,8 +221,8 @@ export class SyntheticNamespaceDeclaration {
// add synthetic references, in case of chained
// namespace imports
- keys( this.originals ).forEach( name => {
- this.originals[ name ].addReference( new SyntheticReference( name ) );
+ forOwn( this.originals, ( original, name ) => {
+ original.addReference( new SyntheticReference( name ) );
});
}
@@ -202,7 +241,7 @@ export class SyntheticNamespaceDeclaration {
return `${indentString}${name}: ${original.render()}`;
});
- return `var ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`;
+ return `${this.module.bundle.varOrConst} ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`;
}
render () {
@@ -210,11 +249,8 @@ export class SyntheticNamespaceDeclaration {
}
use () {
- keys( this.originals ).forEach( name => {
- this.originals[ name ].use();
- });
-
- this.aliases.forEach( alias => alias.use() );
+ forOwn( this.originals, use );
+ this.aliases.forEach( use );
}
}
@@ -246,7 +282,7 @@ export class ExternalDeclaration {
}
if ( this.name === 'default' ) {
- return !es6 && this.module.exportsNames ?
+ return this.module.exportsNamespace || ( !es6 && this.module.exportsNames ) ?
`${this.module.name}__default` :
this.module.name;
}
diff --git a/src/ExternalModule.js b/src/ExternalModule.js
index 3113a5d..db9c062 100644
--- a/src/ExternalModule.js
+++ b/src/ExternalModule.js
@@ -27,9 +27,8 @@ export default class ExternalModule {
}
traceExport ( name ) {
- if ( name !== 'default' && name !== '*' ) {
- this.exportsNames = true;
- }
+ if ( name !== 'default' && name !== '*' ) this.exportsNames = true;
+ if ( name === '*' ) this.exportsNamespace = true;
return this.declarations[ name ] || (
this.declarations[ name ] = new ExternalDeclaration( this, name )
diff --git a/src/Module.js b/src/Module.js
index 0e42f77..175ecd5 100644
--- a/src/Module.js
+++ b/src/Module.js
@@ -7,7 +7,11 @@ import { basename, extname } from './utils/path.js';
import getLocation from './utils/getLocation.js';
import makeLegalIdentifier from './utils/makeLegalIdentifier.js';
import SOURCEMAPPING_URL from './utils/sourceMappingURL.js';
-import { SyntheticDefaultDeclaration, SyntheticNamespaceDeclaration } from './Declaration.js';
+import {
+ SyntheticDefaultDeclaration,
+ SyntheticGlobalDeclaration,
+ SyntheticNamespaceDeclaration
+} from './Declaration.js';
import { isFalsy, isTruthy } from './ast/conditions.js';
import { emptyBlockStatement } from './ast/create.js';
import extractNames from './ast/extractNames.js';
@@ -73,7 +77,13 @@ export default class Module {
else {
node.specifiers.forEach( specifier => {
- this.reexports[ specifier.exported.name ] = {
+ const name = specifier.exported.name;
+
+ if ( this.exports[ name ] || this.reexports[ name ] ) {
+ throw new Error( `A module cannot have multiple exports with the same name ('${name}')` );
+ }
+
+ this.reexports[ name ] = {
start: specifier.start,
source,
localName: specifier.local.name,
@@ -89,6 +99,11 @@ export default class Module {
else if ( node.type === 'ExportDefaultDeclaration' ) {
const identifier = ( node.declaration.id && node.declaration.id.name ) || node.declaration.name;
+ if ( this.exports.default ) {
+ // TODO indicate location
+ throw new Error( 'A module can only have one default export' );
+ }
+
this.exports.default = {
localName: 'default',
identifier
@@ -98,37 +113,41 @@ export default class Module {
this.declarations.default = new SyntheticDefaultDeclaration( node, statement, identifier || this.basename() );
}
- // export { foo, bar, baz }
// export var { foo, bar } = ...
// export var foo = 42;
// export var a = 1, b = 2, c = 3;
// export function foo () {}
- else if ( node.type === 'ExportNamedDeclaration' ) {
+ else if ( node.declaration ) {
+ let declaration = node.declaration;
+
+ if ( declaration.type === 'VariableDeclaration' ) {
+ declaration.declarations.forEach( decl => {
+ extractNames( decl.id ).forEach( localName => {
+ this.exports[ localName ] = { localName };
+ });
+ });
+ } else {
+ // export function foo () {}
+ const localName = declaration.id.name;
+ this.exports[ localName ] = { localName };
+ }
+ }
+
+ // export { foo, bar, baz }
+ else {
if ( node.specifiers.length ) {
- // export { foo, bar, baz }
node.specifiers.forEach( specifier => {
const localName = specifier.local.name;
const exportedName = specifier.exported.name;
+ if ( this.exports[ exportedName ] || this.reexports[ exportedName ] ) {
+ throw new Error( `A module cannot have multiple exports with the same name ('${exportedName}')` );
+ }
+
this.exports[ exportedName ] = { localName };
});
- }
-
- else {
- let declaration = node.declaration;
-
- if ( declaration.type === 'VariableDeclaration' ) {
- declaration.declarations.forEach( decl => {
- extractNames( decl.id ).forEach( localName => {
- this.exports[ localName ] = { localName };
- });
- });
- }
- else {
- // export function foo () {}
- const localName = declaration.id.name;
- this.exports[ localName ] = { localName };
- }
+ } else {
+ this.bundle.onwarn( `Module ${this.id} has an empty export declaration` );
}
}
}
@@ -185,7 +204,7 @@ export default class Module {
const declaration = this.declarations[ name ];
const statement = declaration.statement;
- if ( statement.node.type !== 'VariableDeclaration' ) return;
+ if ( !statement || statement.node.type !== 'VariableDeclaration' ) return;
const init = statement.node.declarations[0].init;
if ( !init || init.type === 'FunctionExpression' ) return;
@@ -314,6 +333,20 @@ export default class Module {
this.magicString.addSourcemapLocation( node.start );
this.magicString.addSourcemapLocation( node.end );
+ },
+
+ leave: ( node, parent, prop ) => {
+ // eliminate dead branches early
+ if ( node.type === 'ConditionalExpression' ) {
+ if ( isFalsy( node.test ) ) {
+ this.magicString.remove( node.start, node.alternate.start );
+ parent[prop] = node.alternate;
+ } else if ( isTruthy( node.test ) ) {
+ this.magicString.remove( node.start, node.consequent.start );
+ this.magicString.remove( node.consequent.end, node.end );
+ parent[prop] = node.consequent;
+ }
+ }
}
});
@@ -441,7 +474,7 @@ export default class Module {
if ( declaration.exportName && declaration.isReassigned ) { // `var foo = ...` becomes `exports.foo = ...`
magicString.remove( statement.start, declarator.init ? declarator.start : statement.next );
- return;
+ if ( !declarator.init ) return;
}
}
@@ -503,7 +536,8 @@ export default class Module {
if ( keys( toDeshadow ).length ) {
statement.references.forEach( reference => {
if ( !reference.rewritten && reference.name in toDeshadow ) {
- magicString.overwrite( reference.start, reference.end, toDeshadow[ reference.name ], true );
+ const replacement = toDeshadow[ reference.name ];
+ magicString.overwrite( reference.start, reference.end, reference.isShorthandProperty ? `${reference.name}: ${replacement}` : replacement, true );
}
});
}
@@ -558,7 +592,7 @@ export default class Module {
if ( statement.node.declaration.type === 'FunctionExpression' ) {
magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${defaultName}` );
} else {
- magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${defaultName} = ` );
+ magicString.overwrite( statement.node.start, statement.node.declaration.start, `${this.bundle.varOrConst} ${defaultName} = ` );
}
}
@@ -577,7 +611,23 @@ export default class Module {
return magicString.trim();
}
- run () {
+ /**
+ * Statically runs the module marking the top-level statements that must be
+ * included for the module to execute successfully.
+ *
+ * @param {boolean} treeshake - if we should tree-shake the module
+ * @return {boolean} marked - if any new statements were marked for inclusion
+ */
+ run ( treeshake ) {
+ if ( !treeshake ) {
+ this.statements.forEach( statement => {
+ if ( statement.isImportDeclaration || ( statement.isExportDeclaration && statement.node.isSynthetic ) ) return;
+
+ statement.mark();
+ });
+ return false;
+ }
+
let marked = false;
this.statements.forEach( statement => {
@@ -624,7 +674,13 @@ export default class Module {
const exportDeclaration = this.exports[ name ];
if ( exportDeclaration ) {
- return this.trace( exportDeclaration.localName );
+ const name = exportDeclaration.localName;
+ const declaration = this.trace( name );
+
+ if ( declaration ) return declaration;
+
+ this.bundle.assumedGlobals[ name ] = true;
+ return ( this.declarations[ name ] = new SyntheticGlobalDeclaration( name ) );
}
for ( let i = 0; i < this.exportAllModules.length; i += 1 ) {
diff --git a/src/Reference.js b/src/Reference.js
index e86ad9b..5c5c3e9 100644
--- a/src/Reference.js
+++ b/src/Reference.js
@@ -10,7 +10,7 @@ export class Reference {
let root = node;
while ( root.type === 'MemberExpression' ) {
- this.parts.unshift( root.property.name );
+ this.parts.unshift( root.property );
root = root.object;
}
diff --git a/src/Statement.js b/src/Statement.js
index 8bdd85c..3c00c36 100644
--- a/src/Statement.js
+++ b/src/Statement.js
@@ -44,10 +44,11 @@ export default class Statement {
let readDepth = 0;
walk( this.node, {
- enter ( node, parent ) {
+ enter ( node, parent, prop ) {
// warn about eval
if ( node.type === 'CallExpression' && node.callee.name === 'eval' && !scope.contains( 'eval' ) ) {
- module.bundle.onwarn( `Use of \`eval\` (in ${module.id}) is discouraged, as it may cause issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details` );
+ // TODO show location
+ module.bundle.onwarn( `Use of \`eval\` (in ${module.id}) is strongly discouraged, as it poses security risks and may cause issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details` );
}
// skip re-export declarations
@@ -61,42 +62,36 @@ export default class Statement {
if ( node._scope ) scope = node._scope;
if ( /Function/.test( node.type ) ) readDepth += 1;
- // special case – shorthand properties. because node.key === node.value,
- // we can't differentiate once we've descended into the node
- if ( node.type === 'Property' && node.shorthand && parent.type !== 'ObjectPattern' ) {
- const reference = new Reference( node.key, scope );
- reference.isShorthandProperty = true; // TODO feels a bit kludgy
- references.push( reference );
- return this.skip();
- }
-
let isReassignment;
if ( parent && isModifierNode( parent ) ) {
let subject = parent[ modifierNodes[ parent.type ] ];
- let depth = 0;
- while ( subject.type === 'MemberExpression' ) {
- subject = subject.object;
- depth += 1;
- }
+ if ( node === subject ) {
+ let depth = 0;
+
+ while ( subject.type === 'MemberExpression' ) {
+ subject = subject.object;
+ depth += 1;
+ }
- const importDeclaration = module.imports[ subject.name ];
+ const importDeclaration = module.imports[ subject.name ];
- if ( !scope.contains( subject.name ) && importDeclaration ) {
- const minDepth = importDeclaration.name === '*' ?
- 2 : // cannot do e.g. `namespace.foo = bar`
- 1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine
+ if ( !scope.contains( subject.name ) && importDeclaration ) {
+ const minDepth = importDeclaration.name === '*' ?
+ 2 : // cannot do e.g. `namespace.foo = bar`
+ 1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine
- if ( depth < minDepth ) {
- const err = new Error( `Illegal reassignment to import '${subject.name}'` );
- err.file = module.id;
- err.loc = getLocation( module.magicString.toString(), subject.start );
- throw err;
+ if ( depth < minDepth ) {
+ const err = new Error( `Illegal reassignment to import '${subject.name}'` );
+ err.file = module.id;
+ err.loc = getLocation( module.magicString.original, subject.start );
+ throw err;
+ }
}
- }
- isReassignment = !depth;
+ isReassignment = !depth;
+ }
}
if ( isReference( node, parent ) ) {
@@ -106,9 +101,19 @@ export default class Statement {
scope.parent :
scope;
+ const isShorthandProperty = parent.type === 'Property' && parent.shorthand;
+
+ // Since `node.key` can equal `node.value` for shorthand properties
+ // we must use the `prop` argument provided by `estree-walker` to determine
+ // if we're looking at the key or the value.
+ // If they are equal, we'll return to not create duplicate references.
+ if ( isShorthandProperty && parent.value === parent.key && prop === 'value' ) {
+ return;
+ }
+
const reference = new Reference( node, referenceScope, statement );
reference.isReassignment = isReassignment;
-
+ reference.isShorthandProperty = isShorthandProperty;
references.push( reference );
this.skip(); // don't descend from `foo.bar.baz` into `foo.bar`
diff --git a/src/ast/attachScopes.js b/src/ast/attachScopes.js
index 92798e8..51fc28a 100644
--- a/src/ast/attachScopes.js
+++ b/src/ast/attachScopes.js
@@ -29,7 +29,7 @@ export default function attachScopes ( statement ) {
let newScope;
// create new function scope
- if ( /Function/.test( node.type ) ) {
+ if ( /(Function|Class)/.test( node.type ) ) {
newScope = new Scope({
parent: scope,
block: false,
@@ -38,7 +38,7 @@ export default function attachScopes ( statement ) {
// named function expressions - the name is considered
// part of the function's scope
- if ( node.type === 'FunctionExpression' && node.id ) {
+ if ( /(Function|Class)Expression/.test( node.type ) && node.id ) {
newScope.addDeclaration( node, false, false );
}
}
diff --git a/src/ast/isReference.js b/src/ast/isReference.js
index 0c9a9d7..c2e6c89 100644
--- a/src/ast/isReference.js
+++ b/src/ast/isReference.js
@@ -10,7 +10,9 @@ export default function isReference ( node, parent ) {
if ( !parent ) return true;
// TODO is this right?
- if ( parent.type === 'MemberExpression' ) return parent.computed || node === parent.object;
+ if ( parent.type === 'MemberExpression' || parent.type === 'MethodDefinition' ) {
+ return parent.computed || node === parent.object;
+ }
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
if ( parent.type === 'Property' ) return parent.computed || node === parent.value;
diff --git a/src/finalisers/cjs.js b/src/finalisers/cjs.js
index c71f59d..f6302ff 100644
--- a/src/finalisers/cjs.js
+++ b/src/finalisers/cjs.js
@@ -3,28 +3,37 @@ 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);
+ let needsInterop = false;
- if (hasDefaultImport) {
- intro += `function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; }\n\n`;
- }
+ const varOrConst = bundle.varOrConst;
// TODO handle empty imports, once they're supported
const importBlock = bundle.externalModules
.map( module => {
if ( module.declarations.default ) {
- 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}'));`;
+ if ( module.exportsNamespace ) {
+ return `${varOrConst} ${module.name} = require('${module.id}');` +
+ `\n${varOrConst} ${module.name}__default = ${module.name}['default'];`;
+ }
+
+ needsInterop = true;
+
+ if ( module.exportsNames ) {
+ return `${varOrConst} ${module.name} = require('${module.id}');` +
+ `\n${varOrConst} ${module.name}__default = _interopDefault(${module.name});`;
}
+
+ return `${varOrConst} ${module.name} = _interopDefault(require('${module.id}'));`;
} else {
- return `var ${module.name} = require('${module.id}');`;
+ return `${varOrConst} ${module.name} = require('${module.id}');`;
}
})
.join( '\n' );
+ if ( needsInterop ) {
+ intro += `function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\n`;
+ }
+
if ( importBlock ) {
intro += importBlock + '\n\n';
}
diff --git a/src/finalisers/es6.js b/src/finalisers/es6.js
index 7de4c74..bd3f93f 100644
--- a/src/finalisers/es6.js
+++ b/src/finalisers/es6.js
@@ -10,10 +10,20 @@ export default function es6 ( bundle, magicString ) {
const specifiers = [];
const specifiersList = [specifiers];
const importedNames = keys( module.declarations )
- .filter( name => name !== '*' && name !== 'default' );
+ .filter( name => name !== '*' && name !== 'default' )
+ .map( name => {
+ const declaration = module.declarations[ name ];
+
+ if ( declaration.name === declaration.safeName ) return declaration.name;
+ return `${declaration.name} as ${declaration.safeName}`;
+ });
if ( module.declarations.default ) {
- specifiers.push( module.name );
+ if ( module.exportsNamespace ) {
+ specifiersList.push([ `${module.name}__default` ]);
+ } else {
+ specifiers.push( module.name );
+ }
}
const namespaceSpecifier = module.declarations['*'] ? `* as ${module.name}` : null;
@@ -47,10 +57,11 @@ export default function es6 ( bundle, magicString ) {
const specifiers = module.getExports().filter( notDefault ).map( name => {
const declaration = module.traceExport( name );
+ const rendered = declaration.render( true );
- return declaration.name === name ?
+ return rendered === name ?
name :
- `${declaration.name} as ${name}`;
+ `${rendered} as ${name}`;
});
let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : '';
diff --git a/src/finalisers/iife.js b/src/finalisers/iife.js
index 95c6d65..adb7019 100644
--- a/src/finalisers/iife.js
+++ b/src/finalisers/iife.js
@@ -31,7 +31,7 @@ export default function iife ( bundle, magicString, { exportMode, indentString }
}
if ( exportMode === 'named' ) {
- dependencies.unshift( `(this.${name} = {})` );
+ dependencies.unshift( `(this.${name} = this.${name} || {})` );
args.unshift( 'exports' );
}
@@ -41,7 +41,7 @@ export default function iife ( bundle, magicString, { exportMode, indentString }
let outro = `\n\n}(${dependencies}));`;
if ( exportMode === 'default' ) {
- intro = ( isNamespaced ? `this.` : `var ` ) + `${name} = ${intro}`;
+ intro = ( isNamespaced ? `this.` : `${bundle.varOrConst} ` ) + `${name} = ${intro}`;
}
if ( isNamespaced ) {
diff --git a/src/finalisers/shared/getInteropBlock.js b/src/finalisers/shared/getInteropBlock.js
index e0e2617..67a26d7 100644
--- a/src/finalisers/shared/getInteropBlock.js
+++ b/src/finalisers/shared/getInteropBlock.js
@@ -1,11 +1,17 @@
export default function getInteropBlock ( bundle ) {
return bundle.externalModules
.map( module => {
- return module.declarations.default ?
- ( module.exportsNames ?
- `var ${module.name}__default = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};` :
- `${module.name} = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};` ) :
- null;
+ if ( !module.declarations.default ) return null;
+
+ if ( module.exportsNamespace ) {
+ return `${bundle.varOrConst} ${module.name}__default = ${module.name}['default'];`;
+ }
+
+ if ( module.exportsNames ) {
+ return `${bundle.varOrConst} ${module.name}__default = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};`;
+ }
+
+ return `${module.name} = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};`;
})
.filter( Boolean )
.join( '\n' );
diff --git a/src/finalisers/umd.js b/src/finalisers/umd.js
index 3e8e813..0ec344e 100644
--- a/src/finalisers/umd.js
+++ b/src/finalisers/umd.js
@@ -31,7 +31,7 @@ export default function umd ( bundle, magicString, { exportMode, indentString },
if ( exportMode === 'named' ) {
amdDeps.unshift( `'exports'` );
cjsDeps.unshift( `exports` );
- globalDeps.unshift( `(${setupNamespace(options.moduleName)} = {})` );
+ globalDeps.unshift( `(${setupNamespace(options.moduleName)} = global.${options.moduleName} || {})` );
args.unshift( 'exports' );
}
@@ -45,11 +45,19 @@ export default function umd ( bundle, magicString, { exportMode, indentString },
const useStrict = options.useStrict !== false ? ` 'use strict';` : ``;
+ const globalExport = options.noConflict === true ?
+ `(function() {
+ var current = global.${options.moduleName};
+ var exports = factory(${globalDeps});
+ global.${options.moduleName} = exports;
+ exports.noConflict = function() { global.${options.moduleName} = current; return exports; };
+ })()` : `(${defaultExport}factory(${globalDeps}))`;
+
const intro =
`(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? ${cjsExport}factory(${cjsDeps.join( ', ' )}) :
typeof define === 'function' && define.amd ? define(${amdParams}factory) :
- (${defaultExport}factory(${globalDeps}));
+ ${globalExport};
}(this, function (${args}) {${useStrict}
`.replace( /^\t\t/gm, '' ).replace( /^\t/gm, magicString.getIndentString() );
diff --git a/src/rollup.js b/src/rollup.js
index d509bd2..77a97bd 100644
--- a/src/rollup.js
+++ b/src/rollup.js
@@ -12,6 +12,7 @@ const ALLOWED_KEYS = [
'banner',
'dest',
'entry',
+ 'exports',
'external',
'footer',
'format',
@@ -20,10 +21,14 @@ const ALLOWED_KEYS = [
'intro',
'moduleId',
'moduleName',
+ 'noConflict',
'onwarn',
'outro',
'plugins',
- 'sourceMap'
+ 'preferConst',
+ 'sourceMap',
+ 'treeshake',
+ 'useStrict'
];
export function rollup ( options ) {
diff --git a/src/utils/collapseSourcemaps.js b/src/utils/collapseSourcemaps.js
index 36a46c8..ff86eaf 100644
--- a/src/utils/collapseSourcemaps.js
+++ b/src/utils/collapseSourcemaps.js
@@ -1,25 +1,25 @@
import { encode, decode } from 'sourcemap-codec';
-function Source ( index ) {
- this.isOriginal = true;
- this.index = index;
-}
+class Source {
+ constructor ( index ) {
+ this.isOriginal = true;
+ this.index = index;
+ }
-Source.prototype = {
traceSegment ( line, column, name ) {
return { line, column, name, index: this.index };
}
-};
+}
-function Link ( map, sources ) {
- if ( !map ) throw new Error( 'Cannot generate a sourcemap if non-sourcemap-generating transformers are used' );
+class Link {
+ constructor ( map, sources ) {
+ if ( !map ) throw new Error( 'Cannot generate a sourcemap if non-sourcemap-generating transformers are used' );
- this.sources = sources;
- this.names = map.names;
- this.mappings = decode( map.mappings );
-}
+ this.sources = sources;
+ this.names = map.names;
+ this.mappings = decode( map.mappings );
+ }
-Link.prototype = { // TODO bring into line with others post-https://github.com/rollup/rollup/pull/386
traceMappings () {
let names = [];
@@ -57,7 +57,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
});
return { names, mappings };
- },
+ }
traceSegment ( line, column, name ) {
const segments = this.mappings[ line ];
@@ -71,8 +71,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
if ( segment[0] === column ) {
const source = this.sources[ segment[1] ];
-
- if ( !source ) throw new Error( 'Bad sourcemap' );
+ if ( !source ) return null;
return source.traceSegment( segment[2], segment[3], this.names[ segment[4] ] || name );
}
@@ -80,7 +79,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
return null;
}
-};
+}
export default function collapseSourcemaps ( map, modules, bundleSourcemapChain ) {
const sources = modules.map( ( module, i ) => {
diff --git a/src/utils/getExportMode.js b/src/utils/getExportMode.js
index ed52c6a..f37ff1e 100644
--- a/src/utils/getExportMode.js
+++ b/src/utils/getExportMode.js
@@ -4,7 +4,7 @@ function badExports ( option, keys ) {
throw new Error( `'${option}' was specified for options.exports, but entry module has following exports: ${keys.join(', ')}` );
}
-export default function getExportMode ( bundle, exportMode ) {
+export default function getExportMode ( bundle, exportMode, moduleName ) {
const exportKeys = keys( bundle.entryModule.exports )
.concat( keys( bundle.entryModule.reexports ) )
.concat( bundle.entryModule.exportAllSources ); // not keys, but makes our job easier this way
@@ -23,6 +23,9 @@ export default function getExportMode ( bundle, exportMode ) {
} else if ( exportKeys.length === 1 && exportKeys[0] === 'default' ) {
exportMode = 'default';
} else {
+ if ( bundle.entryModule.exports.default ) {
+ bundle.onwarn( `Using named and default exports together. Consumers of your bundle will have to use ${moduleName || 'bundle'}['default'] to access the default export, which may not be what you want. Use \`exports: 'named'\` to disable this warning. See https://github.com/rollup/rollup/wiki/JavaScript-API#exports for more information` );
+ }
exportMode = 'named';
}
}
diff --git a/src/utils/object.js b/src/utils/object.js
index a11ea25..b4e1ff1 100644
--- a/src/utils/object.js
+++ b/src/utils/object.js
@@ -1,5 +1,9 @@
-export const keys = Object.keys;
+export const { keys } = Object;
export function blank () {
return Object.create( null );
}
+
+export function forOwn ( object, func ) {
+ Object.keys( object ).forEach( key => func( object[ key ], key ) );
+}
diff --git a/src/utils/promise.js b/src/utils/promise.js
new file mode 100644
index 0000000..1730de8
--- /dev/null
+++ b/src/utils/promise.js
@@ -0,0 +1,16 @@
+import Promise from 'es6-promise/lib/es6-promise/promise.js';
+
+export function mapSequence ( array, fn ) {
+ let results = [];
+ let promise = Promise.resolve();
+
+ function next ( member, i ) {
+ return fn( member ).then( value => results[i] = value );
+ }
+
+ for ( let i = 0; i < array.length; i += 1 ) {
+ promise = promise.then( () => next( array[i], i ) );
+ }
+
+ return promise.then( () => results );
+}
diff --git a/src/utils/run.js b/src/utils/run.js
index 4470305..3e91d63 100644
--- a/src/utils/run.js
+++ b/src/utils/run.js
@@ -75,6 +75,10 @@ export default function run ( node, scope, statement, strongDependencies, force
}
}
+ else if ( node.type === 'DebuggerStatement' ) {
+ hasSideEffect = true;
+ }
+
else if ( node.type === 'ThrowStatement' ) {
// we only care about errors thrown at the top level, otherwise
// any function with error checking gets included if called
@@ -95,6 +99,8 @@ export default function run ( node, scope, statement, strongDependencies, force
if ( declaration ) {
if ( declaration.isParam ) hasSideEffect = true;
+ } else if ( !scope.isTopLevel ) {
+ hasSideEffect = true;
} else {
declaration = statement.module.trace( subject.name );
diff --git a/src/utils/transform.js b/src/utils/transform.js
index 5ddde28..b401370 100644
--- a/src/utils/transform.js
+++ b/src/utils/transform.js
@@ -39,5 +39,10 @@ export default function transform ( source, id, transformers ) {
}, Promise.resolve( source.code ) )
- .then( code => ({ code, originalCode, ast, sourceMapChain }) );
+ .then( code => ({ code, originalCode, ast, sourceMapChain }) )
+ .catch( err => {
+ err.id = id;
+ err.message = `Error loading ${id}: ${err.message}`;
+ throw err;
+ });
}
diff --git a/.babelrc b/test/.babelrc
similarity index 100%
rename from .babelrc
rename to test/.babelrc
diff --git a/test/cli/config-missing-export/_config.js b/test/cli/config-missing-export/_config.js
new file mode 100644
index 0000000..051f155
--- /dev/null
+++ b/test/cli/config-missing-export/_config.js
@@ -0,0 +1,9 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'throws error if config does not export an object',
+ command: 'rollup -c',
+ error: function ( err ) {
+ assert.ok( /Config file must export an options object/.test( err.message ) );
+ }
+};
diff --git a/test/cli/config-missing-export/rollup.config.js b/test/cli/config-missing-export/rollup.config.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/cli/no-treeshake/_config.js b/test/cli/no-treeshake/_config.js
new file mode 100644
index 0000000..18d8b69
--- /dev/null
+++ b/test/cli/no-treeshake/_config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ description: 'generates IIFE export with all code',
+ command: 'rollup main.js --format iife --name shakeless --no-treeshake'
+};
diff --git a/test/cli/no-treeshake/_expected.js b/test/cli/no-treeshake/_expected.js
new file mode 100644
index 0000000..6c3cf53
--- /dev/null
+++ b/test/cli/no-treeshake/_expected.js
@@ -0,0 +1,10 @@
+var shakeless = (function () {
+ 'use strict';
+
+ const version = '1.2.0';
+
+ var main = ( x, y ) => x + y;
+
+ return main;
+
+}());
diff --git a/test/cli/no-treeshake/main.js b/test/cli/no-treeshake/main.js
new file mode 100644
index 0000000..1aa6a51
--- /dev/null
+++ b/test/cli/no-treeshake/main.js
@@ -0,0 +1,3 @@
+const version = '1.2.0';
+
+export default ( x, y ) => x + y;
diff --git a/test/form/assignment-to-exports-class-declaration/_config.js b/test/form/assignment-to-exports-class-declaration/_config.js
new file mode 100644
index 0000000..0f3d2ef
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ description: 'does not rewrite class declaration IDs',
+ options: {
+ moduleName: 'myModule'
+ }
+};
diff --git a/test/form/assignment-to-exports-class-declaration/_expected/amd.js b/test/form/assignment-to-exports-class-declaration/_expected/amd.js
new file mode 100644
index 0000000..c2d0691
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_expected/amd.js
@@ -0,0 +1,6 @@
+define(['exports'], function (exports) { 'use strict';
+
+ exports.Foo = class Foo {}
+ exports.Foo = lol( exports.Foo );
+
+});
diff --git a/test/form/assignment-to-exports-class-declaration/_expected/cjs.js b/test/form/assignment-to-exports-class-declaration/_expected/cjs.js
new file mode 100644
index 0000000..b062474
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_expected/cjs.js
@@ -0,0 +1,4 @@
+'use strict';
+
+exports.Foo = class Foo {}
+exports.Foo = lol( exports.Foo );
diff --git a/test/form/assignment-to-exports-class-declaration/_expected/es6.js b/test/form/assignment-to-exports-class-declaration/_expected/es6.js
new file mode 100644
index 0000000..08e82c9
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_expected/es6.js
@@ -0,0 +1,4 @@
+Foo = class Foo {}
+Foo = lol( Foo );
+
+export { Foo };
\ No newline at end of file
diff --git a/test/form/assignment-to-exports-class-declaration/_expected/iife.js b/test/form/assignment-to-exports-class-declaration/_expected/iife.js
new file mode 100644
index 0000000..fa37538
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_expected/iife.js
@@ -0,0 +1,7 @@
+(function (exports) {
+ 'use strict';
+
+ exports.Foo = class Foo {}
+ exports.Foo = lol( exports.Foo );
+
+}((this.myModule = this.myModule || {})));
diff --git a/test/form/assignment-to-exports-class-declaration/_expected/umd.js b/test/form/assignment-to-exports-class-declaration/_expected/umd.js
new file mode 100644
index 0000000..bbefc87
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/_expected/umd.js
@@ -0,0 +1,10 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (factory((global.myModule = global.myModule || {})));
+}(this, function (exports) { 'use strict';
+
+ exports.Foo = class Foo {}
+ exports.Foo = lol( exports.Foo );
+
+}));
diff --git a/test/form/assignment-to-exports-class-declaration/main.js b/test/form/assignment-to-exports-class-declaration/main.js
new file mode 100644
index 0000000..ceae376
--- /dev/null
+++ b/test/form/assignment-to-exports-class-declaration/main.js
@@ -0,0 +1,2 @@
+export let Foo = class Foo {}
+Foo = lol( Foo );
diff --git a/test/form/computed-properties/_expected/amd.js b/test/form/computed-properties/_expected/amd.js
index 4fd933f..0ccd4d8 100644
--- a/test/form/computed-properties/_expected/amd.js
+++ b/test/form/computed-properties/_expected/amd.js
@@ -1,9 +1,19 @@
define(['exports'], function (exports) { 'use strict';
var foo = 'foo';
+ var bar = 'bar';
+ var baz = 'baz';
+ var bam = 'bam';
- var x = {[foo]: 'bar'};
+ var x = { [foo]: 'bar' };
+
+ class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+ }
exports.x = x;
+ exports.X = X;
});
\ No newline at end of file
diff --git a/test/form/computed-properties/_expected/cjs.js b/test/form/computed-properties/_expected/cjs.js
index 22126d8..443bab3 100644
--- a/test/form/computed-properties/_expected/cjs.js
+++ b/test/form/computed-properties/_expected/cjs.js
@@ -1,7 +1,17 @@
'use strict';
var foo = 'foo';
+var bar = 'bar';
+var baz = 'baz';
+var bam = 'bam';
-var x = {[foo]: 'bar'};
+var x = { [foo]: 'bar' };
-exports.x = x;
\ No newline at end of file
+class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+}
+
+exports.x = x;
+exports.X = X;
\ No newline at end of file
diff --git a/test/form/computed-properties/_expected/es6.js b/test/form/computed-properties/_expected/es6.js
index 6dc09ca..d818b11 100644
--- a/test/form/computed-properties/_expected/es6.js
+++ b/test/form/computed-properties/_expected/es6.js
@@ -1,5 +1,14 @@
var foo = 'foo';
+var bar = 'bar';
+var baz = 'baz';
+var bam = 'bam';
-var x = {[foo]: 'bar'};
+var x = { [foo]: 'bar' };
-export { x };
\ No newline at end of file
+class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+}
+
+export { x, X };
\ No newline at end of file
diff --git a/test/form/computed-properties/_expected/iife.js b/test/form/computed-properties/_expected/iife.js
index 35b80af..031368a 100644
--- a/test/form/computed-properties/_expected/iife.js
+++ b/test/form/computed-properties/_expected/iife.js
@@ -2,9 +2,19 @@
'use strict';
var foo = 'foo';
+ var bar = 'bar';
+ var baz = 'baz';
+ var bam = 'bam';
- var x = {[foo]: 'bar'};
+ var x = { [foo]: 'bar' };
+
+ class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+ }
exports.x = x;
+ exports.X = X;
-}((this.computedProperties = {})));
\ No newline at end of file
+}((this.computedProperties = this.computedProperties || {})));
\ No newline at end of file
diff --git a/test/form/computed-properties/_expected/umd.js b/test/form/computed-properties/_expected/umd.js
index 5f7d146..ae57683 100644
--- a/test/form/computed-properties/_expected/umd.js
+++ b/test/form/computed-properties/_expected/umd.js
@@ -1,13 +1,23 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.computedProperties = {})));
+ (factory((global.computedProperties = global.computedProperties || {})));
}(this, function (exports) { 'use strict';
var foo = 'foo';
+ var bar = 'bar';
+ var baz = 'baz';
+ var bam = 'bam';
- var x = {[foo]: 'bar'};
+ var x = { [foo]: 'bar' };
+
+ class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+ }
exports.x = x;
+ exports.X = X;
}));
\ No newline at end of file
diff --git a/test/form/computed-properties/main.js b/test/form/computed-properties/main.js
index 65bb97c..6cfc64a 100644
--- a/test/form/computed-properties/main.js
+++ b/test/form/computed-properties/main.js
@@ -1,3 +1,12 @@
var foo = 'foo';
+var bar = 'bar';
+var baz = 'baz';
+var bam = 'bam';
-export var x = {[foo]: 'bar'};
+export var x = { [foo]: 'bar' };
+
+export class X {
+ [bar] () {}
+ get [baz] () {}
+ set [bam] ( value ) {}
+}
diff --git a/test/form/conflicting-imports/_config.js b/test/form/conflicting-imports/_config.js
new file mode 100644
index 0000000..a9b8ddf
--- /dev/null
+++ b/test/form/conflicting-imports/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'ensures bundle imports are deconflicted (#659)'
+};
diff --git a/test/form/conflicting-imports/_expected/amd.js b/test/form/conflicting-imports/_expected/amd.js
new file mode 100644
index 0000000..e3b61ef
--- /dev/null
+++ b/test/form/conflicting-imports/_expected/amd.js
@@ -0,0 +1,7 @@
+define(['foo', 'bar'], function (foo, bar) { 'use strict';
+
+ console.log( bar.a );
+
+ console.log( foo.a );
+
+});
\ No newline at end of file
diff --git a/test/form/conflicting-imports/_expected/cjs.js b/test/form/conflicting-imports/_expected/cjs.js
new file mode 100644
index 0000000..2c2c321
--- /dev/null
+++ b/test/form/conflicting-imports/_expected/cjs.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var foo = require('foo');
+var bar = require('bar');
+
+console.log( bar.a );
+
+console.log( foo.a );
\ No newline at end of file
diff --git a/test/form/conflicting-imports/_expected/es6.js b/test/form/conflicting-imports/_expected/es6.js
new file mode 100644
index 0000000..281b463
--- /dev/null
+++ b/test/form/conflicting-imports/_expected/es6.js
@@ -0,0 +1,6 @@
+import { a } from 'foo';
+import { a as a$1 } from 'bar';
+
+console.log( a$1 );
+
+console.log( a );
diff --git a/test/form/conflicting-imports/_expected/iife.js b/test/form/conflicting-imports/_expected/iife.js
new file mode 100644
index 0000000..6f9d443
--- /dev/null
+++ b/test/form/conflicting-imports/_expected/iife.js
@@ -0,0 +1,8 @@
+(function (foo,bar) {
+ 'use strict';
+
+ console.log( bar.a );
+
+ console.log( foo.a );
+
+}(foo,bar));
\ No newline at end of file
diff --git a/test/form/conflicting-imports/_expected/umd.js b/test/form/conflicting-imports/_expected/umd.js
new file mode 100644
index 0000000..8254c77
--- /dev/null
+++ b/test/form/conflicting-imports/_expected/umd.js
@@ -0,0 +1,11 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('foo'), require('bar')) :
+ typeof define === 'function' && define.amd ? define(['foo', 'bar'], factory) :
+ (factory(global.foo,global.bar));
+}(this, function (foo,bar) { 'use strict';
+
+ console.log( bar.a );
+
+ console.log( foo.a );
+
+}));
\ No newline at end of file
diff --git a/test/form/conflicting-imports/main.js b/test/form/conflicting-imports/main.js
new file mode 100644
index 0000000..8ed570b
--- /dev/null
+++ b/test/form/conflicting-imports/main.js
@@ -0,0 +1,4 @@
+import { a } from 'foo';
+import './other.js';
+
+console.log( a );
diff --git a/test/form/conflicting-imports/other.js b/test/form/conflicting-imports/other.js
new file mode 100644
index 0000000..157ab35
--- /dev/null
+++ b/test/form/conflicting-imports/other.js
@@ -0,0 +1,3 @@
+import { a } from 'bar';
+
+console.log( a );
diff --git a/test/form/dedupes-external-imports/_expected/iife.js b/test/form/dedupes-external-imports/_expected/iife.js
index 17ed0b7..57e6649 100644
--- a/test/form/dedupes-external-imports/_expected/iife.js
+++ b/test/form/dedupes-external-imports/_expected/iife.js
@@ -30,4 +30,4 @@
exports.bar = bar;
exports.baz = baz;
-}((this.myBundle = {}),external));
+}((this.myBundle = this.myBundle || {}),external));
diff --git a/test/form/dedupes-external-imports/_expected/umd.js b/test/form/dedupes-external-imports/_expected/umd.js
index 70bc301..06be0e7 100644
--- a/test/form/dedupes-external-imports/_expected/umd.js
+++ b/test/form/dedupes-external-imports/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) :
typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) :
- (factory((global.myBundle = {}),global.external));
+ (factory((global.myBundle = global.myBundle || {}),global.external));
}(this, function (exports,external) { 'use strict';
class Foo extends external.Component {
diff --git a/test/form/erroneous-nested-member-expression/_config.js b/test/form/erroneous-nested-member-expression/_config.js
new file mode 100644
index 0000000..684fe7c
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'erroneous nested member expression does not mess up naming'
+};
diff --git a/test/form/erroneous-nested-member-expression/_expected/amd.js b/test/form/erroneous-nested-member-expression/_expected/amd.js
new file mode 100644
index 0000000..6499b90
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_expected/amd.js
@@ -0,0 +1,13 @@
+define(function () { 'use strict';
+
+ function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+ };
+
+ yar.har();
+
+});
\ No newline at end of file
diff --git a/test/form/erroneous-nested-member-expression/_expected/cjs.js b/test/form/erroneous-nested-member-expression/_expected/cjs.js
new file mode 100644
index 0000000..aa4b949
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_expected/cjs.js
@@ -0,0 +1,11 @@
+'use strict';
+
+function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+};
+
+yar.har();
\ No newline at end of file
diff --git a/test/form/erroneous-nested-member-expression/_expected/es6.js b/test/form/erroneous-nested-member-expression/_expected/es6.js
new file mode 100644
index 0000000..34c4e2e
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_expected/es6.js
@@ -0,0 +1,9 @@
+function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+};
+
+yar.har();
\ No newline at end of file
diff --git a/test/form/erroneous-nested-member-expression/_expected/iife.js b/test/form/erroneous-nested-member-expression/_expected/iife.js
new file mode 100644
index 0000000..4233cfe
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_expected/iife.js
@@ -0,0 +1,14 @@
+(function () {
+ 'use strict';
+
+ function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+ };
+
+ yar.har();
+
+}());
\ No newline at end of file
diff --git a/test/form/erroneous-nested-member-expression/_expected/umd.js b/test/form/erroneous-nested-member-expression/_expected/umd.js
new file mode 100644
index 0000000..d11bd9f
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/_expected/umd.js
@@ -0,0 +1,17 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (factory());
+}(this, function () { 'use strict';
+
+ function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+ };
+
+ yar.har();
+
+}));
\ No newline at end of file
diff --git a/test/form/erroneous-nested-member-expression/foo.js b/test/form/erroneous-nested-member-expression/foo.js
new file mode 100644
index 0000000..44f5e23
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/foo.js
@@ -0,0 +1,7 @@
+export function yar() {
+ return {
+ har() {
+ console.log('har?');
+ }
+ };
+};
diff --git a/test/form/erroneous-nested-member-expression/main.js b/test/form/erroneous-nested-member-expression/main.js
new file mode 100644
index 0000000..37c4b16
--- /dev/null
+++ b/test/form/erroneous-nested-member-expression/main.js
@@ -0,0 +1,2 @@
+import * as foo from './foo.js';
+foo.yar.har();
diff --git a/test/form/export-all-from-internal/_expected/iife.js b/test/form/export-all-from-internal/_expected/iife.js
index b5dad56..8a3cd17 100644
--- a/test/form/export-all-from-internal/_expected/iife.js
+++ b/test/form/export-all-from-internal/_expected/iife.js
@@ -7,4 +7,4 @@
exports.a = a;
exports.b = b;
-}((this.exposedInternals = {})));
+}((this.exposedInternals = this.exposedInternals || {})));
diff --git a/test/form/export-all-from-internal/_expected/umd.js b/test/form/export-all-from-internal/_expected/umd.js
index 74613b4..b249cc6 100644
--- a/test/form/export-all-from-internal/_expected/umd.js
+++ b/test/form/export-all-from-internal/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.exposedInternals = {})));
+ (factory((global.exposedInternals = global.exposedInternals || {})));
}(this, function (exports) { 'use strict';
const a = 1;
diff --git a/test/form/export-default-import/_config.js b/test/form/export-default-import/_config.js
new file mode 100644
index 0000000..860f688
--- /dev/null
+++ b/test/form/export-default-import/_config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ description: 'correctly exports a default import, even in ES mode (#513)',
+ options: {
+ moduleName: 'myBundle'
+ }
+};
diff --git a/test/form/export-default-import/_expected/amd.js b/test/form/export-default-import/_expected/amd.js
new file mode 100644
index 0000000..9158c43
--- /dev/null
+++ b/test/form/export-default-import/_expected/amd.js
@@ -0,0 +1,9 @@
+define(['exports', 'x'], function (exports, x) { 'use strict';
+
+ x = 'default' in x ? x['default'] : x;
+
+
+
+ exports.x = x;
+
+});
\ No newline at end of file
diff --git a/test/form/export-default-import/_expected/cjs.js b/test/form/export-default-import/_expected/cjs.js
new file mode 100644
index 0000000..60037db
--- /dev/null
+++ b/test/form/export-default-import/_expected/cjs.js
@@ -0,0 +1,9 @@
+'use strict';
+
+function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
+
+var x = _interopDefault(require('x'));
+
+
+
+exports.x = x;
\ No newline at end of file
diff --git a/test/form/export-default-import/_expected/es6.js b/test/form/export-default-import/_expected/es6.js
new file mode 100644
index 0000000..87ab795
--- /dev/null
+++ b/test/form/export-default-import/_expected/es6.js
@@ -0,0 +1,5 @@
+import x from 'x';
+
+
+
+export { x };
diff --git a/test/form/export-default-import/_expected/iife.js b/test/form/export-default-import/_expected/iife.js
new file mode 100644
index 0000000..4c3865e
--- /dev/null
+++ b/test/form/export-default-import/_expected/iife.js
@@ -0,0 +1,10 @@
+(function (exports,x) {
+ 'use strict';
+
+ x = 'default' in x ? x['default'] : x;
+
+
+
+ exports.x = x;
+
+}((this.myBundle = this.myBundle || {}),x));
\ No newline at end of file
diff --git a/test/form/export-default-import/_expected/umd.js b/test/form/export-default-import/_expected/umd.js
new file mode 100644
index 0000000..872c0d8
--- /dev/null
+++ b/test/form/export-default-import/_expected/umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('x')) :
+ typeof define === 'function' && define.amd ? define(['exports', 'x'], factory) :
+ (factory((global.myBundle = global.myBundle || {}),global.x));
+}(this, function (exports,x) { 'use strict';
+
+ x = 'default' in x ? x['default'] : x;
+
+
+
+ exports.x = x;
+
+}));
\ No newline at end of file
diff --git a/test/form/export-default-import/main.js b/test/form/export-default-import/main.js
new file mode 100644
index 0000000..31bb602
--- /dev/null
+++ b/test/form/export-default-import/main.js
@@ -0,0 +1,3 @@
+import x from 'x';
+
+export { x };
diff --git a/test/form/exports-at-end-if-possible/_expected/iife.js b/test/form/exports-at-end-if-possible/_expected/iife.js
index a0ce6a9..1c5c67b 100644
--- a/test/form/exports-at-end-if-possible/_expected/iife.js
+++ b/test/form/exports-at-end-if-possible/_expected/iife.js
@@ -9,4 +9,4 @@
exports.FOO = FOO;
-}((this.myBundle = {})));
+}((this.myBundle = this.myBundle || {})));
diff --git a/test/form/exports-at-end-if-possible/_expected/umd.js b/test/form/exports-at-end-if-possible/_expected/umd.js
index 20d0d2a..e9cbc8d 100644
--- a/test/form/exports-at-end-if-possible/_expected/umd.js
+++ b/test/form/exports-at-end-if-possible/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.myBundle = {})));
+ (factory((global.myBundle = global.myBundle || {})));
}(this, function (exports) { 'use strict';
var FOO = 'foo';
diff --git a/test/form/external-imports-custom-names/_expected/cjs.js b/test/form/external-imports-custom-names/_expected/cjs.js
index 8f6506e..9600acd 100644
--- a/test/form/external-imports-custom-names/_expected/cjs.js
+++ b/test/form/external-imports-custom-names/_expected/cjs.js
@@ -1,6 +1,6 @@
'use strict';
-function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; }
+function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var $ = _interopDefault(require('jquery'));
diff --git a/test/form/external-imports/_expected/cjs.js b/test/form/external-imports/_expected/cjs.js
index a3ee9b0..94dbdae 100644
--- a/test/form/external-imports/_expected/cjs.js
+++ b/test/form/external-imports/_expected/cjs.js
@@ -1,6 +1,6 @@
'use strict';
-function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; }
+function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var factory = _interopDefault(require('factory'));
var baz = require('baz');
diff --git a/test/form/import-external-namespace-and-default/_config.js b/test/form/import-external-namespace-and-default/_config.js
new file mode 100644
index 0000000..5ee7b48
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'disinguishes between external default and namespace (#637)'
+};
diff --git a/test/form/import-external-namespace-and-default/_expected/amd.js b/test/form/import-external-namespace-and-default/_expected/amd.js
new file mode 100644
index 0000000..1f4b3f9
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_expected/amd.js
@@ -0,0 +1,9 @@
+define(['foo'], function (foo) { 'use strict';
+
+ var foo__default = foo['default'];
+
+ console.log( foo.bar );
+
+ console.log( foo__default );
+
+});
diff --git a/test/form/import-external-namespace-and-default/_expected/cjs.js b/test/form/import-external-namespace-and-default/_expected/cjs.js
new file mode 100644
index 0000000..14c733e
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_expected/cjs.js
@@ -0,0 +1,8 @@
+'use strict';
+
+var foo = require('foo');
+var foo__default = foo['default'];
+
+console.log( foo.bar );
+
+console.log( foo__default );
diff --git a/test/form/import-external-namespace-and-default/_expected/es6.js b/test/form/import-external-namespace-and-default/_expected/es6.js
new file mode 100644
index 0000000..5655595
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_expected/es6.js
@@ -0,0 +1,6 @@
+import * as foo from 'foo';
+import foo__default from 'foo';
+
+console.log( foo.bar );
+
+console.log( foo__default );
diff --git a/test/form/import-external-namespace-and-default/_expected/iife.js b/test/form/import-external-namespace-and-default/_expected/iife.js
new file mode 100644
index 0000000..b2c5788
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_expected/iife.js
@@ -0,0 +1,10 @@
+(function (foo) {
+ 'use strict';
+
+ var foo__default = foo['default'];
+
+ console.log( foo.bar );
+
+ console.log( foo__default );
+
+}(foo));
diff --git a/test/form/import-external-namespace-and-default/_expected/umd.js b/test/form/import-external-namespace-and-default/_expected/umd.js
new file mode 100644
index 0000000..ddcdcbd
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/_expected/umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('foo')) :
+ typeof define === 'function' && define.amd ? define(['foo'], factory) :
+ (factory(global.foo));
+}(this, function (foo) { 'use strict';
+
+ var foo__default = foo['default'];
+
+ console.log( foo.bar );
+
+ console.log( foo__default );
+
+}));
diff --git a/test/form/import-external-namespace-and-default/main.js b/test/form/import-external-namespace-and-default/main.js
new file mode 100644
index 0000000..719a96a
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/main.js
@@ -0,0 +1,4 @@
+import foo from 'foo';
+import './other.js';
+
+console.log( foo );
diff --git a/test/form/import-external-namespace-and-default/other.js b/test/form/import-external-namespace-and-default/other.js
new file mode 100644
index 0000000..8149fb6
--- /dev/null
+++ b/test/form/import-external-namespace-and-default/other.js
@@ -0,0 +1,3 @@
+import * as foo from 'foo';
+
+console.log( foo.bar );
diff --git a/test/form/import-named-exported-global-with-alias/_config.js b/test/form/import-named-exported-global-with-alias/_config.js
new file mode 100644
index 0000000..85b39fe
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/_config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ description: 'allow globals to be exported and imported',
+ options: {
+ moduleName: 'doc'
+ }
+};
diff --git a/test/form/import-named-exported-global-with-alias/_expected/amd.js b/test/form/import-named-exported-global-with-alias/_expected/amd.js
new file mode 100644
index 0000000..ec759b1
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/_expected/amd.js
@@ -0,0 +1,5 @@
+define(function () { 'use strict';
+
+
+
+});
\ No newline at end of file
diff --git a/test/form/import-named-exported-global-with-alias/_expected/cjs.js b/test/form/import-named-exported-global-with-alias/_expected/cjs.js
new file mode 100644
index 0000000..eb109ab
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/_expected/cjs.js
@@ -0,0 +1,2 @@
+'use strict';
+
diff --git a/test/form/import-named-exported-global-with-alias/_expected/es6.js b/test/form/import-named-exported-global-with-alias/_expected/es6.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/form/import-named-exported-global-with-alias/_expected/iife.js b/test/form/import-named-exported-global-with-alias/_expected/iife.js
new file mode 100644
index 0000000..f3d1016
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/_expected/iife.js
@@ -0,0 +1,6 @@
+(function () {
+ 'use strict';
+
+
+
+}());
\ No newline at end of file
diff --git a/test/form/import-named-exported-global-with-alias/_expected/umd.js b/test/form/import-named-exported-global-with-alias/_expected/umd.js
new file mode 100644
index 0000000..f3395b7
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/_expected/umd.js
@@ -0,0 +1,9 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (factory());
+}(this, function () { 'use strict';
+
+
+
+}));
\ No newline at end of file
diff --git a/test/form/import-named-exported-global-with-alias/browser.js b/test/form/import-named-exported-global-with-alias/browser.js
new file mode 100644
index 0000000..a7aab36
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/browser.js
@@ -0,0 +1 @@
+export { document };
diff --git a/test/form/import-named-exported-global-with-alias/main.js b/test/form/import-named-exported-global-with-alias/main.js
new file mode 100644
index 0000000..5d3739c
--- /dev/null
+++ b/test/form/import-named-exported-global-with-alias/main.js
@@ -0,0 +1,2 @@
+import { document } from './browser.js';
+var d = document;
diff --git a/test/form/multiple-exports/_expected/iife.js b/test/form/multiple-exports/_expected/iife.js
index 3a3975d..d2da90f 100644
--- a/test/form/multiple-exports/_expected/iife.js
+++ b/test/form/multiple-exports/_expected/iife.js
@@ -7,4 +7,4 @@
exports.foo = foo;
exports.bar = bar;
-}((this.myBundle = {})));
+}((this.myBundle = this.myBundle || {})));
diff --git a/test/form/multiple-exports/_expected/umd.js b/test/form/multiple-exports/_expected/umd.js
index 485e381..30a54d6 100644
--- a/test/form/multiple-exports/_expected/umd.js
+++ b/test/form/multiple-exports/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.myBundle = {})));
+ (factory((global.myBundle = global.myBundle || {})));
}(this, function (exports) { 'use strict';
var foo = 1;
diff --git a/test/form/namespaced-named-exports/_expected/iife.js b/test/form/namespaced-named-exports/_expected/iife.js
index 2fc75df..69637e9 100644
--- a/test/form/namespaced-named-exports/_expected/iife.js
+++ b/test/form/namespaced-named-exports/_expected/iife.js
@@ -7,4 +7,4 @@ this.foo.bar = this.foo.bar || {};
exports.answer = answer;
-}((this.foo.bar.baz = {})));
+}((this.foo.bar.baz = this.foo.bar.baz || {})));
diff --git a/test/form/namespaced-named-exports/_expected/umd.js b/test/form/namespaced-named-exports/_expected/umd.js
index aeb7775..9a0f47d 100644
--- a/test/form/namespaced-named-exports/_expected/umd.js
+++ b/test/form/namespaced-named-exports/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.foo = global.foo || {}, global.foo.bar = global.foo.bar || {}, global.foo.bar.baz = {})));
+ (factory((global.foo = global.foo || {}, global.foo.bar = global.foo.bar || {}, global.foo.bar.baz = global.foo.bar.baz || {})));
}(this, function (exports) { 'use strict';
var answer = 42;
diff --git a/test/form/no-treeshake/_config.js b/test/form/no-treeshake/_config.js
new file mode 100644
index 0000000..a997358
--- /dev/null
+++ b/test/form/no-treeshake/_config.js
@@ -0,0 +1,11 @@
+module.exports = {
+ description: 'all code should be included if tree-shaking is disabled',
+ options: {
+ external: [ 'external' ],
+ globals: {
+ external: 'external'
+ },
+ moduleName: /* not shaken, but */ 'stirred',
+ treeshake: false
+ }
+};
diff --git a/test/form/no-treeshake/_expected/amd.js b/test/form/no-treeshake/_expected/amd.js
new file mode 100644
index 0000000..7bbe64b
--- /dev/null
+++ b/test/form/no-treeshake/_expected/amd.js
@@ -0,0 +1,25 @@
+define(['exports', 'external'], function (exports, external) { 'use strict';
+
+ var foo = 'unused';
+
+ const quux = 1;
+
+ const other = () => quux;
+
+ function bar () {
+ return foo;
+ }
+
+ function baz () {
+ return 13 + external.value;
+ }
+
+ var create = Object.create;
+ var getPrototypeOf = Object.getPrototypeOf;
+
+ exports.baz = baz;
+ exports.create = create;
+ exports.getPrototypeOf = getPrototypeOf;
+ exports.strange = quux;
+
+});
diff --git a/test/form/no-treeshake/_expected/cjs.js b/test/form/no-treeshake/_expected/cjs.js
new file mode 100644
index 0000000..c188f06
--- /dev/null
+++ b/test/form/no-treeshake/_expected/cjs.js
@@ -0,0 +1,25 @@
+'use strict';
+
+var external = require('external');
+
+var foo = 'unused';
+
+const quux = 1;
+
+const other = () => quux;
+
+function bar () {
+ return foo;
+}
+
+function baz () {
+ return 13 + external.value;
+}
+
+var create = Object.create;
+var getPrototypeOf = Object.getPrototypeOf;
+
+exports.baz = baz;
+exports.create = create;
+exports.getPrototypeOf = getPrototypeOf;
+exports.strange = quux;
diff --git a/test/form/no-treeshake/_expected/es6.js b/test/form/no-treeshake/_expected/es6.js
new file mode 100644
index 0000000..54f2add
--- /dev/null
+++ b/test/form/no-treeshake/_expected/es6.js
@@ -0,0 +1,20 @@
+import * as external from 'external';
+
+var foo = 'unused';
+
+const quux = 1;
+
+const other = () => quux;
+
+function bar () {
+ return foo;
+}
+
+function baz () {
+ return 13 + external.value;
+}
+
+var create = Object.create;
+var getPrototypeOf = Object.getPrototypeOf;
+
+export { baz, create, getPrototypeOf, quux as strange };
diff --git a/test/form/no-treeshake/_expected/iife.js b/test/form/no-treeshake/_expected/iife.js
new file mode 100644
index 0000000..7c3ad8d
--- /dev/null
+++ b/test/form/no-treeshake/_expected/iife.js
@@ -0,0 +1,26 @@
+(function (exports,external) {
+ 'use strict';
+
+ var foo = 'unused';
+
+ const quux = 1;
+
+ const other = () => quux;
+
+ function bar () {
+ return foo;
+ }
+
+ function baz () {
+ return 13 + external.value;
+ }
+
+ var create = Object.create;
+ var getPrototypeOf = Object.getPrototypeOf;
+
+ exports.baz = baz;
+ exports.create = create;
+ exports.getPrototypeOf = getPrototypeOf;
+ exports.strange = quux;
+
+}((this.stirred = this.stirred || {}),external));
diff --git a/test/form/no-treeshake/_expected/umd.js b/test/form/no-treeshake/_expected/umd.js
new file mode 100644
index 0000000..2136453
--- /dev/null
+++ b/test/form/no-treeshake/_expected/umd.js
@@ -0,0 +1,29 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) :
+ typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) :
+ (factory((global.stirred = global.stirred || {}),global.external));
+}(this, function (exports,external) { 'use strict';
+
+ var foo = 'unused';
+
+ const quux = 1;
+
+ const other = () => quux;
+
+ function bar () {
+ return foo;
+ }
+
+ function baz () {
+ return 13 + external.value;
+ }
+
+ var create = Object.create;
+ var getPrototypeOf = Object.getPrototypeOf;
+
+ exports.baz = baz;
+ exports.create = create;
+ exports.getPrototypeOf = getPrototypeOf;
+ exports.strange = quux;
+
+}));
diff --git a/test/form/no-treeshake/foo.js b/test/form/no-treeshake/foo.js
new file mode 100644
index 0000000..e4c7f51
--- /dev/null
+++ b/test/form/no-treeshake/foo.js
@@ -0,0 +1 @@
+export default 'unused';
diff --git a/test/form/no-treeshake/main.js b/test/form/no-treeshake/main.js
new file mode 100644
index 0000000..5a5f67e
--- /dev/null
+++ b/test/form/no-treeshake/main.js
@@ -0,0 +1,13 @@
+import * as external from 'external';
+import foo from './foo.js'
+export { quux as strange } from './quux.js';
+
+function bar () {
+ return foo;
+}
+
+export function baz () {
+ return 13 + external.value;
+}
+
+export var create = Object.create, getPrototypeOf = Object.getPrototypeOf;
diff --git a/test/form/no-treeshake/quux.js b/test/form/no-treeshake/quux.js
new file mode 100644
index 0000000..ceb5f12
--- /dev/null
+++ b/test/form/no-treeshake/quux.js
@@ -0,0 +1,3 @@
+export const quux = 1;
+
+const other = () => quux;
diff --git a/test/form/prefer-const/_config.js b/test/form/prefer-const/_config.js
new file mode 100644
index 0000000..ebb4828
--- /dev/null
+++ b/test/form/prefer-const/_config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ description: 'uses const instead of var if specified (#653)',
+ options: {
+ preferConst: true,
+ moduleName: 'myBundle'
+ }
+};
diff --git a/test/form/prefer-const/_expected/amd.js b/test/form/prefer-const/_expected/amd.js
new file mode 100644
index 0000000..a89dacd
--- /dev/null
+++ b/test/form/prefer-const/_expected/amd.js
@@ -0,0 +1,18 @@
+define(['external', 'other', 'another'], function (external, other, another) { 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+
+ const namespace = Object.freeze({
+ a: a,
+ b: b
+ });
+
+ console.log( Object.keys( namespace ) );
+
+ const main = 42;
+
+ return main;
+
+});
diff --git a/test/form/prefer-const/_expected/cjs.js b/test/form/prefer-const/_expected/cjs.js
new file mode 100644
index 0000000..5c2e4da
--- /dev/null
+++ b/test/form/prefer-const/_expected/cjs.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const external = require('external');
+const other = require('other');
+const another = require('another');
+
+const a = 1;
+const b = 2;
+
+
+const namespace = Object.freeze({
+ a: a,
+ b: b
+});
+
+console.log( Object.keys( namespace ) );
+
+const main = 42;
+
+module.exports = main;
diff --git a/test/form/prefer-const/_expected/es6.js b/test/form/prefer-const/_expected/es6.js
new file mode 100644
index 0000000..8f5a5c9
--- /dev/null
+++ b/test/form/prefer-const/_expected/es6.js
@@ -0,0 +1,18 @@
+import 'external';
+import 'other';
+import 'another';
+
+const a = 1;
+const b = 2;
+
+
+const namespace = Object.freeze({
+ a: a,
+ b: b
+});
+
+console.log( Object.keys( namespace ) );
+
+const main = 42;
+
+export default main;
diff --git a/test/form/prefer-const/_expected/iife.js b/test/form/prefer-const/_expected/iife.js
new file mode 100644
index 0000000..9c66729
--- /dev/null
+++ b/test/form/prefer-const/_expected/iife.js
@@ -0,0 +1,19 @@
+const myBundle = (function (external,other,another) {
+ 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+
+ const namespace = Object.freeze({
+ a: a,
+ b: b
+ });
+
+ console.log( Object.keys( namespace ) );
+
+ const main = 42;
+
+ return main;
+
+}(external,other,another));
diff --git a/test/form/prefer-const/_expected/umd.js b/test/form/prefer-const/_expected/umd.js
new file mode 100644
index 0000000..0c54878
--- /dev/null
+++ b/test/form/prefer-const/_expected/umd.js
@@ -0,0 +1,22 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('external'), require('other'), require('another')) :
+ typeof define === 'function' && define.amd ? define(['external', 'other', 'another'], factory) :
+ (global.myBundle = factory(global.external,global.other,global.another));
+}(this, function (external,other,another) { 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+
+ const namespace = Object.freeze({
+ a: a,
+ b: b
+ });
+
+ console.log( Object.keys( namespace ) );
+
+ const main = 42;
+
+ return main;
+
+}));
diff --git a/test/form/prefer-const/main.js b/test/form/prefer-const/main.js
new file mode 100644
index 0000000..e8cc563
--- /dev/null
+++ b/test/form/prefer-const/main.js
@@ -0,0 +1,9 @@
+import external from 'external';
+import a from 'other';
+import { b } from 'other';
+import { another } from 'another';
+import * as namespace from './namespace.js';
+
+console.log( Object.keys( namespace ) );
+
+export default 42;
diff --git a/test/form/prefer-const/namespace.js b/test/form/prefer-const/namespace.js
new file mode 100644
index 0000000..72ab60e
--- /dev/null
+++ b/test/form/prefer-const/namespace.js
@@ -0,0 +1,2 @@
+export const a = 1;
+export const b = 2;
diff --git a/test/form/preserve-debugger/_config.js b/test/form/preserve-debugger/_config.js
new file mode 100644
index 0000000..3e65815
--- /dev/null
+++ b/test/form/preserve-debugger/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'debugger statements are preserved (#664)'
+};
diff --git a/test/form/preserve-debugger/_expected/amd.js b/test/form/preserve-debugger/_expected/amd.js
new file mode 100644
index 0000000..be1ef13
--- /dev/null
+++ b/test/form/preserve-debugger/_expected/amd.js
@@ -0,0 +1,7 @@
+define(function () { 'use strict';
+
+ before();
+ debugger;
+ after();
+
+});
diff --git a/test/form/preserve-debugger/_expected/cjs.js b/test/form/preserve-debugger/_expected/cjs.js
new file mode 100644
index 0000000..ae69f57
--- /dev/null
+++ b/test/form/preserve-debugger/_expected/cjs.js
@@ -0,0 +1,5 @@
+'use strict';
+
+before();
+debugger;
+after();
diff --git a/test/form/preserve-debugger/_expected/es6.js b/test/form/preserve-debugger/_expected/es6.js
new file mode 100644
index 0000000..ce1bafd
--- /dev/null
+++ b/test/form/preserve-debugger/_expected/es6.js
@@ -0,0 +1,3 @@
+before();
+debugger;
+after();
diff --git a/test/form/preserve-debugger/_expected/iife.js b/test/form/preserve-debugger/_expected/iife.js
new file mode 100644
index 0000000..b40a100
--- /dev/null
+++ b/test/form/preserve-debugger/_expected/iife.js
@@ -0,0 +1,8 @@
+(function () {
+ 'use strict';
+
+ before();
+ debugger;
+ after();
+
+}());
diff --git a/test/form/preserve-debugger/_expected/umd.js b/test/form/preserve-debugger/_expected/umd.js
new file mode 100644
index 0000000..dd19c2d
--- /dev/null
+++ b/test/form/preserve-debugger/_expected/umd.js
@@ -0,0 +1,11 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (factory());
+}(this, function () { 'use strict';
+
+ before();
+ debugger;
+ after();
+
+}));
diff --git a/test/form/preserve-debugger/main.js b/test/form/preserve-debugger/main.js
new file mode 100644
index 0000000..ce1bafd
--- /dev/null
+++ b/test/form/preserve-debugger/main.js
@@ -0,0 +1,3 @@
+before();
+debugger;
+after();
diff --git a/test/form/preserves-comments-after-imports/_expected/iife.js b/test/form/preserves-comments-after-imports/_expected/iife.js
index e9338dc..ee4c000 100644
--- a/test/form/preserves-comments-after-imports/_expected/iife.js
+++ b/test/form/preserves-comments-after-imports/_expected/iife.js
@@ -9,4 +9,4 @@
exports.obj = obj;
-}((this.myBundle = {})));
+}((this.myBundle = this.myBundle || {})));
diff --git a/test/form/preserves-comments-after-imports/_expected/umd.js b/test/form/preserves-comments-after-imports/_expected/umd.js
index ac58856..13a54bf 100644
--- a/test/form/preserves-comments-after-imports/_expected/umd.js
+++ b/test/form/preserves-comments-after-imports/_expected/umd.js
@@ -1,7 +1,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (factory((global.myBundle = {})));
+ (factory((global.myBundle = global.myBundle || {})));
}(this, function (exports) { 'use strict';
/** A comment for a number */
diff --git a/test/form/umd-noconflict/_config.js b/test/form/umd-noconflict/_config.js
new file mode 100644
index 0000000..9bbcec6
--- /dev/null
+++ b/test/form/umd-noconflict/_config.js
@@ -0,0 +1,10 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'exports noConflict method for default umd when requested',
+ options: {
+ noConflict: true,
+ moduleName: 'FooBar'
+ }
+};
+
diff --git a/test/form/umd-noconflict/_expected/amd.js b/test/form/umd-noconflict/_expected/amd.js
new file mode 100644
index 0000000..16ca409
--- /dev/null
+++ b/test/form/umd-noconflict/_expected/amd.js
@@ -0,0 +1,15 @@
+define(['exports'], function (exports) { 'use strict';
+
+ function doThings() {
+ console.log( 'doing things...' );
+ }
+
+ const number = 42;
+
+ var setting = 'no';
+
+ exports.doThings = doThings;
+ exports.number = number;
+ exports.setting = setting;
+
+});
\ No newline at end of file
diff --git a/test/form/umd-noconflict/_expected/cjs.js b/test/form/umd-noconflict/_expected/cjs.js
new file mode 100644
index 0000000..4379f50
--- /dev/null
+++ b/test/form/umd-noconflict/_expected/cjs.js
@@ -0,0 +1,13 @@
+'use strict';
+
+function doThings() {
+ console.log( 'doing things...' );
+}
+
+const number = 42;
+
+var setting = 'no';
+
+exports.doThings = doThings;
+exports.number = number;
+exports.setting = setting;
\ No newline at end of file
diff --git a/test/form/umd-noconflict/_expected/es6.js b/test/form/umd-noconflict/_expected/es6.js
new file mode 100644
index 0000000..26bd5fb
--- /dev/null
+++ b/test/form/umd-noconflict/_expected/es6.js
@@ -0,0 +1,9 @@
+function doThings() {
+ console.log( 'doing things...' );
+}
+
+const number = 42;
+
+var setting = 'no';
+
+export { doThings, number, setting };
\ No newline at end of file
diff --git a/test/form/umd-noconflict/_expected/iife.js b/test/form/umd-noconflict/_expected/iife.js
new file mode 100644
index 0000000..5d76948
--- /dev/null
+++ b/test/form/umd-noconflict/_expected/iife.js
@@ -0,0 +1,16 @@
+(function (exports) {
+ 'use strict';
+
+ function doThings() {
+ console.log( 'doing things...' );
+ }
+
+ const number = 42;
+
+ var setting = 'no';
+
+ exports.doThings = doThings;
+ exports.number = number;
+ exports.setting = setting;
+
+}((this.FooBar = this.FooBar || {})));
\ No newline at end of file
diff --git a/test/form/umd-noconflict/_expected/umd.js b/test/form/umd-noconflict/_expected/umd.js
new file mode 100644
index 0000000..5578ce9
--- /dev/null
+++ b/test/form/umd-noconflict/_expected/umd.js
@@ -0,0 +1,24 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ (function() {
+ var current = global.FooBar;
+ var exports = factory((global.FooBar = global.FooBar || {}));
+ global.FooBar = exports;
+ exports.noConflict = function() { global.FooBar = current; return exports; };
+ })();
+}(this, function (exports) { 'use strict';
+
+ function doThings() {
+ console.log( 'doing things...' );
+ }
+
+ const number = 42;
+
+ var setting = 'no';
+
+ exports.doThings = doThings;
+ exports.number = number;
+ exports.setting = setting;
+
+}));
diff --git a/test/form/umd-noconflict/main.js b/test/form/umd-noconflict/main.js
new file mode 100644
index 0000000..136039a
--- /dev/null
+++ b/test/form/umd-noconflict/main.js
@@ -0,0 +1,7 @@
+export function doThings() {
+ console.log( 'doing things...' );
+}
+
+export const number = 42;
+
+export var setting = 'no';
diff --git a/test/form/whitespace-around-namespace-member-expression/_config.js b/test/form/whitespace-around-namespace-member-expression/_config.js
new file mode 100644
index 0000000..a97b168
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'whitespace around the "." in member expressions does not mess up renaming'
+};
diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/amd.js b/test/form/whitespace-around-namespace-member-expression/_expected/amd.js
new file mode 100644
index 0000000..00fa37b
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_expected/amd.js
@@ -0,0 +1,9 @@
+define(function () { 'use strict';
+
+ function yar() {
+ console.log('yar?');
+ }
+
+ yar();
+
+});
\ No newline at end of file
diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/cjs.js b/test/form/whitespace-around-namespace-member-expression/_expected/cjs.js
new file mode 100644
index 0000000..c47867c
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_expected/cjs.js
@@ -0,0 +1,7 @@
+'use strict';
+
+function yar() {
+ console.log('yar?');
+}
+
+yar();
\ No newline at end of file
diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/es6.js b/test/form/whitespace-around-namespace-member-expression/_expected/es6.js
new file mode 100644
index 0000000..9ad6744
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_expected/es6.js
@@ -0,0 +1,5 @@
+function yar() {
+ console.log('yar?');
+}
+
+yar();
\ No newline at end of file
diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/iife.js b/test/form/whitespace-around-namespace-member-expression/_expected/iife.js
new file mode 100644
index 0000000..5a0d920
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_expected/iife.js
@@ -0,0 +1,10 @@
+(function () {
+ 'use strict';
+
+ function yar() {
+ console.log('yar?');
+ }
+
+ yar();
+
+}());
\ No newline at end of file
diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/umd.js b/test/form/whitespace-around-namespace-member-expression/_expected/umd.js
new file mode 100644
index 0000000..ae6ce6f
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/_expected/umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (factory());
+}(this, function () { 'use strict';
+
+ function yar() {
+ console.log('yar?');
+ }
+
+ yar();
+
+}));
\ No newline at end of file
diff --git a/test/form/whitespace-around-namespace-member-expression/foo.js b/test/form/whitespace-around-namespace-member-expression/foo.js
new file mode 100644
index 0000000..1479860
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/foo.js
@@ -0,0 +1,3 @@
+export function yar() {
+ console.log('yar?');
+}
diff --git a/test/form/whitespace-around-namespace-member-expression/main.js b/test/form/whitespace-around-namespace-member-expression/main.js
new file mode 100644
index 0000000..eba0ddf
--- /dev/null
+++ b/test/form/whitespace-around-namespace-member-expression/main.js
@@ -0,0 +1,2 @@
+import * as foo from './foo.js';
+foo .yar();
diff --git a/test/function/assignment-to-exports-b/_config.js b/test/function/assignment-to-exports-b/_config.js
new file mode 100644
index 0000000..9abbeab
--- /dev/null
+++ b/test/function/assignment-to-exports-b/_config.js
@@ -0,0 +1,8 @@
+const assert = require( 'assert' );
+
+module.exports = {
+ description: 'exports are rewritten inside a variable init',
+ exports: exports => {
+ assert.equal( exports.b, 42 );
+ }
+};
diff --git a/test/function/assignment-to-exports-b/main.js b/test/function/assignment-to-exports-b/main.js
new file mode 100644
index 0000000..d503419
--- /dev/null
+++ b/test/function/assignment-to-exports-b/main.js
@@ -0,0 +1,9 @@
+var a = { prop: 42 };
+var b = a.prop;
+
+function set ( new_a, new_b ) {
+ a = new_a;
+ b = new_b;
+}
+
+export { a, b, set };
diff --git a/test/function/configure-relative-external-module/_config.js b/test/function/configure-relative-external-module/_config.js
new file mode 100644
index 0000000..bbcebcf
--- /dev/null
+++ b/test/function/configure-relative-external-module/_config.js
@@ -0,0 +1,21 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+var mockedValue = {
+ val: 'A value'
+};
+
+module.exports = {
+ description: 'allows a nonexistent relative module to be configured as external',
+ options: {
+ external: [ path.join( __dirname, './nonexistent-relative-dependency.js') ]
+ },
+ context: {
+ require: function() {
+ return mockedValue;
+ }
+ },
+ exports: function () {
+ assert.equal( mockedValue.wasAltered, true );
+ }
+};
diff --git a/test/function/configure-relative-external-module/main.js b/test/function/configure-relative-external-module/main.js
new file mode 100644
index 0000000..317fa9f
--- /dev/null
+++ b/test/function/configure-relative-external-module/main.js
@@ -0,0 +1,3 @@
+import relativeDep from './nonexistent-relative-dependency.js';
+
+relativeDep.wasAltered = true;
diff --git a/test/function/confused-default-identifier/_config.js b/test/function/confused-default-identifier/_config.js
index 75c2e8f..1b0bbf2 100644
--- a/test/function/confused-default-identifier/_config.js
+++ b/test/function/confused-default-identifier/_config.js
@@ -1,5 +1,8 @@
+var assert = require( 'assert' );
+
module.exports = {
- description: 'Rollup should not get confused and allow "default" as an identifier name'
+ description: 'Rollup should not get confused and allow "default" as an identifier name',
+ warnings: function () {} // suppress
};
// https://github.com/rollup/rollup/issues/215
diff --git a/test/function/custom-path-resolver-async/_config.js b/test/function/custom-path-resolver-async/_config.js
index 2d7539a..a0df42f 100644
--- a/test/function/custom-path-resolver-async/_config.js
+++ b/test/function/custom-path-resolver-async/_config.js
@@ -21,6 +21,11 @@ module.exports = {
}
}]
},
+ warnings: function ( warnings ) {
+ assert.deepEqual( warnings, [
+ "Treating 'path' as external dependency"
+ ]);
+ },
exports: function ( exports ) {
assert.strictEqual( exports.path, require( 'path' ) );
}
diff --git a/test/function/custom-path-resolver-sync/_config.js b/test/function/custom-path-resolver-sync/_config.js
index 4e0b5bf..b676f5d 100644
--- a/test/function/custom-path-resolver-sync/_config.js
+++ b/test/function/custom-path-resolver-sync/_config.js
@@ -13,6 +13,11 @@ module.exports = {
}
}]
},
+ warnings: function ( warnings ) {
+ assert.deepEqual( warnings, [
+ "Treating 'path' as external dependency"
+ ]);
+ },
exports: function ( exports ) {
assert.strictEqual( exports.path, require( 'path' ) );
}
diff --git a/test/function/deshadowed-shorthand-property/_config.js b/test/function/deshadowed-shorthand-property/_config.js
new file mode 100644
index 0000000..352f7f3
--- /dev/null
+++ b/test/function/deshadowed-shorthand-property/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'shorthand properties referencing deshadowed variables are expanded'
+};
diff --git a/test/function/deshadowed-shorthand-property/foo.js b/test/function/deshadowed-shorthand-property/foo.js
new file mode 100644
index 0000000..c03d7e4
--- /dev/null
+++ b/test/function/deshadowed-shorthand-property/foo.js
@@ -0,0 +1,3 @@
+export default function answer () {
+ return 42;
+}
diff --git a/test/function/deshadowed-shorthand-property/main.js b/test/function/deshadowed-shorthand-property/main.js
new file mode 100644
index 0000000..7942ca4
--- /dev/null
+++ b/test/function/deshadowed-shorthand-property/main.js
@@ -0,0 +1,8 @@
+import foo from './foo.js';
+
+function x () {
+ var answer = foo();
+ return { answer };
+}
+
+assert.equal( x().answer, 42 );
diff --git a/test/function/disappearing-exported-value/_config.js b/test/function/disappearing-exported-value/_config.js
new file mode 100644
index 0000000..534c5ae
--- /dev/null
+++ b/test/function/disappearing-exported-value/_config.js
@@ -0,0 +1,9 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'exported values do not mysteriously disappear (#484)',
+ exports: function ( exports ) {
+ assert.equal( exports.exportedAnswer, 42 );
+ assert.equal( exports.foo(), 42 );
+ }
+};
diff --git a/test/function/disappearing-exported-value/answer.js b/test/function/disappearing-exported-value/answer.js
new file mode 100644
index 0000000..1cdee13
--- /dev/null
+++ b/test/function/disappearing-exported-value/answer.js
@@ -0,0 +1,2 @@
+var answer = 42;
+export { answer };
diff --git a/test/function/disappearing-exported-value/main.js b/test/function/disappearing-exported-value/main.js
new file mode 100644
index 0000000..260980c
--- /dev/null
+++ b/test/function/disappearing-exported-value/main.js
@@ -0,0 +1,8 @@
+import { answer as importedAnswer } from './answer.js';
+export { answer as exportedAnswer } from './answer.js';
+
+export function foo () {
+ var value;
+ value = importedAnswer;
+ return value;
+}
diff --git a/test/function/double-default-export/_config.js b/test/function/double-default-export/_config.js
new file mode 100644
index 0000000..26e86e7
--- /dev/null
+++ b/test/function/double-default-export/_config.js
@@ -0,0 +1,8 @@
+const assert = require( 'assert' );
+
+module.exports = {
+ description: 'throws on double default exports',
+ error: err => {
+ assert.equal( err.message, 'A module can only have one default export' );
+ }
+};
diff --git a/test/function/double-default-export/foo.js b/test/function/double-default-export/foo.js
new file mode 100644
index 0000000..13ef7e5
--- /dev/null
+++ b/test/function/double-default-export/foo.js
@@ -0,0 +1,2 @@
+export default 1;
+export default 2;
diff --git a/test/function/double-default-export/main.js b/test/function/double-default-export/main.js
new file mode 100644
index 0000000..afac292
--- /dev/null
+++ b/test/function/double-default-export/main.js
@@ -0,0 +1,2 @@
+import foo from './foo.js';
+console.log( foo );
diff --git a/test/function/double-named-export/_config.js b/test/function/double-named-export/_config.js
new file mode 100644
index 0000000..577b421
--- /dev/null
+++ b/test/function/double-named-export/_config.js
@@ -0,0 +1,8 @@
+const assert = require( 'assert' );
+
+module.exports = {
+ description: 'throws on duplicate named exports',
+ error: err => {
+ assert.equal( err.message, `A module cannot have multiple exports with the same name ('foo')` );
+ }
+};
diff --git a/test/function/double-named-export/foo.js b/test/function/double-named-export/foo.js
new file mode 100644
index 0000000..d0dbc69
--- /dev/null
+++ b/test/function/double-named-export/foo.js
@@ -0,0 +1,3 @@
+var foo = 1;
+export { foo };
+export { foo };
diff --git a/test/function/double-named-export/main.js b/test/function/double-named-export/main.js
new file mode 100644
index 0000000..1b3e409
--- /dev/null
+++ b/test/function/double-named-export/main.js
@@ -0,0 +1,2 @@
+import { foo } from './foo.js';
+console.log( foo );
diff --git a/test/function/double-named-reexport/_config.js b/test/function/double-named-reexport/_config.js
new file mode 100644
index 0000000..577b421
--- /dev/null
+++ b/test/function/double-named-reexport/_config.js
@@ -0,0 +1,8 @@
+const assert = require( 'assert' );
+
+module.exports = {
+ description: 'throws on duplicate named exports',
+ error: err => {
+ assert.equal( err.message, `A module cannot have multiple exports with the same name ('foo')` );
+ }
+};
diff --git a/test/function/double-named-reexport/bar.js b/test/function/double-named-reexport/bar.js
new file mode 100644
index 0000000..2263b5a
--- /dev/null
+++ b/test/function/double-named-reexport/bar.js
@@ -0,0 +1 @@
+export var foo = 2;
diff --git a/test/function/double-named-reexport/foo.js b/test/function/double-named-reexport/foo.js
new file mode 100644
index 0000000..434e3eb
--- /dev/null
+++ b/test/function/double-named-reexport/foo.js
@@ -0,0 +1,3 @@
+var foo = 1;
+export { foo };
+export { foo } from './bar.js';
diff --git a/test/function/double-named-reexport/main.js b/test/function/double-named-reexport/main.js
new file mode 100644
index 0000000..1b3e409
--- /dev/null
+++ b/test/function/double-named-reexport/main.js
@@ -0,0 +1,2 @@
+import { foo } from './foo.js';
+console.log( foo );
diff --git a/test/function/empty-exports/_config.js b/test/function/empty-exports/_config.js
new file mode 100644
index 0000000..65b2185
--- /dev/null
+++ b/test/function/empty-exports/_config.js
@@ -0,0 +1,17 @@
+var assert = require( 'assert' );
+
+var warned = false;
+
+module.exports = {
+ description: 'warns on export {}, but does not fail',
+ options: {
+ onwarn: function ( msg ) {
+ warned = true;
+ assert.ok( /main\.js has an empty export declaration/.test( msg ) );
+ }
+ },
+ exports: function ( exports ) {
+ assert.equal( Object.keys( exports ).length, 0 );
+ assert.ok( warned, 'did not warn' );
+ }
+};
diff --git a/test/function/empty-exports/main.js b/test/function/empty-exports/main.js
new file mode 100644
index 0000000..cb0ff5c
--- /dev/null
+++ b/test/function/empty-exports/main.js
@@ -0,0 +1 @@
+export {};
diff --git a/test/function/export-global/_config.js b/test/function/export-global/_config.js
new file mode 100644
index 0000000..ab430c2
--- /dev/null
+++ b/test/function/export-global/_config.js
@@ -0,0 +1,9 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'any global variables in scope can be re-exported',
+
+ exports: function ( exports ) {
+ assert.equal( exports.Buffer, Buffer );
+ }
+};
diff --git a/test/function/export-global/main.js b/test/function/export-global/main.js
new file mode 100644
index 0000000..8e0da61
--- /dev/null
+++ b/test/function/export-global/main.js
@@ -0,0 +1 @@
+export { Buffer };
diff --git a/test/function/export-two-ways-function/_config.js b/test/function/export-two-ways-function/_config.js
new file mode 100644
index 0000000..ec064dd
--- /dev/null
+++ b/test/function/export-two-ways-function/_config.js
@@ -0,0 +1,9 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'exports the same function more than one way (#648)',
+ exports: function ( exports ) {
+ assert.equal( exports.foo, exports.bar );
+ assert.equal( exports.foo(), 42 );
+ }
+};
diff --git a/test/function/export-two-ways-function/main.js b/test/function/export-two-ways-function/main.js
new file mode 100644
index 0000000..7b14c6e
--- /dev/null
+++ b/test/function/export-two-ways-function/main.js
@@ -0,0 +1,8 @@
+var bar;
+bar = foo;
+
+function foo () {
+ return 42;
+}
+
+export { foo, bar };
diff --git a/test/function/exports-flag-allowed-in-options/_config.js b/test/function/exports-flag-allowed-in-options/_config.js
new file mode 100644
index 0000000..9fb6472
--- /dev/null
+++ b/test/function/exports-flag-allowed-in-options/_config.js
@@ -0,0 +1,12 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'exports flag is passed through to bundle options',
+ options: {
+ exports: 'named'
+ },
+ exports: function ( exports ) {
+ assert.equal( exports.y, 42 );
+ assert.ok( !( 'x' in exports ) );
+ }
+};
diff --git a/test/function/exports-flag-allowed-in-options/foo.js b/test/function/exports-flag-allowed-in-options/foo.js
new file mode 100644
index 0000000..a48ffd9
--- /dev/null
+++ b/test/function/exports-flag-allowed-in-options/foo.js
@@ -0,0 +1 @@
+export var x = 42;
diff --git a/test/function/exports-flag-allowed-in-options/main.js b/test/function/exports-flag-allowed-in-options/main.js
new file mode 100644
index 0000000..04b166b
--- /dev/null
+++ b/test/function/exports-flag-allowed-in-options/main.js
@@ -0,0 +1 @@
+export { x as y } from './foo';
diff --git a/test/function/external-alias/_config.js b/test/function/external-alias/_config.js
new file mode 100644
index 0000000..3232f3b
--- /dev/null
+++ b/test/function/external-alias/_config.js
@@ -0,0 +1,28 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+module.exports = {
+ description: 'includes an external module included dynamically by an alias',
+ options: {
+ entry: path.join( __dirname, 'first', 'main.js' ),
+ external: [ 'lodash' ],
+
+ // Define a simple alias plugin for underscore
+ plugins: [
+ {
+ resolveId: function ( id ) {
+ if ( id === 'underscore' ) {
+ return 'lodash';
+ }
+ }
+ }
+ ]
+ },
+
+ context: {
+ require: function ( required ) {
+ assert.equal( required, 'lodash' );
+ return 1;
+ }
+ }
+};
diff --git a/test/function/external-alias/first/main.js b/test/function/external-alias/first/main.js
new file mode 100644
index 0000000..3503622
--- /dev/null
+++ b/test/function/external-alias/first/main.js
@@ -0,0 +1,10 @@
+import _ from 'underscore';
+import first from './module';
+
+export default function ( inputs ) {
+ if ( !_.isArray( inputs ) ) {
+ return inputs;
+ }
+
+ return first.square( inputs );
+};
diff --git a/test/function/external-alias/first/module.js b/test/function/external-alias/first/module.js
new file mode 100644
index 0000000..4bacbea
--- /dev/null
+++ b/test/function/external-alias/first/module.js
@@ -0,0 +1,7 @@
+import _ from 'underscore';
+
+export default function square ( inputs ) {
+ return _.map( inputs, function ( x ) {
+ return x * x;
+ });
+};
diff --git a/test/function/external-function/_config.js b/test/function/external-function/_config.js
new file mode 100644
index 0000000..ec2b8a6
--- /dev/null
+++ b/test/function/external-function/_config.js
@@ -0,0 +1,14 @@
+module.exports = {
+ description: 'allows external option to be a function (#522)',
+ options: {
+ external: id => {
+ return id === 'external';
+ }
+ },
+ context: {
+ require: id => {
+ if ( id === 'external' ) return 42;
+ return require( id );
+ }
+ }
+};
diff --git a/test/function/external-function/main.js b/test/function/external-function/main.js
new file mode 100644
index 0000000..bfc7dca
--- /dev/null
+++ b/test/function/external-function/main.js
@@ -0,0 +1,2 @@
+import ext from 'external';
+assert.equal( ext, 42 );
diff --git a/test/function/external-normalization/_config.js b/test/function/external-normalization/_config.js
new file mode 100644
index 0000000..d0b4cfb
--- /dev/null
+++ b/test/function/external-normalization/_config.js
@@ -0,0 +1,18 @@
+var path = require( 'path' );
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'external paths from custom resolver remain external (#633)',
+ options: {
+ external: [ 'path' ],
+ plugins: [{
+ resolveId: ( id ) => {
+ if ( id == './dep.js' ) return 'path';
+ return id;
+ }
+ }]
+ },
+ exports: exports => {
+ assert.equal( exports, path.resolve );
+ }
+};
diff --git a/test/function/external-normalization/main.js b/test/function/external-normalization/main.js
new file mode 100644
index 0000000..d6b8c6c
--- /dev/null
+++ b/test/function/external-normalization/main.js
@@ -0,0 +1,2 @@
+import { resolve } from './dep.js';
+export default resolve;
diff --git a/test/function/load-returns-string-or-null/_config.js b/test/function/load-returns-string-or-null/_config.js
new file mode 100644
index 0000000..ea80699
--- /dev/null
+++ b/test/function/load-returns-string-or-null/_config.js
@@ -0,0 +1,15 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'throws error if load returns something wacky',
+ options: {
+ plugins: [{
+ load: function () {
+ return 42;
+ }
+ }]
+ },
+ error: function ( err ) {
+ assert.ok( /load hook should return a string, a \{ code, map \} object, or nothing\/null/.test( err.message ) );
+ }
+};
diff --git a/test/function/member-expression-assignment-in-function/_config.js b/test/function/member-expression-assignment-in-function/_config.js
new file mode 100644
index 0000000..bf7e6fc
--- /dev/null
+++ b/test/function/member-expression-assignment-in-function/_config.js
@@ -0,0 +1,10 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'detect side effect in member expression assignment when not top level',
+ code: function ( code ) {
+ assert.equal( code.indexOf( 'function set(key, value) { foo[key] = value; }' ) >= 0, true, code );
+ assert.equal( code.indexOf( 'set("bar", 2);' ) >= 0, true, code );
+ assert.equal( code.indexOf( 'set("qux", 3);' ) >= 0, true, code );
+ }
+}
diff --git a/test/function/member-expression-assignment-in-function/main.js b/test/function/member-expression-assignment-in-function/main.js
new file mode 100644
index 0000000..f627721
--- /dev/null
+++ b/test/function/member-expression-assignment-in-function/main.js
@@ -0,0 +1,9 @@
+var foo = {};
+
+function set(key, value) { foo[key] = value; }
+
+set("bar", 2);
+set("qux", 3);
+
+console.log(foo);
+
diff --git a/test/function/object-destructuring-renaming/_config.js b/test/function/object-destructuring-renaming/_config.js
new file mode 100644
index 0000000..4a1b8b6
--- /dev/null
+++ b/test/function/object-destructuring-renaming/_config.js
@@ -0,0 +1,12 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'renaming destructured object properties should request the correct property (#527)',
+
+ // we must transpile the object destructuring to test it
+ babel: true,
+
+ exports: function ( exports ) {
+ assert.equal( exports.env, process.env );
+ }
+};
diff --git a/test/function/object-destructuring-renaming/main.js b/test/function/object-destructuring-renaming/main.js
new file mode 100644
index 0000000..cc67a81
--- /dev/null
+++ b/test/function/object-destructuring-renaming/main.js
@@ -0,0 +1,3 @@
+import { getEnv } from './module.js';
+
+export var env = getEnv();
diff --git a/test/function/object-destructuring-renaming/module.js b/test/function/object-destructuring-renaming/module.js
new file mode 100644
index 0000000..787b1b9
--- /dev/null
+++ b/test/function/object-destructuring-renaming/module.js
@@ -0,0 +1,5 @@
+const { env } = process;
+
+export function getEnv() {
+ return env;
+}
diff --git a/test/function/relative-external-include-once-nested/_config.js b/test/function/relative-external-include-once-nested/_config.js
new file mode 100644
index 0000000..07aa08e
--- /dev/null
+++ b/test/function/relative-external-include-once-nested/_config.js
@@ -0,0 +1,18 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+module.exports = {
+ description: 'includes a relative external module only once (nested version)',
+ options: {
+ external: path.join( __dirname, './first/foo.js' )
+ },
+ context: {
+ require: function ( required ) {
+ assert.equal( required, './first/foo.js' );
+ return 1;
+ }
+ },
+ exports: function ( exports ) {
+ assert.equal( exports, 3 );
+ }
+};
diff --git a/test/function/relative-external-include-once-nested/first/foo.js b/test/function/relative-external-include-once-nested/first/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/relative-external-include-once-nested/first/module.js b/test/function/relative-external-include-once-nested/first/module.js
new file mode 100644
index 0000000..a0aecca
--- /dev/null
+++ b/test/function/relative-external-include-once-nested/first/module.js
@@ -0,0 +1,4 @@
+import foo from './foo';
+import second from './second/module';
+
+export default foo + second;
diff --git a/test/function/relative-external-include-once-nested/first/second/module.js b/test/function/relative-external-include-once-nested/first/second/module.js
new file mode 100644
index 0000000..4fa8fdc
--- /dev/null
+++ b/test/function/relative-external-include-once-nested/first/second/module.js
@@ -0,0 +1,3 @@
+import foo from '../foo';
+
+export default foo;
diff --git a/test/function/relative-external-include-once-nested/main.js b/test/function/relative-external-include-once-nested/main.js
new file mode 100644
index 0000000..545e333
--- /dev/null
+++ b/test/function/relative-external-include-once-nested/main.js
@@ -0,0 +1,4 @@
+import foo from './first/foo';
+import first from './first/module';
+
+export default foo + first;
diff --git a/test/function/relative-external-include-once-two-external/_config.js b/test/function/relative-external-include-once-two-external/_config.js
new file mode 100644
index 0000000..d83e72f
--- /dev/null
+++ b/test/function/relative-external-include-once-two-external/_config.js
@@ -0,0 +1,22 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+
+module.exports = {
+ description: 'includes a relative external module only once (two external deps)',
+ options: {
+ external: [
+ path.join( __dirname, './foo.js' ),
+ path.join( __dirname, './first/foo.js' )
+ ]
+ },
+ context: {
+ require: function ( required ) {
+ assert( [ './foo.js', './first/foo.js' ].indexOf(required) !== -1, 'required wrong module' );
+ return required === './foo.js' ? 'a' : 'b';
+ }
+ },
+ exports: function ( exports ) {
+ assert( exports === 'ab' || exports === 'ba', 'two different modules should be required' );
+ }
+};
diff --git a/test/function/relative-external-include-once-two-external/first/foo.js b/test/function/relative-external-include-once-two-external/first/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/relative-external-include-once-two-external/first/module.js b/test/function/relative-external-include-once-two-external/first/module.js
new file mode 100644
index 0000000..4ad6554
--- /dev/null
+++ b/test/function/relative-external-include-once-two-external/first/module.js
@@ -0,0 +1,3 @@
+import foo from './foo';
+
+export default foo;
diff --git a/test/function/relative-external-include-once-two-external/foo.js b/test/function/relative-external-include-once-two-external/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/relative-external-include-once-two-external/main.js b/test/function/relative-external-include-once-two-external/main.js
new file mode 100644
index 0000000..dff375c
--- /dev/null
+++ b/test/function/relative-external-include-once-two-external/main.js
@@ -0,0 +1,4 @@
+import foo from './foo';
+import first from './first/module';
+
+export default foo + first;
diff --git a/test/function/relative-external-include-once-up/_config.js b/test/function/relative-external-include-once-up/_config.js
new file mode 100644
index 0000000..15821ba
--- /dev/null
+++ b/test/function/relative-external-include-once-up/_config.js
@@ -0,0 +1,19 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+module.exports = {
+ description: 'includes a relative external module only once (from upper directory too)',
+ options: {
+ entry: path.join( __dirname, 'first', 'main.js' ),
+ external: path.join( __dirname, './foo.js' )
+ },
+ context: {
+ require: function ( required ) {
+ assert.equal( required, '../foo.js' );
+ return 1;
+ }
+ },
+ exports: function ( exports ) {
+ assert.equal( exports, 3 );
+ }
+};
diff --git a/test/function/relative-external-include-once-up/first/main.js b/test/function/relative-external-include-once-up/first/main.js
new file mode 100644
index 0000000..a07e358
--- /dev/null
+++ b/test/function/relative-external-include-once-up/first/main.js
@@ -0,0 +1,4 @@
+import foo from '../foo';
+import first from './module';
+
+export default foo + first;
diff --git a/test/function/relative-external-include-once-up/first/module.js b/test/function/relative-external-include-once-up/first/module.js
new file mode 100644
index 0000000..0798b47
--- /dev/null
+++ b/test/function/relative-external-include-once-up/first/module.js
@@ -0,0 +1,4 @@
+import foo from '../foo';
+import second from './second/module';
+
+export default foo + second;
diff --git a/test/function/relative-external-include-once-up/first/second/module.js b/test/function/relative-external-include-once-up/first/second/module.js
new file mode 100644
index 0000000..b643f0c
--- /dev/null
+++ b/test/function/relative-external-include-once-up/first/second/module.js
@@ -0,0 +1,3 @@
+import foo from '../../foo';
+
+export default foo;
diff --git a/test/function/relative-external-include-once-up/foo.js b/test/function/relative-external-include-once-up/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/relative-external-include-once/_config.js b/test/function/relative-external-include-once/_config.js
new file mode 100644
index 0000000..4349dc1
--- /dev/null
+++ b/test/function/relative-external-include-once/_config.js
@@ -0,0 +1,18 @@
+var assert = require( 'assert' );
+var path = require( 'path' );
+
+module.exports = {
+ description: 'includes a relative external module only once',
+ options: {
+ external: path.join( __dirname, './foo.js' )
+ },
+ context: {
+ require: function ( required ) {
+ assert.equal( required, './foo.js' );
+ return 1;
+ }
+ },
+ exports: function ( exports ) {
+ assert.equal( exports, 3 );
+ }
+};
diff --git a/test/function/relative-external-include-once/first/module.js b/test/function/relative-external-include-once/first/module.js
new file mode 100644
index 0000000..0798b47
--- /dev/null
+++ b/test/function/relative-external-include-once/first/module.js
@@ -0,0 +1,4 @@
+import foo from '../foo';
+import second from './second/module';
+
+export default foo + second;
diff --git a/test/function/relative-external-include-once/first/second/module.js b/test/function/relative-external-include-once/first/second/module.js
new file mode 100644
index 0000000..b643f0c
--- /dev/null
+++ b/test/function/relative-external-include-once/first/second/module.js
@@ -0,0 +1,3 @@
+import foo from '../../foo';
+
+export default foo;
diff --git a/test/function/relative-external-include-once/foo.js b/test/function/relative-external-include-once/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/relative-external-include-once/main.js b/test/function/relative-external-include-once/main.js
new file mode 100644
index 0000000..dff375c
--- /dev/null
+++ b/test/function/relative-external-include-once/main.js
@@ -0,0 +1,4 @@
+import foo from './foo';
+import first from './first/module';
+
+export default foo + first;
diff --git a/test/function/report-transform-error-file/_config.js b/test/function/report-transform-error-file/_config.js
new file mode 100644
index 0000000..c856974
--- /dev/null
+++ b/test/function/report-transform-error-file/_config.js
@@ -0,0 +1,17 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'reports which file caused a transform error',
+ options: {
+ plugins: [{
+ transform: function ( code, id ) {
+ if ( /foo/.test( id ) ) {
+ throw new Error( 'nope' );
+ }
+ }
+ }]
+ },
+ error: function ( err ) {
+ assert.ok( ~err.message.indexOf( 'foo.js' ) );
+ }
+};
diff --git a/test/function/report-transform-error-file/foo.js b/test/function/report-transform-error-file/foo.js
new file mode 100644
index 0000000..a2db33b
--- /dev/null
+++ b/test/function/report-transform-error-file/foo.js
@@ -0,0 +1,3 @@
+export default function () {
+ console.log( 'foo' );
+}
diff --git a/test/function/report-transform-error-file/main.js b/test/function/report-transform-error-file/main.js
new file mode 100644
index 0000000..e1fb5c4
--- /dev/null
+++ b/test/function/report-transform-error-file/main.js
@@ -0,0 +1,3 @@
+import foo from './foo.js';
+
+foo();
diff --git a/test/function/skips-dead-branches-f/_config.js b/test/function/skips-dead-branches-f/_config.js
index 428bd69..e43c622 100644
--- a/test/function/skips-dead-branches-f/_config.js
+++ b/test/function/skips-dead-branches-f/_config.js
@@ -1,7 +1,7 @@
var assert = require( 'assert' );
module.exports = {
- description: 'skips a dead branch (g)',
+ description: 'skips a dead branch (f)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
diff --git a/test/function/skips-dead-branches-g/_config.js b/test/function/skips-dead-branches-g/_config.js
new file mode 100644
index 0000000..d1e507d
--- /dev/null
+++ b/test/function/skips-dead-branches-g/_config.js
@@ -0,0 +1,9 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'skips a dead conditional expression branch (g)',
+ code: function ( code ) {
+ assert.ok( code.indexOf( 'var c = a;' ) >= 0, code );
+ assert.ok( code.indexOf( 'var d = b;' ) >= 0, code );
+ }
+};
diff --git a/test/function/skips-dead-branches-g/main.js b/test/function/skips-dead-branches-g/main.js
new file mode 100644
index 0000000..0c271f4
--- /dev/null
+++ b/test/function/skips-dead-branches-g/main.js
@@ -0,0 +1,6 @@
+var a = 0;
+var b = 1;
+var c = true ? a : b;
+var d = false ? a : b;
+
+console.log( c + d );
diff --git a/test/function/trim-conditional-branches-in-exports/_config.js b/test/function/trim-conditional-branches-in-exports/_config.js
new file mode 100644
index 0000000..c084f7e
--- /dev/null
+++ b/test/function/trim-conditional-branches-in-exports/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'trims conditional branches with a renamed default export'
+};
diff --git a/test/function/trim-conditional-branches-in-exports/foo.js b/test/function/trim-conditional-branches-in-exports/foo.js
new file mode 100644
index 0000000..82df459
--- /dev/null
+++ b/test/function/trim-conditional-branches-in-exports/foo.js
@@ -0,0 +1,2 @@
+var foo = 0;
+export default Math.random() < 0.5 ? foo : foo;
diff --git a/test/function/trim-conditional-branches-in-exports/main.js b/test/function/trim-conditional-branches-in-exports/main.js
new file mode 100644
index 0000000..8e67e6f
--- /dev/null
+++ b/test/function/trim-conditional-branches-in-exports/main.js
@@ -0,0 +1,2 @@
+import foo from './foo.js';
+console.log( true ? false ? foo : 0 : 1 );
diff --git a/test/function/warn-on-auto-named-default-exports/_config.js b/test/function/warn-on-auto-named-default-exports/_config.js
new file mode 100644
index 0000000..f093781
--- /dev/null
+++ b/test/function/warn-on-auto-named-default-exports/_config.js
@@ -0,0 +1,10 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'warns if default and named exports are used in auto mode',
+ warnings: function ( warnings ) {
+ assert.deepEqual( warnings, [
+ 'Using named and default exports together. Consumers of your bundle will have to use bundle[\'default\'] to access the default export, which may not be what you want. Use `exports: \'named\'` to disable this warning. See https://github.com/rollup/rollup/wiki/JavaScript-API#exports for more information'
+ ]);
+ }
+};
diff --git a/test/function/warn-on-auto-named-default-exports/main.js b/test/function/warn-on-auto-named-default-exports/main.js
new file mode 100644
index 0000000..74d988c
--- /dev/null
+++ b/test/function/warn-on-auto-named-default-exports/main.js
@@ -0,0 +1,10 @@
+function foo () {
+ console.log( 'foo' );
+}
+
+function bar () {
+ console.log( 'bar' );
+}
+
+export default foo;
+export { bar };
diff --git a/test/function/warn-on-eval/_config.js b/test/function/warn-on-eval/_config.js
index 62a3ee4..169171c 100644
--- a/test/function/warn-on-eval/_config.js
+++ b/test/function/warn-on-eval/_config.js
@@ -8,7 +8,7 @@ module.exports = {
options: {
onwarn: function ( message ) {
warned = true;
- assert.ok( /Use of `eval` \(in .+?main\.js\) is discouraged, as it may cause issues with minification\. See https:\/\/github.com\/rollup\/rollup\/wiki\/Troubleshooting#avoiding-eval for more details/.test( message ) );
+ assert.ok( /Use of `eval` \(in .+?main\.js\) is strongly discouraged, as it poses security risks and may cause issues with minification\. See https:\/\/github.com\/rollup\/rollup\/wiki\/Troubleshooting#avoiding-eval for more details/.test( message ) );
}
},
exports: function () {
diff --git a/test/sourcemaps/single-length-segments/_config.js b/test/sourcemaps/single-length-segments/_config.js
new file mode 100644
index 0000000..76d47e0
--- /dev/null
+++ b/test/sourcemaps/single-length-segments/_config.js
@@ -0,0 +1,37 @@
+var fs = require( 'fs' );
+var path = require( 'path' );
+var assert = require( 'assert' );
+var getLocation = require( '../../utils/getLocation' );
+var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer;
+
+var original = fs.readFileSync( path.resolve( __dirname, 'main.js' ), 'utf-8' );
+
+module.exports = {
+ description: 'handles single-length sourcemap segments',
+ options: {
+ plugins: [
+ {
+ transform: function () {
+ return {
+ code: fs.readFileSync( path.resolve( __dirname, 'output.js' ), 'utf-8' ),
+ map: fs.readFileSync( path.resolve( __dirname, 'output.js.map' ), 'utf-8' )
+ };
+ }
+ }
+ ],
+ moduleName: 'x'
+ },
+ test: function ( code, map ) {
+ var smc = new SourceMapConsumer( map );
+
+ [ 'Foo', 'log' ].forEach( function ( token ) {
+ var generatedLoc = getLocation( code, code.indexOf( token ) );
+ var originalLoc = smc.originalPositionFor( generatedLoc );
+ var expectedLoc = getLocation( original, original.indexOf( token ) );
+
+ assert.ok( /main/.test( originalLoc.source ) );
+ assert.equal( originalLoc.line, expectedLoc.line );
+ assert.equal( originalLoc.column, expectedLoc.column );
+ });
+ }
+};
diff --git a/test/sourcemaps/single-length-segments/main.js b/test/sourcemaps/single-length-segments/main.js
new file mode 100644
index 0000000..49c57e7
--- /dev/null
+++ b/test/sourcemaps/single-length-segments/main.js
@@ -0,0 +1,7 @@
+class Foo {
+ bar () {
+ console.log( 42 );
+ }
+}
+
+export { Foo };
diff --git a/test/sourcemaps/single-length-segments/output.js b/test/sourcemaps/single-length-segments/output.js
new file mode 100644
index 0000000..4121f3a
--- /dev/null
+++ b/test/sourcemaps/single-length-segments/output.js
@@ -0,0 +1,15 @@
+var Foo = function () {
+ function Foo() {
+ babelHelpers.classCallCheck(this, Foo);
+ }
+
+ babelHelpers.createClass(Foo, [{
+ key: "bar",
+ value: function bar() {
+ console.log(42);
+ }
+ }]);
+ return Foo;
+}();
+
+export { Foo };
diff --git a/test/sourcemaps/single-length-segments/output.js.map b/test/sourcemaps/single-length-segments/output.js.map
new file mode 100644
index 0000000..4f0165c
--- /dev/null
+++ b/test/sourcemaps/single-length-segments/output.js.map
@@ -0,0 +1,8 @@
+{
+ "version":3,
+ "sources":["index.js"],
+ "names":[],
+ "mappings":"IAAM,G;;;;;;;wBACE;AACN,WAAQ,GAAR,CAAa,EAAb;AACA;;;;;AAGF,SAAS,GAAT",
+ "file":"index.js",
+ "sourcesContent":["class Foo {\n\tbar () {\n\t\tconsole.log( 42 );\n\t}\n}\n\nexport { Foo };\n"]
+}
diff --git a/test/test.js b/test/test.js
index bf6e5a2..22239fe 100644
--- a/test/test.js
+++ b/test/test.js
@@ -76,7 +76,7 @@ describe( 'rollup', function () {
return rollup.rollup({ entry: 'x', plUgins: [] }).then( function () {
throw new Error( 'Missing expected error' );
}, function ( err ) {
- assert.equal( 'Unexpected key \'plUgins\' found, expected one of: banner, dest, entry, external, footer, format, globals, indent, intro, moduleId, moduleName, onwarn, outro, plugins, sourceMap', err.message );
+ assert.equal( err.message, 'Unexpected key \'plUgins\' found, expected one of: banner, dest, entry, exports, external, footer, format, globals, indent, intro, moduleId, moduleName, noConflict, onwarn, outro, plugins, preferConst, sourceMap, treeshake, useStrict' );
});
});
});
@@ -133,9 +133,13 @@ describe( 'rollup', function () {
var config = loadConfig( FUNCTION + '/' + dir + '/_config.js' );
( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () {
- var options = extend( {}, config.options, {
- entry: FUNCTION + '/' + dir + '/main.js'
- });
+ var warnings = [];
+ var captureWarning = msg => warnings.push( msg );
+
+ var options = extend( {
+ entry: FUNCTION + '/' + dir + '/main.js',
+ onwarn: captureWarning
+ }, config.options );
if ( config.solo ) console.group( dir );
@@ -149,6 +153,7 @@ describe( 'rollup', function () {
// try to generate output
try {
+ if(config.bundleOptions) { console.log(config.bundleOptions); }
var result = bundle.generate( extend( {}, config.bundleOptions, {
format: 'cjs'
}));
@@ -214,6 +219,12 @@ describe( 'rollup', function () {
}
}
+ if ( config.warnings ) {
+ config.warnings( warnings );
+ } else if ( warnings.length ) {
+ throw new Error( `Got unexpected warnings:\n${warnings.join('\n')}` );
+ }
+
if ( config.show || unintendedError ) {
console.log( code + '\n\n\n' );
}
@@ -342,7 +353,10 @@ describe( 'rollup', function () {
PATH: path.resolve( __dirname, '../bin' ) + path.delimiter + process.env.PATH
}
}, function ( err, code, stderr ) {
- if ( err ) return done( err );
+ if ( err || config.error ) {
+ config.error( err );
+ return done();
+ }
if ( stderr ) console.error( stderr );