Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rollup

Package Overview
Dependencies
Maintainers
3
Versions
834
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rollup - npm Package Compare versions

Comparing version 0.20.5 to 0.21.0

src/ast/conditions.js

10

bin/runRollup.js

@@ -7,2 +7,5 @@ require( 'source-map-support' ).install();

// log to stderr to keep `rollup main.js > bundle.js` from breaking
var log = console.error.bind(console);
module.exports = function ( command ) {

@@ -28,3 +31,3 @@ if ( command._.length > 1 ) {

entry: config,
onwarn: function () {}
onwarn: log
}).then( function ( bundle ) {

@@ -54,3 +57,4 @@ var code = bundle.generate({

require.extensions[ '.js' ] = defaultLoader;
});
})
.catch(log);
} else {

@@ -90,2 +94,4 @@ execute( {}, command );

options.onwarn = options.onwarn || log;
options.external = external;

@@ -92,0 +98,0 @@ options.indent = command.indent !== false;

# rollup changelog
## 0.21.0
* Only include statements whose side-effects are relevant (i.e. contribute to exports or affect global state) ([#253](https://github.com/rollup/rollup/pull/253)) ([#253](https://github.com/rollup/rollup/pull/253))
* Exclude dead branches from analysis and inclusion ([#249](https://github.com/rollup/rollup/pull/249))
* Add `aggressive: true` option to eliminate all side-effects outside entry module
* More informative error when re-exporting non-existent binding ([#274](https://github.com/rollup/rollup/issues/274))
* Fix infinite recursion bug ([#291](https://github.com/rollup/rollup/issues/291))
* Log errors when using `rollup --config` ([#288](https://github.com/rollup/rollup/pull/288))
* Return rejected promises on startup instead of throwing error, if options are invalid ([#303](https://github.com/rollup/rollup/pull/303))
## 0.20.5

@@ -4,0 +14,0 @@

8

package.json
{
"name": "rollup",
"version": "0.20.5",
"version": "0.21.0",
"description": "Next-generation ES6 module bundler",

@@ -11,3 +11,3 @@ "main": "dist/rollup.js",

"scripts": {
"pretest": "npm run build",
"pretest": "npm run lint && npm run build",
"test": "mocha",

@@ -21,3 +21,3 @@ "pretest-coverage": "npm run build",

"prepublish": "npm test && npm run build:browser",
"lint": "eslint src"
"lint": "eslint src browser"
},

@@ -45,3 +45,3 @@ "repository": {

"devDependencies": {
"acorn": "^2.5.0",
"acorn": "^2.6.4",
"babel-core": "^5.8.32",

@@ -48,0 +48,0 @@ "codecov.io": "^0.1.6",

@@ -5,3 +5,3 @@ # Rollup

<a href="https://travis-ci.org/rollup/rollup">
<img src="http://img.shields.io/travis/rollup/rollup.svg"
<img src="https://api.travis-ci.org/rollup/rollup.svg?branch=master"
alt="build status">

@@ -8,0 +8,0 @@ </a>

@@ -23,3 +23,6 @@ import { walk } from 'estree-walker';

const isBlockDeclaration = blockDeclarations[ node.kind ];
node.declarations.forEach( declaration => scope.addDeclaration( declaration, isBlockDeclaration, true ) );
node.declarations.forEach( declarator => {
scope.addDeclaration( declarator, isBlockDeclaration, true );
});
}

@@ -26,0 +29,0 @@

import { blank, keys } from '../utils/object.js';
import Declaration from '../Declaration.js';

@@ -36,37 +37,2 @@ const extractors = {

class Declaration {
constructor () {
this.statement = null;
this.name = null;
this.isReassigned = false;
this.aliases = [];
}
addAlias ( declaration ) {
this.aliases.push( declaration );
}
addReference ( reference ) {
reference.declaration = this;
this.name = reference.name; // TODO handle differences of opinion
if ( reference.isReassignment ) this.isReassigned = true;
}
render ( es6 ) {
if ( es6 ) return this.name;
if ( !this.isReassigned || !this.isExported ) return this.name;
return `exports.${this.name}`;
}
use () {
this.isUsed = true;
if ( this.statement ) this.statement.mark();
this.aliases.forEach( alias => alias.use() );
}
}
export default class Scope {

@@ -78,2 +44,3 @@ constructor ( options ) {

this.isBlockScope = !!options.block;
this.isTopLevel = !this.parent || ( this.parent.isTopLevel && this.isBlockScope );

@@ -85,3 +52,3 @@ this.declarations = blank();

extractNames( param ).forEach( name => {
this.declarations[ name ] = new Declaration( name );
this.declarations[ name ] = new Declaration( param, true );
});

@@ -99,3 +66,3 @@ });

extractNames( node.id ).forEach( name => {
this.declarations[ name ] = new Declaration( name );
this.declarations[ name ] = new Declaration( node );
});

@@ -102,0 +69,0 @@ }

@@ -42,3 +42,2 @@ import Promise from 'es6-promise/lib/es6-promise/promise.js';

this.pending = blank();
this.moduleById = blank();

@@ -54,2 +53,3 @@ this.modules = [];

this.onwarn = options.onwarn || onwarn;
this.aggressive = options.aggressive;

@@ -61,2 +61,5 @@ // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles

build () {
// Phase 1 – discovery. We load the entry module and find which
// modules it imports, and import those, until we have all
// of the entry module's dependencies
return Promise.resolve( this.resolveId( this.entry, undefined ) )

@@ -67,2 +70,4 @@ .then( id => this.fetchModule( id, undefined ) )

// Phase 2 – binding. We link references to their declarations
// to generate a complete picture of the bundle
this.modules.forEach( module => module.bindImportSpecifiers() );

@@ -72,2 +77,5 @@ this.modules.forEach( module => module.bindAliases() );

// Phase 3 – marking. We 'run' each statement to see which ones
// need to be included in the generated bundle
// mark all export statements

@@ -81,2 +89,3 @@ entryModule.getExports().forEach( name => {

// mark statements that should appear in the bundle
let settled = false;

@@ -86,7 +95,14 @@ while ( !settled ) {

this.modules.forEach( module => {
if ( module.markAllSideEffects() ) settled = false;
});
if ( this.aggressive ) {
settled = !entryModule.run();
} else {
this.modules.forEach( module => {
if ( module.run() ) settled = false;
});
}
}
// Phase 4 – final preparation. We order the modules with an
// enhanced topological sort that accounts for cycles, then
// ensure that names are deconflicted throughout the bundle
this.orderedModules = this.sort();

@@ -131,4 +147,4 @@ this.deconflict();

// short-circuit cycles
if ( this.pending[ id ] ) return null;
this.pending[ id ] = true;
if ( id in this.moduleById ) return null;
this.moduleById[ id ] = null;

@@ -269,8 +285,6 @@ return Promise.resolve( this.load( id ) )

keys( strongDependencies ).forEach( id => {
const imported = strongDependencies[ id ];
strongDependencies.forEach( imported => {
strongDeps[ module.id ].push( imported );
if ( seen[ id ] ) {
if ( seen[ imported.id ] ) {
// we need to prevent an infinite loop, and note that

@@ -285,6 +299,4 @@ // we need to check for strong/weak dependency relationships

keys( weakDependencies ).forEach( id => {
const imported = weakDependencies[ id ];
if ( seen[ id ] ) {
weakDependencies.forEach( imported => {
if ( seen[ imported.id ] ) {
// we need to prevent an infinite loop, and note that

@@ -291,0 +303,0 @@ // we need to check for strong/weak dependency relationships

import { blank } from './utils/object.js';
import makeLegalIdentifier from './utils/makeLegalIdentifier.js';
import { ExternalDeclaration } from './Declaration.js';
class ExternalDeclaration {
constructor ( module, name ) {
this.module = module;
this.name = name;
this.isExternal = true;
}
addAlias () {
// noop
}
addReference ( reference ) {
reference.declaration = this;
if ( this.name === 'default' || this.name === '*' ) {
this.module.suggestName( reference.name );
}
}
render ( es6 ) {
if ( this.name === '*' ) {
return this.module.name;
}
if ( this.name === 'default' ) {
return !es6 && this.module.exportsNames ?
`${this.module.name}__default` :
this.module.name;
}
return es6 ? this.name : `${this.module.name}.${this.name}`;
}
use () {
// noop?
}
}
export default class ExternalModule {

@@ -43,0 +6,0 @@ constructor ( id ) {

@@ -10,124 +10,6 @@ import { parse } from 'acorn/src/index.js';

import SOURCEMAPPING_URL from './utils/sourceMappingURL.js';
import { SyntheticDefaultDeclaration, SyntheticNamespaceDeclaration } from './Declaration.js';
import { isFalsy, isTruthy } from './ast/conditions.js';
import { emptyBlockStatement } from './ast/create.js';
class SyntheticDefaultDeclaration {
constructor ( node, statement, name ) {
this.node = node;
this.statement = statement;
this.name = name;
this.original = null;
this.isExported = false;
this.aliases = [];
}
addAlias ( declaration ) {
this.aliases.push( declaration );
}
addReference ( reference ) {
// Don't change the name to `default`; it's not a valid identifier name.
if ( reference.name === 'default' ) return;
reference.declaration = this;
this.name = reference.name;
}
bind ( declaration ) {
this.original = declaration;
}
render () {
return !this.original || this.original.isReassigned ?
this.name :
this.original.render();
}
use () {
this.isUsed = true;
this.statement.mark();
if ( this.original ) this.original.use();
this.aliases.forEach( alias => alias.use() );
}
}
class SyntheticNamespaceDeclaration {
constructor ( module ) {
this.module = module;
this.name = null;
this.needsNamespaceBlock = false;
this.aliases = [];
this.originals = blank();
module.getExports().forEach( name => {
this.originals[ name ] = module.traceExport( name );
});
}
addAlias ( declaration ) {
this.aliases.push( declaration );
}
addReference ( reference ) {
// if we have e.g. `foo.bar`, we can optimise
// the reference by pointing directly to `bar`
if ( reference.parts.length ) {
reference.name = reference.parts.shift();
reference.end += reference.name.length + 1; // TODO this is brittle
const original = this.originals[ reference.name ];
// throw with an informative error message if the reference doesn't exist.
if ( !original ) {
this.module.bundle.onwarn( `Export '${reference.name}' is not defined by '${this.module.id}'` );
reference.isUndefined = true;
return;
}
original.addReference( reference );
return;
}
// otherwise we're accessing the namespace directly,
// which means we need to mark all of this module's
// exports and render a namespace block in the bundle
if ( !this.needsNamespaceBlock ) {
this.needsNamespaceBlock = true;
this.module.bundle.internalNamespaces.push( this );
}
reference.declaration = this;
this.name = reference.name;
}
renderBlock ( indentString ) {
const members = keys( this.originals ).map( name => {
const original = this.originals[ name ];
if ( original.isReassigned ) {
return `${indentString}get ${name} () { return ${original.render()}; }`;
}
return `${indentString}${name}: ${original.render()}`;
});
return `var ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`;
}
render () {
return this.name;
}
use () {
keys( this.originals ).forEach( name => {
this.originals[ name ].use();
});
this.aliases.forEach( alias => alias.use() );
}
}
export default class Module {

@@ -173,2 +55,4 @@ constructor ({ id, code, originalCode, ast, sourceMapChain, bundle }) {

this.analyse();
this.strongDependencies = [];
}

@@ -193,2 +77,3 @@

this.reexports[ specifier.exported.name ] = {
start: specifier.start,
source,

@@ -280,3 +165,3 @@ localName: specifier.local.name,

statement.analyse();
statement.firstPass();

@@ -305,4 +190,7 @@ statement.scope.eachDeclaration( ( name, declaration ) => {

const init = statement.node.declarations[0].init;
if ( !init || init.type === 'FunctionExpression' ) return;
statement.references.forEach( reference => {
if ( reference.name === name || !reference.isImmediatelyUsed ) return;
if ( reference.name === name ) return;

@@ -361,4 +249,4 @@ const otherDeclaration = this.trace( reference.name );

consolidateDependencies () {
let strongDependencies = blank();
let weakDependencies = blank();
let strongDependencies = [];
let weakDependencies = [];

@@ -370,24 +258,10 @@ // treat all imports as weak dependencies

if ( !dependency.isExternal ) {
weakDependencies[ dependency.id ] = dependency;
if ( !dependency.isExternal && !~weakDependencies.indexOf( dependency ) ) {
weakDependencies.push( dependency );
}
});
// identify strong dependencies to break ties in case of cycles
this.statements.forEach( statement => {
statement.references.forEach( reference => {
const declaration = reference.declaration;
strongDependencies = this.strongDependencies
.filter( module => module !== this );
if ( declaration && declaration.statement ) {
const module = declaration.statement.module;
if ( module === this ) return;
// TODO disregard function declarations
if ( reference.isImmediatelyUsed ) {
strongDependencies[ module.id ] = module;
}
}
});
});
return { strongDependencies, weakDependencies };

@@ -416,12 +290,2 @@ }

markAllSideEffects () {
let hasSideEffect = false;
this.statements.forEach( statement => {
if ( statement.markSideEffect() ) hasSideEffect = true;
});
return hasSideEffect;
}
namespace () {

@@ -457,2 +321,13 @@ if ( !this.declarations['*'] ) {

enter: node => {
// eliminate dead branches early
if ( node.type === 'IfStatement' ) {
if ( isFalsy( node.test ) ) {
this.magicString.overwrite( node.consequent.start, node.consequent.end, '{}' );
node.consequent = emptyBlockStatement( node.consequent.start, node.consequent.end );
} else if ( node.alternate && isTruthy( node.test ) ) {
this.magicString.overwrite( node.alternate.start, node.alternate.end, '{}' );
node.alternate = emptyBlockStatement( node.alternate.start, node.alternate.end );
}
}
this.magicString.addSourcemapLocation( node.start );

@@ -696,2 +571,12 @@ this.magicString.addSourcemapLocation( node.end );

run () {
let marked = false;
this.statements.forEach( statement => {
marked = marked || statement.run( this.strongDependencies );
});
return marked;
}
trace ( name ) {

@@ -720,3 +605,12 @@ if ( name in this.declarations ) return this.declarations[ name ];

if ( reexportDeclaration ) {
return reexportDeclaration.module.traceExport( reexportDeclaration.localName );
const declaration = reexportDeclaration.module.traceExport( reexportDeclaration.localName );
if ( !declaration ) {
const err = new Error( `'${reexportDeclaration.localName}' is not exported by '${reexportDeclaration.module.id}' (imported by '${this.id}')` );
err.file = this.id;
err.loc = getLocation( this.code, reexportDeclaration.start );
throw err;
}
return declaration;
}

@@ -723,0 +617,0 @@

@@ -12,7 +12,7 @@ import Promise from 'es6-promise/lib/es6-promise/promise.js';

if ( !options || !options.entry ) {
throw new Error( 'You must supply options.entry to rollup' );
return Promise.reject( new Error( 'You must supply options.entry to rollup' ) );
}
if ( options.transform || options.load || options.resolveId || options.resolveExternal ) {
throw new Error( 'The `transform`, `load`, `resolveId` and `resolveExternal` options are deprecated in favour of a unified plugin API. See https://github.com/rollup/rollup/wiki/Plugins for details' );
return Promise.reject( new Error( 'The `transform`, `load`, `resolveId` and `resolveExternal` options are deprecated in favour of a unified plugin API. See https://github.com/rollup/rollup/wiki/Plugins for details' ) );
}

@@ -19,0 +19,0 @@

import { walk } from 'estree-walker';
import Scope from './ast/Scope.js';
import attachScopes from './ast/attachScopes.js';
import modifierNodes from './ast/modifierNodes.js';
import isFunctionDeclaration from './ast/isFunctionDeclaration.js';
import isReference from './ast/isReference.js';
import getLocation from './utils/getLocation.js';
import run from './utils/run.js';
const modifierNodes = {
AssignmentExpression: 'left',
UpdateExpression: 'argument'
};
function isIife ( node, parent ) {
return parent && parent.type === 'CallExpression' && node === parent.callee;
}
function isReference ( node, parent ) {
if ( node.type === 'MemberExpression' ) {
return !node.computed && isReference( node.object, node );
}
if ( node.type === 'Identifier' ) {
// TODO is this right?
if ( parent.type === 'MemberExpression' ) return parent.computed || node === parent.object;
// disregard the `bar` in { bar: foo }
if ( parent.type === 'Property' && node !== parent.value ) return false;
// disregard the `bar` in `class Foo { bar () {...} }`
if ( parent.type === 'MethodDefinition' ) return false;
// disregard the `bar` in `export { foo as bar }`
if ( parent.type === 'ExportSpecifier' && node !== parent.local ) return;
return true;
}
}
class Reference {
constructor ( node, scope ) {
constructor ( node, scope, statement ) {
this.node = node;
this.scope = scope;
this.statement = statement;

@@ -74,2 +48,3 @@ this.declaration = null; // bound later

this.isIncluded = false;
this.ran = false;

@@ -79,5 +54,8 @@ this.isImportDeclaration = node.type === 'ImportDeclaration';

this.isReexportDeclaration = this.isExportDeclaration && !!node.source;
this.isFunctionDeclaration = isFunctionDeclaration( node ) ||
this.isExportDeclaration && isFunctionDeclaration( node.declaration );
}
analyse () {
firstPass () {
if ( this.isImportDeclaration ) return; // nothing to analyse

@@ -95,2 +73,3 @@

// find references
const statement = this;
let { module, references, scope, stringLiteralRanges } = this;

@@ -115,3 +94,3 @@ let readDepth = 0;

if ( node._scope ) scope = node._scope;
if ( /Function/.test( node.type ) && !isIife( node, parent ) ) readDepth += 1;
if ( /Function/.test( node.type ) ) readDepth += 1;

@@ -163,14 +142,13 @@ // special case – shorthand properties. because node.key === node.value,

const reference = new Reference( node, referenceScope );
const reference = new Reference( node, referenceScope, statement );
reference.isReassignment = isReassignment;
references.push( reference );
reference.isImmediatelyUsed = !readDepth;
reference.isReassignment = isReassignment;
this.skip(); // don't descend from `foo.bar.baz` into `foo.bar`
}
},
leave ( node, parent ) {
leave ( node ) {
if ( node._scope ) scope = scope.parent;
if ( /Function/.test( node.type ) && !isIife( node, parent ) ) readDepth -= 1;
if ( /Function/.test( node.type ) ) readDepth -= 1;
}

@@ -189,35 +167,10 @@ });

markSideEffect () {
if ( this.isIncluded ) return;
run ( strongDependencies ) {
if ( ( this.ran && this.isIncluded ) || this.isImportDeclaration || this.isFunctionDeclaration ) return;
this.ran = true;
const statement = this;
let hasSideEffect = false;
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' || node.type === 'NewExpression' ) {
hasSideEffect = true;
}
else if ( node.type in modifierNodes ) {
let subject = node[ modifierNodes[ node.type ] ];
while ( subject.type === 'MemberExpression' ) subject = subject.object;
const declaration = statement.module.trace( subject.name );
if ( !declaration || declaration.isExternal || declaration.statement.isIncluded ) {
hasSideEffect = true;
}
}
if ( hasSideEffect ) this.skip();
}
});
if ( hasSideEffect ) statement.mark();
return hasSideEffect;
if ( run( this.node, this.scope, this, strongDependencies ) ) {
this.mark();
return true;
}
}

@@ -224,0 +177,0 @@

import { isFile, readFileSync } from './fs.js';
import { dirname, extname, isAbsolute, resolve } from './path.js';
import { dirname, isAbsolute, resolve } from './path.js';

@@ -31,3 +31,3 @@ export function load ( id ) {

export function onwarn ( msg ) {
console.error( msg );
console.error( msg ); //eslint-disable-line no-console
}

@@ -12,3 +12,3 @@ import Promise from 'es6-promise/lib/es6-promise/promise.js';

}, Promise.resolve() );
}
};
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc