diff --git a/package.json b/package.json index b5f55c2..fcc43da 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "dependencies": { "acorn": "^1.1.0", "chalk": "^1.0.0", - "magic-string": "^0.6.2", + "magic-string": "^0.6.4", "minimist": "^1.1.1", "sander": "^0.3.3", "source-map-support": "^0.3.1" diff --git a/src/Bundle.js b/src/Bundle.js index 4ed55a0..3bf0138 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -13,15 +13,6 @@ import getExportMode from './utils/getExportMode'; import getIndentString from './utils/getIndentString'; 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 { constructor ( options ) { this.entry = options.entry; @@ -90,7 +81,7 @@ export default class Bundle { return this.markAllModifierStatements(); }) .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`) - this.statements.forEach( statement => { - const module = statement.module; - const names = keys( statement.defines ); + this.orderedModules.forEach( module => { + module.statements.forEach( statement => { + const names = keys( statement.defines ); - // with default exports that are expressions (`export default 42`), - // we need to ensure that the name chosen for the expression does - // not conflict - if ( statement.node.type === 'ExportDefaultDeclaration' ) { - const name = module.getCanonicalName( 'default', es6 ); + // with default exports that are expressions (`export default 42`), + // we need to ensure that the name chosen for the expression does + // not conflict + if ( statement.node.type === 'ExportDefaultDeclaration' ) { + const name = module.getCanonicalName( 'default', es6 ); - const isProxy = statement.node.declaration && statement.node.declaration.type === 'Identifier'; - const shouldDeconflict = !isProxy || ( module.getCanonicalName( statement.node.declaration.name, es6 ) !== name ); + const isProxy = statement.node.declaration && statement.node.declaration.type === 'Identifier'; + const shouldDeconflict = !isProxy || ( module.getCanonicalName( statement.node.declaration.name, es6 ) !== name ); - if ( shouldDeconflict && !~names.indexOf( name ) ) { - names.push( name ); + if ( shouldDeconflict && !~names.indexOf( name ) ) { + names.push( name ); + } } - } - names.forEach( name => { - if ( definers[ name ] ) { - conflicts[ name ] = true; - } else { - definers[ name ] = []; - } + names.forEach( name => { + if ( definers[ name ] ) { + conflicts[ name ] = true; + } else { + definers[ name ] = []; + } - // TODO in good js, there shouldn't be duplicate definitions - // per module... but some people write bad js - definers[ name ].push( module ); + // TODO in good js, there shouldn't be duplicate definitions + // per module... but some people write bad js + definers[ name ].push( module ); + }); }); }); @@ -213,9 +205,58 @@ export default class Bundle { }); } - generate ( options = {} ) { - let magicString = new MagicString.Bundle({ separator: '' }); + 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(); + }); + } + + render ( options = {} ) { const format = options.format || 'es6'; this.deconflict( format === 'es6' ); @@ -256,113 +297,14 @@ export default class Bundle { this.toExport = keys( this.entryModule.exports ) .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 => { - // skip `export { foo, bar, baz }` - if ( statement.node.type === 'ExportNamedDeclaration' ) { - // skip `export { foo, bar, baz }` - if ( statement.node.specifiers.length ) return; + let magicString = new MagicString.Bundle({ separator: '\n\n' }); - // skip `export var foo;` if foo is exported - if ( isEmptyExportedVarDeclaration( statement.node.declaration, statement.module, allBundleExports, format === 'es6' ) ) return; + this.orderedModules.forEach( module => { + 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 @@ -408,57 +350,6 @@ export default class Bundle { 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 () { let seen = {}; let ordered = []; @@ -540,14 +431,6 @@ export default class Bundle { }); } - let statements = []; - - ordered.forEach( module => { - module.statements.forEach( statement => { - if ( statement.isIncluded ) statements.push( statement ); - }); - }); - - return statements; + return ordered; } } diff --git a/src/Module.js b/src/Module.js index a26e340..3cf9b8a 100644 --- a/src/Module.js +++ b/src/Module.js @@ -4,10 +4,8 @@ import { parse } from 'acorn'; import MagicString from 'magic-string'; import Statement from './Statement'; import walk from './ast/walk'; -import analyse from './ast/analyse'; import { blank, keys } from './utils/object'; import { first, sequence } from './utils/promise'; -import { isImportDeclaration, isExportDeclaration } from './utils/map-helpers'; import getLocation from './utils/getLocation'; import makeLegalIdentifier from './utils/makeLegalIdentifier'; @@ -21,6 +19,15 @@ function deconflict ( name, names ) { 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 { constructor ({ id, source, bundle }) { this.source = source; @@ -169,14 +176,12 @@ export default class Module { analyse () { // discover this module's imports and exports this.statements.forEach( statement => { - if ( isImportDeclaration( statement ) ) this.addImport( statement ); - else if ( isExportDeclaration( statement ) ) this.addExport( statement ); - }); + if ( statement.isImportDeclaration ) this.addImport( statement ); + else if ( statement.isExportDeclaration ) this.addExport( statement ); - analyse( this.magicString, this ); + statement.analyse(); - // consolidate names that are defined/modified in this module - this.statements.forEach( statement => { + // consolidate names that are defined/modified in this module keys( statement.defines ).forEach( name => { this.definitions[ name ] = statement; }); @@ -530,37 +535,60 @@ export default class Module { }); 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 // 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 ) { - node.declarations.forEach( declarator => { - const magicString = this.magicString.snip( declarator.start, declarator.end ).trim(); - magicString.prepend( `${node.kind} ` ).append( ';' ); + // remove the leading var/let/const + this.magicString.remove( node.start, node.declarations[0].start ); + + node.declarations.forEach( ( declarator, i ) => { + const { start, end } = declarator; const syntheticNode = { type: 'VariableDeclaration', kind: node.kind, - start: node.start, - end: node.end, - declarations: [ declarator ] + start, + end, + declarations: [ declarator ], + isSynthetic: true }; - const statement = new Statement( syntheticNode, magicString, this, statements.length ); + const statement = new Statement( syntheticNode, this, start, end ); statements.push( statement ); }); + + lastChar = node.end; // TODO account for trailing line comment } else { - const magicString = this.magicString.snip( node.start, node.end ).trim(); - const statement = new Statement( node, magicString, this, statements.length ); - + let comment; + 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 ); + + lastChar = end; } }); + statements.forEach( ( statement, i ) => { + const nextStatement = statements[ i + 1 ]; + statement.next = nextStatement ? nextStatement.start : statement.end; + }); + return statements; } @@ -569,6 +597,102 @@ export default class Module { 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 ) { // deconflict anonymous default exports with this module's definitions const shouldDeconflict = this.exports.default && this.exports.default.isAnonymous; diff --git a/src/Statement.js b/src/Statement.js index 7cfbebf..43b6bf7 100644 --- a/src/Statement.js +++ b/src/Statement.js @@ -9,12 +9,12 @@ function isIife ( node, parent ) { } export default class Statement { - constructor ( node, magicString, module, index ) { + constructor ( node, module, start, end ) { this.node = node; this.module = module; - this.magicString = magicString; - this.index = index; - this.id = module.id + '#' + index; + this.start = start; + this.end = end; + this.next = null; // filled in later this.scope = new Scope(); this.defines = blank(); @@ -24,30 +24,19 @@ export default class Statement { this.isIncluded = false; - this.leadingComments = []; - this.trailingComment = null; - this.margin = [ 0, 0 ]; - - // some facts about this statement... this.isImportDeclaration = node.type === 'ImportDeclaration'; this.isExportDeclaration = /^Export/.test( node.type ); - this.isExportAllDeclaration = /^ExportAll/.test( node.type ); } analyse () { if ( this.isImportDeclaration ) return; // nothing to analyse - const statement = this; // TODO use arrow functions instead - const magicString = this.magicString; - let scope = this.scope; walk( this.node, { enter ( node, parent ) { let newScope; - magicString.addSourcemapLocation( node.start ); - switch ( node.type ) { case 'FunctionExpression': case 'FunctionDeclaration': @@ -146,7 +135,7 @@ export default class Statement { } keys( scope.declarations ).forEach( name => { - statement.defines[ name ] = true; + this.defines[ name ] = true; }); } @@ -247,8 +236,7 @@ export default class Statement { }); } - replaceIdentifiers ( names, bundleExports ) { - const magicString = this.magicString.clone(); + replaceIdentifiers ( magicString, names, bundleExports ) { const replacementStack = [ names ]; const nameList = keys( names ); @@ -292,11 +280,13 @@ export default class Statement { .map( name => `\n${bundleExports[name]} = ${name};` ) .join( '' ); - // TODO clean this up - try { - magicString.insert( node.end, exportInitialisers ); - } catch ( err ) { - magicString.append( exportInitialisers ); + if ( exportInitialisers ) { + // TODO clean this up + try { + magicString.insert( node.end, exportInitialisers ); + } catch ( err ) { + magicString.append( exportInitialisers ); + } } } } diff --git a/src/ast/analyse.js b/src/ast/analyse.js deleted file mode 100644 index 21b5f4c..0000000 --- a/src/ast/analyse.js +++ /dev/null @@ -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; - }); -} diff --git a/src/rollup.js b/src/rollup.js index 0b8a652..846c8f2 100644 --- a/src/rollup.js +++ b/src/rollup.js @@ -14,14 +14,14 @@ export function rollup ( options ) { return bundle.build().then( () => { return { - generate: options => bundle.generate( options ), + generate: options => bundle.render( options ), write: options => { if ( !options || !options.dest ) { throw new Error( 'You must supply options.dest to bundle.write' ); } const dest = options.dest; - let { code, map } = bundle.generate( options ); + let { code, map } = bundle.render( options ); let promises = []; diff --git a/src/utils/map-helpers.js b/src/utils/map-helpers.js index 9576535..49e0942 100644 --- a/src/utils/map-helpers.js +++ b/src/utils/map-helpers.js @@ -9,11 +9,3 @@ export function quoteId ( x ) { export function req ( x ) { return `require('${x.id}')`; } - -export function isImportDeclaration ( statement ) { - return statement.isImportDeclaration; -} - -export function isExportDeclaration ( statement ) { - return statement.isExportDeclaration; -} diff --git a/test/form/exported-empty-vars/_expected/es6.js b/test/form/exported-empty-vars/_expected/es6.js index 8151c68..3be564f 100644 --- a/test/form/exported-empty-vars/_expected/es6.js +++ b/test/form/exported-empty-vars/_expected/es6.js @@ -3,7 +3,6 @@ foo = 42; var bar; var baz; - bar = 43; baz = 44; diff --git a/test/form/self-contained-bundle/_expected/amd.js b/test/form/self-contained-bundle/_expected/amd.js index 5638a53..ed04c7c 100644 --- a/test/form/self-contained-bundle/_expected/amd.js +++ b/test/form/self-contained-bundle/_expected/amd.js @@ -8,7 +8,6 @@ define(function () { 'use strict'; return 42; } - // comment before 1 console.log( 1 ); diff --git a/test/form/self-contained-bundle/_expected/cjs.js b/test/form/self-contained-bundle/_expected/cjs.js index 8b0b5bd..8a71fe7 100644 --- a/test/form/self-contained-bundle/_expected/cjs.js +++ b/test/form/self-contained-bundle/_expected/cjs.js @@ -8,7 +8,6 @@ function bar () { return 42; } - // comment before 1 console.log( 1 ); diff --git a/test/form/self-contained-bundle/_expected/es6.js b/test/form/self-contained-bundle/_expected/es6.js index def67b9..7d5460c 100644 --- a/test/form/self-contained-bundle/_expected/es6.js +++ b/test/form/self-contained-bundle/_expected/es6.js @@ -6,7 +6,6 @@ function bar () { return 42; } - // comment before 1 console.log( 1 ); diff --git a/test/form/self-contained-bundle/_expected/iife.js b/test/form/self-contained-bundle/_expected/iife.js index 1ec92be..46f6561 100644 --- a/test/form/self-contained-bundle/_expected/iife.js +++ b/test/form/self-contained-bundle/_expected/iife.js @@ -8,7 +8,6 @@ return 42; } - // comment before 1 console.log( 1 ); diff --git a/test/form/self-contained-bundle/_expected/umd.js b/test/form/self-contained-bundle/_expected/umd.js index 854c4e4..51b72b0 100644 --- a/test/form/self-contained-bundle/_expected/umd.js +++ b/test/form/self-contained-bundle/_expected/umd.js @@ -12,7 +12,6 @@ return 42; } - // comment before 1 console.log( 1 ); diff --git a/test/function/unused-var-a/_config.js b/test/function/unused-var-a/_config.js new file mode 100644 index 0000000..05a2b74 --- /dev/null +++ b/test/function/unused-var-a/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'omits unused var declaration (a)' +}; diff --git a/test/function/unused-var-a/foo.js b/test/function/unused-var-a/foo.js new file mode 100644 index 0000000..ef10681 --- /dev/null +++ b/test/function/unused-var-a/foo.js @@ -0,0 +1,2 @@ +var unused = 'unused', foo = 'foo', bar = 'bar'; +export { foo, bar }; diff --git a/test/function/unused-var-a/main.js b/test/function/unused-var-a/main.js new file mode 100644 index 0000000..9922892 --- /dev/null +++ b/test/function/unused-var-a/main.js @@ -0,0 +1,4 @@ +import { foo, bar } from './foo'; + +assert.equal( foo, 'foo' ); +assert.equal( bar, 'bar' ); diff --git a/test/function/unused-var-b/_config.js b/test/function/unused-var-b/_config.js new file mode 100644 index 0000000..174d9fe --- /dev/null +++ b/test/function/unused-var-b/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'omits unused var declaration (b)' +}; diff --git a/test/function/unused-var-b/foo.js b/test/function/unused-var-b/foo.js new file mode 100644 index 0000000..26a8538 --- /dev/null +++ b/test/function/unused-var-b/foo.js @@ -0,0 +1,2 @@ +var foo = 'foo', unused = 'unused', bar = 'bar'; +export { foo, bar }; diff --git a/test/function/unused-var-b/main.js b/test/function/unused-var-b/main.js new file mode 100644 index 0000000..9922892 --- /dev/null +++ b/test/function/unused-var-b/main.js @@ -0,0 +1,4 @@ +import { foo, bar } from './foo'; + +assert.equal( foo, 'foo' ); +assert.equal( bar, 'bar' ); diff --git a/test/function/unused-var-c/_config.js b/test/function/unused-var-c/_config.js new file mode 100644 index 0000000..e40d968 --- /dev/null +++ b/test/function/unused-var-c/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'omits unused var declaration (c)' +}; diff --git a/test/function/unused-var-c/foo.js b/test/function/unused-var-c/foo.js new file mode 100644 index 0000000..14e28bb --- /dev/null +++ b/test/function/unused-var-c/foo.js @@ -0,0 +1,2 @@ +var foo = 'foo', bar = 'bar', unused = 'unused'; +export { foo, bar }; diff --git a/test/function/unused-var-c/main.js b/test/function/unused-var-c/main.js new file mode 100644 index 0000000..9922892 --- /dev/null +++ b/test/function/unused-var-c/main.js @@ -0,0 +1,4 @@ +import { foo, bar } from './foo'; + +assert.equal( foo, 'foo' ); +assert.equal( bar, 'bar' ); diff --git a/test/function/unused-var-d/_config.js b/test/function/unused-var-d/_config.js new file mode 100644 index 0000000..78379d6 --- /dev/null +++ b/test/function/unused-var-d/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'omits unused var declaration (d)' +}; diff --git a/test/function/unused-var-d/foo.js b/test/function/unused-var-d/foo.js new file mode 100644 index 0000000..630ff46 --- /dev/null +++ b/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 }; diff --git a/test/function/unused-var-d/main.js b/test/function/unused-var-d/main.js new file mode 100644 index 0000000..9922892 --- /dev/null +++ b/test/function/unused-var-d/main.js @@ -0,0 +1,4 @@ +import { foo, bar } from './foo'; + +assert.equal( foo, 'foo' ); +assert.equal( bar, 'bar' );