Browse Source

merge master -> side-effects

better-aggressive
Rich Harris 9 years ago
parent
commit
2316cff821
  1. 12
      CHANGELOG.md
  2. 2
      README.md
  3. 10
      bin/runRollup.js
  4. 8
      package.json
  5. 13
      src/Module.js
  6. 3
      src/Statement.js
  7. 2
      src/ast/attachScopes.js
  8. 38
      src/ast/conditions.js
  9. 7
      src/ast/create.js
  10. 1
      src/rollup.js
  11. 4
      src/utils/defaults.js
  12. 2
      src/utils/first.js
  13. 1
      src/utils/run.js
  14. 35
      src/utils/transform.js
  15. 10
      test/function/assignment-to-re-exports-conflict/_config.js
  16. 10
      test/function/assignment-to-re-exports-conflict/count.js
  17. 1
      test/function/assignment-to-re-exports-conflict/main.js
  18. 10
      test/function/assignment-to-re-exports/_config.js
  19. 5
      test/function/assignment-to-re-exports/count.js
  20. 1
      test/function/assignment-to-re-exports/main.js
  21. 8
      test/function/export-from-no-local-binding-var/_config.js
  22. 1
      test/function/export-from-no-local-binding-var/foo.js
  23. 3
      test/function/export-from-no-local-binding-var/main.js
  24. 8
      test/function/skips-dead-branches-b/_config.js
  25. 11
      test/function/skips-dead-branches-b/main.js
  26. 8
      test/function/skips-dead-branches-c/_config.js
  27. 11
      test/function/skips-dead-branches-c/main.js
  28. 8
      test/function/skips-dead-branches-d/_config.js
  29. 11
      test/function/skips-dead-branches-d/main.js
  30. 8
      test/function/skips-dead-branches-e/_config.js
  31. 11
      test/function/skips-dead-branches-e/main.js
  32. 8
      test/function/skips-dead-branches-f/_config.js
  33. 11
      test/function/skips-dead-branches-f/main.js
  34. 8
      test/function/skips-dead-branches/_config.js
  35. 11
      test/function/skips-dead-branches/main.js
  36. 24
      test/function/transformer-async/_config.js
  37. 1
      test/function/transformer-async/main.js
  38. 2
      test/test.js

12
CHANGELOG.md

@ -1,5 +1,17 @@
# rollup changelog
## 0.20.5
* Ensure re-exports don't create a local binding ([#270](https://github.com/rollup/rollup/pull/270))
## 0.20.4
* Check file exists at resolve time, to allow filenames with non-extension dots in them ([#250](https://github.com/rollup/rollup/pull/250))
* Import `Promise` where used, for Node 0.10 support ([#254](https://github.com/rollup/rollup/issues/254))
* Allow asynchronous transformer plugins ([#260](https://github.com/rollup/rollup/issues/260))
* Don't assume re-exported bindings are globals when deconflicting ([#267](https://github.com/rollup/rollup/issues/267))
## 0.20.3
* Fix bug where multiple `export *` declarations caused error ([#244](https://github.com/rollup/rollup/pulls/244))

2
README.md

@ -2,7 +2,7 @@
<p align="center">
<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">
</a>
<a href="https://npmjs.org/package/rollup">

10
bin/runRollup.js

@ -4,6 +4,9 @@ var path = require( 'path' );
var handleError = require( './handleError' );
var rollup = require( '../' );
// log to stderr to keep `rollup main.js > bundle.js` from breaking
var log = console.error.bind(console);
module.exports = function ( command ) {
if ( command._.length > 1 ) {
handleError({ code: 'ONE_AT_A_TIME' });
@ -24,7 +27,7 @@ module.exports = function ( command ) {
rollup.rollup({
entry: config,
onwarn: function () {}
onwarn: log
}).then( function ( bundle ) {
var code = bundle.generate({
format: 'cjs'
@ -49,7 +52,8 @@ module.exports = function ( command ) {
execute( options, command );
require.extensions[ '.js' ] = defaultLoader;
});
})
.catch(log);
} else {
execute( {}, command );
}
@ -84,6 +88,8 @@ function execute ( options, command ) {
command.globals = globals;
}
options.onwarn = options.onwarn || log;
options.external = external;
options.indent = command.indent !== false;

8
package.json

@ -1,6 +1,6 @@
{
"name": "rollup",
"version": "0.20.3",
"version": "0.20.5",
"description": "Next-generation ES6 module bundler",
"main": "dist/rollup.js",
"jsnext:main": "src/rollup.js",
@ -8,7 +8,7 @@
"rollup": "./bin/rollup"
},
"scripts": {
"pretest": "npm run build",
"pretest": "npm run lint && 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",
@ -17,7 +17,7 @@
"build": "git rev-parse HEAD > .commithash && rollup -c -o dist/rollup.js",
"build:browser": "git rev-parse HEAD > .commithash && rollup -c rollup.config.browser.js -o dist/rollup.browser.js",
"prepublish": "npm test && npm run build:browser",
"lint": "eslint src"
"lint": "eslint src browser"
},
"repository": {
"type": "git",
@ -50,7 +50,7 @@
"istanbul": "^0.4.0",
"magic-string": "^0.8.0",
"mocha": "^2.3.3",
"remap-istanbul": "^0.3.1",
"remap-istanbul": "^0.4.0",
"rollup": "^0.20.2",
"rollup-plugin-babel": "^1.0.0",
"rollup-plugin-npm": "^1.0.0",

13
src/Module.js

@ -8,6 +8,8 @@ import getLocation from './utils/getLocation.js';
import makeLegalIdentifier from './utils/makeLegalIdentifier.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';
export default class Module {
constructor ({ id, code, originalCode, ast, sourceMapChain, bundle }) {
@ -307,6 +309,17 @@ export default class Module {
walk( ast, {
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 );
this.magicString.addSourcemapLocation( node.end );
}

3
src/Statement.js

@ -79,6 +79,9 @@ export default class Statement {
module.bundle.onwarn( `Use of \`eval\` (in ${module.id}) is discouraged, as it may cause issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details` );
}
// skip re-export declarations
if ( node.type === 'ExportNamedDeclaration' && node.source ) return this.skip();
if ( node.type === 'TemplateElement' ) stringLiteralRanges.push([ node.start, node.end ]);
if ( node.type === 'Literal' && typeof node.value === 'string' && /\n/.test( node.raw ) ) {
stringLiteralRanges.push([ node.start + 1, node.end - 1 ]);

2
src/ast/attachScopes.js

@ -17,7 +17,7 @@ export default function attachScopes ( statement ) {
scope.addDeclaration( node, false, false );
}
// var foo = 1
// var foo = 1, bar = 2
if ( node.type === 'VariableDeclaration' ) {
const isBlockDeclaration = blockDeclarations[ node.kind ];

38
src/ast/conditions.js

@ -0,0 +1,38 @@
export function isTruthy ( node ) {
if ( node.type === 'Literal' ) return !!node.value;
if ( node.type === 'ParenthesizedExpression' ) return isTruthy( node.expression );
if ( node.operator in operators ) return operators[ node.operator ]( node );
}
export function isFalsy ( node ) {
return not( isTruthy( node ) );
}
function not ( value ) {
return value === undefined ? value : !value;
}
function equals ( a, b, strict ) {
if ( a.type !== b.type ) return undefined;
if ( a.type === 'Literal' ) return strict ? a.value === b.value : a.value == b.value;
}
const operators = {
'==': x => {
return equals( x.left, x.right, false );
},
'!=': x => not( operators['==']( x ) ),
'===': x => {
return equals( x.left, x.right, true );
},
'!==': x => not( operators['===']( x ) ),
'!': x => isFalsy( x.argument ),
'&&': x => isTruthy( x.left ) && isTruthy( x.right ),
'||': x => isTruthy( x.left ) || isTruthy( x.right )
};

7
src/ast/create.js

@ -0,0 +1,7 @@
export function emptyBlockStatement ( start, end ) {
return {
start, end,
type: 'BlockStatement',
body: []
};
}

1
src/rollup.js

@ -1,3 +1,4 @@
import Promise from 'es6-promise/lib/es6-promise/promise.js';
import { basename } from './utils/path.js';
import { writeFile } from './utils/fs.js';
import { keys } from './utils/object.js';

4
src/utils/defaults.js

@ -1,5 +1,5 @@
import { isFile, readFileSync } from './fs.js';
import { dirname, extname, isAbsolute, resolve } from './path.js';
import { dirname, isAbsolute, resolve } from './path.js';
export function load ( id ) {
return readFileSync( id, 'utf-8' );
@ -28,5 +28,5 @@ export function resolveId ( importee, importer ) {
}
export function onwarn ( msg ) {
console.error( msg );
console.error( msg ); //eslint-disable-line no-console
}

2
src/utils/first.js

@ -9,5 +9,5 @@ export default function first ( candidates ) {
result :
Promise.resolve( candidate( ...args ) ) );
}, Promise.resolve() );
}
};
}

1
src/utils/run.js

@ -1,6 +1,5 @@
import { walk } from 'estree-walker';
import modifierNodes from '../ast/modifierNodes.js';
import isFunctionDeclaration from '../ast/isFunctionDeclaration.js';
import isReference from '../ast/isReference.js';
import flatten from '../ast/flatten';

35
src/utils/transform.js

@ -1,3 +1,5 @@
import Promise from 'es6-promise/lib/es6-promise/promise.js';
export default function transform ( source, id, transformers ) {
let sourceMapChain = [];
@ -11,24 +13,27 @@ export default function transform ( source, id, transformers ) {
let originalCode = source.code;
let ast = source.ast;
let code = transformers.reduce( ( previous, transformer ) => {
let result = transformer( previous, id );
return transformers.reduce( ( promise, transformer ) => {
return promise.then( previous => {
return Promise.resolve( transformer( previous, id ) ).then( result => {
if ( result == null ) return previous;
if ( result == null ) return previous;
if ( typeof result === 'string' ) {
result = {
code: result,
ast: null,
map: null
};
}
if ( typeof result === 'string' ) {
result = {
code: result,
ast: null,
map: null
};
}
sourceMapChain.push( result.map );
ast = result.ast;
sourceMapChain.push( result.map );
ast = result.ast;
return result.code;
});
});
return result.code;
}, source.code );
}, Promise.resolve( source.code ) )
return { code, originalCode, ast, sourceMapChain };
.then( code => ({ code, originalCode, ast, sourceMapChain }) );
}

10
test/function/assignment-to-re-exports-conflict/_config.js

@ -0,0 +1,10 @@
var assert = require( 'assert' );
module.exports = {
description: 're-exports are kept up-to-date',
exports: function ( exports ) {
assert.equal( exports.count, 0 );
exports.incr();
assert.equal( exports.count, 1 );
}
};

10
test/function/assignment-to-re-exports-conflict/count.js

@ -0,0 +1,10 @@
export var count = 0;
export function conflict () {
var foo = 0,
count = 42;
}
export function incr () {
count += 1;
}

1
test/function/assignment-to-re-exports-conflict/main.js

@ -0,0 +1 @@
export {count, incr, conflict} from './count';

10
test/function/assignment-to-re-exports/_config.js

@ -0,0 +1,10 @@
var assert = require( 'assert' );
module.exports = {
description: 're-exports are kept up-to-date',
exports: function ( exports ) {
assert.equal( exports.count, 0 );
exports.incr();
assert.equal( exports.count, 1 );
}
};

5
test/function/assignment-to-re-exports/count.js

@ -0,0 +1,5 @@
export var count = 0;
export function incr () {
count += 1;
}

1
test/function/assignment-to-re-exports/main.js

@ -0,0 +1 @@
export {count, incr} from './count';

8
test/function/export-from-no-local-binding-var/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'export from does not create a local binding',
runtimeError: function ( err ) {
assert.ok( /foo is not defined/.test( err.message ) );
}
};

1
test/function/export-from-no-local-binding-var/foo.js

@ -0,0 +1 @@
export default function() {}

3
test/function/export-from-no-local-binding-var/main.js

@ -0,0 +1,3 @@
export {default as foo} from './foo';
export var foo1 = foo(); // This should fail as foo lacks a local binding.

8
test/function/skips-dead-branches-b/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (b)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-b/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( true ) bar();
else obj.foo();

8
test/function/skips-dead-branches-c/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (c)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-c/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( !true ) obj.foo();
bar();

8
test/function/skips-dead-branches-d/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (d)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-d/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( 'development' === 'production' ) obj.foo();
bar();

8
test/function/skips-dead-branches-e/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (e)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-e/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( 'production' !== 'production' ) obj.foo();
bar();

8
test/function/skips-dead-branches-f/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (g)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-f/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( 42 != '42' ) obj.foo();
bar();

8
test/function/skips-dead-branches/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( false ) obj.foo();
else bar();

24
test/function/transformer-async/_config.js

@ -0,0 +1,24 @@
var Promise = require( 'es6-promise' ).Promise;
module.exports = {
description: 'transformers can be asynchronous',
options: {
plugins: [
{
transform: function ( code ) {
return Promise.resolve( code.replace( 'x', 1 ) );
}
},
{
transform: function ( code ) {
return code.replace( '1', 2 );
}
},
{
transform: function ( code ) {
return Promise.resolve( code.replace( '2', 3 ) );
}
}
]
}
};

1
test/function/transformer-async/main.js

@ -0,0 +1 @@
assert.equal( x, 3 );

2
test/test.js

@ -161,6 +161,8 @@ describe( 'rollup', function () {
code = result.code;
}
if ( config.code ) config.code( code );
var module = {
exports: {}
};

Loading…
Cancel
Save