diff --git a/.babelrc b/.babelrc
index 6ce65b2..ed25dc0 100644
--- a/.babelrc
+++ b/.babelrc
@@ -5,6 +5,7 @@
"es6.classes",
"es6.constants",
"es6.destructuring",
+ "es6.modules",
"es6.parameters",
"es6.properties.shorthand",
"es6.spread",
diff --git a/.eslintrc b/.eslintrc
index 11f6d54..6e5fb1a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,15 +1,19 @@
{
"rules": {
- "indent": [ 2, "tab", { "SwitchCase": 1}],
+ "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",
diff --git a/.gitignore b/.gitignore
index 5000af5..41653e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ node_modules
.gobble*
dist
_actual
+coverage
diff --git a/.travis.yml b/.travis.yml
index 7fdfdb4..9c889c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,8 @@
sudo: false
language: node_js
node_js:
- - "0.10"
- "0.12"
- - "iojs"
+ - "4"
env:
global:
- BUILD_TIMEOUT=10000
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d58f37b..cde4345 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,32 @@
# rollup changelog
+## 0.16.4
+
+* Fix import paths with `.` ([#133](https://github.com/rollup/rollup/issues/133))
+* Prevent sourceMappingURL confusion leading to broken sourcemap
+* Add code coverage reporting [#130](https://github.com/rollup/rollup/pull/130))
+* Add `modules` property to user-facing `bundle` – an array with `{id}` objects ([#128](https://github.com/rollup/rollup/issues/128))
+
+## 0.16.3
+
+* Prevent adjacent blocks of multiple var declarations causing magic-string failure ([#105](https://github.com/rollup/rollup/issues/105))
+
+## 0.16.2
+
+* Top-level function calls and assignments to globals are treated as side-effects, and always included
+* Import files from subdirectories of external packages, e.g. `import mod from 'foo/sub/mod'` ([#126](https://github.com/rollup/rollup/issues/126))
+
+## 0.16.1
+
+* Handle assignment patterns, and destructured/rest parameters, when analysing scopes
+* Fix bug preventing project from self-building (make base `Identifier` class markable)
+
+## 0.16.0
+
+* Internal refactoring ([#99](https://github.com/rollup/rollup/pull/99))
+* Optimisation for statically-analysable namespace imports ([#99](https://github.com/rollup/rollup/pull/99))
+* Windows support (theoretically!) ([#117](https://github.com/rollup/rollup/pull/117) / [#119](https://github.com/rollup/rollup/pull/119))
+
## 0.15.0
* Load all modules specified by `import` statements, and do tree-shaking synchronously once loading is complete. This results in simpler and faster code, and enables future improvements ([#97](https://github.com/rollup/rollup/pull/97))
diff --git a/README.md b/README.md
index 978fded..265a504 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,9 @@
+
+
+
> *I roll up, I roll up, I roll up, Shawty I roll up*
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..cd3fab4
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,33 @@
+# http://www.appveyor.com/docs/appveyor-yml
+
+version: "{build}"
+
+clone_depth: 10
+
+init:
+ - git config --global core.autocrlf false
+
+environment:
+ matrix:
+ # node.js
+ - nodejs_version: 0.10
+ - nodejs_version: 0.12
+ # io.js
+ - nodejs_version: 1
+
+install:
+ - ps: Install-Product node $env:nodejs_version
+ - npm install
+
+build: off
+
+test_script:
+ - node --version && npm --version
+ - npm test
+
+matrix:
+ fast_finish: false
+
+# cache:
+# - C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache
+# - node_modules -> package.json # local npm modules
diff --git a/browser/sander.js b/browser/sander.js
index 6436076..5dbe4fc 100644
--- a/browser/sander.js
+++ b/browser/sander.js
@@ -1,3 +1,7 @@
+export function readdirSync () {
+ throw new Error( 'Cannot use sander.readdirSync inside browser' );
+}
+
export function readFile () {
throw new Error( 'Cannot use sander.readFile inside browser' );
}
diff --git a/gobblefile.js b/gobblefile.js
index 6036237..4042dd7 100644
--- a/gobblefile.js
+++ b/gobblefile.js
@@ -8,7 +8,8 @@ var node = src
entry: 'rollup.js',
dest: 'rollup.js',
format: 'cjs',
- external: [ 'sander', 'acorn' ]
+ external: [ 'sander', 'acorn' ],
+ sourceMap: true
})
.transform( 'babel' );
diff --git a/package.json b/package.json
index 1e18cfa..b95ed8b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rollup",
- "version": "0.15.0",
+ "version": "0.17.0",
"description": "Next-generation ES6 module bundler",
"main": "dist/rollup.js",
"jsnext:main": "src/rollup.js",
@@ -8,15 +8,19 @@
"rollup": "./bin/rollup"
},
"scripts": {
- "test": "mocha",
"pretest": "npm run build",
+ "test": "mocha",
+ "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",
+ "ci": "npm run test-coverage && codecov < coverage/coverage-remapped.lcov",
"build": "gobble build -f dist",
"prepublish": "npm test",
"lint": "eslint src"
},
"repository": {
"type": "git",
- "url": "https://github.com/rich-harris/rollup"
+ "url": "https://github.com/rollup/rollup"
},
"keywords": [
"modules",
@@ -26,13 +30,18 @@
"optimizer"
],
"author": "Rich Harris",
+ "contributors": [
+ "Oskar Segersvärd "
+ ],
"license": "MIT",
"bugs": {
- "url": "https://github.com/rich-harris/rollup/issues"
+ "url": "https://github.com/rollup/rollup/issues"
},
- "homepage": "https://github.com/rich-harris/rollup",
+ "homepage": "https://github.com/rollup/rollup",
"devDependencies": {
+ "babel": "^5.8.21",
"babel-core": "^5.5.8",
+ "codecov.io": "^0.1.6",
"console-group": "^0.1.2",
"eslint": "^1.1.0",
"gobble": "^0.10.1",
@@ -40,9 +49,11 @@
"gobble-browserify": "^0.6.1",
"gobble-cli": "^0.4.2",
"gobble-esperanto-bundle": "^0.2.0",
- "gobble-rollup": "^0.7.0",
+ "gobble-rollup": "^0.8.0",
"gobble-rollup-babel": "^0.1.0",
+ "istanbul": "^0.3.20",
"mocha": "^2.2.4",
+ "remap-istanbul": "^0.2.0",
"source-map": "^0.4.4"
},
"dependencies": {
diff --git a/src/Bundle.js b/src/Bundle.js
index 25cff8a..5a6199d 100644
--- a/src/Bundle.js
+++ b/src/Bundle.js
@@ -1,4 +1,3 @@
-import { basename, extname } from './utils/path';
import { Promise } from 'sander';
import MagicString from 'magic-string';
import { blank, keys } from './utils/object';
@@ -66,7 +65,7 @@ export default class Bundle {
// `export default a + b` - generate an export name
// based on the id of the entry module
else {
- let defaultExportName = makeLegalIdentifier( basename( this.entryModule.id ).slice( 0, -extname( this.entryModule.id ).length ) );
+ let defaultExportName = this.entryModule.basename();
// deconflict
let topLevelNames = [];
@@ -84,16 +83,23 @@ export default class Bundle {
entryModule.markAllStatements( true );
this.markAllModifierStatements();
+
+ // Include all side-effects
+ // TODO does this obviate the need for markAllStatements throughout?
+ this.modules.forEach( module => {
+ module.markAllSideEffects();
+ });
+
this.orderedModules = this.sort();
});
}
// TODO would be better to deconflict once, rather than per-render
deconflict ( es6 ) {
- let usedNames = blank();
+ let nameCount = blank();
// ensure no conflicts with globals
- keys( this.assumedGlobals ).forEach( name => usedNames[ name ] = true );
+ keys( this.assumedGlobals ).forEach( name => nameCount[ name ] = 0 );
let allReplacements = blank();
@@ -158,11 +164,15 @@ export default class Bundle {
});
function getSafeName ( name ) {
- while ( usedNames[ name ] ) {
- name = `_${name}`;
+ if ( name in nameCount ) {
+ nameCount[ name ] += 1;
+ name = `${name}$${nameCount[ name ]}`;
+
+ while ( name in nameCount ) name = `_${name}`; // just to avoid any crazy edge cases
+ return name;
}
- usedNames[ name ] = true;
+ nameCount[ name ] = 0;
return name;
}
@@ -322,8 +332,7 @@ export default class Bundle {
// since we're rewriting variable exports, we want to
// ensure we don't try and export them again at the bottom
- this.toExport = keys( this.entryModule.exports )
- .concat( keys( this.entryModule.reexports ) )
+ this.toExport = this.entryModule.getExports()
.filter( key => !varExports[ key ] );
let magicString = new MagicString.Bundle({ separator: '\n\n' });
@@ -501,8 +510,12 @@ export default class Bundle {
const exportDeclaration = module.exports[ name ];
if ( exportDeclaration ) return this.trace( module, exportDeclaration.localName );
- const exportDelegate = module.exportDelegates[ name ];
- if ( exportDelegate ) return this.traceExport( exportDelegate.module, name, es6 );
+ for ( let i = 0; i < module.exportAlls.length; i += 1 ) {
+ const declaration = module.exportAlls[i];
+ if ( declaration.module.exports[ name ] ) {
+ return this.traceExport( declaration.module, name, es6 );
+ }
+ }
throw new Error( `Could not trace binding '${name}' from ${module.id}` );
}
diff --git a/src/Module.js b/src/Module.js
index 384fa7d..135eb13 100644
--- a/src/Module.js
+++ b/src/Module.js
@@ -3,8 +3,10 @@ import MagicString from 'magic-string';
import Statement from './Statement';
import walk from './ast/walk';
import { blank, keys } from './utils/object';
+import { basename, extname } from './utils/path';
import getLocation from './utils/getLocation';
import makeLegalIdentifier from './utils/makeLegalIdentifier';
+import SOURCEMAPPING_URL from './utils/sourceMappingURL';
function deconflict ( name, names ) {
while ( name in names ) {
@@ -37,7 +39,7 @@ export default class Module {
});
// remove existing sourceMappingURL comments
- const pattern = /\/\/#\s+sourceMappingURL=.+\n?/g;
+ const pattern = new RegExp( `\\/\\/#\\s+${SOURCEMAPPING_URL}=.+\\n?`, 'g' );
let match;
while ( match = pattern.exec( source ) ) {
this.magicString.remove( match.index, match.index + match[0].length );
@@ -243,6 +245,10 @@ export default class Module {
});
}
+ basename () {
+ return makeLegalIdentifier( basename( this.id ).slice( 0, -extname( this.id ).length ) );
+ }
+
bindImportSpecifiers () {
if ( this.boundImportSpecifiers ) return;
this.boundImportSpecifiers = true;
@@ -329,6 +335,16 @@ export default class Module {
});
});
+ // special case – `export { ... } from './other'` in entry module
+ if ( this.exportAlls.length ) {
+ this.exportAlls.forEach( ({ source }) => {
+ const resolved = this.resolvedIds[ source ];
+ const otherModule = this.bundle.moduleById[ resolved ];
+
+ strongDependencies[ otherModule.id ] = otherModule;
+ });
+ }
+
return { strongDependencies, weakDependencies };
}
@@ -355,6 +371,26 @@ export default class Module {
return importDeclaration.module.findDefiningStatement( name );
}
+ getExports () {
+ let exports = blank();
+
+ keys( this.exports ).forEach( name => {
+ exports[ name ] = true;
+ });
+
+ keys( this.reexports ).forEach( name => {
+ exports[ name ] = true;
+ });
+
+ this.exportAlls.forEach( ({ module }) => {
+ module.getExports().forEach( name => {
+ if ( name !== 'default' ) exports[ name ] = true;
+ });
+ });
+
+ return keys( exports );
+ }
+
mark ( name ) {
// shortcut cycles
if ( this.marked[ name ] ) return;
@@ -418,6 +454,12 @@ export default class Module {
}
}
+ markAllSideEffects () {
+ this.statements.forEach( statement => {
+ statement.markSideEffect();
+ });
+ }
+
markAllStatements ( isEntryModule ) {
this.statements.forEach( statement => {
if ( statement.isIncluded ) return; // TODO can this happen? probably not...
@@ -530,8 +572,12 @@ export default class Module {
// should be split up. Otherwise, we may end up including code we
// don't need, just because an unwanted declarator is included
if ( node.type === 'VariableDeclaration' && node.declarations.length > 1 ) {
- // remove the leading var/let/const
- this.magicString.remove( node.start, node.declarations[0].start );
+ // remove the leading var/let/const... UNLESS the previous node
+ // was also a synthetic node, in which case it'll get removed anyway
+ const lastStatement = statements[ statements.length - 1 ];
+ if ( !lastStatement || !lastStatement.node.isSynthetic ) {
+ this.magicString.remove( node.start, node.declarations[0].start );
+ }
node.declarations.forEach( declarator => {
const { start, end } = declarator;
@@ -642,7 +688,12 @@ export default class Module {
statement.replaceIdentifiers( magicString, replacements, bundleExports );
// modify exports as necessary
- if ( statement.isExportDeclaration ) {
+ if ( statement.isReexportDeclaration ) {
+ // remove `export { foo } from './other'` and `export * from './other'`
+ magicString.remove( statement.start, statement.next );
+ }
+
+ else if ( statement.isExportDeclaration ) {
// remove `export` from `export var foo = 42`
if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration' ) {
magicString.remove( statement.node.start, statement.node.declaration.start );
diff --git a/src/Statement.js b/src/Statement.js
index ae4638d..5cc62cf 100644
--- a/src/Statement.js
+++ b/src/Statement.js
@@ -3,6 +3,16 @@ import getLocation from './utils/getLocation';
import walk from './ast/walk';
import Scope from './ast/Scope';
+const blockDeclarations = {
+ 'const': true,
+ 'let': true
+};
+
+const modifierNodes = {
+ AssignmentExpression: 'left',
+ UpdateExpression: 'argument'
+};
+
function isIife ( node, parent ) {
return parent && parent.type === 'CallExpression' && node === parent.callee;
}
@@ -31,6 +41,7 @@ export default class Statement {
this.reassigns = blank();
+ this.hasSideEffects = false;
this.isIncluded = false;
this.isImportDeclaration = node.type === 'ImportDeclaration';
@@ -49,7 +60,8 @@ export default class Statement {
switch ( node.type ) {
case 'FunctionDeclaration':
- scope.addDeclaration( node.id.name, node, false );
+ scope.addDeclaration( node, false, false );
+ break;
case 'BlockStatement':
if ( parent && /Function/.test( parent.type ) ) {
@@ -62,7 +74,7 @@ export default class Statement {
// named function expressions - the name is considered
// part of the function's scope
if ( parent.type === 'FunctionExpression' && parent.id ) {
- newScope.addDeclaration( parent.id.name, parent, false );
+ newScope.addDeclaration( parent, false, false );
}
} else {
newScope = new Scope({
@@ -84,12 +96,13 @@ export default class Statement {
case 'VariableDeclaration':
node.declarations.forEach( declarator => {
- scope.addDeclaration( declarator.id.name, node, true );
+ const isBlockDeclaration = node.type === 'VariableDeclaration' && blockDeclarations[ node.kind ];
+ scope.addDeclaration( declarator, isBlockDeclaration, true );
});
break;
case 'ClassDeclaration':
- scope.addDeclaration( node.id.name, node, false );
+ scope.addDeclaration( node, false, false );
break;
}
@@ -265,14 +278,22 @@ export default class Statement {
const id = this.module.resolvedIds[ this.node.source.value ];
const otherModule = this.module.bundle.moduleById[ id ];
- this.node.specifiers.forEach( specifier => {
- const reexport = this.module.reexports[ specifier.exported.name ];
+ if ( this.node.specifiers ) {
+ this.node.specifiers.forEach( specifier => {
+ const reexport = this.module.reexports[ specifier.exported.name ];
- reexport.isUsed = true;
- reexport.module = otherModule; // TODO still necessary?
+ reexport.isUsed = true;
+ reexport.module = otherModule; // TODO still necessary?
- if ( !otherModule.isExternal ) otherModule.markExport( specifier.local.name, specifier.exported.name, this.module );
- });
+ if ( !otherModule.isExternal ) otherModule.markExport( specifier.local.name, specifier.exported.name, this.module );
+ });
+ } else {
+ otherModule.needsAll = true;
+
+ otherModule.getExports().forEach( name => {
+ if ( name !== 'default' ) otherModule.markExport( name, name, this.module );
+ });
+ }
return;
}
@@ -283,6 +304,32 @@ export default class Statement {
});
}
+ markSideEffect () {
+ const statement = this;
+
+ walk( this.node, {
+ enter ( node, parent ) {
+ if ( /Function/.test( node.type ) && !isIife( node, parent ) ) return this.skip();
+
+ // If this is a top-level call expression, or an assignment to a global,
+ // this statement will need to be marked
+ if ( node.type === 'CallExpression' ) {
+ statement.mark();
+ }
+
+ else if ( node.type in modifierNodes ) {
+ let subject = node[ modifierNodes[ node.type ] ];
+ while ( subject.type === 'MemberExpression' ) subject = subject.object;
+
+ const bundle = statement.module.bundle;
+ const canonicalName = bundle.trace( statement.module, subject.name );
+
+ if ( bundle.assumedGlobals[ canonicalName ] ) statement.mark();
+ }
+ }
+ });
+ }
+
replaceIdentifiers ( magicString, names, bundleExports ) {
const replacementStack = [ names ];
const nameList = keys( names );
diff --git a/src/ast/Scope.js b/src/ast/Scope.js
index aeb9da7..7bd79bf 100644
--- a/src/ast/Scope.js
+++ b/src/ast/Scope.js
@@ -1,10 +1,38 @@
import { blank } from '../utils/object';
-const blockDeclarations = {
- 'const': true,
- 'let': true
+const extractors = {
+ Identifier ( names, param ) {
+ names.push( param.name );
+ },
+
+ ObjectPattern ( names, param ) {
+ param.properties.forEach( prop => {
+ extractors[ prop.key.type ]( names, prop.key );
+ });
+ },
+
+ ArrayPattern ( names, param ) {
+ param.elements.forEach( element => {
+ if ( element ) extractors[ element.type ]( names, element );
+ });
+ },
+
+ RestElement ( names, param ) {
+ extractors[ param.argument.type ]( names, param.argument );
+ },
+
+ AssignmentPattern ( names, param ) {
+ return extractors[ param.left.type ]( names, param.left );
+ }
};
+function extractNames ( param ) {
+ let names = [];
+
+ extractors[ param.type ]( names, param );
+ return names;
+}
+
export default class Scope {
constructor ( options ) {
options = options || {};
@@ -18,26 +46,29 @@ export default class Scope {
if ( options.params ) {
options.params.forEach( param => {
- this.declarations[ param.name ] = param;
+ extractNames( param ).forEach( name => {
+ this.declarations[ name ] = true;
+ });
});
}
}
- addDeclaration ( name, declaration, isVar ) {
- const isBlockDeclaration = declaration.type === 'VariableDeclaration' && blockDeclarations[ declaration.kind ];
-
+ addDeclaration ( declaration, isBlockDeclaration, isVar ) {
if ( !isBlockDeclaration && this.isBlockScope ) {
- // it's a `var` or function declaration, and this
+ // it's a `var` or function node, and this
// is a block scope, so we need to go up
- this.parent.addDeclaration( name, declaration, isVar );
+ this.parent.addDeclaration( declaration, isBlockDeclaration, isVar );
} else {
- this.declarations[ name ] = declaration;
- if ( isVar ) this.varDeclarations.push( name );
+ extractNames( declaration.id ).forEach( name => {
+ this.declarations[ name ] = true;
+ if ( isVar ) this.varDeclarations.push( name );
+ });
}
}
contains ( name ) {
- return !!this.getDeclaration( name );
+ return this.declarations[ name ] ||
+ ( this.parent ? this.parent.contains( name ) : false );
}
findDefiningScope ( name ) {
@@ -51,9 +82,4 @@ export default class Scope {
return null;
}
-
- getDeclaration ( name ) {
- return this.declarations[ name ] ||
- this.parent && this.parent.getDeclaration( name );
- }
}
diff --git a/src/rollup.js b/src/rollup.js
index ee2b3b0..94722e7 100644
--- a/src/rollup.js
+++ b/src/rollup.js
@@ -1,11 +1,9 @@
import { basename } from './utils/path';
import { writeFile } from 'sander';
import { keys } from './utils/object';
+import SOURCEMAPPING_URL from './utils/sourceMappingURL';
import Bundle from './Bundle';
-let SOURCEMAPPING_URL = 'sourceMa';
-SOURCEMAPPING_URL += 'ppingURL';
-
export function rollup ( options ) {
if ( !options || !options.entry ) {
throw new Error( 'You must supply options.entry to rollup' );
@@ -17,6 +15,9 @@ export function rollup ( options ) {
return {
imports: bundle.externalModules.map( module => module.id ),
exports: keys( bundle.entryModule.exports ),
+ modules: bundle.orderedModules.map( module => {
+ return { id: module.id };
+ }),
generate: options => bundle.render( options ),
write: options => {
diff --git a/src/utils/getExportMode.js b/src/utils/getExportMode.js
index 86ed4d4..3c41629 100644
--- a/src/utils/getExportMode.js
+++ b/src/utils/getExportMode.js
@@ -5,7 +5,9 @@ function badExports ( option, keys ) {
}
export default function getExportMode ( bundle, exportMode ) {
- const exportKeys = keys( bundle.entryModule.exports ).concat( keys( bundle.entryModule.reexports ) );
+ const exportKeys = keys( bundle.entryModule.exports )
+ .concat( keys( bundle.entryModule.reexports ) )
+ .concat( bundle.entryModule.exportAlls ); // not keys, but makes our job easier this way
if ( exportMode === 'default' ) {
if ( exportKeys.length !== 1 || exportKeys[0] !== 'default' ) {
diff --git a/src/utils/makeLegalIdentifier.js b/src/utils/makeLegalIdentifier.js
index 7e0a846..1dd4454 100644
--- a/src/utils/makeLegalIdentifier.js
+++ b/src/utils/makeLegalIdentifier.js
@@ -8,7 +8,10 @@ reservedWords.concat( builtins ).forEach( word => blacklisted[ word ] = true );
export default function makeLegalIdentifier ( str ) {
- str = str.replace( /[^$_a-zA-Z0-9]/g, '_' );
+ str = str
+ .replace( /-(\w)/g, ( _, letter ) => letter.toUpperCase() )
+ .replace( /[^$_a-zA-Z0-9]/g, '_' );
+
if ( /\d/.test( str[0] ) || blacklisted[ str ] ) str = `_${str}`;
return str;
diff --git a/src/utils/path.js b/src/utils/path.js
index b5db7c1..1ea179f 100644
--- a/src/utils/path.js
+++ b/src/utils/path.js
@@ -1,6 +1,6 @@
// TODO does this all work on windows?
-export const absolutePath = /^(?:\/|(?:[A-Za-z]:)?\\)/;
+export const absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|\/])/;
export function isAbsolute ( path ) {
return absolutePath.test( path );
@@ -35,12 +35,10 @@ export function relative ( from, to ) {
toParts.shift();
}
- while ( toParts[0] && toParts[0][0] === '.' ) {
+ while ( toParts[0] === '.' || toParts[0] === '..' ) {
const toPart = toParts.shift();
if ( toPart === '..' ) {
fromParts.pop();
- } else if ( toPart !== '.' ) {
- throw new Error( `Unexpected path part (${toPart})` );
}
}
diff --git a/src/utils/resolveId.js b/src/utils/resolveId.js
index 6b82f0d..3090001 100644
--- a/src/utils/resolveId.js
+++ b/src/utils/resolveId.js
@@ -1,5 +1,14 @@
import { absolutePath, dirname, isAbsolute, resolve } from './path';
-import { readFileSync } from 'sander';
+import { readdirSync, readFileSync } from 'sander';
+
+function dirExists ( dir ) {
+ try {
+ readdirSync( dir );
+ return true;
+ } catch ( err ) {
+ return false;
+ }
+}
export function defaultResolver ( importee, importer, options ) {
// absolute paths are left untouched
@@ -10,8 +19,10 @@ export function defaultResolver ( importee, importer, options ) {
// we try to resolve external modules
if ( importee[0] !== '.' ) {
+ const [ id ] = importee.split( /[\/\\]/ );
+
// unless we want to keep it external, that is
- if ( ~options.external.indexOf( importee ) ) return null;
+ if ( ~options.external.indexOf( id ) ) return null;
return options.resolveExternal( importee, importer, options );
}
@@ -24,29 +35,32 @@ export function defaultExternalResolver ( id, importer ) {
const root = absolutePath.exec( importer )[0];
let dir = dirname( importer );
- while ( dir !== root ) {
- const pkgPath = resolve( dir, 'node_modules', id, 'package.json' );
- let pkgJson;
+ // `foo` should use jsnext:main, but `foo/src/bar` shouldn't
+ const parts = id.split( /[\/\\]/ );
- try {
- pkgJson = readFileSync( pkgPath ).toString();
- } catch ( err ) {
- // noop
- }
+ while ( dir !== root && dir !== '.' ) {
+ const modulePath = resolve( dir, 'node_modules', parts[0] );
+
+ if ( dirExists( modulePath ) ) {
+ // `foo/src/bar`
+ if ( parts.length > 1 ) {
+ return resolve( modulePath, ...parts.slice( 1 ) ).replace( /\.js$/, '' ) + '.js';
+ }
- if ( pkgJson ) {
+ // `foo`
+ const pkgPath = resolve( modulePath, 'package.json' );
let pkg;
try {
- pkg = JSON.parse( pkgJson );
+ pkg = JSON.parse( readFileSync( pkgPath ).toString() );
} catch ( err ) {
- throw new Error( `Malformed JSON: ${pkgPath}` );
+ throw new Error( `Missing or malformed package.json: ${modulePath}` );
}
const main = pkg[ 'jsnext:main' ];
if ( !main ) {
- throw new Error( `Package ${id} does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = ['${id}']). See https://github.com/rollup/rollup/wiki/jsnext:main for more info` );
+ throw new Error( `Package ${id} (imported by ${importer}) does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = ['${id}']). See https://github.com/rollup/rollup/wiki/jsnext:main for more info` );
}
return resolve( dirname( pkgPath ), main ).replace( /\.js$/, '' ) + '.js';
diff --git a/src/utils/sourceMappingURL.js b/src/utils/sourceMappingURL.js
new file mode 100644
index 0000000..616c24d
--- /dev/null
+++ b/src/utils/sourceMappingURL.js
@@ -0,0 +1,6 @@
+// this looks ridiculous, but it prevents sourcemap tooling from mistaking
+// this for an actual sourceMappingURL
+let SOURCEMAPPING_URL = 'sourceMa';
+SOURCEMAPPING_URL += 'ppingURL';
+
+export default SOURCEMAPPING_URL;
diff --git a/test/cli/external-modules/main.js b/test/cli/external-modules/main.js
index 03f1b74..abaa454 100644
--- a/test/cli/external-modules/main.js
+++ b/test/cli/external-modules/main.js
@@ -1,5 +1,5 @@
-import { relative } from 'path';
+import { relative, normalize } from 'path';
import { format } from 'util';
assert.equal( format( 'it %s', 'works' ), 'it works' );
-assert.equal( relative( 'a/b/c', 'a/c/b' ), '../../c/b' );
+assert.equal( relative( 'a/b/c', 'a/c/b' ), normalize('../../c/b') );
diff --git a/test/form/export-all-from-internal/_config.js b/test/form/export-all-from-internal/_config.js
new file mode 100644
index 0000000..83871ca
--- /dev/null
+++ b/test/form/export-all-from-internal/_config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ description: 'should be able to export * from the bundle',
+ options: {
+ moduleName: 'exposedInternals'
+ }
+};
diff --git a/test/form/export-all-from-internal/_expected/amd.js b/test/form/export-all-from-internal/_expected/amd.js
new file mode 100644
index 0000000..6b0c47e
--- /dev/null
+++ b/test/form/export-all-from-internal/_expected/amd.js
@@ -0,0 +1,9 @@
+define(['exports'], function (exports) { 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+ exports.a = a;
+ exports.b = b;
+
+});
diff --git a/test/form/export-all-from-internal/_expected/cjs.js b/test/form/export-all-from-internal/_expected/cjs.js
new file mode 100644
index 0000000..869bba0
--- /dev/null
+++ b/test/form/export-all-from-internal/_expected/cjs.js
@@ -0,0 +1,7 @@
+'use strict';
+
+const a = 1;
+const b = 2;
+
+exports.a = a;
+exports.b = b;
diff --git a/test/form/export-all-from-internal/_expected/es6.js b/test/form/export-all-from-internal/_expected/es6.js
new file mode 100644
index 0000000..aafcac6
--- /dev/null
+++ b/test/form/export-all-from-internal/_expected/es6.js
@@ -0,0 +1,4 @@
+const a = 1;
+const b = 2;
+
+export { a, b };
diff --git a/test/form/export-all-from-internal/_expected/iife.js b/test/form/export-all-from-internal/_expected/iife.js
new file mode 100644
index 0000000..238e208
--- /dev/null
+++ b/test/form/export-all-from-internal/_expected/iife.js
@@ -0,0 +1,9 @@
+(function (exports) { 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+ exports.a = a;
+ exports.b = b;
+
+})((this.exposedInternals = {}));
diff --git a/test/form/export-all-from-internal/_expected/umd.js b/test/form/export-all-from-internal/_expected/umd.js
new file mode 100644
index 0000000..50c5cc4
--- /dev/null
+++ b/test/form/export-all-from-internal/_expected/umd.js
@@ -0,0 +1,13 @@
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
+ factory((global.exposedInternals = {}));
+}(this, function (exports) { 'use strict';
+
+ const a = 1;
+ const b = 2;
+
+ exports.a = a;
+ exports.b = b;
+
+}));
diff --git a/test/form/export-all-from-internal/internal.js b/test/form/export-all-from-internal/internal.js
new file mode 100644
index 0000000..8f791b6
--- /dev/null
+++ b/test/form/export-all-from-internal/internal.js
@@ -0,0 +1,3 @@
+export const a = 1;
+export const b = 2;
+export default 42;
diff --git a/test/form/export-all-from-internal/main.js b/test/form/export-all-from-internal/main.js
new file mode 100644
index 0000000..676c1ba
--- /dev/null
+++ b/test/form/export-all-from-internal/main.js
@@ -0,0 +1 @@
+export * from './internal.js';
diff --git a/test/form/internal-conflict-resolution/_expected/amd.js b/test/form/internal-conflict-resolution/_expected/amd.js
index f2b3c4a..24d63fa 100644
--- a/test/form/internal-conflict-resolution/_expected/amd.js
+++ b/test/form/internal-conflict-resolution/_expected/amd.js
@@ -1,9 +1,9 @@
define(function () { 'use strict';
- var _bar = 42;
+ var bar$1 = 42;
function foo () {
- return _bar;
+ return bar$1;
}
function bar () {
diff --git a/test/form/internal-conflict-resolution/_expected/cjs.js b/test/form/internal-conflict-resolution/_expected/cjs.js
index 74ae2f8..76c44a7 100644
--- a/test/form/internal-conflict-resolution/_expected/cjs.js
+++ b/test/form/internal-conflict-resolution/_expected/cjs.js
@@ -1,9 +1,9 @@
'use strict';
-var _bar = 42;
+var bar$1 = 42;
function foo () {
- return _bar;
+ return bar$1;
}
function bar () {
diff --git a/test/form/internal-conflict-resolution/_expected/es6.js b/test/form/internal-conflict-resolution/_expected/es6.js
index e1fc1f7..086f425 100644
--- a/test/form/internal-conflict-resolution/_expected/es6.js
+++ b/test/form/internal-conflict-resolution/_expected/es6.js
@@ -1,7 +1,7 @@
-var _bar = 42;
+var bar$1 = 42;
function foo () {
- return _bar;
+ return bar$1;
}
function bar () {
diff --git a/test/form/internal-conflict-resolution/_expected/iife.js b/test/form/internal-conflict-resolution/_expected/iife.js
index efe296f..b32c809 100644
--- a/test/form/internal-conflict-resolution/_expected/iife.js
+++ b/test/form/internal-conflict-resolution/_expected/iife.js
@@ -1,9 +1,9 @@
(function () { 'use strict';
- var _bar = 42;
+ var bar$1 = 42;
function foo () {
- return _bar;
+ return bar$1;
}
function bar () {
diff --git a/test/form/internal-conflict-resolution/_expected/umd.js b/test/form/internal-conflict-resolution/_expected/umd.js
index 979f229..c879634 100644
--- a/test/form/internal-conflict-resolution/_expected/umd.js
+++ b/test/form/internal-conflict-resolution/_expected/umd.js
@@ -4,10 +4,10 @@
factory();
}(this, function () { 'use strict';
- var _bar = 42;
+ var bar$1 = 42;
function foo () {
- return _bar;
+ return bar$1;
}
function bar () {
diff --git a/test/form/namespace-optimization/_config.js b/test/form/namespace-optimization/_config.js
new file mode 100644
index 0000000..e6eccae
--- /dev/null
+++ b/test/form/namespace-optimization/_config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ skip: true,
+ description: 'it does static lookup optimization of internal namespaces'
+};
diff --git a/test/form/namespace-optimization/_expected/amd.js b/test/form/namespace-optimization/_expected/amd.js
new file mode 100644
index 0000000..a244c47
--- /dev/null
+++ b/test/form/namespace-optimization/_expected/amd.js
@@ -0,0 +1,7 @@
+define(function () { 'use strict';
+
+ function a () {}
+
+ a();
+
+});
diff --git a/test/form/namespace-optimization/_expected/cjs.js b/test/form/namespace-optimization/_expected/cjs.js
new file mode 100644
index 0000000..b52a7e5
--- /dev/null
+++ b/test/form/namespace-optimization/_expected/cjs.js
@@ -0,0 +1,5 @@
+'use strict';
+
+function a () {}
+
+a();
diff --git a/test/form/namespace-optimization/_expected/es6.js b/test/form/namespace-optimization/_expected/es6.js
new file mode 100644
index 0000000..8bee044
--- /dev/null
+++ b/test/form/namespace-optimization/_expected/es6.js
@@ -0,0 +1,3 @@
+function a () {}
+
+a();
diff --git a/test/form/namespace-optimization/_expected/iife.js b/test/form/namespace-optimization/_expected/iife.js
new file mode 100644
index 0000000..aac8ff9
--- /dev/null
+++ b/test/form/namespace-optimization/_expected/iife.js
@@ -0,0 +1,7 @@
+(function () { 'use strict';
+
+ function a () {}
+
+ a();
+
+})();
diff --git a/test/form/namespace-optimization/_expected/umd.js b/test/form/namespace-optimization/_expected/umd.js
new file mode 100644
index 0000000..38f7835
--- /dev/null
+++ b/test/form/namespace-optimization/_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';
+
+ function a () {}
+
+ a();
+
+}));
diff --git a/test/form/namespace-optimization/bar.js b/test/form/namespace-optimization/bar.js
new file mode 100644
index 0000000..aa96676
--- /dev/null
+++ b/test/form/namespace-optimization/bar.js
@@ -0,0 +1,3 @@
+import * as quux from './quux';
+
+export { quux };
diff --git a/test/form/namespace-optimization/foo.js b/test/form/namespace-optimization/foo.js
new file mode 100644
index 0000000..42a93ae
--- /dev/null
+++ b/test/form/namespace-optimization/foo.js
@@ -0,0 +1,3 @@
+import * as bar from './bar';
+
+export { bar };
diff --git a/test/form/namespace-optimization/main.js b/test/form/namespace-optimization/main.js
new file mode 100644
index 0000000..e902244
--- /dev/null
+++ b/test/form/namespace-optimization/main.js
@@ -0,0 +1,3 @@
+import * as foo from './foo';
+
+foo.bar.quux.a();
diff --git a/test/form/namespace-optimization/quux.js b/test/form/namespace-optimization/quux.js
new file mode 100644
index 0000000..103a9f0
--- /dev/null
+++ b/test/form/namespace-optimization/quux.js
@@ -0,0 +1 @@
+export function a () {}
diff --git a/test/form/unused-side-effect/_config.js b/test/form/unused-side-effect/_config.js
new file mode 100644
index 0000000..0431077
--- /dev/null
+++ b/test/form/unused-side-effect/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'side-effects to non-globals are not blindly included'
+};
diff --git a/test/form/unused-side-effect/_expected/amd.js b/test/form/unused-side-effect/_expected/amd.js
new file mode 100644
index 0000000..c82bf4f
--- /dev/null
+++ b/test/form/unused-side-effect/_expected/amd.js
@@ -0,0 +1,7 @@
+define(function () { 'use strict';
+
+ var foo = 42;
+
+ assert.equal( foo, 42 );
+
+});
diff --git a/test/form/unused-side-effect/_expected/cjs.js b/test/form/unused-side-effect/_expected/cjs.js
new file mode 100644
index 0000000..0d2573f
--- /dev/null
+++ b/test/form/unused-side-effect/_expected/cjs.js
@@ -0,0 +1,5 @@
+'use strict';
+
+var foo = 42;
+
+assert.equal( foo, 42 );
diff --git a/test/form/unused-side-effect/_expected/es6.js b/test/form/unused-side-effect/_expected/es6.js
new file mode 100644
index 0000000..e50ecda
--- /dev/null
+++ b/test/form/unused-side-effect/_expected/es6.js
@@ -0,0 +1,3 @@
+var foo = 42;
+
+assert.equal( foo, 42 );
diff --git a/test/form/unused-side-effect/_expected/iife.js b/test/form/unused-side-effect/_expected/iife.js
new file mode 100644
index 0000000..a3f7fc8
--- /dev/null
+++ b/test/form/unused-side-effect/_expected/iife.js
@@ -0,0 +1,7 @@
+(function () { 'use strict';
+
+ var foo = 42;
+
+ assert.equal( foo, 42 );
+
+})();
diff --git a/test/form/unused-side-effect/_expected/umd.js b/test/form/unused-side-effect/_expected/umd.js
new file mode 100644
index 0000000..f96fd30
--- /dev/null
+++ b/test/form/unused-side-effect/_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';
+
+ var foo = 42;
+
+ assert.equal( foo, 42 );
+
+}));
diff --git a/test/form/unused-side-effect/foo.js b/test/form/unused-side-effect/foo.js
new file mode 100644
index 0000000..7953f6e
--- /dev/null
+++ b/test/form/unused-side-effect/foo.js
@@ -0,0 +1,13 @@
+var uid = 0;
+uid = 1;
+uid += 1;
+uid++;
+
+// ensure identifiers aren't treated as globals just because
+// var declaration hasn't been encountered yet...
+uid2 = 1;
+uid2 += 1;
+uid2++;
+var uid2;
+
+export var foo = 42;
diff --git a/test/form/unused-side-effect/main.js b/test/form/unused-side-effect/main.js
new file mode 100644
index 0000000..ef12cae
--- /dev/null
+++ b/test/form/unused-side-effect/main.js
@@ -0,0 +1,2 @@
+import { foo } from './foo';
+assert.equal( foo, 42 );
diff --git a/test/function/allows-external-modules-from-nested-module/main.js b/test/function/allows-external-modules-from-nested-module/main.js
index 8bacdc9..bdd4f85 100644
--- a/test/function/allows-external-modules-from-nested-module/main.js
+++ b/test/function/allows-external-modules-from-nested-module/main.js
@@ -1,8 +1,8 @@
-import { relative } from 'path';
+import { relative, normalize } from 'path';
import foo from './foo';
var path = 'foo/bar/baz';
var path2 = 'foo/baz/bar';
-assert.equal( relative( path, path2 ), '../../baz/bar' );
-assert.equal( foo, '../../c/b' );
\ No newline at end of file
+assert.equal( relative( path, path2 ), normalize('../../baz/bar') );
+assert.equal( foo, normalize('../../c/b') );
\ No newline at end of file
diff --git a/test/function/assignment-patterns/_config.js b/test/function/assignment-patterns/_config.js
new file mode 100644
index 0000000..d4afdc3
--- /dev/null
+++ b/test/function/assignment-patterns/_config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ description: 'allows reassigments to default parameters that shadow imports',
+ babel: true
+};
diff --git a/test/function/assignment-patterns/main.js b/test/function/assignment-patterns/main.js
new file mode 100644
index 0000000..844c908
--- /dev/null
+++ b/test/function/assignment-patterns/main.js
@@ -0,0 +1,21 @@
+import { bar, baz, x, items, p, q, r, s } from './other';
+
+function foo ( bar = 1, { baz } = { baz: 2 }, [[[,x = 3] = []] = []] = [], ...items ) {
+ bar += 1;
+ baz += 1;
+ x += 1;
+
+ let { p, q } = { p: 4, q: 5 };
+ let [ r, s ] = [ 6, 7 ];
+
+ p++;
+ q += 1;
+ r = 7;
+ s = 6;
+
+ return bar + baz + x + items.length + p + q + r + s;
+}
+
+assert.equal( foo(), 33 );
+assert.equal( foo( 2 ), 34 );
+assert.equal( foo( 2, { baz: 3 }, [[[99,10]]], 'a', 'b', 'c' ), 45 );
diff --git a/test/function/assignment-patterns/other.js b/test/function/assignment-patterns/other.js
new file mode 100644
index 0000000..840584c
--- /dev/null
+++ b/test/function/assignment-patterns/other.js
@@ -0,0 +1,8 @@
+export const bar = 'bar';
+export const baz = 'baz';
+export const x = 'x';
+export const items = 'items';
+export const p = 'p';
+export const q = 'q';
+export const r = 'r';
+export const s = 's';
diff --git a/test/function/cannot-import-self/_config.js b/test/function/cannot-import-self/_config.js
new file mode 100644
index 0000000..2413d03
--- /dev/null
+++ b/test/function/cannot-import-self/_config.js
@@ -0,0 +1,8 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'prevents a module importing itself',
+ error: function ( err ) {
+ assert.ok( /A module cannot import itself/.test( err.message ) );
+ }
+};
diff --git a/test/function/cannot-import-self/main.js b/test/function/cannot-import-self/main.js
new file mode 100644
index 0000000..48e08e6
--- /dev/null
+++ b/test/function/cannot-import-self/main.js
@@ -0,0 +1 @@
+import me from './main';
diff --git a/test/function/custom-path-resolver-async/_config.js b/test/function/custom-path-resolver-async/_config.js
index 287f536..c336d67 100644
--- a/test/function/custom-path-resolver-async/_config.js
+++ b/test/function/custom-path-resolver-async/_config.js
@@ -8,7 +8,7 @@ module.exports = {
var Promise = require( 'sander' ).Promise;
var resolved;
- if ( importee === path.resolve( __dirname, 'main.js' ) ) return importee;
+ if ( path.normalize(importee) === path.resolve( __dirname, 'main.js' ) ) return importee;
if ( importee === 'foo' ) {
resolved = path.resolve( __dirname, 'bar.js' );
diff --git a/test/function/custom-path-resolver-sync/_config.js b/test/function/custom-path-resolver-sync/_config.js
index 9a755e5..ee993e1 100644
--- a/test/function/custom-path-resolver-sync/_config.js
+++ b/test/function/custom-path-resolver-sync/_config.js
@@ -5,7 +5,7 @@ module.exports = {
description: 'uses a custom path resolver (synchronous)',
options: {
resolveId: function ( importee, importer ) {
- if ( importee === path.resolve( __dirname, 'main.js' ) ) return importee;
+ if ( path.normalize(importee) === path.resolve( __dirname, 'main.js' ) ) return importee;
if ( importee === 'foo' ) return path.resolve( __dirname, 'bar.js' );
return false;
diff --git a/test/function/duplicate-import-fails/_config.js b/test/function/duplicate-import-fails/_config.js
index 4280c53..4083690 100644
--- a/test/function/duplicate-import-fails/_config.js
+++ b/test/function/duplicate-import-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows duplicate imports',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 2, column: 9 });
assert.ok( /Duplicated import/.test( err.message ) );
}
diff --git a/test/function/duplicate-import-specifier-fails/_config.js b/test/function/duplicate-import-specifier-fails/_config.js
index b935a69..e3957b5 100644
--- a/test/function/duplicate-import-specifier-fails/_config.js
+++ b/test/function/duplicate-import-specifier-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows duplicate import specifiers',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 1, column: 12 });
assert.ok( /Duplicated import/.test( err.message ) );
}
diff --git a/test/function/dynamic-namespace-lookup/_config.js b/test/function/dynamic-namespace-lookup/_config.js
new file mode 100644
index 0000000..3c2fe54
--- /dev/null
+++ b/test/function/dynamic-namespace-lookup/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'does namespace optimization when possible, but not for dynamic lookups'
+};
diff --git a/test/function/dynamic-namespace-lookup/foo.js b/test/function/dynamic-namespace-lookup/foo.js
new file mode 100644
index 0000000..a727aee
--- /dev/null
+++ b/test/function/dynamic-namespace-lookup/foo.js
@@ -0,0 +1,2 @@
+export var bar = 'bar';
+export var baz = 'baz';
diff --git a/test/function/dynamic-namespace-lookup/main.js b/test/function/dynamic-namespace-lookup/main.js
new file mode 100644
index 0000000..ee1ce10
--- /dev/null
+++ b/test/function/dynamic-namespace-lookup/main.js
@@ -0,0 +1,8 @@
+import * as foo from './foo';
+
+var bar = 'baz';
+
+assert.equal( foo.bar, 'bar' );
+assert.equal( foo.baz, 'baz' );
+
+assert.equal( foo[ bar ], 'baz' );
diff --git a/test/function/export-not-at-top-level-fails/_config.js b/test/function/export-not-at-top-level-fails/_config.js
index c68ca42..2dadeab 100644
--- a/test/function/export-not-at-top-level-fails/_config.js
+++ b/test/function/export-not-at-top-level-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows non-top-level exports',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 2, column: 2 });
assert.ok( /may only appear at the top level/.test( err.message ) );
}
diff --git a/test/function/export-type-mismatch-b/_config.js b/test/function/export-type-mismatch-b/_config.js
new file mode 100644
index 0000000..25a7220
--- /dev/null
+++ b/test/function/export-type-mismatch-b/_config.js
@@ -0,0 +1,11 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'export type must be auto, default, named or none',
+ bundleOptions: {
+ exports: 'blah'
+ },
+ generateError: function ( err ) {
+ assert.ok( /options\.exports must be 'default', 'named', 'none', 'auto', or left unspecified/.test( err.message ) );
+ }
+};
diff --git a/test/function/export-type-mismatch-b/main.js b/test/function/export-type-mismatch-b/main.js
new file mode 100644
index 0000000..7a4e8a7
--- /dev/null
+++ b/test/function/export-type-mismatch-b/main.js
@@ -0,0 +1 @@
+export default 42;
diff --git a/test/function/export-type-mismatch-c/_config.js b/test/function/export-type-mismatch-c/_config.js
new file mode 100644
index 0000000..8df0d58
--- /dev/null
+++ b/test/function/export-type-mismatch-c/_config.js
@@ -0,0 +1,11 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'cannot have named exports if explicit export type is default',
+ bundleOptions: {
+ exports: 'none'
+ },
+ generateError: function ( err ) {
+ assert.ok( /'none' was specified for options\.exports/.test( err.message ) );
+ }
+};
diff --git a/test/function/export-type-mismatch-c/main.js b/test/function/export-type-mismatch-c/main.js
new file mode 100644
index 0000000..7a4e8a7
--- /dev/null
+++ b/test/function/export-type-mismatch-c/main.js
@@ -0,0 +1 @@
+export default 42;
diff --git a/test/function/export-type-mismatch/_config.js b/test/function/export-type-mismatch/_config.js
new file mode 100644
index 0000000..5b321d6
--- /dev/null
+++ b/test/function/export-type-mismatch/_config.js
@@ -0,0 +1,11 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'cannot have named exports if explicit export type is default',
+ bundleOptions: {
+ exports: 'default'
+ },
+ generateError: function ( err ) {
+ assert.ok( /'default' was specified for options\.exports/.test( err.message ) );
+ }
+};
diff --git a/test/function/export-type-mismatch/main.js b/test/function/export-type-mismatch/main.js
new file mode 100644
index 0000000..3b8dc9f
--- /dev/null
+++ b/test/function/export-type-mismatch/main.js
@@ -0,0 +1 @@
+export var foo = 42;
diff --git a/test/function/globally-called-modifying-function/_config.js b/test/function/globally-called-modifying-function/_config.js
new file mode 100644
index 0000000..86b2f62
--- /dev/null
+++ b/test/function/globally-called-modifying-function/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'globally called function should be included if it modifies an exported value (#112)'
+};
diff --git a/test/function/globally-called-modifying-function/main.js b/test/function/globally-called-modifying-function/main.js
new file mode 100644
index 0000000..3b2061e
--- /dev/null
+++ b/test/function/globally-called-modifying-function/main.js
@@ -0,0 +1,3 @@
+import value from './module.js';
+
+assert.equal( value, 3 );
diff --git a/test/function/globally-called-modifying-function/module.js b/test/function/globally-called-modifying-function/module.js
new file mode 100644
index 0000000..fc50ee5
--- /dev/null
+++ b/test/function/globally-called-modifying-function/module.js
@@ -0,0 +1,17 @@
+var value = 1;
+
+function change () {
+ value = 2;
+}
+
+function changeAgain () {
+ value += 1;
+}
+
+change();
+
+if ( true ) {
+ changeAgain();
+}
+
+export default value;
diff --git a/test/function/handles-multiple-declarations/_config.js b/test/function/handles-multiple-declarations/_config.js
new file mode 100644
index 0000000..94022ee
--- /dev/null
+++ b/test/function/handles-multiple-declarations/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'handles multiple declaration blocks with multiple declarations (#105)'
+};
diff --git a/test/function/handles-multiple-declarations/main.js b/test/function/handles-multiple-declarations/main.js
new file mode 100644
index 0000000..a8af4cd
--- /dev/null
+++ b/test/function/handles-multiple-declarations/main.js
@@ -0,0 +1,2 @@
+var a, b;
+var c, d;
diff --git a/test/function/has-modules-array/_config.js b/test/function/has-modules-array/_config.js
new file mode 100644
index 0000000..a2a12c3
--- /dev/null
+++ b/test/function/has-modules-array/_config.js
@@ -0,0 +1,12 @@
+var path = require( 'path' );
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'user-facing bundle has modules array',
+ bundle: function ( bundle ) {
+ assert.ok( bundle.modules );
+ assert.equal( bundle.modules.length, 2 );
+ assert.equal( path.relative(bundle.modules[0].id, path.resolve(__dirname, 'foo.js')), '' );
+ assert.equal( path.relative(bundle.modules[1].id, path.resolve(__dirname, 'main.js')), '' );
+ }
+};
diff --git a/test/function/has-modules-array/foo.js b/test/function/has-modules-array/foo.js
new file mode 100644
index 0000000..7a4e8a7
--- /dev/null
+++ b/test/function/has-modules-array/foo.js
@@ -0,0 +1 @@
+export default 42;
diff --git a/test/function/has-modules-array/main.js b/test/function/has-modules-array/main.js
new file mode 100644
index 0000000..3206f53
--- /dev/null
+++ b/test/function/has-modules-array/main.js
@@ -0,0 +1,2 @@
+import foo from './foo';
+assert.equal( foo, 42 );
diff --git a/test/function/import-default-from-external/main.js b/test/function/import-default-from-external/main.js
index 5d5cd6d..aacce04 100644
--- a/test/function/import-default-from-external/main.js
+++ b/test/function/import-default-from-external/main.js
@@ -4,4 +4,4 @@ import path from 'path';
var path1 = 'foo/bar/baz';
var path2 = 'foo/baz/bar';
-assert.equal( path.relative( path1, path2 ), '../../baz/bar' );
\ No newline at end of file
+assert.equal( path.relative( path1, path2 ), path.normalize('../../baz/bar') );
\ No newline at end of file
diff --git a/test/function/import-from-external-subdirectory/_config.js b/test/function/import-from-external-subdirectory/_config.js
new file mode 100644
index 0000000..57a682c
--- /dev/null
+++ b/test/function/import-from-external-subdirectory/_config.js
@@ -0,0 +1,4 @@
+module.exports = {
+ description: 'default resolver imports from a subdirectory of an external module',
+ babel: true
+};
diff --git a/test/function/import-from-external-subdirectory/main.js b/test/function/import-from-external-subdirectory/main.js
new file mode 100644
index 0000000..966ed65
--- /dev/null
+++ b/test/function/import-from-external-subdirectory/main.js
@@ -0,0 +1,5 @@
+// this test is brittle, it relies on this dependency continuing
+// to be structured in a certain way
+import btoa from 'magic-string/src/utils/btoa';
+
+assert.equal( btoa( 'it works' ), new Buffer( 'it works' ).toString( 'base64' ) );
diff --git a/test/function/import-named-from-external/main.js b/test/function/import-named-from-external/main.js
index 49027f6..1030a82 100644
--- a/test/function/import-named-from-external/main.js
+++ b/test/function/import-named-from-external/main.js
@@ -1,6 +1,6 @@
-import { relative } from 'path';
+import { relative, normalize } from 'path';
var path = 'foo/bar/baz';
var path2 = 'foo/baz/bar';
-assert.equal( relative( path, path2 ), '../../baz/bar' );
\ No newline at end of file
+assert.equal( relative( path, path2 ), normalize('../../baz/bar') );
\ No newline at end of file
diff --git a/test/function/import-namespace-from-external-module-renamed/main.js b/test/function/import-namespace-from-external-module-renamed/main.js
index 2208cd4..947231e 100644
--- a/test/function/import-namespace-from-external-module-renamed/main.js
+++ b/test/function/import-namespace-from-external-module-renamed/main.js
@@ -3,4 +3,4 @@ import * as node_path from 'path';
var path1 = 'foo/bar/baz';
var path2 = 'foo/baz/bar';
-assert.equal( node_path.relative( path1, path2 ), '../../baz/bar' );
+assert.equal( node_path.relative( path1, path2 ), node_path.normalize('../../baz/bar') );
diff --git a/test/function/import-namespace-from-external-module/main.js b/test/function/import-namespace-from-external-module/main.js
index 000a219..10f9d36 100644
--- a/test/function/import-namespace-from-external-module/main.js
+++ b/test/function/import-namespace-from-external-module/main.js
@@ -3,4 +3,4 @@ import * as path from 'path';
var path1 = 'foo/bar/baz';
var path2 = 'foo/baz/bar';
-assert.equal( path.relative( path1, path2 ), '../../baz/bar' );
\ No newline at end of file
+assert.equal( path.relative( path1, path2 ), path.normalize('../../baz/bar') );
\ No newline at end of file
diff --git a/test/function/import-not-at-top-level-fails/_config.js b/test/function/import-not-at-top-level-fails/_config.js
index c75e986..4f873aa 100644
--- a/test/function/import-not-at-top-level-fails/_config.js
+++ b/test/function/import-not-at-top-level-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows non-top-level imports',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 2, column: 2 });
assert.ok( /may only appear at the top level/.test( err.message ) );
}
diff --git a/test/function/import-of-unexported-fails/_config.js b/test/function/import-of-unexported-fails/_config.js
new file mode 100644
index 0000000..3027ba9
--- /dev/null
+++ b/test/function/import-of-unexported-fails/_config.js
@@ -0,0 +1,8 @@
+var assert = require( 'assert' );
+
+module.exports = {
+ description: 'marking an imported, but unexported, identifier should throw',
+ error: function ( err ) {
+ assert.ok( /Module .+empty\.js does not export default \(imported by .+main\.js\)/.test( err.message ) );
+ }
+};
diff --git a/test/function/import-of-unexported-fails/empty.js b/test/function/import-of-unexported-fails/empty.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/function/import-of-unexported-fails/main.js b/test/function/import-of-unexported-fails/main.js
new file mode 100644
index 0000000..37cf334
--- /dev/null
+++ b/test/function/import-of-unexported-fails/main.js
@@ -0,0 +1,3 @@
+import a from './empty.js';
+
+a();
diff --git a/test/function/imports-are-deconflicted-b/main.js b/test/function/imports-are-deconflicted-b/main.js
index fa81bd0..cf917fc 100644
--- a/test/function/imports-are-deconflicted-b/main.js
+++ b/test/function/imports-are-deconflicted-b/main.js
@@ -1,5 +1,6 @@
import foo from './foo';
import bar from './bar';
+import { normalize } from 'path';
assert.equal( foo, 'foo' );
-assert.equal( bar(), '../../baz/bar' );
+assert.equal( bar(), normalize('../../baz/bar') );
diff --git a/test/function/imports-are-deconflicted/main.js b/test/function/imports-are-deconflicted/main.js
index fa81bd0..cf917fc 100644
--- a/test/function/imports-are-deconflicted/main.js
+++ b/test/function/imports-are-deconflicted/main.js
@@ -1,5 +1,6 @@
import foo from './foo';
import bar from './bar';
+import { normalize } from 'path';
assert.equal( foo, 'foo' );
-assert.equal( bar(), '../../baz/bar' );
+assert.equal( bar(), normalize('../../baz/bar') );
diff --git a/test/function/modify-assumed-global/_config.js b/test/function/modify-assumed-global/_config.js
new file mode 100644
index 0000000..ee89a52
--- /dev/null
+++ b/test/function/modify-assumed-global/_config.js
@@ -0,0 +1,14 @@
+var assert = require( 'assert' );
+
+var Math = {};
+
+module.exports = {
+ description: 'side-effects to assumed globals are included',
+ context: {
+ Math: Math
+ },
+ exports: function ( exports ) {
+ assert.equal( Math.square( 3 ), 9 );
+ assert.equal( Math.cube( 3 ), 27 );
+ }
+};
diff --git a/test/function/modify-assumed-global/main.js b/test/function/modify-assumed-global/main.js
new file mode 100644
index 0000000..cc4f217
--- /dev/null
+++ b/test/function/modify-assumed-global/main.js
@@ -0,0 +1,3 @@
+import { square } from './math';
+
+assert.equal( square( 2 ), 4 );
diff --git a/test/function/modify-assumed-global/math.js b/test/function/modify-assumed-global/math.js
new file mode 100644
index 0000000..469df59
--- /dev/null
+++ b/test/function/modify-assumed-global/math.js
@@ -0,0 +1,15 @@
+function square ( x ) {
+ return x * x;
+}
+
+function cube ( x ) {
+ return x * x * x;
+}
+
+Math.square = square;
+
+if ( true ) {
+ Math.cube = cube;
+}
+
+export { square };
diff --git a/test/function/module-sort-order/_config.js b/test/function/module-sort-order/_config.js
new file mode 100644
index 0000000..a84538d
--- /dev/null
+++ b/test/function/module-sort-order/_config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ // solo: true,
+ // show: true,
+ description: 'module sorter is not confused by top-level call expressions'
+};
diff --git a/test/function/module-sort-order/a.js b/test/function/module-sort-order/a.js
new file mode 100644
index 0000000..cf43071
--- /dev/null
+++ b/test/function/module-sort-order/a.js
@@ -0,0 +1,20 @@
+import { b } from './b';
+import z from './z';
+
+z();
+
+const p = {
+ q: function () {
+ b.nope();
+ }
+};
+
+(function () {
+ const p = {
+ q: function () {
+ b.nope();
+ }
+ };
+})();
+
+export default 42;
diff --git a/test/function/module-sort-order/b.js b/test/function/module-sort-order/b.js
new file mode 100644
index 0000000..3a7e6b7
--- /dev/null
+++ b/test/function/module-sort-order/b.js
@@ -0,0 +1 @@
+export const b = function () {};
diff --git a/test/function/module-sort-order/c.js b/test/function/module-sort-order/c.js
new file mode 100644
index 0000000..4bbf7c1
--- /dev/null
+++ b/test/function/module-sort-order/c.js
@@ -0,0 +1,3 @@
+import { b } from './b';
+
+export const c = function () {};
diff --git a/test/function/module-sort-order/main.js b/test/function/module-sort-order/main.js
new file mode 100644
index 0000000..dcd42cb
--- /dev/null
+++ b/test/function/module-sort-order/main.js
@@ -0,0 +1,4 @@
+import a from './a';
+import z from './z';
+
+z();
diff --git a/test/function/module-sort-order/z.js b/test/function/module-sort-order/z.js
new file mode 100644
index 0000000..8b67172
--- /dev/null
+++ b/test/function/module-sort-order/z.js
@@ -0,0 +1,5 @@
+import { c } from './c';
+
+export default function () {
+ c();
+}
diff --git a/test/function/namespace-reassign-import-fails/_config.js b/test/function/namespace-reassign-import-fails/_config.js
index 7e2d7a8..2d606f4 100644
--- a/test/function/namespace-reassign-import-fails/_config.js
+++ b/test/function/namespace-reassign-import-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows reassignments to namespace exports',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 3, column: 0 });
assert.ok( /Illegal reassignment/.test( err.message ) );
}
diff --git a/test/function/namespace-update-import-fails/_config.js b/test/function/namespace-update-import-fails/_config.js
index 116f4d0..4cff5c0 100644
--- a/test/function/namespace-update-import-fails/_config.js
+++ b/test/function/namespace-update-import-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows updates to namespace exports',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 3, column: 0 });
assert.ok( /Illegal reassignment/.test( err.message ) );
}
diff --git a/test/function/property-keys-not-renamed/_config.js b/test/function/property-keys-not-renamed/_config.js
new file mode 100644
index 0000000..d4e1f82
--- /dev/null
+++ b/test/function/property-keys-not-renamed/_config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ description: 'does not rename property keys'
+};
diff --git a/test/function/property-keys-not-renamed/main.js b/test/function/property-keys-not-renamed/main.js
new file mode 100644
index 0000000..9134b8e
--- /dev/null
+++ b/test/function/property-keys-not-renamed/main.js
@@ -0,0 +1,7 @@
+import one from './one';
+import two from './two';
+import three from './three';
+
+assert.equal( one(), 'one' );
+assert.equal( two(), 'two' );
+assert.equal( three(), 'three' );
diff --git a/test/function/property-keys-not-renamed/one.js b/test/function/property-keys-not-renamed/one.js
new file mode 100644
index 0000000..ab4a0f9
--- /dev/null
+++ b/test/function/property-keys-not-renamed/one.js
@@ -0,0 +1,11 @@
+var obj = {
+ foo: foo
+};
+
+function foo () {
+ return 'one';
+}
+
+export default function () {
+ return obj.foo();
+}
diff --git a/test/function/property-keys-not-renamed/three.js b/test/function/property-keys-not-renamed/three.js
new file mode 100644
index 0000000..a78e2e5
--- /dev/null
+++ b/test/function/property-keys-not-renamed/three.js
@@ -0,0 +1,11 @@
+var obj = {
+ foo: foo
+};
+
+function foo () {
+ return 'three';
+}
+
+export default function () {
+ return obj.foo();
+}
diff --git a/test/function/property-keys-not-renamed/two.js b/test/function/property-keys-not-renamed/two.js
new file mode 100644
index 0000000..70e142b
--- /dev/null
+++ b/test/function/property-keys-not-renamed/two.js
@@ -0,0 +1,11 @@
+var obj = {
+ foo: foo
+};
+
+function foo () {
+ return 'two';
+}
+
+export default function () {
+ return obj.foo();
+}
diff --git a/test/function/reassign-import-fails/_config.js b/test/function/reassign-import-fails/_config.js
index c73c36d..e01d090 100644
--- a/test/function/reassign-import-fails/_config.js
+++ b/test/function/reassign-import-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows assignments to imported bindings',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 8, column: 0 });
assert.ok( /Illegal reassignment/.test( err.message ) );
}
diff --git a/test/function/reassign-import-not-at-top-level-fails/_config.js b/test/function/reassign-import-not-at-top-level-fails/_config.js
index d17af29..6e00786 100644
--- a/test/function/reassign-import-not-at-top-level-fails/_config.js
+++ b/test/function/reassign-import-not-at-top-level-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows assignments to imported bindings not at the top level',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 7, column: 2 });
assert.ok( /Illegal reassignment/.test( err.message ) );
}
diff --git a/test/function/shadowed-external-export/main.js b/test/function/shadowed-external-export/main.js
index d8a080a..37ce4be 100644
--- a/test/function/shadowed-external-export/main.js
+++ b/test/function/shadowed-external-export/main.js
@@ -1,4 +1,4 @@
-import { relative } from 'path';
+import { relative, normalize } from 'path';
var paths = {};
function getRelativePath ( path, path2 ) {
@@ -6,5 +6,5 @@ function getRelativePath ( path, path2 ) {
return relative( path, path2 );
}
-assert.equal( getRelativePath( 'foo/bar/baz', 'foo/baz/bar' ), '../../baz/bar' );
+assert.equal( getRelativePath( 'foo/bar/baz', 'foo/baz/bar' ), normalize('../../baz/bar') );
assert.deepEqual( paths, { 'foo/bar/baz': true });
diff --git a/test/function/shorthand-properties/baz.js b/test/function/shorthand-properties/baz.js
new file mode 100644
index 0000000..d826bfa
--- /dev/null
+++ b/test/function/shorthand-properties/baz.js
@@ -0,0 +1,3 @@
+export default function bar () {
+ return 'main-bar';
+}
diff --git a/test/function/shorthand-properties/foo.js b/test/function/shorthand-properties/foo.js
index 25941fc..831360e 100644
--- a/test/function/shorthand-properties/foo.js
+++ b/test/function/shorthand-properties/foo.js
@@ -1,7 +1,10 @@
+import baz from './baz.js';
+
function bar () {
return 'foo-bar';
}
export var foo = {
- bar
+ bar,
+ baz
};
diff --git a/test/function/shorthand-properties/main.js b/test/function/shorthand-properties/main.js
index 5118a11..754fba8 100644
--- a/test/function/shorthand-properties/main.js
+++ b/test/function/shorthand-properties/main.js
@@ -1,8 +1,5 @@
+import bar from './baz.js';
import { foo } from './foo';
-function bar () {
- return 'main-bar';
-}
-
assert.equal( bar(), 'main-bar' );
assert.equal( foo.bar(), 'foo-bar' );
diff --git a/test/function/update-expression-of-import-fails/_config.js b/test/function/update-expression-of-import-fails/_config.js
index f2f1390..5f5c27c 100644
--- a/test/function/update-expression-of-import-fails/_config.js
+++ b/test/function/update-expression-of-import-fails/_config.js
@@ -4,7 +4,7 @@ var assert = require( 'assert' );
module.exports = {
description: 'disallows updates to imported bindings',
error: function ( err ) {
- assert.equal( err.file, path.resolve( __dirname, 'main.js' ) );
+ assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) );
assert.deepEqual( err.loc, { line: 3, column: 0 });
assert.ok( /Illegal reassignment/.test( err.message ) );
}
diff --git a/test/sourcemaps/basic-support/_config.js b/test/sourcemaps/basic-support/_config.js
index b83cd6b..c547c32 100644
--- a/test/sourcemaps/basic-support/_config.js
+++ b/test/sourcemaps/basic-support/_config.js
@@ -18,7 +18,7 @@ module.exports = {
assert.equal( originalLoc.line, 4 );
assert.equal( originalLoc.column, 0 );
- assert.equal( path.resolve( originalLoc.source ), path.resolve( __dirname, 'main.js' ) );
+ assert.equal( originalLoc.source, 'sourcemaps/basic-support/main.js' );
// foo.js
generatedLoc = getLocation( code, code.indexOf( "console.log( 'hello from foo.js' )" ) );
@@ -26,7 +26,7 @@ module.exports = {
assert.equal( originalLoc.line, 2 );
assert.equal( originalLoc.column, 1 );
- assert.equal( path.resolve( originalLoc.source ), path.resolve( __dirname, 'foo.js' ) );
+ assert.equal( originalLoc.source, 'sourcemaps/basic-support/foo.js' );
// bar.js
generatedLoc = getLocation( code, code.indexOf( "console.log( 'hello from bar.js' )" ) );
@@ -34,6 +34,6 @@ module.exports = {
assert.equal( originalLoc.line, 2 );
assert.equal( originalLoc.column, 1 );
- assert.equal( path.resolve( originalLoc.source ), path.resolve( __dirname, 'bar.js' ) );
+ assert.equal( originalLoc.source, 'sourcemaps/basic-support/bar.js' );
}
};
diff --git a/test/sourcemaps/names/_config.js b/test/sourcemaps/names/_config.js
index 14f081a..ce0bccb 100644
--- a/test/sourcemaps/names/_config.js
+++ b/test/sourcemaps/names/_config.js
@@ -1,4 +1,3 @@
-var path = require( 'path' );
var assert = require( 'assert' );
var getLocation = require( '../../utils/getLocation' );
var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer;
@@ -9,21 +8,20 @@ module.exports = {
moduleName: 'myModule'
},
test: function ( code, map ) {
- var match = /Object\.create\( ([^\.]+)\.prototype/.exec( code );
+ var smc = new SourceMapConsumer( map );
- var deconflictedName = match[1];
- if ( deconflictedName === 'Foo' ) throw new Error( 'Need to update this test!' );
+ var pattern = /Object\.create\( ([\w\$\d]+)\.prototype \)/;
+ var match = pattern.exec( code );
- var smc = new SourceMapConsumer( map );
+ var generatedLoc = getLocation( code, match.index + 'Object.create ( '.length );
+ var original = smc.originalPositionFor( generatedLoc );
+ assert.equal( original.name, 'Bar' );
- var index = code.indexOf( deconflictedName );
- var generatedLoc = getLocation( code, index );
- var originalLoc = smc.originalPositionFor( generatedLoc );
- assert.equal( originalLoc.name, 'Foo' );
+ pattern = /function Foo([\w\$\d]+)/;
+ match = pattern.exec( code );
- index = code.indexOf( deconflictedName, index + 1 );
- generatedLoc = getLocation( code, index );
- originalLoc = smc.originalPositionFor( generatedLoc );
- assert.equal( originalLoc.name, 'Bar' );
+ generatedLoc = getLocation( code, match.index + 'function '.length );
+ original = smc.originalPositionFor( generatedLoc );
+ assert.equal( original.name, 'Foo' );
}
};
diff --git a/test/test.js b/test/test.js
index 337d33d..520330a 100644
--- a/test/test.js
+++ b/test/test.js
@@ -2,11 +2,11 @@ require( 'source-map-support' ).install();
require( 'console-group' ).install();
var path = require( 'path' );
+var os = require( 'os' );
var sander = require( 'sander' );
var assert = require( 'assert' );
var exec = require( 'child_process' ).exec;
var babel = require( 'babel-core' );
-var sequence = require( './utils/promiseSequence' );
var rollup = require( '../dist/rollup' );
var FUNCTION = path.resolve( __dirname, 'function' );
@@ -32,6 +32,10 @@ function extend ( target ) {
return target;
}
+function normaliseOutput ( code ) {
+ return code.toString().trim().replace( /\r\n/g, '\n' );
+}
+
describe( 'rollup', function () {
describe( 'sanity checks', function () {
it( 'exists', function () {
@@ -41,6 +45,36 @@ describe( 'rollup', function () {
it( 'has a rollup method', function () {
assert.equal( typeof rollup.rollup, 'function' );
});
+
+ it( 'fails without options or options.entry', function () {
+ assert.throws( function () {
+ rollup.rollup();
+ }, /must supply options\.entry/ );
+
+ assert.throws( function () {
+ rollup.rollup({});
+ }, /must supply options\.entry/ );
+ });
+ });
+
+ describe( 'bundle.write()', function () {
+ it( 'fails without options or options.dest', function () {
+ return rollup.rollup({
+ entry: 'x',
+ resolveId: function () { return 'test'; },
+ load: function () {
+ return '// empty';
+ }
+ }).then( function ( bundle ) {
+ assert.throws( function () {
+ bundle.write();
+ }, /must supply options\.dest/ );
+
+ assert.throws( function () {
+ bundle.write({});
+ }, /must supply options\.dest/ );
+ });
+ });
});
describe( 'function', function () {
@@ -76,60 +110,60 @@ describe( 'rollup', function () {
format: 'cjs'
}));
- if ( config.error ) {
+ if ( config.generateError ) {
unintendedError = new Error( 'Expected an error while generating output' );
}
} catch ( err ) {
- if ( config.error ) {
- config.error( err );
+ if ( config.generateError ) {
+ config.generateError( err );
} else {
unintendedError = err;
}
}
if ( unintendedError ) throw unintendedError;
+ if ( config.error || config.generateError ) return;
var code;
- try {
- if ( config.babel ) {
- code = babel.transform( result.code, {
- blacklist: [ 'es6.modules' ],
- loose: [ 'es6.classes' ]
- }).code;
- } else {
- code = result.code;
- }
+ if ( config.babel ) {
+ code = babel.transform( result.code, {
+ blacklist: [ 'es6.modules' ],
+ loose: [ 'es6.classes' ]
+ }).code;
+ } else {
+ code = result.code;
+ }
- var module = {
- exports: {}
- };
+ var module = {
+ exports: {}
+ };
- var context = extend({
- require: require,
- module: module,
- exports: module.exports,
- assert: assert
- }, config.context || {} );
+ var context = extend({
+ require: require,
+ module: module,
+ exports: module.exports,
+ assert: assert
+ }, config.context || {} );
- var contextKeys = Object.keys( context );
- var contextValues = contextKeys.map( function ( key ) {
- return context[ key ];
- });
+ var contextKeys = Object.keys( context );
+ var contextValues = contextKeys.map( function ( key ) {
+ return context[ key ];
+ });
+ try {
var fn = new Function( contextKeys, code );
fn.apply( {}, contextValues );
- if ( config.error ) {
+ if ( config.runtimeError ) {
unintendedError = new Error( 'Expected an error while executing output' );
- }
-
- if ( config.exports ) {
- config.exports( module.exports );
+ } else {
+ if ( config.exports ) config.exports( module.exports );
+ if ( config.bundle ) config.bundle( bundle );
}
} catch ( err ) {
- if ( config.error ) {
- config.error( err );
+ if ( config.runtimeError ) {
+ config.runtimeError( err );
} else {
unintendedError = err;
}
@@ -157,49 +191,45 @@ describe( 'rollup', function () {
sander.readdirSync( FORM ).sort().forEach( function ( dir ) {
if ( dir[0] === '.' ) return; // .DS_Store...
- describe( dir, function () {
- var config = require( FORM + '/' + dir + '/_config' );
+ var config = require( FORM + '/' + dir + '/_config' );
- var options = extend( {}, config.options, {
- entry: FORM + '/' + dir + '/main.js'
- });
-
- var bundlePromise = rollup.rollup( options );
+ var options = extend( {}, config.options, {
+ entry: FORM + '/' + dir + '/main.js'
+ });
+ ( config.skip ? describe.skip : config.solo ? describe.only : describe)( dir, function () {
PROFILES.forEach( function ( profile ) {
- ( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
- if ( config.solo ) console.group( dir );
-
- return bundlePromise.then( function ( bundle ) {
+ it( 'generates ' + profile.format, function () {
+ return rollup.rollup( options ).then( function ( bundle ) {
var options = extend( {}, config.options, {
dest: FORM + '/' + dir + '/_actual/' + profile.format + '.js',
format: profile.format
});
return bundle.write( options ).then( function () {
- var actualCode = sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ).toString().trim();
+ var actualCode = normaliseOutput( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ) );
var expectedCode;
var actualMap;
var expectedMap;
try {
- expectedCode = sander.readFileSync( FORM, dir, '_expected', profile.format + '.js' ).toString().trim();
+ expectedCode = normaliseOutput( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js' ) );
} catch ( err ) {
expectedCode = 'missing file';
}
try {
actualMap = JSON.parse( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js.map' ).toString() );
+ actualMap.sourcesContent = actualMap.sourcesContent.map( normaliseOutput );
} catch ( err ) {}
try {
expectedMap = JSON.parse( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js.map' ).toString() );
+ expectedMap.sourcesContent = expectedMap.sourcesContent.map( normaliseOutput );
} catch ( err ) {}
assert.equal( actualCode, expectedCode );
assert.deepEqual( actualMap, expectedMap );
-
- if ( config.solo ) console.groupEnd();
});
});
});
@@ -219,15 +249,13 @@ describe( 'rollup', function () {
entry: SOURCEMAPS + '/' + dir + '/main.js'
});
- var bundlePromise = rollup.rollup( options );
-
PROFILES.forEach( function ( profile ) {
( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {
- return bundlePromise.then( function ( bundle ) {
+ return rollup.rollup( options ).then( function ( bundle ) {
var options = extend( {}, config.options, {
format: profile.format,
sourceMap: true,
- sourceMapFile: 'bundle.js'
+ sourceMapFile: path.resolve( __dirname, 'bundle.js' )
});
var result = bundle.generate( options );
@@ -249,9 +277,13 @@ describe( 'rollup', function () {
( config.skip ? it.skip : config.solo ? it.only : it )( dir, function ( done ) {
process.chdir( path.resolve( CLI, dir ) );
+ if (os.platform() === 'win32') {
+ config.command = "node " + path.resolve( __dirname, '../bin' ) + path.sep + config.command;
+ }
+
exec( config.command, {
env: {
- PATH: path.resolve( __dirname, '../bin' ) + ':' + process.env.PATH
+ PATH: path.resolve( __dirname, '../bin' ) + path.delimiter + process.env.PATH
}
}, function ( err, code, stderr ) {
if ( err ) return done( err );
@@ -310,7 +342,7 @@ describe( 'rollup', function () {
else {
var expected = sander.readFileSync( '_expected.js' ).toString();
try {
- assert.equal( code.trim(), expected.trim() );
+ assert.equal( normaliseOutput( code ), normaliseOutput( expected ) );
done();
} catch ( err ) {
done( err );