Navigation Menu

Skip to content

Commit

Permalink
Merge branch 'master' into tagged-template-expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Aug 11, 2017
2 parents 8071790 + 2395452 commit 5bdb0cb
Show file tree
Hide file tree
Showing 100 changed files with 2,296 additions and 1,178 deletions.
1 change: 0 additions & 1 deletion .eslintrc → .eslintrc.json
Expand Up @@ -5,7 +5,6 @@
"semi": [ 2, "always" ],
"keyword-spacing": [ 2, { "before": true, "after": true } ],
"space-before-blocks": [ 2, "always" ],
"space-before-function-paren": [ 2, "always" ],
"no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
"no-cond-assign": 0,
"no-unused-vars": 2,
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -7,3 +7,4 @@ coverage
.commithash
.idea
bin/rollup
test/_tmp
4 changes: 2 additions & 2 deletions bin/src/index.js
@@ -1,7 +1,7 @@
import minimist from 'minimist';
import help from './help.md';
import { version } from '../../package.json';
import runRollup from './runRollup';
import run from './run/index.js';

const command = minimist( process.argv.slice( 2 ), {
alias: {
Expand Down Expand Up @@ -35,5 +35,5 @@ else if ( command.version ) {
}

else {
runRollup( command );
run( command );
}
39 changes: 16 additions & 23 deletions bin/src/logging.js
Expand Up @@ -2,42 +2,35 @@ import chalk from 'chalk';
import relativeId from '../../src/utils/relativeId.js';

if ( !process.stderr.isTTY ) chalk.enabled = false;
const warnSymbol = process.stderr.isTTY ? `⚠️ ` : `Warning: `;
const errorSymbol = process.stderr.isTTY ? `🚨 ` : `Error: `;

// log to stderr to keep `rollup main.js > bundle.js` from breaking
export const stderr = console.error.bind( console ); // eslint-disable-line no-console

function log ( object, symbol ) {
let description = object.message || object;
if (object.name) description = object.name + ': ' + description;
const message = (object.plugin ? `(${object.plugin} plugin) ${description}` : description) || object;;
export function handleError ( err, recover ) {
let description = err.message || err;
if (err.name) description = `${err.name}: ${description}`;
const message = (err.plugin ? `(${err.plugin} plugin) ${description}` : description) || err;

stderr( `${symbol}${chalk.bold( message )}` );
stderr( chalk.bold.red( `[!] ${chalk.bold( message )}` ) );

// TODO should this be "object.url || (object.file && object.loc.file) || object.id"?
if ( object.url ) {
stderr( chalk.cyan( object.url ) );
// TODO should this be "err.url || (err.file && err.loc.file) || err.id"?
if ( err.url ) {
stderr( chalk.cyan( err.url ) );
}

if ( object.loc ) {
stderr( `${relativeId( object.loc.file || object.id )} (${object.loc.line}:${object.loc.column})` );
} else if ( object.id ) {
stderr( relativeId( object.id ) );
if ( err.loc ) {
stderr( `${relativeId( err.loc.file || err.id )} (${err.loc.line}:${err.loc.column})` );
} else if ( err.id ) {
stderr( relativeId( err.id ) );
}

if ( object.frame ) {
stderr( chalk.dim( object.frame ) );
if ( err.frame ) {
stderr( chalk.dim( err.frame ) );
} else if ( err.stack ) {
stderr( chalk.dim( err.stack ) );
}

stderr( '' );
}

export function handleWarning ( warning ) {
log( warning, warnSymbol );
}

export function handleError ( err, recover ) {
log( err, errorSymbol );
if ( !recover ) process.exit( 1 );
}
275 changes: 275 additions & 0 deletions bin/src/run/batchWarnings.js
@@ -0,0 +1,275 @@
import chalk from 'chalk';
import { stderr } from '../logging.js';
import relativeId from '../../../src/utils/relativeId.js';

export default function batchWarnings () {
let allWarnings = new Map();
let count = 0;

return {
get count() {
return count;
},

add: warning => {
if ( typeof warning === 'string' ) {
warning = { code: 'UNKNOWN', message: warning };
}

if ( warning.code in immediateHandlers ) {
immediateHandlers[ warning.code ]( warning );
return;
}

if ( !allWarnings.has( warning.code ) ) allWarnings.set( warning.code, [] );
allWarnings.get( warning.code ).push( warning );

count += 1;
},

flush: () => {
if ( count === 0 ) return;

const codes = Array.from( allWarnings.keys() )
.sort( ( a, b ) => {
if ( deferredHandlers[a] && deferredHandlers[b] ) {
return deferredHandlers[a].priority - deferredHandlers[b].priority;
}

if ( deferredHandlers[a] ) return -1;
if ( deferredHandlers[b] ) return 1;
return allWarnings.get( b ).length - allWarnings.get( a ).length;
});

codes.forEach( code => {
const handler = deferredHandlers[ code ];
const warnings = allWarnings.get( code );

if ( handler ) {
handler.fn( warnings );
} else {
warnings.forEach( warning => {
stderr( `${chalk.bold.yellow('(!)')} ${chalk.bold.yellow( warning.message )}` );

if ( warning.url ) info( warning.url );

const id = warning.loc && warning.loc.file || warning.id;
if ( id ) {
const loc = warning.loc ?
`${relativeId( id )}: (${warning.loc.line}:${warning.loc.column})` :
relativeId( id );

stderr( chalk.bold( relativeId( loc ) ) );
}

if ( warning.frame ) info( warning.frame );
});
}
});

allWarnings = new Map();
}
};
}

const immediateHandlers = {
MISSING_NODE_BUILTINS: warning => {
title( `Missing shims for Node.js built-ins` );

const detail = warning.modules.length === 1 ?
`'${warning.modules[0]}'` :
`${warning.modules.slice( 0, -1 ).map( name => `'${name}'` ).join( ', ' )} and '${warning.modules.slice( -1 )}'`;
stderr( `Creating a browser bundle that depends on ${detail}. You might need to include https://www.npmjs.com/package/rollup-plugin-node-builtins` );
},

MIXED_EXPORTS: () => {
title( 'Mixing named and default exports' );
stderr( `Consumers of your bundle will have to use bundle['default'] to access the default export, which may not be what you want. Use \`exports: 'named'\` to disable this warning` );
},

EMPTY_BUNDLE: () => {
title( `Generated an empty bundle` );
}
};

// TODO select sensible priorities
const deferredHandlers = {
UNUSED_EXTERNAL_IMPORT: {
priority: 1,
fn: warnings => {
title( 'Unused external imports' );
warnings.forEach( warning => {
stderr( `${warning.names} imported from external module '${warning.source}' but never used` );
});
}
},

UNRESOLVED_IMPORT: {
priority: 1,
fn: warnings => {
title( 'Unresolved dependencies' );
info( 'https://github.com/rollup/rollup/wiki/Troubleshooting#treating-module-as-external-dependency' );

const dependencies = new Map();
warnings.forEach( warning => {
if ( !dependencies.has( warning.source ) ) dependencies.set( warning.source, [] );
dependencies.get( warning.source ).push( warning.importer );
});

Array.from( dependencies.keys() ).forEach( dependency => {
const importers = dependencies.get( dependency );
stderr( `${chalk.bold( dependency )} (imported by ${importers.join( ', ' )})` );
});
}
},

MISSING_EXPORT: {
priority: 1,
fn: warnings => {
title( 'Missing exports' );
info( 'https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module' );

warnings.forEach( warning => {
stderr( chalk.bold( warning.importer ) );
stderr( `${warning.missing} is not exported by ${warning.exporter}` );
stderr( chalk.grey( warning.frame ) );
});
}
},

THIS_IS_UNDEFINED: {
priority: 1,
fn: warnings => {
title( '`this` has been rewritten to `undefined`' );
info( 'https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined' );
showTruncatedWarnings(warnings);
}
},

EVAL: {
priority: 1,
fn: warnings => {
title( 'Use of eval is strongly discouraged' );
info( 'https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval' );
showTruncatedWarnings(warnings);
}
},

NON_EXISTENT_EXPORT: {
priority: 1,
fn: warnings => {
title( `Import of non-existent ${warnings.length > 1 ? 'exports' : 'export'}` );
showTruncatedWarnings(warnings);
}
},

NAMESPACE_CONFLICT: {
priority: 1,
fn: warnings => {
title( `Conflicting re-exports` );
warnings.forEach(warning => {
stderr( `${chalk.bold(relativeId(warning.reexporter))} re-exports '${warning.name}' from both ${relativeId(warning.sources[0])} and ${relativeId(warning.sources[1])} (will be ignored)` );
});
}
},

MISSING_GLOBAL_NAME: {
priority: 1,
fn: warnings => {
title( `Missing global variable ${warnings.length > 1 ? 'names' : 'name'}` );
stderr( `Use options.globals to specify browser global variable names corresponding to external modules` );
warnings.forEach(warning => {
stderr(`${chalk.bold(warning.source)} (guessing '${warning.guess}')`);
});
}
},

SOURCEMAP_BROKEN: {
priority: 1,
fn: warnings => {
title( `Broken sourcemap` );
info( 'https://github.com/rollup/rollup/wiki/Troubleshooting#sourcemap-is-likely-to-be-incorrect' );

const plugins = Array.from( new Set( warnings.map( w => w.plugin ).filter( Boolean ) ) );
const detail = plugins.length === 0 ? '' : plugins.length > 1 ?
` (such as ${plugins.slice(0, -1).map(p => `'${p}'`).join(', ')} and '${plugins.slice(-1)}')` :
` (such as '${plugins[0]}')`;

stderr( `Plugins that transform code${detail} should generate accompanying sourcemaps` );
}
},

PLUGIN_WARNING: {
priority: 1,
fn: warnings => {
const nestedByPlugin = nest(warnings, 'plugin');

nestedByPlugin.forEach(({ key: plugin, items }) => {
const nestedByMessage = nest(items, 'message');

let lastUrl;

nestedByMessage.forEach(({ key: message, items }) => {
title( `${plugin} plugin: ${message}` );
items.forEach(warning => {
if ( warning.url !== lastUrl ) info( lastUrl = warning.url );

const loc = warning.loc ?
`${relativeId( warning.id )}: (${warning.loc.line}:${warning.loc.column})` :
relativeId( warning.id );

stderr( chalk.bold( relativeId( loc ) ) );
if ( warning.frame ) info( warning.frame );
});
});
});
}
}
};

function title ( str ) {
stderr( `${chalk.bold.yellow('(!)')} ${chalk.bold.yellow( str )}` );
}

function info ( url ) {
stderr( chalk.grey( url ) );
}

function nest(array, prop) {
const nested = [];
const lookup = new Map();

array.forEach(item => {
const key = item[prop];
if (!lookup.has(key)) {
lookup.set(key, {
key,
items: []
});

nested.push(lookup.get(key));
}

lookup.get(key).items.push(item);
});

return nested;
}

function showTruncatedWarnings(warnings) {
const nestedByModule = nest(warnings, 'id');

const sliced = nestedByModule.length > 5 ? nestedByModule.slice(0, 3) : nestedByModule;
sliced.forEach(({ key: id, items }) => {
stderr( chalk.bold( relativeId( id ) ) );
stderr( chalk.grey( items[0].frame ) );

if ( items.length > 1 ) {
stderr( `...and ${items.length - 1} other ${items.length > 2 ? 'occurrences' : 'occurrence'}` );
}
});

if ( nestedByModule.length > sliced.length ) {
stderr( `\n...and ${nestedByModule.length - sliced.length} other files` );
}
}

0 comments on commit 5bdb0cb

Please sign in to comment.