Browse Source

Merge branch 'master' into gh-438-b

gh-438-b
Rich-Harris 9 years ago
parent
commit
fcc13f5eb4
  1. 42
      .eslintrc
  2. 1
      .gitattributes
  3. 82
      CHANGELOG.md
  4. 10
      README.md
  5. 4
      bin/handleError.js
  6. 1
      bin/help.md
  7. 14
      bin/runRollup.js
  8. 23
      package.json
  9. 6
      rollup.config.js
  10. 90
      src/Bundle.js
  11. 66
      src/Declaration.js
  12. 5
      src/ExternalModule.js
  13. 112
      src/Module.js
  14. 2
      src/Reference.js
  15. 63
      src/Statement.js
  16. 4
      src/ast/attachScopes.js
  17. 4
      src/ast/isReference.js
  18. 29
      src/finalisers/cjs.js
  19. 19
      src/finalisers/es6.js
  20. 4
      src/finalisers/iife.js
  21. 16
      src/finalisers/shared/getInteropBlock.js
  22. 12
      src/finalisers/umd.js
  23. 7
      src/rollup.js
  24. 33
      src/utils/collapseSourcemaps.js
  25. 5
      src/utils/getExportMode.js
  26. 6
      src/utils/object.js
  27. 16
      src/utils/promise.js
  28. 6
      src/utils/run.js
  29. 7
      src/utils/transform.js
  30. 0
      test/.babelrc
  31. 9
      test/cli/config-missing-export/_config.js
  32. 0
      test/cli/config-missing-export/rollup.config.js
  33. 4
      test/cli/no-treeshake/_config.js
  34. 10
      test/cli/no-treeshake/_expected.js
  35. 3
      test/cli/no-treeshake/main.js
  36. 6
      test/form/assignment-to-exports-class-declaration/_config.js
  37. 6
      test/form/assignment-to-exports-class-declaration/_expected/amd.js
  38. 4
      test/form/assignment-to-exports-class-declaration/_expected/cjs.js
  39. 4
      test/form/assignment-to-exports-class-declaration/_expected/es6.js
  40. 7
      test/form/assignment-to-exports-class-declaration/_expected/iife.js
  41. 10
      test/form/assignment-to-exports-class-declaration/_expected/umd.js
  42. 2
      test/form/assignment-to-exports-class-declaration/main.js
  43. 12
      test/form/computed-properties/_expected/amd.js
  44. 12
      test/form/computed-properties/_expected/cjs.js
  45. 13
      test/form/computed-properties/_expected/es6.js
  46. 14
      test/form/computed-properties/_expected/iife.js
  47. 14
      test/form/computed-properties/_expected/umd.js
  48. 11
      test/form/computed-properties/main.js
  49. 3
      test/form/conflicting-imports/_config.js
  50. 7
      test/form/conflicting-imports/_expected/amd.js
  51. 8
      test/form/conflicting-imports/_expected/cjs.js
  52. 6
      test/form/conflicting-imports/_expected/es6.js
  53. 8
      test/form/conflicting-imports/_expected/iife.js
  54. 11
      test/form/conflicting-imports/_expected/umd.js
  55. 4
      test/form/conflicting-imports/main.js
  56. 3
      test/form/conflicting-imports/other.js
  57. 2
      test/form/dedupes-external-imports/_expected/iife.js
  58. 2
      test/form/dedupes-external-imports/_expected/umd.js
  59. 3
      test/form/erroneous-nested-member-expression/_config.js
  60. 13
      test/form/erroneous-nested-member-expression/_expected/amd.js
  61. 11
      test/form/erroneous-nested-member-expression/_expected/cjs.js
  62. 9
      test/form/erroneous-nested-member-expression/_expected/es6.js
  63. 14
      test/form/erroneous-nested-member-expression/_expected/iife.js
  64. 17
      test/form/erroneous-nested-member-expression/_expected/umd.js
  65. 7
      test/form/erroneous-nested-member-expression/foo.js
  66. 2
      test/form/erroneous-nested-member-expression/main.js
  67. 2
      test/form/export-all-from-internal/_expected/iife.js
  68. 2
      test/form/export-all-from-internal/_expected/umd.js
  69. 6
      test/form/export-default-import/_config.js
  70. 9
      test/form/export-default-import/_expected/amd.js
  71. 9
      test/form/export-default-import/_expected/cjs.js
  72. 5
      test/form/export-default-import/_expected/es6.js
  73. 10
      test/form/export-default-import/_expected/iife.js
  74. 13
      test/form/export-default-import/_expected/umd.js
  75. 3
      test/form/export-default-import/main.js
  76. 2
      test/form/exports-at-end-if-possible/_expected/iife.js
  77. 2
      test/form/exports-at-end-if-possible/_expected/umd.js
  78. 2
      test/form/external-imports-custom-names/_expected/cjs.js
  79. 2
      test/form/external-imports/_expected/cjs.js
  80. 3
      test/form/import-external-namespace-and-default/_config.js
  81. 9
      test/form/import-external-namespace-and-default/_expected/amd.js
  82. 8
      test/form/import-external-namespace-and-default/_expected/cjs.js
  83. 6
      test/form/import-external-namespace-and-default/_expected/es6.js
  84. 10
      test/form/import-external-namespace-and-default/_expected/iife.js
  85. 13
      test/form/import-external-namespace-and-default/_expected/umd.js
  86. 4
      test/form/import-external-namespace-and-default/main.js
  87. 3
      test/form/import-external-namespace-and-default/other.js
  88. 6
      test/form/import-named-exported-global-with-alias/_config.js
  89. 5
      test/form/import-named-exported-global-with-alias/_expected/amd.js
  90. 2
      test/form/import-named-exported-global-with-alias/_expected/cjs.js
  91. 0
      test/form/import-named-exported-global-with-alias/_expected/es6.js
  92. 6
      test/form/import-named-exported-global-with-alias/_expected/iife.js
  93. 9
      test/form/import-named-exported-global-with-alias/_expected/umd.js
  94. 1
      test/form/import-named-exported-global-with-alias/browser.js
  95. 2
      test/form/import-named-exported-global-with-alias/main.js
  96. 2
      test/form/multiple-exports/_expected/iife.js
  97. 2
      test/form/multiple-exports/_expected/umd.js
  98. 2
      test/form/namespaced-named-exports/_expected/iife.js
  99. 2
      test/form/namespaced-named-exports/_expected/umd.js
  100. 11
      test/form/no-treeshake/_config.js

42
.eslintrc

@ -1,23 +1,23 @@
{ {
"rules": { "root": true,
"indent": [ 2, "tab", { "SwitchCase": 1 } ], "rules": {
"quotes": [ 2, "single" ], "indent": [ 2, "tab", { "SwitchCase": 1 } ],
"linebreak-style": [ 2, "unix" ], "semi": [ 2, "always" ],
"semi": [ 2, "always" ], "keyword-spacing": [ 2, { "before": true, "after": true } ],
"space-after-keywords": [ 2, "always" ], "space-before-blocks": [ 2, "always" ],
"space-before-blocks": [ 2, "always" ], "space-before-function-paren": [ 2, "always" ],
"space-before-function-paren": [ 2, "always" ], "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
"no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ], "no-cond-assign": [ 0 ]
"no-cond-assign": [ 0 ] },
}, "env": {
"env": { "es6": true,
"es6": true, "browser": true,
"browser": true, "mocha": true,
"mocha": true, "node": true
"node": true },
}, "extends": "eslint:recommended",
"extends": "eslint:recommended", "parserOptions": {
"ecmaFeatures": { "ecmaVersion": 6,
"modules": true "sourceType": "module"
} }
} }

1
.gitattributes

@ -0,0 +1 @@
*.js eol=lf

82
CHANGELOG.md

@ -1,5 +1,87 @@
# rollup changelog # rollup changelog
## 0.26.6
* Deconflict named imports from external modules in ES bundles ([#659](https://github.com/rollup/rollup/issues/659))
* Support `options.preferConst` to generate `const` declarations for exports rather than `var` declarations ([#653](https://github.com/rollup/rollup/issues/653))
## 0.26.5
* Preserve `debugger` statements ([#664](https://github.com/rollup/rollup/issues/664))
* Allow `options.external` to be a function ([#522](https://github.com/rollup/rollup/issues/522))
## 0.26.4
* Prevent plugin-provided external IDs being normalised ([#630](https://github.com/rollup/rollup/issues/630), [#633](https://github.com/rollup/rollup/issues/633))
* Throw if module exports/re-exports the same name twice, or has multiple default exports ([#679](https://github.com/rollup/rollup/issues/679))
* Warn about `eval` security issue ([#675]((https://github.com/rollup/rollup/issues/675)))
## 0.26.3
* Ensure reference is not incorrectly marked as a reassignment ([#648](https://github.com/rollup/rollup/issues/648))
## 0.26.2
* Sanity check output of `load` hook ([#607](https://github.com/rollup/rollup/issues/607))
* Correct scoping for ID class expressions ([#626](https://github.com/rollup/rollup/issues/626))
* Warn if named and default exports are used together in auto mode ([#587](https://github.com/rollup/rollup/issues/587))
* Allow variable initialisers to be rewritten if necessary ([#632](https://github.com/rollup/rollup/issues/632))
* Prevent double `var` with no-treeshake option ([#639](https://github.com/rollup/rollup/pull/639))
## 0.26.1
* Add `treeshake: false`/`--no-treeshake` option for debugging ([#505](https://github.com/rollup/rollup/issues/505))
* Update build process to use Bublé ([#620](https://github.com/rollup/rollup/pull/620))
## 0.26.0
* Add `noConflict`/`--no-conflict` option for UMD builds ([#580](https://github.com/rollup/rollup/pull/580))
* Normalise relative external paths ([#591](https://github.com/rollup/rollup/pull/591))
* Report files causing transform errors ([#609](https://github.com/rollup/rollup/pull/609))
* Handle sourcemap segments with a single member ([#619](https://github.com/rollup/rollup/pull/619))
* Update dependencies
## 0.25.8
* Unixize entry path ([#586](https://github.com/rollup/rollup/pull/586))
## 0.25.7
* Expand deshadowed shorthand properties ([#575](https://github.com/rollup/rollup/issues/575))
* Allow external files to be non-existent ([#532](https://github.com/rollup/rollup/issues/532))
## 0.25.6
* Fix a regression introduced by #566 ([#569](https://github.com/rollup/rollup/issues/569))
* Prune dead conditional expressions more carefully ([#567](https://github.com/rollup/rollup/issues/567))
## 0.25.5
* Make sure shorthand destructuring assignments don't break ([#528](https://github.com/rollup/rollup/issues/528))
* Allow 'exports' key ([#542](https://github.com/rollup/rollup/issues/542))
* Ensure `foo. bar` where `foo` is a namespace import is rewritten correctly ([#566](https://github.com/rollup/rollup/issues/566))
* Fix an edge case for exported globals (e.g. `export { document }`) ([#562](https://github.com/rollup/rollup/issues/562))
## 0.25.4
* Fix misnamed exports of default imports in ES bundles ([#513](https://github.com/rollup/rollup/issues/513))
* CLI: warn on missing config ([#515](https://github.com/rollup/rollup/pull/515))
* Detect side-effects in non-top-level member expression assignment ([#476](https://github.com/rollup/rollup/issues/476))
* Don't remove computed property class keys ([#504](https://github.com/rollup/rollup/issues/504))
* Augment existing global object rather than replacing ([#493](https://github.com/rollup/rollup/issues/493))
* Don't fail on `export {}`, warn instead ([#486](https://github.com/rollup/rollup/issues/486))
## 0.25.3
* Handle non-objects and `null` in `_interopDefault` ([#474](https://github.com/rollup/rollup/issues/474))
## 0.25.2
* Skip dead branches of a conditional expression (#[465](https://github.com/rollup/rollup/pull/465))
* Allow globals to be exported ([#472](https://github.com/rollup/rollup/pull/472))
* Ensure reassigned exports are exported ([#484](https://github.com/rollup/rollup/issues/484))
## 0.25.1 ## 0.25.1
* Throw error if namespace is called ([#446](https://github.com/rollup/rollup/issues/446)) * Throw error if namespace is called ([#446](https://github.com/rollup/rollup/issues/446))

10
README.md

@ -5,7 +5,7 @@
<img src="https://api.travis-ci.org/rollup/rollup.svg?branch=master" <img src="https://api.travis-ci.org/rollup/rollup.svg?branch=master"
alt="build status"> alt="build status">
</a> </a>
<a href="https://npmjs.org/package/rollup"> <a href="https://www.npmjs.com/package/rollup">
<img src="https://img.shields.io/npm/v/rollup.svg" <img src="https://img.shields.io/npm/v/rollup.svg"
alt="npm version"> alt="npm version">
</a> </a>
@ -17,8 +17,8 @@
<img src="https://david-dm.org/rollup/rollup.svg" <img src="https://david-dm.org/rollup/rollup.svg"
alt="dependency status"> alt="dependency status">
</a> </a>
<a href="http://codecov.io/github/rollup/rollup?branch=master"> <a href="https://codecov.io/github/rollup/rollup?branch=master">
<img src="http://codecov.io/github/rollup/rollup/coverage.svg?branch=master" alt="Coverage via Codecov" /> <img src="https://codecov.io/github/rollup/rollup/coverage.svg?branch=master" alt="Coverage via Codecov" />
</a> </a>
<a href='https://gitter.im/rollup/rollup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge'> <a href='https://gitter.im/rollup/rollup?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge'>
<img src='https://badges.gitter.im/rollup/rollup.svg' <img src='https://badges.gitter.im/rollup/rollup.svg'
@ -133,12 +133,12 @@ Unfortunately, **traditional modules – CommonJS and AMD – result in code mo
If your `package.json` has a `jsnext:main` field, ES6-aware tools like Rollup can import the ES6 version of the package instead of the legacy CommonJS or UMD version. You'll be writing your code in a more future-proof way, and helping to bring an end to the [dark days of JavaScript package management](https://medium.com/@trek/last-week-i-had-a-small-meltdown-on-twitter-about-npms-future-plans-around-front-end-packaging-b424dd8d367a). [Learn more here.](https://github.com/rollup/rollup/wiki/jsnext:main) If your `package.json` has a `jsnext:main` field, ES6-aware tools like Rollup can import the ES6 version of the package instead of the legacy CommonJS or UMD version. You'll be writing your code in a more future-proof way, and helping to bring an end to the [dark days of JavaScript package management](https://medium.com/@trek/last-week-i-had-a-small-meltdown-on-twitter-about-npms-future-plans-around-front-end-packaging-b424dd8d367a). [Learn more here.](https://github.com/rollup/rollup/wiki/jsnext:main)
See [rollup-starter-project](https://github.com/eventualbuddha/rollup-starter-project) for inspiration on how to get started. See [rollup-starter-project](https://github.com/rollup/rollup-starter-project) for inspiration on how to get started.
## How does this compare to JSPM/SystemJS? ## How does this compare to JSPM/SystemJS?
[JSPM](http://jspm.io/) is awesome! It's a little different to this project though – it combines a repository with a package manager and a client-side module loader, as opposed to simply bundling modules. JSPM allows you to use any module format and even develop without a build step, so it's a great choice for creating applications. Rollup generates smaller bundles that don't use the complex SystemJS format, and so is a better choice for creating libraries. A future version of JSPM [may use Rollup internally](https://github.com/systemjs/builder/pull/205), so you'll get the best of both worlds. [JSPM](http://jspm.io/) is awesome, and [it uses Rollup](https://github.com/systemjs/builder/pull/205) in its builder! In addition to bundling modules, it also combines a repository with a package manager and a client-side module loader. JSPM allows you to use any module format and even develop without a build step, so it's a great choice for creating applications. Stand-alone Rollup doesn't use the complex SystemJS format, making it a better choice for creating libraries.
## License ## License

4
bin/handleError.js

@ -1,6 +1,10 @@
var chalk = require( 'chalk' ); var chalk = require( 'chalk' );
var handlers = { var handlers = {
MISSING_CONFIG: function () {
console.error( chalk.red( 'Config file must export an options object. See https://github.com/rollup/rollup/wiki/Command-Line-Interface#using-a-config-file' ) );
},
MISSING_INPUT_OPTION: function () { MISSING_INPUT_OPTION: function () {
console.error( chalk.red( 'You must specify an --input (-i) option' ) ); console.error( chalk.red( 'You must specify an --input (-i) option' ) );
}, },

1
bin/help.md

@ -21,6 +21,7 @@ Basic options:
--no-strict Don't emit a `"use strict";` in the generated modules. --no-strict Don't emit a `"use strict";` in the generated modules.
--no-indent Don't indent result --no-indent Don't indent result
--environment <values> Settings passed to config file (see example) --environment <values> Settings passed to config file (see example)
--no-conflict Generate a noConflict method for UMD globals
--intro Content to insert at top of bundle (inside wrapper) --intro Content to insert at top of bundle (inside wrapper)
--outro Content to insert at end of bundle (inside wrapper) --outro Content to insert at end of bundle (inside wrapper)
--banner Content to insert at top of bundle (outside wrapper) --banner Content to insert at top of bundle (outside wrapper)

14
bin/runRollup.js

@ -59,6 +59,9 @@ module.exports = function ( command ) {
try { try {
var options = require( path.resolve( config ) ); var options = require( path.resolve( config ) );
if ( Object.keys( options ).length === 0 ) {
handleError({ code: 'MISSING_CONFIG' });
}
} catch ( err ) { } catch ( err ) {
handleError( err ); handleError( err );
} }
@ -79,12 +82,14 @@ var equivalents = {
format: 'format', format: 'format',
globals: 'globals', globals: 'globals',
id: 'moduleId', id: 'moduleId',
indent: 'indent',
input: 'entry', input: 'entry',
intro: 'intro', intro: 'intro',
name: 'moduleName', name: 'moduleName',
output: 'dest', output: 'dest',
outro: 'outro', outro: 'outro',
sourcemap: 'sourceMap' sourcemap: 'sourceMap',
treeshake: 'treeshake'
}; };
function execute ( options, command ) { function execute ( options, command ) {
@ -110,10 +115,13 @@ function execute ( options, command ) {
options.onwarn = options.onwarn || log; options.onwarn = options.onwarn || log;
options.external = external; options.external = external;
options.indent = command.indent !== false;
options.noConflict = command.conflict === false;
delete command.conflict;
// Use any options passed through the CLI as overrides.
Object.keys( equivalents ).forEach( function ( cliOption ) { Object.keys( equivalents ).forEach( function ( cliOption ) {
if ( command[ cliOption ] ) { if ( command.hasOwnProperty( cliOption ) ) {
options[ equivalents[ cliOption ] ] = command[ cliOption ]; options[ equivalents[ cliOption ] ] = command[ cliOption ];
} }
}); });

23
package.json

@ -1,6 +1,6 @@
{ {
"name": "rollup", "name": "rollup",
"version": "0.25.1", "version": "0.26.6",
"description": "Next-generation ES6 module bundler", "description": "Next-generation ES6 module bundler",
"main": "dist/rollup.js", "main": "dist/rollup.js",
"jsnext:main": "src/rollup.js", "jsnext:main": "src/rollup.js",
@ -9,7 +9,7 @@
}, },
"scripts": { "scripts": {
"pretest": "npm run build", "pretest": "npm run build",
"test": "mocha", "test": "mocha --compilers js:buble/register",
"pretest-coverage": "npm run build", "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", "test-coverage": "rm -rf coverage/* && istanbul cover --report json node_modules/.bin/_mocha -- -u exports -R spec test/test.js",
"posttest-coverage": "remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.json -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.lcov -t lcovonly -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped -t html -b dist", "posttest-coverage": "remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.json -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.lcov -t lcovonly -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped -t html -b dist",
@ -40,22 +40,23 @@
}, },
"homepage": "https://github.com/rollup/rollup", "homepage": "https://github.com/rollup/rollup",
"devDependencies": { "devDependencies": {
"acorn": "^2.6.4", "acorn": "^3.1.0",
"babel-core": "^5.8.32", "babel-core": "^5.8.32",
"buble": "^0.6.4",
"codecov.io": "^0.1.6", "codecov.io": "^0.1.6",
"console-group": "^0.1.2", "console-group": "^0.2.0",
"es6-promise": "^3.0.2", "es6-promise": "^3.0.2",
"eslint": "^1.7.1", "eslint": "^2.9.0",
"estree-walker": "^0.2.0", "estree-walker": "^0.2.0",
"istanbul": "^0.4.0", "istanbul": "^0.4.0",
"magic-string": "^0.10.1", "magic-string": "^0.10.1",
"mocha": "^2.3.3", "mocha": "^2.3.3",
"remap-istanbul": "^0.4.0", "remap-istanbul": "^0.5.1",
"rollup": "^0.20.2", "rollup": "^0.26.2",
"rollup-plugin-babel": "^1.0.0", "rollup-plugin-buble": "^0.6.0",
"rollup-plugin-npm": "^1.0.0", "rollup-plugin-node-resolve": "^1.5.0",
"rollup-plugin-replace": "^1.0.1", "rollup-plugin-replace": "^1.0.1",
"sander": "^0.4.0", "sander": "^0.5.0",
"source-map": "^0.5.3", "source-map": "^0.5.3",
"sourcemap-codec": "^1.2.1", "sourcemap-codec": "^1.2.1",
"uglify-js": "^2.6.1" "uglify-js": "^2.6.1"
@ -63,7 +64,7 @@
"dependencies": { "dependencies": {
"chalk": "^1.1.1", "chalk": "^1.1.1",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"source-map-support": "^0.3.2" "source-map-support": "^0.4.0"
}, },
"files": [ "files": [
"src", "src",

6
rollup.config.js

@ -1,6 +1,6 @@
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import babel from 'rollup-plugin-babel'; import buble from 'rollup-plugin-buble';
import npm from 'rollup-plugin-npm'; import npm from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace'; import replace from 'rollup-plugin-replace';
var pkg = JSON.parse( readFileSync( 'package.json', 'utf-8' ) ); var pkg = JSON.parse( readFileSync( 'package.json', 'utf-8' ) );
@ -22,7 +22,7 @@ export default {
entry: 'src/rollup.js', entry: 'src/rollup.js',
format: 'cjs', format: 'cjs',
plugins: [ plugins: [
babel({ buble({
include: [ 'src/**', 'node_modules/acorn/**' ] include: [ 'src/**', 'node_modules/acorn/**' ]
}), }),

90
src/Bundle.js

@ -1,7 +1,6 @@
import Promise from 'es6-promise/lib/es6-promise/promise.js';
import MagicString from 'magic-string'; import MagicString from 'magic-string';
import first from './utils/first.js'; import first from './utils/first.js';
import { blank, keys } from './utils/object.js'; import { blank, forOwn, keys } from './utils/object.js';
import Module from './Module.js'; import Module from './Module.js';
import ExternalModule from './ExternalModule.js'; import ExternalModule from './ExternalModule.js';
import finalisers from './finalisers/index.js'; import finalisers from './finalisers/index.js';
@ -10,12 +9,13 @@ import { load, makeOnwarn, resolveId } from './utils/defaults.js';
import getExportMode from './utils/getExportMode.js'; import getExportMode from './utils/getExportMode.js';
import getIndentString from './utils/getIndentString.js'; import getIndentString from './utils/getIndentString.js';
import { unixizePath } from './utils/normalizePlatform.js'; import { unixizePath } from './utils/normalizePlatform.js';
import { mapSequence } from './utils/promise.js';
import transform from './utils/transform.js'; import transform from './utils/transform.js';
import transformBundle from './utils/transformBundle.js'; import transformBundle from './utils/transformBundle.js';
import collapseSourcemaps from './utils/collapseSourcemaps.js'; import collapseSourcemaps from './utils/collapseSourcemaps.js';
import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js';
import callIfFunction from './utils/callIfFunction.js'; import callIfFunction from './utils/callIfFunction.js';
import { isRelative, resolve } from './utils/path.js'; import { dirname, isRelative, isAbsolute, relative, resolve } from './utils/path.js';
export default class Bundle { export default class Bundle {
constructor ( options ) { constructor ( options ) {
@ -27,11 +27,14 @@ export default class Bundle {
} }
}); });
this.entry = options.entry; this.entry = unixizePath( options.entry );
this.entryId = null;
this.entryModule = null; this.entryModule = null;
this.treeshake = options.treeshake !== false;
this.resolveId = first( this.resolveId = first(
[ id => ~this.external.indexOf( id ) ? false : null ] [ id => this.isExternal( id ) ? false : null ]
.concat( this.plugins.map( plugin => plugin.resolveId ).filter( Boolean ) ) .concat( this.plugins.map( plugin => plugin.resolveId ).filter( Boolean ) )
.concat( resolveId ) .concat( resolveId )
); );
@ -59,11 +62,19 @@ export default class Bundle {
this.assumedGlobals = blank(); this.assumedGlobals = blank();
this.external = ensureArray( options.external ).map( id => id.replace( /[\/\\]/g, '/' ) ); if ( typeof options.external === 'function' ) {
this.isExternal = options.external;
} else {
const ids = ensureArray( options.external ).map( id => id.replace( /[\/\\]/g, '/' ) );
this.isExternal = id => ids.indexOf( id ) !== -1;
}
this.onwarn = options.onwarn || makeOnwarn(); this.onwarn = options.onwarn || makeOnwarn();
// TODO strictly speaking, this only applies with non-ES6, non-default-only bundles // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles
[ 'module', 'exports', '_interopDefault' ].forEach( global => this.assumedGlobals[ global ] = true ); [ 'module', 'exports', '_interopDefault' ].forEach( global => this.assumedGlobals[ global ] = true );
this.varOrConst = options.preferConst ? 'const' : 'var';
} }
build () { build () {
@ -71,7 +82,10 @@ export default class Bundle {
// modules it imports, and import those, until we have all // modules it imports, and import those, until we have all
// of the entry module's dependencies // of the entry module's dependencies
return this.resolveId( this.entry, undefined ) return this.resolveId( this.entry, undefined )
.then( id => this.fetchModule( id, undefined ) ) .then( id => {
this.entryId = id;
return this.fetchModule( id, undefined );
})
.then( entryModule => { .then( entryModule => {
this.entryModule = entryModule; this.entryModule = entryModule;
@ -98,7 +112,7 @@ export default class Bundle {
settled = true; settled = true;
this.modules.forEach( module => { this.modules.forEach( module => {
if ( module.run() ) settled = false; if ( module.run( this.treeshake ) ) settled = false;
}); });
} }
@ -130,15 +144,14 @@ export default class Bundle {
// ensure we don't shadow named external imports, if // ensure we don't shadow named external imports, if
// we're creating an ES6 bundle // we're creating an ES6 bundle
keys( module.declarations ).forEach( name => { forOwn( module.declarations, ( declaration, name ) => {
const declaration = module.declarations[ name ];
declaration.setSafeName( getSafeName( name ) ); declaration.setSafeName( getSafeName( name ) );
}); });
}); });
this.modules.forEach( module => { this.modules.forEach( module => {
keys( module.declarations ).forEach( originalName => { forOwn( module.declarations, ( declaration, originalName ) => {
const declaration = module.declarations[ originalName ]; if ( declaration.isGlobal ) return;
if ( originalName === 'default' ) { if ( originalName === 'default' ) {
if ( declaration.original && !declaration.original.isReassigned ) return; if ( declaration.original && !declaration.original.isReassigned ) return;
@ -162,6 +175,12 @@ export default class Bundle {
msg += `: ${err.message}`; msg += `: ${err.message}`;
throw new Error( msg ); throw new Error( msg );
}) })
.then( source => {
if ( typeof source === 'string' ) return source;
if ( source && typeof source === 'object' && source.code ) return source;
throw new Error( `Error loading ${id}: load hook should return a string, a { code, map } object, or nothing/null` );
})
.then( source => transform( source, id, this.transformers ) ) .then( source => transform( source, id, this.transformers ) )
.then( source => { .then( source => {
const { code, originalCode, ast, sourceMapChain } = source; const { code, originalCode, ast, sourceMapChain } = source;
@ -176,23 +195,39 @@ export default class Bundle {
} }
fetchAllDependencies ( module ) { fetchAllDependencies ( module ) {
const promises = module.sources.map( source => { return mapSequence( module.sources, source => {
return this.resolveId( source, module.id ) return this.resolveId( source, module.id )
.then( resolvedId => { .then( resolvedId => {
// If the `resolvedId` is supposed to be external, make it so. let externalName;
const forcedExternal = resolvedId && ~this.external.indexOf( resolvedId.replace( /[\/\\]/g, '/' ) ); if ( resolvedId ) {
// If the `resolvedId` is supposed to be external, make it so.
externalName = resolvedId.replace( /[\/\\]/g, '/' );
} else if ( isRelative( source ) ) {
// This could be an external, relative dependency, based on the current module's parent dir.
externalName = resolve( module.id, '..', source );
}
const forcedExternal = externalName && this.isExternal( externalName );
if ( !resolvedId || forcedExternal ) { if ( !resolvedId || forcedExternal ) {
let normalizedExternal = source;
if ( !forcedExternal ) { if ( !forcedExternal ) {
if ( isRelative( source ) ) throw new Error( `Could not resolve ${source} from ${module.id}` ); if ( isRelative( source ) ) throw new Error( `Could not resolve ${source} from ${module.id}` );
if ( !~this.external.indexOf( source ) ) this.onwarn( `Treating '${source}' as external dependency` ); if ( !this.isExternal( source ) ) this.onwarn( `Treating '${source}' as external dependency` );
} else if ( resolvedId ) {
if ( isRelative(resolvedId) || isAbsolute(resolvedId) ) {
// Try to deduce relative path from entry dir if resolvedId is defined as a relative path.
normalizedExternal = this.getPathRelativeToEntryDirname( resolvedId );
} else {
normalizedExternal = resolvedId;
}
} }
module.resolvedIds[ source ] = source; module.resolvedIds[ source ] = normalizedExternal;
if ( !this.moduleById[ source ] ) { if ( !this.moduleById[ normalizedExternal ] ) {
const module = new ExternalModule( source ); const module = new ExternalModule( normalizedExternal );
this.externalModules.push( module ); this.externalModules.push( module );
this.moduleById[ source ] = module; this.moduleById[ normalizedExternal ] = module;
} }
} }
@ -206,15 +241,26 @@ export default class Bundle {
} }
}); });
}); });
}
getPathRelativeToEntryDirname ( resolvedId ) {
// Get a path relative to the resolved entry directory
const entryDirname = dirname( this.entryId );
const relativeToEntry = relative( entryDirname, resolvedId );
if ( isRelative( relativeToEntry )) {
return relativeToEntry;
}
return Promise.all( promises ); // The path is missing the `./` prefix
return `./${relativeToEntry}`;
} }
render ( options = {} ) { render ( options = {} ) {
const format = options.format || 'es6'; const format = options.format || 'es6';
// Determine export mode - 'default', 'named', 'none' // Determine export mode - 'default', 'named', 'none'
const exportMode = getExportMode( this, options.exports ); const exportMode = getExportMode( this, options.exports, options.moduleName );
let magicString = new MagicString.Bundle({ separator: '\n\n' }); let magicString = new MagicString.Bundle({ separator: '\n\n' });
let usedModules = []; let usedModules = [];

66
src/Declaration.js

@ -1,7 +1,9 @@
import { blank, keys } from './utils/object.js'; import { blank, forOwn, keys } from './utils/object.js';
import run from './utils/run.js'; import run from './utils/run.js';
import { SyntheticReference } from './Reference.js'; import { SyntheticReference } from './Reference.js';
const use = alias => alias.use();
export default class Declaration { export default class Declaration {
constructor ( node, isParam, statement ) { constructor ( node, isParam, statement ) {
if ( node ) { if ( node ) {
@ -68,7 +70,7 @@ export default class Declaration {
this.isUsed = true; this.isUsed = true;
if ( this.statement ) this.statement.mark(); if ( this.statement ) this.statement.mark();
this.aliases.forEach( alias => alias.use() ); this.aliases.forEach( use );
} }
} }
@ -129,7 +131,44 @@ export class SyntheticDefaultDeclaration {
if ( this.original ) this.original.use(); if ( this.original ) this.original.use();
this.aliases.forEach( alias => alias.use() ); this.aliases.forEach( use );
}
}
export class SyntheticGlobalDeclaration {
constructor ( name ) {
this.name = name;
this.isExternal = true;
this.isGlobal = true;
this.isReassigned = false;
this.aliases = [];
this.isUsed = false;
}
addAlias ( declaration ) {
this.aliases.push( declaration );
}
addReference ( reference ) {
reference.declaration = this;
if ( reference.isReassignment ) this.isReassigned = true;
}
render () {
return this.name;
}
run () {
return true;
}
use () {
if ( this.isUsed ) return;
this.isUsed = true;
this.aliases.forEach( use );
} }
} }
@ -156,9 +195,9 @@ export class SyntheticNamespaceDeclaration {
// if we have e.g. `foo.bar`, we can optimise // if we have e.g. `foo.bar`, we can optimise
// the reference by pointing directly to `bar` // the reference by pointing directly to `bar`
if ( reference.parts.length ) { if ( reference.parts.length ) {
reference.name = reference.parts.shift(); const ref = reference.parts.shift();
reference.name = ref.name;
reference.end += reference.name.length + 1; // TODO this is brittle reference.end = ref.end;
const original = this.originals[ reference.name ]; const original = this.originals[ reference.name ];
@ -182,8 +221,8 @@ export class SyntheticNamespaceDeclaration {
// add synthetic references, in case of chained // add synthetic references, in case of chained
// namespace imports // namespace imports
keys( this.originals ).forEach( name => { forOwn( this.originals, ( original, name ) => {
this.originals[ name ].addReference( new SyntheticReference( name ) ); original.addReference( new SyntheticReference( name ) );
}); });
} }
@ -202,7 +241,7 @@ export class SyntheticNamespaceDeclaration {
return `${indentString}${name}: ${original.render()}`; return `${indentString}${name}: ${original.render()}`;
}); });
return `var ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`; return `${this.module.bundle.varOrConst} ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`;
} }
render () { render () {
@ -210,11 +249,8 @@ export class SyntheticNamespaceDeclaration {
} }
use () { use () {
keys( this.originals ).forEach( name => { forOwn( this.originals, use );
this.originals[ name ].use(); this.aliases.forEach( use );
});
this.aliases.forEach( alias => alias.use() );
} }
} }
@ -246,7 +282,7 @@ export class ExternalDeclaration {
} }
if ( this.name === 'default' ) { if ( this.name === 'default' ) {
return !es6 && this.module.exportsNames ? return this.module.exportsNamespace || ( !es6 && this.module.exportsNames ) ?
`${this.module.name}__default` : `${this.module.name}__default` :
this.module.name; this.module.name;
} }

5
src/ExternalModule.js

@ -27,9 +27,8 @@ export default class ExternalModule {
} }
traceExport ( name ) { traceExport ( name ) {
if ( name !== 'default' && name !== '*' ) { if ( name !== 'default' && name !== '*' ) this.exportsNames = true;
this.exportsNames = true; if ( name === '*' ) this.exportsNamespace = true;
}
return this.declarations[ name ] || ( return this.declarations[ name ] || (
this.declarations[ name ] = new ExternalDeclaration( this, name ) this.declarations[ name ] = new ExternalDeclaration( this, name )

112
src/Module.js

@ -7,7 +7,11 @@ import { basename, extname } from './utils/path.js';
import getLocation from './utils/getLocation.js'; import getLocation from './utils/getLocation.js';
import makeLegalIdentifier from './utils/makeLegalIdentifier.js'; import makeLegalIdentifier from './utils/makeLegalIdentifier.js';
import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js';
import { SyntheticDefaultDeclaration, SyntheticNamespaceDeclaration } from './Declaration.js'; import {
SyntheticDefaultDeclaration,
SyntheticGlobalDeclaration,
SyntheticNamespaceDeclaration
} from './Declaration.js';
import { isFalsy, isTruthy } from './ast/conditions.js'; import { isFalsy, isTruthy } from './ast/conditions.js';
import { emptyBlockStatement } from './ast/create.js'; import { emptyBlockStatement } from './ast/create.js';
import extractNames from './ast/extractNames.js'; import extractNames from './ast/extractNames.js';
@ -73,7 +77,13 @@ export default class Module {
else { else {
node.specifiers.forEach( specifier => { node.specifiers.forEach( specifier => {
this.reexports[ specifier.exported.name ] = { const name = specifier.exported.name;
if ( this.exports[ name ] || this.reexports[ name ] ) {
throw new Error( `A module cannot have multiple exports with the same name ('${name}')` );
}
this.reexports[ name ] = {
start: specifier.start, start: specifier.start,
source, source,
localName: specifier.local.name, localName: specifier.local.name,
@ -89,6 +99,11 @@ export default class Module {
else if ( node.type === 'ExportDefaultDeclaration' ) { else if ( node.type === 'ExportDefaultDeclaration' ) {
const identifier = ( node.declaration.id && node.declaration.id.name ) || node.declaration.name; const identifier = ( node.declaration.id && node.declaration.id.name ) || node.declaration.name;
if ( this.exports.default ) {
// TODO indicate location
throw new Error( 'A module can only have one default export' );
}
this.exports.default = { this.exports.default = {
localName: 'default', localName: 'default',
identifier identifier
@ -98,37 +113,41 @@ export default class Module {
this.declarations.default = new SyntheticDefaultDeclaration( node, statement, identifier || this.basename() ); this.declarations.default = new SyntheticDefaultDeclaration( node, statement, identifier || this.basename() );
} }
// export { foo, bar, baz }
// export var { foo, bar } = ... // export var { foo, bar } = ...
// export var foo = 42; // export var foo = 42;
// export var a = 1, b = 2, c = 3; // export var a = 1, b = 2, c = 3;
// export function foo () {} // export function foo () {}
else if ( node.type === 'ExportNamedDeclaration' ) { else if ( node.declaration ) {
let declaration = node.declaration;
if ( declaration.type === 'VariableDeclaration' ) {
declaration.declarations.forEach( decl => {
extractNames( decl.id ).forEach( localName => {
this.exports[ localName ] = { localName };
});
});
} else {
// export function foo () {}
const localName = declaration.id.name;
this.exports[ localName ] = { localName };
}
}
// export { foo, bar, baz }
else {
if ( node.specifiers.length ) { if ( node.specifiers.length ) {
// export { foo, bar, baz }
node.specifiers.forEach( specifier => { node.specifiers.forEach( specifier => {
const localName = specifier.local.name; const localName = specifier.local.name;
const exportedName = specifier.exported.name; const exportedName = specifier.exported.name;
if ( this.exports[ exportedName ] || this.reexports[ exportedName ] ) {
throw new Error( `A module cannot have multiple exports with the same name ('${exportedName}')` );
}
this.exports[ exportedName ] = { localName }; this.exports[ exportedName ] = { localName };
}); });
} } else {
this.bundle.onwarn( `Module ${this.id} has an empty export declaration` );
else {
let declaration = node.declaration;
if ( declaration.type === 'VariableDeclaration' ) {
declaration.declarations.forEach( decl => {
extractNames( decl.id ).forEach( localName => {
this.exports[ localName ] = { localName };
});
});
}
else {
// export function foo () {}
const localName = declaration.id.name;
this.exports[ localName ] = { localName };
}
} }
} }
} }
@ -185,7 +204,7 @@ export default class Module {
const declaration = this.declarations[ name ]; const declaration = this.declarations[ name ];
const statement = declaration.statement; const statement = declaration.statement;
if ( statement.node.type !== 'VariableDeclaration' ) return; if ( !statement || statement.node.type !== 'VariableDeclaration' ) return;
const init = statement.node.declarations[0].init; const init = statement.node.declarations[0].init;
if ( !init || init.type === 'FunctionExpression' ) return; if ( !init || init.type === 'FunctionExpression' ) return;
@ -314,6 +333,20 @@ export default class Module {
this.magicString.addSourcemapLocation( node.start ); this.magicString.addSourcemapLocation( node.start );
this.magicString.addSourcemapLocation( node.end ); this.magicString.addSourcemapLocation( node.end );
},
leave: ( node, parent, prop ) => {
// eliminate dead branches early
if ( node.type === 'ConditionalExpression' ) {
if ( isFalsy( node.test ) ) {
this.magicString.remove( node.start, node.alternate.start );
parent[prop] = node.alternate;
} else if ( isTruthy( node.test ) ) {
this.magicString.remove( node.start, node.consequent.start );
this.magicString.remove( node.consequent.end, node.end );
parent[prop] = node.consequent;
}
}
} }
}); });
@ -441,7 +474,7 @@ export default class Module {
if ( declaration.exportName && declaration.isReassigned ) { // `var foo = ...` becomes `exports.foo = ...` if ( declaration.exportName && declaration.isReassigned ) { // `var foo = ...` becomes `exports.foo = ...`
magicString.remove( statement.start, declarator.init ? declarator.start : statement.next ); magicString.remove( statement.start, declarator.init ? declarator.start : statement.next );
return; if ( !declarator.init ) return;
} }
} }
@ -503,7 +536,8 @@ export default class Module {
if ( keys( toDeshadow ).length ) { if ( keys( toDeshadow ).length ) {
statement.references.forEach( reference => { statement.references.forEach( reference => {
if ( !reference.rewritten && reference.name in toDeshadow ) { if ( !reference.rewritten && reference.name in toDeshadow ) {
magicString.overwrite( reference.start, reference.end, toDeshadow[ reference.name ], true ); const replacement = toDeshadow[ reference.name ];
magicString.overwrite( reference.start, reference.end, reference.isShorthandProperty ? `${reference.name}: ${replacement}` : replacement, true );
} }
}); });
} }
@ -558,7 +592,7 @@ export default class Module {
if ( statement.node.declaration.type === 'FunctionExpression' ) { if ( statement.node.declaration.type === 'FunctionExpression' ) {
magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${defaultName}` ); magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${defaultName}` );
} else { } else {
magicString.overwrite( statement.node.start, statement.node.declaration.start, `var ${defaultName} = ` ); magicString.overwrite( statement.node.start, statement.node.declaration.start, `${this.bundle.varOrConst} ${defaultName} = ` );
} }
} }
@ -577,7 +611,23 @@ export default class Module {
return magicString.trim(); return magicString.trim();
} }
run () { /**
* Statically runs the module marking the top-level statements that must be
* included for the module to execute successfully.
*
* @param {boolean} treeshake - if we should tree-shake the module
* @return {boolean} marked - if any new statements were marked for inclusion
*/
run ( treeshake ) {
if ( !treeshake ) {
this.statements.forEach( statement => {
if ( statement.isImportDeclaration || ( statement.isExportDeclaration && statement.node.isSynthetic ) ) return;
statement.mark();
});
return false;
}
let marked = false; let marked = false;
this.statements.forEach( statement => { this.statements.forEach( statement => {
@ -624,7 +674,13 @@ export default class Module {
const exportDeclaration = this.exports[ name ]; const exportDeclaration = this.exports[ name ];
if ( exportDeclaration ) { if ( exportDeclaration ) {
return this.trace( exportDeclaration.localName ); const name = exportDeclaration.localName;
const declaration = this.trace( name );
if ( declaration ) return declaration;
this.bundle.assumedGlobals[ name ] = true;
return ( this.declarations[ name ] = new SyntheticGlobalDeclaration( name ) );
} }
for ( let i = 0; i < this.exportAllModules.length; i += 1 ) { for ( let i = 0; i < this.exportAllModules.length; i += 1 ) {

2
src/Reference.js

@ -10,7 +10,7 @@ export class Reference {
let root = node; let root = node;
while ( root.type === 'MemberExpression' ) { while ( root.type === 'MemberExpression' ) {
this.parts.unshift( root.property.name ); this.parts.unshift( root.property );
root = root.object; root = root.object;
} }

63
src/Statement.js

@ -44,10 +44,11 @@ export default class Statement {
let readDepth = 0; let readDepth = 0;
walk( this.node, { walk( this.node, {
enter ( node, parent ) { enter ( node, parent, prop ) {
// warn about eval // warn about eval
if ( node.type === 'CallExpression' && node.callee.name === 'eval' && !scope.contains( 'eval' ) ) { if ( node.type === 'CallExpression' && node.callee.name === 'eval' && !scope.contains( 'eval' ) ) {
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` ); // TODO show location
module.bundle.onwarn( `Use of \`eval\` (in ${module.id}) is strongly discouraged, as it poses security risks and may cause issues with minification. See https://github.com/rollup/rollup/wiki/Troubleshooting#avoiding-eval for more details` );
} }
// skip re-export declarations // skip re-export declarations
@ -61,42 +62,36 @@ export default class Statement {
if ( node._scope ) scope = node._scope; if ( node._scope ) scope = node._scope;
if ( /Function/.test( node.type ) ) readDepth += 1; if ( /Function/.test( node.type ) ) readDepth += 1;
// special case – shorthand properties. because node.key === node.value,
// we can't differentiate once we've descended into the node
if ( node.type === 'Property' && node.shorthand && parent.type !== 'ObjectPattern' ) {
const reference = new Reference( node.key, scope );
reference.isShorthandProperty = true; // TODO feels a bit kludgy
references.push( reference );
return this.skip();
}
let isReassignment; let isReassignment;
if ( parent && isModifierNode( parent ) ) { if ( parent && isModifierNode( parent ) ) {
let subject = parent[ modifierNodes[ parent.type ] ]; let subject = parent[ modifierNodes[ parent.type ] ];
let depth = 0;
while ( subject.type === 'MemberExpression' ) { if ( node === subject ) {
subject = subject.object; let depth = 0;
depth += 1;
} while ( subject.type === 'MemberExpression' ) {
subject = subject.object;
depth += 1;
}
const importDeclaration = module.imports[ subject.name ]; const importDeclaration = module.imports[ subject.name ];
if ( !scope.contains( subject.name ) && importDeclaration ) { if ( !scope.contains( subject.name ) && importDeclaration ) {
const minDepth = importDeclaration.name === '*' ? const minDepth = importDeclaration.name === '*' ?
2 : // cannot do e.g. `namespace.foo = bar` 2 : // cannot do e.g. `namespace.foo = bar`
1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine 1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine
if ( depth < minDepth ) { if ( depth < minDepth ) {
const err = new Error( `Illegal reassignment to import '${subject.name}'` ); const err = new Error( `Illegal reassignment to import '${subject.name}'` );
err.file = module.id; err.file = module.id;
err.loc = getLocation( module.magicString.toString(), subject.start ); err.loc = getLocation( module.magicString.original, subject.start );
throw err; throw err;
}
} }
}
isReassignment = !depth; isReassignment = !depth;
}
} }
if ( isReference( node, parent ) ) { if ( isReference( node, parent ) ) {
@ -106,9 +101,19 @@ export default class Statement {
scope.parent : scope.parent :
scope; scope;
const isShorthandProperty = parent.type === 'Property' && parent.shorthand;
// Since `node.key` can equal `node.value` for shorthand properties
// we must use the `prop` argument provided by `estree-walker` to determine
// if we're looking at the key or the value.
// If they are equal, we'll return to not create duplicate references.
if ( isShorthandProperty && parent.value === parent.key && prop === 'value' ) {
return;
}
const reference = new Reference( node, referenceScope, statement ); const reference = new Reference( node, referenceScope, statement );
reference.isReassignment = isReassignment; reference.isReassignment = isReassignment;
reference.isShorthandProperty = isShorthandProperty;
references.push( reference ); references.push( reference );
this.skip(); // don't descend from `foo.bar.baz` into `foo.bar` this.skip(); // don't descend from `foo.bar.baz` into `foo.bar`

4
src/ast/attachScopes.js

@ -29,7 +29,7 @@ export default function attachScopes ( statement ) {
let newScope; let newScope;
// create new function scope // create new function scope
if ( /Function/.test( node.type ) ) { if ( /(Function|Class)/.test( node.type ) ) {
newScope = new Scope({ newScope = new Scope({
parent: scope, parent: scope,
block: false, block: false,
@ -38,7 +38,7 @@ export default function attachScopes ( statement ) {
// named function expressions - the name is considered // named function expressions - the name is considered
// part of the function's scope // part of the function's scope
if ( node.type === 'FunctionExpression' && node.id ) { if ( /(Function|Class)Expression/.test( node.type ) && node.id ) {
newScope.addDeclaration( node, false, false ); newScope.addDeclaration( node, false, false );
} }
} }

4
src/ast/isReference.js

@ -10,7 +10,9 @@ export default function isReference ( node, parent ) {
if ( !parent ) return true; if ( !parent ) return true;
// TODO is this right? // TODO is this right?
if ( parent.type === 'MemberExpression' ) return parent.computed || node === parent.object; if ( parent.type === 'MemberExpression' || parent.type === 'MethodDefinition' ) {
return parent.computed || node === parent.object;
}
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }` // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
if ( parent.type === 'Property' ) return parent.computed || node === parent.value; if ( parent.type === 'Property' ) return parent.computed || node === parent.value;

29
src/finalisers/cjs.js

@ -3,28 +3,37 @@ import getExportBlock from './shared/getExportBlock.js';
export default function cjs ( bundle, magicString, { exportMode }, options ) { export default function cjs ( bundle, magicString, { exportMode }, options ) {
let intro = options.useStrict === false ? `` : `'use strict';\n\n`; let intro = options.useStrict === false ? `` : `'use strict';\n\n`;
const hasDefaultImport = bundle.externalModules.some( mod => mod.declarations.default); let needsInterop = false;
if (hasDefaultImport) { const varOrConst = bundle.varOrConst;
intro += `function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; }\n\n`;
}
// TODO handle empty imports, once they're supported // TODO handle empty imports, once they're supported
const importBlock = bundle.externalModules const importBlock = bundle.externalModules
.map( module => { .map( module => {
if ( module.declarations.default ) { if ( module.declarations.default ) {
if (module.exportsNames) { if ( module.exportsNamespace ) {
return `var ${module.name} = require('${module.id}');` + return `${varOrConst} ${module.name} = require('${module.id}');` +
`\nvar ${module.name}__default = _interopDefault(${module.name});`; `\n${varOrConst} ${module.name}__default = ${module.name}['default'];`;
} else { }
return `var ${module.name} = _interopDefault(require('${module.id}'));`;
needsInterop = true;
if ( module.exportsNames ) {
return `${varOrConst} ${module.name} = require('${module.id}');` +
`\n${varOrConst} ${module.name}__default = _interopDefault(${module.name});`;
} }
return `${varOrConst} ${module.name} = _interopDefault(require('${module.id}'));`;
} else { } else {
return `var ${module.name} = require('${module.id}');`; return `${varOrConst} ${module.name} = require('${module.id}');`;
} }
}) })
.join( '\n' ); .join( '\n' );
if ( needsInterop ) {
intro += `function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }\n\n`;
}
if ( importBlock ) { if ( importBlock ) {
intro += importBlock + '\n\n'; intro += importBlock + '\n\n';
} }

19
src/finalisers/es6.js

@ -10,10 +10,20 @@ export default function es6 ( bundle, magicString ) {
const specifiers = []; const specifiers = [];
const specifiersList = [specifiers]; const specifiersList = [specifiers];
const importedNames = keys( module.declarations ) const importedNames = keys( module.declarations )
.filter( name => name !== '*' && name !== 'default' ); .filter( name => name !== '*' && name !== 'default' )
.map( name => {
const declaration = module.declarations[ name ];
if ( declaration.name === declaration.safeName ) return declaration.name;
return `${declaration.name} as ${declaration.safeName}`;
});
if ( module.declarations.default ) { if ( module.declarations.default ) {
specifiers.push( module.name ); if ( module.exportsNamespace ) {
specifiersList.push([ `${module.name}__default` ]);
} else {
specifiers.push( module.name );
}
} }
const namespaceSpecifier = module.declarations['*'] ? `* as ${module.name}` : null; const namespaceSpecifier = module.declarations['*'] ? `* as ${module.name}` : null;
@ -47,10 +57,11 @@ export default function es6 ( bundle, magicString ) {
const specifiers = module.getExports().filter( notDefault ).map( name => { const specifiers = module.getExports().filter( notDefault ).map( name => {
const declaration = module.traceExport( name ); const declaration = module.traceExport( name );
const rendered = declaration.render( true );
return declaration.name === name ? return rendered === name ?
name : name :
`${declaration.name} as ${name}`; `${rendered} as ${name}`;
}); });
let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : ''; let exportBlock = specifiers.length ? `export { ${specifiers.join(', ')} };` : '';

4
src/finalisers/iife.js

@ -31,7 +31,7 @@ export default function iife ( bundle, magicString, { exportMode, indentString }
} }
if ( exportMode === 'named' ) { if ( exportMode === 'named' ) {
dependencies.unshift( `(this.${name} = {})` ); dependencies.unshift( `(this.${name} = this.${name} || {})` );
args.unshift( 'exports' ); args.unshift( 'exports' );
} }
@ -41,7 +41,7 @@ export default function iife ( bundle, magicString, { exportMode, indentString }
let outro = `\n\n}(${dependencies}));`; let outro = `\n\n}(${dependencies}));`;
if ( exportMode === 'default' ) { if ( exportMode === 'default' ) {
intro = ( isNamespaced ? `this.` : `var ` ) + `${name} = ${intro}`; intro = ( isNamespaced ? `this.` : `${bundle.varOrConst} ` ) + `${name} = ${intro}`;
} }
if ( isNamespaced ) { if ( isNamespaced ) {

16
src/finalisers/shared/getInteropBlock.js

@ -1,11 +1,17 @@
export default function getInteropBlock ( bundle ) { export default function getInteropBlock ( bundle ) {
return bundle.externalModules return bundle.externalModules
.map( module => { .map( module => {
return module.declarations.default ? if ( !module.declarations.default ) return null;
( module.exportsNames ?
`var ${module.name}__default = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};` : if ( module.exportsNamespace ) {
`${module.name} = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};` ) : return `${bundle.varOrConst} ${module.name}__default = ${module.name}['default'];`;
null; }
if ( module.exportsNames ) {
return `${bundle.varOrConst} ${module.name}__default = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};`;
}
return `${module.name} = 'default' in ${module.name} ? ${module.name}['default'] : ${module.name};`;
}) })
.filter( Boolean ) .filter( Boolean )
.join( '\n' ); .join( '\n' );

12
src/finalisers/umd.js

@ -31,7 +31,7 @@ export default function umd ( bundle, magicString, { exportMode, indentString },
if ( exportMode === 'named' ) { if ( exportMode === 'named' ) {
amdDeps.unshift( `'exports'` ); amdDeps.unshift( `'exports'` );
cjsDeps.unshift( `exports` ); cjsDeps.unshift( `exports` );
globalDeps.unshift( `(${setupNamespace(options.moduleName)} = {})` ); globalDeps.unshift( `(${setupNamespace(options.moduleName)} = global.${options.moduleName} || {})` );
args.unshift( 'exports' ); args.unshift( 'exports' );
} }
@ -45,11 +45,19 @@ export default function umd ( bundle, magicString, { exportMode, indentString },
const useStrict = options.useStrict !== false ? ` 'use strict';` : ``; const useStrict = options.useStrict !== false ? ` 'use strict';` : ``;
const globalExport = options.noConflict === true ?
`(function() {
var current = global.${options.moduleName};
var exports = factory(${globalDeps});
global.${options.moduleName} = exports;
exports.noConflict = function() { global.${options.moduleName} = current; return exports; };
})()` : `(${defaultExport}factory(${globalDeps}))`;
const intro = const intro =
`(function (global, factory) { `(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? ${cjsExport}factory(${cjsDeps.join( ', ' )}) : typeof exports === 'object' && typeof module !== 'undefined' ? ${cjsExport}factory(${cjsDeps.join( ', ' )}) :
typeof define === 'function' && define.amd ? define(${amdParams}factory) : typeof define === 'function' && define.amd ? define(${amdParams}factory) :
(${defaultExport}factory(${globalDeps})); ${globalExport};
}(this, function (${args}) {${useStrict} }(this, function (${args}) {${useStrict}
`.replace( /^\t\t/gm, '' ).replace( /^\t/gm, magicString.getIndentString() ); `.replace( /^\t\t/gm, '' ).replace( /^\t/gm, magicString.getIndentString() );

7
src/rollup.js

@ -12,6 +12,7 @@ const ALLOWED_KEYS = [
'banner', 'banner',
'dest', 'dest',
'entry', 'entry',
'exports',
'external', 'external',
'footer', 'footer',
'format', 'format',
@ -20,10 +21,14 @@ const ALLOWED_KEYS = [
'intro', 'intro',
'moduleId', 'moduleId',
'moduleName', 'moduleName',
'noConflict',
'onwarn', 'onwarn',
'outro', 'outro',
'plugins', 'plugins',
'sourceMap' 'preferConst',
'sourceMap',
'treeshake',
'useStrict'
]; ];
export function rollup ( options ) { export function rollup ( options ) {

33
src/utils/collapseSourcemaps.js

@ -1,25 +1,25 @@
import { encode, decode } from 'sourcemap-codec'; import { encode, decode } from 'sourcemap-codec';
function Source ( index ) { class Source {
this.isOriginal = true; constructor ( index ) {
this.index = index; this.isOriginal = true;
} this.index = index;
}
Source.prototype = {
traceSegment ( line, column, name ) { traceSegment ( line, column, name ) {
return { line, column, name, index: this.index }; return { line, column, name, index: this.index };
} }
}; }
function Link ( map, sources ) { class Link {
if ( !map ) throw new Error( 'Cannot generate a sourcemap if non-sourcemap-generating transformers are used' ); constructor ( map, sources ) {
if ( !map ) throw new Error( 'Cannot generate a sourcemap if non-sourcemap-generating transformers are used' );
this.sources = sources; this.sources = sources;
this.names = map.names; this.names = map.names;
this.mappings = decode( map.mappings ); this.mappings = decode( map.mappings );
} }
Link.prototype = { // TODO bring into line with others post-https://github.com/rollup/rollup/pull/386
traceMappings () { traceMappings () {
let names = []; let names = [];
@ -57,7 +57,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
}); });
return { names, mappings }; return { names, mappings };
}, }
traceSegment ( line, column, name ) { traceSegment ( line, column, name ) {
const segments = this.mappings[ line ]; const segments = this.mappings[ line ];
@ -71,8 +71,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
if ( segment[0] === column ) { if ( segment[0] === column ) {
const source = this.sources[ segment[1] ]; const source = this.sources[ segment[1] ];
if ( !source ) return null;
if ( !source ) throw new Error( 'Bad sourcemap' );
return source.traceSegment( segment[2], segment[3], this.names[ segment[4] ] || name ); return source.traceSegment( segment[2], segment[3], this.names[ segment[4] ] || name );
} }
@ -80,7 +79,7 @@ Link.prototype = { // TODO bring into line with others post-https://github.com/r
return null; return null;
} }
}; }
export default function collapseSourcemaps ( map, modules, bundleSourcemapChain ) { export default function collapseSourcemaps ( map, modules, bundleSourcemapChain ) {
const sources = modules.map( ( module, i ) => { const sources = modules.map( ( module, i ) => {

5
src/utils/getExportMode.js

@ -4,7 +4,7 @@ function badExports ( option, keys ) {
throw new Error( `'${option}' was specified for options.exports, but entry module has following exports: ${keys.join(', ')}` ); throw new Error( `'${option}' was specified for options.exports, but entry module has following exports: ${keys.join(', ')}` );
} }
export default function getExportMode ( bundle, exportMode ) { export default function getExportMode ( bundle, exportMode, moduleName ) {
const exportKeys = keys( bundle.entryModule.exports ) const exportKeys = keys( bundle.entryModule.exports )
.concat( keys( bundle.entryModule.reexports ) ) .concat( keys( bundle.entryModule.reexports ) )
.concat( bundle.entryModule.exportAllSources ); // not keys, but makes our job easier this way .concat( bundle.entryModule.exportAllSources ); // not keys, but makes our job easier this way
@ -23,6 +23,9 @@ export default function getExportMode ( bundle, exportMode ) {
} else if ( exportKeys.length === 1 && exportKeys[0] === 'default' ) { } else if ( exportKeys.length === 1 && exportKeys[0] === 'default' ) {
exportMode = 'default'; exportMode = 'default';
} else { } else {
if ( bundle.entryModule.exports.default ) {
bundle.onwarn( `Using named and default exports together. Consumers of your bundle will have to use ${moduleName || 'bundle'}['default'] to access the default export, which may not be what you want. Use \`exports: 'named'\` to disable this warning. See https://github.com/rollup/rollup/wiki/JavaScript-API#exports for more information` );
}
exportMode = 'named'; exportMode = 'named';
} }
} }

6
src/utils/object.js

@ -1,5 +1,9 @@
export const keys = Object.keys; export const { keys } = Object;
export function blank () { export function blank () {
return Object.create( null ); return Object.create( null );
} }
export function forOwn ( object, func ) {
Object.keys( object ).forEach( key => func( object[ key ], key ) );
}

16
src/utils/promise.js

@ -0,0 +1,16 @@
import Promise from 'es6-promise/lib/es6-promise/promise.js';
export function mapSequence ( array, fn ) {
let results = [];
let promise = Promise.resolve();
function next ( member, i ) {
return fn( member ).then( value => results[i] = value );
}
for ( let i = 0; i < array.length; i += 1 ) {
promise = promise.then( () => next( array[i], i ) );
}
return promise.then( () => results );
}

6
src/utils/run.js

@ -75,6 +75,10 @@ export default function run ( node, scope, statement, strongDependencies, force
} }
} }
else if ( node.type === 'DebuggerStatement' ) {
hasSideEffect = true;
}
else if ( node.type === 'ThrowStatement' ) { else if ( node.type === 'ThrowStatement' ) {
// we only care about errors thrown at the top level, otherwise // we only care about errors thrown at the top level, otherwise
// any function with error checking gets included if called // any function with error checking gets included if called
@ -95,6 +99,8 @@ export default function run ( node, scope, statement, strongDependencies, force
if ( declaration ) { if ( declaration ) {
if ( declaration.isParam ) hasSideEffect = true; if ( declaration.isParam ) hasSideEffect = true;
} else if ( !scope.isTopLevel ) {
hasSideEffect = true;
} else { } else {
declaration = statement.module.trace( subject.name ); declaration = statement.module.trace( subject.name );

7
src/utils/transform.js

@ -39,5 +39,10 @@ export default function transform ( source, id, transformers ) {
}, Promise.resolve( source.code ) ) }, Promise.resolve( source.code ) )
.then( code => ({ code, originalCode, ast, sourceMapChain }) ); .then( code => ({ code, originalCode, ast, sourceMapChain }) )
.catch( err => {
err.id = id;
err.message = `Error loading ${id}: ${err.message}`;
throw err;
});
} }

0
.babelrc → test/.babelrc

9
test/cli/config-missing-export/_config.js

@ -0,0 +1,9 @@
var assert = require( 'assert' );
module.exports = {
description: 'throws error if config does not export an object',
command: 'rollup -c',
error: function ( err ) {
assert.ok( /Config file must export an options object/.test( err.message ) );
}
};

0
test/cli/config-missing-export/rollup.config.js

4
test/cli/no-treeshake/_config.js

@ -0,0 +1,4 @@
module.exports = {
description: 'generates IIFE export with all code',
command: 'rollup main.js --format iife --name shakeless --no-treeshake'
};

10
test/cli/no-treeshake/_expected.js

@ -0,0 +1,10 @@
var shakeless = (function () {
'use strict';
const version = '1.2.0';
var main = ( x, y ) => x + y;
return main;
}());

3
test/cli/no-treeshake/main.js

@ -0,0 +1,3 @@
const version = '1.2.0';
export default ( x, y ) => x + y;

6
test/form/assignment-to-exports-class-declaration/_config.js

@ -0,0 +1,6 @@
module.exports = {
description: 'does not rewrite class declaration IDs',
options: {
moduleName: 'myModule'
}
};

6
test/form/assignment-to-exports-class-declaration/_expected/amd.js

@ -0,0 +1,6 @@
define(['exports'], function (exports) { 'use strict';
exports.Foo = class Foo {}
exports.Foo = lol( exports.Foo );
});

4
test/form/assignment-to-exports-class-declaration/_expected/cjs.js

@ -0,0 +1,4 @@
'use strict';
exports.Foo = class Foo {}
exports.Foo = lol( exports.Foo );

4
test/form/assignment-to-exports-class-declaration/_expected/es6.js

@ -0,0 +1,4 @@
Foo = class Foo {}
Foo = lol( Foo );
export { Foo };

7
test/form/assignment-to-exports-class-declaration/_expected/iife.js

@ -0,0 +1,7 @@
(function (exports) {
'use strict';
exports.Foo = class Foo {}
exports.Foo = lol( exports.Foo );
}((this.myModule = this.myModule || {})));

10
test/form/assignment-to-exports-class-declaration/_expected/umd.js

@ -0,0 +1,10 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.myModule = global.myModule || {})));
}(this, function (exports) { 'use strict';
exports.Foo = class Foo {}
exports.Foo = lol( exports.Foo );
}));

2
test/form/assignment-to-exports-class-declaration/main.js

@ -0,0 +1,2 @@
export let Foo = class Foo {}
Foo = lol( Foo );

12
test/form/computed-properties/_expected/amd.js

@ -1,9 +1,19 @@
define(['exports'], function (exports) { 'use strict'; define(['exports'], function (exports) { 'use strict';
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
var x = {[foo]: 'bar'}; var x = { [foo]: 'bar' };
class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}
exports.x = x; exports.x = x;
exports.X = X;
}); });

12
test/form/computed-properties/_expected/cjs.js

@ -1,7 +1,17 @@
'use strict'; 'use strict';
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
var x = {[foo]: 'bar'}; var x = { [foo]: 'bar' };
class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}
exports.x = x; exports.x = x;
exports.X = X;

13
test/form/computed-properties/_expected/es6.js

@ -1,5 +1,14 @@
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
var x = {[foo]: 'bar'}; var x = { [foo]: 'bar' };
export { x }; class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}
export { x, X };

14
test/form/computed-properties/_expected/iife.js

@ -2,9 +2,19 @@
'use strict'; 'use strict';
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
var x = {[foo]: 'bar'}; var x = { [foo]: 'bar' };
class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}
exports.x = x; exports.x = x;
exports.X = X;
}((this.computedProperties = {}))); }((this.computedProperties = this.computedProperties || {})));

14
test/form/computed-properties/_expected/umd.js

@ -1,13 +1,23 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.computedProperties = {}))); (factory((global.computedProperties = global.computedProperties || {})));
}(this, function (exports) { 'use strict'; }(this, function (exports) { 'use strict';
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
var x = {[foo]: 'bar'}; var x = { [foo]: 'bar' };
class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}
exports.x = x; exports.x = x;
exports.X = X;
})); }));

11
test/form/computed-properties/main.js

@ -1,3 +1,12 @@
var foo = 'foo'; var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
var bam = 'bam';
export var x = {[foo]: 'bar'}; export var x = { [foo]: 'bar' };
export class X {
[bar] () {}
get [baz] () {}
set [bam] ( value ) {}
}

3
test/form/conflicting-imports/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'ensures bundle imports are deconflicted (#659)'
};

7
test/form/conflicting-imports/_expected/amd.js

@ -0,0 +1,7 @@
define(['foo', 'bar'], function (foo, bar) { 'use strict';
console.log( bar.a );
console.log( foo.a );
});

8
test/form/conflicting-imports/_expected/cjs.js

@ -0,0 +1,8 @@
'use strict';
var foo = require('foo');
var bar = require('bar');
console.log( bar.a );
console.log( foo.a );

6
test/form/conflicting-imports/_expected/es6.js

@ -0,0 +1,6 @@
import { a } from 'foo';
import { a as a$1 } from 'bar';
console.log( a$1 );
console.log( a );

8
test/form/conflicting-imports/_expected/iife.js

@ -0,0 +1,8 @@
(function (foo,bar) {
'use strict';
console.log( bar.a );
console.log( foo.a );
}(foo,bar));

11
test/form/conflicting-imports/_expected/umd.js

@ -0,0 +1,11 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('foo'), require('bar')) :
typeof define === 'function' && define.amd ? define(['foo', 'bar'], factory) :
(factory(global.foo,global.bar));
}(this, function (foo,bar) { 'use strict';
console.log( bar.a );
console.log( foo.a );
}));

4
test/form/conflicting-imports/main.js

@ -0,0 +1,4 @@
import { a } from 'foo';
import './other.js';
console.log( a );

3
test/form/conflicting-imports/other.js

@ -0,0 +1,3 @@
import { a } from 'bar';
console.log( a );

2
test/form/dedupes-external-imports/_expected/iife.js

@ -30,4 +30,4 @@
exports.bar = bar; exports.bar = bar;
exports.baz = baz; exports.baz = baz;
}((this.myBundle = {}),external)); }((this.myBundle = this.myBundle || {}),external));

2
test/form/dedupes-external-imports/_expected/umd.js

@ -1,7 +1,7 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) :
typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) : typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) :
(factory((global.myBundle = {}),global.external)); (factory((global.myBundle = global.myBundle || {}),global.external));
}(this, function (exports,external) { 'use strict'; }(this, function (exports,external) { 'use strict';
class Foo extends external.Component { class Foo extends external.Component {

3
test/form/erroneous-nested-member-expression/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'erroneous nested member expression does not mess up naming'
};

13
test/form/erroneous-nested-member-expression/_expected/amd.js

@ -0,0 +1,13 @@
define(function () { 'use strict';
function yar() {
return {
har() {
console.log('har?');
}
};
};
yar.har();
});

11
test/form/erroneous-nested-member-expression/_expected/cjs.js

@ -0,0 +1,11 @@
'use strict';
function yar() {
return {
har() {
console.log('har?');
}
};
};
yar.har();

9
test/form/erroneous-nested-member-expression/_expected/es6.js

@ -0,0 +1,9 @@
function yar() {
return {
har() {
console.log('har?');
}
};
};
yar.har();

14
test/form/erroneous-nested-member-expression/_expected/iife.js

@ -0,0 +1,14 @@
(function () {
'use strict';
function yar() {
return {
har() {
console.log('har?');
}
};
};
yar.har();
}());

17
test/form/erroneous-nested-member-expression/_expected/umd.js

@ -0,0 +1,17 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
(factory());
}(this, function () { 'use strict';
function yar() {
return {
har() {
console.log('har?');
}
};
};
yar.har();
}));

7
test/form/erroneous-nested-member-expression/foo.js

@ -0,0 +1,7 @@
export function yar() {
return {
har() {
console.log('har?');
}
};
};

2
test/form/erroneous-nested-member-expression/main.js

@ -0,0 +1,2 @@
import * as foo from './foo.js';
foo.yar.har();

2
test/form/export-all-from-internal/_expected/iife.js

@ -7,4 +7,4 @@
exports.a = a; exports.a = a;
exports.b = b; exports.b = b;
}((this.exposedInternals = {}))); }((this.exposedInternals = this.exposedInternals || {})));

2
test/form/export-all-from-internal/_expected/umd.js

@ -1,7 +1,7 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.exposedInternals = {}))); (factory((global.exposedInternals = global.exposedInternals || {})));
}(this, function (exports) { 'use strict'; }(this, function (exports) { 'use strict';
const a = 1; const a = 1;

6
test/form/export-default-import/_config.js

@ -0,0 +1,6 @@
module.exports = {
description: 'correctly exports a default import, even in ES mode (#513)',
options: {
moduleName: 'myBundle'
}
};

9
test/form/export-default-import/_expected/amd.js

@ -0,0 +1,9 @@
define(['exports', 'x'], function (exports, x) { 'use strict';
x = 'default' in x ? x['default'] : x;
exports.x = x;
});

9
test/form/export-default-import/_expected/cjs.js

@ -0,0 +1,9 @@
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var x = _interopDefault(require('x'));
exports.x = x;

5
test/form/export-default-import/_expected/es6.js

@ -0,0 +1,5 @@
import x from 'x';
export { x };

10
test/form/export-default-import/_expected/iife.js

@ -0,0 +1,10 @@
(function (exports,x) {
'use strict';
x = 'default' in x ? x['default'] : x;
exports.x = x;
}((this.myBundle = this.myBundle || {}),x));

13
test/form/export-default-import/_expected/umd.js

@ -0,0 +1,13 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('x')) :
typeof define === 'function' && define.amd ? define(['exports', 'x'], factory) :
(factory((global.myBundle = global.myBundle || {}),global.x));
}(this, function (exports,x) { 'use strict';
x = 'default' in x ? x['default'] : x;
exports.x = x;
}));

3
test/form/export-default-import/main.js

@ -0,0 +1,3 @@
import x from 'x';
export { x };

2
test/form/exports-at-end-if-possible/_expected/iife.js

@ -9,4 +9,4 @@
exports.FOO = FOO; exports.FOO = FOO;
}((this.myBundle = {}))); }((this.myBundle = this.myBundle || {})));

2
test/form/exports-at-end-if-possible/_expected/umd.js

@ -1,7 +1,7 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.myBundle = {}))); (factory((global.myBundle = global.myBundle || {})));
}(this, function (exports) { 'use strict'; }(this, function (exports) { 'use strict';
var FOO = 'foo'; var FOO = 'foo';

2
test/form/external-imports-custom-names/_expected/cjs.js

@ -1,6 +1,6 @@
'use strict'; 'use strict';
function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; } function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var $ = _interopDefault(require('jquery')); var $ = _interopDefault(require('jquery'));

2
test/form/external-imports/_expected/cjs.js

@ -1,6 +1,6 @@
'use strict'; 'use strict';
function _interopDefault (ex) { return 'default' in ex ? ex['default'] : ex; } function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var factory = _interopDefault(require('factory')); var factory = _interopDefault(require('factory'));
var baz = require('baz'); var baz = require('baz');

3
test/form/import-external-namespace-and-default/_config.js

@ -0,0 +1,3 @@
module.exports = {
description: 'disinguishes between external default and namespace (#637)'
};

9
test/form/import-external-namespace-and-default/_expected/amd.js

@ -0,0 +1,9 @@
define(['foo'], function (foo) { 'use strict';
var foo__default = foo['default'];
console.log( foo.bar );
console.log( foo__default );
});

8
test/form/import-external-namespace-and-default/_expected/cjs.js

@ -0,0 +1,8 @@
'use strict';
var foo = require('foo');
var foo__default = foo['default'];
console.log( foo.bar );
console.log( foo__default );

6
test/form/import-external-namespace-and-default/_expected/es6.js

@ -0,0 +1,6 @@
import * as foo from 'foo';
import foo__default from 'foo';
console.log( foo.bar );
console.log( foo__default );

10
test/form/import-external-namespace-and-default/_expected/iife.js

@ -0,0 +1,10 @@
(function (foo) {
'use strict';
var foo__default = foo['default'];
console.log( foo.bar );
console.log( foo__default );
}(foo));

13
test/form/import-external-namespace-and-default/_expected/umd.js

@ -0,0 +1,13 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('foo')) :
typeof define === 'function' && define.amd ? define(['foo'], factory) :
(factory(global.foo));
}(this, function (foo) { 'use strict';
var foo__default = foo['default'];
console.log( foo.bar );
console.log( foo__default );
}));

4
test/form/import-external-namespace-and-default/main.js

@ -0,0 +1,4 @@
import foo from 'foo';
import './other.js';
console.log( foo );

3
test/form/import-external-namespace-and-default/other.js

@ -0,0 +1,3 @@
import * as foo from 'foo';
console.log( foo.bar );

6
test/form/import-named-exported-global-with-alias/_config.js

@ -0,0 +1,6 @@
module.exports = {
description: 'allow globals to be exported and imported',
options: {
moduleName: 'doc'
}
};

5
test/form/import-named-exported-global-with-alias/_expected/amd.js

@ -0,0 +1,5 @@
define(function () { 'use strict';
});

2
test/form/import-named-exported-global-with-alias/_expected/cjs.js

@ -0,0 +1,2 @@
'use strict';

0
test/form/import-named-exported-global-with-alias/_expected/es6.js

6
test/form/import-named-exported-global-with-alias/_expected/iife.js

@ -0,0 +1,6 @@
(function () {
'use strict';
}());

9
test/form/import-named-exported-global-with-alias/_expected/umd.js

@ -0,0 +1,9 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
typeof define === 'function' && define.amd ? define(factory) :
(factory());
}(this, function () { 'use strict';
}));

1
test/form/import-named-exported-global-with-alias/browser.js

@ -0,0 +1 @@
export { document };

2
test/form/import-named-exported-global-with-alias/main.js

@ -0,0 +1,2 @@
import { document } from './browser.js';
var d = document;

2
test/form/multiple-exports/_expected/iife.js

@ -7,4 +7,4 @@
exports.foo = foo; exports.foo = foo;
exports.bar = bar; exports.bar = bar;
}((this.myBundle = {}))); }((this.myBundle = this.myBundle || {})));

2
test/form/multiple-exports/_expected/umd.js

@ -1,7 +1,7 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.myBundle = {}))); (factory((global.myBundle = global.myBundle || {})));
}(this, function (exports) { 'use strict'; }(this, function (exports) { 'use strict';
var foo = 1; var foo = 1;

2
test/form/namespaced-named-exports/_expected/iife.js

@ -7,4 +7,4 @@ this.foo.bar = this.foo.bar || {};
exports.answer = answer; exports.answer = answer;
}((this.foo.bar.baz = {}))); }((this.foo.bar.baz = this.foo.bar.baz || {})));

2
test/form/namespaced-named-exports/_expected/umd.js

@ -1,7 +1,7 @@
(function (global, factory) { (function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) : typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.foo = global.foo || {}, global.foo.bar = global.foo.bar || {}, global.foo.bar.baz = {}))); (factory((global.foo = global.foo || {}, global.foo.bar = global.foo.bar || {}, global.foo.bar.baz = global.foo.bar.baz || {})));
}(this, function (exports) { 'use strict'; }(this, function (exports) { 'use strict';
var answer = 42; var answer = 42;

11
test/form/no-treeshake/_config.js

@ -0,0 +1,11 @@
module.exports = {
description: 'all code should be included if tree-shaking is disabled',
options: {
external: [ 'external' ],
globals: {
external: 'external'
},
moduleName: /* not shaken, but */ 'stirred',
treeshake: false
}
};

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save