Browse Source

Merge pull request #64 from rollup/module-render

Move rendering logic into modules
contingency-plan
Oskar Segersvärd 10 years ago
parent
commit
72eb56109e
  1. 2
      package.json
  2. 279
      src/Bundle.js
  3. 162
      src/Module.js
  4. 36
      src/Statement.js
  5. 66
      src/ast/analyse.js
  6. 4
      src/rollup.js
  7. 8
      src/utils/map-helpers.js
  8. 1
      test/form/exported-empty-vars/_expected/es6.js
  9. 1
      test/form/self-contained-bundle/_expected/amd.js
  10. 1
      test/form/self-contained-bundle/_expected/cjs.js
  11. 1
      test/form/self-contained-bundle/_expected/es6.js
  12. 1
      test/form/self-contained-bundle/_expected/iife.js
  13. 1
      test/form/self-contained-bundle/_expected/umd.js
  14. 3
      test/function/unused-var-a/_config.js
  15. 2
      test/function/unused-var-a/foo.js
  16. 4
      test/function/unused-var-a/main.js
  17. 3
      test/function/unused-var-b/_config.js
  18. 2
      test/function/unused-var-b/foo.js
  19. 4
      test/function/unused-var-b/main.js
  20. 3
      test/function/unused-var-c/_config.js
  21. 2
      test/function/unused-var-c/foo.js
  22. 4
      test/function/unused-var-c/main.js
  23. 3
      test/function/unused-var-d/_config.js
  24. 5
      test/function/unused-var-d/foo.js
  25. 4
      test/function/unused-var-d/main.js

2
package.json

@ -46,7 +46,7 @@
"dependencies": { "dependencies": {
"acorn": "^1.1.0", "acorn": "^1.1.0",
"chalk": "^1.0.0", "chalk": "^1.0.0",
"magic-string": "^0.6.2", "magic-string": "^0.6.4",
"minimist": "^1.1.1", "minimist": "^1.1.1",
"sander": "^0.3.3", "sander": "^0.3.3",
"source-map-support": "^0.3.1" "source-map-support": "^0.3.1"

279
src/Bundle.js

@ -13,15 +13,6 @@ import getExportMode from './utils/getExportMode';
import getIndentString from './utils/getIndentString'; import getIndentString from './utils/getIndentString';
import { unixizePath } from './utils/normalizePlatform.js'; import { unixizePath } from './utils/normalizePlatform.js';
function isEmptyExportedVarDeclaration ( node, module, allBundleExports, es6 ) {
if ( node.type !== 'VariableDeclaration' || node.declarations[0].init ) return false;
const name = node.declarations[0].id.name;
const canonicalName = module.getCanonicalName( name, es6 );
return canonicalName in allBundleExports;
}
export default class Bundle { export default class Bundle {
constructor ( options ) { constructor ( options ) {
this.entry = options.entry; this.entry = options.entry;
@ -90,7 +81,7 @@ export default class Bundle {
return this.markAllModifierStatements(); return this.markAllModifierStatements();
}) })
.then( () => { .then( () => {
this.statements = this.sort(); this.orderedModules = this.sort();
}); });
} }
@ -115,34 +106,35 @@ export default class Bundle {
}); });
// Discover conflicts (i.e. two statements in separate modules both define `foo`) // Discover conflicts (i.e. two statements in separate modules both define `foo`)
this.statements.forEach( statement => { this.orderedModules.forEach( module => {
const module = statement.module; module.statements.forEach( statement => {
const names = keys( statement.defines ); const names = keys( statement.defines );
// with default exports that are expressions (`export default 42`), // with default exports that are expressions (`export default 42`),
// we need to ensure that the name chosen for the expression does // we need to ensure that the name chosen for the expression does
// not conflict // not conflict
if ( statement.node.type === 'ExportDefaultDeclaration' ) { if ( statement.node.type === 'ExportDefaultDeclaration' ) {
const name = module.getCanonicalName( 'default', es6 ); const name = module.getCanonicalName( 'default', es6 );
const isProxy = statement.node.declaration && statement.node.declaration.type === 'Identifier'; const isProxy = statement.node.declaration && statement.node.declaration.type === 'Identifier';
const shouldDeconflict = !isProxy || ( module.getCanonicalName( statement.node.declaration.name, es6 ) !== name ); const shouldDeconflict = !isProxy || ( module.getCanonicalName( statement.node.declaration.name, es6 ) !== name );
if ( shouldDeconflict && !~names.indexOf( name ) ) { if ( shouldDeconflict && !~names.indexOf( name ) ) {
names.push( name ); names.push( name );
}
} }
}
names.forEach( name => { names.forEach( name => {
if ( definers[ name ] ) { if ( definers[ name ] ) {
conflicts[ name ] = true; conflicts[ name ] = true;
} else { } else {
definers[ name ] = []; definers[ name ] = [];
} }
// TODO in good js, there shouldn't be duplicate definitions // TODO in good js, there shouldn't be duplicate definitions
// per module... but some people write bad js // per module... but some people write bad js
definers[ name ].push( module ); definers[ name ].push( module );
});
}); });
}); });
@ -213,9 +205,58 @@ export default class Bundle {
}); });
} }
generate ( options = {} ) { markAllModifierStatements () {
let magicString = new MagicString.Bundle({ separator: '' }); let settled = true;
let promises = [];
this.modules.forEach( module => {
module.statements.forEach( statement => {
if ( statement.isIncluded ) return;
keys( statement.modifies ).forEach( name => {
const definingStatement = module.definitions[ name ];
const exportDeclaration = module.exports[ name ] || (
module.exports.default && module.exports.default.identifier === name && module.exports.default
);
const shouldMark = ( definingStatement && definingStatement.isIncluded ) ||
( exportDeclaration && exportDeclaration.isUsed );
if ( shouldMark ) {
settled = false;
promises.push( statement.mark() );
return;
}
// special case - https://github.com/rollup/rollup/pull/40
const importDeclaration = module.imports[ name ];
if ( !importDeclaration ) return;
const promise = Promise.resolve( importDeclaration.module || this.fetchModule( importDeclaration.source, module.id ) )
.then( module => {
importDeclaration.module = module;
const exportDeclaration = module.exports[ importDeclaration.name ];
// TODO things like `export default a + b` don't apply here... right?
return module.findDefiningStatement( exportDeclaration.localName );
})
.then( definingStatement => {
if ( !definingStatement ) return;
settled = false;
return statement.mark();
});
promises.push( promise );
});
});
});
return Promise.all( promises ).then( () => {
if ( !settled ) return this.markAllModifierStatements();
});
}
render ( options = {} ) {
const format = options.format || 'es6'; const format = options.format || 'es6';
this.deconflict( format === 'es6' ); this.deconflict( format === 'es6' );
@ -256,113 +297,14 @@ export default class Bundle {
this.toExport = keys( this.entryModule.exports ) this.toExport = keys( this.entryModule.exports )
.filter( key => !this.varExports[ key ] ); .filter( key => !this.varExports[ key ] );
// Apply new names and add to the output bundle
let previousModule = null;
let previousIndex = -1;
let previousMargin = 0;
this.statements.forEach( statement => { let magicString = new MagicString.Bundle({ separator: '\n\n' });
// skip `export { foo, bar, baz }`
if ( statement.node.type === 'ExportNamedDeclaration' ) {
// skip `export { foo, bar, baz }`
if ( statement.node.specifiers.length ) return;
// skip `export var foo;` if foo is exported this.orderedModules.forEach( module => {
if ( isEmptyExportedVarDeclaration( statement.node.declaration, statement.module, allBundleExports, format === 'es6' ) ) return; const source = module.render( allBundleExports, format );
if ( source.toString().length ) {
magicString.addSource( source );
} }
// skip empty var declarations for exported bindings
// (otherwise we're left with `exports.foo;`, which is useless)
if ( isEmptyExportedVarDeclaration( statement.node, statement.module, allBundleExports, format === 'es6' ) ) return;
let replacements = blank();
let bundleExports = blank();
keys( statement.dependsOn )
.concat( keys( statement.defines ) )
.forEach( name => {
const canonicalName = statement.module.getCanonicalName( name, format === 'es6' );
if ( allBundleExports[ canonicalName ] ) {
bundleExports[ name ] = replacements[ name ] = allBundleExports[ canonicalName ];
} else if ( name !== canonicalName ) {
replacements[ name ] = canonicalName;
}
});
const source = statement.replaceIdentifiers( replacements, bundleExports );
// modify exports as necessary
if ( statement.isExportDeclaration ) {
// remove `export` from `export var foo = 42`
if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration' ) {
source.remove( statement.node.start, statement.node.declaration.start );
}
// remove `export` from `export class Foo {...}` or `export default Foo`
// TODO default exports need different treatment
else if ( statement.node.declaration.id ) {
source.remove( statement.node.start, statement.node.declaration.start );
}
else if ( statement.node.type === 'ExportDefaultDeclaration' ) {
const module = statement.module;
const canonicalName = module.getCanonicalName( 'default', format === 'es6' );
if ( statement.node.declaration.type === 'Identifier' && canonicalName === module.getCanonicalName( statement.node.declaration.name, format === 'es6' ) ) {
return;
}
// anonymous functions should be converted into declarations
if ( statement.node.declaration.type === 'FunctionExpression' ) {
source.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${canonicalName}` );
} else {
source.overwrite( statement.node.start, statement.node.declaration.start, `var ${canonicalName} = ` );
}
}
else {
throw new Error( 'Unhandled export' );
}
}
// ensure there is always a newline between statements, and add
// additional newlines as necessary to reflect original source
const minSeparation = ( previousModule !== statement.module ) || ( statement.index !== previousIndex + 1 ) ? 3 : 2;
const margin = Math.max( minSeparation, statement.margin[0], previousMargin );
let newLines = new Array( margin ).join( '\n' );
// add leading comments
if ( statement.leadingComments.length ) {
const commentBlock = newLines + statement.leadingComments.map( ({ separator, comment }) => {
return separator + ( comment.block ?
`/*${comment.text}*/` :
`//${comment.text}` );
}).join( '' );
magicString.addSource( new MagicString( commentBlock ) );
newLines = new Array( statement.margin[0] ).join( '\n' ); // TODO handle gaps between comment block and statement
}
// add the statement itself
magicString.addSource({
content: source,
separator: newLines
});
// add trailing comments
const comment = statement.trailingComment;
if ( comment ) {
const commentBlock = comment.block ?
` /*${comment.text}*/` :
` //${comment.text}`;
magicString.append( commentBlock );
}
previousMargin = statement.margin[1];
previousModule = statement.module;
previousIndex = statement.index;
}); });
// prepend bundle with internal namespaces // prepend bundle with internal namespaces
@ -408,57 +350,6 @@ export default class Bundle {
return { code, map }; return { code, map };
} }
markAllModifierStatements () {
let settled = true;
let promises = [];
this.modules.forEach( module => {
module.statements.forEach( statement => {
if ( statement.isIncluded ) return;
keys( statement.modifies ).forEach( name => {
const definingStatement = module.definitions[ name ];
const exportDeclaration = module.exports[ name ] || (
module.exports.default && module.exports.default.identifier === name && module.exports.default
);
const shouldMark = ( definingStatement && definingStatement.isIncluded ) ||
( exportDeclaration && exportDeclaration.isUsed );
if ( shouldMark ) {
settled = false;
promises.push( statement.mark() );
return;
}
// special case - https://github.com/rollup/rollup/pull/40
const importDeclaration = module.imports[ name ];
if ( !importDeclaration ) return;
const promise = Promise.resolve( importDeclaration.module || this.fetchModule( importDeclaration.source, module.id ) )
.then( module => {
importDeclaration.module = module;
const exportDeclaration = module.exports[ importDeclaration.name ];
// TODO things like `export default a + b` don't apply here... right?
return module.findDefiningStatement( exportDeclaration.localName );
})
.then( definingStatement => {
if ( !definingStatement ) return;
settled = false;
return statement.mark();
});
promises.push( promise );
});
});
});
return Promise.all( promises ).then( () => {
if ( !settled ) return this.markAllModifierStatements();
});
}
sort () { sort () {
let seen = {}; let seen = {};
let ordered = []; let ordered = [];
@ -540,14 +431,6 @@ export default class Bundle {
}); });
} }
let statements = []; return ordered;
ordered.forEach( module => {
module.statements.forEach( statement => {
if ( statement.isIncluded ) statements.push( statement );
});
});
return statements;
} }
} }

162
src/Module.js

@ -4,10 +4,8 @@ import { parse } from 'acorn';
import MagicString from 'magic-string'; import MagicString from 'magic-string';
import Statement from './Statement'; import Statement from './Statement';
import walk from './ast/walk'; import walk from './ast/walk';
import analyse from './ast/analyse';
import { blank, keys } from './utils/object'; import { blank, keys } from './utils/object';
import { first, sequence } from './utils/promise'; import { first, sequence } from './utils/promise';
import { isImportDeclaration, isExportDeclaration } from './utils/map-helpers';
import getLocation from './utils/getLocation'; import getLocation from './utils/getLocation';
import makeLegalIdentifier from './utils/makeLegalIdentifier'; import makeLegalIdentifier from './utils/makeLegalIdentifier';
@ -21,6 +19,15 @@ function deconflict ( name, names ) {
return name; return name;
} }
function isEmptyExportedVarDeclaration ( node, module, allBundleExports, es6 ) {
if ( node.type !== 'VariableDeclaration' || node.declarations[0].init ) return false;
const name = node.declarations[0].id.name;
const canonicalName = module.getCanonicalName( name, es6 );
return canonicalName in allBundleExports;
}
export default class Module { export default class Module {
constructor ({ id, source, bundle }) { constructor ({ id, source, bundle }) {
this.source = source; this.source = source;
@ -169,14 +176,12 @@ export default class Module {
analyse () { analyse () {
// discover this module's imports and exports // discover this module's imports and exports
this.statements.forEach( statement => { this.statements.forEach( statement => {
if ( isImportDeclaration( statement ) ) this.addImport( statement ); if ( statement.isImportDeclaration ) this.addImport( statement );
else if ( isExportDeclaration( statement ) ) this.addExport( statement ); else if ( statement.isExportDeclaration ) this.addExport( statement );
});
analyse( this.magicString, this ); statement.analyse();
// consolidate names that are defined/modified in this module // consolidate names that are defined/modified in this module
this.statements.forEach( statement => {
keys( statement.defines ).forEach( name => { keys( statement.defines ).forEach( name => {
this.definitions[ name ] = statement; this.definitions[ name ] = statement;
}); });
@ -530,37 +535,60 @@ export default class Module {
}); });
let statements = []; let statements = [];
let lastChar = 0;
let commentIndex = 0;
ast.body.map( node => { ast.body.forEach( node => {
// special case - top-level var declarations with multiple declarators // special case - top-level var declarations with multiple declarators
// should be split up. Otherwise, we may end up including code we // should be split up. Otherwise, we may end up including code we
// don't need, just because an unwanted declarator is included // don't need, just because an unwanted declarator is included
if ( node.type === 'VariableDeclaration' && node.declarations.length > 1 ) { if ( node.type === 'VariableDeclaration' && node.declarations.length > 1 ) {
node.declarations.forEach( declarator => { // remove the leading var/let/const
const magicString = this.magicString.snip( declarator.start, declarator.end ).trim(); this.magicString.remove( node.start, node.declarations[0].start );
magicString.prepend( `${node.kind} ` ).append( ';' );
node.declarations.forEach( ( declarator, i ) => {
const { start, end } = declarator;
const syntheticNode = { const syntheticNode = {
type: 'VariableDeclaration', type: 'VariableDeclaration',
kind: node.kind, kind: node.kind,
start: node.start, start,
end: node.end, end,
declarations: [ declarator ] declarations: [ declarator ],
isSynthetic: true
}; };
const statement = new Statement( syntheticNode, magicString, this, statements.length ); const statement = new Statement( syntheticNode, this, start, end );
statements.push( statement ); statements.push( statement );
}); });
lastChar = node.end; // TODO account for trailing line comment
} }
else { else {
const magicString = this.magicString.snip( node.start, node.end ).trim(); let comment;
const statement = new Statement( node, magicString, this, statements.length ); do {
comment = this.comments[ commentIndex ];
if ( !comment ) break;
if ( comment.start > node.start ) break;
commentIndex += 1;
} while ( comment.end < lastChar );
const start = comment ? Math.min( comment.start, node.start ) : node.start;
const end = node.end; // TODO account for trailing line comment
const statement = new Statement( node, this, start, end );
statements.push( statement ); statements.push( statement );
lastChar = end;
} }
}); });
statements.forEach( ( statement, i ) => {
const nextStatement = statements[ i + 1 ];
statement.next = nextStatement ? nextStatement.start : statement.end;
});
return statements; return statements;
} }
@ -569,6 +597,102 @@ export default class Module {
this.canonicalNames[ name ] = this.canonicalNames[ name + '-es6' ] = replacement; this.canonicalNames[ name ] = this.canonicalNames[ name + '-es6' ] = replacement;
} }
render ( allBundleExports, format ) {
let magicString = this.magicString.clone();
let previousIndex = -1;
let previousMargin = 0;
this.statements.forEach( ( statement, i ) => {
if ( !statement.isIncluded ) {
magicString.remove( statement.start, statement.next );
return;
}
// skip `export { foo, bar, baz }`
if ( statement.node.type === 'ExportNamedDeclaration' ) {
// skip `export { foo, bar, baz }`
if ( statement.node.specifiers.length ) {
magicString.remove( statement.start, statement.next );
return;
};
// skip `export var foo;` if foo is exported
if ( isEmptyExportedVarDeclaration( statement.node.declaration, statement.module, allBundleExports, format === 'es6' ) ) {
magicString.remove( statement.start, statement.next );
return;
}
}
// skip empty var declarations for exported bindings
// (otherwise we're left with `exports.foo;`, which is useless)
if ( isEmptyExportedVarDeclaration( statement.node, statement.module, allBundleExports, format === 'es6' ) ) {
magicString.remove( statement.start, statement.next );
return;
}
// split up/remove var declarations as necessary
if ( statement.node.isSynthetic ) {
magicString.insert( statement.start, `${statement.node.kind} ` );
magicString.overwrite( statement.end, statement.next, ';\n' ); // TODO account for trailing newlines
}
let replacements = blank();
let bundleExports = blank();
keys( statement.dependsOn )
.concat( keys( statement.defines ) )
.forEach( name => {
const canonicalName = statement.module.getCanonicalName( name, format === 'es6' );
if ( allBundleExports[ canonicalName ] ) {
bundleExports[ name ] = replacements[ name ] = allBundleExports[ canonicalName ];
} else if ( name !== canonicalName ) {
replacements[ name ] = canonicalName;
}
});
statement.replaceIdentifiers( magicString, replacements, bundleExports );
// modify exports as necessary
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 );
}
// remove `export` from `export class Foo {...}` or `export default Foo`
// TODO default exports need different treatment
else if ( statement.node.declaration.id ) {
magicString.remove( statement.node.start, statement.node.declaration.start );
}
else if ( statement.node.type === 'ExportDefaultDeclaration' ) {
const module = statement.module;
const canonicalName = module.getCanonicalName( 'default', format === 'es6' );
if ( statement.node.declaration.type === 'Identifier' && canonicalName === module.getCanonicalName( statement.node.declaration.name, format === 'es6' ) ) {
magicString.remove( statement.start, statement.next );
return;
}
// anonymous functions should be converted into declarations
if ( statement.node.declaration.type === 'FunctionExpression' ) {
magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${canonicalName}` );
} else {
magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${canonicalName} = ` );
}
}
else {
throw new Error( 'Unhandled export' );
}
}
});
return magicString.trim();
}
suggestName ( defaultOrBatch, suggestion ) { suggestName ( defaultOrBatch, suggestion ) {
// deconflict anonymous default exports with this module's definitions // deconflict anonymous default exports with this module's definitions
const shouldDeconflict = this.exports.default && this.exports.default.isAnonymous; const shouldDeconflict = this.exports.default && this.exports.default.isAnonymous;

36
src/Statement.js

@ -9,12 +9,12 @@ function isIife ( node, parent ) {
} }
export default class Statement { export default class Statement {
constructor ( node, magicString, module, index ) { constructor ( node, module, start, end ) {
this.node = node; this.node = node;
this.module = module; this.module = module;
this.magicString = magicString; this.start = start;
this.index = index; this.end = end;
this.id = module.id + '#' + index; this.next = null; // filled in later
this.scope = new Scope(); this.scope = new Scope();
this.defines = blank(); this.defines = blank();
@ -24,30 +24,19 @@ export default class Statement {
this.isIncluded = false; this.isIncluded = false;
this.leadingComments = [];
this.trailingComment = null;
this.margin = [ 0, 0 ];
// some facts about this statement...
this.isImportDeclaration = node.type === 'ImportDeclaration'; this.isImportDeclaration = node.type === 'ImportDeclaration';
this.isExportDeclaration = /^Export/.test( node.type ); this.isExportDeclaration = /^Export/.test( node.type );
this.isExportAllDeclaration = /^ExportAll/.test( node.type );
} }
analyse () { analyse () {
if ( this.isImportDeclaration ) return; // nothing to analyse if ( this.isImportDeclaration ) return; // nothing to analyse
const statement = this; // TODO use arrow functions instead
const magicString = this.magicString;
let scope = this.scope; let scope = this.scope;
walk( this.node, { walk( this.node, {
enter ( node, parent ) { enter ( node, parent ) {
let newScope; let newScope;
magicString.addSourcemapLocation( node.start );
switch ( node.type ) { switch ( node.type ) {
case 'FunctionExpression': case 'FunctionExpression':
case 'FunctionDeclaration': case 'FunctionDeclaration':
@ -146,7 +135,7 @@ export default class Statement {
} }
keys( scope.declarations ).forEach( name => { keys( scope.declarations ).forEach( name => {
statement.defines[ name ] = true; this.defines[ name ] = true;
}); });
} }
@ -247,8 +236,7 @@ export default class Statement {
}); });
} }
replaceIdentifiers ( names, bundleExports ) { replaceIdentifiers ( magicString, names, bundleExports ) {
const magicString = this.magicString.clone();
const replacementStack = [ names ]; const replacementStack = [ names ];
const nameList = keys( names ); const nameList = keys( names );
@ -292,11 +280,13 @@ export default class Statement {
.map( name => `\n${bundleExports[name]} = ${name};` ) .map( name => `\n${bundleExports[name]} = ${name};` )
.join( '' ); .join( '' );
// TODO clean this up if ( exportInitialisers ) {
try { // TODO clean this up
magicString.insert( node.end, exportInitialisers ); try {
} catch ( err ) { magicString.insert( node.end, exportInitialisers );
magicString.append( exportInitialisers ); } catch ( err ) {
magicString.append( exportInitialisers );
}
} }
} }
} }

66
src/ast/analyse.js

@ -1,66 +0,0 @@
export default function analyse ( magicString, module ) {
// first we need to generate comprehensive scope info
let previousStatement = null;
let commentIndex = 0;
module.statements.forEach( statement => {
const node = statement.node;
let trailing = !!previousStatement;
let previousComment;
// TODO surely this can be neater
// attach leading comment
do {
let comment = module.comments[ commentIndex ];
// prevent comments inside the previous statement being
// appended to it
if ( previousStatement ) {
while ( comment && comment.start < previousStatement.node.end ) {
commentIndex += 1;
comment = module.comments[ commentIndex ];
}
}
if ( !comment || ( comment.end > node.start ) ) break;
// attach any trailing comment to the previous statement
if ( trailing && !/\n/.test( module.source.slice( previousStatement.node.end, comment.start ) ) ) {
previousStatement.trailingComment = comment;
}
// then attach leading comments to this statement
else {
statement.leadingComments.push({
separator: previousComment ? magicString.slice( previousComment.end, comment.start ) : '\n',
comment
});
previousComment = comment;
}
commentIndex += 1;
trailing = false;
} while ( module.comments[ commentIndex ] );
// determine margin
const previousEnd = previousComment ?
previousComment.end :
previousStatement ?
( previousStatement.trailingComment || previousStatement.node ).end :
0;
//const start = ( statement.leadingComments[0] || node ).start;
const gap = magicString.original.slice( previousEnd, node.start );
const margin = gap.split( '\n' ).length;
if ( previousStatement ) previousStatement.margin[1] = margin;
statement.margin[0] = margin;
statement.analyse();
previousStatement = statement;
});
}

4
src/rollup.js

@ -14,14 +14,14 @@ export function rollup ( options ) {
return bundle.build().then( () => { return bundle.build().then( () => {
return { return {
generate: options => bundle.generate( options ), generate: options => bundle.render( options ),
write: options => { write: options => {
if ( !options || !options.dest ) { if ( !options || !options.dest ) {
throw new Error( 'You must supply options.dest to bundle.write' ); throw new Error( 'You must supply options.dest to bundle.write' );
} }
const dest = options.dest; const dest = options.dest;
let { code, map } = bundle.generate( options ); let { code, map } = bundle.render( options );
let promises = []; let promises = [];

8
src/utils/map-helpers.js

@ -9,11 +9,3 @@ export function quoteId ( x ) {
export function req ( x ) { export function req ( x ) {
return `require('${x.id}')`; return `require('${x.id}')`;
} }
export function isImportDeclaration ( statement ) {
return statement.isImportDeclaration;
}
export function isExportDeclaration ( statement ) {
return statement.isExportDeclaration;
}

1
test/form/exported-empty-vars/_expected/es6.js

@ -3,7 +3,6 @@ foo = 42;
var bar; var bar;
var baz; var baz;
bar = 43; bar = 43;
baz = 44; baz = 44;

1
test/form/self-contained-bundle/_expected/amd.js

@ -8,7 +8,6 @@ define(function () { 'use strict';
return 42; return 42;
} }
// comment before 1 // comment before 1
console.log( 1 ); console.log( 1 );

1
test/form/self-contained-bundle/_expected/cjs.js

@ -8,7 +8,6 @@ function bar () {
return 42; return 42;
} }
// comment before 1 // comment before 1
console.log( 1 ); console.log( 1 );

1
test/form/self-contained-bundle/_expected/es6.js

@ -6,7 +6,6 @@ function bar () {
return 42; return 42;
} }
// comment before 1 // comment before 1
console.log( 1 ); console.log( 1 );

1
test/form/self-contained-bundle/_expected/iife.js

@ -8,7 +8,6 @@
return 42; return 42;
} }
// comment before 1 // comment before 1
console.log( 1 ); console.log( 1 );

1
test/form/self-contained-bundle/_expected/umd.js

@ -12,7 +12,6 @@
return 42; return 42;
} }
// comment before 1 // comment before 1
console.log( 1 ); console.log( 1 );

3
test/function/unused-var-a/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'omits unused var declaration (a)'
};

2
test/function/unused-var-a/foo.js

@ -0,0 +1,2 @@
var unused = 'unused', foo = 'foo', bar = 'bar';
export { foo, bar };

4
test/function/unused-var-a/main.js

@ -0,0 +1,4 @@
import { foo, bar } from './foo';
assert.equal( foo, 'foo' );
assert.equal( bar, 'bar' );

3
test/function/unused-var-b/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'omits unused var declaration (b)'
};

2
test/function/unused-var-b/foo.js

@ -0,0 +1,2 @@
var foo = 'foo', unused = 'unused', bar = 'bar';
export { foo, bar };

4
test/function/unused-var-b/main.js

@ -0,0 +1,4 @@
import { foo, bar } from './foo';
assert.equal( foo, 'foo' );
assert.equal( bar, 'bar' );

3
test/function/unused-var-c/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'omits unused var declaration (c)'
};

2
test/function/unused-var-c/foo.js

@ -0,0 +1,2 @@
var foo = 'foo', bar = 'bar', unused = 'unused';
export { foo, bar };

4
test/function/unused-var-c/main.js

@ -0,0 +1,4 @@
import { foo, bar } from './foo';
assert.equal( foo, 'foo' );
assert.equal( bar, 'bar' );

3
test/function/unused-var-d/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'omits unused var declaration (d)'
};

5
test/function/unused-var-d/foo.js

@ -0,0 +1,5 @@
var unused_a = 'a', unused_b = 'b';
var unused_c = 'c';
var foo = 'foo', bar = 'bar';
export { foo, bar };

4
test/function/unused-var-d/main.js

@ -0,0 +1,4 @@
import { foo, bar } from './foo';
assert.equal( foo, 'foo' );
assert.equal( bar, 'bar' );
Loading…
Cancel
Save