diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000000..6df029f6ed8 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +test/* +!test/test.js diff --git a/.eslintrc b/.eslintrc index 0f98dff25d0..d9150f9de08 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,17 +7,38 @@ "space-before-blocks": [ 2, "always" ], "space-before-function-paren": [ 2, "always" ], "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ], - "no-cond-assign": [ 0 ] + "no-cond-assign": 0, + "no-unused-vars": 2, + "object-shorthand": [ 2, "always" ], + "no-const-assign": 2, + "no-class-assign": 2, + "no-this-before-super": 2, + "no-var": 2, + "no-unreachable": 2, + "valid-typeof": 2, + "quote-props": [ 2, "as-needed" ], + "one-var": [ 2, "never" ], + "prefer-arrow-callback": 2, + "prefer-const": [ 2, { "destructuring": "all" } ], + "arrow-spacing": 2 }, "env": { "es6": true, "browser": true, - "mocha": true, "node": true }, - "extends": "eslint:recommended", + "extends": [ + "eslint:recommended", + "plugin:import/errors", + "plugin:import/warnings" + ], "parserOptions": { "ecmaVersion": 6, "sourceType": "module" + }, + "settings": { + "import/ignore": [ 0, [ + "\\.path.js$" + ] ] } } diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000000..4e2b4999652 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,18 @@ + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..d2882acf4ac --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + diff --git a/.gitignore b/.gitignore index 55804cbe8c8..f5abf8d2c85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ .DS_Store -node_modules -!test/node_modules +/node_modules .gobble* dist _actual coverage .commithash .idea +bin/rollup diff --git a/.travis.yml b/.travis.yml index 9a040ed26e2..83d1bca66ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ language: node_js node_js: - "0.12" - "4" + - "6" env: global: - BUILD_TIMEOUT=10000 diff --git a/CHANGELOG.md b/CHANGELOG.md index 03d0f1afa6a..ef52701531b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,261 @@ # rollup changelog +## 0.37.0 + +* [BREAKING] Default exports are not included in reified namespaces ([#1028](https://github.com/rollup/rollup/issues/1028)) +* Parentheses do not defeat tree-shaking ([#1101](https://github.com/rollup/rollup/issues/1101), [#1128](https://github.com/rollup/rollup/issues/1128)) +* More `legacy` fixes: do not create getters ([#1069](https://github.com/rollup/rollup/pull/1069)), do not include `__esModule` ([#1068](https://github.com/rollup/rollup/pull/1068)), quote reserved property names ([#1057](https://github.com/rollup/rollup/pull/1057)) +* Fix missing namespace member warnings ([#1045](https://github.com/rollup/rollup/issues/1045)) +* Fix TypeError in arrow function without braces returning a function ([#1062](https://github.com/rollup/rollup/pull/1062)) + +## 0.36.4 + +* Only depend on program-level call expressions ([#977](https://github.com/rollup/rollup/issues/977)) + +## 0.36.3 + +* Add `legacy` option for IE8 support ([#989](https://github.com/rollup/rollup/pull/989)) + +## 0.36.2 + +* Insert semicolons where necessary to fix broken code ([#1004](https://github.com/rollup/rollup/issues/1004)) +* Include module ID and location when warning about top-level `this` ([#1012](https://github.com/rollup/rollup/pull/1012)) +* More informative error for missing exports ([#1033](https://github.com/rollup/rollup/issues/1033)) +* `options.moduleContext` for per-module context overrides ([#1023](https://github.com/rollup/rollup/pull/1023)) + +## 0.36.1 + +* Include naked block statements ([#981](https://github.com/rollup/rollup/issues/981)) +* Correctly include falsy alternate statements in optimised if blocks ([#973](https://github.com/rollup/rollup/issues/973)) +* Prevent omission of default exports that are only used by the exporting module ([#967](https://github.com/rollup/rollup/pull/967)) +* Prevent warning on `auto` exports with ES output ([#966](https://github.com/rollup/rollup/pull/966)) + +## 0.36.0 + +* `export { foo as default }` no longer creates a live binding ([#860](https://github.com/rollup/rollup/issues/860)) + +## 0.35.15 + +* Warn on missing unused imports in deshadowing phase ([#928](https://github.com/rollup/rollup/issues/928)) +* Always add a newline to the end of bundles ([#958](https://github.com/rollup/rollup/issues/958)) + +## 0.35.14 + +* Include all parent statements of expression with effects, up to function boundary ([#930](https://github.com/rollup/rollup/issues/930)) + +## 0.35.13 + +* Include superclasses when including their subclasses ([#932](https://github.com/rollup/rollup/issues/932)) + +## 0.35.12 + +* Add `interop: false` option to disable unwrapping of external imports ([#939](https://github.com/rollup/rollup/issues/939)) + +## 0.35.11 + +* Deconflict reified namespaces with other declarations ([#910](https://github.com/rollup/rollup/issues/910)) + +## 0.35.10 + +* Only remove EmptyStatement nodes directly inside blocks ([#913](https://github.com/rollup/rollup/issues/931)) + +## 0.35.9 + +* Support Node 0.12 ([#909](https://github.com/rollup/rollup/issues/909)) + +## 0.35.8 + +* Correctly deshadow re-assigned module functions ([#910](https://github.com/rollup/rollup/issues/910)) + +## 0.35.7 + +* Refactor `flushTime.js` ([#922](https://github.com/rollup/rollup/pull/922)) + +## 0.35.6 + +* Fix browser build + +## 0.35.5 + +* Allow empty for loop heads ([#919](https://github.com/rollup/rollup/issues/919)) + +## 0.35.4 + +* Preserve effects in for-of and for-in loops ([#870](https://github.com/rollup/rollup/issues/870)) +* Remove empty statements ([#918](https://github.com/rollup/rollup/pull/918)) + +## 0.35.3 + +* Render identifiers inside template literals + +## 0.35.2 + +* Fix broken build caused by out of date locally installed dependencies + +## 0.35.1 + +* Rewrite deconflicted class identifiers ([#915](https://github.com/rollup/rollup/pull/915)) +* Include `dependencies` in `bundle.modules` objects ([#903](https://github.com/rollup/rollup/issues/903)) +* Update to Acorn 4 ([#914](https://github.com/rollup/rollup/pull/914)) + +## 0.35.0 + +* Rewrite analysis/tree-shaking code ([#902](https://github.com/rollup/rollup/pull/902)) +* Include conditional mutations of global objects ([#901](https://github.com/rollup/rollup/issues/901)) +* Only reify namespaces if necessary ([#898](https://github.com/rollup/rollup/issues/898)) +* Track mutations of aliased globals ([#893](https://github.com/rollup/rollup/issues/893)) +* Include duplicated var declarations ([#716](https://github.com/rollup/rollup/issues/716)) + +## 0.34.13 + +* Pass `{ format }` through to `transformBundle` ([#867](https://github.com/rollup/rollup/issues/867)) + +## 0.34.12 + +* Fix `rollup --watch` ([#887](https://github.com/rollup/rollup/issues/887)) +* Case-sensitive paths ([#862](https://github.com/rollup/rollup/issues/862)) + +## 0.34.11 + +* Prevent leaky state when `bundle` is reused ([#875](https://github.com/rollup/rollup/issues/875)) +* Ensure `intro` appears before interop block ([#880](https://github.com/rollup/rollup/issues/880)) + +## 0.34.10 + +* Allow custom `options.context` to replace top-level `this` ([#851](https://github.com/rollup/rollup/issues/851)) +* Fix `noConflict` when used via `rollup --config` ([#846](https://github.com/rollup/rollup/issues/846)) +* Place `outro` block *after* export block ([#852](https://github.com/rollup/rollup/issues/852)) + +## 0.34.9 + +* Disable indentation by default, for faster bundle generation ([#812](https://github.com/rollup/rollup/pull/812)) +* More helpful error on missing entry file ([#802](https://github.com/rollup/rollup/issues/802)) +* Preserve comments before import declarations ([#815](https://github.com/rollup/rollup/pull/815)) + +## 0.34.8 + +* Wrap UMD factory function in parens to avoid lazy parsing ([#774](https://github.com/rollup/rollup/pull/774)) + +## 0.34.7 + +* Leave it up to resolveId to normalize the entry path ([#835](https://github.com/rollup/rollup/pull/835)) +* Cache decoded mappings ([#834](https://github.com/rollup/rollup/pull/834)) + +## 0.34.5 + +* Fix circular export ([#813](https://github.com/rollup/rollup/issues/813)) + +## 0.34.4 + +* Module render performance tweak ([#823](https://github.com/rollup/rollup/pull/823)) + +## 0.34.3 + +* Avoid infinite recursion in `Bundle.sort()` ([#800](https://github.com/rollup/rollup/pull/800)) + +## 0.34.2 + +* resolveId calls are cached now to improve incremental build +* Fixed error message recursion in plugins + +## 0.34.1 + +* Support `paths` config ([#754](https://github.com/rollup/rollup/issues/754)) +* Allow `export *` from external module, internally + +## 0.34.0 + +* Use resolved IDs for relative imports that are also external modules, to allow `options.globals` to work with them ([#763](https://github.com/rollup/rollup/issues/763)) +* Ensure reassigned exports are declared in an ES bundle, and remove empty `exports.foo;` statements ([#755](https://github.com/rollup/rollup/issues/755)) +* Add newline after sourcemap comment ([#756](https://github.com/rollup/rollup/issues/756)) + +## 0.33.2 + +* Add `bundle` as second argument to `ongenerate` and `onwrite` hooks ([#773](https://github.com/rollup/rollup/pull/773)) +* Warn on top-level `this` ([#770](https://github.com/rollup/rollup/issues/770)) + +## 0.33.1 + +* Fix `--no-strict` option ([#751](https://github.com/rollup/rollup/pull/751)) +* Fix Windows edge case with case-sensitive paths ([#760](https://github.com/rollup/rollup/pull/760)) + +## 0.33.0 + +* Downgrade missing transformer sourcemap to a warning, not an error, and print the name of the offending plugin if possible ([#746](https://github.com/rollup/rollup/issues/746)) +* Warn if same name is re-exported from two modules ([#722](https://github.com/rollup/rollup/issues/722)) + +## 0.32.4 + +* Add `ongenerate` and `onwrite` plugin hooks ([#742](https://github.com/rollup/rollup/pull/742)) + +## 0.32.3 + +* Generated correct sourcemaps with reified namespaces ([#668](https://github.com/rollup/rollup/issues/668)) +* Exclude plugin helper modules from sourcemaps ([#747](https://github.com/rollup/rollup/pull/747)) + +## 0.32.2 + +* Allow `--globals` to work with `--external` or `options.external` in whatever configuration ([#743](https://github.com/rollup/rollup/issues/743)) + +## 0.32.1 + +* Preserve side-effects to default exports that coincide with used named exports ([#733](https://github.com/rollup/rollup/issues/733)) +* Support `rollup -c node:pkgname` ([#736](https://github.com/rollup/rollup/issues/736)) + +## 0.32.0 + +* Deprecate `es6` format in favour of `es` ([#468](https://github.com/rollup/rollup/issues/468)) +* Add correct `jsnext:main` build ([#726](https://github.com/rollup/rollup/pull/726)) + +## 0.31.2 + +* Allow `load` plugins to provide sourcemap ([#715](https://github.com/rollup/rollup/pull/715)) +* Allow `sourceMapFile` in config options ([#717](https://github.com/rollup/rollup/issues/717)) + +## 0.31.1 + +* Logging for errors emitted by `rollup-watch` ([#712](https://github.com/rollup/rollup/issues/712)) + +## 0.31.0 + +* Rewrite top-level `this` as `undefined` ([#707](https://github.com/rollup/rollup/pull/707)) +* Pass `options.acorn` to Acorn ([#564](https://github.com/rollup/rollup/issues/564)) + +## 0.30.0 + +* Bundle CLI ([#700](https://github.com/rollup/rollup/issues/700)) +* Ensure absolute paths are normalised ([#704](https://github.com/rollup/rollup/issues/704)) +* Allow `rollup --watch` to work with targets + +## 0.29.1 + +* Merge `target` options with main options ([#701](https://github.com/rollup/rollup/issues/701)) +* Update magic-string ([#690](https://github.com/rollup/rollup/issues/690)) + +## 0.29.0 + +* `rollup --watch` ([#284](https://github.com/rollup/rollup/issues/284)) + +## 0.28.0 + +* Experimental support for incremental rebuilds ([#658](https://github.com/rollup/rollup/pull/658)) + +## 0.27.1 + +* Ensure names exported from a module are not replaced with reserved words ([#696](https://github.com/rollup/rollup/pull/696)) +* Revert ([#692](https://github.com/rollup/rollup/pull/692)) – resolved IDs must be strings + +## 0.27.0 + +* Use native promises instead of `es6-promise` ([#689](https://github.com/rollup/rollup/issues/689)) +* Support multiple targets in config files ([#655](https://github.com/rollup/rollup/issues/655)) +* Allow `resolveId` plugin functions to return non-strings ([#692](https://github.com/rollup/rollup/pull/692)) + +## 0.26.7 + +* Distinguish between default and namespace imports of external module ([#637](https://github.com/rollup/rollup/issues/637)) +* Add `__esModule` property to named exports in AMD, CJS and UMD modes ([#650](https://github.com/rollup/rollup/issues/650)) + ## 0.26.6 * Deconflict named imports from external modules in ES bundles ([#659](https://github.com/rollup/rollup/issues/659)) diff --git a/LICENSE.md b/LICENSE.md index ae037ce08c3..ec3180a8f60 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 [these people](https://github.com/rollup/rollup/graphs/contributors) +Copyright (c) 2016 [these people](https://github.com/rollup/rollup/graphs/contributors) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6e02e51db4e..25d19589542 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ alt="license"> - dependency status - Coverage via Codecov + Coverage via Codecov bundle.js` from breaking -var log = console.error.bind(console); - -module.exports = function ( command ) { - if ( command._.length > 1 ) { - handleError({ code: 'ONE_AT_A_TIME' }); - } - - if ( command._.length === 1 ) { - if ( command.input ) { - handleError({ code: 'DUPLICATE_IMPORT_OPTIONS' }); - } - - command.input = command._[0]; - } - - if ( command.environment ) { - command.environment.split( ',' ).forEach( function ( pair ) { - var index = pair.indexOf( ':' ); - if ( ~index ) { - process.env[ pair.slice( 0, index ) ] = pair.slice( index + 1 ); - } else { - process.env[ pair ] = true; - } - }); - } - - var config = command.config === true ? 'rollup.config.js' : command.config; - - if ( config ) { - config = path.resolve( config ); - - rollup.rollup({ - entry: config, - onwarn: function ( message ) { - if ( /Treating .+ as external dependency/.test( message ) ) return; - log( message ); - } - }).then( function ( bundle ) { - var code = bundle.generate({ - format: 'cjs' - }).code; - - // temporarily override require - var defaultLoader = require.extensions[ '.js' ]; - require.extensions[ '.js' ] = function ( m, filename ) { - if ( filename === config ) { - m._compile( code, filename ); - } else { - defaultLoader( m, filename ); - } - }; - - try { - var options = require( path.resolve( config ) ); - if ( Object.keys( options ).length === 0 ) { - handleError({ code: 'MISSING_CONFIG' }); - } - } catch ( err ) { - handleError( err ); - } - - execute( options, command ); - - require.extensions[ '.js' ] = defaultLoader; - }) - .catch(log); - } else { - execute( {}, command ); - } -}; - -var equivalents = { - banner: 'banner', - footer: 'footer', - format: 'format', - globals: 'globals', - id: 'moduleId', - indent: 'indent', - input: 'entry', - intro: 'intro', - name: 'moduleName', - output: 'dest', - outro: 'outro', - sourcemap: 'sourceMap', - treeshake: 'treeshake' -}; - -function execute ( options, command ) { - var external = ( options.external || [] ) - .concat( command.external ? command.external.split( ',' ) : [] ); - - if ( command.globals ) { - var globals = Object.create( null ); - - command.globals.split( ',' ).forEach(function ( str ) { - var names = str.split( ':' ); - globals[ names[0] ] = names[1]; - - // Add missing Module IDs to external. - if ( external.indexOf( names[0] ) === -1 ) { - external.push( names[0] ); - } - }); - - command.globals = globals; - } - - options.onwarn = options.onwarn || log; - - options.external = external; - - options.noConflict = command.conflict === false; - delete command.conflict; - - // Use any options passed through the CLI as overrides. - Object.keys( equivalents ).forEach( function ( cliOption ) { - if ( command.hasOwnProperty( cliOption ) ) { - options[ equivalents[ cliOption ] ] = command[ cliOption ]; - } - }); - - try { - bundle( options ).catch( handleError ); - } catch ( err ) { - handleError( err ); - } -} - -function bundle ( options ) { - if ( !options.entry ) { - handleError({ code: 'MISSING_INPUT_OPTION' }); - } - - return rollup.rollup( options ).then( function ( bundle ) { - if ( options.dest ) { - return bundle.write( options ); - } - - if ( options.sourceMap && options.sourceMap !== 'inline' ) { - handleError({ code: 'MISSING_OUTPUT_OPTION' }); - } - - var result = bundle.generate( options ); - - var code = result.code, - map = result.map; - - if ( options.sourceMap === 'inline' ) { - code += '\n//# sourceMappingURL=' + map.toUrl(); - } - - process.stdout.write( code ); - }); -} diff --git a/bin/showHelp.js b/bin/showHelp.js deleted file mode 100644 index 1cc19b651af..00000000000 --- a/bin/showHelp.js +++ /dev/null @@ -1,13 +0,0 @@ -var fs = require( 'fs' ); -var path = require( 'path' ); - -module.exports = function () { - fs.readFile( path.join( __dirname, 'help.md' ), function ( err, result ) { - var help; - - if ( err ) throw err; - - help = result.toString().replace( '<%= version %>', require( '../package.json' ).version ); - console.log( '\n' + help + '\n' ); - }); -}; diff --git a/bin/src/handleError.js b/bin/src/handleError.js new file mode 100644 index 00000000000..80892fd0337 --- /dev/null +++ b/bin/src/handleError.js @@ -0,0 +1,65 @@ +import * as chalk from 'chalk'; + +function stderr ( msg ) { + console.error( msg ); // eslint-disable-line no-console +} + +const handlers = { + MISSING_CONFIG: () => { + stderr( chalk.red( 'Config file must export an options object. See https://github.com/rollup/rollup/wiki/Command-Line-Interface#using-a-config-file' ) ); + }, + + MISSING_EXTERNAL_CONFIG: err => { + stderr( chalk.red( `Could not resolve config file ${err.config}` ) ); + }, + + MISSING_INPUT_OPTION: () => { + stderr( chalk.red( 'You must specify an --input (-i) option' ) ); + }, + + MISSING_OUTPUT_OPTION: () => { + stderr( chalk.red( 'You must specify an --output (-o) option when creating a file with a sourcemap' ) ); + }, + + MISSING_NAME: () => { + stderr( chalk.red( 'You must supply a name for UMD exports (e.g. `--name myModule`)' ) ); + }, + + PARSE_ERROR: err => { + stderr( chalk.red( `Error parsing ${err.file}: ${err.message}` ) ); + }, + + ONE_AT_A_TIME: () => { + stderr( chalk.red( 'rollup can only bundle one file at a time' ) ); + }, + + DUPLICATE_IMPORT_OPTIONS: () => { + stderr( chalk.red( 'use --input, or pass input path as argument' ) ); + }, + + ROLLUP_WATCH_NOT_INSTALLED: () => { + stderr( chalk.red( 'rollup --watch depends on the rollup-watch package, which could not be found. You can install it globally (recommended) with ' ) + chalk.cyan( 'npm install -g rollup-watch' ) ); + }, + + WATCHER_MISSING_INPUT_OR_OUTPUT: () => { + stderr( chalk.red( 'must specify --input and --output when using rollup --watch' ) ); + } +}; + +export default function handleError ( err, recover ) { + const handler = handlers[ err && err.code ]; + + if ( handler ) { + handler( err ); + } else { + stderr( chalk.red( err.message || err ) ); + + if ( err.stack ) { + stderr( chalk.grey( err.stack ) ); + } + } + + stderr( `Type ${chalk.cyan( 'rollup --help' )} for help, or visit https://github.com/rollup/rollup/wiki` ); + + if ( !recover ) process.exit( 1 ); +} diff --git a/bin/help.md b/bin/src/help.md similarity index 92% rename from bin/help.md rename to bin/src/help.md index 46886c7849d..58482d5678b 100644 --- a/bin/help.md +++ b/bin/src/help.md @@ -1,4 +1,4 @@ -rollup version <%= version %> +rollup version __VERSION__ ===================================== Usage: rollup [options] @@ -9,9 +9,10 @@ Basic options: -h, --help Show this help message -c, --config Use this config file (if argument is used but value is unspecified, defaults to rollup.config.js) +-w, --watch Watch files in bundle and rebuild on changes -i, --input Input (alternative to ) -o, --output Output (if absent, prints to stdout) --f, --format [es6] Type of output (amd, cjs, es6, iife, umd) +-f, --format [es] Type of output (amd, cjs, es, iife, umd) -e, --external Comma-separate list of module IDs to exclude -g, --globals Comma-separate list of `module ID:Global` pairs Any module IDs defined here are added to external diff --git a/bin/src/index.js b/bin/src/index.js new file mode 100644 index 00000000000..cbc81238cfd --- /dev/null +++ b/bin/src/index.js @@ -0,0 +1,39 @@ +import minimist from 'minimist'; +import help from './help.md'; +import { version } from '../../package.json'; +import runRollup from './runRollup'; + +const command = minimist( process.argv.slice( 2 ), { + alias: { + // Aliases + strict: 'useStrict', + + // Short options + c: 'config', + d: 'indent', + e: 'external', + f: 'format', + g: 'globals', + h: 'help', + i: 'input', + l: 'legacy', + m: 'sourcemap', + n: 'name', + o: 'output', + u: 'id', + v: 'version', + w: 'watch' + } +}); + +if ( command.help || ( process.argv.length <= 2 && process.stdin.isTTY ) ) { + console.log( `\n${help.replace('__VERSION__', version)}\n` ); // eslint-disable-line no-console +} + +else if ( command.version ) { + console.log( `rollup version ${version}` ); // eslint-disable-line no-console +} + +else { + runRollup( command ); +} diff --git a/bin/src/runRollup.js b/bin/src/runRollup.js new file mode 100644 index 00000000000..84cd3da575b --- /dev/null +++ b/bin/src/runRollup.js @@ -0,0 +1,247 @@ +import { realpathSync } from 'fs'; +import * as rollup from 'rollup'; +import relative from 'require-relative'; +import handleError from './handleError'; +import SOURCEMAPPING_URL from './sourceMappingUrl.js'; + +import { install as installSourcemapSupport } from 'source-map-support'; +installSourcemapSupport(); + +// stderr to stderr to keep `rollup main.js > bundle.js` from breaking +const stderr = console.error.bind( console ); // eslint-disable-line no-console + +export default function runRollup ( command ) { + if ( command._.length > 1 ) { + handleError({ code: 'ONE_AT_A_TIME' }); + } + + if ( command._.length === 1 ) { + if ( command.input ) { + handleError({ code: 'DUPLICATE_IMPORT_OPTIONS' }); + } + + command.input = command._[0]; + } + + if ( command.environment ) { + command.environment.split( ',' ).forEach( pair => { + const index = pair.indexOf( ':' ); + if ( ~index ) { + process.env[ pair.slice( 0, index ) ] = pair.slice( index + 1 ); + } else { + process.env[ pair ] = true; + } + }); + } + + let config = command.config === true ? 'rollup.config.js' : command.config; + + if ( config ) { + if ( config.slice( 0, 5 ) === 'node:' ) { + const pkgName = config.slice( 5 ); + try { + config = relative.resolve( `rollup-config-${pkgName}`, process.cwd() ); + } catch ( err ) { + try { + config = relative.resolve( pkgName, process.cwd() ); + } catch ( err ) { + if ( err.code === 'MODULE_NOT_FOUND' ) { + handleError({ code: 'MISSING_EXTERNAL_CONFIG', config }); + } + + throw err; + } + } + } else { + // find real path of config so it matches what Node provides to callbacks in require.extensions + config = realpathSync( config ); + } + + rollup.rollup({ + entry: config, + onwarn: message => { + if ( /Treating .+ as external dependency/.test( message ) ) return; + stderr( message ); + } + }).then( bundle => { + const { code } = bundle.generate({ + format: 'cjs' + }); + + // temporarily override require + const defaultLoader = require.extensions[ '.js' ]; + require.extensions[ '.js' ] = ( m, filename ) => { + if ( filename === config ) { + m._compile( code, filename ); + } else { + defaultLoader( m, filename ); + } + }; + + try { + const options = require( config ); + if ( Object.keys( options ).length === 0 ) { + handleError({ code: 'MISSING_CONFIG' }); + } + execute( options, command ); + require.extensions[ '.js' ] = defaultLoader; + } catch ( err ) { + handleError( err ); + } + }) + .catch( stderr ); + } else { + execute( {}, command ); + } +} + +const equivalents = { + useStrict: 'useStrict', + banner: 'banner', + footer: 'footer', + format: 'format', + globals: 'globals', + id: 'moduleId', + indent: 'indent', + input: 'entry', + intro: 'intro', + legacy: 'legacy', + name: 'moduleName', + output: 'dest', + outro: 'outro', + sourcemap: 'sourceMap', + treeshake: 'treeshake' +}; + +function execute ( options, command ) { + let external; + + const commandExternal = ( command.external || '' ).split( ',' ); + const optionsExternal = options.external; + + if ( command.globals ) { + let globals = Object.create( null ); + + command.globals.split( ',' ).forEach( str => { + const names = str.split( ':' ); + globals[ names[0] ] = names[1]; + + // Add missing Module IDs to external. + if ( commandExternal.indexOf( names[0] ) === -1 ) { + commandExternal.push( names[0] ); + } + }); + + command.globals = globals; + } + + if ( typeof optionsExternal === 'function' ) { + external = id => { + return optionsExternal( id ) || ~commandExternal.indexOf( id ); + }; + } else { + external = ( optionsExternal || [] ).concat( commandExternal ); + } + + options.onwarn = options.onwarn || stderr; + + options.external = external; + + // Use any options passed through the CLI as overrides. + Object.keys( equivalents ).forEach( cliOption => { + if ( command.hasOwnProperty( cliOption ) ) { + options[ equivalents[ cliOption ] ] = command[ cliOption ]; + } + }); + + try { + if ( command.watch ) { + if ( !options.entry || ( !options.dest && !options.targets ) ) { + handleError({ code: 'WATCHER_MISSING_INPUT_OR_OUTPUT' }); + } + + try { + const watch = relative( 'rollup-watch', process.cwd() ); + const watcher = watch( rollup, options ); + + watcher.on( 'event', event => { + switch ( event.code ) { + case 'STARTING': + stderr( 'checking rollup-watch version...' ); + break; + + case 'BUILD_START': + stderr( 'bundling...' ); + break; + + case 'BUILD_END': + stderr( 'bundled in ' + event.duration + 'ms. Watching for changes...' ); + break; + + case 'ERROR': + handleError( event.error, true ); + break; + + default: + stderr( 'unknown event', event ); + } + }); + } catch ( err ) { + if ( err.code === 'MODULE_NOT_FOUND' ) { + err.code = 'ROLLUP_WATCH_NOT_INSTALLED'; + } + + handleError( err ); + } + } else { + bundle( options ).catch( handleError ); + } + } catch ( err ) { + handleError( err ); + } +} + +function clone ( object ) { + return assign( {}, object ); +} + +function assign ( target, source ) { + Object.keys( source ).forEach( key => { + target[ key ] = source[ key ]; + }); + return target; +} + +function bundle ( options ) { + if ( !options.entry ) { + handleError({ code: 'MISSING_INPUT_OPTION' }); + } + + return rollup.rollup( options ).then( bundle => { + if ( options.dest ) { + return bundle.write( options ); + } + + if ( options.targets ) { + let result = null; + + options.targets.forEach( target => { + result = bundle.write( assign( clone( options ), target ) ); + }); + + return result; + } + + if ( options.sourceMap && options.sourceMap !== 'inline' ) { + handleError({ code: 'MISSING_OUTPUT_OPTION' }); + } + + let { code, map } = bundle.generate( options ); + + if ( options.sourceMap === 'inline' ) { + code += `\n//# ${SOURCEMAPPING_URL}=${map.toUrl()}\n`; + } + + process.stdout.write( code ); + }); +} diff --git a/bin/src/sourceMappingUrl.js b/bin/src/sourceMappingUrl.js new file mode 100644 index 00000000000..e7c42659fde --- /dev/null +++ b/bin/src/sourceMappingUrl.js @@ -0,0 +1,4 @@ +let SOURCEMAPPING_URL = 'sourceMa'; +SOURCEMAPPING_URL += 'ppingURL'; + +export default SOURCEMAPPING_URL; diff --git a/browser/path.js b/browser/path.js new file mode 100644 index 00000000000..279ba669a69 --- /dev/null +++ b/browser/path.js @@ -0,0 +1,80 @@ +export const absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|\/])/; +export const relativePath = /^\.?\.\//; + +export function isAbsolute ( path ) { + return absolutePath.test( path ); +} + +export function isRelative ( path ) { + return relativePath.test( path ); +} + +export function normalize ( path ) { + return path.replace( /\\/g, '/' ); +} + +export function basename ( path ) { + return path.split( /(\/|\\)/ ).pop(); +} + +export function dirname ( path ) { + const match = /(\/|\\)[^\/\\]*$/.exec( path ); + if ( !match ) return '.'; + + const dir = path.slice( 0, -match[0].length ); + + // If `dir` is the empty string, we're at root. + return dir ? dir : '/'; +} + +export function extname ( path ) { + const match = /\.[^\.]+$/.exec( basename( path ) ); + if ( !match ) return ''; + return match[0]; +} + +export function relative ( from, to ) { + const fromParts = from.split( /[\/\\]/ ).filter( Boolean ); + const toParts = to.split( /[\/\\]/ ).filter( Boolean ); + + while ( fromParts[0] && toParts[0] && fromParts[0] === toParts[0] ) { + fromParts.shift(); + toParts.shift(); + } + + while ( toParts[0] === '.' || toParts[0] === '..' ) { + const toPart = toParts.shift(); + if ( toPart === '..' ) { + fromParts.pop(); + } + } + + while ( fromParts.pop() ) { + toParts.unshift( '..' ); + } + + return toParts.join( '/' ); +} + +export function resolve ( ...paths ) { + let resolvedParts = paths.shift().split( /[\/\\]/ ); + + paths.forEach( path => { + if ( isAbsolute( path ) ) { + resolvedParts = path.split( /[\/\\]/ ); + } else { + const parts = path.split( /[\/\\]/ ); + + while ( parts[0] === '.' || parts[0] === '..' ) { + const part = parts.shift(); + if ( part === '..' ) { + resolvedParts.pop(); + } + } + + resolvedParts.push.apply( resolvedParts, parts ); + } + }); + + return resolvedParts.join( '/' ); // TODO windows... +} diff --git a/browser/promise.js b/browser/promise.js deleted file mode 100644 index 06b83096a64..00000000000 --- a/browser/promise.js +++ /dev/null @@ -1 +0,0 @@ -export default window.Promise; diff --git a/package.json b/package.json index be499e9d075..ea85120e494 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,29 @@ { "name": "rollup", - "version": "0.26.6", + "version": "0.37.0", "description": "Next-generation ES6 module bundler", "main": "dist/rollup.js", - "jsnext:main": "src/rollup.js", + "module": "dist/rollup.es.js", + "jsnext:main": "dist/rollup.es.js", "bin": { "rollup": "./bin/rollup" }, "scripts": { - "pretest": "npm run build", - "test": "mocha --compilers js:buble/register", + "pretest": "npm run build && npm run build:cli", + "test": "mocha", + "test:quick": "rollup -c && 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", "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", "ci": "npm run test-coverage && codecov < coverage/coverage-remapped.lcov", - "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", + "build": "git rev-parse HEAD > .commithash && rollup -c", + "build:cli": "rollup -c rollup.config.cli.js", + "build:browser": "git rev-parse HEAD > .commithash && rollup -c rollup.config.browser.js", + "watch": "rollup -c -w", + "watch:browser": "rollup -c rollup.config.browser.js -w", + "watch:cli": "rollup -c rollup.config.cli.js -w", "prepublish": "npm run lint && npm test && npm run build:browser", - "lint": "eslint src browser" + "lint": "eslint src browser test/test.js test/utils test/**/_config.js" }, "repository": { "type": "git", @@ -32,7 +38,8 @@ ], "author": "Rich Harris", "contributors": [ - "Oskar Segersvärd " + "Oskar Segersvärd ", + "Bogdan Chadkin " ], "license": "MIT", "bugs": { @@ -40,36 +47,38 @@ }, "homepage": "https://github.com/rollup/rollup", "devDependencies": { - "acorn": "^3.1.0", - "babel-core": "^5.8.32", - "buble": "^0.6.4", + "acorn": "^4.0.1", + "buble": "^0.12.5", + "chalk": "^1.1.3", "codecov.io": "^0.1.6", - "console-group": "^0.2.0", - "es6-promise": "^3.0.2", - "eslint": "^2.9.0", - "estree-walker": "^0.2.0", - "istanbul": "^0.4.0", - "magic-string": "^0.10.1", - "mocha": "^2.3.3", - "remap-istanbul": "^0.5.1", - "rollup": "^0.26.2", - "rollup-plugin-buble": "^0.6.0", - "rollup-plugin-node-resolve": "^1.5.0", - "rollup-plugin-replace": "^1.0.1", - "sander": "^0.5.0", - "source-map": "^0.5.3", - "sourcemap-codec": "^1.2.1", - "uglify-js": "^2.6.1" + "console-group": "^0.3.1", + "eslint": "^2.13.0", + "eslint-plugin-import": "^1.14.0", + "estree-walker": "^0.2.1", + "istanbul": "^0.4.3", + "magic-string": "^0.15.2", + "minimist": "^1.2.0", + "mocha": "^3.0.0", + "remap-istanbul": "^0.6.4", + "require-relative": "^0.8.7", + "rollup": "^0.34.0", + "rollup-plugin-buble": "^0.12.1", + "rollup-plugin-commonjs": "^3.0.0", + "rollup-plugin-json": "^2.0.0", + "rollup-plugin-node-resolve": "^2.0.0", + "rollup-plugin-replace": "^1.1.0", + "rollup-plugin-string": "^2.0.0", + "sander": "^0.5.1", + "source-map": "^0.5.6", + "sourcemap-codec": "^1.3.0", + "uglify-js": "^2.6.2" }, "dependencies": { - "chalk": "^1.1.1", - "minimist": "^1.2.0", "source-map-support": "^0.4.0" }, "files": [ - "src", "dist", - "bin", + "bin/rollup", "README.md" ] } diff --git a/rollup.config.browser.js b/rollup.config.browser.js index adee949af9a..95977b4866a 100644 --- a/rollup.config.browser.js +++ b/rollup.config.browser.js @@ -3,11 +3,12 @@ import config from './rollup.config.js'; config.plugins.push({ load: function ( id ) { - if ( ~id.indexOf( 'fs.js' ) ) return readFileSync( 'browser/fs.js' ).toString(); - if ( ~id.indexOf( 'es6-promise' ) ) return readFileSync( 'browser/promise.js' ).toString(); + if ( ~id.indexOf( 'fs.js' ) ) return readFileSync( 'browser/fs.js', 'utf-8' ); + if ( ~id.indexOf( 'path.js' ) ) return readFileSync( 'browser/path.js', 'utf-8' ); } }); config.format = 'umd'; +config.dest = 'dist/rollup.browser.js'; export default config; diff --git a/rollup.config.cli.js b/rollup.config.cli.js new file mode 100644 index 00000000000..982f6b08753 --- /dev/null +++ b/rollup.config.cli.js @@ -0,0 +1,34 @@ +import buble from 'rollup-plugin-buble'; +import json from 'rollup-plugin-json'; +import string from 'rollup-plugin-string'; +import nodeResolve from 'rollup-plugin-node-resolve'; +import commonjs from 'rollup-plugin-commonjs'; + +export default { + entry: 'bin/src/index.js', + dest: 'bin/rollup', + format: 'cjs', + banner: '#!/usr/bin/env node', + plugins: [ + string({ include: '**/*.md' }), + json(), + buble(), + commonjs({ + include: 'node_modules/**', + namedExports: { chalk: [ 'red', 'cyan', 'grey' ] } + }), + nodeResolve({ + main: true + }) + ], + external: [ + 'fs', + 'path', + 'module', + 'source-map-support', + 'rollup' + ], + paths: { + rollup: '../dist/rollup.js' + } +}; diff --git a/rollup.config.js b/rollup.config.js index 521d6144f72..cc0b9ba4a65 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,6 @@ import { readFileSync } from 'fs'; import buble from 'rollup-plugin-buble'; -import npm from 'rollup-plugin-node-resolve'; +import nodeResolve from 'rollup-plugin-node-resolve'; import replace from 'rollup-plugin-replace'; var pkg = JSON.parse( readFileSync( 'package.json', 'utf-8' ) ); @@ -20,13 +20,15 @@ var banner = readFileSync( 'src/banner.js', 'utf-8' ) export default { entry: 'src/rollup.js', - format: 'cjs', plugins: [ buble({ - include: [ 'src/**', 'node_modules/acorn/**' ] + include: [ 'src/**', 'node_modules/acorn/**' ], + target: { + node: '0.12' + } }), - npm({ + nodeResolve({ jsnext: true }), @@ -37,8 +39,15 @@ export default { values: { 'VERSION': pkg.version } }) ], - external: [ 'fs' ], + external: [ + 'fs', + 'path' + ], banner: banner, sourceMap: true, - moduleName: 'rollup' + moduleName: 'rollup', + targets: [ + { dest: 'dist/rollup.js', format: 'cjs' }, + { dest: 'dist/rollup.es.js', format: 'es' } + ] }; diff --git a/src/Bundle.js b/src/Bundle.js index 95c0d109c9c..9c6b44d4db9 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -1,5 +1,8 @@ -import MagicString from 'magic-string'; +import { timeStart, timeEnd } from './utils/flushTime.js'; +import { decode } from 'sourcemap-codec'; +import { Bundle as MagicStringBundle } from 'magic-string'; import first from './utils/first.js'; +import { find } from './utils/array.js'; import { blank, forOwn, keys } from './utils/object.js'; import Module from './Module.js'; import ExternalModule from './ExternalModule.js'; @@ -8,26 +11,32 @@ import ensureArray from './utils/ensureArray.js'; import { load, makeOnwarn, resolveId } from './utils/defaults.js'; import getExportMode from './utils/getExportMode.js'; import getIndentString from './utils/getIndentString.js'; -import { unixizePath } from './utils/normalizePlatform.js'; import { mapSequence } from './utils/promise.js'; import transform from './utils/transform.js'; import transformBundle from './utils/transformBundle.js'; import collapseSourcemaps from './utils/collapseSourcemaps.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; import callIfFunction from './utils/callIfFunction.js'; -import { dirname, isRelative, isAbsolute, relative, resolve } from './utils/path.js'; +import { dirname, isRelative, isAbsolute, normalize, relative, resolve } from './utils/path.js'; +import BundleScope from './ast/scopes/BundleScope.js'; export default class Bundle { constructor ( options ) { + this.cachedModules = new Map(); + if ( options.cache ) { + options.cache.modules.forEach( module => { + this.cachedModules.set( module.id, module ); + }); + } + this.plugins = ensureArray( options.plugins ); - this.plugins.forEach( plugin => { - if ( plugin.options ) { - options = plugin.options( options ) || options; - } - }); + options = this.plugins.reduce( ( acc, plugin ) => { + if ( plugin.options ) return plugin.options( acc ) || acc; + return acc; + }, options); - this.entry = unixizePath( options.entry ); + this.entry = options.entry; this.entryId = null; this.entryModule = null; @@ -39,42 +48,56 @@ export default class Bundle { .concat( resolveId ) ); - this.load = first( - this.plugins - .map( plugin => plugin.load ) - .filter( Boolean ) - .concat( load ) - ); - - this.transformers = this.plugins - .map( plugin => plugin.transform ) + const loaders = this.plugins + .map( plugin => plugin.load ) .filter( Boolean ); + this.hasLoaders = loaders.length !== 0; + this.load = first( loaders.concat( load ) ); - this.bundleTransformers = this.plugins - .map( plugin => plugin.transformBundle ) - .filter( Boolean ); + this.getPath = typeof options.paths === 'function' ? + ( id => options.paths( id ) || this.getPathRelativeToEntryDirname( id ) ) : + options.paths ? + ( id => options.paths.hasOwnProperty( id ) ? options.paths[ id ] : this.getPathRelativeToEntryDirname( id ) ) : + id => this.getPathRelativeToEntryDirname( id ); - this.moduleById = blank(); - this.modules = []; + this.scope = new BundleScope(); + // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles + [ 'module', 'exports', '_interopDefault' ].forEach( name => { + this.scope.findDeclaration( name ); // creates global declaration as side-effect + }); + this.moduleById = new Map(); + this.modules = []; this.externalModules = []; - this.internalNamespaces = []; - this.assumedGlobals = blank(); + this.context = String( options.context ); + + if ( typeof options.moduleContext === 'function' ) { + this.getModuleContext = id => options.moduleContext( id ) || this.context; + } else if ( typeof options.moduleContext === 'object' ) { + const moduleContext = new Map(); + Object.keys( options.moduleContext ).forEach( key => { + moduleContext.set( resolve( key ), options.moduleContext[ key ] ); + }); + this.getModuleContext = id => moduleContext.get( id ) || this.context; + } else { + this.getModuleContext = () => this.context; + } if ( typeof options.external === 'function' ) { this.isExternal = options.external; } else { - const ids = ensureArray( options.external ).map( id => id.replace( /[\/\\]/g, '/' ) ); + const ids = ensureArray( options.external ); this.isExternal = id => ids.indexOf( id ) !== -1; } this.onwarn = options.onwarn || makeOnwarn(); - // TODO strictly speaking, this only applies with non-ES6, non-default-only bundles - [ 'module', 'exports', '_interopDefault' ].forEach( global => this.assumedGlobals[ global ] = true ); - this.varOrConst = options.preferConst ? 'const' : 'var'; + this.legacy = options.legacy; + this.acornOptions = options.acorn || {}; + + this.dependentExpressions = []; } build () { @@ -83,6 +106,7 @@ export default class Bundle { // of the entry module's dependencies return this.resolveId( this.entry, undefined ) .then( id => { + if ( id == null ) throw new Error( `Could not resolve entry (${this.entry})` ); this.entryId = id; return this.fetchModule( id, undefined ); }) @@ -91,44 +115,79 @@ export default class Bundle { // Phase 2 – binding. We link references to their declarations // to generate a complete picture of the bundle + + timeStart( 'phase 2' ); + this.modules.forEach( module => module.bindImportSpecifiers() ); - this.modules.forEach( module => module.bindAliases() ); this.modules.forEach( module => module.bindReferences() ); + timeEnd( 'phase 2' ); + // Phase 3 – marking. We 'run' each statement to see which ones // need to be included in the generated bundle + timeStart( 'phase 3' ); + // mark all export statements entryModule.getExports().forEach( name => { const declaration = entryModule.traceExport( name ); + declaration.exportName = name; + declaration.activate(); - declaration.use(); + if ( declaration.isNamespace ) { + declaration.needsNamespaceBlock = true; + } }); // mark statements that should appear in the bundle - let settled = false; - while ( !settled ) { - settled = true; - + if ( this.treeshake ) { this.modules.forEach( module => { - if ( module.run( this.treeshake ) ) settled = false; + module.run(); }); + + let settled = false; + while ( !settled ) { + settled = true; + + let i = this.dependentExpressions.length; + while ( i-- ) { + const expression = this.dependentExpressions[i]; + + let statement = expression; + while ( statement.parent && !/Function/.test( statement.parent.type ) ) statement = statement.parent; + + if ( !statement || statement.ran ) { + this.dependentExpressions.splice( i, 1 ); + } else if ( expression.isUsedByBundle() ) { + settled = false; + statement.run( statement.findScope() ); + this.dependentExpressions.splice( i, 1 ); + } + } + } } + timeEnd( 'phase 3' ); + // Phase 4 – final preparation. We order the modules with an // enhanced topological sort that accounts for cycles, then // ensure that names are deconflicted throughout the bundle + + timeStart( 'phase 4' ); + this.orderedModules = this.sort(); this.deconflict(); + + timeEnd( 'phase 4' ); }); } deconflict () { - let used = blank(); + const used = blank(); // ensure no conflicts with globals - keys( this.assumedGlobals ).forEach( name => used[ name ] = 1 ); + keys( this.scope.declarations ).forEach( name => used[ name ] = 1 ); function getSafeName ( name ) { while ( used[ name ] ) { @@ -139,33 +198,45 @@ export default class Bundle { return name; } + const toDeshadow = new Map(); + this.externalModules.forEach( module => { - module.name = getSafeName( module.name ); + const safeName = getSafeName( module.name ); + toDeshadow.set( safeName, true ); + module.name = safeName; // ensure we don't shadow named external imports, if // we're creating an ES6 bundle forOwn( module.declarations, ( declaration, name ) => { - declaration.setSafeName( getSafeName( name ) ); + const safeName = getSafeName( name ); + toDeshadow.set( safeName, true ); + declaration.setSafeName( safeName ); }); }); this.modules.forEach( module => { - forOwn( module.declarations, ( declaration, originalName ) => { - if ( declaration.isGlobal ) return; - - if ( originalName === 'default' ) { - if ( declaration.original && !declaration.original.isReassigned ) return; + forOwn( module.scope.declarations, ( declaration ) => { + if ( declaration.isDefault && declaration.declaration.id ) { + return; } declaration.name = getSafeName( declaration.name ); }); + + // deconflict reified namespaces + const namespace = module.namespace(); + if ( namespace.needsNamespaceBlock ) { + namespace.name = getSafeName( namespace.name ); + } }); + + this.scope.deshadow( toDeshadow ); } fetchModule ( id, importer ) { // short-circuit cycles - if ( id in this.moduleById ) return null; - this.moduleById[ id ] = null; + if ( this.moduleById.has( id ) ) return null; + this.moduleById.set( id, null ); return this.load( id ) .catch( err => { @@ -181,57 +252,85 @@ export default class Bundle { 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 => { - const { code, originalCode, ast, sourceMapChain } = source; + if ( typeof source === 'string' ) { + source = { + code: source, + ast: null + }; + } + + if ( this.cachedModules.has( id ) && this.cachedModules.get( id ).originalCode === source.code ) { + return this.cachedModules.get( id ); + } - const module = new Module({ id, code, originalCode, ast, sourceMapChain, bundle: this }); + return transform( source, id, this.plugins ); + }) + .then( source => { + const { code, originalCode, originalSourceMap, ast, sourceMapChain, resolvedIds } = source; + + const module = new Module({ + id, + code, + originalCode, + originalSourceMap, + ast, + sourceMapChain, + resolvedIds, + bundle: this + }); this.modules.push( module ); - this.moduleById[ id ] = module; + this.moduleById.set( id, module ); - return this.fetchAllDependencies( module ).then( () => module ); + return this.fetchAllDependencies( module ).then( () => { + keys( module.exports ).forEach( name => { + module.exportsAll[name] = module.id; + }); + module.exportAllSources.forEach( source => { + const id = module.resolvedIds[ source ]; + const exportAllModule = this.moduleById.get( id ); + if ( exportAllModule.isExternal ) return; + + keys( exportAllModule.exportsAll ).forEach( name => { + if ( name in module.exportsAll ) { + this.onwarn( `Conflicting namespaces: ${module.id} re-exports '${name}' from both ${module.exportsAll[ name ]} (will be ignored) and ${exportAllModule.exportsAll[ name ]}.` ); + } + module.exportsAll[ name ] = exportAllModule.exportsAll[ name ]; + }); + }); + return module; + }); }); } fetchAllDependencies ( module ) { return mapSequence( module.sources, source => { - return this.resolveId( source, module.id ) + const resolvedId = module.resolvedIds[ source ]; + return ( resolvedId ? Promise.resolve( resolvedId ) : this.resolveId( source, module.id ) ) .then( resolvedId => { - let externalName; - 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 externalId = resolvedId || ( + isRelative( source ) ? resolve( module.id, '..', source ) : source + ); + + let isExternal = this.isExternal( externalId ); + + if ( !resolvedId && !isExternal ) { + if ( isRelative( source ) ) throw new Error( `Could not resolve '${source}' from ${module.id}` ); + + this.onwarn( `Treating '${source}' as external dependency` ); + isExternal = true; } - const forcedExternal = externalName && this.isExternal( externalName ); - - if ( !resolvedId || forcedExternal ) { - let normalizedExternal = source; - - if ( !forcedExternal ) { - if ( isRelative( source ) ) throw new Error( `Could not resolve ${source} from ${module.id}` ); - 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 ] = normalizedExternal; - if ( !this.moduleById[ normalizedExternal ] ) { - const module = new ExternalModule( normalizedExternal ); + if ( isExternal ) { + module.resolvedIds[ source ] = externalId; + + if ( !this.moduleById.has( externalId ) ) { + const module = new ExternalModule( externalId, this.getPath( externalId ) ); this.externalModules.push( module ); - this.moduleById[ normalizedExternal ] = module; + this.moduleById.set( externalId, module ); } - } - - else { + } else { if ( resolvedId === module.id ) { throw new Error( `A module cannot import itself (${resolvedId})` ); } @@ -244,51 +343,62 @@ 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( resolvedId ) || isAbsolute( resolvedId ) ) { + const entryDirname = dirname( this.entryId ); + const relativeToEntry = normalize( relative( entryDirname, resolvedId ) ); - if ( isRelative( relativeToEntry )) { - return relativeToEntry; + return isRelative( relativeToEntry ) ? relativeToEntry : `./${relativeToEntry}`; } - // The path is missing the `./` prefix - return `./${relativeToEntry}`; + return resolvedId; } render ( options = {} ) { - const format = options.format || 'es6'; + if ( options.format === 'es6' ) { + this.onwarn( 'The es6 format is deprecated – use `es` instead' ); + options.format = 'es'; + } + + const format = options.format || 'es'; // Determine export mode - 'default', 'named', 'none' - const exportMode = getExportMode( this, options.exports, options.moduleName ); + const exportMode = getExportMode( this, options ); + + let magicString = new MagicStringBundle({ separator: '\n\n' }); + const usedModules = []; - let magicString = new MagicString.Bundle({ separator: '\n\n' }); - let usedModules = []; + timeStart( 'render modules' ); this.orderedModules.forEach( module => { - const source = module.render( format === 'es6' ); + const source = module.render( format === 'es', this.legacy ); + if ( source.toString().length ) { magicString.addSource( source ); usedModules.push( module ); } }); - const intro = [ options.intro ] + timeEnd( 'render modules' ); + + let intro = [ options.intro ] .concat( this.plugins.map( plugin => plugin.intro && plugin.intro() ) ) .filter( Boolean ) .join( '\n\n' ); - if ( intro ) magicString.prepend( intro + '\n' ); - if ( options.outro ) magicString.append( '\n' + options.outro ); + if ( intro ) intro += '\n'; const indentString = getIndentString( magicString, options ); const finalise = finalisers[ format ]; if ( !finalise ) throw new Error( `You must specify an output type - valid options are ${keys( finalisers ).join( ', ' )}` ); - magicString = finalise( this, magicString.trim(), { exportMode, indentString }, options ); + timeStart( 'render format' ); + + magicString = finalise( this, magicString.trim(), { exportMode, indentString, intro }, options ); + + timeEnd( 'render format' ); const banner = [ options.banner ] .concat( this.plugins.map( plugin => plugin.banner ) ) @@ -307,34 +417,43 @@ export default class Bundle { let code = magicString.toString(); let map = null; - let bundleSourcemapChain = []; + const bundleSourcemapChain = []; - code = transformBundle( code, this.bundleTransformers, bundleSourcemapChain ) + code = transformBundle( code, this.plugins, bundleSourcemapChain, options ) .replace( new RegExp( `\\/\\/#\\s+${SOURCEMAPPING_URL}=.+\\n?`, 'g' ), '' ); if ( options.sourceMap ) { + timeStart( 'sourceMap' ); + let file = options.sourceMapFile || options.dest; if ( file ) file = resolve( typeof process !== 'undefined' ? process.cwd() : '', file ); - map = magicString.generateMap({ file, includeContent: true }); - - if ( this.transformers.length || this.bundleTransformers.length ) { - map = collapseSourcemaps( map, usedModules, bundleSourcemapChain ); + if ( this.hasLoaders || find( this.plugins, plugin => plugin.transform || plugin.transformBundle ) ) { + map = magicString.generateMap( {} ); + if ( typeof map.mappings === 'string' ) { + map.mappings = decode( map.mappings ); + } + map = collapseSourcemaps( file, map, usedModules, bundleSourcemapChain, this.onwarn ); + } else { + map = magicString.generateMap({ file, includeContent: true }); } - map.sources = map.sources.map( unixizePath ); + map.sources = map.sources.map( normalize ); + + timeEnd( 'sourceMap' ); } + if ( code[ code.length - 1 ] !== '\n' ) code += '\n'; return { code, map }; } sort () { - let seen = {}; let hasCycles; - let ordered = []; + const seen = {}; + const ordered = []; - let stronglyDependsOn = blank(); - let dependsOn = blank(); + const stronglyDependsOn = blank(); + const dependsOn = blank(); this.modules.forEach( module => { stronglyDependsOn[ module.id ] = blank(); @@ -384,15 +503,17 @@ export default class Bundle { // b imports a, a is placed before b. We need to find the module // in question, so we can provide a useful error message let parent = '[[unknown]]'; + const visited = {}; const findParent = module => { if ( dependsOn[ module.id ][ a.id ] && dependsOn[ module.id ][ b.id ] ) { parent = module.id; - } else { - for ( let i = 0; i < module.dependencies.length; i += 1 ) { - const dependency = module.dependencies[i]; - if ( findParent( dependency ) ) return; - } + return true; + } + visited[ module.id ] = true; + for ( let i = 0; i < module.dependencies.length; i += 1 ) { + const dependency = module.dependencies[i]; + if ( !visited[ dependency.id ] && findParent( dependency ) ) return true; } }; diff --git a/src/Declaration.js b/src/Declaration.js index 0601606c5bf..88f55530a58 100644 --- a/src/Declaration.js +++ b/src/Declaration.js @@ -1,174 +1,41 @@ import { blank, forOwn, keys } from './utils/object.js'; -import run from './utils/run.js'; -import { SyntheticReference } from './Reference.js'; - -const use = alias => alias.use(); +import makeLegalIdentifier, { reservedWords } from './utils/makeLegalIdentifier.js'; +import { UNKNOWN } from './ast/values.js'; export default class Declaration { - constructor ( node, isParam, statement ) { - if ( node ) { - if ( node.type === 'FunctionDeclaration' ) { - this.isFunctionDeclaration = true; - this.functionNode = node; - } else if ( node.type === 'VariableDeclarator' && node.init && /FunctionExpression/.test( node.init.type ) ) { - this.isFunctionDeclaration = true; - this.functionNode = node.init; - } - } + constructor ( node, isParam ) { + this.node = node; - this.statement = statement; - this.name = null; + this.name = node.id ? node.id.name : node.name; this.exportName = null; this.isParam = isParam; this.isReassigned = false; - this.aliases = []; - - this.isUsed = false; - } - - addAlias ( declaration ) { - this.aliases.push( declaration ); - } - - addReference ( reference ) { - reference.declaration = this; - this.name = reference.name; // TODO handle differences of opinion - - if ( reference.isReassignment ) this.isReassigned = true; - } - - render ( es6 ) { - if ( es6 ) return this.name; - if ( !this.isReassigned || !this.exportName ) return this.name; - - return `exports.${this.exportName}`; } - run ( strongDependencies ) { - if ( this.tested ) return this.hasSideEffects; + activate () { + if ( this.activated ) return; + this.activated = true; - - if ( !this.functionNode ) { - this.hasSideEffects = true; // err on the side of caution. TODO handle unambiguous `var x; x = y => z` cases - } else { - if ( this.running ) return true; // short-circuit infinite loop - this.running = true; - - this.hasSideEffects = run( this.functionNode.body, this.functionNode._scope, this.statement, strongDependencies, false ); - - this.running = false; - } - - this.tested = true; - return this.hasSideEffects; - } - - use () { - if ( this.isUsed ) return; - - this.isUsed = true; - if ( this.statement ) this.statement.mark(); - - this.aliases.forEach( use ); - } -} - -export class SyntheticDefaultDeclaration { - constructor ( node, statement, name ) { - this.node = node; - this.statement = statement; - this.name = name; - - this.original = null; - this.exportName = null; - this.aliases = []; - } - - addAlias ( declaration ) { - this.aliases.push( declaration ); + if ( this.isParam ) return; + this.node.activate(); } addReference ( reference ) { - // Bind the reference to `this` declaration. reference.declaration = this; - // Don't change the name to `default`; it's not a valid identifier name. - if ( reference.name === 'default' ) return; - - this.name = reference.name; - } - - bind ( declaration ) { - this.original = declaration; - } - - render () { - return !this.original || this.original.isReassigned ? - this.name : - this.original.render(); - } - - run ( strongDependencies ) { - if ( this.original ) { - return this.original.run( strongDependencies ); + if ( reference.name !== this.name ) { + this.name = makeLegalIdentifier( reference.name ); // TODO handle differences of opinion } - let declaration = this.node.declaration; - while ( declaration.type === 'ParenthesizedExpression' ) declaration = declaration.expression; - - if ( /FunctionExpression/.test( declaration.type ) ) { - return run( declaration.body, this.statement.scope, this.statement, strongDependencies, false ); - } - - // otherwise assume the worst - return true; - } - - use () { - this.isUsed = true; - this.statement.mark(); - - if ( this.original ) this.original.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; + render ( es ) { + if ( es ) return this.name; + if ( !this.isReassigned || !this.exportName ) return this.name; - this.aliases.forEach( use ); + return `exports.${this.exportName}`; } } @@ -176,10 +43,9 @@ export class SyntheticNamespaceDeclaration { constructor ( module ) { this.isNamespace = true; this.module = module; - this.name = null; + this.name = module.basename(); this.needsNamespaceBlock = false; - this.aliases = []; this.originals = blank(); module.getExports().forEach( name => { @@ -187,70 +53,42 @@ export class SyntheticNamespaceDeclaration { }); } - addAlias ( declaration ) { - this.aliases.push( declaration ); - } + activate () { + this.needsNamespaceBlock = true; - addReference ( reference ) { - // if we have e.g. `foo.bar`, we can optimise - // the reference by pointing directly to `bar` - if ( reference.parts.length ) { - const ref = reference.parts.shift(); - reference.name = ref.name; - reference.end = ref.end; - - const original = this.originals[ reference.name ]; - - // throw with an informative error message if the reference doesn't exist. - if ( !original ) { - this.module.bundle.onwarn( `Export '${reference.name}' is not defined by '${this.module.id}'` ); - reference.isUndefined = true; - return; - } + // add synthetic references, in case of chained + // namespace imports + forOwn( this.originals, original => { + original.activate(); + }); + } - original.addReference( reference ); - return; - } + addReference ( node ) { + this.name = node.name; + } - // otherwise we're accessing the namespace directly, - // which means we need to mark all of this module's - // exports and render a namespace block in the bundle - if ( !this.needsNamespaceBlock ) { - this.needsNamespaceBlock = true; - this.module.bundle.internalNamespaces.push( this ); - - // add synthetic references, in case of chained - // namespace imports - forOwn( this.originals, ( original, name ) => { - original.addReference( new SyntheticReference( name ) ); - }); - } + gatherPossibleValues ( values ) { + values.add( UNKNOWN ); + } - reference.declaration = this; - this.name = reference.name; + getName () { + return this.name; } - renderBlock ( indentString ) { + renderBlock ( es, legacy, indentString ) { const members = keys( this.originals ).map( name => { const original = this.originals[ name ]; - if ( original.isReassigned ) { - return `${indentString}get ${name} () { return ${original.render()}; }`; + if ( original.isReassigned && !legacy ) { + return `${indentString}get ${name} () { return ${original.getName( es )}; }`; } - return `${indentString}${name}: ${original.render()}`; + if ( legacy && ~reservedWords.indexOf( name ) ) name = `'${name}'`; + return `${indentString}${name}: ${original.getName( es )}`; }); - return `${this.module.bundle.varOrConst} ${this.render()} = Object.freeze({\n${members.join( ',\n' )}\n});\n\n`; - } - - render () { - return this.name; - } - - use () { - forOwn( this.originals, use ); - this.aliases.forEach( use ); + const callee = legacy ? `(Object.freeze || Object)` : `Object.freeze`; + return `${this.module.bundle.varOrConst} ${this.getName( es )} = ${callee}({\n${members.join( ',\n' )}\n});\n\n`; } } @@ -261,10 +99,12 @@ export class ExternalDeclaration { this.safeName = null; this.isExternal = true; + this.activated = true; + this.isNamespace = name === '*'; } - addAlias () { + activate () { // noop } @@ -276,29 +116,25 @@ export class ExternalDeclaration { } } - render ( es6 ) { + gatherPossibleValues ( values ) { + values.add( UNKNOWN ); + } + + getName ( es ) { if ( this.name === '*' ) { return this.module.name; } if ( this.name === 'default' ) { - return this.module.exportsNamespace || ( !es6 && this.module.exportsNames ) ? + return this.module.exportsNamespace || ( !es && this.module.exportsNames ) ? `${this.module.name}__default` : this.module.name; } - return es6 ? this.safeName : `${this.module.name}.${this.name}`; - } - - run () { - return true; + return es ? this.safeName : `${this.module.name}.${this.name}`; } setSafeName ( name ) { this.safeName = name; } - - use () { - // noop? - } } diff --git a/src/ExternalModule.js b/src/ExternalModule.js index db9c06217be..e532f25b170 100644 --- a/src/ExternalModule.js +++ b/src/ExternalModule.js @@ -3,9 +3,11 @@ import makeLegalIdentifier from './utils/makeLegalIdentifier.js'; import { ExternalDeclaration } from './Declaration.js'; export default class ExternalModule { - constructor ( id ) { + constructor ( id, relativePath ) { this.id = id; - this.name = makeLegalIdentifier( id ); + this.path = relativePath; + + this.name = makeLegalIdentifier( relativePath ); this.nameSuggestions = blank(); this.mostCommonSuggestion = 0; diff --git a/src/Module.js b/src/Module.js index 175ecd542db..ecb22f85531 100644 --- a/src/Module.js +++ b/src/Module.js @@ -1,38 +1,64 @@ +import { timeStart, timeEnd } from './utils/flushTime.js'; import { parse } from 'acorn/src/index.js'; import MagicString from 'magic-string'; -import { walk } from 'estree-walker'; -import Statement from './Statement.js'; -import { blank, keys } from './utils/object.js'; +import { assign, blank, deepClone, keys } from './utils/object.js'; import { basename, extname } from './utils/path.js'; import getLocation from './utils/getLocation.js'; import makeLegalIdentifier from './utils/makeLegalIdentifier.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; -import { - SyntheticDefaultDeclaration, - SyntheticGlobalDeclaration, - SyntheticNamespaceDeclaration -} from './Declaration.js'; -import { isFalsy, isTruthy } from './ast/conditions.js'; -import { emptyBlockStatement } from './ast/create.js'; -import extractNames from './ast/extractNames.js'; +import error from './utils/error.js'; +import relativeId from './utils/relativeId.js'; +import { SyntheticNamespaceDeclaration } from './Declaration.js'; +import extractNames from './ast/utils/extractNames.js'; +import enhance from './ast/enhance.js'; +import ModuleScope from './ast/scopes/ModuleScope.js'; + +function tryParse ( code, comments, acornOptions, id ) { + try { + return parse( code, assign({ + ecmaVersion: 7, + sourceType: 'module', + onComment: ( block, text, start, end ) => comments.push({ block, text, start, end }), + preserveParens: false + }, acornOptions )); + } catch ( err ) { + err.code = 'PARSE_ERROR'; + err.file = id; // see above - not necessarily true, but true enough + err.message += ` in ${id}`; + throw err; + } +} export default class Module { - constructor ({ id, code, originalCode, ast, sourceMapChain, bundle }) { + constructor ({ id, code, originalCode, originalSourceMap, ast, sourceMapChain, resolvedIds, bundle }) { this.code = code; this.originalCode = originalCode; + this.originalSourceMap = originalSourceMap; this.sourceMapChain = sourceMapChain; + this.comments = []; + + timeStart( 'ast' ); + + this.ast = ast || tryParse( code, this.comments, bundle.acornOptions, id ); // TODO what happens to comments if AST is provided? + this.astClone = deepClone( this.ast ); + + timeEnd( 'ast' ); + this.bundle = bundle; this.id = id; + this.excludeFromSourcemap = /\0/.test( id ); + this.context = bundle.getModuleContext( id ); // all dependencies this.sources = []; this.dependencies = []; - this.resolvedIds = blank(); + this.resolvedIds = resolvedIds || blank(); // imports and exports, indexed by local name this.imports = blank(); this.exports = blank(); + this.exportsAll = blank(); this.reexports = blank(); this.exportAllSources = []; @@ -41,7 +67,7 @@ export default class Module { // By default, `id` is the filename. Custom resolvers and loaders // can change that, but it makes sense to use it for the source filename this.magicString = new MagicString( code, { - filename: id, + filename: this.excludeFromSourcemap ? null : id, // don't include plugin helpers in sourcemap indentExclusionRanges: [] }); @@ -52,17 +78,20 @@ export default class Module { this.magicString.remove( match.index, match.index + match[0].length ); } - this.comments = []; - this.statements = this.parse( ast ); - this.declarations = blank(); + this.type = 'Module'; // TODO only necessary so that Scope knows this should be treated as a function scope... messy + this.scope = new ModuleScope( this ); + + timeStart( 'analyse' ); + this.analyse(); + timeEnd( 'analyse' ); + this.strongDependencies = []; } - addExport ( statement ) { - const node = statement.node; + addExport ( node ) { const source = node.source && node.source.value; // export { name } from './other.js' @@ -110,7 +139,7 @@ export default class Module { }; // create a synthetic declaration - this.declarations.default = new SyntheticDefaultDeclaration( node, statement, identifier || this.basename() ); + //this.declarations.default = new SyntheticDefaultDeclaration( node, identifier || this.basename() ); } // export var { foo, bar } = ... @@ -118,7 +147,7 @@ export default class Module { // export var a = 1, b = 2, c = 3; // export function foo () {} else if ( node.declaration ) { - let declaration = node.declaration; + const declaration = node.declaration; if ( declaration.type === 'VariableDeclaration' ) { declaration.declarations.forEach( decl => { @@ -144,7 +173,13 @@ export default class Module { throw new Error( `A module cannot have multiple exports with the same name ('${exportedName}')` ); } - this.exports[ exportedName ] = { localName }; + // `export { default as foo }` – special case. We want importers + // to use the UnboundDefaultExport proxy, not the original declaration + if ( exportedName === 'default' ) { + this.exports[ exportedName ] = { localName: 'default' }; + } else { + this.exports[ exportedName ] = { localName }; + } }); } else { this.bundle.onwarn( `Module ${this.id} has an empty export declaration` ); @@ -152,8 +187,7 @@ export default class Module { } } - addImport ( statement ) { - const node = statement.node; + addImport ( node ) { const source = node.source.value; if ( !~this.sources.indexOf( source ) ) this.sources.push( source ); @@ -172,22 +206,26 @@ export default class Module { const isNamespace = specifier.type === 'ImportNamespaceSpecifier'; const name = isDefault ? 'default' : isNamespace ? '*' : specifier.imported.name; - this.imports[ localName ] = { source, name, module: null }; + this.imports[ localName ] = { source, specifier, name, module: null }; }); } analyse () { + enhance( this.ast, this, this.comments ); + // discover this module's imports and exports - this.statements.forEach( statement => { - if ( statement.isImportDeclaration ) this.addImport( statement ); - else if ( statement.isExportDeclaration ) this.addExport( statement ); + let lastNode; - statement.firstPass(); + for ( const node of this.ast.body ) { + if ( node.isImportDeclaration ) { + this.addImport( node ); + } else if ( node.isExportDeclaration ) { + this.addExport( node ); + } - statement.scope.eachDeclaration( ( name, declaration ) => { - this.declarations[ name ] = declaration; - }); - }); + if ( lastNode ) lastNode.next = node.leadingCommentStart || node.start; + lastNode = node; + } } basename () { @@ -197,81 +235,53 @@ export default class Module { return makeLegalIdentifier( ext ? base.slice( 0, -ext.length ) : base ); } - bindAliases () { - keys( this.declarations ).forEach( name => { - if ( name === '*' ) return; - - const declaration = this.declarations[ name ]; - const statement = declaration.statement; - - if ( !statement || statement.node.type !== 'VariableDeclaration' ) return; - - const init = statement.node.declarations[0].init; - if ( !init || init.type === 'FunctionExpression' ) return; - - statement.references.forEach( reference => { - if ( reference.name === name ) return; - - const otherDeclaration = this.trace( reference.name ); - if ( otherDeclaration ) otherDeclaration.addAlias( declaration ); - }); - }); - } - bindImportSpecifiers () { [ this.imports, this.reexports ].forEach( specifiers => { keys( specifiers ).forEach( name => { const specifier = specifiers[ name ]; const id = this.resolvedIds[ specifier.source ]; - specifier.module = this.bundle.moduleById[ id ]; + specifier.module = this.bundle.moduleById.get( id ); }); }); this.exportAllModules = this.exportAllSources.map( source => { const id = this.resolvedIds[ source ]; - return this.bundle.moduleById[ id ]; + return this.bundle.moduleById.get( id ); }); this.sources.forEach( source => { const id = this.resolvedIds[ source ]; - const module = this.bundle.moduleById[ id ]; + const module = this.bundle.moduleById.get( id ); if ( !module.isExternal ) this.dependencies.push( module ); }); } bindReferences () { - if ( this.declarations.default ) { - if ( this.exports.default.identifier ) { - const declaration = this.trace( this.exports.default.identifier ); - if ( declaration ) this.declarations.default.bind( declaration ); - } + for ( const node of this.ast.body ) { + node.bind( this.scope ); } - this.statements.forEach( statement => { - // skip `export { foo, bar, baz }`... - if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.specifiers.length ) { - // ...unless this is the entry module - if ( this !== this.bundle.entryModule ) return; - } + // if ( this.declarations.default ) { + // if ( this.exports.default.identifier ) { + // const declaration = this.trace( this.exports.default.identifier ); + // if ( declaration ) this.declarations.default.bind( declaration ); + // } + // } + } - statement.references.forEach( reference => { - const declaration = reference.scope.findDeclaration( reference.name ) || - this.trace( reference.name ); + findParent () { + // TODO what does it mean if we're here? + return null; + } - if ( declaration ) { - declaration.addReference( reference ); - } else { - // TODO handle globals - this.bundle.assumedGlobals[ reference.name ] = true; - } - }); - }); + findScope () { + return this.scope; } getExports () { - let exports = blank(); + const exports = blank(); keys( this.exports ).forEach( name => { exports[ name ] = true; @@ -282,6 +292,8 @@ export default class Module { }); this.exportAllModules.forEach( module => { + if ( module.isExternal ) return; // TODO + module.getExports().forEach( name => { if ( name !== 'default' ) exports[ name ] = true; }); @@ -298,347 +310,46 @@ export default class Module { return this.declarations['*']; } - parse ( ast ) { - // The ast can be supplied programmatically (but usually won't be) - if ( !ast ) { - // Try to extract a list of top-level statements/declarations. If - // the parse fails, attach file info and abort - try { - ast = parse( this.code, { - ecmaVersion: 6, - sourceType: 'module', - onComment: ( block, text, start, end ) => this.comments.push({ block, text, start, end }), - preserveParens: true - }); - } catch ( err ) { - err.code = 'PARSE_ERROR'; - err.file = this.id; // see above - not necessarily true, but true enough - err.message += ` in ${this.id}`; - throw err; - } - } - - 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 ); - }, - - 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; - } - } - } - }); - - let statements = []; - let lastChar = 0; - let commentIndex = 0; - - ast.body.forEach( node => { - if ( node.type === 'EmptyStatement' ) return; - - if ( - node.type === 'ExportNamedDeclaration' && - node.declaration && - node.declaration.type === 'VariableDeclaration' && - node.declaration.declarations && - node.declaration.declarations.length > 1 - ) { - // push a synthetic export declaration - const syntheticNode = { - type: 'ExportNamedDeclaration', - specifiers: node.declaration.declarations.map( declarator => { - const id = { name: declarator.id.name }; - return { - local: id, - exported: id - }; - }), - isSynthetic: true - }; - - const statement = new Statement( syntheticNode, this, node.start, node.start ); - statements.push( statement ); - - this.magicString.remove( node.start, node.declaration.start ); - node = node.declaration; - } - - // special case - top-level var declarations with multiple declarators - // should be split up. Otherwise, we may end up including code we - // don't need, just because an unwanted declarator is included - if ( node.type === 'VariableDeclaration' && node.declarations.length > 1 ) { - // remove the leading var/let/const... UNLESS the previous node - // was also a synthetic node, in which case it'll get removed anyway - const lastStatement = statements[ statements.length - 1 ]; - if ( !lastStatement || !lastStatement.node.isSynthetic ) { - this.magicString.remove( node.start, node.declarations[0].start ); - } - - node.declarations.forEach( declarator => { - const { start, end } = declarator; - - const syntheticNode = { - type: 'VariableDeclaration', - kind: node.kind, - start, - end, - declarations: [ declarator ], - isSynthetic: true - }; - - const statement = new Statement( syntheticNode, this, start, end ); - statements.push( statement ); - }); - - lastChar = node.end; // TODO account for trailing line comment - } + render ( es, legacy ) { + const magicString = this.magicString.clone(); - else { - let comment; - do { - comment = this.comments[ commentIndex ]; - if ( !comment ) break; - if ( comment.start > node.start ) break; - commentIndex += 1; - } while ( comment.end < lastChar ); - - const start = comment ? Math.min( comment.start, node.start ) : node.start; - const end = node.end; // TODO account for trailing line comment - - const statement = new Statement( node, this, start, end ); - statements.push( statement ); - - lastChar = end; - } - }); - - let i = statements.length; - let next = this.code.length; - while ( i-- ) { - statements[i].next = next; - if ( !statements[i].isSynthetic ) next = statements[i].start; + for ( const node of this.ast.body ) { + node.render( magicString, es ); } - return statements; - } - - render ( es6 ) { - let magicString = this.magicString.clone(); - - this.statements.forEach( statement => { - if ( !statement.isIncluded ) { - magicString.remove( statement.start, statement.next ); - return; - } - - statement.stringLiteralRanges.forEach( range => magicString.indentExclusionRanges.push( range ) ); - - // skip `export { foo, bar, baz }` - if ( statement.node.type === 'ExportNamedDeclaration' ) { - if ( statement.node.isSynthetic ) return; - - // skip `export { foo, bar, baz }` - if ( statement.node.specifiers.length ) { - magicString.remove( statement.start, statement.next ); - return; - } - } - - // split up/remove var declarations as necessary - if ( statement.node.type === 'VariableDeclaration' ) { - const declarator = statement.node.declarations[0]; - - if ( declarator.id.type === 'Identifier' ) { - const declaration = this.declarations[ declarator.id.name ]; - - if ( declaration.exportName && declaration.isReassigned ) { // `var foo = ...` becomes `exports.foo = ...` - magicString.remove( statement.start, declarator.init ? declarator.start : statement.next ); - if ( !declarator.init ) return; - } - } - - else { - // we handle destructuring differently, because whereas we can rewrite - // `var foo = ...` as `exports.foo = ...`, in a case like `var { a, b } = c()` - // where `a` or `b` is exported and reassigned, we have to append - // `exports.a = a;` and `exports.b = b` instead - extractNames( declarator.id ).forEach( name => { - const declaration = this.declarations[ name ]; - - if ( declaration.exportName && declaration.isReassigned ) { - magicString.insert( statement.end, `;\nexports.${name} = ${declaration.render( es6 )}` ); - } - }); - } - - if ( statement.node.isSynthetic ) { - // insert `var/let/const` if necessary - magicString.insert( statement.start, `${statement.node.kind} ` ); - magicString.overwrite( statement.end, statement.next, ';\n' ); // TODO account for trailing newlines - } - } - - let toDeshadow = blank(); - - statement.references.forEach( reference => { - const { start, end } = reference; - - if ( reference.isUndefined ) { - magicString.overwrite( start, end, 'undefined', true ); - } - - const declaration = reference.declaration; - - if ( declaration ) { - const name = declaration.render( es6 ); - - // the second part of this check is necessary because of - // namespace optimisation – name of `foo.bar` could be `bar` - if ( reference.name === name && name.length === end - start ) return; - - reference.rewritten = true; - - // prevent local variables from shadowing renamed references - const identifier = name.match( /[^\.]+/ )[0]; - if ( reference.scope.contains( identifier ) ) { - toDeshadow[ identifier ] = `${identifier}$$`; // TODO more robust mechanism - } - - if ( reference.isShorthandProperty ) { - magicString.insert( end, `: ${name}` ); - } else { - magicString.overwrite( start, end, name, true ); - } - } - }); - - if ( keys( toDeshadow ).length ) { - statement.references.forEach( reference => { - if ( !reference.rewritten && reference.name in toDeshadow ) { - const replacement = toDeshadow[ reference.name ]; - magicString.overwrite( reference.start, reference.end, reference.isShorthandProperty ? `${reference.name}: ${replacement}` : replacement, true ); - } - }); - } - - // modify exports as necessary - if ( statement.isExportDeclaration ) { - // remove `export` from `export var foo = 42` - // TODO: can we do something simpler here? - // we just want to remove `export`, right? - if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration' ) { - const name = extractNames( statement.node.declaration.declarations[ 0 ].id )[ 0 ]; - const declaration = this.declarations[ name ]; - - if ( !declaration ) throw new Error( `Missing declaration for ${name}!` ); - - const end = declaration.exportName && declaration.isReassigned ? - statement.node.declaration.declarations[0].start : - statement.node.declaration.start; - - magicString.remove( statement.node.start, end ); - } - - else if ( statement.node.type === 'ExportAllDeclaration' ) { - // TODO: remove once `export * from 'external'` is supported. - magicString.remove( statement.start, statement.next ); - } - - // remove `export` from `export class Foo {...}` or `export default Foo` - // TODO default exports need different treatment - else if ( statement.node.declaration.id ) { - magicString.remove( statement.node.start, statement.node.declaration.start ); - } - - else if ( statement.node.type === 'ExportDefaultDeclaration' ) { - const defaultDeclaration = this.declarations.default; - - // prevent `var foo = foo` - if ( defaultDeclaration.original && !defaultDeclaration.original.isReassigned ) { - magicString.remove( statement.start, statement.next ); - return; - } - - const defaultName = defaultDeclaration.render(); - - // prevent `var undefined = sideEffectyDefault(foo)` - if ( !defaultDeclaration.exportName && !defaultDeclaration.isUsed ) { - magicString.remove( statement.start, statement.node.declaration.start ); - return; - } - - // anonymous functions should be converted into declarations - if ( statement.node.declaration.type === 'FunctionExpression' ) { - magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${defaultName}` ); - } else { - magicString.overwrite( statement.node.start, statement.node.declaration.start, `${this.bundle.varOrConst} ${defaultName} = ` ); - } - } - - else { - throw new Error( 'Unhandled export' ); - } - } - }); - - // add namespace block if necessary - const namespace = this.declarations['*']; - if ( namespace && namespace.needsNamespaceBlock ) { - magicString.append( '\n\n' + namespace.renderBlock( magicString.getIndentString() ) ); + if ( this.namespace().needsNamespaceBlock ) { + magicString.append( '\n\n' + this.namespace().renderBlock( es, legacy, '\t' ) ); // TODO use correct indentation } return magicString.trim(); } - /** - * 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; + run () { + for ( const node of this.ast.body ) { + if ( node.hasEffects( this.scope ) ) { + node.run( this.scope ); + } } + } - let marked = false; - - this.statements.forEach( statement => { - marked = statement.run( this.strongDependencies ) || marked; - }); - - return marked; + toJSON () { + return { + id: this.id, + dependencies: this.dependencies.map( module => module.id ), + code: this.code, + originalCode: this.originalCode, + ast: this.astClone, + sourceMapChain: this.sourceMapChain, + resolvedIds: this.resolvedIds + }; } trace ( name ) { - if ( name in this.declarations ) return this.declarations[ name ]; + // TODO this is slightly circular + if ( name in this.scope.declarations ) { + return this.scope.declarations[ name ]; + } + if ( name in this.imports ) { const importDeclaration = this.imports[ name ]; const otherModule = importDeclaration.module; @@ -649,7 +360,14 @@ export default class Module { const declaration = otherModule.traceExport( importDeclaration.name ); - if ( !declaration ) throw new Error( `Module ${otherModule.id} does not export ${importDeclaration.name} (imported by ${this.id})` ); + if ( !declaration ) { + error({ + message: `'${importDeclaration.name}' is not exported by ${relativeId( otherModule.id )} (imported by ${relativeId( this.id )}). For help fixing this error see https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module`, + file: this.id, + loc: getLocation( this.code, importDeclaration.specifier.start ) + }); + } + return declaration; } @@ -663,10 +381,11 @@ export default class Module { const declaration = reexportDeclaration.module.traceExport( reexportDeclaration.localName ); if ( !declaration ) { - const err = new Error( `'${reexportDeclaration.localName}' is not exported by '${reexportDeclaration.module.id}' (imported by '${this.id}')` ); - err.file = this.id; - err.loc = getLocation( this.code, reexportDeclaration.start ); - throw err; + error({ + message: `'${reexportDeclaration.localName}' is not exported by '${reexportDeclaration.module.id}' (imported by '${this.id}')`, + file: this.id, + loc: getLocation( this.code, reexportDeclaration.start ) + }); } return declaration; @@ -677,12 +396,11 @@ export default class Module { 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 ) ); + return declaration || this.bundle.scope.findDeclaration( name ); } + if ( name === 'default' ) return; + for ( let i = 0; i < this.exportAllModules.length; i += 1 ) { const module = this.exportAllModules[i]; const declaration = module.traceExport( name ); diff --git a/src/Reference.js b/src/Reference.js deleted file mode 100644 index 5c5c3e9b66b..00000000000 --- a/src/Reference.js +++ /dev/null @@ -1,30 +0,0 @@ -export class Reference { - constructor ( node, scope, statement ) { - this.node = node; - this.scope = scope; - this.statement = statement; - - this.declaration = null; // bound later - - this.parts = []; - - let root = node; - while ( root.type === 'MemberExpression' ) { - this.parts.unshift( root.property ); - root = root.object; - } - - this.name = root.name; - - this.start = node.start; - this.end = node.start + this.name.length; // can be overridden in the case of namespace members - this.rewritten = false; - } -} - -export class SyntheticReference { - constructor ( name ) { - this.name = name; - this.parts = []; - } -} diff --git a/src/Statement.js b/src/Statement.js deleted file mode 100644 index 3c00c363d92..00000000000 --- a/src/Statement.js +++ /dev/null @@ -1,155 +0,0 @@ -import { walk } from 'estree-walker'; -import Scope from './ast/Scope.js'; -import attachScopes from './ast/attachScopes.js'; -import modifierNodes, { isModifierNode } from './ast/modifierNodes.js'; -import isFunctionDeclaration from './ast/isFunctionDeclaration.js'; -import isReference from './ast/isReference.js'; -import getLocation from './utils/getLocation.js'; -import run from './utils/run.js'; -import { Reference } from './Reference.js'; - -export default class Statement { - constructor ( node, module, start, end ) { - this.node = node; - this.module = module; - this.start = start; - this.end = end; - this.next = null; // filled in later - - this.scope = new Scope({ statement: this }); - - this.references = []; - this.stringLiteralRanges = []; - - this.isIncluded = false; - this.ran = false; - - this.isImportDeclaration = node.type === 'ImportDeclaration'; - this.isExportDeclaration = /^Export/.test( node.type ); - this.isReexportDeclaration = this.isExportDeclaration && !!node.source; - - this.isFunctionDeclaration = isFunctionDeclaration( node ) || - this.isExportDeclaration && isFunctionDeclaration( node.declaration ); - } - - firstPass () { - if ( this.isImportDeclaration ) return; // nothing to analyse - - // attach scopes - attachScopes( this ); - - // find references - const statement = this; - let { module, references, scope, stringLiteralRanges } = this; - let readDepth = 0; - - walk( this.node, { - enter ( node, parent, prop ) { - // warn about eval - if ( node.type === 'CallExpression' && node.callee.name === 'eval' && !scope.contains( 'eval' ) ) { - // 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 - 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 ]); - } - - if ( node._scope ) scope = node._scope; - if ( /Function/.test( node.type ) ) readDepth += 1; - - let isReassignment; - - if ( parent && isModifierNode( parent ) ) { - let subject = parent[ modifierNodes[ parent.type ] ]; - - if ( node === subject ) { - let depth = 0; - - while ( subject.type === 'MemberExpression' ) { - subject = subject.object; - depth += 1; - } - - const importDeclaration = module.imports[ subject.name ]; - - if ( !scope.contains( subject.name ) && importDeclaration ) { - const minDepth = importDeclaration.name === '*' ? - 2 : // cannot do e.g. `namespace.foo = bar` - 1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine - - if ( depth < minDepth ) { - const err = new Error( `Illegal reassignment to import '${subject.name}'` ); - err.file = module.id; - err.loc = getLocation( module.magicString.original, subject.start ); - throw err; - } - } - - isReassignment = !depth; - } - } - - if ( isReference( node, parent ) ) { - // function declaration IDs are a special case – they're associated - // with the parent scope - const referenceScope = parent.type === 'FunctionDeclaration' && node === parent.id ? - scope.parent : - 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 ); - reference.isReassignment = isReassignment; - reference.isShorthandProperty = isShorthandProperty; - references.push( reference ); - - this.skip(); // don't descend from `foo.bar.baz` into `foo.bar` - } - }, - leave ( node ) { - if ( node._scope ) scope = scope.parent; - if ( /Function/.test( node.type ) ) readDepth -= 1; - } - }); - } - - mark () { - if ( this.isIncluded ) return; // prevent infinite loops - this.isIncluded = true; - - this.references.forEach( reference => { - if ( reference.declaration ) reference.declaration.use(); - }); - } - - run ( strongDependencies ) { - if ( ( this.ran && this.isIncluded ) || this.isImportDeclaration || this.isFunctionDeclaration ) return; - this.ran = true; - - if ( run( this.node, this.scope, this, strongDependencies, false ) ) { - this.mark(); - return true; - } - } - - source () { - return this.module.source.slice( this.start, this.end ); - } - - toString () { - return this.module.magicString.slice( this.start, this.end ); - } -} diff --git a/src/ast/Node.js b/src/ast/Node.js new file mode 100644 index 00000000000..6a80ede4b86 --- /dev/null +++ b/src/ast/Node.js @@ -0,0 +1,100 @@ +import { UNKNOWN } from './values.js'; +import getLocation from '../utils/getLocation.js'; + +export default class Node { + bind ( scope ) { + this.eachChild( child => child.bind( this.scope || scope ) ); + } + + eachChild ( callback ) { + for ( const key of this.keys ) { + if ( this.shorthand && key === 'key' ) continue; // key and value are the same + + const value = this[ key ]; + + if ( value ) { + if ( 'length' in value ) { + for ( const child of value ) { + if ( child ) callback( child ); + } + } else if ( value ) { + callback( value ); + } + } + } + } + + findParent ( selector ) { + return selector.test( this.type ) ? this : this.parent.findParent( selector ); + } + + // TODO abolish findScope. if a node needs to store scope, store it + findScope ( functionScope ) { + return this.parent.findScope( functionScope ); + } + + gatherPossibleValues ( values ) { + //this.eachChild( child => child.gatherPossibleValues( values ) ); + values.add( UNKNOWN ); + } + + getValue () { + return UNKNOWN; + } + + hasEffects ( scope ) { + if ( this.scope ) scope = this.scope; + + for ( const key of this.keys ) { + const value = this[ key ]; + + if ( value ) { + if ( 'length' in value ) { + for ( const child of value ) { + if ( child && child.hasEffects( scope ) ) { + return true; + } + } + } else if ( value && value.hasEffects( scope ) ) { + return true; + } + } + } + } + + initialise ( scope ) { + this.eachChild( child => child.initialise( this.scope || scope ) ); + } + + insertSemicolon ( code ) { + if ( code.original[ this.end - 1 ] !== ';' ) { + code.insertLeft( this.end, ';' ); + } + } + + locate () { + // useful for debugging + const location = getLocation( this.module.code, this.start ); + location.file = this.module.id; + location.toString = () => JSON.stringify( location ); + + return location; + } + + render ( code, es ) { + this.eachChild( child => child.render( code, es ) ); + } + + run ( scope ) { + if ( this.ran ) return; + this.ran = true; + + this.eachChild( child => { + child.run( this.scope || scope ); + }); + } + + toString () { + return this.module.code.slice( this.start, this.end ); + } +} diff --git a/src/ast/Scope.js b/src/ast/Scope.js deleted file mode 100644 index 0dc48ec42e4..00000000000 --- a/src/ast/Scope.js +++ /dev/null @@ -1,52 +0,0 @@ -import { blank, keys } from '../utils/object.js'; -import Declaration from '../Declaration.js'; -import extractNames from './extractNames.js'; - -export default class Scope { - constructor ( options ) { - options = options || {}; - - this.parent = options.parent; - this.statement = options.statement || this.parent.statement; - this.isBlockScope = !!options.block; - this.isTopLevel = !this.parent || ( this.parent.isTopLevel && this.isBlockScope ); - - this.declarations = blank(); - - if ( options.params ) { - options.params.forEach( param => { - extractNames( param ).forEach( name => { - this.declarations[ name ] = new Declaration( param, true, this.statement ); - }); - }); - } - } - - addDeclaration ( node, isBlockDeclaration, isVar ) { - if ( !isBlockDeclaration && this.isBlockScope ) { - // it's a `var` or function node, and this - // is a block scope, so we need to go up - this.parent.addDeclaration( node, isBlockDeclaration, isVar ); - } else { - extractNames( node.id ).forEach( name => { - this.declarations[ name ] = new Declaration( node, false, this.statement ); - }); - } - } - - contains ( name ) { - return this.declarations[ name ] || - ( this.parent ? this.parent.contains( name ) : false ); - } - - eachDeclaration ( fn ) { - keys( this.declarations ).forEach( key => { - fn( key, this.declarations[ key ] ); - }); - } - - findDeclaration ( name ) { - return this.declarations[ name ] || - ( this.parent && this.parent.findDeclaration( name ) ); - } -} diff --git a/src/ast/attachScopes.js b/src/ast/attachScopes.js deleted file mode 100644 index 51fc28aec48..00000000000 --- a/src/ast/attachScopes.js +++ /dev/null @@ -1,78 +0,0 @@ -import { walk } from 'estree-walker'; -import Scope from './Scope.js'; - -const blockDeclarations = { - 'const': true, - 'let': true -}; - -export default function attachScopes ( statement ) { - let { node, scope } = statement; - - walk( node, { - enter ( node, parent ) { - // function foo () {...} - // class Foo {...} - if ( /(Function|Class)Declaration/.test( node.type ) ) { - scope.addDeclaration( node, false, false ); - } - - // var foo = 1, bar = 2 - if ( node.type === 'VariableDeclaration' ) { - const isBlockDeclaration = blockDeclarations[ node.kind ]; - - node.declarations.forEach( declarator => { - scope.addDeclaration( declarator, isBlockDeclaration, true ); - }); - } - - let newScope; - - // create new function scope - if ( /(Function|Class)/.test( node.type ) ) { - newScope = new Scope({ - parent: scope, - block: false, - params: node.params - }); - - // named function expressions - the name is considered - // part of the function's scope - if ( /(Function|Class)Expression/.test( node.type ) && node.id ) { - newScope.addDeclaration( node, false, false ); - } - } - - // create new block scope - if ( node.type === 'BlockStatement' && ( !parent || !/Function/.test( parent.type ) ) ) { - newScope = new Scope({ - parent: scope, - block: true - }); - } - - // catch clause has its own block scope - if ( node.type === 'CatchClause' ) { - newScope = new Scope({ - parent: scope, - params: [ node.param ], - block: true - }); - } - - if ( newScope ) { - Object.defineProperty( node, '_scope', { - value: newScope, - configurable: true - }); - - scope = newScope; - } - }, - leave ( node ) { - if ( node._scope ) { - scope = scope.parent; - } - } - }); -} diff --git a/src/ast/conditions.js b/src/ast/conditions.js deleted file mode 100644 index b21e4d41947..00000000000 --- a/src/ast/conditions.js +++ /dev/null @@ -1,38 +0,0 @@ -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 ) -}; diff --git a/src/ast/create.js b/src/ast/create.js deleted file mode 100644 index e767dbdec3b..00000000000 --- a/src/ast/create.js +++ /dev/null @@ -1,7 +0,0 @@ -export function emptyBlockStatement ( start, end ) { - return { - start, end, - type: 'BlockStatement', - body: [] - }; -} diff --git a/src/ast/enhance.js b/src/ast/enhance.js new file mode 100644 index 00000000000..6a86daba7cc --- /dev/null +++ b/src/ast/enhance.js @@ -0,0 +1,63 @@ +import nodes from './nodes/index.js'; +import Node from './Node.js'; +import keys from './keys.js'; + +const newline = /\n/; + +export default function enhance ( ast, module, comments ) { + enhanceNode( ast, module, module, module.magicString ); + + let comment = comments.shift(); + + for ( const node of ast.body ) { + if ( comment && ( comment.start < node.start ) ) { + node.leadingCommentStart = comment.start; + } + + while ( comment && comment.end < node.end ) comment = comments.shift(); + + // if the next comment is on the same line as the end of the node, + // treat is as a trailing comment + if ( comment && !newline.test( module.code.slice( node.end, comment.start ) ) ) { + node.trailingCommentEnd = comment.end; // TODO is node.trailingCommentEnd used anywhere? + comment = comments.shift(); + } + + node.initialise( module.scope ); + } +} + +function enhanceNode ( raw, parent, module, code ) { + if ( !raw ) return; + + if ( 'length' in raw ) { + for ( let i = 0; i < raw.length; i += 1 ) { + enhanceNode( raw[i], parent, module, code ); + } + + return; + } + + // with e.g. shorthand properties, key and value are + // the same node. We don't want to enhance an object twice + if ( raw.__enhanced ) return; + raw.__enhanced = true; + + if ( !keys[ raw.type ] ) { + keys[ raw.type ] = Object.keys( raw ).filter( key => typeof raw[ key ] === 'object' ); + } + + raw.parent = parent; + raw.module = module; + raw.keys = keys[ raw.type ]; + + code.addSourcemapLocation( raw.start ); + code.addSourcemapLocation( raw.end ); + + for ( const key of keys[ raw.type ] ) { + enhanceNode( raw[ key ], raw, module, code ); + } + + const type = nodes[ raw.type ] || Node; + raw.__proto__ = type.prototype; +} diff --git a/src/ast/isFunctionDeclaration.js b/src/ast/isFunctionDeclaration.js deleted file mode 100644 index a1573e76d51..00000000000 --- a/src/ast/isFunctionDeclaration.js +++ /dev/null @@ -1,6 +0,0 @@ -export default function isFunctionDeclaration ( node ) { - if ( !node ) return false; - - return node.type === 'FunctionDeclaration' || - ( node.type === 'VariableDeclaration' && node.init && /FunctionExpression/.test( node.init.type ) ); -} diff --git a/src/ast/keys.js b/src/ast/keys.js new file mode 100644 index 00000000000..194ccf777dc --- /dev/null +++ b/src/ast/keys.js @@ -0,0 +1,4 @@ +export default { + Program: [ 'body' ], + Literal: [] +}; diff --git a/src/ast/modifierNodes.js b/src/ast/modifierNodes.js deleted file mode 100644 index 3696fd169f5..00000000000 --- a/src/ast/modifierNodes.js +++ /dev/null @@ -1,19 +0,0 @@ -const modifierNodes = { - AssignmentExpression: 'left', - UpdateExpression: 'argument', - UnaryExpression: 'argument' -}; - -export default modifierNodes; - -export function isModifierNode ( node ) { - if ( !( node.type in modifierNodes ) ) { - return false; - } - - if ( node.type === 'UnaryExpression' ) { - return node.operator === 'delete'; - } - - return true; -} diff --git a/src/ast/nodes/ArrayExpression.js b/src/ast/nodes/ArrayExpression.js new file mode 100644 index 00000000000..ff60919aca3 --- /dev/null +++ b/src/ast/nodes/ArrayExpression.js @@ -0,0 +1,8 @@ +import Node from '../Node.js'; +import { ARRAY } from '../values.js'; + +export default class ArrayExpression extends Node { + gatherPossibleValues ( values ) { + values.add( ARRAY ); + } +} diff --git a/src/ast/nodes/ArrowFunctionExpression.js b/src/ast/nodes/ArrowFunctionExpression.js new file mode 100644 index 00000000000..8d9a3d2e878 --- /dev/null +++ b/src/ast/nodes/ArrowFunctionExpression.js @@ -0,0 +1,38 @@ +import Node from '../Node.js'; +import Scope from '../scopes/Scope.js'; +import extractNames from '../utils/extractNames.js'; + +export default class ArrowFunctionExpression extends Node { + bind ( scope ) { + super.bind( this.scope || scope ); + } + + findScope ( functionScope ) { + return this.scope || this.parent.findScope( functionScope ); + } + + hasEffects () { + return false; + } + + initialise ( scope ) { + if ( this.body.type === 'BlockStatement' ) { + this.body.createScope( scope ); + this.scope = this.body.scope; + } else { + this.scope = new Scope({ + parent: scope, + isBlockScope: false, + isLexicalBoundary: false + }); + + for ( const param of this.params ) { + for ( const name of extractNames( param ) ) { + this.scope.addDeclaration( name, null, null, true ); // TODO ugh + } + } + } + + super.initialise( this.scope ); + } +} diff --git a/src/ast/nodes/AssignmentExpression.js b/src/ast/nodes/AssignmentExpression.js new file mode 100644 index 00000000000..bbbb7d0ab96 --- /dev/null +++ b/src/ast/nodes/AssignmentExpression.js @@ -0,0 +1,50 @@ +import Node from '../Node.js'; +import disallowIllegalReassignment from './shared/disallowIllegalReassignment.js'; +import isUsedByBundle from './shared/isUsedByBundle.js'; +import isProgramLevel from '../utils/isProgramLevel.js'; +import { NUMBER, STRING } from '../values.js'; + +export default class AssignmentExpression extends Node { + bind ( scope ) { + const subject = this.left; + + this.subject = subject; + disallowIllegalReassignment( scope, subject ); + + if ( subject.type === 'Identifier' ) { + const declaration = scope.findDeclaration( subject.name ); + declaration.isReassigned = true; + + if ( declaration.possibleValues ) { // TODO this feels hacky + if ( this.operator === '=' ) { + declaration.possibleValues.add( this.right ); + } else if ( this.operator === '+=' ) { + declaration.possibleValues.add( STRING ).add( NUMBER ); + } else { + declaration.possibleValues.add( NUMBER ); + } + } + } + + super.bind( scope ); + } + + hasEffects ( scope ) { + const hasEffects = this.isUsedByBundle() || this.right.hasEffects( scope ); + return hasEffects; + } + + initialise ( scope ) { + this.scope = scope; + + if ( isProgramLevel( this ) ) { + this.module.bundle.dependentExpressions.push( this ); + } + + super.initialise( scope ); + } + + isUsedByBundle () { + return isUsedByBundle( this.scope, this.subject ); + } +} diff --git a/src/ast/nodes/BinaryExpression.js b/src/ast/nodes/BinaryExpression.js new file mode 100644 index 00000000000..da3d4da3a28 --- /dev/null +++ b/src/ast/nodes/BinaryExpression.js @@ -0,0 +1,38 @@ +import Node from '../Node.js'; +import { UNKNOWN } from '../values.js'; + +const operators = { + '==': ( left, right ) => left == right, + '!=': ( left, right ) => left != right, + '===': ( left, right ) => left === right, + '!==': ( left, right ) => left !== right, + '<': ( left, right ) => left < right, + '<=': ( left, right ) => left <= right, + '>': ( left, right ) => left > right, + '>=': ( left, right ) => left >= right, + '<<': ( left, right ) => left << right, + '>>': ( left, right ) => left >> right, + '>>>': ( left, right ) => left >>> right, + '+': ( left, right ) => left + right, + '-': ( left, right ) => left - right, + '*': ( left, right ) => left * right, + '/': ( left, right ) => left / right, + '%': ( left, right ) => left % right, + '|': ( left, right ) => left | right, + '^': ( left, right ) => left ^ right, + '&': ( left, right ) => left & right, + in: ( left, right ) => left in right, + instanceof: ( left, right ) => left instanceof right +}; + +export default class BinaryExpression extends Node { + getValue () { + const leftValue = this.left.getValue(); + if ( leftValue === UNKNOWN ) return UNKNOWN; + + const rightValue = this.right.getValue(); + if ( rightValue === UNKNOWN ) return UNKNOWN; + + return operators[ this.operator ]( leftValue, rightValue ); + } +} diff --git a/src/ast/nodes/BlockStatement.js b/src/ast/nodes/BlockStatement.js new file mode 100644 index 00000000000..d83d321ef65 --- /dev/null +++ b/src/ast/nodes/BlockStatement.js @@ -0,0 +1,59 @@ +import Statement from './shared/Statement.js'; +import Scope from '../scopes/Scope.js'; +import extractNames from '../utils/extractNames.js'; + +export default class BlockStatement extends Statement { + bind () { + for ( const node of this.body ) { + node.bind( this.scope ); + } + } + + createScope ( parent ) { + this.parentIsFunction = /Function/.test( this.parent.type ); + this.isFunctionBlock = this.parentIsFunction || this.parent.type === 'Module'; + + this.scope = new Scope({ + parent, + isBlockScope: !this.isFunctionBlock, + isLexicalBoundary: this.isFunctionBlock && this.parent.type !== 'ArrowFunctionExpression', + owner: this // TODO is this used anywhere? + }); + + const params = this.parent.params || ( this.parent.type === 'CatchClause' && [ this.parent.param ] ); + + if ( params && params.length ) { + params.forEach( node => { + extractNames( node ).forEach( name => { + this.scope.addDeclaration( name, node, false, true ); + }); + }); + } + } + + findScope ( functionScope ) { + return functionScope && !this.isFunctionBlock ? this.parent.findScope( functionScope ) : this.scope; + } + + initialise ( scope ) { + if ( !this.scope ) this.createScope( scope ); // scope can be created early in some cases, e.g for (let i... ) + + let lastNode; + for ( const node of this.body ) { + node.initialise( this.scope ); + + if ( lastNode ) lastNode.next = node.start; + lastNode = node; + } + } + + render ( code, es ) { + if (this.body.length) { + for ( const node of this.body ) { + node.render( code, es ); + } + } else { + Statement.prototype.render.call(this, code, es); + } + } +} diff --git a/src/ast/nodes/CallExpression.js b/src/ast/nodes/CallExpression.js new file mode 100644 index 00000000000..720e866c53d --- /dev/null +++ b/src/ast/nodes/CallExpression.js @@ -0,0 +1,43 @@ +import getLocation from '../../utils/getLocation.js'; +import error from '../../utils/error.js'; +import Node from '../Node.js'; +import isProgramLevel from '../utils/isProgramLevel.js'; +import callHasEffects from './shared/callHasEffects.js'; + +export default class CallExpression extends Node { + bind ( scope ) { + if ( this.callee.type === 'Identifier' ) { + const declaration = scope.findDeclaration( this.callee.name ); + + if ( declaration.isNamespace ) { + error({ + message: `Cannot call a namespace ('${this.callee.name}')`, + file: this.module.id, + pos: this.start, + loc: getLocation( this.module.code, this.start ) + }); + } + + if ( this.callee.name === 'eval' && declaration.isGlobal ) { + this.module.bundle.onwarn( `Use of \`eval\` (in ${this.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` ); + } + } + + super.bind( scope ); + } + + hasEffects ( scope ) { + return callHasEffects( scope, this.callee ); + } + + initialise ( scope ) { + if ( isProgramLevel( this ) ) { + this.module.bundle.dependentExpressions.push( this ); + } + super.initialise( scope ); + } + + isUsedByBundle () { + return this.hasEffects( this.findScope() ); + } +} diff --git a/src/ast/nodes/ClassDeclaration.js b/src/ast/nodes/ClassDeclaration.js new file mode 100644 index 00000000000..f1a1daadf6b --- /dev/null +++ b/src/ast/nodes/ClassDeclaration.js @@ -0,0 +1,45 @@ +import Node from '../Node.js'; + +// TODO is this basically identical to FunctionDeclaration? +export default class ClassDeclaration extends Node { + activate () { + if ( this.activated ) return; + this.activated = true; + + if ( this.superClass ) this.superClass.run( this.scope ); + this.body.run(); + } + + addReference () { + /* noop? */ + } + + gatherPossibleValues ( values ) { + values.add( this ); + } + + getName () { + return this.name; + } + + hasEffects () { + return false; + } + + initialise ( scope ) { + this.scope = scope; + + this.name = this.id.name; + + scope.addDeclaration( this.name, this, false, false ); + super.initialise( scope ); + } + + render ( code, es ) { + if ( this.activated ) { + super.render( code, es ); + } else { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } + } +} diff --git a/src/ast/nodes/ClassExpression.js b/src/ast/nodes/ClassExpression.js new file mode 100644 index 00000000000..63f1399663b --- /dev/null +++ b/src/ast/nodes/ClassExpression.js @@ -0,0 +1,26 @@ +import Node from '../Node.js'; +import Scope from '../scopes/Scope.js'; + +export default class ClassExpression extends Node { + bind () { + super.bind( this.scope ); + } + + findScope () { + return this.scope; + } + + initialise () { + this.scope = new Scope({ + isBlockScope: true, + parent: this.parent.findScope( false ) + }); + + if ( this.id ) { + // function expression IDs belong to the child scope... + this.scope.addDeclaration( this.id.name, this, false, true ); + } + + super.initialise( this.scope ); + } +} diff --git a/src/ast/nodes/ConditionalExpression.js b/src/ast/nodes/ConditionalExpression.js new file mode 100644 index 00000000000..9c7b4445b87 --- /dev/null +++ b/src/ast/nodes/ConditionalExpression.js @@ -0,0 +1,65 @@ +import Node from '../Node.js'; +import { UNKNOWN } from '../values.js'; + +export default class ConditionalExpression extends Node { + initialise ( scope ) { + if ( this.module.bundle.treeshake ) { + this.testValue = this.test.getValue(); + + if ( this.testValue === UNKNOWN ) { + super.initialise( scope ); + } + + else if ( this.testValue ) { + this.consequent.initialise( scope ); + this.alternate = null; + } else if ( this.alternate ) { + this.alternate.initialise( scope ); + this.consequent = null; + } + } + + else { + super.initialise( scope ); + } + } + + gatherPossibleValues ( values ) { + const testValue = this.test.getValue(); + + if ( testValue === UNKNOWN ) { + values.add( this.consequent ).add( this.alternate ); + } else { + values.add( testValue ? this.consequent : this.alternate ); + } + } + + getValue () { + const testValue = this.test.getValue(); + if ( testValue === UNKNOWN ) return UNKNOWN; + + return testValue ? this.consequent.getValue() : this.alternate.getValue(); + } + + render ( code, es ) { + if ( !this.module.bundle.treeshake ) { + super.render( code, es ); + } + + else { + if ( this.testValue === UNKNOWN ) { + super.render( code, es ); + } + + else if ( this.testValue ) { + code.remove( this.start, this.consequent.start ); + code.remove( this.consequent.end, this.end ); + this.consequent.render( code, es ); + } else { + code.remove( this.start, this.alternate.start ); + code.remove( this.alternate.end, this.end ); + this.alternate.render( code, es ); + } + } + } +} diff --git a/src/ast/nodes/EmptyStatement.js b/src/ast/nodes/EmptyStatement.js new file mode 100644 index 00000000000..5f7309c0ecf --- /dev/null +++ b/src/ast/nodes/EmptyStatement.js @@ -0,0 +1,9 @@ +import Statement from './shared/Statement.js'; + +export default class EmptyStatement extends Statement { + render ( code ) { + if ( this.parent.type === 'BlockStatement' || this.parent.type === 'Program' ) { + code.remove( this.start, this.end ); + } + } +} diff --git a/src/ast/nodes/ExportAllDeclaration.js b/src/ast/nodes/ExportAllDeclaration.js new file mode 100644 index 00000000000..a0f53085dc7 --- /dev/null +++ b/src/ast/nodes/ExportAllDeclaration.js @@ -0,0 +1,11 @@ +import Node from '../Node.js'; + +export default class ExportAllDeclaration extends Node { + initialise () { + this.isExportDeclaration = true; + } + + render ( code ) { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } +} diff --git a/src/ast/nodes/ExportDefaultDeclaration.js b/src/ast/nodes/ExportDefaultDeclaration.js new file mode 100644 index 00000000000..94c2784622c --- /dev/null +++ b/src/ast/nodes/ExportDefaultDeclaration.js @@ -0,0 +1,105 @@ +import Node from '../Node.js'; + +const functionOrClassDeclaration = /^(?:Function|Class)Declaration/; + +export default class ExportDefaultDeclaration extends Node { + initialise ( scope ) { + this.isExportDeclaration = true; + this.isDefault = true; + + this.name = ( this.declaration.id && this.declaration.id.name ) || this.declaration.name || this.module.basename(); + scope.declarations.default = this; + + this.declaration.initialise( scope ); + } + + activate () { + if ( this.activated ) return; + this.activated = true; + + this.run(); + } + + addReference ( reference ) { + this.name = reference.name; + if ( this.original ) this.original.addReference( reference ); + } + + bind ( scope ) { + const name = ( this.declaration.id && this.declaration.id.name ) || this.declaration.name; + if ( name ) this.original = scope.findDeclaration( name ); + + this.declaration.bind( scope ); + } + + gatherPossibleValues ( values ) { + this.declaration.gatherPossibleValues( values ); + } + + getName ( es ) { + if ( this.original && !this.original.isReassigned ) { + return this.original.getName( es ); + } + + return this.name; + } + + // TODO this is total chaos, tidy it up + render ( code, es ) { + const treeshake = this.module.bundle.treeshake; + const name = this.getName( es ); + + // paren workaround: find first non-whitespace character position after `export default` + let declaration_start; + if ( this.declaration ) { + const statementStr = code.original.slice( this.start, this.end ); + declaration_start = this.start + statementStr.match(/^\s*export\s+default\s+/)[0].length; + } + + if ( this.shouldInclude || this.declaration.activated ) { + if ( this.activated ) { + if ( functionOrClassDeclaration.test( this.declaration.type ) ) { + if ( this.declaration.id ) { + code.remove( this.start, declaration_start ); + } else { + throw new Error( 'TODO anonymous class/function declaration' ); + } + } + + else { + if ( this.original && this.original.getName( es ) === name ) { + // prevent `var foo = foo` + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + return; // don't render children. TODO this seems like a bit of a hack + } else { + code.overwrite( this.start, declaration_start, `${this.module.bundle.varOrConst} ${name} = ` ); + } + + this.insertSemicolon( code ); + } + } else { + // remove `var foo` from `var foo = bar()`, if `foo` is unused + code.remove( this.start, declaration_start ); + } + + super.render( code, es ); + } else { + if ( treeshake ) { + if ( functionOrClassDeclaration.test( this.declaration.type ) ) { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } else { + const hasEffects = this.declaration.hasEffects( this.module.scope ); + code.remove( this.start, hasEffects ? declaration_start : this.next || this.end ); + } + } else { + code.overwrite( this.start, declaration_start, `${this.module.bundle.varOrConst} ${name} = ` ); + } + // code.remove( this.start, this.next || this.end ); + } + } + + run ( scope ) { + this.shouldInclude = true; + super.run( scope ); + } +} diff --git a/src/ast/nodes/ExportNamedDeclaration.js b/src/ast/nodes/ExportNamedDeclaration.js new file mode 100644 index 00000000000..3f9ba4e917e --- /dev/null +++ b/src/ast/nodes/ExportNamedDeclaration.js @@ -0,0 +1,80 @@ +import { find } from '../../utils/array.js'; +import Node from '../Node.js'; + +class UnboundDefaultExport { + constructor ( original ) { + this.original = original; + this.name = original.name; + } + + activate () { + if ( this.activated ) return; + this.activated = true; + + this.original.activate(); + } + + addReference ( reference ) { + this.name = reference.name; + this.original.addReference( reference ); + } + + bind ( scope ) { + this.original.bind( scope ); + } + + gatherPossibleValues ( values ) { + this.original.gatherPossibleValues( values ); + } + + getName ( es ) { + if ( this.original && !this.original.isReassigned ) { + return this.original.getName( es ); + } + + return this.name; + } +} + +export default class ExportNamedDeclaration extends Node { + initialise ( scope ) { + this.scope = scope; + this.isExportDeclaration = true; + + // special case – `export { foo as default }` should not create a live binding + const defaultExport = find( this.specifiers, specifier => specifier.exported.name === 'default' ); + if ( defaultExport ) { + const declaration = this.scope.findDeclaration( defaultExport.local.name ); + this.defaultExport = new UnboundDefaultExport( declaration ); + scope.declarations.default = this.defaultExport; + } + + if ( this.declaration ) this.declaration.initialise( scope ); + } + + bind ( scope ) { + if ( this.declaration ) this.declaration.bind( scope ); + } + + render ( code, es ) { + if ( this.declaration ) { + code.remove( this.start, this.declaration.start ); + this.declaration.render( code, es ); + } else { + const start = this.leadingCommentStart || this.start; + const end = this.next || this.end; + + if ( this.defaultExport ) { + const name = this.defaultExport.getName( es ); + const originalName = this.defaultExport.original.getName( es ); + + if ( name !== originalName ) { + code.overwrite( start, end, `var ${name} = ${originalName};` ); + return; + } + } + + code.remove( start, end ); + } + } +} diff --git a/src/ast/nodes/ExpressionStatement.js b/src/ast/nodes/ExpressionStatement.js new file mode 100644 index 00000000000..719854120ff --- /dev/null +++ b/src/ast/nodes/ExpressionStatement.js @@ -0,0 +1,8 @@ +import Statement from './shared/Statement.js'; + +export default class ExpressionStatement extends Statement { + render ( code, es ) { + super.render( code, es ); + if ( this.shouldInclude ) this.insertSemicolon( code ); + } +} diff --git a/src/ast/nodes/ForInStatement.js b/src/ast/nodes/ForInStatement.js new file mode 100644 index 00000000000..1872b963b21 --- /dev/null +++ b/src/ast/nodes/ForInStatement.js @@ -0,0 +1,22 @@ +import Statement from './shared/Statement.js'; +import assignTo from './shared/assignTo.js'; +import Scope from '../scopes/Scope.js'; +import { STRING } from '../values.js'; + +export default class ForInStatement extends Statement { + initialise ( scope ) { + if ( this.body.type === 'BlockStatement' ) { + this.body.createScope( scope ); + this.scope = this.body.scope; + } else { + this.scope = new Scope({ + parent: scope, + isBlockScope: true, + isLexicalBoundary: false + }); + } + + super.initialise( this.scope ); + assignTo( this.left, this.scope, STRING ); + } +} diff --git a/src/ast/nodes/ForOfStatement.js b/src/ast/nodes/ForOfStatement.js new file mode 100644 index 00000000000..a5225f847b7 --- /dev/null +++ b/src/ast/nodes/ForOfStatement.js @@ -0,0 +1,22 @@ +import Statement from './shared/Statement.js'; +import assignTo from './shared/assignTo.js'; +import Scope from '../scopes/Scope.js'; +import { UNKNOWN } from '../values.js'; + +export default class ForOfStatement extends Statement { + initialise ( scope ) { + if ( this.body.type === 'BlockStatement' ) { + this.body.createScope( scope ); + this.scope = this.body.scope; + } else { + this.scope = new Scope({ + parent: scope, + isBlockScope: true, + isLexicalBoundary: false + }); + } + + super.initialise( this.scope ); + assignTo( this.left, this.scope, UNKNOWN ); + } +} diff --git a/src/ast/nodes/ForStatement.js b/src/ast/nodes/ForStatement.js new file mode 100644 index 00000000000..11e98e5c18c --- /dev/null +++ b/src/ast/nodes/ForStatement.js @@ -0,0 +1,23 @@ +import Statement from './shared/Statement.js'; +import Scope from '../scopes/Scope.js'; + +export default class ForStatement extends Statement { + initialise ( scope ) { + if ( this.body.type === 'BlockStatement' ) { + this.body.createScope( scope ); + this.scope = this.body.scope; + } else { + this.scope = new Scope({ + parent: scope, + isBlockScope: true, + isLexicalBoundary: false + }); + } + + // can't use super, because we need to control the order + if ( this.init ) this.init.initialise( this.scope ); + if ( this.test ) this.test.initialise( this.scope ); + if ( this.update ) this.update.initialise( this.scope ); + this.body.initialise( this.scope ); + } +} diff --git a/src/ast/nodes/FunctionDeclaration.js b/src/ast/nodes/FunctionDeclaration.js new file mode 100644 index 00000000000..dffed953dc9 --- /dev/null +++ b/src/ast/nodes/FunctionDeclaration.js @@ -0,0 +1,53 @@ +import Node from '../Node.js'; + +export default class FunctionDeclaration extends Node { + activate () { + if ( this.activated ) return; + this.activated = true; + + const scope = this.body.scope; + this.params.forEach( param => param.run( scope ) ); // in case of assignment patterns + this.body.run(); + } + + addReference () { + /* noop? */ + } + + bind ( scope ) { + this.id.bind( scope ); + this.params.forEach( param => param.bind( this.body.scope ) ); + this.body.bind( scope ); + } + + gatherPossibleValues ( values ) { + values.add( this ); + } + + getName () { + return this.name; + } + + hasEffects () { + return false; + } + + initialise ( scope ) { + this.name = this.id.name; // may be overridden by bundle.deconflict + scope.addDeclaration( this.name, this, false, false ); + + this.body.createScope( scope ); + + this.id.initialise( scope ); + this.params.forEach( param => param.initialise( this.body.scope ) ); + this.body.initialise(); + } + + render ( code, es ) { + if ( !this.module.bundle.treeshake || this.activated ) { + super.render( code, es ); + } else { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } + } +} diff --git a/src/ast/nodes/FunctionExpression.js b/src/ast/nodes/FunctionExpression.js new file mode 100644 index 00000000000..4d170af168b --- /dev/null +++ b/src/ast/nodes/FunctionExpression.js @@ -0,0 +1,21 @@ +import Node from '../Node.js'; + +export default class FunctionExpression extends Node { + bind () { + if ( this.id ) this.id.bind( this.body.scope ); + this.params.forEach( param => param.bind( this.body.scope ) ); + this.body.bind(); + } + + hasEffects () { + return false; + } + + initialise ( scope ) { + this.body.createScope( scope ); + + if ( this.id ) this.id.initialise( this.body.scope ); + this.params.forEach( param => param.initialise( this.body.scope ) ); + this.body.initialise(); + } +} diff --git a/src/ast/nodes/Identifier.js b/src/ast/nodes/Identifier.js new file mode 100644 index 00000000000..836462bd1fe --- /dev/null +++ b/src/ast/nodes/Identifier.js @@ -0,0 +1,35 @@ +import Node from '../Node.js'; +import isReference from '../utils/isReference.js'; + +export default class Identifier extends Node { + bind ( scope ) { + if ( isReference( this, this.parent ) ) { + this.declaration = scope.findDeclaration( this.name ); + this.declaration.addReference( this ); // TODO necessary? + } + } + + gatherPossibleValues ( values ) { + if ( isReference( this, this.parent ) ) { + values.add( this ); + } + } + + render ( code, es ) { + if ( this.declaration ) { + const name = this.declaration.getName( es ); + if ( name !== this.name ) { + code.overwrite( this.start, this.end, name, true ); + + // special case + if ( this.parent.type === 'Property' && this.parent.shorthand ) { + code.insertLeft( this.start, `${this.name}: ` ); + } + } + } + } + + run () { + if ( this.declaration ) this.declaration.activate(); + } +} diff --git a/src/ast/nodes/IfStatement.js b/src/ast/nodes/IfStatement.js new file mode 100644 index 00000000000..fe83a784cab --- /dev/null +++ b/src/ast/nodes/IfStatement.js @@ -0,0 +1,76 @@ +import Statement from './shared/Statement.js'; +import { UNKNOWN } from '../values.js'; + +// Statement types which may contain if-statements as direct children. +const statementsWithIfStatements = new Set([ + 'DoWhileStatement', + 'ForInStatement', + 'ForOfStatement', + 'ForStatement', + 'IfStatement', + 'WhileStatement' +]); + +// TODO DRY this out +export default class IfStatement extends Statement { + initialise ( scope ) { + this.testValue = this.test.getValue(); + + if ( this.module.bundle.treeshake ) { + if ( this.testValue === UNKNOWN ) { + super.initialise( scope ); + } + + else if ( this.testValue ) { + this.consequent.initialise( scope ); + this.alternate = null; + } + + else { + if ( this.alternate ) this.alternate.initialise( scope ); + this.consequent = null; + } + } + + else { + super.initialise( scope ); + } + } + + render ( code, es ) { + if ( this.module.bundle.treeshake ) { + if ( this.testValue === UNKNOWN ) { + super.render( code, es ); + } + + else { + code.overwrite( this.test.start, this.test.end, JSON.stringify( this.testValue ) ); + + // TODO if no block-scoped declarations, remove enclosing + // curlies and dedent block (if there is a block) + + if ( this.testValue ) { + code.remove( this.start, this.consequent.start ); + code.remove( this.consequent.end, this.end ); + this.consequent.render( code, es ); + } + + else { + code.remove( this.start, this.alternate ? this.alternate.start : this.next || this.end ); + + if ( this.alternate ) { + this.alternate.render( code, es ); + } + + else if ( statementsWithIfStatements.has( this.parent.type ) ) { + code.insertRight( this.start, '{}' ); + } + } + } + } + + else { + super.render( code, es ); + } + } +} diff --git a/src/ast/nodes/ImportDeclaration.js b/src/ast/nodes/ImportDeclaration.js new file mode 100644 index 00000000000..0edc68b2111 --- /dev/null +++ b/src/ast/nodes/ImportDeclaration.js @@ -0,0 +1,16 @@ +import Node from '../Node.js'; + +export default class ImportDeclaration extends Node { + bind () { + // noop + // TODO do the inter-module binding setup here? + } + + initialise () { + this.isImportDeclaration = true; + } + + render ( code ) { + code.remove( this.start, this.next || this.end ); + } +} diff --git a/src/ast/nodes/Literal.js b/src/ast/nodes/Literal.js new file mode 100644 index 00000000000..3b54f14294f --- /dev/null +++ b/src/ast/nodes/Literal.js @@ -0,0 +1,17 @@ +import Node from '../Node.js'; + +export default class Literal extends Node { + getValue () { + return this.value; + } + + gatherPossibleValues ( values ) { + values.add( this ); + } + + render ( code ) { + if ( typeof this.value === 'string' ) { + code.indentExclusionRanges.push([ this.start + 1, this.end - 1 ]); + } + } +} diff --git a/src/ast/nodes/MemberExpression.js b/src/ast/nodes/MemberExpression.js new file mode 100644 index 00000000000..eca57a280f3 --- /dev/null +++ b/src/ast/nodes/MemberExpression.js @@ -0,0 +1,84 @@ +import getLocation from '../../utils/getLocation.js'; +import relativeId from '../../utils/relativeId.js'; +import isReference from '../utils/isReference.js'; +import Node from '../Node.js'; +import { UNKNOWN } from '../values.js'; + +class Keypath { + constructor ( node ) { + this.parts = []; + + while ( node.type === 'MemberExpression' ) { + this.parts.unshift( node.property ); + node = node.object; + } + + this.root = node; + } +} + +export default class MemberExpression extends Node { + bind ( scope ) { + // if this resolves to a namespaced declaration, prepare + // to replace it + // TODO this code is a bit inefficient + if ( isReference( this ) ) { // TODO optimise namespace access like `foo['bar']` as well + const keypath = new Keypath( this ); + + let declaration = scope.findDeclaration( keypath.root.name ); + + while ( declaration.isNamespace && keypath.parts.length ) { + const exporterId = declaration.module.id; + + const part = keypath.parts[0]; + declaration = declaration.module.traceExport( part.name ); + + if ( !declaration ) { + const { line, column } = getLocation( this.module.code, this.start ); + this.module.bundle.onwarn( `${relativeId( this.module.id )} (${line}:${column}) '${part.name}' is not exported by '${relativeId( exporterId )}'. See https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module` ); + this.replacement = 'undefined'; + return; + } + + keypath.parts.shift(); + } + + if ( keypath.parts.length ) { + super.bind( scope ); + return; // not a namespaced declaration + } + + this.declaration = declaration; + + if ( declaration.isExternal ) { + declaration.module.suggestName( keypath.root.name ); + } + } + + else { + super.bind( scope ); + } + } + + gatherPossibleValues ( values ) { + values.add( UNKNOWN ); // TODO + } + + render ( code, es ) { + if ( this.declaration ) { + const name = this.declaration.getName( es ); + if ( name !== this.name ) code.overwrite( this.start, this.end, name, true ); + } + + else if ( this.replacement ) { + code.overwrite( this.start, this.end, this.replacement, true ); + } + + super.render( code, es ); + } + + run ( scope ) { + if ( this.declaration ) this.declaration.activate(); + super.run( scope ); + } +} diff --git a/src/ast/nodes/NewExpression.js b/src/ast/nodes/NewExpression.js new file mode 100644 index 00000000000..8bfbb3359f0 --- /dev/null +++ b/src/ast/nodes/NewExpression.js @@ -0,0 +1,8 @@ +import Node from '../Node.js'; +import callHasEffects from './shared/callHasEffects.js'; + +export default class NewExpression extends Node { + hasEffects ( scope ) { + return callHasEffects( scope, this.callee ); + } +} diff --git a/src/ast/nodes/ObjectExpression.js b/src/ast/nodes/ObjectExpression.js new file mode 100644 index 00000000000..724cb00c514 --- /dev/null +++ b/src/ast/nodes/ObjectExpression.js @@ -0,0 +1,8 @@ +import Node from '../Node.js'; +import { OBJECT } from '../values.js'; + +export default class ObjectExpression extends Node { + gatherPossibleValues ( values ) { + values.add( OBJECT ); + } +} diff --git a/src/ast/nodes/ReturnStatement.js b/src/ast/nodes/ReturnStatement.js new file mode 100644 index 00000000000..bff5ae126d6 --- /dev/null +++ b/src/ast/nodes/ReturnStatement.js @@ -0,0 +1,7 @@ +import Node from '../Node.js'; + +export default class ReturnStatement extends Node { + // hasEffects () { + // return true; + // } +} diff --git a/src/ast/nodes/TemplateLiteral.js b/src/ast/nodes/TemplateLiteral.js new file mode 100644 index 00000000000..b25ef48c86a --- /dev/null +++ b/src/ast/nodes/TemplateLiteral.js @@ -0,0 +1,8 @@ +import Node from '../Node.js'; + +export default class TemplateLiteral extends Node { + render ( code, es ) { + code.indentExclusionRanges.push([ this.start, this.end ]); + super.render( code, es ); + } +} diff --git a/src/ast/nodes/ThisExpression.js b/src/ast/nodes/ThisExpression.js new file mode 100644 index 00000000000..ae351738be7 --- /dev/null +++ b/src/ast/nodes/ThisExpression.js @@ -0,0 +1,26 @@ +import Node from '../Node.js'; +import getLocation from '../../utils/getLocation.js'; +import relativeId from '../../utils/relativeId.js'; + +const warning = `The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten. See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined for more information`; + +export default class ThisExpression extends Node { + initialise ( scope ) { + const lexicalBoundary = scope.findLexicalBoundary(); + + if ( lexicalBoundary.isModuleScope ) { + this.alias = this.module.context; + if ( this.alias === 'undefined' ) { + const { line, column } = getLocation( this.module.code, this.start ); + const detail = `${relativeId( this.module.id )} (${line}:${column + 1})`; // use one-based column number convention + this.module.bundle.onwarn( `${detail} ${warning}` ); + } + } + } + + render ( code ) { + if ( this.alias ) { + code.overwrite( this.start, this.end, this.alias, true ); + } + } +} diff --git a/src/ast/nodes/ThrowStatement.js b/src/ast/nodes/ThrowStatement.js new file mode 100644 index 00000000000..4e9047bfc4a --- /dev/null +++ b/src/ast/nodes/ThrowStatement.js @@ -0,0 +1,7 @@ +import Node from '../Node.js'; + +export default class ThrowStatement extends Node { + hasEffects ( scope ) { + return scope.findLexicalBoundary().isModuleScope; // TODO should this just be `true`? probably... + } +} diff --git a/src/ast/nodes/UnaryExpression.js b/src/ast/nodes/UnaryExpression.js new file mode 100644 index 00000000000..9be1c2c3689 --- /dev/null +++ b/src/ast/nodes/UnaryExpression.js @@ -0,0 +1,34 @@ +import Node from '../Node.js'; +import { UNKNOWN } from '../values.js'; + +const operators = { + "-": value => -value, + "+": value => +value, + "!": value => !value, + "~": value => ~value, + typeof: value => typeof value, + void: () => undefined, + delete: () => UNKNOWN +}; + +export default class UnaryExpression extends Node { + bind ( scope ) { + if ( this.value === UNKNOWN ) super.bind( scope ); + } + + getValue () { + const argumentValue = this.argument.getValue(); + if ( argumentValue === UNKNOWN ) return UNKNOWN; + + return operators[ this.operator ]( argumentValue ); + } + + hasEffects ( scope ) { + return this.operator === 'delete' || this.argument.hasEffects( scope ); + } + + initialise ( scope ) { + this.value = this.getValue(); + if ( this.value === UNKNOWN ) super.initialise( scope ); + } +} diff --git a/src/ast/nodes/UpdateExpression.js b/src/ast/nodes/UpdateExpression.js new file mode 100644 index 00000000000..9fcea9dc50f --- /dev/null +++ b/src/ast/nodes/UpdateExpression.js @@ -0,0 +1,39 @@ +import Node from '../Node.js'; +import disallowIllegalReassignment from './shared/disallowIllegalReassignment.js'; +import isUsedByBundle from './shared/isUsedByBundle.js'; +import { NUMBER } from '../values.js'; + +export default class UpdateExpression extends Node { + bind ( scope ) { + const subject = this.argument; + + this.subject = subject; + disallowIllegalReassignment( scope, this.argument ); + + if ( subject.type === 'Identifier' ) { + const declaration = scope.findDeclaration( subject.name ); + declaration.isReassigned = true; + + if ( declaration.possibleValues ) { + declaration.possibleValues.add( NUMBER ); + } + } + + super.bind( scope ); + } + + hasEffects ( scope ) { + return isUsedByBundle( scope, this.subject ); + } + + initialise ( scope ) { + this.scope = scope; + + this.module.bundle.dependentExpressions.push( this ); + super.initialise( scope ); + } + + isUsedByBundle () { + return isUsedByBundle( this.scope, this.subject ); + } +} diff --git a/src/ast/nodes/VariableDeclaration.js b/src/ast/nodes/VariableDeclaration.js new file mode 100644 index 00000000000..77f4433d67d --- /dev/null +++ b/src/ast/nodes/VariableDeclaration.js @@ -0,0 +1,107 @@ +import Node from '../Node.js'; +import extractNames from '../utils/extractNames.js'; + +function getSeparator ( code, start ) { + let c = start; + + while ( c > 0 && code[ c - 1 ] !== '\n' ) { + c -= 1; + if ( code[c] === ';' || code[c] === '{' ) return '; '; + } + + const lineStart = code.slice( c, start ).match( /^\s*/ )[0]; + + return `;\n${lineStart}`; +} + +const forStatement = /^For(?:Of|In)?Statement/; + +export default class VariableDeclaration extends Node { + initialise ( scope ) { + this.scope = scope; + super.initialise( scope ); + } + + render ( code, es ) { + const treeshake = this.module.bundle.treeshake; + + let shouldSeparate = false; + let separator; + + if ( this.scope.isModuleScope && !forStatement.test( this.parent.type ) ) { + shouldSeparate = true; + separator = getSeparator( this.module.code, this.start ); + } + + let c = this.start; + let empty = true; + + for ( let i = 0; i < this.declarations.length; i += 1 ) { + const declarator = this.declarations[i]; + + const prefix = empty ? '' : separator; // TODO indentation + + if ( declarator.id.type === 'Identifier' ) { + const proxy = declarator.proxies.get( declarator.id.name ); + const isExportedAndReassigned = !es && proxy.exportName && proxy.isReassigned; + + if ( isExportedAndReassigned ) { + if ( declarator.init ) { + if ( shouldSeparate ) code.overwrite( c, declarator.start, prefix ); + c = declarator.end; + empty = false; + } + } else if ( !treeshake || proxy.activated ) { + if ( shouldSeparate ) code.overwrite( c, declarator.start, `${prefix}${this.kind} ` ); // TODO indentation + c = declarator.end; + empty = false; + } + } + + else { + const exportAssignments = []; + let activated = false; + + extractNames( declarator.id ).forEach( name => { + const proxy = declarator.proxies.get( name ); + const isExportedAndReassigned = !es && proxy.exportName && proxy.isReassigned; + + if ( isExportedAndReassigned ) { + // code.overwrite( c, declarator.start, prefix ); + // c = declarator.end; + // empty = false; + exportAssignments.push( 'TODO' ); + } else if ( declarator.activated ) { + activated = true; + } + }); + + if ( !treeshake || activated ) { + if ( shouldSeparate ) code.overwrite( c, declarator.start, `${prefix}${this.kind} ` ); // TODO indentation + c = declarator.end; + empty = false; + } + + if ( exportAssignments.length ) { + throw new Error( 'TODO' ); + } + } + + declarator.render( code, es ); + } + + if ( treeshake && empty ) { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } else { + // always include a semi-colon (https://github.com/rollup/rollup/pull/1013), + // unless it's a var declaration in a loop head + const needsSemicolon = !forStatement.test( this.parent.type ); + + if ( this.end > c ) { + code.overwrite( c, this.end, needsSemicolon ? ';' : '' ); + } else if ( needsSemicolon ) { + this.insertSemicolon( code ); + } + } + } +} diff --git a/src/ast/nodes/VariableDeclarator.js b/src/ast/nodes/VariableDeclarator.js new file mode 100644 index 00000000000..dc35bff9d2d --- /dev/null +++ b/src/ast/nodes/VariableDeclarator.js @@ -0,0 +1,91 @@ +import Node from '../Node.js'; +import extractNames from '../utils/extractNames.js'; +import { UNKNOWN } from '../values.js'; + +class DeclaratorProxy { + constructor ( name, declarator, isTopLevel, init ) { + this.name = name; + this.declarator = declarator; + + this.activated = false; + this.isReassigned = false; + this.exportName = null; + + this.duplicates = []; + this.possibleValues = new Set( init ? [ init ] : null ); + } + + activate () { + this.activated = true; + this.declarator.activate(); + this.duplicates.forEach( dupe => dupe.activate() ); + } + + addReference () { + /* noop? */ + } + + gatherPossibleValues ( values ) { + this.possibleValues.forEach( value => values.add( value ) ); + } + + getName ( es ) { + // TODO desctructuring... + if ( es ) return this.name; + if ( !this.isReassigned || !this.exportName ) return this.name; + + return `exports.${this.exportName}`; + } + + toString () { + return this.name; + } +} + +export default class VariableDeclarator extends Node { + activate () { + if ( this.activated ) return; + this.activated = true; + + this.run( this.findScope() ); + } + + hasEffects ( scope ) { + return this.init && this.init.hasEffects( scope ); + } + + initialise ( scope ) { + this.proxies = new Map(); + + const lexicalBoundary = scope.findLexicalBoundary(); + + const init = this.init ? + ( this.id.type === 'Identifier' ? this.init : UNKNOWN ) : // TODO maybe UNKNOWN is unnecessary + null; + + extractNames( this.id ).forEach( name => { + const proxy = new DeclaratorProxy( name, this, lexicalBoundary.isModuleScope, init ); + + this.proxies.set( name, proxy ); + scope.addDeclaration( name, proxy, this.parent.kind === 'var' ); + }); + + super.initialise( scope ); + } + + render ( code, es ) { + extractNames( this.id ).forEach( name => { + const declaration = this.proxies.get( name ); + + if ( !es && declaration.exportName && declaration.isReassigned ) { + if ( this.init ) { + code.overwrite( this.start, this.id.end, declaration.getName( es ) ); + } else if ( this.module.bundle.treeshake ) { + code.remove( this.start, this.end ); + } + } + }); + + super.render( code, es ); + } +} diff --git a/src/ast/nodes/index.js b/src/ast/nodes/index.js new file mode 100644 index 00000000000..1c3ba4c39d4 --- /dev/null +++ b/src/ast/nodes/index.js @@ -0,0 +1,76 @@ +import ArrayExpression from './ArrayExpression.js'; +import ArrowFunctionExpression from './ArrowFunctionExpression.js'; +import AssignmentExpression from './AssignmentExpression.js'; +import BinaryExpression from './BinaryExpression.js'; +import BlockStatement from './BlockStatement.js'; +import CallExpression from './CallExpression.js'; +import ClassDeclaration from './ClassDeclaration.js'; +import ClassExpression from './ClassExpression.js'; +import ConditionalExpression from './ConditionalExpression.js'; +import EmptyStatement from './EmptyStatement.js'; +import ExportAllDeclaration from './ExportAllDeclaration.js'; +import ExportDefaultDeclaration from './ExportDefaultDeclaration.js'; +import ExportNamedDeclaration from './ExportNamedDeclaration.js'; +import ExpressionStatement from './ExpressionStatement.js'; +import ForStatement from './ForStatement.js'; +import ForInStatement from './ForInStatement.js'; +import ForOfStatement from './ForOfStatement.js'; +import FunctionDeclaration from './FunctionDeclaration.js'; +import FunctionExpression from './FunctionExpression.js'; +import Identifier from './Identifier.js'; +import IfStatement from './IfStatement.js'; +import ImportDeclaration from './ImportDeclaration.js'; +import Literal from './Literal.js'; +import MemberExpression from './MemberExpression.js'; +import NewExpression from './NewExpression.js'; +import ObjectExpression from './ObjectExpression.js'; +import ReturnStatement from './ReturnStatement.js'; +import Statement from './shared/Statement.js'; +import TemplateLiteral from './TemplateLiteral.js'; +import ThisExpression from './ThisExpression.js'; +import ThrowStatement from './ThrowStatement.js'; +import UnaryExpression from './UnaryExpression.js'; +import UpdateExpression from './UpdateExpression.js'; +import VariableDeclarator from './VariableDeclarator.js'; +import VariableDeclaration from './VariableDeclaration.js'; + +export default { + ArrayExpression, + ArrowFunctionExpression, + AssignmentExpression, + BinaryExpression, + BlockStatement, + CallExpression, + ClassDeclaration, + ClassExpression, + ConditionalExpression, + DoWhileStatement: Statement, + EmptyStatement, + ExportAllDeclaration, + ExportDefaultDeclaration, + ExportNamedDeclaration, + ExpressionStatement, + ForStatement, + ForInStatement, + ForOfStatement, + FunctionDeclaration, + FunctionExpression, + Identifier, + IfStatement, + ImportDeclaration, + Literal, + MemberExpression, + NewExpression, + ObjectExpression, + ReturnStatement, + SwitchStatement: Statement, + TemplateLiteral, + ThisExpression, + ThrowStatement, + TryStatement: Statement, + UnaryExpression, + UpdateExpression, + VariableDeclarator, + VariableDeclaration, + WhileStatement: Statement +}; diff --git a/src/ast/nodes/shared/Statement.js b/src/ast/nodes/shared/Statement.js new file mode 100644 index 00000000000..5667652071c --- /dev/null +++ b/src/ast/nodes/shared/Statement.js @@ -0,0 +1,16 @@ +import Node from '../../Node.js'; + +export default class Statement extends Node { + render ( code, es ) { + if ( !this.module.bundle.treeshake || this.shouldInclude ) { + super.render( code, es ); + } else { + code.remove( this.leadingCommentStart || this.start, this.next || this.end ); + } + } + + run ( scope ) { + this.shouldInclude = true; + super.run( scope ); + } +} diff --git a/src/ast/nodes/shared/assignTo.js b/src/ast/nodes/shared/assignTo.js new file mode 100644 index 00000000000..2ec7d1775a8 --- /dev/null +++ b/src/ast/nodes/shared/assignTo.js @@ -0,0 +1,27 @@ +import extractNames from '../../utils/extractNames.js'; + +export default function assignToForLoopLeft ( node, scope, value ) { + if ( node.type === 'VariableDeclaration' ) { + for ( const proxy of node.declarations[0].proxies.values() ) { + proxy.possibleValues.add( value ); + } + } + + else { + if ( node.type === 'MemberExpression' ) { + // apparently this is legal JavaScript? Though I don't know what + // kind of monster would write `for ( foo.bar of thing ) {...}` + + // for now, do nothing, as I'm not sure anything needs to happen... + } + + else { + for ( const name of extractNames( node ) ) { + const declaration = scope.findDeclaration( name ); + if ( declaration.possibleValues ) { + declaration.possibleValues.add( value ); + } + } + } + } +} diff --git a/src/ast/nodes/shared/callHasEffects.js b/src/ast/nodes/shared/callHasEffects.js new file mode 100644 index 00000000000..6df76d1d51d --- /dev/null +++ b/src/ast/nodes/shared/callHasEffects.js @@ -0,0 +1,67 @@ +import flatten from '../../utils/flatten.js'; +import isReference from '../../utils/isReference.js'; +import pureFunctions from './pureFunctions.js'; +import { UNKNOWN } from '../../values.js'; + +const currentlyCalling = new Set(); + +function fnHasEffects ( fn ) { + if ( currentlyCalling.has( fn ) ) return false; // prevent infinite loops... TODO there must be a better way + currentlyCalling.add( fn ); + + // handle body-less arrow functions + const scope = fn.body.scope || fn.scope; + const body = fn.body.type === 'BlockStatement' ? fn.body.body : [ fn.body ]; + + for ( const node of body ) { + if ( node.hasEffects( scope ) ) { + currentlyCalling.delete( fn ); + return true; + } + } + + currentlyCalling.delete( fn ); + return false; +} + +export default function callHasEffects ( scope, callee ) { + const values = new Set([ callee ]); + + for ( const node of values ) { + if ( node === UNKNOWN ) return true; // err on side of caution + + if ( /Function/.test( node.type ) ) { + if ( fnHasEffects( node ) ) return true; + } + + else if ( isReference( node ) ) { + const flattened = flatten( node ); + const declaration = scope.findDeclaration( flattened.name ); + + if ( declaration.isGlobal ) { + if ( !pureFunctions[ flattened.keypath ] ) return true; + } + + else if ( declaration.isExternal ) { + return true; // TODO make this configurable? e.g. `path.[whatever]` + } + + else { + if ( node.declaration ) { + node.declaration.gatherPossibleValues( values ); + } else { + return true; + } + } + } + + else { + if ( !node.gatherPossibleValues ) { + throw new Error( 'TODO' ); + } + node.gatherPossibleValues( values ); + } + } + + return false; +} diff --git a/src/ast/nodes/shared/disallowIllegalReassignment.js b/src/ast/nodes/shared/disallowIllegalReassignment.js new file mode 100644 index 00000000000..a40969fcab0 --- /dev/null +++ b/src/ast/nodes/shared/disallowIllegalReassignment.js @@ -0,0 +1,28 @@ +import getLocation from '../../../utils/getLocation.js'; +import error from '../../../utils/error.js'; + +// TODO tidy this up a bit (e.g. they can both use node.module.imports) +export default function disallowIllegalReassignment ( scope, node ) { + if ( node.type === 'MemberExpression' && node.object.type === 'Identifier' ) { + const declaration = scope.findDeclaration( node.object.name ); + if ( declaration.isNamespace ) { + error({ + message: `Illegal reassignment to import '${node.object.name}'`, + file: node.module.id, + pos: node.start, + loc: getLocation( node.module.code, node.start ) + }); + } + } + + else if ( node.type === 'Identifier' ) { + if ( node.module.imports[ node.name ] && !scope.contains( node.name ) ) { + error({ + message: `Illegal reassignment to import '${node.name}'`, + file: node.module.id, + pos: node.start, + loc: getLocation( node.module.code, node.start ) + }); + } + } +} diff --git a/src/ast/nodes/shared/isUsedByBundle.js b/src/ast/nodes/shared/isUsedByBundle.js new file mode 100644 index 00000000000..d33561a0d5a --- /dev/null +++ b/src/ast/nodes/shared/isUsedByBundle.js @@ -0,0 +1,38 @@ +import { UNKNOWN } from '../../values.js'; + +export default function isUsedByBundle ( scope, node ) { + // const expression = node; + while ( node.type === 'MemberExpression' ) node = node.object; + + const declaration = scope.findDeclaration( node.name ); + + if ( declaration.isParam ) { + return true; + + // TODO if we mutate a parameter, assume the worst + // return node !== expression; + } + + if ( declaration.activated ) return true; + + const values = new Set(); + declaration.gatherPossibleValues( values ); + for ( const value of values ) { + if ( value === UNKNOWN ) { + return true; + } + + if ( value.type === 'Identifier' ) { + if ( value.declaration.activated ) { + return true; + } + value.declaration.gatherPossibleValues( values ); + } + + else if ( value.gatherPossibleValues ) { + value.gatherPossibleValues( values ); + } + } + + return false; +} diff --git a/src/utils/pureFunctions.js b/src/ast/nodes/shared/pureFunctions.js similarity index 98% rename from src/utils/pureFunctions.js rename to src/ast/nodes/shared/pureFunctions.js index 3642a0566a2..3301085971b 100644 --- a/src/utils/pureFunctions.js +++ b/src/ast/nodes/shared/pureFunctions.js @@ -1,9 +1,9 @@ -let pureFunctions = {}; +const pureFunctions = {}; const arrayTypes = 'Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array'.split( ' ' ); const simdTypes = 'Int8x16 Int16x8 Int32x4 Float32x4 Float64x2'.split( ' ' ); const simdMethods = 'abs add and bool check div equal extractLane fromFloat32x4 fromFloat32x4Bits fromFloat64x2 fromFloat64x2Bits fromInt16x8Bits fromInt32x4 fromInt32x4Bits fromInt8x16Bits greaterThan greaterThanOrEqual lessThan lessThanOrEqual load max maxNum min minNum mul neg not notEqual or reciprocalApproximation reciprocalSqrtApproximation replaceLane select selectBits shiftLeftByScalar shiftRightArithmeticByScalar shiftRightLogicalByScalar shuffle splat sqrt store sub swizzle xor'.split( ' ' ); -let allSimdMethods = []; +const allSimdMethods = []; simdTypes.forEach( t => { simdMethods.forEach( m => { allSimdMethods.push( `SIMD.${t}.${m}` ); diff --git a/src/ast/scopes/BundleScope.js b/src/ast/scopes/BundleScope.js new file mode 100644 index 00000000000..6c0f0ea39a5 --- /dev/null +++ b/src/ast/scopes/BundleScope.js @@ -0,0 +1,40 @@ +import Scope from './Scope.js'; +import { UNKNOWN } from '../values'; + +class SyntheticGlobalDeclaration { + constructor ( name ) { + this.name = name; + this.isExternal = true; + this.isGlobal = true; + this.isReassigned = false; + + this.activated = true; + } + + activate () { + /* noop */ + } + + addReference ( reference ) { + reference.declaration = this; + if ( reference.isReassignment ) this.isReassigned = true; + } + + gatherPossibleValues ( values ) { + values.add( UNKNOWN ); + } + + getName () { + return this.name; + } +} + +export default class BundleScope extends Scope { + findDeclaration ( name ) { + if ( !this.declarations[ name ] ) { + this.declarations[ name ] = new SyntheticGlobalDeclaration( name ); + } + + return this.declarations[ name ]; + } +} diff --git a/src/ast/scopes/ModuleScope.js b/src/ast/scopes/ModuleScope.js new file mode 100644 index 00000000000..5a18d6f6991 --- /dev/null +++ b/src/ast/scopes/ModuleScope.js @@ -0,0 +1,53 @@ +import { forOwn } from '../../utils/object.js'; +import Scope from './Scope.js'; + +export default class ModuleScope extends Scope { + constructor ( module ) { + super({ + isBlockScope: false, + isLexicalBoundary: true, + isModuleScope: true, + parent: module.bundle.scope + }); + + this.module = module; + } + + deshadow ( names ) { + names = new Map( names ); + + forOwn( this.module.imports, specifier => { + if ( specifier.module.isExternal ) return; + + specifier.module.getExports().forEach( name => { + names.set(name); + }); + + if ( specifier.name !== '*' ) { + const declaration = specifier.module.traceExport( specifier.name ); + if ( !declaration ) { + this.module.bundle.onwarn( `Non-existent export '${specifier.name}' is imported from ${specifier.module.id} by ${this.module.id}` ); + return; + } + const name = declaration.getName( true ); + if ( name !== specifier.name ) { + names.set( declaration.getName( true ) ); + } + } + }); + + super.deshadow( names ); + } + + findDeclaration ( name ) { + if ( this.declarations[ name ] ) { + return this.declarations[ name ]; + } + + return this.module.trace( name ) || this.parent.findDeclaration( name ); + } + + findLexicalBoundary () { + return this; + } +} diff --git a/src/ast/scopes/Scope.js b/src/ast/scopes/Scope.js new file mode 100644 index 00000000000..2c250a8b5af --- /dev/null +++ b/src/ast/scopes/Scope.js @@ -0,0 +1,96 @@ +import { blank, keys } from '../../utils/object.js'; +import { UNKNOWN } from '../values.js'; + +class Parameter { + constructor ( name ) { + this.name = name; + + this.isParam = true; + this.activated = true; + } + + activate () { + // noop + } + + addReference () { + // noop? + } + + gatherPossibleValues ( values ) { + values.add( UNKNOWN ); // TODO populate this at call time + } + + getName () { + return this.name; + } +} + +export default class Scope { + constructor ( options = {} ) { + this.parent = options.parent; + this.isBlockScope = !!options.isBlockScope; + this.isLexicalBoundary = !!options.isLexicalBoundary; + this.isModuleScope = !!options.isModuleScope; + + this.children = []; + if ( this.parent ) this.parent.children.push( this ); + + this.declarations = blank(); + + if ( this.isLexicalBoundary && !this.isModuleScope ) { + this.declarations.arguments = new Parameter( 'arguments' ); + } + } + + addDeclaration ( name, declaration, isVar, isParam ) { + if ( isVar && this.isBlockScope ) { + this.parent.addDeclaration( name, declaration, isVar, isParam ); + } else { + const existingDeclaration = this.declarations[ name ]; + + if ( existingDeclaration && existingDeclaration.duplicates ) { + // TODO warn/throw on duplicates? + existingDeclaration.duplicates.push( declaration ); + } else { + this.declarations[ name ] = isParam ? new Parameter( name ) : declaration; + } + } + } + + contains ( name ) { + return !!this.declarations[ name ] || + ( this.parent ? this.parent.contains( name ) : false ); + } + + deshadow ( names ) { + keys( this.declarations ).forEach( key => { + const declaration = this.declarations[ key ]; + + // we can disregard exports.foo etc + if ( declaration.exportName && declaration.isReassigned ) return; + + const name = declaration.getName( true ); + let deshadowed = name; + + let i = 1; + + while ( names.has( deshadowed ) ) { + deshadowed = `${name}$$${i++}`; + } + + declaration.name = deshadowed; + }); + + this.children.forEach( scope => scope.deshadow( names ) ); + } + + findDeclaration ( name ) { + return this.declarations[ name ] || + ( this.parent && this.parent.findDeclaration( name ) ); + } + + findLexicalBoundary () { + return this.isLexicalBoundary ? this : this.parent.findLexicalBoundary(); + } +} diff --git a/src/ast/extractNames.js b/src/ast/utils/extractNames.js similarity index 100% rename from src/ast/extractNames.js rename to src/ast/utils/extractNames.js diff --git a/src/ast/flatten.js b/src/ast/utils/flatten.js similarity index 94% rename from src/ast/flatten.js rename to src/ast/utils/flatten.js index 0cecbde8839..2000c8941ab 100644 --- a/src/ast/flatten.js +++ b/src/ast/utils/flatten.js @@ -1,5 +1,5 @@ export default function flatten ( node ) { - let parts = []; + const parts = []; while ( node.type === 'MemberExpression' ) { if ( node.computed ) return null; parts.unshift( node.property.name ); diff --git a/src/ast/utils/isProgramLevel.js b/src/ast/utils/isProgramLevel.js new file mode 100644 index 00000000000..b23de1252f3 --- /dev/null +++ b/src/ast/utils/isProgramLevel.js @@ -0,0 +1,10 @@ +export default function isProgramLevel ( node ) { + do { + if ( node.type === 'Program' ) { + return true; + } + node = node.parent; + } while ( node && !/Function/.test( node.type ) ); + + return false; +} diff --git a/src/ast/isReference.js b/src/ast/utils/isReference.js similarity index 100% rename from src/ast/isReference.js rename to src/ast/utils/isReference.js diff --git a/src/ast/values.js b/src/ast/values.js new file mode 100644 index 00000000000..dadd74a6ad1 --- /dev/null +++ b/src/ast/values.js @@ -0,0 +1,8 @@ +// properties are for debugging purposes only +export const ARRAY = { ARRAY: true, toString: () => '[[ARRAY]]' }; +export const BOOLEAN = { BOOLEAN: true, toString: () => '[[BOOLEAN]]' }; +export const FUNCTION = { FUNCTION: true, toString: () => '[[FUNCTION]]' }; +export const NUMBER = { NUMBER: true, toString: () => '[[NUMBER]]' }; +export const OBJECT = { OBJECT: true, toString: () => '[[OBJECT]]' }; +export const STRING = { STRING: true, toString: () => '[[STRING]]' }; +export const UNKNOWN = { UNKNOWN: true, toString: () => '[[UNKNOWN]]' }; diff --git a/src/finalisers/amd.js b/src/finalisers/amd.js index 7f6330571bc..64adffdba02 100644 --- a/src/finalisers/amd.js +++ b/src/finalisers/amd.js @@ -1,10 +1,11 @@ -import { getName, quoteId } from '../utils/map-helpers.js'; +import { getName, quotePath } from '../utils/map-helpers.js'; import getInteropBlock from './shared/getInteropBlock.js'; import getExportBlock from './shared/getExportBlock.js'; +import esModuleExport from './shared/esModuleExport.js'; -export default function amd ( bundle, magicString, { exportMode, indentString }, options ) { - let deps = bundle.externalModules.map( quoteId ); - let args = bundle.externalModules.map( getName ); +export default function amd ( bundle, magicString, { exportMode, indentString, intro }, options ) { + const deps = bundle.externalModules.map( quotePath ); + const args = bundle.externalModules.map( getName ); if ( exportMode === 'named' ) { args.unshift( `exports` ); @@ -16,17 +17,21 @@ export default function amd ( bundle, magicString, { exportMode, indentString }, ( deps.length ? `[${deps.join( ', ' )}], ` : `` ); const useStrict = options.useStrict !== false ? ` 'use strict';` : ``; - const intro = `define(${params}function (${args.join( ', ' )}) {${useStrict}\n\n`; + const wrapperStart = `define(${params}function (${args.join( ', ' )}) {${useStrict}\n\n`; // var foo__default = 'default' in foo ? foo['default'] : foo; - const interopBlock = getInteropBlock( bundle ); + const interopBlock = getInteropBlock( bundle, options ); if ( interopBlock ) magicString.prepend( interopBlock + '\n\n' ); + if ( intro ) magicString.prepend( intro ); + const exportBlock = getExportBlock( bundle.entryModule, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); + if ( exportMode === 'named' && options.legacy !== true ) magicString.append( `\n\n${esModuleExport}` ); + if ( options.outro ) magicString.append( `\n${options.outro}` ); return magicString .indent( indentString ) .append( '\n\n});' ) - .prepend( intro ); + .prepend( wrapperStart ); } diff --git a/src/finalisers/cjs.js b/src/finalisers/cjs.js index f6302ff0dbc..e89ef323e7e 100644 --- a/src/finalisers/cjs.js +++ b/src/finalisers/cjs.js @@ -1,31 +1,34 @@ import getExportBlock from './shared/getExportBlock.js'; +import esModuleExport from './shared/esModuleExport.js'; -export default function cjs ( bundle, magicString, { exportMode }, options ) { - let intro = options.useStrict === false ? `` : `'use strict';\n\n`; +export default function cjs ( bundle, magicString, { exportMode, intro }, options ) { + intro = ( options.useStrict === false ? intro : `'use strict';\n\n${intro}` ) + + ( exportMode === 'named' && options.legacy !== true ? `${esModuleExport}\n\n` : '' ); let needsInterop = false; const varOrConst = bundle.varOrConst; + const interop = options.interop !== false; // TODO handle empty imports, once they're supported const importBlock = bundle.externalModules .map( module => { - if ( module.declarations.default ) { + if ( interop && module.declarations.default ) { if ( module.exportsNamespace ) { - return `${varOrConst} ${module.name} = require('${module.id}');` + + return `${varOrConst} ${module.name} = require('${module.path}');` + `\n${varOrConst} ${module.name}__default = ${module.name}['default'];`; } needsInterop = true; if ( module.exportsNames ) { - return `${varOrConst} ${module.name} = require('${module.id}');` + + return `${varOrConst} ${module.name} = require('${module.path}');` + `\n${varOrConst} ${module.name}__default = _interopDefault(${module.name});`; } - return `${varOrConst} ${module.name} = _interopDefault(require('${module.id}'));`; + return `${varOrConst} ${module.name} = _interopDefault(require('${module.path}'));`; } else { - return `${varOrConst} ${module.name} = require('${module.id}');`; + return `${varOrConst} ${module.name} = require('${module.path}');`; } }) .join( '\n' ); @@ -42,6 +45,7 @@ export default function cjs ( bundle, magicString, { exportMode }, options ) { const exportBlock = getExportBlock( bundle.entryModule, exportMode, 'module.exports =' ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); + if ( options.outro ) magicString.append( `\n${options.outro}` ); return magicString; } diff --git a/src/finalisers/es6.js b/src/finalisers/es.js similarity index 75% rename from src/finalisers/es6.js rename to src/finalisers/es.js index bd3f93fd2b5..8251fe3f0ee 100644 --- a/src/finalisers/es6.js +++ b/src/finalisers/es.js @@ -4,7 +4,7 @@ function notDefault ( name ) { return name !== 'default'; } -export default function es6 ( bundle, magicString ) { +export default function es ( bundle, magicString, { intro }, options ) { const importBlock = bundle.externalModules .map( module => { const specifiers = []; @@ -26,8 +26,8 @@ export default function es6 ( bundle, magicString ) { } } - const namespaceSpecifier = module.declarations['*'] ? `* as ${module.name}` : null; - const namedSpecifier = importedNames.length ? `{ ${importedNames.join( ', ' )} }` : null; + const namespaceSpecifier = module.declarations['*'] ? `* as ${module.name}` : null; // TODO prevent unnecessary namespace import, e.g form/external-imports + const namedSpecifier = importedNames.length ? `{ ${importedNames.sort().join( ', ' )} }` : null; if ( namespaceSpecifier && namedSpecifier ) { // Namespace and named specifiers cannot be combined. @@ -42,22 +42,21 @@ export default function es6 ( bundle, magicString ) { return specifiersList .map( specifiers => specifiers.length ? - `import ${specifiers.join( ', ' )} from '${module.id}';` : - `import '${module.id}';` + `import ${specifiers.join( ', ' )} from '${module.path}';` : + `import '${module.path}';` ) .join( '\n' ); }) .join( '\n' ); - if ( importBlock ) { - magicString.prepend( importBlock + '\n\n' ); - } + if ( importBlock ) intro += importBlock + '\n\n'; + if ( intro ) magicString.prepend( intro ); const module = bundle.entryModule; const specifiers = module.getExports().filter( notDefault ).map( name => { const declaration = module.traceExport( name ); - const rendered = declaration.render( true ); + const rendered = declaration.getName( true ); return rendered === name ? name : @@ -68,12 +67,11 @@ export default function es6 ( bundle, magicString ) { const defaultExport = module.exports.default || module.reexports.default; if ( defaultExport ) { - exportBlock += `export default ${module.traceExport( 'default' ).render( true )};`; + exportBlock += `export default ${module.traceExport( 'default' ).getName( true )};`; } - if ( exportBlock ) { - magicString.append( '\n\n' + exportBlock.trim() ); - } + if ( exportBlock ) magicString.append( '\n\n' + exportBlock.trim() ); + if ( options.outro ) magicString.append( `\n${options.outro}` ); return magicString.trim(); } diff --git a/src/finalisers/iife.js b/src/finalisers/iife.js index adb701928d2..01d13252413 100644 --- a/src/finalisers/iife.js +++ b/src/finalisers/iife.js @@ -3,60 +3,70 @@ import { getName } from '../utils/map-helpers.js'; import getInteropBlock from './shared/getInteropBlock.js'; import getExportBlock from './shared/getExportBlock.js'; import getGlobalNameMaker from './shared/getGlobalNameMaker.js'; +import propertyStringFor from './shared/propertyStringFor'; + +// thisProp('foo.bar-baz.qux') === "this.foo['bar-baz'].qux" +const thisProp = propertyStringFor('this'); + +// propString('foo.bar-baz.qux') === ".foo['bar-baz'].qux" +const propString = propertyStringFor(''); function setupNamespace ( keypath ) { - let parts = keypath.split( '.' ); // TODO support e.g. `foo['something-hyphenated']`? + const parts = keypath.split( '.' ); parts.pop(); let acc = 'this'; return parts - .map( part => ( acc += `.${part}`, `${acc} = ${acc} || {};` ) ) + .map( part => ( acc += propString(part), `${acc} = ${acc} || {};` ) ) .join( '\n' ) + '\n'; } -export default function iife ( bundle, magicString, { exportMode, indentString }, options ) { +export default function iife ( bundle, magicString, { exportMode, indentString, intro }, options ) { const globalNameMaker = getGlobalNameMaker( options.globals || blank(), bundle.onwarn ); const name = options.moduleName; const isNamespaced = name && ~name.indexOf( '.' ); - let dependencies = bundle.externalModules.map( globalNameMaker ); + const dependencies = bundle.externalModules.map( globalNameMaker ); - let args = bundle.externalModules.map( getName ); + const args = bundle.externalModules.map( getName ); if ( exportMode !== 'none' && !name ) { throw new Error( 'You must supply options.moduleName for IIFE bundles' ); } if ( exportMode === 'named' ) { - dependencies.unshift( `(this.${name} = this.${name} || {})` ); + dependencies.unshift( `(${thisProp(name)} = ${thisProp(name)} || {})` ); args.unshift( 'exports' ); } - const useStrict = options.useStrict !== false ? `'use strict';` : ``; + const useStrict = options.useStrict !== false ? `${indentString}'use strict';\n\n` : ``; - let intro = `(function (${args}) {\n`; - let outro = `\n\n}(${dependencies}));`; + let wrapperIntro = `(function (${args}) {\n${useStrict}`; + const wrapperOutro = `\n\n}(${dependencies}));`; if ( exportMode === 'default' ) { - intro = ( isNamespaced ? `this.` : `${bundle.varOrConst} ` ) + `${name} = ${intro}`; + wrapperIntro = ( isNamespaced ? thisProp(name) : `${bundle.varOrConst} ${name}` ) + ` = ${wrapperIntro}`; } if ( isNamespaced ) { - intro = setupNamespace( name ) + intro; + wrapperIntro = setupNamespace( name ) + wrapperIntro; } // var foo__default = 'default' in foo ? foo['default'] : foo; - const interopBlock = getInteropBlock( bundle ); + const interopBlock = getInteropBlock( bundle, options ); if ( interopBlock ) magicString.prepend( interopBlock + '\n\n' ); - if ( useStrict ) magicString.prepend( useStrict + '\n\n' ); + + if ( intro ) magicString.prepend( intro ); + const exportBlock = getExportBlock( bundle.entryModule, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); + if ( options.outro ) magicString.append( `\n${options.outro}` ); return magicString .indent( indentString ) - .prepend( intro ) - .append( outro ); + .prepend( wrapperIntro ) + .append( wrapperOutro ); } diff --git a/src/finalisers/index.js b/src/finalisers/index.js index 3ada90ac493..1089ccbd42e 100644 --- a/src/finalisers/index.js +++ b/src/finalisers/index.js @@ -1,7 +1,7 @@ import amd from './amd.js'; import cjs from './cjs.js'; -import es6 from './es6.js'; +import es from './es.js'; import iife from './iife.js'; import umd from './umd.js'; -export default { amd, cjs, es6, iife, umd }; +export default { amd, cjs, es, iife, umd }; diff --git a/src/finalisers/shared/esModuleExport.js b/src/finalisers/shared/esModuleExport.js new file mode 100644 index 00000000000..7764bdc7071 --- /dev/null +++ b/src/finalisers/shared/esModuleExport.js @@ -0,0 +1 @@ +export default `Object.defineProperty(exports, '__esModule', { value: true });`; diff --git a/src/finalisers/shared/getExportBlock.js b/src/finalisers/shared/getExportBlock.js index 972da5950c7..5a7f34f9813 100644 --- a/src/finalisers/shared/getExportBlock.js +++ b/src/finalisers/shared/getExportBlock.js @@ -1,6 +1,6 @@ export default function getExportBlock ( entryModule, exportMode, mechanism = 'return' ) { if ( exportMode === 'default' ) { - return `${mechanism} ${entryModule.traceExport( 'default' ).render( false )};`; + return `${mechanism} ${entryModule.traceExport( 'default' ).getName( false )};`; } return entryModule.getExports() @@ -9,7 +9,9 @@ export default function getExportBlock ( entryModule, exportMode, mechanism = 'r const declaration = entryModule.traceExport( name ); const lhs = `exports${prop}`; - const rhs = declaration.render( false ); + const rhs = declaration ? + declaration.getName( false ) : + name; // exporting a global // prevent `exports.count = exports.count` if ( lhs === rhs ) return null; diff --git a/src/finalisers/shared/getInteropBlock.js b/src/finalisers/shared/getInteropBlock.js index 67a26d7c43f..6ecdba02148 100644 --- a/src/finalisers/shared/getInteropBlock.js +++ b/src/finalisers/shared/getInteropBlock.js @@ -1,7 +1,7 @@ -export default function getInteropBlock ( bundle ) { +export default function getInteropBlock ( bundle, options ) { return bundle.externalModules .map( module => { - if ( !module.declarations.default ) return null; + if ( !module.declarations.default || options.interop === false ) return null; if ( module.exportsNamespace ) { return `${bundle.varOrConst} ${module.name}__default = ${module.name}['default'];`; diff --git a/src/finalisers/shared/propertyStringFor.js b/src/finalisers/shared/propertyStringFor.js new file mode 100644 index 00000000000..72ad1bb8c80 --- /dev/null +++ b/src/finalisers/shared/propertyStringFor.js @@ -0,0 +1,18 @@ +// Generate strings which dereference dotted properties, but use array notation `['prop-deref']` +// if the property name isn't trivial + +const shouldUseDot = /^[a-zA-Z$_][a-zA-Z0-9$_]*$/; +const dereferenceString = prop => + prop.match(shouldUseDot) ? `.${prop}` : `['${prop}']`; + +/** + * returns a function which generates property dereference strings for the given name + * + * const getGlobalProp = propertyStringFor('global'); + * getGlobalProp('foo.bar-baz.qux') => `global.bar['bar-baz'].qux` + */ +const propertyStringFor = objName => propName => + objName + propName.split('.').map(dereferenceString).join(''); + + +export default propertyStringFor; \ No newline at end of file diff --git a/src/finalisers/umd.js b/src/finalisers/umd.js index 0ec344eb511..dd8b9c6421a 100644 --- a/src/finalisers/umd.js +++ b/src/finalisers/umd.js @@ -1,8 +1,16 @@ import { blank } from '../utils/object.js'; -import { getName, quoteId, req } from '../utils/map-helpers.js'; +import { getName, quotePath, req } from '../utils/map-helpers.js'; import getInteropBlock from './shared/getInteropBlock.js'; import getExportBlock from './shared/getExportBlock.js'; import getGlobalNameMaker from './shared/getGlobalNameMaker.js'; +import esModuleExport from './shared/esModuleExport.js'; +import propertyStringFor from './shared/propertyStringFor.js'; + +// globalProp('foo.bar-baz') === "global.foo['bar-baz']" +const globalProp = propertyStringFor('global'); + +// propString('foo.bar-baz') === ".foo['bar']" +const propString = propertyStringFor(''); function setupNamespace ( name ) { const parts = name.split( '.' ); @@ -10,28 +18,30 @@ function setupNamespace ( name ) { let acc = 'global'; return parts - .map( part => ( acc += `.${part}`, `${acc} = ${acc} || {}` ) ) - .concat( `global.${name}` ) + .map( part => ( acc += propString(part), `${acc} = ${acc} || {}` ) ) + .concat( globalProp(name) ) .join( ', ' ); } -export default function umd ( bundle, magicString, { exportMode, indentString }, options ) { +const wrapperOutro = '\n\n})));'; + +export default function umd ( bundle, magicString, { exportMode, indentString, intro }, options ) { if ( exportMode !== 'none' && !options.moduleName ) { throw new Error( 'You must supply options.moduleName for UMD bundles' ); } const globalNameMaker = getGlobalNameMaker( options.globals || blank(), bundle.onwarn ); - let amdDeps = bundle.externalModules.map( quoteId ); - let cjsDeps = bundle.externalModules.map( req ); - let globalDeps = bundle.externalModules.map( module => `global.${globalNameMaker( module )}` ); + const amdDeps = bundle.externalModules.map( quotePath ); + const cjsDeps = bundle.externalModules.map( req ); + const globalDeps = bundle.externalModules.map( module => globalProp(globalNameMaker( module )) ); - let args = bundle.externalModules.map( getName ); + const args = bundle.externalModules.map( getName ); if ( exportMode === 'named' ) { amdDeps.unshift( `'exports'` ); cjsDeps.unshift( `exports` ); - globalDeps.unshift( `(${setupNamespace(options.moduleName)} = global.${options.moduleName} || {})` ); + globalDeps.unshift( `(${setupNamespace(options.moduleName)} = ${globalProp(options.moduleName)} || {})` ); args.unshift( 'exports' ); } @@ -47,31 +57,35 @@ export default function umd ( bundle, magicString, { exportMode, indentString }, const globalExport = options.noConflict === true ? `(function() { - var current = global.${options.moduleName}; + var current = ${globalProp(options.moduleName)}; var exports = factory(${globalDeps}); - global.${options.moduleName} = exports; - exports.noConflict = function() { global.${options.moduleName} = current; return exports; }; + ${globalProp(options.moduleName)} = exports; + exports.noConflict = function() { ${globalProp(options.moduleName)} = current; return exports; }; })()` : `(${defaultExport}factory(${globalDeps}))`; - const intro = + const wrapperIntro = `(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? ${cjsExport}factory(${cjsDeps.join( ', ' )}) : typeof define === 'function' && define.amd ? define(${amdParams}factory) : ${globalExport}; - }(this, function (${args}) {${useStrict} + }(this, (function (${args}) {${useStrict} `.replace( /^\t\t/gm, '' ).replace( /^\t/gm, magicString.getIndentString() ); // var foo__default = 'default' in foo ? foo['default'] : foo; - const interopBlock = getInteropBlock( bundle ); + const interopBlock = getInteropBlock( bundle, options ); if ( interopBlock ) magicString.prepend( interopBlock + '\n\n' ); + if ( intro ) magicString.prepend( intro ); + const exportBlock = getExportBlock( bundle.entryModule, exportMode ); if ( exportBlock ) magicString.append( '\n\n' + exportBlock ); + if ( exportMode === 'named' && options.legacy !== true ) magicString.append( `\n\n${esModuleExport}` ); + if ( options.outro ) magicString.append( `\n${options.outro}` ); return magicString .trim() .indent( indentString ) - .append( '\n\n}));' ) - .prepend( intro ); + .append( wrapperOutro ) + .prepend( wrapperIntro ); } diff --git a/src/rollup.js b/src/rollup.js index 77a97bd103f..cf79500473b 100644 --- a/src/rollup.js +++ b/src/rollup.js @@ -1,7 +1,8 @@ -import Promise from 'es6-promise/lib/es6-promise/promise.js'; +import { timeStart, timeEnd, flushTime } from './utils/flushTime.js'; import { basename } from './utils/path.js'; import { writeFile } from './utils/fs.js'; -import { keys } from './utils/object.js'; +import { assign, keys } from './utils/object.js'; +import { mapSequence } from './utils/promise.js'; import validateKeys from './utils/validateKeys.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; import Bundle from './Bundle.js'; @@ -9,7 +10,10 @@ import Bundle from './Bundle.js'; export const VERSION = '<@VERSION@>'; const ALLOWED_KEYS = [ + 'acorn', 'banner', + 'cache', + 'context', 'dest', 'entry', 'exports', @@ -18,54 +22,87 @@ const ALLOWED_KEYS = [ 'format', 'globals', 'indent', + 'interop', 'intro', + 'legacy', + 'moduleContext', 'moduleId', 'moduleName', 'noConflict', 'onwarn', 'outro', + 'paths', 'plugins', 'preferConst', 'sourceMap', + 'sourceMapFile', + 'targets', 'treeshake', 'useStrict' ]; -export function rollup ( options ) { +function checkOptions ( options ) { if ( !options || !options.entry ) { - return Promise.reject( new Error( 'You must supply options.entry to rollup' ) ); + return new Error( 'You must supply options.entry to rollup' ); } if ( options.transform || options.load || options.resolveId || options.resolveExternal ) { - return Promise.reject( new Error( 'The `transform`, `load`, `resolveId` and `resolveExternal` options are deprecated in favour of a unified plugin API. See https://github.com/rollup/rollup/wiki/Plugins for details' ) ); + return new Error( 'The `transform`, `load`, `resolveId` and `resolveExternal` options are deprecated in favour of a unified plugin API. See https://github.com/rollup/rollup/wiki/Plugins for details' ); } - const error = validateKeys( options, ALLOWED_KEYS ); + const error = validateKeys( keys(options), ALLOWED_KEYS ); + if ( error ) return error; - if ( error ) { - return Promise.reject( error ); - } + return null; +} + +export function rollup ( options ) { + const error = checkOptions ( options ); + if ( error ) return Promise.reject( error ); const bundle = new Bundle( options ); + timeStart( '--BUILD--' ); + return bundle.build().then( () => { - return { + timeEnd( '--BUILD--' ); + + function generate ( options ) { + timeStart( '--GENERATE--' ); + + const rendered = bundle.render( options ); + + timeEnd( '--GENERATE--' ); + + bundle.plugins.forEach( plugin => { + if ( plugin.ongenerate ) { + plugin.ongenerate( assign({ + bundle: result + }, options ), rendered); + } + }); + + flushTime(); + + return rendered; + } + + const result = { imports: bundle.externalModules.map( module => module.id ), exports: keys( bundle.entryModule.exports ), - modules: bundle.orderedModules.map( module => { - return { id: module.id }; - }), + modules: bundle.orderedModules.map( module => module.toJSON() ), - generate: options => bundle.render( options ), + generate, write: options => { if ( !options || !options.dest ) { throw new Error( 'You must supply options.dest to bundle.write' ); } const dest = options.dest; - let { code, map } = bundle.render( options ); + const output = generate( options ); + let { code, map } = output; - let promises = []; + const promises = []; if ( options.sourceMap ) { let url; @@ -77,12 +114,20 @@ export function rollup ( options ) { promises.push( writeFile( dest + '.map', map.toString() ) ); } - code += `\n//# ${SOURCEMAPPING_URL}=${url}`; + code += `//# ${SOURCEMAPPING_URL}=${url}\n`; } promises.push( writeFile( dest, code ) ); - return Promise.all( promises ); + return Promise.all( promises ).then( () => { + return mapSequence( bundle.plugins.filter( plugin => plugin.onwrite ), plugin => { + return Promise.resolve( plugin.onwrite( assign({ + bundle: result + }, options ), output)); + }); + }); } }; + + return result; }); } diff --git a/src/utils/array.js b/src/utils/array.js new file mode 100644 index 00000000000..c7910e2fd6c --- /dev/null +++ b/src/utils/array.js @@ -0,0 +1,7 @@ +export function find ( array, fn ) { + for ( let i = 0; i < array.length; i += 1 ) { + if ( fn( array[i], i ) ) return array[i]; + } + + return null; +} diff --git a/src/utils/collapseSourcemaps.js b/src/utils/collapseSourcemaps.js index ff86eaf2c78..7a504bae2f1 100644 --- a/src/utils/collapseSourcemaps.js +++ b/src/utils/collapseSourcemaps.js @@ -1,44 +1,61 @@ -import { encode, decode } from 'sourcemap-codec'; +import { encode } from 'sourcemap-codec'; +import { dirname, relative, resolve } from './path.js'; class Source { - constructor ( index ) { + constructor ( filename, content ) { this.isOriginal = true; - this.index = index; + this.filename = filename; + this.content = content; } traceSegment ( line, column, name ) { - return { line, column, name, index: this.index }; + return { line, column, name, source: this }; } } class Link { constructor ( map, sources ) { - if ( !map ) throw new Error( 'Cannot generate a sourcemap if non-sourcemap-generating transformers are used' ); - this.sources = sources; this.names = map.names; - this.mappings = decode( map.mappings ); + this.mappings = map.mappings; } traceMappings () { - let names = []; + const sources = []; + const sourcesContent = []; + const names = []; const mappings = this.mappings.map( line => { - let tracedLine = []; + const tracedLine = []; line.forEach( segment => { const source = this.sources[ segment[1] ]; const traced = source.traceSegment( segment[2], segment[3], this.names[ segment[4] ] ); if ( traced ) { + let sourceIndex = null; let nameIndex = null; segment = [ segment[0], - traced.index, + null, traced.line, traced.column ]; + // newer sources are more likely to be used, so search backwards. + sourceIndex = sources.lastIndexOf( traced.source.filename ); + if ( sourceIndex === -1 ) { + sourceIndex = sources.length; + sources.push( traced.source.filename ); + sourcesContent[ sourceIndex ] = traced.source.content; + } else if ( sourcesContent[ sourceIndex ] == null ) { + sourcesContent[ sourceIndex ] = traced.source.content; + } else if ( traced.source.content != null && sourcesContent[ sourceIndex ] !== traced.source.content ) { + throw new Error( `Multiple conflicting contents for sourcemap source ${source.filename}` ); + } + + segment[1] = sourceIndex; + if ( traced.name ) { nameIndex = names.indexOf( traced.name ); if ( nameIndex === -1 ) { @@ -56,7 +73,7 @@ class Link { return tracedLine; }); - return { names, mappings }; + return { sources, sourcesContent, names, mappings }; } traceSegment ( line, column, name ) { @@ -81,29 +98,67 @@ class Link { } } -export default function collapseSourcemaps ( map, modules, bundleSourcemapChain ) { - const sources = modules.map( ( module, i ) => { - let source = new Source( i ); +export default function collapseSourcemaps ( file, map, modules, bundleSourcemapChain, onwarn ) { + const moduleSources = modules.filter( module => !module.excludeFromSourcemap ).map( module => { + let sourceMapChain = module.sourceMapChain; + + let source; + if ( module.originalSourceMap == null ) { + source = new Source( module.id, module.originalCode ); + } else { + const sources = module.originalSourceMap.sources; + const sourcesContent = module.originalSourceMap.sourcesContent || []; + + if ( sources == null || ( sources.length <= 1 && sources[0] == null ) ) { + source = new Source( module.id, sourcesContent[0] ); + sourceMapChain = [ module.originalSourceMap ].concat( sourceMapChain ); + } else { + // TODO indiscriminately treating IDs and sources as normal paths is probably bad. + const directory = dirname( module.id ) || '.'; + const sourceRoot = module.originalSourceMap.sourceRoot || '.'; + + const baseSources = sources.map( (source, i) => { + return new Source( resolve( directory, sourceRoot, source ), sourcesContent[i] ); + }); + + source = new Link( module.originalSourceMap, baseSources ); + } + } + + sourceMapChain.forEach( map => { + if ( map.missing ) { + onwarn( `Sourcemap is likely to be incorrect: a plugin${map.plugin ? ` ('${map.plugin}')` : ``} was used to transform files, but didn't generate a sourcemap for the transformation. Consult https://github.com/rollup/rollup/wiki/Troubleshooting and the plugin documentation for more information` ); + + map = { + names: [], + mappings: '' + }; + } - module.sourceMapChain.forEach( map => { source = new Link( map, [ source ]); }); return source; }); - let source = new Link( map, sources ); + let source = new Link( map, moduleSources ); bundleSourcemapChain.forEach( map => { source = new Link( map, [ source ] ); }); - const { names, mappings } = source.traceMappings(); + let { sources, sourcesContent, names, mappings } = source.traceMappings(); + + if ( file ) { + const directory = dirname( file ); + sources = sources.map( source => relative( directory, source ) ); + } // we re-use the `map` object because it has convenient toString/toURL methods - map.sourcesContent = modules.map( module => module.originalCode ); - map.mappings = encode( mappings ); + map.sources = sources; + map.sourcesContent = sourcesContent; map.names = names; + map.mappings = encode( mappings ); return map; } diff --git a/src/utils/defaults.js b/src/utils/defaults.js index d52553ef103..2dc0b744356 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -1,5 +1,5 @@ -import { lstatSync, readFileSync, realpathSync } from './fs.js'; -import { dirname, isAbsolute, resolve } from './path.js'; +import { lstatSync, readdirSync, readFileSync, realpathSync } from './fs.js'; +import { basename, dirname, isAbsolute, resolve } from './path.js'; import { blank } from './object.js'; export function load ( id ) { @@ -10,12 +10,16 @@ function findFile ( file ) { try { const stats = lstatSync( file ); if ( stats.isSymbolicLink() ) return findFile( realpathSync( file ) ); - if ( stats.isFile() ) return file; + if ( stats.isFile() ) { + // check case + const name = basename( file ); + const files = readdirSync( dirname( file ) ); + + if ( ~files.indexOf( name ) ) return file; + } } catch ( err ) { // suppress } - - return null; } function addJsExtensionIfNecessary ( file ) { @@ -26,7 +30,7 @@ export function resolveId ( importee, importer ) { if ( typeof process === 'undefined' ) throw new Error( `It looks like you're using Rollup in a non-Node.js environment. This means you must supply a plugin with custom resolveId and load functions. See https://github.com/rollup/rollup/wiki/Plugins for more information` ); // absolute paths are left untouched - if ( isAbsolute( importee ) ) return addJsExtensionIfNecessary( importee ); + if ( isAbsolute( importee ) ) return addJsExtensionIfNecessary( resolve( importee ) ); // if this is the entry point, resolve against cwd if ( importer === undefined ) return addJsExtensionIfNecessary( resolve( process.cwd(), importee ) ); @@ -39,7 +43,7 @@ export function resolveId ( importee, importer ) { export function makeOnwarn () { - let warned = blank(); + const warned = blank(); return msg => { if ( msg in warned ) return; diff --git a/src/utils/first.js b/src/utils/first.js index 21d6fe3aca1..72462461cd9 100644 --- a/src/utils/first.js +++ b/src/utils/first.js @@ -1,5 +1,3 @@ -import Promise from 'es6-promise/lib/es6-promise/promise.js'; - // Return the first non-falsy result from an array of // maybe-sync, maybe-promise-returning functions export default function first ( candidates ) { diff --git a/src/utils/flushTime.js b/src/utils/flushTime.js new file mode 100644 index 00000000000..9f32e455233 --- /dev/null +++ b/src/utils/flushTime.js @@ -0,0 +1,55 @@ +const DEBUG = false; +const map = new Map; + +let timeStartHelper; +let timeEndHelper; + +if ( typeof process === 'undefined' ) { + timeStartHelper = function timeStartHelper () { + return window.performance.now(); + }; + + timeEndHelper = function timeEndHelper ( previous ) { + return window.performance.now() - previous; + }; +} else { + timeStartHelper = function timeStartHelper () { + return process.hrtime(); + }; + + timeEndHelper = function timeEndHelper ( previous ) { + const hrtime = process.hrtime( previous ); + return hrtime[0] * 1e3 + Math.floor( hrtime[1] / 1e6 ); + }; +} + +export function timeStart ( label ) { + if ( !map.has( label ) ) { + map.set( label, { + time: 0 + }); + } + map.get( label ).start = timeStartHelper(); +} + +export function timeEnd ( label ) { + if ( map.has( label ) ) { + const item = map.get( label ); + item.time += timeEndHelper( item.start ); + } +} + +export function flushTime ( log = defaultLog ) { + for ( const item of map.entries() ) { + log( item[0], item[1].time ); + } + map.clear(); +} + +function defaultLog ( label, time ) { + if ( DEBUG ) { + /* eslint-disable no-console */ + console.info( '%dms: %s', time, label ); + /* eslint-enable no-console */ + } +} diff --git a/src/utils/fs.js b/src/utils/fs.js index 2afe00be6f6..db790a95056 100644 --- a/src/utils/fs.js +++ b/src/utils/fs.js @@ -1,4 +1,3 @@ -import Promise from 'es6-promise/lib/es6-promise/promise.js'; import * as fs from 'fs'; import { dirname } from './path.js'; diff --git a/src/utils/getExportMode.js b/src/utils/getExportMode.js index f37ff1edf56..a3d00a0004b 100644 --- a/src/utils/getExportMode.js +++ b/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(', ')}` ); } -export default function getExportMode ( bundle, exportMode, moduleName ) { +export default function getExportMode ( bundle, {exports: exportMode, moduleName, format} ) { const exportKeys = keys( bundle.entryModule.exports ) .concat( keys( bundle.entryModule.reexports ) ) .concat( bundle.entryModule.exportAllSources ); // not keys, but makes our job easier this way @@ -23,7 +23,7 @@ export default function getExportMode ( bundle, exportMode, moduleName ) { } else if ( exportKeys.length === 1 && exportKeys[0] === 'default' ) { exportMode = 'default'; } else { - if ( bundle.entryModule.exports.default ) { + if ( bundle.entryModule.exports.default && format !== 'es') { 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'; diff --git a/src/utils/getIndentString.js b/src/utils/getIndentString.js index 8ad7b558eeb..5130ed876ba 100644 --- a/src/utils/getIndentString.js +++ b/src/utils/getIndentString.js @@ -1,5 +1,5 @@ export default function getIndentString ( magicString, options ) { - if ( !( 'indent' in options ) || options.indent === true ) { + if ( options.indent === true ) { return magicString.getIndentString(); } diff --git a/src/utils/makeLegalIdentifier.js b/src/utils/makeLegalIdentifier.js index fd75ee8fae7..846c42e158f 100644 --- a/src/utils/makeLegalIdentifier.js +++ b/src/utils/makeLegalIdentifier.js @@ -1,9 +1,9 @@ import { blank } from './object.js'; -const reservedWords = 'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public'.split( ' ' ); +export const reservedWords = 'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public'.split( ' ' ); const builtins = 'Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl'.split( ' ' ); -let blacklisted = blank(); +const blacklisted = blank(); reservedWords.concat( builtins ).forEach( word => blacklisted[ word ] = true ); diff --git a/src/utils/map-helpers.js b/src/utils/map-helpers.js index 49e094246c3..6ce7293bd17 100644 --- a/src/utils/map-helpers.js +++ b/src/utils/map-helpers.js @@ -2,10 +2,10 @@ export function getName ( x ) { return x.name; } -export function quoteId ( x ) { - return `'${x.id}'`; +export function quotePath ( x ) { + return `'${x.path}'`; } export function req ( x ) { - return `require('${x.id}')`; + return `require('${x.path}')`; } diff --git a/src/utils/normalizePlatform.js b/src/utils/normalizePlatform.js deleted file mode 100644 index 5c8fd335e8e..00000000000 --- a/src/utils/normalizePlatform.js +++ /dev/null @@ -1,3 +0,0 @@ -export function unixizePath ( path ) { - return path.split( /[\/\\]/ ).join( '/' ); -} diff --git a/src/utils/object.js b/src/utils/object.js index b4e1ff1c8a2..947c8e18f7a 100644 --- a/src/utils/object.js +++ b/src/utils/object.js @@ -7,3 +7,34 @@ export function blank () { export function forOwn ( object, func ) { Object.keys( object ).forEach( key => func( object[ key ], key ) ); } + +export function assign ( target, ...sources ) { + sources.forEach( source => { + for ( const key in source ) { + if ( source.hasOwnProperty( key ) ) target[ key ] = source[ key ]; + } + }); + + return target; +} + +const isArray = Array.isArray; + +// used for cloning ASTs. Not for use with cyclical structures! +export function deepClone ( obj ) { + if ( !obj ) return obj; + if ( typeof obj !== 'object' ) return obj; + + if ( isArray( obj ) ) { + const clone = new Array( obj.length ); + for ( let i = 0; i < obj.length; i += 1 ) clone[i] = deepClone( obj[i] ); + return clone; + } + + const clone = {}; + for ( const key in obj ) { + clone[ key ] = deepClone( obj[ key ] ); + } + + return clone; +} diff --git a/src/utils/path.js b/src/utils/path.js index ec749a4d8a2..d2ce64d0a46 100644 --- a/src/utils/path.js +++ b/src/utils/path.js @@ -1,5 +1,3 @@ -// TODO does this all work on windows? - export const absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|\/])/; export const relativePath = /^\.?\.\//; @@ -11,68 +9,8 @@ export function isRelative ( path ) { return relativePath.test( path ); } -export function basename ( path ) { - return path.split( /(\/|\\)/ ).pop(); -} - -export function dirname ( path ) { - const match = /(\/|\\)[^\/\\]*$/.exec( path ); - if ( !match ) return '.'; - - const dir = path.slice( 0, -match[0].length ); - - // If `dir` is the empty string, we're at root. - return dir ? dir : '/'; -} - -export function extname ( path ) { - const match = /\.[^\.]+$/.exec( basename( path ) ); - if ( !match ) return ''; - return match[0]; -} - -export function relative ( from, to ) { - const fromParts = from.split( /[\/\\]/ ).filter( Boolean ); - const toParts = to.split( /[\/\\]/ ).filter( Boolean ); - - while ( fromParts[0] && toParts[0] && fromParts[0] === toParts[0] ) { - fromParts.shift(); - toParts.shift(); - } - - while ( toParts[0] === '.' || toParts[0] === '..' ) { - const toPart = toParts.shift(); - if ( toPart === '..' ) { - fromParts.pop(); - } - } - - while ( fromParts.pop() ) { - toParts.unshift( '..' ); - } - - return toParts.join( '/' ); +export function normalize ( path ) { + return path.replace( /\\/g, '/' ); } -export function resolve ( ...paths ) { - let resolvedParts = paths.shift().split( /[\/\\]/ ); - - paths.forEach( path => { - if ( isAbsolute( path ) ) { - resolvedParts = path.split( /[\/\\]/ ); - } else { - const parts = path.split( /[\/\\]/ ); - - while ( parts[0] === '.' || parts[0] === '..' ) { - const part = parts.shift(); - if ( part === '..' ) { - resolvedParts.pop(); - } - } - - resolvedParts.push.apply( resolvedParts, parts ); - } - }); - - return resolvedParts.join( '/' ); // TODO windows... -} +export { basename, dirname, extname, relative, resolve } from 'path'; diff --git a/src/utils/promise.js b/src/utils/promise.js index 1730de81589..096343c02e3 100644 --- a/src/utils/promise.js +++ b/src/utils/promise.js @@ -1,7 +1,5 @@ -import Promise from 'es6-promise/lib/es6-promise/promise.js'; - export function mapSequence ( array, fn ) { - let results = []; + const results = []; let promise = Promise.resolve(); function next ( member, i ) { diff --git a/src/utils/relativeId.js b/src/utils/relativeId.js new file mode 100644 index 00000000000..e26bd0240d1 --- /dev/null +++ b/src/utils/relativeId.js @@ -0,0 +1,4 @@ +export default function relativeId ( id ) { + if ( typeof process === 'undefined' ) return id; + return id.replace( process.cwd(), '' ).replace( /^[\/\\]/, '' ); +} diff --git a/src/utils/run.js b/src/utils/run.js deleted file mode 100644 index 3e91d637e45..00000000000 --- a/src/utils/run.js +++ /dev/null @@ -1,119 +0,0 @@ -import { walk } from 'estree-walker'; -import modifierNodes, { isModifierNode } from '../ast/modifierNodes.js'; -import isReference from '../ast/isReference.js'; -import flatten from '../ast/flatten'; -import pureFunctions from './pureFunctions.js'; -import getLocation from './getLocation.js'; -import error from './error.js'; - -function call ( callee, scope, statement, strongDependencies ) { - while ( callee.type === 'ParenthesizedExpression' ) callee = callee.expression; - - if ( callee.type === 'Identifier' ) { - const declaration = scope.findDeclaration( callee.name ) || - statement.module.trace( callee.name ); - - if ( declaration ) { - if ( declaration.isNamespace ) { - error({ - message: `Cannot call a namespace ('${callee.name}')`, - file: statement.module.id, - pos: callee.start, - loc: getLocation( statement.module.code, callee.start ) - }); - } - - return declaration.run( strongDependencies ); - } - - return !pureFunctions[ callee.name ]; - } - - if ( /FunctionExpression/.test( callee.type ) ) { - return run( callee.body, scope, statement, strongDependencies ); - } - - if ( callee.type === 'MemberExpression' ) { - const flattened = flatten( callee ); - - if ( flattened ) { - // if we're calling e.g. Object.keys(thing), there are no side-effects - // TODO make pureFunctions configurable - const declaration = scope.findDeclaration( flattened.name ) || statement.module.trace( flattened.name ); - - return ( !!declaration || !pureFunctions[ flattened.keypath ] ); - } - } - - // complex case like `( a ? b : c )()` or foo[bar].baz()` - // – err on the side of caution - return true; -} - -export default function run ( node, scope, statement, strongDependencies, force ) { - let hasSideEffect = false; - - walk( node, { - enter ( node, parent ) { - if ( !force && /Function/.test( node.type ) ) return this.skip(); - - if ( node._scope ) scope = node._scope; - - if ( isReference( node, parent ) ) { - const flattened = flatten( node ); - - if ( flattened.name === 'arguments' ) { - hasSideEffect = true; - } - - else if ( !scope.contains( flattened.name ) ) { - const declaration = statement.module.trace( flattened.name ); - if ( declaration && !declaration.isExternal ) { - const module = declaration.module || declaration.statement.module; // TODO is this right? - if ( !module.isExternal && !~strongDependencies.indexOf( module ) ) strongDependencies.push( module ); - } - } - } - - else if ( node.type === 'DebuggerStatement' ) { - hasSideEffect = true; - } - - else if ( node.type === 'ThrowStatement' ) { - // we only care about errors thrown at the top level, otherwise - // any function with error checking gets included if called - if ( scope.isTopLevel ) hasSideEffect = true; - } - - else if ( node.type === 'CallExpression' || node.type === 'NewExpression' ) { - if ( call( node.callee, scope, statement, strongDependencies ) ) { - hasSideEffect = true; - } - } - - else if ( isModifierNode( node ) ) { - let subject = node[ modifierNodes[ node.type ] ]; - while ( subject.type === 'MemberExpression' ) subject = subject.object; - - let declaration = scope.findDeclaration( subject.name ); - - if ( declaration ) { - if ( declaration.isParam ) hasSideEffect = true; - } else if ( !scope.isTopLevel ) { - hasSideEffect = true; - } else { - declaration = statement.module.trace( subject.name ); - - if ( !declaration || declaration.isExternal || declaration.isUsed ) { - hasSideEffect = true; - } - } - } - }, - leave ( node ) { - if ( node._scope ) scope = scope.parent; - } - }); - - return hasSideEffect; -} diff --git a/src/utils/transform.js b/src/utils/transform.js index b4013707145..2f0c167b40c 100644 --- a/src/utils/transform.js +++ b/src/utils/transform.js @@ -1,21 +1,22 @@ -import Promise from 'es6-promise/lib/es6-promise/promise.js'; +import { decode } from 'sourcemap-codec'; -export default function transform ( source, id, transformers ) { - let sourceMapChain = []; +export default function transform ( source, id, plugins ) { + const sourceMapChain = []; - if ( typeof source === 'string' ) { - source = { - code: source, - ast: null - }; + const originalSourceMap = typeof source.map === 'string' ? JSON.parse( source.map ) : source.map; + + if ( originalSourceMap && typeof originalSourceMap.mappings === 'string' ) { + originalSourceMap.mappings = decode( originalSourceMap.mappings ); } - let originalCode = source.code; + const originalCode = source.code; let ast = source.ast; - return transformers.reduce( ( promise, transformer ) => { + return plugins.reduce( ( promise, plugin ) => { return promise.then( previous => { - return Promise.resolve( transformer( previous, id ) ).then( result => { + if ( !plugin.transform ) return previous; + + return Promise.resolve( plugin.transform( previous, id ) ).then( result => { if ( result == null ) return previous; if ( typeof result === 'string' ) { @@ -30,19 +31,25 @@ export default function transform ( source, id, transformers ) { result.map = JSON.parse( result.map ); } - sourceMapChain.push( result.map ); + if ( result.map && typeof result.map.mappings === 'string' ) { + result.map.mappings = decode( result.map.mappings ); + } + + sourceMapChain.push( result.map || { missing: true, plugin: plugin.name }); // lil' bit hacky but it works ast = result.ast; return result.code; }); + }).catch( err => { + if ( !err.rollupTransform ) { + err.rollupTransform = true; + err.id = id; + err.plugin = plugin.name; + err.message = `Error transforming ${id}${plugin.name ? ` with '${plugin.name}' plugin` : ''}: ${err.message}`; + } + throw err; }); - }, Promise.resolve( source.code ) ) - .then( code => ({ code, originalCode, ast, sourceMapChain }) ) - .catch( err => { - err.id = id; - err.message = `Error loading ${id}: ${err.message}`; - throw err; - }); + .then( code => ({ code, originalCode, originalSourceMap, ast, sourceMapChain }) ); } diff --git a/src/utils/transformBundle.js b/src/utils/transformBundle.js index f82bfb6ec9a..8569ad560e2 100644 --- a/src/utils/transformBundle.js +++ b/src/utils/transformBundle.js @@ -1,6 +1,18 @@ -export default function transformBundle ( code, transformers, sourceMapChain ) { - return transformers.reduce( ( code, transformer ) => { - let result = transformer( code ); +import { decode } from 'sourcemap-codec'; + +export default function transformBundle ( code, plugins, sourceMapChain, options ) { + return plugins.reduce( ( code, plugin ) => { + if ( !plugin.transformBundle ) return code; + + let result; + + try { + result = plugin.transformBundle( code, { format : options.format } ); + } catch ( err ) { + err.plugin = plugin.name; + err.message = `Error transforming bundle${plugin.name ? ` with '${plugin.name}' plugin` : ''}: ${err.message}`; + throw err; + } if ( result == null ) return code; @@ -11,7 +23,11 @@ export default function transformBundle ( code, transformers, sourceMapChain ) { }; } - const map = typeof result.map === 'string' ? JSON.parse( result.map ) : map; + const map = typeof result.map === 'string' ? JSON.parse( result.map ) : result.map; + if ( map && typeof map.mappings === 'string' ) { + map.mappings = decode( map.mappings ); + } + sourceMapChain.push( map ); return result.code; diff --git a/src/utils/validateKeys.js b/src/utils/validateKeys.js index 3ff51cdc340..d717b0a46bd 100644 --- a/src/utils/validateKeys.js +++ b/src/utils/validateKeys.js @@ -1,8 +1,4 @@ -import { keys } from './object.js'; - -export default function validateKeys ( object, allowedKeys ) { - const actualKeys = keys( object ); - +export default function validateKeys ( actualKeys, allowedKeys ) { let i = actualKeys.length; while ( i-- ) { diff --git a/test/.babelrc b/test/.babelrc deleted file mode 100644 index e4491c20282..00000000000 --- a/test/.babelrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "whitelist": [ - "es6.arrowFunctions", - "es6.blockScoping", - "es6.classes", - "es6.constants", - "es6.destructuring", - "es6.modules", - "es6.parameters", - "es6.properties.shorthand", - "es6.spread", - "es6.templateLiterals" - ], - "loose": [ - "es6.classes", - "es6.destructuring" - ], - "compact": false, - "sourceMap": true -} diff --git a/test/.eslintrc b/test/.eslintrc new file mode 100644 index 00000000000..3f85d4c7d3d --- /dev/null +++ b/test/.eslintrc @@ -0,0 +1,9 @@ +{ + "rules": { + "no-console": [ 0 ], + "no-unused-vars": [ "error", { "vars": "all", "args": "none" } ] + }, + "env": { + "mocha": true + } +} diff --git a/test/cli/banner-intro-outro-footer/_config.js b/test/cli/banner-intro-outro-footer/_config.js index 2e30a3c0e10..2d676391077 100644 --- a/test/cli/banner-intro-outro-footer/_config.js +++ b/test/cli/banner-intro-outro-footer/_config.js @@ -1,4 +1,4 @@ module.exports = { description: 'adds banner/intro/outro/footer', - command: 'rollup -i main.js -f iife --banner "// banner" --intro "// intro" --outro "// outro" --footer "// footer"' + command: 'rollup -i main.js -f iife --indent --banner "// banner" --intro "// intro" --outro "// outro" --footer "// footer"' }; diff --git a/test/cli/config-cwd-case-insensitive/_config.js b/test/cli/config-cwd-case-insensitive/_config.js new file mode 100644 index 00000000000..c0df3fcb042 --- /dev/null +++ b/test/cli/config-cwd-case-insensitive/_config.js @@ -0,0 +1,13 @@ +var os = require( 'os' ); + +function toggleCase ( s ) { + return ( s == s.toLowerCase() ) ? s.toUpperCase() : s.toLowerCase(); +} + +module.exports = { + skip: os.platform() !== 'win32', + description: "can load config with cwd that doesn't match realpath", + command: 'rollup -c', + cwd: __dirname.replace( /^[A-Z]:\\/i, toggleCase ), + execute: true +}; diff --git a/test/cli/config-cwd-case-insensitive/main.js b/test/cli/config-cwd-case-insensitive/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/config-cwd-case-insensitive/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/config-cwd-case-insensitive/rollup.config.js b/test/cli/config-cwd-case-insensitive/rollup.config.js new file mode 100644 index 00000000000..3cc995e2f4a --- /dev/null +++ b/test/cli/config-cwd-case-insensitive/rollup.config.js @@ -0,0 +1,9 @@ +var replace = require( 'rollup-plugin-replace' ); + +module.exports = { + entry: 'main.js', + format: 'cjs', + plugins: [ + replace({ 'ANSWER': 42 }) + ] +}; diff --git a/test/cli/config-external-function/_config.js b/test/cli/config-external-function/_config.js new file mode 100644 index 00000000000..9f21d968ead --- /dev/null +++ b/test/cli/config-external-function/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'external option gets passed from config', + command: 'rollup -c -e assert,external-module' +}; diff --git a/test/cli/config-external-function/_expected.js b/test/cli/config-external-function/_expected.js new file mode 100644 index 00000000000..d760df4b168 --- /dev/null +++ b/test/cli/config-external-function/_expected.js @@ -0,0 +1,8 @@ +'use strict'; + +var ___config_js = require('./_config.js'); +var assert = require('assert'); +var externalModule = require('external-module'); + +assert.ok( ___config_js.execute ); +externalModule.method(); diff --git a/test/cli/config-external-function/main.js b/test/cli/config-external-function/main.js new file mode 100644 index 00000000000..cfefa8cf535 --- /dev/null +++ b/test/cli/config-external-function/main.js @@ -0,0 +1,6 @@ +import { execute } from './_config.js'; +import { ok } from 'assert'; +import { method } from 'external-module'; + +ok( execute ); +method(); diff --git a/test/cli/config-external-function/rollup.config.js b/test/cli/config-external-function/rollup.config.js new file mode 100644 index 00000000000..10362207963 --- /dev/null +++ b/test/cli/config-external-function/rollup.config.js @@ -0,0 +1,21 @@ +import assert from 'assert'; +import { resolve } from 'path'; + +var config = resolve( './_config.js' ); + +export default { + entry: 'main.js', + format: 'cjs', + + external: function ( id ) { + return id === config; + }, + + plugins: [ + { + load: function ( id ) { + assert.notEqual( id, config ); + } + } + ] +}; diff --git a/test/cli/external-modules-auto-global/_config.js b/test/cli/external-modules-auto-global/_config.js new file mode 100644 index 00000000000..9f3e784156f --- /dev/null +++ b/test/cli/external-modules-auto-global/_config.js @@ -0,0 +1,5 @@ +module.exports = { + description: 'populates options.external with --global keys', + command: 'rollup main.js --format iife --globals mathematics:Math', + execute: true +}; diff --git a/test/cli/external-modules-auto-global/main.js b/test/cli/external-modules-auto-global/main.js new file mode 100644 index 00000000000..dcd8569f77f --- /dev/null +++ b/test/cli/external-modules-auto-global/main.js @@ -0,0 +1,3 @@ +import { max } from 'mathematics'; + +assert.equal( max( 1, 2, 3 ), 3 ); diff --git a/test/cli/indent-none/_config.js b/test/cli/indent-none/_config.js index a9d130708bb..e37aead6bc1 100644 --- a/test/cli/indent-none/_config.js +++ b/test/cli/indent-none/_config.js @@ -1,5 +1,3 @@ -var assert = require( 'assert' ); - module.exports = { description: 'disables indentation with --no-indent', command: 'rollup main.js --format umd --no-indent' diff --git a/test/cli/indent-none/_expected.js b/test/cli/indent-none/_expected.js index 414587c98e9..343dda26134 100644 --- a/test/cli/indent-none/_expected.js +++ b/test/cli/indent-none/_expected.js @@ -2,8 +2,8 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; assert.equal( 1 + 1, 2 ); -})); +}))); diff --git a/test/cli/module-name/_config.js b/test/cli/module-name/_config.js index da790e488e4..ca5d167ab90 100644 --- a/test/cli/module-name/_config.js +++ b/test/cli/module-name/_config.js @@ -1,4 +1,4 @@ module.exports = { description: 'generates UMD export with correct moduleName', - command: 'rollup main.js --format umd --name myBundle' + command: 'rollup main.js --format umd --name myBundle --indent' }; diff --git a/test/cli/module-name/_expected.js b/test/cli/module-name/_expected.js index 4a351acdb73..2f715871718 100644 --- a/test/cli/module-name/_expected.js +++ b/test/cli/module-name/_expected.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); +}))); diff --git a/test/cli/multiple-targets-shared-config/_config.js b/test/cli/multiple-targets-shared-config/_config.js new file mode 100644 index 00000000000..6d7125c8d54 --- /dev/null +++ b/test/cli/multiple-targets-shared-config/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'uses shared config for each target', + command: 'rollup -c' +}; diff --git a/test/cli/multiple-targets-shared-config/_expected/cjs.js b/test/cli/multiple-targets-shared-config/_expected/cjs.js new file mode 100644 index 00000000000..d3b3eb093fe --- /dev/null +++ b/test/cli/multiple-targets-shared-config/_expected/cjs.js @@ -0,0 +1,6 @@ +'use strict'; + +var main = 0; + +module.exports = main; +//# sourceMappingURL=cjs.js.map \ No newline at end of file diff --git a/test/cli/multiple-targets-shared-config/_expected/cjs.js.map b/test/cli/multiple-targets-shared-config/_expected/cjs.js.map new file mode 100644 index 00000000000..d88316aa0c2 --- /dev/null +++ b/test/cli/multiple-targets-shared-config/_expected/cjs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cjs.js","sources":["../main.js"],"sourcesContent":["export default 0;\n"],"names":[],"mappings":";;AAAA,WAAe,CAAC,CAAC,;;"} diff --git a/test/cli/multiple-targets-shared-config/_expected/es.js b/test/cli/multiple-targets-shared-config/_expected/es.js new file mode 100644 index 00000000000..9c36d9fe10b --- /dev/null +++ b/test/cli/multiple-targets-shared-config/_expected/es.js @@ -0,0 +1,4 @@ +var main = 0; + +export default main; +//# sourceMappingURL=es.js.map diff --git a/test/cli/multiple-targets-shared-config/_expected/es.js.map b/test/cli/multiple-targets-shared-config/_expected/es.js.map new file mode 100644 index 00000000000..6cc964bb83f --- /dev/null +++ b/test/cli/multiple-targets-shared-config/_expected/es.js.map @@ -0,0 +1 @@ +{"version":3,"file":"es.js","sources":["../main.js"],"sourcesContent":["export default 0;\n"],"names":[],"mappings":"AAAA,WAAe,CAAC,CAAC,;;"} diff --git a/test/cli/multiple-targets-shared-config/main.js b/test/cli/multiple-targets-shared-config/main.js new file mode 100644 index 00000000000..7f810d3f328 --- /dev/null +++ b/test/cli/multiple-targets-shared-config/main.js @@ -0,0 +1 @@ +export default 0; diff --git a/test/cli/multiple-targets-shared-config/rollup.config.js b/test/cli/multiple-targets-shared-config/rollup.config.js new file mode 100644 index 00000000000..1a2d8a19698 --- /dev/null +++ b/test/cli/multiple-targets-shared-config/rollup.config.js @@ -0,0 +1,14 @@ +export default { + entry: 'main.js', + sourceMap: true, + targets: [ + { + format: 'cjs', + dest: '_actual/cjs.js' + }, + { + format: 'es', + dest: '_actual/es.js' + } + ] +}; diff --git a/test/cli/multiple-targets/_config.js b/test/cli/multiple-targets/_config.js new file mode 100644 index 00000000000..73d5d28f379 --- /dev/null +++ b/test/cli/multiple-targets/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'generates multiple output files when multiple targets are specified', + command: 'rollup -c' +}; diff --git a/test/cli/multiple-targets/_expected/cjs.js b/test/cli/multiple-targets/_expected/cjs.js new file mode 100644 index 00000000000..98deb0cc09f --- /dev/null +++ b/test/cli/multiple-targets/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +var main = 0; + +module.exports = main; diff --git a/test/cli/multiple-targets/_expected/es.js b/test/cli/multiple-targets/_expected/es.js new file mode 100644 index 00000000000..d3265929a72 --- /dev/null +++ b/test/cli/multiple-targets/_expected/es.js @@ -0,0 +1,3 @@ +var main = 0; + +export default main; diff --git a/test/cli/multiple-targets/main.js b/test/cli/multiple-targets/main.js new file mode 100644 index 00000000000..7f810d3f328 --- /dev/null +++ b/test/cli/multiple-targets/main.js @@ -0,0 +1 @@ +export default 0; diff --git a/test/cli/multiple-targets/rollup.config.js b/test/cli/multiple-targets/rollup.config.js new file mode 100644 index 00000000000..f12e0c778a8 --- /dev/null +++ b/test/cli/multiple-targets/rollup.config.js @@ -0,0 +1,13 @@ +export default { + entry: 'main.js', + targets: [ + { + format: 'cjs', + dest: '_actual/cjs.js' + }, + { + format: 'es', + dest: '_actual/es.js' + } + ] +}; diff --git a/test/cli/no-conflict/_config.js b/test/cli/no-conflict/_config.js new file mode 100644 index 00000000000..cc870f8a263 --- /dev/null +++ b/test/cli/no-conflict/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'respects noConflict option', + command: 'rollup --config rollup.config.js' +}; diff --git a/test/cli/no-conflict/_expected.js b/test/cli/no-conflict/_expected.js new file mode 100644 index 00000000000..1b363c90eaf --- /dev/null +++ b/test/cli/no-conflict/_expected.js @@ -0,0 +1,16 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (function() { + var current = global.conflictyName; + var exports = factory(); + global.conflictyName = exports; + exports.noConflict = function() { global.conflictyName = current; return exports; }; + })(); +}(this, (function () { 'use strict'; + +var main = {}; + +return main; + +}))); diff --git a/test/cli/no-conflict/main.js b/test/cli/no-conflict/main.js new file mode 100644 index 00000000000..ff8b4c56321 --- /dev/null +++ b/test/cli/no-conflict/main.js @@ -0,0 +1 @@ +export default {}; diff --git a/test/cli/no-conflict/rollup.config.js b/test/cli/no-conflict/rollup.config.js new file mode 100644 index 00000000000..a1b8d7d86f0 --- /dev/null +++ b/test/cli/no-conflict/rollup.config.js @@ -0,0 +1,6 @@ +module.exports = { + entry: 'main.js', + format: 'umd', + moduleName: 'conflictyName', + noConflict: true +}; diff --git a/test/cli/no-strict/_config.js b/test/cli/no-strict/_config.js new file mode 100644 index 00000000000..72d4a3242ee --- /dev/null +++ b/test/cli/no-strict/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'use no strict option', + command: 'rollup -i main.js -f iife --no-strict --indent' +}; diff --git a/test/cli/no-strict/_expected.js b/test/cli/no-strict/_expected.js new file mode 100644 index 00000000000..d7c1012673c --- /dev/null +++ b/test/cli/no-strict/_expected.js @@ -0,0 +1,4 @@ +(function () { + console.log( 42 ); + +}()); diff --git a/test/cli/no-strict/main.js b/test/cli/no-strict/main.js new file mode 100644 index 00000000000..5c72ff35124 --- /dev/null +++ b/test/cli/no-strict/main.js @@ -0,0 +1 @@ +console.log( 42 ); diff --git a/test/cli/no-treeshake/_config.js b/test/cli/no-treeshake/_config.js index 18d8b6911d6..be25c453098 100644 --- a/test/cli/no-treeshake/_config.js +++ b/test/cli/no-treeshake/_config.js @@ -1,4 +1,4 @@ module.exports = { description: 'generates IIFE export with all code', - command: 'rollup main.js --format iife --name shakeless --no-treeshake' + command: 'rollup main.js --format iife --name shakeless --no-treeshake --indent' }; diff --git a/test/cli/node-config-auto-prefix/_config.js b/test/cli/node-config-auto-prefix/_config.js new file mode 100644 index 00000000000..88b1368e750 --- /dev/null +++ b/test/cli/node-config-auto-prefix/_config.js @@ -0,0 +1,5 @@ +module.exports = { + description: 'uses config file installed from npm', + command: 'rollup --config node:foo', + execute: true +}; diff --git a/test/cli/node-config-auto-prefix/_expected.js b/test/cli/node-config-auto-prefix/_expected.js new file mode 100644 index 00000000000..b5aa08a6ad6 --- /dev/null +++ b/test/cli/node-config-auto-prefix/_expected.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.myBundle = factory(); +}(this, function () { 'use strict'; + + var main = 42; + + return main; + +})); diff --git a/test/cli/node-config-auto-prefix/main.js b/test/cli/node-config-auto-prefix/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/node-config-auto-prefix/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/lib/config.js b/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/lib/config.js new file mode 100644 index 00000000000..3cc995e2f4a --- /dev/null +++ b/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/lib/config.js @@ -0,0 +1,9 @@ +var replace = require( 'rollup-plugin-replace' ); + +module.exports = { + entry: 'main.js', + format: 'cjs', + plugins: [ + replace({ 'ANSWER': 42 }) + ] +}; diff --git a/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/package.json b/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/package.json new file mode 100644 index 00000000000..fbd490130d0 --- /dev/null +++ b/test/cli/node-config-auto-prefix/node_modules/rollup-config-foo/package.json @@ -0,0 +1,3 @@ +{ + "main": "lib/config.js" +} diff --git a/test/cli/node-config/_config.js b/test/cli/node-config/_config.js new file mode 100644 index 00000000000..88b1368e750 --- /dev/null +++ b/test/cli/node-config/_config.js @@ -0,0 +1,5 @@ +module.exports = { + description: 'uses config file installed from npm', + command: 'rollup --config node:foo', + execute: true +}; diff --git a/test/cli/node-config/_expected.js b/test/cli/node-config/_expected.js new file mode 100644 index 00000000000..b5aa08a6ad6 --- /dev/null +++ b/test/cli/node-config/_expected.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.myBundle = factory(); +}(this, function () { 'use strict'; + + var main = 42; + + return main; + +})); diff --git a/test/cli/node-config/main.js b/test/cli/node-config/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/node-config/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/node-config/node_modules/foo/lib/config.js b/test/cli/node-config/node_modules/foo/lib/config.js new file mode 100644 index 00000000000..3cc995e2f4a --- /dev/null +++ b/test/cli/node-config/node_modules/foo/lib/config.js @@ -0,0 +1,9 @@ +var replace = require( 'rollup-plugin-replace' ); + +module.exports = { + entry: 'main.js', + format: 'cjs', + plugins: [ + replace({ 'ANSWER': 42 }) + ] +}; diff --git a/test/cli/node-config/node_modules/foo/package.json b/test/cli/node-config/node_modules/foo/package.json new file mode 100644 index 00000000000..fbd490130d0 --- /dev/null +++ b/test/cli/node-config/node_modules/foo/package.json @@ -0,0 +1,3 @@ +{ + "main": "lib/config.js" +} diff --git a/test/cli/sourcemap-newline/_config.js b/test/cli/sourcemap-newline/_config.js new file mode 100644 index 00000000000..14276190df7 --- /dev/null +++ b/test/cli/sourcemap-newline/_config.js @@ -0,0 +1,9 @@ +const assert = require( 'assert' ); + +module.exports = { + description: 'adds a newline after the sourceMappingURL comment (#756)', + command: 'rollup -i main.js -m inline', + result: code => { + assert.equal( code.slice( -1 ), '\n' ); + } +}; diff --git a/test/cli/sourcemap-newline/main.js b/test/cli/sourcemap-newline/main.js new file mode 100644 index 00000000000..5c72ff35124 --- /dev/null +++ b/test/cli/sourcemap-newline/main.js @@ -0,0 +1 @@ +console.log( 42 ); diff --git a/test/form/absolute-path-resolver/_config.js b/test/form/absolute-path-resolver/_config.js new file mode 100644 index 00000000000..a2f129c2e02 --- /dev/null +++ b/test/form/absolute-path-resolver/_config.js @@ -0,0 +1,14 @@ +var path = require('path'); + +module.exports = { + description: 'normalizes absolute ids', + options: { + plugins: [{ + transform: function (code, id) { + if (/main/.test(id)) { + return code.replace('"./a.js"', JSON.stringify(path.resolve(__dirname, 'a.js'))); + } + } + }] + } +}; diff --git a/test/form/absolute-path-resolver/_expected/amd.js b/test/form/absolute-path-resolver/_expected/amd.js new file mode 100644 index 00000000000..4718f2e6862 --- /dev/null +++ b/test/form/absolute-path-resolver/_expected/amd.js @@ -0,0 +1,10 @@ +define(function () { 'use strict'; + + var a = () => { + console.log('props'); + }; + + a(); + a(); + +}); \ No newline at end of file diff --git a/test/form/absolute-path-resolver/_expected/cjs.js b/test/form/absolute-path-resolver/_expected/cjs.js new file mode 100644 index 00000000000..473b57e0197 --- /dev/null +++ b/test/form/absolute-path-resolver/_expected/cjs.js @@ -0,0 +1,8 @@ +'use strict'; + +var a = () => { + console.log('props'); +}; + +a(); +a(); \ No newline at end of file diff --git a/test/form/absolute-path-resolver/_expected/es.js b/test/form/absolute-path-resolver/_expected/es.js new file mode 100644 index 00000000000..0415d2c05c3 --- /dev/null +++ b/test/form/absolute-path-resolver/_expected/es.js @@ -0,0 +1,6 @@ +var a = () => { + console.log('props'); +}; + +a(); +a(); \ No newline at end of file diff --git a/test/form/absolute-path-resolver/_expected/iife.js b/test/form/absolute-path-resolver/_expected/iife.js new file mode 100644 index 00000000000..cb9df4a40c8 --- /dev/null +++ b/test/form/absolute-path-resolver/_expected/iife.js @@ -0,0 +1,11 @@ +(function () { + 'use strict'; + + var a = () => { + console.log('props'); + }; + + a(); + a(); + +}()); \ No newline at end of file diff --git a/test/form/absolute-path-resolver/_expected/umd.js b/test/form/absolute-path-resolver/_expected/umd.js new file mode 100644 index 00000000000..611df0c41da --- /dev/null +++ b/test/form/absolute-path-resolver/_expected/umd.js @@ -0,0 +1,14 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var a = () => { + console.log('props'); + }; + + a(); + a(); + +}))); diff --git a/test/form/absolute-path-resolver/a.js b/test/form/absolute-path-resolver/a.js new file mode 100644 index 00000000000..3223031dc70 --- /dev/null +++ b/test/form/absolute-path-resolver/a.js @@ -0,0 +1,3 @@ +export var a = () => { + console.log('props'); +}; \ No newline at end of file diff --git a/test/form/absolute-path-resolver/main.js b/test/form/absolute-path-resolver/main.js new file mode 100644 index 00000000000..f0b4f66763f --- /dev/null +++ b/test/form/absolute-path-resolver/main.js @@ -0,0 +1,4 @@ +import { a } from "./a.js"; +import { a as b } from "./a.js"; +a(); +b(); \ No newline at end of file diff --git a/test/form/assignment-to-exports-class-declaration/_config.js b/test/form/assignment-to-exports-class-declaration/_config.js index 0f3d2ef51aa..f7296e0ff7d 100644 --- a/test/form/assignment-to-exports-class-declaration/_config.js +++ b/test/form/assignment-to-exports-class-declaration/_config.js @@ -1,5 +1,5 @@ module.exports = { - description: 'does not rewrite class declaration IDs', + description: 'does not rewrite class expression IDs', options: { moduleName: 'myModule' } diff --git a/test/form/assignment-to-exports-class-declaration/_expected/amd.js b/test/form/assignment-to-exports-class-declaration/_expected/amd.js index c2d069112ca..b6e6ac96007 100644 --- a/test/form/assignment-to-exports-class-declaration/_expected/amd.js +++ b/test/form/assignment-to-exports-class-declaration/_expected/amd.js @@ -1,6 +1,8 @@ define(['exports'], function (exports) { 'use strict'; - exports.Foo = class Foo {} + exports.Foo = class Foo {}; exports.Foo = lol( exports.Foo ); + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/assignment-to-exports-class-declaration/_expected/cjs.js b/test/form/assignment-to-exports-class-declaration/_expected/cjs.js index b062474db41..d291984995d 100644 --- a/test/form/assignment-to-exports-class-declaration/_expected/cjs.js +++ b/test/form/assignment-to-exports-class-declaration/_expected/cjs.js @@ -1,4 +1,6 @@ 'use strict'; -exports.Foo = class Foo {} +Object.defineProperty(exports, '__esModule', { value: true }); + +exports.Foo = class Foo {}; exports.Foo = lol( exports.Foo ); diff --git a/test/form/assignment-to-exports-class-declaration/_expected/es.js b/test/form/assignment-to-exports-class-declaration/_expected/es.js new file mode 100644 index 00000000000..d4297e67896 --- /dev/null +++ b/test/form/assignment-to-exports-class-declaration/_expected/es.js @@ -0,0 +1,4 @@ +let Foo = class Foo {}; +Foo = lol( Foo ); + +export { Foo }; diff --git a/test/form/assignment-to-exports-class-declaration/_expected/es6.js b/test/form/assignment-to-exports-class-declaration/_expected/es6.js deleted file mode 100644 index 08e82c978a8..00000000000 --- a/test/form/assignment-to-exports-class-declaration/_expected/es6.js +++ /dev/null @@ -1,4 +0,0 @@ -Foo = class Foo {} -Foo = lol( Foo ); - -export { Foo }; \ No newline at end of file diff --git a/test/form/assignment-to-exports-class-declaration/_expected/iife.js b/test/form/assignment-to-exports-class-declaration/_expected/iife.js index fa375381176..09261c7a80f 100644 --- a/test/form/assignment-to-exports-class-declaration/_expected/iife.js +++ b/test/form/assignment-to-exports-class-declaration/_expected/iife.js @@ -1,7 +1,7 @@ (function (exports) { 'use strict'; - exports.Foo = class Foo {} + exports.Foo = class Foo {}; exports.Foo = lol( exports.Foo ); }((this.myModule = this.myModule || {}))); diff --git a/test/form/assignment-to-exports-class-declaration/_expected/umd.js b/test/form/assignment-to-exports-class-declaration/_expected/umd.js index bbefc871910..33b21403beb 100644 --- a/test/form/assignment-to-exports-class-declaration/_expected/umd.js +++ b/test/form/assignment-to-exports-class-declaration/_expected/umd.js @@ -2,9 +2,11 @@ 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'; +}(this, (function (exports) { 'use strict'; - exports.Foo = class Foo {} + exports.Foo = class Foo {}; exports.Foo = lol( exports.Foo ); -})); + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/assignment-to-exports/_config.js b/test/form/assignment-to-exports/_config.js new file mode 100644 index 00000000000..3c9f6d4effe --- /dev/null +++ b/test/form/assignment-to-exports/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'declares updated variable in ES output (#755)', + options: { + moduleName: 'bundle' + } +}; diff --git a/test/form/assignment-to-exports/_expected/amd.js b/test/form/assignment-to-exports/_expected/amd.js new file mode 100644 index 00000000000..6f8d4d86676 --- /dev/null +++ b/test/form/assignment-to-exports/_expected/amd.js @@ -0,0 +1,7 @@ +define(['exports'], function (exports) { 'use strict'; + + exports.foo = 1; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/assignment-to-exports/_expected/cjs.js b/test/form/assignment-to-exports/_expected/cjs.js new file mode 100644 index 00000000000..9de421531cc --- /dev/null +++ b/test/form/assignment-to-exports/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +exports.foo = 1; diff --git a/test/form/assignment-to-exports/_expected/es.js b/test/form/assignment-to-exports/_expected/es.js new file mode 100644 index 00000000000..e6c6e5f6876 --- /dev/null +++ b/test/form/assignment-to-exports/_expected/es.js @@ -0,0 +1,4 @@ +var foo; +foo = 1; + +export { foo }; diff --git a/test/form/assignment-to-exports/_expected/iife.js b/test/form/assignment-to-exports/_expected/iife.js new file mode 100644 index 00000000000..3ac6c5f0d36 --- /dev/null +++ b/test/form/assignment-to-exports/_expected/iife.js @@ -0,0 +1,6 @@ +(function (exports) { + 'use strict'; + + exports.foo = 1; + +}((this.bundle = this.bundle || {}))); diff --git a/test/form/assignment-to-exports/_expected/umd.js b/test/form/assignment-to-exports/_expected/umd.js new file mode 100644 index 00000000000..80039f99221 --- /dev/null +++ b/test/form/assignment-to-exports/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.bundle = global.bundle || {}))); +}(this, (function (exports) { 'use strict'; + + exports.foo = 1; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/assignment-to-exports/main.js b/test/form/assignment-to-exports/main.js new file mode 100644 index 00000000000..bd12ed8037e --- /dev/null +++ b/test/form/assignment-to-exports/main.js @@ -0,0 +1,2 @@ +export var foo; +foo = 1; diff --git a/test/form/banner-and-footer-plugin/_config.js b/test/form/banner-and-footer-plugin/_config.js index 14324186c7c..1e1367fe516 100644 --- a/test/form/banner-and-footer-plugin/_config.js +++ b/test/form/banner-and-footer-plugin/_config.js @@ -12,4 +12,4 @@ module.exports = { } ] } -} +}; diff --git a/test/form/banner-and-footer-plugin/_expected/es6.js b/test/form/banner-and-footer-plugin/_expected/es.js similarity index 100% rename from test/form/banner-and-footer-plugin/_expected/es6.js rename to test/form/banner-and-footer-plugin/_expected/es.js diff --git a/test/form/banner-and-footer-plugin/_expected/umd.js b/test/form/banner-and-footer-plugin/_expected/umd.js index 3e3bef01b28..29d8c60158e 100644 --- a/test/form/banner-and-footer-plugin/_expected/umd.js +++ b/test/form/banner-and-footer-plugin/_expected/umd.js @@ -4,10 +4,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; console.log( 1 + 1 ); -})); +}))); /* first footer */ /* second footer */ \ No newline at end of file diff --git a/test/form/banner-and-footer/_expected/es6.js b/test/form/banner-and-footer/_expected/es.js similarity index 100% rename from test/form/banner-and-footer/_expected/es6.js rename to test/form/banner-and-footer/_expected/es.js diff --git a/test/form/banner-and-footer/_expected/umd.js b/test/form/banner-and-footer/_expected/umd.js index 356ff47e6bd..9fa72aaa8ac 100644 --- a/test/form/banner-and-footer/_expected/umd.js +++ b/test/form/banner-and-footer/_expected/umd.js @@ -3,9 +3,9 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; console.log( 'hello world' ); -})); +}))); /* this is a footer */ \ No newline at end of file diff --git a/test/form/block-comments/_expected/es6.js b/test/form/block-comments/_expected/es.js similarity index 100% rename from test/form/block-comments/_expected/es6.js rename to test/form/block-comments/_expected/es.js diff --git a/test/form/block-comments/_expected/umd.js b/test/form/block-comments/_expected/umd.js index c00edfacc82..6afff4a7f83 100644 --- a/test/form/block-comments/_expected/umd.js +++ b/test/form/block-comments/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { return embiggen( 6, 7 ); @@ -20,4 +20,4 @@ alert( foo() ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/body-less-for-loops/_config.js b/test/form/body-less-for-loops/_config.js new file mode 100644 index 00000000000..a748fa03e69 --- /dev/null +++ b/test/form/body-less-for-loops/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'supports body-less for loops' +}; diff --git a/test/form/body-less-for-loops/_expected/amd.js b/test/form/body-less-for-loops/_expected/amd.js new file mode 100644 index 00000000000..464893d146e --- /dev/null +++ b/test/form/body-less-for-loops/_expected/amd.js @@ -0,0 +1,16 @@ +define(function () { 'use strict'; + + for ( let i = 0; i < 10; i += 1 ) console.log( i ); + for ( const letter of array ) console.log( letter ); + for ( const index in array ) console.log( index ); + + let i; + for ( i = 0; i < 10; i += 1 ) console.log( i ); + + let letter; + for ( letter of array ) console.log( letter ); + + let index; + for ( index in array ) console.log( index ); + +}); \ No newline at end of file diff --git a/test/form/body-less-for-loops/_expected/cjs.js b/test/form/body-less-for-loops/_expected/cjs.js new file mode 100644 index 00000000000..f2e4fdebc27 --- /dev/null +++ b/test/form/body-less-for-loops/_expected/cjs.js @@ -0,0 +1,14 @@ +'use strict'; + +for ( let i = 0; i < 10; i += 1 ) console.log( i ); +for ( const letter of array ) console.log( letter ); +for ( const index in array ) console.log( index ); + +let i; +for ( i = 0; i < 10; i += 1 ) console.log( i ); + +let letter; +for ( letter of array ) console.log( letter ); + +let index; +for ( index in array ) console.log( index ); \ No newline at end of file diff --git a/test/form/body-less-for-loops/_expected/es.js b/test/form/body-less-for-loops/_expected/es.js new file mode 100644 index 00000000000..63ee4e50a93 --- /dev/null +++ b/test/form/body-less-for-loops/_expected/es.js @@ -0,0 +1,12 @@ +for ( let i = 0; i < 10; i += 1 ) console.log( i ); +for ( const letter of array ) console.log( letter ); +for ( const index in array ) console.log( index ); + +let i; +for ( i = 0; i < 10; i += 1 ) console.log( i ); + +let letter; +for ( letter of array ) console.log( letter ); + +let index; +for ( index in array ) console.log( index ); \ No newline at end of file diff --git a/test/form/body-less-for-loops/_expected/iife.js b/test/form/body-less-for-loops/_expected/iife.js new file mode 100644 index 00000000000..2214bd42fe3 --- /dev/null +++ b/test/form/body-less-for-loops/_expected/iife.js @@ -0,0 +1,17 @@ +(function () { + 'use strict'; + + for ( let i = 0; i < 10; i += 1 ) console.log( i ); + for ( const letter of array ) console.log( letter ); + for ( const index in array ) console.log( index ); + + let i; + for ( i = 0; i < 10; i += 1 ) console.log( i ); + + let letter; + for ( letter of array ) console.log( letter ); + + let index; + for ( index in array ) console.log( index ); + +}()); \ No newline at end of file diff --git a/test/form/body-less-for-loops/_expected/umd.js b/test/form/body-less-for-loops/_expected/umd.js new file mode 100644 index 00000000000..98400216c1d --- /dev/null +++ b/test/form/body-less-for-loops/_expected/umd.js @@ -0,0 +1,20 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + for ( let i = 0; i < 10; i += 1 ) console.log( i ); + for ( const letter of array ) console.log( letter ); + for ( const index in array ) console.log( index ); + + let i; + for ( i = 0; i < 10; i += 1 ) console.log( i ); + + let letter; + for ( letter of array ) console.log( letter ); + + let index; + for ( index in array ) console.log( index ); + +}))); \ No newline at end of file diff --git a/test/form/body-less-for-loops/main.js b/test/form/body-less-for-loops/main.js new file mode 100644 index 00000000000..3aa7b7e8d15 --- /dev/null +++ b/test/form/body-less-for-loops/main.js @@ -0,0 +1,12 @@ +for ( let i = 0; i < 10; i += 1 ) console.log( i ); +for ( const letter of array ) console.log( letter ); +for ( const index in array ) console.log( index ); + +let i; +for ( i = 0; i < 10; i += 1 ) console.log( i ); + +let letter; +for ( letter of array ) console.log( letter ); + +let index; +for ( index in array ) console.log( index ); diff --git a/test/form/comment-before-import/_config.js b/test/form/comment-before-import/_config.js new file mode 100644 index 00000000000..823ac6379a3 --- /dev/null +++ b/test/form/comment-before-import/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'preserves comments before imports' +}; diff --git a/test/form/comment-before-import/_expected/amd.js b/test/form/comment-before-import/_expected/amd.js new file mode 100644 index 00000000000..8ee578297b5 --- /dev/null +++ b/test/form/comment-before-import/_expected/amd.js @@ -0,0 +1,12 @@ +define(function () { 'use strict'; + + // bar.js + var bar = 21; + + // foo.js + var foo = bar * 2; + + // main.js + console.log( foo ); + +}); \ No newline at end of file diff --git a/test/form/comment-before-import/_expected/cjs.js b/test/form/comment-before-import/_expected/cjs.js new file mode 100644 index 00000000000..04e5550e3b8 --- /dev/null +++ b/test/form/comment-before-import/_expected/cjs.js @@ -0,0 +1,10 @@ +'use strict'; + +// bar.js +var bar = 21; + +// foo.js +var foo = bar * 2; + +// main.js +console.log( foo ); \ No newline at end of file diff --git a/test/form/comment-before-import/_expected/es.js b/test/form/comment-before-import/_expected/es.js new file mode 100644 index 00000000000..1c21cb39cff --- /dev/null +++ b/test/form/comment-before-import/_expected/es.js @@ -0,0 +1,8 @@ +// bar.js +var bar = 21; + +// foo.js +var foo = bar * 2; + +// main.js +console.log( foo ); \ No newline at end of file diff --git a/test/form/comment-before-import/_expected/iife.js b/test/form/comment-before-import/_expected/iife.js new file mode 100644 index 00000000000..7d1e8f99394 --- /dev/null +++ b/test/form/comment-before-import/_expected/iife.js @@ -0,0 +1,13 @@ +(function () { + 'use strict'; + + // bar.js + var bar = 21; + + // foo.js + var foo = bar * 2; + + // main.js + console.log( foo ); + +}()); \ No newline at end of file diff --git a/test/form/comment-before-import/_expected/umd.js b/test/form/comment-before-import/_expected/umd.js new file mode 100644 index 00000000000..9d407005cc7 --- /dev/null +++ b/test/form/comment-before-import/_expected/umd.js @@ -0,0 +1,16 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + // bar.js + var bar = 21; + + // foo.js + var foo = bar * 2; + + // main.js + console.log( foo ); + +}))); \ No newline at end of file diff --git a/test/form/comment-before-import/bar.js b/test/form/comment-before-import/bar.js new file mode 100644 index 00000000000..3595594a5c1 --- /dev/null +++ b/test/form/comment-before-import/bar.js @@ -0,0 +1,2 @@ +// bar.js +export default 21; diff --git a/test/form/comment-before-import/foo.js b/test/form/comment-before-import/foo.js new file mode 100644 index 00000000000..b3747d0462c --- /dev/null +++ b/test/form/comment-before-import/foo.js @@ -0,0 +1,4 @@ +// foo.js +import bar from './bar.js'; + +export default bar * 2; diff --git a/test/form/comment-before-import/main.js b/test/form/comment-before-import/main.js new file mode 100644 index 00000000000..d8169aeeec5 --- /dev/null +++ b/test/form/comment-before-import/main.js @@ -0,0 +1,4 @@ +// main.js +import foo from './foo.js'; + +console.log( foo ); diff --git a/test/form/computed-properties/_expected/amd.js b/test/form/computed-properties/_expected/amd.js index 0ccd4d8a90d..cafa2621623 100644 --- a/test/form/computed-properties/_expected/amd.js +++ b/test/form/computed-properties/_expected/amd.js @@ -16,4 +16,6 @@ define(['exports'], function (exports) { 'use strict'; exports.x = x; exports.X = X; -}); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/computed-properties/_expected/cjs.js b/test/form/computed-properties/_expected/cjs.js index 443bab3cb3f..77f714cbdb8 100644 --- a/test/form/computed-properties/_expected/cjs.js +++ b/test/form/computed-properties/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var foo = 'foo'; var bar = 'bar'; var baz = 'baz'; @@ -14,4 +16,4 @@ class X { } exports.x = x; -exports.X = X; \ No newline at end of file +exports.X = X; diff --git a/test/form/computed-properties/_expected/es6.js b/test/form/computed-properties/_expected/es.js similarity index 100% rename from test/form/computed-properties/_expected/es6.js rename to test/form/computed-properties/_expected/es.js diff --git a/test/form/computed-properties/_expected/umd.js b/test/form/computed-properties/_expected/umd.js index ae576832d25..29399794207 100644 --- a/test/form/computed-properties/_expected/umd.js +++ b/test/form/computed-properties/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.computedProperties = global.computedProperties || {}))); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; var foo = 'foo'; var bar = 'bar'; @@ -20,4 +20,6 @@ exports.x = x; exports.X = X; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/conflicting-imports/_expected/es6.js b/test/form/conflicting-imports/_expected/es.js similarity index 100% rename from test/form/conflicting-imports/_expected/es6.js rename to test/form/conflicting-imports/_expected/es.js diff --git a/test/form/conflicting-imports/_expected/umd.js b/test/form/conflicting-imports/_expected/umd.js index 8254c774e62..8d6ea73a3b2 100644 --- a/test/form/conflicting-imports/_expected/umd.js +++ b/test/form/conflicting-imports/_expected/umd.js @@ -2,10 +2,10 @@ 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'; +}(this, (function (foo,bar) { 'use strict'; console.log( bar.a ); console.log( foo.a ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/custom-context/_config.js b/test/form/custom-context/_config.js new file mode 100644 index 00000000000..84f2dbd814e --- /dev/null +++ b/test/form/custom-context/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'allows custom context', + options: { + context: `lolwut` + } +}; diff --git a/test/form/custom-context/_expected/amd.js b/test/form/custom-context/_expected/amd.js new file mode 100644 index 00000000000..a160d17a1b8 --- /dev/null +++ b/test/form/custom-context/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + lolwut.prop = '???'; + +}); diff --git a/test/form/custom-context/_expected/cjs.js b/test/form/custom-context/_expected/cjs.js new file mode 100644 index 00000000000..f42cf3ce457 --- /dev/null +++ b/test/form/custom-context/_expected/cjs.js @@ -0,0 +1,3 @@ +'use strict'; + +lolwut.prop = '???'; diff --git a/test/form/custom-context/_expected/es.js b/test/form/custom-context/_expected/es.js new file mode 100644 index 00000000000..fa83c3d85cd --- /dev/null +++ b/test/form/custom-context/_expected/es.js @@ -0,0 +1 @@ +lolwut.prop = '???'; diff --git a/test/form/custom-context/_expected/iife.js b/test/form/custom-context/_expected/iife.js new file mode 100644 index 00000000000..a41619eb432 --- /dev/null +++ b/test/form/custom-context/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + lolwut.prop = '???'; + +}()); diff --git a/test/form/custom-context/_expected/umd.js b/test/form/custom-context/_expected/umd.js new file mode 100644 index 00000000000..a73a22c0de7 --- /dev/null +++ b/test/form/custom-context/_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'; + + lolwut.prop = '???'; + +}))); diff --git a/test/form/custom-context/main.js b/test/form/custom-context/main.js new file mode 100644 index 00000000000..169f08be96e --- /dev/null +++ b/test/form/custom-context/main.js @@ -0,0 +1 @@ +this.prop = '???'; diff --git a/test/form/custom-module-context-function/_config.js b/test/form/custom-module-context-function/_config.js new file mode 100644 index 00000000000..c15118eacd9 --- /dev/null +++ b/test/form/custom-module-context-function/_config.js @@ -0,0 +1,8 @@ +module.exports = { + description: 'allows custom module-specific context with a function option', + options: { + moduleContext ( id ) { + return /main\.js$/.test( id ) ? 'lolwut' : 'undefined'; + } + } +}; diff --git a/test/form/custom-module-context-function/_expected/amd.js b/test/form/custom-module-context-function/_expected/amd.js new file mode 100644 index 00000000000..92747997ff2 --- /dev/null +++ b/test/form/custom-module-context-function/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}); diff --git a/test/form/custom-module-context-function/_expected/cjs.js b/test/form/custom-module-context-function/_expected/cjs.js new file mode 100644 index 00000000000..35a5b08d3a9 --- /dev/null +++ b/test/form/custom-module-context-function/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +undefined.prop = 'nope'; + +lolwut.prop = '???'; diff --git a/test/form/custom-module-context-function/_expected/es.js b/test/form/custom-module-context-function/_expected/es.js new file mode 100644 index 00000000000..a6903e00c89 --- /dev/null +++ b/test/form/custom-module-context-function/_expected/es.js @@ -0,0 +1,3 @@ +undefined.prop = 'nope'; + +lolwut.prop = '???'; diff --git a/test/form/custom-module-context-function/_expected/iife.js b/test/form/custom-module-context-function/_expected/iife.js new file mode 100644 index 00000000000..7926fe6e7ea --- /dev/null +++ b/test/form/custom-module-context-function/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}()); diff --git a/test/form/custom-module-context-function/_expected/umd.js b/test/form/custom-module-context-function/_expected/umd.js new file mode 100644 index 00000000000..22fa60526fe --- /dev/null +++ b/test/form/custom-module-context-function/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}))); diff --git a/test/form/custom-module-context-function/foo.js b/test/form/custom-module-context-function/foo.js new file mode 100644 index 00000000000..a5a991d6d63 --- /dev/null +++ b/test/form/custom-module-context-function/foo.js @@ -0,0 +1 @@ +this.prop = 'nope'; diff --git a/test/form/custom-module-context-function/main.js b/test/form/custom-module-context-function/main.js new file mode 100644 index 00000000000..1323b6820ce --- /dev/null +++ b/test/form/custom-module-context-function/main.js @@ -0,0 +1,2 @@ +import './foo.js'; +this.prop = '???'; diff --git a/test/form/custom-module-context/_config.js b/test/form/custom-module-context/_config.js new file mode 100644 index 00000000000..f5d68d2f66d --- /dev/null +++ b/test/form/custom-module-context/_config.js @@ -0,0 +1,8 @@ +module.exports = { + description: 'allows custom module-specific context', + options: { + moduleContext: { + 'main.js': 'lolwut' + } + } +}; diff --git a/test/form/custom-module-context/_expected/amd.js b/test/form/custom-module-context/_expected/amd.js new file mode 100644 index 00000000000..92747997ff2 --- /dev/null +++ b/test/form/custom-module-context/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}); diff --git a/test/form/custom-module-context/_expected/cjs.js b/test/form/custom-module-context/_expected/cjs.js new file mode 100644 index 00000000000..35a5b08d3a9 --- /dev/null +++ b/test/form/custom-module-context/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +undefined.prop = 'nope'; + +lolwut.prop = '???'; diff --git a/test/form/custom-module-context/_expected/es.js b/test/form/custom-module-context/_expected/es.js new file mode 100644 index 00000000000..a6903e00c89 --- /dev/null +++ b/test/form/custom-module-context/_expected/es.js @@ -0,0 +1,3 @@ +undefined.prop = 'nope'; + +lolwut.prop = '???'; diff --git a/test/form/custom-module-context/_expected/iife.js b/test/form/custom-module-context/_expected/iife.js new file mode 100644 index 00000000000..7926fe6e7ea --- /dev/null +++ b/test/form/custom-module-context/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}()); diff --git a/test/form/custom-module-context/_expected/umd.js b/test/form/custom-module-context/_expected/umd.js new file mode 100644 index 00000000000..22fa60526fe --- /dev/null +++ b/test/form/custom-module-context/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + undefined.prop = 'nope'; + + lolwut.prop = '???'; + +}))); diff --git a/test/form/custom-module-context/foo.js b/test/form/custom-module-context/foo.js new file mode 100644 index 00000000000..a5a991d6d63 --- /dev/null +++ b/test/form/custom-module-context/foo.js @@ -0,0 +1 @@ +this.prop = 'nope'; diff --git a/test/form/custom-module-context/main.js b/test/form/custom-module-context/main.js new file mode 100644 index 00000000000..1323b6820ce --- /dev/null +++ b/test/form/custom-module-context/main.js @@ -0,0 +1,2 @@ +import './foo.js'; +this.prop = '???'; diff --git a/test/form/dedupes-external-imports/_expected/amd.js b/test/form/dedupes-external-imports/_expected/amd.js index 7f52edaf9b7..a503cb30486 100644 --- a/test/form/dedupes-external-imports/_expected/amd.js +++ b/test/form/dedupes-external-imports/_expected/amd.js @@ -29,4 +29,6 @@ define(['exports', 'external'], function (exports, external) { 'use strict'; exports.bar = bar; exports.baz = baz; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/dedupes-external-imports/_expected/cjs.js b/test/form/dedupes-external-imports/_expected/cjs.js index fd4138bcb97..ede4836925e 100644 --- a/test/form/dedupes-external-imports/_expected/cjs.js +++ b/test/form/dedupes-external-imports/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var external = require('external'); class Foo extends external.Component { diff --git a/test/form/dedupes-external-imports/_expected/es6.js b/test/form/dedupes-external-imports/_expected/es.js similarity index 100% rename from test/form/dedupes-external-imports/_expected/es6.js rename to test/form/dedupes-external-imports/_expected/es.js diff --git a/test/form/dedupes-external-imports/_expected/umd.js b/test/form/dedupes-external-imports/_expected/umd.js index 06be0e74450..f6ef0fe39da 100644 --- a/test/form/dedupes-external-imports/_expected/umd.js +++ b/test/form/dedupes-external-imports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) : typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) : (factory((global.myBundle = global.myBundle || {}),global.external)); -}(this, function (exports,external) { 'use strict'; +}(this, (function (exports,external) { 'use strict'; class Foo extends external.Component { constructor () { @@ -33,4 +33,6 @@ exports.bar = bar; exports.baz = baz; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/duplicated-var-declarations/_config.js b/test/form/duplicated-var-declarations/_config.js new file mode 100644 index 00000000000..4c3038c2012 --- /dev/null +++ b/test/form/duplicated-var-declarations/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not remove duplicated var declarations (#716)' +}; diff --git a/test/form/duplicated-var-declarations/_expected/amd.js b/test/form/duplicated-var-declarations/_expected/amd.js new file mode 100644 index 00000000000..b43e2a4c96f --- /dev/null +++ b/test/form/duplicated-var-declarations/_expected/amd.js @@ -0,0 +1,17 @@ +define(function () { 'use strict'; + + var a = 1; + var b = 2; + + assert.equal( a, 1 ); + assert.equal( b, 2 ); + + var a = 3; + var b = 4; + var c = 5; + + assert.equal( a, 3 ); + assert.equal( b, 4 ); + assert.equal( c, 5 ); + +}); diff --git a/test/form/duplicated-var-declarations/_expected/cjs.js b/test/form/duplicated-var-declarations/_expected/cjs.js new file mode 100644 index 00000000000..e47b61a58e9 --- /dev/null +++ b/test/form/duplicated-var-declarations/_expected/cjs.js @@ -0,0 +1,15 @@ +'use strict'; + +var a = 1; +var b = 2; + +assert.equal( a, 1 ); +assert.equal( b, 2 ); + +var a = 3; +var b = 4; +var c = 5; + +assert.equal( a, 3 ); +assert.equal( b, 4 ); +assert.equal( c, 5 ); diff --git a/test/form/duplicated-var-declarations/_expected/es.js b/test/form/duplicated-var-declarations/_expected/es.js new file mode 100644 index 00000000000..cacf6d2d9a3 --- /dev/null +++ b/test/form/duplicated-var-declarations/_expected/es.js @@ -0,0 +1,13 @@ +var a = 1; +var b = 2; + +assert.equal( a, 1 ); +assert.equal( b, 2 ); + +var a = 3; +var b = 4; +var c = 5; + +assert.equal( a, 3 ); +assert.equal( b, 4 ); +assert.equal( c, 5 ); diff --git a/test/form/duplicated-var-declarations/_expected/iife.js b/test/form/duplicated-var-declarations/_expected/iife.js new file mode 100644 index 00000000000..106066a0a1a --- /dev/null +++ b/test/form/duplicated-var-declarations/_expected/iife.js @@ -0,0 +1,18 @@ +(function () { + 'use strict'; + + var a = 1; + var b = 2; + + assert.equal( a, 1 ); + assert.equal( b, 2 ); + + var a = 3; + var b = 4; + var c = 5; + + assert.equal( a, 3 ); + assert.equal( b, 4 ); + assert.equal( c, 5 ); + +}()); diff --git a/test/form/duplicated-var-declarations/_expected/umd.js b/test/form/duplicated-var-declarations/_expected/umd.js new file mode 100644 index 00000000000..45747992b75 --- /dev/null +++ b/test/form/duplicated-var-declarations/_expected/umd.js @@ -0,0 +1,21 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var a = 1; + var b = 2; + + assert.equal( a, 1 ); + assert.equal( b, 2 ); + + var a = 3; + var b = 4; + var c = 5; + + assert.equal( a, 3 ); + assert.equal( b, 4 ); + assert.equal( c, 5 ); + +}))); diff --git a/test/form/duplicated-var-declarations/main.js b/test/form/duplicated-var-declarations/main.js new file mode 100644 index 00000000000..1eabb5b53b3 --- /dev/null +++ b/test/form/duplicated-var-declarations/main.js @@ -0,0 +1,10 @@ +var a = 1, b = 2; + +assert.equal( a, 1 ); +assert.equal( b, 2 ); + +var a = 3, b = 4, c = 5; + +assert.equal( a, 3 ); +assert.equal( b, 4 ); +assert.equal( c, 5 ); diff --git a/test/form/effect-in-for-of-loop-in-functions/_config.js b/test/form/effect-in-for-of-loop-in-functions/_config.js new file mode 100644 index 00000000000..79abe7413e3 --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'includes effects in for-of loop (#870)' +} diff --git a/test/form/effect-in-for-of-loop-in-functions/_expected/amd.js b/test/form/effect-in-for-of-loop-in-functions/_expected/amd.js new file mode 100644 index 00000000000..a7c1b488500 --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_expected/amd.js @@ -0,0 +1,28 @@ +define(function () { 'use strict'; + + const items = [{}, {}, {}]; + + function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } + } + + a(); + + function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } + } + + c(); + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}); diff --git a/test/form/effect-in-for-of-loop-in-functions/_expected/cjs.js b/test/form/effect-in-for-of-loop-in-functions/_expected/cjs.js new file mode 100644 index 00000000000..51c5f3b83a8 --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_expected/cjs.js @@ -0,0 +1,26 @@ +'use strict'; + +const items = [{}, {}, {}]; + +function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } +} + +a(); + +function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } +} + +c(); + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/effect-in-for-of-loop-in-functions/_expected/es.js b/test/form/effect-in-for-of-loop-in-functions/_expected/es.js new file mode 100644 index 00000000000..0aafee1f7be --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_expected/es.js @@ -0,0 +1,24 @@ +const items = [{}, {}, {}]; + +function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } +} + +a(); + +function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } +} + +c(); + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/effect-in-for-of-loop-in-functions/_expected/iife.js b/test/form/effect-in-for-of-loop-in-functions/_expected/iife.js new file mode 100644 index 00000000000..406ab3aeb8e --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_expected/iife.js @@ -0,0 +1,29 @@ +(function () { + 'use strict'; + + const items = [{}, {}, {}]; + + function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } + } + + a(); + + function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } + } + + c(); + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}()); diff --git a/test/form/effect-in-for-of-loop-in-functions/_expected/umd.js b/test/form/effect-in-for-of-loop-in-functions/_expected/umd.js new file mode 100644 index 00000000000..33518c0de73 --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/_expected/umd.js @@ -0,0 +1,32 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + const items = [{}, {}, {}]; + + function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } + } + + a(); + + function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } + } + + c(); + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}))); diff --git a/test/form/effect-in-for-of-loop-in-functions/main.js b/test/form/effect-in-for-of-loop-in-functions/main.js new file mode 100644 index 00000000000..7ba1241a984 --- /dev/null +++ b/test/form/effect-in-for-of-loop-in-functions/main.js @@ -0,0 +1,41 @@ +const items = [{}, {}, {}]; + +function a () { + for ( const item of items.children ) { + item.foo = 'a'; + } +} + +a(); + +function b () { + for ( const item of items.children ) { + // do nothing + } +} + +b(); + +function c () { + let item; + for ( item of items.children ) { + item.bar = 'c'; + } +} + +c(); + +function d () { + let item; + for ( item of items.children ) { + // do nothing + } +} + +d(); + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/effect-in-for-of-loop/_config.js b/test/form/effect-in-for-of-loop/_config.js new file mode 100644 index 00000000000..79abe7413e3 --- /dev/null +++ b/test/form/effect-in-for-of-loop/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'includes effects in for-of loop (#870)' +} diff --git a/test/form/effect-in-for-of-loop/_expected/amd.js b/test/form/effect-in-for-of-loop/_expected/amd.js new file mode 100644 index 00000000000..c252e26b3b5 --- /dev/null +++ b/test/form/effect-in-for-of-loop/_expected/amd.js @@ -0,0 +1,20 @@ +define(function () { 'use strict'; + + const items = [{}, {}, {}]; + + for ( const a of items.children ) { + a.foo = 'a'; + } + + let c; + for ( c of items.children ) { + c.bar = 'c'; + } + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}); diff --git a/test/form/effect-in-for-of-loop/_expected/cjs.js b/test/form/effect-in-for-of-loop/_expected/cjs.js new file mode 100644 index 00000000000..197b73eca1c --- /dev/null +++ b/test/form/effect-in-for-of-loop/_expected/cjs.js @@ -0,0 +1,18 @@ +'use strict'; + +const items = [{}, {}, {}]; + +for ( const a of items.children ) { + a.foo = 'a'; +} + +let c; +for ( c of items.children ) { + c.bar = 'c'; +} + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/effect-in-for-of-loop/_expected/es.js b/test/form/effect-in-for-of-loop/_expected/es.js new file mode 100644 index 00000000000..3869419531b --- /dev/null +++ b/test/form/effect-in-for-of-loop/_expected/es.js @@ -0,0 +1,16 @@ +const items = [{}, {}, {}]; + +for ( const a of items.children ) { + a.foo = 'a'; +} + +let c; +for ( c of items.children ) { + c.bar = 'c'; +} + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/effect-in-for-of-loop/_expected/iife.js b/test/form/effect-in-for-of-loop/_expected/iife.js new file mode 100644 index 00000000000..7ca26c86ff2 --- /dev/null +++ b/test/form/effect-in-for-of-loop/_expected/iife.js @@ -0,0 +1,21 @@ +(function () { + 'use strict'; + + const items = [{}, {}, {}]; + + for ( const a of items.children ) { + a.foo = 'a'; + } + + let c; + for ( c of items.children ) { + c.bar = 'c'; + } + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}()); diff --git a/test/form/effect-in-for-of-loop/_expected/umd.js b/test/form/effect-in-for-of-loop/_expected/umd.js new file mode 100644 index 00000000000..08ef206f291 --- /dev/null +++ b/test/form/effect-in-for-of-loop/_expected/umd.js @@ -0,0 +1,24 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + const items = [{}, {}, {}]; + + for ( const a of items.children ) { + a.foo = 'a'; + } + + let c; + for ( c of items.children ) { + c.bar = 'c'; + } + + assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } + ]); + +}))); diff --git a/test/form/effect-in-for-of-loop/main.js b/test/form/effect-in-for-of-loop/main.js new file mode 100644 index 00000000000..122bf0f27ee --- /dev/null +++ b/test/form/effect-in-for-of-loop/main.js @@ -0,0 +1,25 @@ +const items = [{}, {}, {}]; + +for ( const a of items.children ) { + a.foo = 'a'; +} + +for ( const b of items.children ) { + // do nothing +} + +let c; +for ( c of items.children ) { + c.bar = 'c'; +} + +let d; +for ( d of items.children ) { + // do nothing +} + +assert.deepEqual( items, [ + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' }, + { foo: 'a', bar: 'c' } +]); diff --git a/test/form/empty-block-statement/_config.js b/test/form/empty-block-statement/_config.js new file mode 100644 index 00000000000..283b0b6931b --- /dev/null +++ b/test/form/empty-block-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty block statement' +}; diff --git a/test/form/empty-block-statement/_expected/amd.js b/test/form/empty-block-statement/_expected/amd.js new file mode 100644 index 00000000000..6036f2851d3 --- /dev/null +++ b/test/form/empty-block-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); diff --git a/test/form/empty-block-statement/_expected/cjs.js b/test/form/empty-block-statement/_expected/cjs.js new file mode 100644 index 00000000000..33f9de05030 --- /dev/null +++ b/test/form/empty-block-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); diff --git a/test/form/empty-block-statement/_expected/es.js b/test/form/empty-block-statement/_expected/es.js new file mode 100644 index 00000000000..472e544d88c --- /dev/null +++ b/test/form/empty-block-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); diff --git a/test/form/empty-block-statement/_expected/iife.js b/test/form/empty-block-statement/_expected/iife.js new file mode 100644 index 00000000000..08a84a95e53 --- /dev/null +++ b/test/form/empty-block-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); diff --git a/test/form/empty-block-statement/_expected/umd.js b/test/form/empty-block-statement/_expected/umd.js new file mode 100644 index 00000000000..0aae43fe29d --- /dev/null +++ b/test/form/empty-block-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); diff --git a/test/form/empty-block-statement/main.js b/test/form/empty-block-statement/main.js new file mode 100644 index 00000000000..edca0106b40 --- /dev/null +++ b/test/form/empty-block-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +{ + // empty +} +console.log( 2 ); diff --git a/test/form/empty-do-while-statement/_config.js b/test/form/empty-do-while-statement/_config.js new file mode 100644 index 00000000000..00672ede4ed --- /dev/null +++ b/test/form/empty-do-while-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty do-while statement' +}; diff --git a/test/form/empty-do-while-statement/_expected/amd.js b/test/form/empty-do-while-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-do-while-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-do-while-statement/_expected/cjs.js b/test/form/empty-do-while-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-do-while-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-do-while-statement/_expected/es.js b/test/form/empty-do-while-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-do-while-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-do-while-statement/_expected/iife.js b/test/form/empty-do-while-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-do-while-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-do-while-statement/_expected/umd.js b/test/form/empty-do-while-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-do-while-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-do-while-statement/main.js b/test/form/empty-do-while-statement/main.js new file mode 100644 index 00000000000..8b04429c137 --- /dev/null +++ b/test/form/empty-do-while-statement/main.js @@ -0,0 +1,6 @@ +console.log( 1 ); +var condition = true; +do { + condition = false; +} while ( condition ); +console.log( 2 ); diff --git a/test/form/empty-for-in-statement/_config.js b/test/form/empty-for-in-statement/_config.js new file mode 100644 index 00000000000..b95837c9a9f --- /dev/null +++ b/test/form/empty-for-in-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty for-in statement' +}; diff --git a/test/form/empty-for-in-statement/_expected/amd.js b/test/form/empty-for-in-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-for-in-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-for-in-statement/_expected/cjs.js b/test/form/empty-for-in-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-for-in-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-for-in-statement/_expected/es.js b/test/form/empty-for-in-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-for-in-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-for-in-statement/_expected/iife.js b/test/form/empty-for-in-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-for-in-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-for-in-statement/_expected/umd.js b/test/form/empty-for-in-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-for-in-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-for-in-statement/main.js b/test/form/empty-for-in-statement/main.js new file mode 100644 index 00000000000..cb706f7a16c --- /dev/null +++ b/test/form/empty-for-in-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +for ( const i in whatever ) { + // do nothing +} +console.log( 2 ); diff --git a/test/form/empty-for-of-statement/_config.js b/test/form/empty-for-of-statement/_config.js new file mode 100644 index 00000000000..4a7bd91179f --- /dev/null +++ b/test/form/empty-for-of-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty for-of statement' +}; diff --git a/test/form/empty-for-of-statement/_expected/amd.js b/test/form/empty-for-of-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-for-of-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-for-of-statement/_expected/cjs.js b/test/form/empty-for-of-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-for-of-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-for-of-statement/_expected/es.js b/test/form/empty-for-of-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-for-of-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-for-of-statement/_expected/iife.js b/test/form/empty-for-of-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-for-of-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-for-of-statement/_expected/umd.js b/test/form/empty-for-of-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-for-of-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-for-of-statement/main.js b/test/form/empty-for-of-statement/main.js new file mode 100644 index 00000000000..e591ddeaef2 --- /dev/null +++ b/test/form/empty-for-of-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +for ( const i of whatever ) { + // do nothing +} +console.log( 2 ); diff --git a/test/form/empty-for-statement/_config.js b/test/form/empty-for-statement/_config.js new file mode 100644 index 00000000000..f448ddf8e8b --- /dev/null +++ b/test/form/empty-for-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty for statement' +}; diff --git a/test/form/empty-for-statement/_expected/amd.js b/test/form/empty-for-statement/_expected/amd.js new file mode 100644 index 00000000000..6036f2851d3 --- /dev/null +++ b/test/form/empty-for-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); diff --git a/test/form/empty-for-statement/_expected/cjs.js b/test/form/empty-for-statement/_expected/cjs.js new file mode 100644 index 00000000000..33f9de05030 --- /dev/null +++ b/test/form/empty-for-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); diff --git a/test/form/empty-for-statement/_expected/es.js b/test/form/empty-for-statement/_expected/es.js new file mode 100644 index 00000000000..472e544d88c --- /dev/null +++ b/test/form/empty-for-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); diff --git a/test/form/empty-for-statement/_expected/iife.js b/test/form/empty-for-statement/_expected/iife.js new file mode 100644 index 00000000000..08a84a95e53 --- /dev/null +++ b/test/form/empty-for-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); diff --git a/test/form/empty-for-statement/_expected/umd.js b/test/form/empty-for-statement/_expected/umd.js new file mode 100644 index 00000000000..0aae43fe29d --- /dev/null +++ b/test/form/empty-for-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); diff --git a/test/form/empty-for-statement/main.js b/test/form/empty-for-statement/main.js new file mode 100644 index 00000000000..3b5d176e118 --- /dev/null +++ b/test/form/empty-for-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +for ( let i = 0; i < 10; i += 1 ) { + // do nothing +} +console.log( 2 ); diff --git a/test/form/empty-if-statement/_config.js b/test/form/empty-if-statement/_config.js new file mode 100644 index 00000000000..abea88980c5 --- /dev/null +++ b/test/form/empty-if-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty if statement' +}; diff --git a/test/form/empty-if-statement/_expected/amd.js b/test/form/empty-if-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-if-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-if-statement/_expected/cjs.js b/test/form/empty-if-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-if-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-if-statement/_expected/es.js b/test/form/empty-if-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-if-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-if-statement/_expected/iife.js b/test/form/empty-if-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-if-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-if-statement/_expected/umd.js b/test/form/empty-if-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-if-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-if-statement/main.js b/test/form/empty-if-statement/main.js new file mode 100644 index 00000000000..6db9dc163b9 --- /dev/null +++ b/test/form/empty-if-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +if ( nothing ) { + // empty +} +console.log( 2 ); diff --git a/test/form/empty-statement-consequent/_config.js b/test/form/empty-statement-consequent/_config.js new file mode 100644 index 00000000000..dc10538fbfb --- /dev/null +++ b/test/form/empty-statement-consequent/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'preserves empty statements used as the consequent of conditionals' +}; diff --git a/test/form/empty-statement-consequent/_expected/amd.js b/test/form/empty-statement-consequent/_expected/amd.js new file mode 100644 index 00000000000..9114028544e --- /dev/null +++ b/test/form/empty-statement-consequent/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + if ( a === 0 ); + else a++; + +}); \ No newline at end of file diff --git a/test/form/empty-statement-consequent/_expected/cjs.js b/test/form/empty-statement-consequent/_expected/cjs.js new file mode 100644 index 00000000000..9b5e04ab9cd --- /dev/null +++ b/test/form/empty-statement-consequent/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +if ( a === 0 ); +else a++; \ No newline at end of file diff --git a/test/form/empty-statement-consequent/_expected/es.js b/test/form/empty-statement-consequent/_expected/es.js new file mode 100644 index 00000000000..04006b3435c --- /dev/null +++ b/test/form/empty-statement-consequent/_expected/es.js @@ -0,0 +1,2 @@ +if ( a === 0 ); +else a++; \ No newline at end of file diff --git a/test/form/empty-statement-consequent/_expected/iife.js b/test/form/empty-statement-consequent/_expected/iife.js new file mode 100644 index 00000000000..45b92d83ca7 --- /dev/null +++ b/test/form/empty-statement-consequent/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + if ( a === 0 ); + else a++; + +}()); \ No newline at end of file diff --git a/test/form/empty-statement-consequent/_expected/umd.js b/test/form/empty-statement-consequent/_expected/umd.js new file mode 100644 index 00000000000..08026c7d0df --- /dev/null +++ b/test/form/empty-statement-consequent/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + if ( a === 0 ); + else a++; + +}))); \ No newline at end of file diff --git a/test/form/empty-statement-consequent/main.js b/test/form/empty-statement-consequent/main.js new file mode 100644 index 00000000000..b6b36cf49d0 --- /dev/null +++ b/test/form/empty-statement-consequent/main.js @@ -0,0 +1,2 @@ +if ( a === 0 ); +else a++; diff --git a/test/form/empty-statement/_config.js b/test/form/empty-statement/_config.js new file mode 100644 index 00000000000..76e4fa332b4 --- /dev/null +++ b/test/form/empty-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty statement' +}; diff --git a/test/form/empty-statement/_expected/amd.js b/test/form/empty-statement/_expected/amd.js new file mode 100644 index 00000000000..d7ee383f28a --- /dev/null +++ b/test/form/empty-statement/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + console.log( 1 ); + + console.log( 2 ); + +}); diff --git a/test/form/empty-statement/_expected/cjs.js b/test/form/empty-statement/_expected/cjs.js new file mode 100644 index 00000000000..2ad8cd21a7d --- /dev/null +++ b/test/form/empty-statement/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +console.log( 1 ); + +console.log( 2 ); diff --git a/test/form/empty-statement/_expected/es.js b/test/form/empty-statement/_expected/es.js new file mode 100644 index 00000000000..b149085e8ec --- /dev/null +++ b/test/form/empty-statement/_expected/es.js @@ -0,0 +1,3 @@ +console.log( 1 ); + +console.log( 2 ); diff --git a/test/form/empty-statement/_expected/iife.js b/test/form/empty-statement/_expected/iife.js new file mode 100644 index 00000000000..c9dbff58946 --- /dev/null +++ b/test/form/empty-statement/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + console.log( 1 ); + + console.log( 2 ); + +}()); diff --git a/test/form/empty-statement/_expected/umd.js b/test/form/empty-statement/_expected/umd.js new file mode 100644 index 00000000000..e97ebffd00d --- /dev/null +++ b/test/form/empty-statement/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + + console.log( 2 ); + +}))); diff --git a/test/form/empty-statement/main.js b/test/form/empty-statement/main.js new file mode 100644 index 00000000000..43f70378fcd --- /dev/null +++ b/test/form/empty-statement/main.js @@ -0,0 +1,4 @@ +; +console.log( 1 );; +; +console.log( 2 );; diff --git a/test/form/empty-switch-statement/_config.js b/test/form/empty-switch-statement/_config.js new file mode 100644 index 00000000000..29c051733d4 --- /dev/null +++ b/test/form/empty-switch-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty switch statement' +}; diff --git a/test/form/empty-switch-statement/_expected/amd.js b/test/form/empty-switch-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-switch-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-switch-statement/_expected/cjs.js b/test/form/empty-switch-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-switch-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-switch-statement/_expected/es.js b/test/form/empty-switch-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-switch-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-switch-statement/_expected/iife.js b/test/form/empty-switch-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-switch-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-switch-statement/_expected/umd.js b/test/form/empty-switch-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-switch-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-switch-statement/main.js b/test/form/empty-switch-statement/main.js new file mode 100644 index 00000000000..58da4d475d3 --- /dev/null +++ b/test/form/empty-switch-statement/main.js @@ -0,0 +1,11 @@ +console.log( 1 ); +var result; +switch ( whatever ) { + case foo: + result = 'foo'; + break; + + default: + result = 'default'; +} +console.log( 2 ); diff --git a/test/form/empty-try-catch-statement/_config.js b/test/form/empty-try-catch-statement/_config.js new file mode 100644 index 00000000000..70bf6529913 --- /dev/null +++ b/test/form/empty-try-catch-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty try-catch-finally statement' +}; diff --git a/test/form/empty-try-catch-statement/_expected/amd.js b/test/form/empty-try-catch-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-try-catch-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-try-catch-statement/_expected/cjs.js b/test/form/empty-try-catch-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-try-catch-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-try-catch-statement/_expected/es.js b/test/form/empty-try-catch-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-try-catch-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-try-catch-statement/_expected/iife.js b/test/form/empty-try-catch-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-try-catch-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-try-catch-statement/_expected/umd.js b/test/form/empty-try-catch-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-try-catch-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-try-catch-statement/main.js b/test/form/empty-try-catch-statement/main.js new file mode 100644 index 00000000000..52ed8c162a6 --- /dev/null +++ b/test/form/empty-try-catch-statement/main.js @@ -0,0 +1,9 @@ +console.log( 1 ); +try { + // do nothing +} catch ( err ) { + // do nothing +} finally { + // do nothing +} +console.log( 2 ); diff --git a/test/form/empty-while-statement/_config.js b/test/form/empty-while-statement/_config.js new file mode 100644 index 00000000000..8db2e7f8646 --- /dev/null +++ b/test/form/empty-while-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'removes an empty while statement' +}; diff --git a/test/form/empty-while-statement/_expected/amd.js b/test/form/empty-while-statement/_expected/amd.js new file mode 100644 index 00000000000..e44e55606b5 --- /dev/null +++ b/test/form/empty-while-statement/_expected/amd.js @@ -0,0 +1,6 @@ +define(function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}); \ No newline at end of file diff --git a/test/form/empty-while-statement/_expected/cjs.js b/test/form/empty-while-statement/_expected/cjs.js new file mode 100644 index 00000000000..1afb1431201 --- /dev/null +++ b/test/form/empty-while-statement/_expected/cjs.js @@ -0,0 +1,4 @@ +'use strict'; + +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-while-statement/_expected/es.js b/test/form/empty-while-statement/_expected/es.js new file mode 100644 index 00000000000..f97f3d0dda5 --- /dev/null +++ b/test/form/empty-while-statement/_expected/es.js @@ -0,0 +1,2 @@ +console.log( 1 ); +console.log( 2 ); \ No newline at end of file diff --git a/test/form/empty-while-statement/_expected/iife.js b/test/form/empty-while-statement/_expected/iife.js new file mode 100644 index 00000000000..39aedbf4a6a --- /dev/null +++ b/test/form/empty-while-statement/_expected/iife.js @@ -0,0 +1,7 @@ +(function () { + 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}()); \ No newline at end of file diff --git a/test/form/empty-while-statement/_expected/umd.js b/test/form/empty-while-statement/_expected/umd.js new file mode 100644 index 00000000000..044519377f3 --- /dev/null +++ b/test/form/empty-while-statement/_expected/umd.js @@ -0,0 +1,10 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + console.log( 2 ); + +}))); \ No newline at end of file diff --git a/test/form/empty-while-statement/main.js b/test/form/empty-while-statement/main.js new file mode 100644 index 00000000000..c499a7f6e93 --- /dev/null +++ b/test/form/empty-while-statement/main.js @@ -0,0 +1,6 @@ +console.log( 1 ); +var condition = true; +while ( condition ) { + condition = false; +} +console.log( 2 ); diff --git a/test/form/erroneous-nested-member-expression/_expected/amd.js b/test/form/erroneous-nested-member-expression/_expected/amd.js index 6499b906671..4b402c74930 100644 --- a/test/form/erroneous-nested-member-expression/_expected/amd.js +++ b/test/form/erroneous-nested-member-expression/_expected/amd.js @@ -6,8 +6,8 @@ define(function () { 'use strict'; console.log('har?'); } }; - }; + } yar.har(); -}); \ No newline at end of file +}); diff --git a/test/form/erroneous-nested-member-expression/_expected/cjs.js b/test/form/erroneous-nested-member-expression/_expected/cjs.js index aa4b949a3ce..01c96f9f880 100644 --- a/test/form/erroneous-nested-member-expression/_expected/cjs.js +++ b/test/form/erroneous-nested-member-expression/_expected/cjs.js @@ -6,6 +6,6 @@ function yar() { console.log('har?'); } }; -}; +} -yar.har(); \ No newline at end of file +yar.har(); diff --git a/test/form/erroneous-nested-member-expression/_expected/es6.js b/test/form/erroneous-nested-member-expression/_expected/es.js similarity index 84% rename from test/form/erroneous-nested-member-expression/_expected/es6.js rename to test/form/erroneous-nested-member-expression/_expected/es.js index 34c4e2e5815..ee4eacedfaf 100644 --- a/test/form/erroneous-nested-member-expression/_expected/es6.js +++ b/test/form/erroneous-nested-member-expression/_expected/es.js @@ -4,6 +4,6 @@ function yar() { console.log('har?'); } }; -}; +} -yar.har(); \ No newline at end of file +yar.har(); diff --git a/test/form/erroneous-nested-member-expression/_expected/iife.js b/test/form/erroneous-nested-member-expression/_expected/iife.js index 4233cfe4b5b..8a8d65ed589 100644 --- a/test/form/erroneous-nested-member-expression/_expected/iife.js +++ b/test/form/erroneous-nested-member-expression/_expected/iife.js @@ -7,8 +7,8 @@ console.log('har?'); } }; - }; + } yar.har(); -}()); \ No newline at end of file +}()); diff --git a/test/form/erroneous-nested-member-expression/_expected/umd.js b/test/form/erroneous-nested-member-expression/_expected/umd.js index d11bd9fd8c7..94dee16b404 100644 --- a/test/form/erroneous-nested-member-expression/_expected/umd.js +++ b/test/form/erroneous-nested-member-expression/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function yar() { return { @@ -10,8 +10,8 @@ console.log('har?'); } }; - }; + } yar.har(); -})); \ No newline at end of file +}))); diff --git a/test/form/exclude-unnecessary-modifications/_expected/es6.js b/test/form/exclude-unnecessary-modifications/_expected/es.js similarity index 100% rename from test/form/exclude-unnecessary-modifications/_expected/es6.js rename to test/form/exclude-unnecessary-modifications/_expected/es.js diff --git a/test/form/exclude-unnecessary-modifications/_expected/umd.js b/test/form/exclude-unnecessary-modifications/_expected/umd.js index d5cd1bd3ac4..457d3c23211 100644 --- a/test/form/exclude-unnecessary-modifications/_expected/umd.js +++ b/test/form/exclude-unnecessary-modifications/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var foo = {}; @@ -29,4 +29,4 @@ console.log( foo ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/export-all-from-internal/_expected/amd.js b/test/form/export-all-from-internal/_expected/amd.js index 6b0c47ebcdf..c3acbb07b16 100644 --- a/test/form/export-all-from-internal/_expected/amd.js +++ b/test/form/export-all-from-internal/_expected/amd.js @@ -6,4 +6,6 @@ define(['exports'], function (exports) { 'use strict'; exports.a = a; exports.b = b; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/export-all-from-internal/_expected/cjs.js b/test/form/export-all-from-internal/_expected/cjs.js index 869bba079af..e208b74e989 100644 --- a/test/form/export-all-from-internal/_expected/cjs.js +++ b/test/form/export-all-from-internal/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + const a = 1; const b = 2; diff --git a/test/form/export-all-from-internal/_expected/es6.js b/test/form/export-all-from-internal/_expected/es.js similarity index 100% rename from test/form/export-all-from-internal/_expected/es6.js rename to test/form/export-all-from-internal/_expected/es.js diff --git a/test/form/export-all-from-internal/_expected/umd.js b/test/form/export-all-from-internal/_expected/umd.js index b249cc60978..5b395379f4e 100644 --- a/test/form/export-all-from-internal/_expected/umd.js +++ b/test/form/export-all-from-internal/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.exposedInternals = global.exposedInternals || {}))); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; const a = 1; const b = 2; @@ -10,4 +10,6 @@ exports.a = a; exports.b = b; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/export-default-2/_expected/es6.js b/test/form/export-default-2/_expected/es.js similarity index 100% rename from test/form/export-default-2/_expected/es6.js rename to test/form/export-default-2/_expected/es.js diff --git a/test/form/export-default-2/_expected/umd.js b/test/form/export-default-2/_expected/umd.js index 69c5a70106f..73b73a1d25c 100644 --- a/test/form/export-default-2/_expected/umd.js +++ b/test/form/export-default-2/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var bar = 1; return bar; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/export-default-3/_expected/es6.js b/test/form/export-default-3/_expected/es.js similarity index 100% rename from test/form/export-default-3/_expected/es6.js rename to test/form/export-default-3/_expected/es.js diff --git a/test/form/export-default-3/_expected/umd.js b/test/form/export-default-3/_expected/umd.js index 69c5a70106f..73b73a1d25c 100644 --- a/test/form/export-default-3/_expected/umd.js +++ b/test/form/export-default-3/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var bar = 1; return bar; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/export-default-import/_expected/amd.js b/test/form/export-default-import/_expected/amd.js index 9158c430d79..c880afb6795 100644 --- a/test/form/export-default-import/_expected/amd.js +++ b/test/form/export-default-import/_expected/amd.js @@ -6,4 +6,6 @@ define(['exports', 'x'], function (exports, x) { 'use strict'; exports.x = x; -}); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/export-default-import/_expected/cjs.js b/test/form/export-default-import/_expected/cjs.js index 60037db75b4..9cf59685e39 100644 --- a/test/form/export-default-import/_expected/cjs.js +++ b/test/form/export-default-import/_expected/cjs.js @@ -1,9 +1,11 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var x = _interopDefault(require('x')); -exports.x = x; \ No newline at end of file +exports.x = x; diff --git a/test/form/export-default-import/_expected/es6.js b/test/form/export-default-import/_expected/es.js similarity index 100% rename from test/form/export-default-import/_expected/es6.js rename to test/form/export-default-import/_expected/es.js diff --git a/test/form/export-default-import/_expected/umd.js b/test/form/export-default-import/_expected/umd.js index 872c0d847d1..6e689d4c729 100644 --- a/test/form/export-default-import/_expected/umd.js +++ b/test/form/export-default-import/_expected/umd.js @@ -2,7 +2,7 @@ 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'; +}(this, (function (exports,x) { 'use strict'; x = 'default' in x ? x['default'] : x; @@ -10,4 +10,6 @@ exports.x = x; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/export-default/_expected/es6.js b/test/form/export-default/_expected/es.js similarity index 100% rename from test/form/export-default/_expected/es6.js rename to test/form/export-default/_expected/es.js diff --git a/test/form/export-default/_expected/umd.js b/test/form/export-default/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/export-default/_expected/umd.js +++ b/test/form/export-default/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/export-multiple-vars/_expected/es6.js b/test/form/export-multiple-vars/_expected/es.js similarity index 100% rename from test/form/export-multiple-vars/_expected/es6.js rename to test/form/export-multiple-vars/_expected/es.js diff --git a/test/form/export-multiple-vars/_expected/umd.js b/test/form/export-multiple-vars/_expected/umd.js index 663cb1efd21..fe8a09dfcd0 100644 --- a/test/form/export-multiple-vars/_expected/umd.js +++ b/test/form/export-multiple-vars/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var a = 1; @@ -14,4 +14,4 @@ assert.equal( e, 5 ); assert.equal( i, 9 ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/exports-at-end-if-possible/_expected/amd.js b/test/form/exports-at-end-if-possible/_expected/amd.js index 2612901171f..7138aff3dcf 100644 --- a/test/form/exports-at-end-if-possible/_expected/amd.js +++ b/test/form/exports-at-end-if-possible/_expected/amd.js @@ -8,4 +8,6 @@ define(['exports'], function (exports) { 'use strict'; exports.FOO = FOO; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/exports-at-end-if-possible/_expected/cjs.js b/test/form/exports-at-end-if-possible/_expected/cjs.js index 57d55d3cb81..f62037c89b9 100644 --- a/test/form/exports-at-end-if-possible/_expected/cjs.js +++ b/test/form/exports-at-end-if-possible/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var FOO = 'foo'; console.log( FOO ); diff --git a/test/form/exports-at-end-if-possible/_expected/es6.js b/test/form/exports-at-end-if-possible/_expected/es.js similarity index 100% rename from test/form/exports-at-end-if-possible/_expected/es6.js rename to test/form/exports-at-end-if-possible/_expected/es.js diff --git a/test/form/exports-at-end-if-possible/_expected/umd.js b/test/form/exports-at-end-if-possible/_expected/umd.js index e9cbc8d163a..c6b382b85aa 100644 --- a/test/form/exports-at-end-if-possible/_expected/umd.js +++ b/test/form/exports-at-end-if-possible/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.myBundle = global.myBundle || {}))); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; var FOO = 'foo'; @@ -12,4 +12,6 @@ exports.FOO = FOO; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/external-import-alias-shadow/_expected/es6.js b/test/form/external-import-alias-shadow/_expected/es.js similarity index 100% rename from test/form/external-import-alias-shadow/_expected/es6.js rename to test/form/external-import-alias-shadow/_expected/es.js diff --git a/test/form/external-import-alias-shadow/_expected/umd.js b/test/form/external-import-alias-shadow/_expected/umd.js index 7be513dd065..29b64b4f365 100644 --- a/test/form/external-import-alias-shadow/_expected/umd.js +++ b/test/form/external-import-alias-shadow/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('acorn')) : typeof define === 'function' && define.amd ? define(['acorn'], factory) : (factory(global.acorn)); -}(this, function (acorn) { 'use strict'; +}(this, (function (acorn) { 'use strict'; function parse$1(source) { return acorn.parse(source, { ecmaVersion: 6 }); @@ -10,4 +10,4 @@ console.log(parse$1('foo')); -})); +}))); diff --git a/test/form/external-imports-custom-names-function/_expected/es6.js b/test/form/external-imports-custom-names-function/_expected/es.js similarity index 100% rename from test/form/external-imports-custom-names-function/_expected/es6.js rename to test/form/external-imports-custom-names-function/_expected/es.js diff --git a/test/form/external-imports-custom-names-function/_expected/umd.js b/test/form/external-imports-custom-names-function/_expected/umd.js index 1018b8a7a62..c9464dd5fff 100644 --- a/test/form/external-imports-custom-names-function/_expected/umd.js +++ b/test/form/external-imports-custom-names-function/_expected/umd.js @@ -2,8 +2,8 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('a-b-c')) : typeof define === 'function' && define.amd ? define(['a-b-c'], factory) : (factory(global.a_b_c)); -}(this, function (aBC) { 'use strict'; +}(this, (function (aBC) { 'use strict'; aBC.foo(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/external-imports-custom-names/_expected/es6.js b/test/form/external-imports-custom-names/_expected/es.js similarity index 100% rename from test/form/external-imports-custom-names/_expected/es6.js rename to test/form/external-imports-custom-names/_expected/es.js diff --git a/test/form/external-imports-custom-names/_expected/umd.js b/test/form/external-imports-custom-names/_expected/umd.js index 07642a17012..d57479b18b4 100644 --- a/test/form/external-imports-custom-names/_expected/umd.js +++ b/test/form/external-imports-custom-names/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) : typeof define === 'function' && define.amd ? define(['jquery'], factory) : (factory(global.jQuery)); -}(this, function ($) { 'use strict'; +}(this, (function ($) { 'use strict'; $ = 'default' in $ ? $['default'] : $; @@ -10,4 +10,4 @@ $( 'body' ).html( '

hello world!

' ); }); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/external-imports/_expected/es6.js b/test/form/external-imports/_expected/es.js similarity index 74% rename from test/form/external-imports/_expected/es6.js rename to test/form/external-imports/_expected/es.js index 1c632ef4cf1..59d2b5efef5 100644 --- a/test/form/external-imports/_expected/es6.js +++ b/test/form/external-imports/_expected/es.js @@ -1,11 +1,11 @@ import factory from 'factory'; import { bar, foo } from 'baz'; -import { port } from 'shipping-port'; +import { forEach, port } from 'shipping-port'; import * as containers from 'shipping-port'; import alphabet, { a } from 'alphabet'; factory( null ); foo( bar, port ); -containers.forEach( console.log, console ); +forEach( console.log, console ); console.log( a ); console.log( alphabet.length ); diff --git a/test/form/external-imports/_expected/umd.js b/test/form/external-imports/_expected/umd.js index 3feb767da7c..4b3fbbf7fe6 100644 --- a/test/form/external-imports/_expected/umd.js +++ b/test/form/external-imports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('factory'), require('baz'), require('shipping-port'), require('alphabet')) : typeof define === 'function' && define.amd ? define(['factory', 'baz', 'shipping-port', 'alphabet'], factory) : (factory(global.factory,global.baz,global.containers,global.alphabet)); -}(this, function (factory,baz,containers,alphabet) { 'use strict'; +}(this, (function (factory,baz,containers,alphabet) { 'use strict'; factory = 'default' in factory ? factory['default'] : factory; var alphabet__default = 'default' in alphabet ? alphabet['default'] : alphabet; @@ -13,4 +13,4 @@ console.log( alphabet.a ); console.log( alphabet__default.length ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/_config.js b/test/form/for-loop-with-empty-head/_config.js new file mode 100644 index 00000000000..3fc4a6756e5 --- /dev/null +++ b/test/form/for-loop-with-empty-head/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'handles for loop with empty head' +}; diff --git a/test/form/for-loop-with-empty-head/_expected/amd.js b/test/form/for-loop-with-empty-head/_expected/amd.js new file mode 100644 index 00000000000..a07e3e04015 --- /dev/null +++ b/test/form/for-loop-with-empty-head/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + for ( ; ; ) { + console.log( 42 ); + } + +}); \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/_expected/cjs.js b/test/form/for-loop-with-empty-head/_expected/cjs.js new file mode 100644 index 00000000000..f94dff7da87 --- /dev/null +++ b/test/form/for-loop-with-empty-head/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +for ( ; ; ) { + console.log( 42 ); +} \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/_expected/es.js b/test/form/for-loop-with-empty-head/_expected/es.js new file mode 100644 index 00000000000..1690f251c70 --- /dev/null +++ b/test/form/for-loop-with-empty-head/_expected/es.js @@ -0,0 +1,3 @@ +for ( ; ; ) { + console.log( 42 ); +} \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/_expected/iife.js b/test/form/for-loop-with-empty-head/_expected/iife.js new file mode 100644 index 00000000000..22172342afe --- /dev/null +++ b/test/form/for-loop-with-empty-head/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + for ( ; ; ) { + console.log( 42 ); + } + +}()); \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/_expected/umd.js b/test/form/for-loop-with-empty-head/_expected/umd.js new file mode 100644 index 00000000000..3e90731c512 --- /dev/null +++ b/test/form/for-loop-with-empty-head/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + for ( ; ; ) { + console.log( 42 ); + } + +}))); \ No newline at end of file diff --git a/test/form/for-loop-with-empty-head/main.js b/test/form/for-loop-with-empty-head/main.js new file mode 100644 index 00000000000..5e492f8fca9 --- /dev/null +++ b/test/form/for-loop-with-empty-head/main.js @@ -0,0 +1,3 @@ +for ( ; ; ) { + console.log( 42 ); +} diff --git a/test/form/import-external-namespace-and-default/_expected/es6.js b/test/form/import-external-namespace-and-default/_expected/es.js similarity index 65% rename from test/form/import-external-namespace-and-default/_expected/es6.js rename to test/form/import-external-namespace-and-default/_expected/es.js index 56555958f4d..07d61c1042c 100644 --- a/test/form/import-external-namespace-and-default/_expected/es6.js +++ b/test/form/import-external-namespace-and-default/_expected/es.js @@ -1,6 +1,7 @@ -import * as foo from 'foo'; +import { bar } from 'foo'; import foo__default from 'foo'; +import * as foo from 'foo'; -console.log( foo.bar ); +console.log( bar ); console.log( foo__default ); diff --git a/test/form/import-external-namespace-and-default/_expected/umd.js b/test/form/import-external-namespace-and-default/_expected/umd.js index ddcdcbd415e..bd10a35565b 100644 --- a/test/form/import-external-namespace-and-default/_expected/umd.js +++ b/test/form/import-external-namespace-and-default/_expected/umd.js @@ -2,7 +2,7 @@ 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'; +}(this, (function (foo) { 'use strict'; var foo__default = foo['default']; @@ -10,4 +10,4 @@ console.log( foo__default ); -})); +}))); diff --git a/test/form/import-named-exported-global-with-alias/_expected/es6.js b/test/form/import-named-exported-global-with-alias/_expected/es.js similarity index 100% rename from test/form/import-named-exported-global-with-alias/_expected/es6.js rename to test/form/import-named-exported-global-with-alias/_expected/es.js diff --git a/test/form/import-named-exported-global-with-alias/_expected/umd.js b/test/form/import-named-exported-global-with-alias/_expected/umd.js index f3395b7d873..d561e69c33b 100644 --- a/test/form/import-named-exported-global-with-alias/_expected/umd.js +++ b/test/form/import-named-exported-global-with-alias/_expected/umd.js @@ -2,8 +2,8 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/includes-all-namespace-declarations/_config.js b/test/form/includes-all-namespace-declarations/_config.js new file mode 100644 index 00000000000..30ffc5edba8 --- /dev/null +++ b/test/form/includes-all-namespace-declarations/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'includes all declarations referenced by reified namespaces' +} diff --git a/test/form/includes-all-namespace-declarations/_expected/amd.js b/test/form/includes-all-namespace-declarations/_expected/amd.js new file mode 100644 index 00000000000..ec759b11cba --- /dev/null +++ b/test/form/includes-all-namespace-declarations/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + + +}); \ No newline at end of file diff --git a/test/form/includes-all-namespace-declarations/_expected/cjs.js b/test/form/includes-all-namespace-declarations/_expected/cjs.js new file mode 100644 index 00000000000..eb109abbed0 --- /dev/null +++ b/test/form/includes-all-namespace-declarations/_expected/cjs.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/test/form/side-effect-l/_expected/es6.js b/test/form/includes-all-namespace-declarations/_expected/es.js similarity index 100% rename from test/form/side-effect-l/_expected/es6.js rename to test/form/includes-all-namespace-declarations/_expected/es.js diff --git a/test/form/includes-all-namespace-declarations/_expected/iife.js b/test/form/includes-all-namespace-declarations/_expected/iife.js new file mode 100644 index 00000000000..f3d1016ed3e --- /dev/null +++ b/test/form/includes-all-namespace-declarations/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +}()); \ No newline at end of file diff --git a/test/form/includes-all-namespace-declarations/_expected/umd.js b/test/form/includes-all-namespace-declarations/_expected/umd.js new file mode 100644 index 00000000000..d561e69c33b --- /dev/null +++ b/test/form/includes-all-namespace-declarations/_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'; + + + +}))); \ No newline at end of file diff --git a/test/form/includes-all-namespace-declarations/indirection.js b/test/form/includes-all-namespace-declarations/indirection.js new file mode 100644 index 00000000000..d98c18c84f9 --- /dev/null +++ b/test/form/includes-all-namespace-declarations/indirection.js @@ -0,0 +1,7 @@ +import * as unused from './unused.js'; + +var indirection = { + unused: unused +}; + +export { indirection }; diff --git a/test/form/includes-all-namespace-declarations/main.js b/test/form/includes-all-namespace-declarations/main.js new file mode 100644 index 00000000000..0b45d9e763e --- /dev/null +++ b/test/form/includes-all-namespace-declarations/main.js @@ -0,0 +1 @@ +import { indirection } from './indirection.js'; diff --git a/test/form/includes-all-namespace-declarations/unused.js b/test/form/includes-all-namespace-declarations/unused.js new file mode 100644 index 00000000000..b0ff5124eef --- /dev/null +++ b/test/form/includes-all-namespace-declarations/unused.js @@ -0,0 +1,3 @@ +function foo () {} + +export { foo }; diff --git a/test/form/indent-false/_expected/es6.js b/test/form/indent-false/_expected/es.js similarity index 100% rename from test/form/indent-false/_expected/es6.js rename to test/form/indent-false/_expected/es.js diff --git a/test/form/indent-false/_expected/umd.js b/test/form/indent-false/_expected/umd.js index d09a5063a40..c0289b07cf9 100644 --- a/test/form/indent-false/_expected/umd.js +++ b/test/form/indent-false/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.foo = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'indented with tabs' ); @@ -10,4 +10,4 @@ function foo () { return foo; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/indent-true-spaces/_expected/es6.js b/test/form/indent-true-spaces/_expected/es.js similarity index 100% rename from test/form/indent-true-spaces/_expected/es6.js rename to test/form/indent-true-spaces/_expected/es.js diff --git a/test/form/indent-true-spaces/_expected/umd.js b/test/form/indent-true-spaces/_expected/umd.js index fbc898e2e49..51032c8e3df 100644 --- a/test/form/indent-true-spaces/_expected/umd.js +++ b/test/form/indent-true-spaces/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.foo = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'indented with spaces' ); @@ -10,4 +10,4 @@ return foo; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/indent-true/_expected/es6.js b/test/form/indent-true/_expected/es.js similarity index 100% rename from test/form/indent-true/_expected/es6.js rename to test/form/indent-true/_expected/es.js diff --git a/test/form/indent-true/_expected/umd.js b/test/form/indent-true/_expected/umd.js index a2b634ecb80..786d82b1c53 100644 --- a/test/form/indent-true/_expected/umd.js +++ b/test/form/indent-true/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.foo = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'indented with tabs' ); @@ -10,4 +10,4 @@ return foo; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/internal-conflict-resolution/_expected/es6.js b/test/form/internal-conflict-resolution/_expected/es.js similarity index 100% rename from test/form/internal-conflict-resolution/_expected/es6.js rename to test/form/internal-conflict-resolution/_expected/es.js diff --git a/test/form/internal-conflict-resolution/_expected/umd.js b/test/form/internal-conflict-resolution/_expected/umd.js index a07cece5ddb..b6d7f90bf5e 100644 --- a/test/form/internal-conflict-resolution/_expected/umd.js +++ b/test/form/internal-conflict-resolution/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var bar$1 = 42; @@ -16,4 +16,4 @@ bar(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/interop-false/_config.js b/test/form/interop-false/_config.js new file mode 100644 index 00000000000..0076e3ab092 --- /dev/null +++ b/test/form/interop-false/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'getInterop with interop: false', + options: { + moduleName: 'foo', + interop: false + } +}; diff --git a/test/form/interop-false/_expected/amd.js b/test/form/interop-false/_expected/amd.js new file mode 100644 index 00000000000..9245883ba6c --- /dev/null +++ b/test/form/interop-false/_expected/amd.js @@ -0,0 +1,7 @@ +define(['core/view'], function (View) { 'use strict'; + + var main = View.extend({}); + + return main; + +}); diff --git a/test/form/interop-false/_expected/cjs.js b/test/form/interop-false/_expected/cjs.js new file mode 100644 index 00000000000..8396bc764b9 --- /dev/null +++ b/test/form/interop-false/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +var View = require('core/view'); + +var main = View.extend({}); + +module.exports = main; diff --git a/test/form/interop-false/_expected/es.js b/test/form/interop-false/_expected/es.js new file mode 100644 index 00000000000..d5e775e86a2 --- /dev/null +++ b/test/form/interop-false/_expected/es.js @@ -0,0 +1,5 @@ +import View from 'core/view'; + +var main = View.extend({}); + +export default main; diff --git a/test/form/interop-false/_expected/iife.js b/test/form/interop-false/_expected/iife.js new file mode 100644 index 00000000000..d94c4325cc1 --- /dev/null +++ b/test/form/interop-false/_expected/iife.js @@ -0,0 +1,8 @@ +var foo = (function (View) { + 'use strict'; + + var main = View.extend({}); + + return main; + +}(View)); diff --git a/test/form/interop-false/_expected/umd.js b/test/form/interop-false/_expected/umd.js new file mode 100644 index 00000000000..5c9be13a166 --- /dev/null +++ b/test/form/interop-false/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('core/view')) : + typeof define === 'function' && define.amd ? define(['core/view'], factory) : + (global.foo = factory(global.View)); +}(this, (function (View) { 'use strict'; + + var main = View.extend({}); + + return main; + +}))); diff --git a/test/form/interop-false/main.js b/test/form/interop-false/main.js new file mode 100644 index 00000000000..a6b10404cfb --- /dev/null +++ b/test/form/interop-false/main.js @@ -0,0 +1,2 @@ +import View from 'core/view'; +export default View.extend({}); diff --git a/test/form/intro-and-outro/_config.js b/test/form/intro-and-outro/_config.js index 36b7a9d74ef..410d586b100 100644 --- a/test/form/intro-and-outro/_config.js +++ b/test/form/intro-and-outro/_config.js @@ -2,6 +2,8 @@ module.exports = { description: 'adds an intro/outro', options: { intro: '/* this is an intro */', - outro: '/* this is an outro */' + outro: '/* this is an outro */', + moduleName: 'foo', + external: [ 'external' ] } }; diff --git a/test/form/intro-and-outro/_expected/amd.js b/test/form/intro-and-outro/_expected/amd.js index a58ac95a344..ca940e42d5e 100644 --- a/test/form/intro-and-outro/_expected/amd.js +++ b/test/form/intro-and-outro/_expected/amd.js @@ -1,7 +1,14 @@ -define(function () { 'use strict'; +define(['external'], function (a) { 'use strict'; /* this is an intro */ - console.log( 'hello world' ); + var a__default = 'default' in a ? a['default'] : a; + + console.log( a__default ); + console.log( a.b ); + + var main = 42; + + return main; /* this is an outro */ }); diff --git a/test/form/intro-and-outro/_expected/cjs.js b/test/form/intro-and-outro/_expected/cjs.js index 662c938756a..6c68e670a59 100644 --- a/test/form/intro-and-outro/_expected/cjs.js +++ b/test/form/intro-and-outro/_expected/cjs.js @@ -1,5 +1,15 @@ 'use strict'; /* this is an intro */ -console.log( 'hello world' ); +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var a = require('external'); +var a__default = _interopDefault(a); + +console.log( a__default ); +console.log( a.b ); + +var main = 42; + +module.exports = main; /* this is an outro */ diff --git a/test/form/intro-and-outro/_expected/es.js b/test/form/intro-and-outro/_expected/es.js new file mode 100644 index 00000000000..2da2a74c1ad --- /dev/null +++ b/test/form/intro-and-outro/_expected/es.js @@ -0,0 +1,10 @@ +/* this is an intro */ +import a, { b } from 'external'; + +console.log( a ); +console.log( b ); + +var main = 42; + +export default main; +/* this is an outro */ diff --git a/test/form/intro-and-outro/_expected/es6.js b/test/form/intro-and-outro/_expected/es6.js deleted file mode 100644 index c017a4570b2..00000000000 --- a/test/form/intro-and-outro/_expected/es6.js +++ /dev/null @@ -1,3 +0,0 @@ -/* this is an intro */ -console.log( 'hello world' ); -/* this is an outro */ diff --git a/test/form/intro-and-outro/_expected/iife.js b/test/form/intro-and-outro/_expected/iife.js index 15a21d930f4..2c716d396b2 100644 --- a/test/form/intro-and-outro/_expected/iife.js +++ b/test/form/intro-and-outro/_expected/iife.js @@ -1,8 +1,15 @@ -(function () { +var foo = (function (a) { 'use strict'; /* this is an intro */ - console.log( 'hello world' ); + var a__default = 'default' in a ? a['default'] : a; + + console.log( a__default ); + console.log( a.b ); + + var main = 42; + + return main; /* this is an outro */ -}()); +}(a)); diff --git a/test/form/intro-and-outro/_expected/umd.js b/test/form/intro-and-outro/_expected/umd.js index c08f507a6bf..232db4edc08 100644 --- a/test/form/intro-and-outro/_expected/umd.js +++ b/test/form/intro-and-outro/_expected/umd.js @@ -1,11 +1,18 @@ (function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory() : - typeof define === 'function' && define.amd ? define(factory) : - (factory()); -}(this, function () { 'use strict'; + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('external')) : + typeof define === 'function' && define.amd ? define(['external'], factory) : + (global.foo = factory(global.a)); +}(this, (function (a) { 'use strict'; /* this is an intro */ - console.log( 'hello world' ); + var a__default = 'default' in a ? a['default'] : a; + + console.log( a__default ); + console.log( a.b ); + + var main = 42; + + return main; /* this is an outro */ -})); \ No newline at end of file +}))); diff --git a/test/form/intro-and-outro/main.js b/test/form/intro-and-outro/main.js index 3b5a60406e2..663ee991f9b 100644 --- a/test/form/intro-and-outro/main.js +++ b/test/form/intro-and-outro/main.js @@ -1 +1,6 @@ -console.log( 'hello world' ); +import a, { b } from 'external' + +console.log( a ); +console.log( b ); + +export default 42; diff --git a/test/form/legacy-getter/_config.js b/test/form/legacy-getter/_config.js new file mode 100644 index 00000000000..591c08e1954 --- /dev/null +++ b/test/form/legacy-getter/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'Does not output getters when in legacy', + options: { + legacy: true, + moduleName: 'foo' + } +}; diff --git a/test/form/legacy-getter/_expected/amd.js b/test/form/legacy-getter/_expected/amd.js new file mode 100644 index 00000000000..4aba57b9b0c --- /dev/null +++ b/test/form/legacy-getter/_expected/amd.js @@ -0,0 +1,23 @@ +define(['exports'], function (exports) { 'use strict'; + + var browserSpecificThing; + + if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; + } else { + browserSpecificThing = "DecentBrowserThing"; + } + + function foo() {} + + + var browserStuff = (Object.freeze || Object)({ + browserSpecificThing: browserSpecificThing, + foo: foo + }); + + console.log(browserSpecificThing); + + exports.B = browserStuff; + +}); diff --git a/test/form/legacy-getter/_expected/cjs.js b/test/form/legacy-getter/_expected/cjs.js new file mode 100644 index 00000000000..3b665619ec7 --- /dev/null +++ b/test/form/legacy-getter/_expected/cjs.js @@ -0,0 +1,21 @@ +'use strict'; + +var browserSpecificThing; + +if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; +} else { + browserSpecificThing = "DecentBrowserThing"; +} + +function foo() {} + + +var browserStuff = (Object.freeze || Object)({ + browserSpecificThing: browserSpecificThing, + foo: foo +}); + +console.log(browserSpecificThing); + +exports.B = browserStuff; diff --git a/test/form/legacy-getter/_expected/es.js b/test/form/legacy-getter/_expected/es.js new file mode 100644 index 00000000000..f2c9a6acbab --- /dev/null +++ b/test/form/legacy-getter/_expected/es.js @@ -0,0 +1,19 @@ +var browserSpecificThing; + +if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; +} else { + browserSpecificThing = "DecentBrowserThing"; +} + +function foo() {} + + +var browserStuff = (Object.freeze || Object)({ + browserSpecificThing: browserSpecificThing, + foo: foo +}); + +console.log(browserSpecificThing); + +export { browserStuff as B }; diff --git a/test/form/legacy-getter/_expected/iife.js b/test/form/legacy-getter/_expected/iife.js new file mode 100644 index 00000000000..a588fbbd3c7 --- /dev/null +++ b/test/form/legacy-getter/_expected/iife.js @@ -0,0 +1,24 @@ +(function (exports) { + 'use strict'; + + var browserSpecificThing; + + if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; + } else { + browserSpecificThing = "DecentBrowserThing"; + } + + function foo() {} + + + var browserStuff = (Object.freeze || Object)({ + browserSpecificThing: browserSpecificThing, + foo: foo + }); + + console.log(browserSpecificThing); + + exports.B = browserStuff; + +}((this.foo = this.foo || {}))); diff --git a/test/form/legacy-getter/_expected/umd.js b/test/form/legacy-getter/_expected/umd.js new file mode 100644 index 00000000000..aa0b4f7bb27 --- /dev/null +++ b/test/form/legacy-getter/_expected/umd.js @@ -0,0 +1,27 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.foo = global.foo || {}))); +}(this, (function (exports) { 'use strict'; + + var browserSpecificThing; + + if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; + } else { + browserSpecificThing = "DecentBrowserThing"; + } + + function foo() {} + + + var browserStuff = (Object.freeze || Object)({ + browserSpecificThing: browserSpecificThing, + foo: foo + }); + + console.log(browserSpecificThing); + + exports.B = browserStuff; + +}))); diff --git a/test/form/legacy-getter/browserStuff.js b/test/form/legacy-getter/browserStuff.js new file mode 100644 index 00000000000..9f3d71cd487 --- /dev/null +++ b/test/form/legacy-getter/browserStuff.js @@ -0,0 +1,9 @@ +export var browserSpecificThing; + +if ('ActiveXObject' in window) { + browserSpecificThing = "InternetExplorerThing"; +} else { + browserSpecificThing = "DecentBrowserThing"; +} + +export function foo() {} diff --git a/test/form/legacy-getter/main.js b/test/form/legacy-getter/main.js new file mode 100644 index 00000000000..27915503578 --- /dev/null +++ b/test/form/legacy-getter/main.js @@ -0,0 +1,4 @@ +import * as B from './browserStuff'; +export {B}; + +console.log(B.browserSpecificThing); diff --git a/test/form/legacy-reified-namespace/_config.js b/test/form/legacy-reified-namespace/_config.js new file mode 100644 index 00000000000..1905df38821 --- /dev/null +++ b/test/form/legacy-reified-namespace/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'quotes reserved words in object literals', + options: { + moduleName: 'myBundle', + legacy: true + } +}; diff --git a/test/form/legacy-reified-namespace/_expected/amd.js b/test/form/legacy-reified-namespace/_expected/amd.js new file mode 100644 index 00000000000..5fb5bd22f5b --- /dev/null +++ b/test/form/legacy-reified-namespace/_expected/amd.js @@ -0,0 +1,14 @@ +define(function () { 'use strict'; + + const _typeof = 'typeof'; + const foo = 1; + + + var namespace = (Object.freeze || Object)({ + 'typeof': _typeof, + foo: foo + }); + + console.log( namespace ); + +}); diff --git a/test/form/legacy-reified-namespace/_expected/cjs.js b/test/form/legacy-reified-namespace/_expected/cjs.js new file mode 100644 index 00000000000..10ecf7cd260 --- /dev/null +++ b/test/form/legacy-reified-namespace/_expected/cjs.js @@ -0,0 +1,12 @@ +'use strict'; + +const _typeof = 'typeof'; +const foo = 1; + + +var namespace = (Object.freeze || Object)({ + 'typeof': _typeof, + foo: foo +}); + +console.log( namespace ); diff --git a/test/form/legacy-reified-namespace/_expected/es.js b/test/form/legacy-reified-namespace/_expected/es.js new file mode 100644 index 00000000000..7b52e339e9e --- /dev/null +++ b/test/form/legacy-reified-namespace/_expected/es.js @@ -0,0 +1,10 @@ +const _typeof = 'typeof'; +const foo = 1; + + +var namespace = (Object.freeze || Object)({ + 'typeof': _typeof, + foo: foo +}); + +console.log( namespace ); diff --git a/test/form/legacy-reified-namespace/_expected/iife.js b/test/form/legacy-reified-namespace/_expected/iife.js new file mode 100644 index 00000000000..9b60efdb1cd --- /dev/null +++ b/test/form/legacy-reified-namespace/_expected/iife.js @@ -0,0 +1,15 @@ +(function () { + 'use strict'; + + const _typeof = 'typeof'; + const foo = 1; + + + var namespace = (Object.freeze || Object)({ + 'typeof': _typeof, + foo: foo + }); + + console.log( namespace ); + +}()); diff --git a/test/form/legacy-reified-namespace/_expected/umd.js b/test/form/legacy-reified-namespace/_expected/umd.js new file mode 100644 index 00000000000..fe542c0c0dd --- /dev/null +++ b/test/form/legacy-reified-namespace/_expected/umd.js @@ -0,0 +1,18 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + const _typeof = 'typeof'; + const foo = 1; + + + var namespace = (Object.freeze || Object)({ + 'typeof': _typeof, + foo: foo + }); + + console.log( namespace ); + +}))); diff --git a/test/form/legacy-reified-namespace/main.js b/test/form/legacy-reified-namespace/main.js new file mode 100644 index 00000000000..5585c1e752c --- /dev/null +++ b/test/form/legacy-reified-namespace/main.js @@ -0,0 +1,3 @@ +import * as namespace from './namespace.js'; + +console.log( namespace ); diff --git a/test/form/legacy-reified-namespace/namespace.js b/test/form/legacy-reified-namespace/namespace.js new file mode 100644 index 00000000000..46fe09d2ae2 --- /dev/null +++ b/test/form/legacy-reified-namespace/namespace.js @@ -0,0 +1,3 @@ +const _typeof = 'typeof'; +export { _typeof as typeof }; +export const foo = 1; diff --git a/test/form/legacy/_config.js b/test/form/legacy/_config.js new file mode 100644 index 00000000000..a461d8eb303 --- /dev/null +++ b/test/form/legacy/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'supports environments without Object.freeze, Object.defined', + options: { + moduleName: 'myBundle', + legacy: true + } +}; diff --git a/test/form/legacy/_expected/amd.js b/test/form/legacy/_expected/amd.js new file mode 100644 index 00000000000..c1b004ad318 --- /dev/null +++ b/test/form/legacy/_expected/amd.js @@ -0,0 +1,20 @@ +define(['exports'], function (exports) { 'use strict'; + + const foo = 1; + const bar = 2; + + + var namespace = (Object.freeze || Object)({ + foo: foo, + bar: bar + }); + + console.log( Object.keys( namespace ) ); + + const a = 1; + const b = 2; + + exports.a = a; + exports.b = b; + +}); diff --git a/test/form/legacy/_expected/cjs.js b/test/form/legacy/_expected/cjs.js new file mode 100644 index 00000000000..f904af34b8c --- /dev/null +++ b/test/form/legacy/_expected/cjs.js @@ -0,0 +1,18 @@ +'use strict'; + +const foo = 1; +const bar = 2; + + +var namespace = (Object.freeze || Object)({ + foo: foo, + bar: bar +}); + +console.log( Object.keys( namespace ) ); + +const a = 1; +const b = 2; + +exports.a = a; +exports.b = b; diff --git a/test/form/legacy/_expected/es.js b/test/form/legacy/_expected/es.js new file mode 100644 index 00000000000..dab29e59840 --- /dev/null +++ b/test/form/legacy/_expected/es.js @@ -0,0 +1,15 @@ +const foo = 1; +const bar = 2; + + +var namespace = (Object.freeze || Object)({ + foo: foo, + bar: bar +}); + +console.log( Object.keys( namespace ) ); + +const a = 1; +const b = 2; + +export { a, b }; diff --git a/test/form/legacy/_expected/iife.js b/test/form/legacy/_expected/iife.js new file mode 100644 index 00000000000..19f8c9139f5 --- /dev/null +++ b/test/form/legacy/_expected/iife.js @@ -0,0 +1,21 @@ +(function (exports) { + 'use strict'; + + const foo = 1; + const bar = 2; + + + var namespace = (Object.freeze || Object)({ + foo: foo, + bar: bar + }); + + console.log( Object.keys( namespace ) ); + + const a = 1; + const b = 2; + + exports.a = a; + exports.b = b; + +}((this.myBundle = this.myBundle || {}))); diff --git a/test/form/legacy/_expected/umd.js b/test/form/legacy/_expected/umd.js new file mode 100644 index 00000000000..7c98779c42c --- /dev/null +++ b/test/form/legacy/_expected/umd.js @@ -0,0 +1,24 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.myBundle = global.myBundle || {}))); +}(this, (function (exports) { 'use strict'; + + const foo = 1; + const bar = 2; + + + var namespace = (Object.freeze || Object)({ + foo: foo, + bar: bar + }); + + console.log( Object.keys( namespace ) ); + + const a = 1; + const b = 2; + + exports.a = a; + exports.b = b; + +}))); diff --git a/test/form/legacy/main.js b/test/form/legacy/main.js new file mode 100644 index 00000000000..d434187c18c --- /dev/null +++ b/test/form/legacy/main.js @@ -0,0 +1,6 @@ +import * as namespace from './namespace.js'; + +console.log( Object.keys( namespace ) ); + +export const a = 1; +export const b = 2; diff --git a/test/form/legacy/namespace.js b/test/form/legacy/namespace.js new file mode 100644 index 00000000000..e3a53f2f9ea --- /dev/null +++ b/test/form/legacy/namespace.js @@ -0,0 +1,2 @@ +export const foo = 1; +export const bar = 2; diff --git a/test/form/module-name-scoped-package/_config.js b/test/form/module-name-scoped-package/_config.js new file mode 100644 index 00000000000..56818817923 --- /dev/null +++ b/test/form/module-name-scoped-package/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'allows module name with dashes to be added to the global object', + options: { + moduleName: '@scoped/npm-package' + } +}; diff --git a/test/form/module-name-scoped-package/_expected/amd.js b/test/form/module-name-scoped-package/_expected/amd.js new file mode 100644 index 00000000000..69586a0bf90 --- /dev/null +++ b/test/form/module-name-scoped-package/_expected/amd.js @@ -0,0 +1,9 @@ +define(['exports'], function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/module-name-scoped-package/_expected/cjs.js b/test/form/module-name-scoped-package/_expected/cjs.js new file mode 100644 index 00000000000..796e3ef7f16 --- /dev/null +++ b/test/form/module-name-scoped-package/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +let foo = 'foo'; + +exports.foo = foo; diff --git a/test/form/module-name-scoped-package/_expected/es.js b/test/form/module-name-scoped-package/_expected/es.js new file mode 100644 index 00000000000..3ee7d0bc1db --- /dev/null +++ b/test/form/module-name-scoped-package/_expected/es.js @@ -0,0 +1,3 @@ +let foo = 'foo'; + +export { foo }; diff --git a/test/form/module-name-scoped-package/_expected/iife.js b/test/form/module-name-scoped-package/_expected/iife.js new file mode 100644 index 00000000000..7445d49b396 --- /dev/null +++ b/test/form/module-name-scoped-package/_expected/iife.js @@ -0,0 +1,8 @@ +(function (exports) { + 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + +}((this['@scoped/npm-package'] = this['@scoped/npm-package'] || {}))); diff --git a/test/form/module-name-scoped-package/_expected/umd.js b/test/form/module-name-scoped-package/_expected/umd.js new file mode 100644 index 00000000000..33822192a14 --- /dev/null +++ b/test/form/module-name-scoped-package/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global['@scoped/npm-package'] = global['@scoped/npm-package'] || {}))); +}(this, (function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/module-name-scoped-package/main.js b/test/form/module-name-scoped-package/main.js new file mode 100644 index 00000000000..816d625996f --- /dev/null +++ b/test/form/module-name-scoped-package/main.js @@ -0,0 +1 @@ +export let foo = 'foo'; diff --git a/test/form/module-name-wat/_config.js b/test/form/module-name-wat/_config.js new file mode 100644 index 00000000000..31fe8d44d0b --- /dev/null +++ b/test/form/module-name-wat/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'properly dereferences properties on the global object regardless of nesting', + options: { + moduleName: 'foo.@scoped/npm-package.bar.why-would-you-do-this' + } +}; diff --git a/test/form/module-name-wat/_expected/amd.js b/test/form/module-name-wat/_expected/amd.js new file mode 100644 index 00000000000..69586a0bf90 --- /dev/null +++ b/test/form/module-name-wat/_expected/amd.js @@ -0,0 +1,9 @@ +define(['exports'], function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/module-name-wat/_expected/cjs.js b/test/form/module-name-wat/_expected/cjs.js new file mode 100644 index 00000000000..796e3ef7f16 --- /dev/null +++ b/test/form/module-name-wat/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +let foo = 'foo'; + +exports.foo = foo; diff --git a/test/form/module-name-wat/_expected/es.js b/test/form/module-name-wat/_expected/es.js new file mode 100644 index 00000000000..3ee7d0bc1db --- /dev/null +++ b/test/form/module-name-wat/_expected/es.js @@ -0,0 +1,3 @@ +let foo = 'foo'; + +export { foo }; diff --git a/test/form/module-name-wat/_expected/iife.js b/test/form/module-name-wat/_expected/iife.js new file mode 100644 index 00000000000..2f7b7b24015 --- /dev/null +++ b/test/form/module-name-wat/_expected/iife.js @@ -0,0 +1,11 @@ +this.foo = this.foo || {}; +this.foo['@scoped/npm-package'] = this.foo['@scoped/npm-package'] || {}; +this.foo['@scoped/npm-package'].bar = this.foo['@scoped/npm-package'].bar || {}; +(function (exports) { + 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + +}((this.foo['@scoped/npm-package'].bar['why-would-you-do-this'] = this.foo['@scoped/npm-package'].bar['why-would-you-do-this'] || {}))); diff --git a/test/form/module-name-wat/_expected/umd.js b/test/form/module-name-wat/_expected/umd.js new file mode 100644 index 00000000000..22c80107284 --- /dev/null +++ b/test/form/module-name-wat/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.foo = global.foo || {}, global.foo['@scoped/npm-package'] = global.foo['@scoped/npm-package'] || {}, global.foo['@scoped/npm-package'].bar = global.foo['@scoped/npm-package'].bar || {}, global.foo['@scoped/npm-package'].bar['why-would-you-do-this'] = global.foo['@scoped/npm-package'].bar['why-would-you-do-this'] || {}))); +}(this, (function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/module-name-wat/main.js b/test/form/module-name-wat/main.js new file mode 100644 index 00000000000..816d625996f --- /dev/null +++ b/test/form/module-name-wat/main.js @@ -0,0 +1 @@ +export let foo = 'foo'; diff --git a/test/form/module-name-with-dashes/_config.js b/test/form/module-name-with-dashes/_config.js new file mode 100644 index 00000000000..c466b887cd3 --- /dev/null +++ b/test/form/module-name-with-dashes/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'allows module name with dashes to be added to the global object', + options: { + moduleName: 'module-name-with-dashes' + } +}; diff --git a/test/form/module-name-with-dashes/_expected/amd.js b/test/form/module-name-with-dashes/_expected/amd.js new file mode 100644 index 00000000000..69586a0bf90 --- /dev/null +++ b/test/form/module-name-with-dashes/_expected/amd.js @@ -0,0 +1,9 @@ +define(['exports'], function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/module-name-with-dashes/_expected/cjs.js b/test/form/module-name-with-dashes/_expected/cjs.js new file mode 100644 index 00000000000..796e3ef7f16 --- /dev/null +++ b/test/form/module-name-with-dashes/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +let foo = 'foo'; + +exports.foo = foo; diff --git a/test/form/module-name-with-dashes/_expected/es.js b/test/form/module-name-with-dashes/_expected/es.js new file mode 100644 index 00000000000..3ee7d0bc1db --- /dev/null +++ b/test/form/module-name-with-dashes/_expected/es.js @@ -0,0 +1,3 @@ +let foo = 'foo'; + +export { foo }; diff --git a/test/form/module-name-with-dashes/_expected/iife.js b/test/form/module-name-with-dashes/_expected/iife.js new file mode 100644 index 00000000000..5eb10627ee3 --- /dev/null +++ b/test/form/module-name-with-dashes/_expected/iife.js @@ -0,0 +1,8 @@ +(function (exports) { + 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + +}((this['module-name-with-dashes'] = this['module-name-with-dashes'] || {}))); diff --git a/test/form/module-name-with-dashes/_expected/umd.js b/test/form/module-name-with-dashes/_expected/umd.js new file mode 100644 index 00000000000..8d90ff63891 --- /dev/null +++ b/test/form/module-name-with-dashes/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global['module-name-with-dashes'] = global['module-name-with-dashes'] || {}))); +}(this, (function (exports) { 'use strict'; + + let foo = 'foo'; + + exports.foo = foo; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/module-name-with-dashes/main.js b/test/form/module-name-with-dashes/main.js new file mode 100644 index 00000000000..816d625996f --- /dev/null +++ b/test/form/module-name-with-dashes/main.js @@ -0,0 +1 @@ +export let foo = 'foo'; diff --git a/test/form/multiple-exports/_expected/amd.js b/test/form/multiple-exports/_expected/amd.js index 2ebff3b7bf3..0d70786c2ea 100644 --- a/test/form/multiple-exports/_expected/amd.js +++ b/test/form/multiple-exports/_expected/amd.js @@ -6,4 +6,6 @@ define(['exports'], function (exports) { 'use strict'; exports.foo = foo; exports.bar = bar; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/multiple-exports/_expected/cjs.js b/test/form/multiple-exports/_expected/cjs.js index 1968b8b0c32..a5fbd761d93 100644 --- a/test/form/multiple-exports/_expected/cjs.js +++ b/test/form/multiple-exports/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var foo = 1; var bar = 2; diff --git a/test/form/multiple-exports/_expected/es6.js b/test/form/multiple-exports/_expected/es.js similarity index 100% rename from test/form/multiple-exports/_expected/es6.js rename to test/form/multiple-exports/_expected/es.js diff --git a/test/form/multiple-exports/_expected/umd.js b/test/form/multiple-exports/_expected/umd.js index 30a54d619ed..4ccb2badf9b 100644 --- a/test/form/multiple-exports/_expected/umd.js +++ b/test/form/multiple-exports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.myBundle = global.myBundle || {}))); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; var foo = 1; var bar = 2; @@ -10,4 +10,6 @@ exports.foo = foo; exports.bar = bar; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/namespace-optimization-b/_expected/amd.js b/test/form/namespace-optimization-b/_expected/amd.js index 30c5406a936..e2582ccbce3 100644 --- a/test/form/namespace-optimization-b/_expected/amd.js +++ b/test/form/namespace-optimization-b/_expected/amd.js @@ -16,4 +16,4 @@ define(function () { 'use strict'; a(); -}); \ No newline at end of file +}); diff --git a/test/form/namespace-optimization-b/_expected/cjs.js b/test/form/namespace-optimization-b/_expected/cjs.js index 3ee6869d3ef..a826df23f94 100644 --- a/test/form/namespace-optimization-b/_expected/cjs.js +++ b/test/form/namespace-optimization-b/_expected/cjs.js @@ -14,4 +14,4 @@ function a () { } } -a(); \ No newline at end of file +a(); diff --git a/test/form/namespace-optimization-b/_expected/es6.js b/test/form/namespace-optimization-b/_expected/es.js similarity index 95% rename from test/form/namespace-optimization-b/_expected/es6.js rename to test/form/namespace-optimization-b/_expected/es.js index 8346d0d5317..85c15d863f4 100644 --- a/test/form/namespace-optimization-b/_expected/es6.js +++ b/test/form/namespace-optimization-b/_expected/es.js @@ -12,4 +12,4 @@ function a () { } } -a(); \ No newline at end of file +a(); diff --git a/test/form/namespace-optimization-b/_expected/iife.js b/test/form/namespace-optimization-b/_expected/iife.js index 6aeb1cd54d9..6c497f5c205 100644 --- a/test/form/namespace-optimization-b/_expected/iife.js +++ b/test/form/namespace-optimization-b/_expected/iife.js @@ -17,4 +17,4 @@ a(); -}()); \ No newline at end of file +}()); diff --git a/test/form/namespace-optimization-b/_expected/umd.js b/test/form/namespace-optimization-b/_expected/umd.js index 866a3bdd79c..7a2c4b0ab6a 100644 --- a/test/form/namespace-optimization-b/_expected/umd.js +++ b/test/form/namespace-optimization-b/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'foo' ); @@ -20,4 +20,4 @@ a(); -})); \ No newline at end of file +}))); diff --git a/test/form/namespace-optimization/_expected/amd.js b/test/form/namespace-optimization/_expected/amd.js index a244c476777..95231f1878b 100644 --- a/test/form/namespace-optimization/_expected/amd.js +++ b/test/form/namespace-optimization/_expected/amd.js @@ -2,6 +2,6 @@ define(function () { 'use strict'; function a () {} - a(); + console.log( a() ); }); diff --git a/test/form/namespace-optimization/_expected/cjs.js b/test/form/namespace-optimization/_expected/cjs.js index b52a7e5c10e..33a83e92c84 100644 --- a/test/form/namespace-optimization/_expected/cjs.js +++ b/test/form/namespace-optimization/_expected/cjs.js @@ -2,4 +2,4 @@ function a () {} -a(); +console.log( a() ); diff --git a/test/form/namespace-optimization/_expected/es.js b/test/form/namespace-optimization/_expected/es.js new file mode 100644 index 00000000000..297521e9926 --- /dev/null +++ b/test/form/namespace-optimization/_expected/es.js @@ -0,0 +1,3 @@ +function a () {} + +console.log( a() ); diff --git a/test/form/namespace-optimization/_expected/es6.js b/test/form/namespace-optimization/_expected/es6.js deleted file mode 100644 index 8bee0446d63..00000000000 --- a/test/form/namespace-optimization/_expected/es6.js +++ /dev/null @@ -1,3 +0,0 @@ -function a () {} - -a(); diff --git a/test/form/namespace-optimization/_expected/iife.js b/test/form/namespace-optimization/_expected/iife.js index 206c2374a02..64673c93d43 100644 --- a/test/form/namespace-optimization/_expected/iife.js +++ b/test/form/namespace-optimization/_expected/iife.js @@ -3,6 +3,6 @@ function a () {} - a(); + console.log( a() ); }()); diff --git a/test/form/namespace-optimization/_expected/umd.js b/test/form/namespace-optimization/_expected/umd.js index 67adf520cd2..bf379efba2c 100644 --- a/test/form/namespace-optimization/_expected/umd.js +++ b/test/form/namespace-optimization/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function a () {} - a(); + console.log( a() ); -})); \ No newline at end of file +}))); diff --git a/test/form/namespace-optimization/main.js b/test/form/namespace-optimization/main.js index e9022440ed2..6b955f7701b 100644 --- a/test/form/namespace-optimization/main.js +++ b/test/form/namespace-optimization/main.js @@ -1,3 +1,3 @@ import * as foo from './foo'; -foo.bar.quux.a(); +console.log( foo.bar.quux.a() ); diff --git a/test/form/namespaced-default-exports/_expected/es6.js b/test/form/namespaced-default-exports/_expected/es.js similarity index 100% rename from test/form/namespaced-default-exports/_expected/es6.js rename to test/form/namespaced-default-exports/_expected/es.js diff --git a/test/form/namespaced-default-exports/_expected/umd.js b/test/form/namespaced-default-exports/_expected/umd.js index b06132bb3c0..9bc50962d4d 100644 --- a/test/form/namespaced-default-exports/_expected/umd.js +++ b/test/form/namespaced-default-exports/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.foo = global.foo || {}, global.foo.bar = global.foo.bar || {}, global.foo.bar.baz = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/namespaced-named-exports/_expected/amd.js b/test/form/namespaced-named-exports/_expected/amd.js index 21429fd0701..cec0f513af2 100644 --- a/test/form/namespaced-named-exports/_expected/amd.js +++ b/test/form/namespaced-named-exports/_expected/amd.js @@ -4,4 +4,6 @@ define(['exports'], function (exports) { 'use strict'; exports.answer = answer; -}); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/namespaced-named-exports/_expected/cjs.js b/test/form/namespaced-named-exports/_expected/cjs.js index 4b8935febd4..f58e06dbe20 100644 --- a/test/form/namespaced-named-exports/_expected/cjs.js +++ b/test/form/namespaced-named-exports/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var answer = 42; -exports.answer = answer; \ No newline at end of file +exports.answer = answer; diff --git a/test/form/namespaced-named-exports/_expected/es6.js b/test/form/namespaced-named-exports/_expected/es.js similarity index 100% rename from test/form/namespaced-named-exports/_expected/es6.js rename to test/form/namespaced-named-exports/_expected/es.js diff --git a/test/form/namespaced-named-exports/_expected/umd.js b/test/form/namespaced-named-exports/_expected/umd.js index 9a0f47d8ddd..474db1fa63b 100644 --- a/test/form/namespaced-named-exports/_expected/umd.js +++ b/test/form/namespaced-named-exports/_expected/umd.js @@ -2,10 +2,12 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (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; exports.answer = answer; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/no-imports-or-exports/_expected/es6.js b/test/form/no-imports-or-exports/_expected/es.js similarity index 100% rename from test/form/no-imports-or-exports/_expected/es6.js rename to test/form/no-imports-or-exports/_expected/es.js diff --git a/test/form/no-imports-or-exports/_expected/umd.js b/test/form/no-imports-or-exports/_expected/umd.js index 5c8c7d38eb0..2a478bf69b3 100644 --- a/test/form/no-imports-or-exports/_expected/umd.js +++ b/test/form/no-imports-or-exports/_expected/umd.js @@ -2,8 +2,8 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; console.log( 'this is it' ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/no-treeshake/_expected/amd.js b/test/form/no-treeshake/_expected/amd.js index 7bbe64b6eec..eb4f6cac9fe 100644 --- a/test/form/no-treeshake/_expected/amd.js +++ b/test/form/no-treeshake/_expected/amd.js @@ -22,4 +22,6 @@ define(['exports', 'external'], function (exports, external) { 'use strict'; exports.getPrototypeOf = getPrototypeOf; exports.strange = quux; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/no-treeshake/_expected/cjs.js b/test/form/no-treeshake/_expected/cjs.js index c188f061991..c65e7006065 100644 --- a/test/form/no-treeshake/_expected/cjs.js +++ b/test/form/no-treeshake/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + var external = require('external'); var foo = 'unused'; diff --git a/test/form/no-treeshake/_expected/es6.js b/test/form/no-treeshake/_expected/es.js similarity index 84% rename from test/form/no-treeshake/_expected/es6.js rename to test/form/no-treeshake/_expected/es.js index 54f2add3899..ddcec9b9c13 100644 --- a/test/form/no-treeshake/_expected/es6.js +++ b/test/form/no-treeshake/_expected/es.js @@ -1,3 +1,4 @@ +import { value } from 'external'; import * as external from 'external'; var foo = 'unused'; @@ -11,7 +12,7 @@ function bar () { } function baz () { - return 13 + external.value; + return 13 + value; } var create = Object.create; diff --git a/test/form/no-treeshake/_expected/umd.js b/test/form/no-treeshake/_expected/umd.js index 2136453f20a..cb1b283fe9f 100644 --- a/test/form/no-treeshake/_expected/umd.js +++ b/test/form/no-treeshake/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('external')) : typeof define === 'function' && define.amd ? define(['exports', 'external'], factory) : (factory((global.stirred = global.stirred || {}),global.external)); -}(this, function (exports,external) { 'use strict'; +}(this, (function (exports,external) { 'use strict'; var foo = 'unused'; @@ -26,4 +26,6 @@ exports.getPrototypeOf = getPrototypeOf; exports.strange = quux; -})); + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/non-empty-block-statement/_config.js b/test/form/non-empty-block-statement/_config.js new file mode 100644 index 00000000000..92803d709a4 --- /dev/null +++ b/test/form/non-empty-block-statement/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'do not remove non an empty block statement' +}; diff --git a/test/form/non-empty-block-statement/_expected/amd.js b/test/form/non-empty-block-statement/_expected/amd.js new file mode 100644 index 00000000000..aaad1ffce51 --- /dev/null +++ b/test/form/non-empty-block-statement/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + console.log( 1 ); + { + var tmp = 10; + } + console.log( tmp ); + +}); diff --git a/test/form/non-empty-block-statement/_expected/cjs.js b/test/form/non-empty-block-statement/_expected/cjs.js new file mode 100644 index 00000000000..ef9e375102a --- /dev/null +++ b/test/form/non-empty-block-statement/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +console.log( 1 ); +{ + var tmp = 10; +} +console.log( tmp ); diff --git a/test/form/non-empty-block-statement/_expected/es.js b/test/form/non-empty-block-statement/_expected/es.js new file mode 100644 index 00000000000..9f19ab61b3a --- /dev/null +++ b/test/form/non-empty-block-statement/_expected/es.js @@ -0,0 +1,5 @@ +console.log( 1 ); +{ + var tmp = 10; +} +console.log( tmp ); diff --git a/test/form/non-empty-block-statement/_expected/iife.js b/test/form/non-empty-block-statement/_expected/iife.js new file mode 100644 index 00000000000..611fa6e610d --- /dev/null +++ b/test/form/non-empty-block-statement/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + console.log( 1 ); + { + var tmp = 10; + } + console.log( tmp ); + +}()); diff --git a/test/form/non-empty-block-statement/_expected/umd.js b/test/form/non-empty-block-statement/_expected/umd.js new file mode 100644 index 00000000000..9015af252b1 --- /dev/null +++ b/test/form/non-empty-block-statement/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + console.log( 1 ); + { + var tmp = 10; + } + console.log( tmp ); + +}))); diff --git a/test/form/non-empty-block-statement/main.js b/test/form/non-empty-block-statement/main.js new file mode 100644 index 00000000000..9f19ab61b3a --- /dev/null +++ b/test/form/non-empty-block-statement/main.js @@ -0,0 +1,5 @@ +console.log( 1 ); +{ + var tmp = 10; +} +console.log( tmp ); diff --git a/test/form/object-destructuring-default-values/_expected/es6.js b/test/form/object-destructuring-default-values/_expected/es.js similarity index 100% rename from test/form/object-destructuring-default-values/_expected/es6.js rename to test/form/object-destructuring-default-values/_expected/es.js diff --git a/test/form/object-destructuring-default-values/_expected/umd.js b/test/form/object-destructuring-default-values/_expected/umd.js index a3e661b2bb5..3a1aeb7e9f7 100644 --- a/test/form/object-destructuring-default-values/_expected/umd.js +++ b/test/form/object-destructuring-default-values/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; const a = 1; const b = 2; @@ -10,4 +10,4 @@ const [ d = b ] = []; console.log(c, d); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/paths-function/_config.js b/test/form/paths-function/_config.js new file mode 100644 index 00000000000..2d1f0552ee7 --- /dev/null +++ b/test/form/paths-function/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'external paths (#754)', + options: { + paths: id => `https://unpkg.com/${id}` + } +}; diff --git a/test/form/paths-function/_expected/amd.js b/test/form/paths-function/_expected/amd.js new file mode 100644 index 00000000000..0893293b0f7 --- /dev/null +++ b/test/form/paths-function/_expected/amd.js @@ -0,0 +1,7 @@ +define(['https://unpkg.com/foo'], function (foo) { 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}); diff --git a/test/form/paths-function/_expected/cjs.js b/test/form/paths-function/_expected/cjs.js new file mode 100644 index 00000000000..4bb08047e68 --- /dev/null +++ b/test/form/paths-function/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var foo = _interopDefault(require('https://unpkg.com/foo')); + +assert.equal( foo, 42 ); diff --git a/test/form/paths-function/_expected/es.js b/test/form/paths-function/_expected/es.js new file mode 100644 index 00000000000..74bfea3791e --- /dev/null +++ b/test/form/paths-function/_expected/es.js @@ -0,0 +1,3 @@ +import foo from 'https://unpkg.com/foo'; + +assert.equal( foo, 42 ); diff --git a/test/form/paths-function/_expected/iife.js b/test/form/paths-function/_expected/iife.js new file mode 100644 index 00000000000..28acdd19868 --- /dev/null +++ b/test/form/paths-function/_expected/iife.js @@ -0,0 +1,8 @@ +(function (foo) { + 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}(foo)); \ No newline at end of file diff --git a/test/form/paths-function/_expected/umd.js b/test/form/paths-function/_expected/umd.js new file mode 100644 index 00000000000..e86e89275d6 --- /dev/null +++ b/test/form/paths-function/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('https://unpkg.com/foo')) : + typeof define === 'function' && define.amd ? define(['https://unpkg.com/foo'], factory) : + (factory(global.foo)); +}(this, (function (foo) { 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}))); diff --git a/test/form/paths-function/main.js b/test/form/paths-function/main.js new file mode 100644 index 00000000000..2b26e36162a --- /dev/null +++ b/test/form/paths-function/main.js @@ -0,0 +1,3 @@ +import foo from 'foo'; + +assert.equal( foo, 42 ); diff --git a/test/form/paths-relative/_config.js b/test/form/paths-relative/_config.js new file mode 100644 index 00000000000..2895b2144b4 --- /dev/null +++ b/test/form/paths-relative/_config.js @@ -0,0 +1,13 @@ +const { resolve } = require( 'path' ); + +const resolved = resolve( __dirname, 'foo.js' ); + +module.exports = { + description: 'external paths (#754)', + options: { + external: [ resolved ], + paths: { + [ resolved ]: '../foo' + } + } +}; diff --git a/test/form/paths-relative/_expected/amd.js b/test/form/paths-relative/_expected/amd.js new file mode 100644 index 00000000000..a13383cf6aa --- /dev/null +++ b/test/form/paths-relative/_expected/amd.js @@ -0,0 +1,7 @@ +define(['../foo'], function (foo) { 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}); diff --git a/test/form/paths-relative/_expected/cjs.js b/test/form/paths-relative/_expected/cjs.js new file mode 100644 index 00000000000..f80ea9b1bb9 --- /dev/null +++ b/test/form/paths-relative/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var foo = _interopDefault(require('../foo')); + +assert.equal( foo, 42 ); diff --git a/test/form/paths-relative/_expected/es.js b/test/form/paths-relative/_expected/es.js new file mode 100644 index 00000000000..2462c870b68 --- /dev/null +++ b/test/form/paths-relative/_expected/es.js @@ -0,0 +1,3 @@ +import foo from '../foo'; + +assert.equal( foo, 42 ); diff --git a/test/form/paths-relative/_expected/iife.js b/test/form/paths-relative/_expected/iife.js new file mode 100644 index 00000000000..28acdd19868 --- /dev/null +++ b/test/form/paths-relative/_expected/iife.js @@ -0,0 +1,8 @@ +(function (foo) { + 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}(foo)); \ No newline at end of file diff --git a/test/form/paths-relative/_expected/umd.js b/test/form/paths-relative/_expected/umd.js new file mode 100644 index 00000000000..02bcdaf1bc4 --- /dev/null +++ b/test/form/paths-relative/_expected/umd.js @@ -0,0 +1,11 @@ +(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'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}))); diff --git a/test/form/paths-relative/main.js b/test/form/paths-relative/main.js new file mode 100644 index 00000000000..c01e9a1475c --- /dev/null +++ b/test/form/paths-relative/main.js @@ -0,0 +1,3 @@ +import foo from './foo.js'; + +assert.equal( foo, 42 ); diff --git a/test/form/paths/_config.js b/test/form/paths/_config.js new file mode 100644 index 00000000000..1d6ed0354db --- /dev/null +++ b/test/form/paths/_config.js @@ -0,0 +1,8 @@ +module.exports = { + description: 'external paths (#754)', + options: { + paths: { + foo: 'https://unpkg.com/foo' + } + } +}; diff --git a/test/form/paths/_expected/amd.js b/test/form/paths/_expected/amd.js new file mode 100644 index 00000000000..0893293b0f7 --- /dev/null +++ b/test/form/paths/_expected/amd.js @@ -0,0 +1,7 @@ +define(['https://unpkg.com/foo'], function (foo) { 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}); diff --git a/test/form/paths/_expected/cjs.js b/test/form/paths/_expected/cjs.js new file mode 100644 index 00000000000..4bb08047e68 --- /dev/null +++ b/test/form/paths/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var foo = _interopDefault(require('https://unpkg.com/foo')); + +assert.equal( foo, 42 ); diff --git a/test/form/paths/_expected/es.js b/test/form/paths/_expected/es.js new file mode 100644 index 00000000000..74bfea3791e --- /dev/null +++ b/test/form/paths/_expected/es.js @@ -0,0 +1,3 @@ +import foo from 'https://unpkg.com/foo'; + +assert.equal( foo, 42 ); diff --git a/test/form/paths/_expected/iife.js b/test/form/paths/_expected/iife.js new file mode 100644 index 00000000000..28acdd19868 --- /dev/null +++ b/test/form/paths/_expected/iife.js @@ -0,0 +1,8 @@ +(function (foo) { + 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}(foo)); \ No newline at end of file diff --git a/test/form/paths/_expected/umd.js b/test/form/paths/_expected/umd.js new file mode 100644 index 00000000000..e86e89275d6 --- /dev/null +++ b/test/form/paths/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('https://unpkg.com/foo')) : + typeof define === 'function' && define.amd ? define(['https://unpkg.com/foo'], factory) : + (factory(global.foo)); +}(this, (function (foo) { 'use strict'; + + foo = 'default' in foo ? foo['default'] : foo; + + assert.equal( foo, 42 ); + +}))); diff --git a/test/form/paths/main.js b/test/form/paths/main.js new file mode 100644 index 00000000000..2b26e36162a --- /dev/null +++ b/test/form/paths/main.js @@ -0,0 +1,3 @@ +import foo from 'foo'; + +assert.equal( foo, 42 ); diff --git a/test/form/prefer-const/_expected/es6.js b/test/form/prefer-const/_expected/es.js similarity index 100% rename from test/form/prefer-const/_expected/es6.js rename to test/form/prefer-const/_expected/es.js diff --git a/test/form/prefer-const/_expected/umd.js b/test/form/prefer-const/_expected/umd.js index 0c548783f68..0ec9750d8bc 100644 --- a/test/form/prefer-const/_expected/umd.js +++ b/test/form/prefer-const/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('external'), require('other'), require('another')) : typeof define === 'function' && define.amd ? define(['external', 'other', 'another'], factory) : (global.myBundle = factory(global.external,global.other,global.another)); -}(this, function (external,other,another) { 'use strict'; +}(this, (function (external,other,another) { 'use strict'; const a = 1; const b = 2; @@ -19,4 +19,4 @@ return main; -})); +}))); diff --git a/test/form/preserve-debugger/_expected/es6.js b/test/form/preserve-debugger/_expected/es.js similarity index 100% rename from test/form/preserve-debugger/_expected/es6.js rename to test/form/preserve-debugger/_expected/es.js diff --git a/test/form/preserve-debugger/_expected/umd.js b/test/form/preserve-debugger/_expected/umd.js index dd19c2daf70..a6ca6352643 100644 --- a/test/form/preserve-debugger/_expected/umd.js +++ b/test/form/preserve-debugger/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; before(); debugger; after(); -})); +}))); diff --git a/test/form/preserves-comments-after-imports/_expected/amd.js b/test/form/preserves-comments-after-imports/_expected/amd.js index 82a0a52fe77..8271ac978d0 100644 --- a/test/form/preserves-comments-after-imports/_expected/amd.js +++ b/test/form/preserves-comments-after-imports/_expected/amd.js @@ -8,4 +8,6 @@ define(['exports'], function (exports) { 'use strict'; exports.obj = obj; + Object.defineProperty(exports, '__esModule', { value: true }); + }); diff --git a/test/form/preserves-comments-after-imports/_expected/cjs.js b/test/form/preserves-comments-after-imports/_expected/cjs.js index 8b15cd1f241..723b1cb3ec0 100644 --- a/test/form/preserves-comments-after-imports/_expected/cjs.js +++ b/test/form/preserves-comments-after-imports/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + /** A comment for a number */ var number = 5; diff --git a/test/form/preserves-comments-after-imports/_expected/es6.js b/test/form/preserves-comments-after-imports/_expected/es.js similarity index 100% rename from test/form/preserves-comments-after-imports/_expected/es6.js rename to test/form/preserves-comments-after-imports/_expected/es.js diff --git a/test/form/preserves-comments-after-imports/_expected/umd.js b/test/form/preserves-comments-after-imports/_expected/umd.js index 13a54bf6ee7..b1cc6a56a2f 100644 --- a/test/form/preserves-comments-after-imports/_expected/umd.js +++ b/test/form/preserves-comments-after-imports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.myBundle = global.myBundle || {}))); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; /** A comment for a number */ var number = 5; @@ -12,4 +12,6 @@ exports.obj = obj; -})); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/relative-external-with-global/_config.js b/test/form/relative-external-with-global/_config.js new file mode 100644 index 00000000000..677bef19f00 --- /dev/null +++ b/test/form/relative-external-with-global/_config.js @@ -0,0 +1,13 @@ +const { resolve } = require( 'path' ); + +const throttle = resolve( __dirname, 'lib/throttle.js' ); + +module.exports = { + description: 'applies globals to externalised relative imports', + options: { + external: [ throttle ], + globals: { + [ throttle ]: 'Lib.throttle' + } + } +}; diff --git a/test/form/relative-external-with-global/_expected/amd.js b/test/form/relative-external-with-global/_expected/amd.js new file mode 100644 index 00000000000..538e97a5e7c --- /dev/null +++ b/test/form/relative-external-with-global/_expected/amd.js @@ -0,0 +1,11 @@ +define(['./lib/throttle.js'], function (throttle) { 'use strict'; + + throttle = 'default' in throttle ? throttle['default'] : throttle; + + const fn = throttle( () => { + console.log( '.' ); + }, 500 ); + + window.addEventListener( 'mousemove', throttle ); + +}); \ No newline at end of file diff --git a/test/form/relative-external-with-global/_expected/cjs.js b/test/form/relative-external-with-global/_expected/cjs.js new file mode 100644 index 00000000000..1b74d5687f4 --- /dev/null +++ b/test/form/relative-external-with-global/_expected/cjs.js @@ -0,0 +1,11 @@ +'use strict'; + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var throttle = _interopDefault(require('./lib/throttle.js')); + +const fn = throttle( () => { + console.log( '.' ); +}, 500 ); + +window.addEventListener( 'mousemove', throttle ); \ No newline at end of file diff --git a/test/form/relative-external-with-global/_expected/es.js b/test/form/relative-external-with-global/_expected/es.js new file mode 100644 index 00000000000..fe8f7cf3d40 --- /dev/null +++ b/test/form/relative-external-with-global/_expected/es.js @@ -0,0 +1,7 @@ +import throttle from './lib/throttle.js'; + +const fn = throttle( () => { + console.log( '.' ); +}, 500 ); + +window.addEventListener( 'mousemove', throttle ); \ No newline at end of file diff --git a/test/form/relative-external-with-global/_expected/iife.js b/test/form/relative-external-with-global/_expected/iife.js new file mode 100644 index 00000000000..a0efcee63f6 --- /dev/null +++ b/test/form/relative-external-with-global/_expected/iife.js @@ -0,0 +1,12 @@ +(function (throttle) { + 'use strict'; + + throttle = 'default' in throttle ? throttle['default'] : throttle; + + const fn = throttle( () => { + console.log( '.' ); + }, 500 ); + + window.addEventListener( 'mousemove', throttle ); + +}(Lib.throttle)); diff --git a/test/form/relative-external-with-global/_expected/umd.js b/test/form/relative-external-with-global/_expected/umd.js new file mode 100644 index 00000000000..5ab1989847a --- /dev/null +++ b/test/form/relative-external-with-global/_expected/umd.js @@ -0,0 +1,15 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('./lib/throttle.js')) : + typeof define === 'function' && define.amd ? define(['./lib/throttle.js'], factory) : + (factory(global.Lib.throttle)); +}(this, (function (throttle) { 'use strict'; + + throttle = 'default' in throttle ? throttle['default'] : throttle; + + const fn = throttle( () => { + console.log( '.' ); + }, 500 ); + + window.addEventListener( 'mousemove', throttle ); + +}))); diff --git a/test/form/relative-external-with-global/main.js b/test/form/relative-external-with-global/main.js new file mode 100644 index 00000000000..750ac953c06 --- /dev/null +++ b/test/form/relative-external-with-global/main.js @@ -0,0 +1,7 @@ +import throttle from './lib/throttle.js'; + +const fn = throttle( () => { + console.log( '.' ); +}, 500 ); + +window.addEventListener( 'mousemove', throttle ); diff --git a/test/form/removes-existing-sourcemap-comments/_expected/amd.js b/test/form/removes-existing-sourcemap-comments/_expected/amd.js index e6143445961..b89e3998084 100644 --- a/test/form/removes-existing-sourcemap-comments/_expected/amd.js +++ b/test/form/removes-existing-sourcemap-comments/_expected/amd.js @@ -1,8 +1,8 @@ define(function () { 'use strict'; - function foo () { + var foo = function () { return 42; - } + }; console.log( foo() ); diff --git a/test/form/removes-existing-sourcemap-comments/_expected/cjs.js b/test/form/removes-existing-sourcemap-comments/_expected/cjs.js index d7a8df25cf3..1152d76ffde 100644 --- a/test/form/removes-existing-sourcemap-comments/_expected/cjs.js +++ b/test/form/removes-existing-sourcemap-comments/_expected/cjs.js @@ -1,7 +1,7 @@ 'use strict'; -function foo () { +var foo = function () { return 42; -} +}; console.log( foo() ); diff --git a/test/form/removes-existing-sourcemap-comments/_expected/es6.js b/test/form/removes-existing-sourcemap-comments/_expected/es.js similarity index 56% rename from test/form/removes-existing-sourcemap-comments/_expected/es6.js rename to test/form/removes-existing-sourcemap-comments/_expected/es.js index c4588288805..0ef10008f1f 100644 --- a/test/form/removes-existing-sourcemap-comments/_expected/es6.js +++ b/test/form/removes-existing-sourcemap-comments/_expected/es.js @@ -1,5 +1,5 @@ -function foo () { +var foo = function () { return 42; -} +}; console.log( foo() ); diff --git a/test/form/removes-existing-sourcemap-comments/_expected/iife.js b/test/form/removes-existing-sourcemap-comments/_expected/iife.js index 5867d0fec7c..cac12fb71ed 100644 --- a/test/form/removes-existing-sourcemap-comments/_expected/iife.js +++ b/test/form/removes-existing-sourcemap-comments/_expected/iife.js @@ -1,9 +1,9 @@ (function () { 'use strict'; - function foo () { + var foo = function () { return 42; - } + }; console.log( foo() ); diff --git a/test/form/removes-existing-sourcemap-comments/_expected/umd.js b/test/form/removes-existing-sourcemap-comments/_expected/umd.js index ef0186e8f56..9a6706d88aa 100644 --- a/test/form/removes-existing-sourcemap-comments/_expected/umd.js +++ b/test/form/removes-existing-sourcemap-comments/_expected/umd.js @@ -2,12 +2,12 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; - function foo () { + var foo = function () { return 42; - } + }; console.log( foo() ); -})); \ No newline at end of file +}))); diff --git a/test/form/self-calling-function-with-effects/_config.js b/test/form/self-calling-function-with-effects/_config.js new file mode 100644 index 00000000000..d20f89b9526 --- /dev/null +++ b/test/form/self-calling-function-with-effects/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'discards a self-calling function with side-effects' +}; diff --git a/test/form/self-calling-function-with-effects/_expected/amd.js b/test/form/self-calling-function-with-effects/_expected/amd.js new file mode 100644 index 00000000000..ad714bdbe72 --- /dev/null +++ b/test/form/self-calling-function-with-effects/_expected/amd.js @@ -0,0 +1,20 @@ +define(function () { 'use strict'; + + function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); + } + + function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); + } + + function baz ( x ) { + bar( x - 1 ); + } + + foo( 10 ); + bar( 10 ); + +}); \ No newline at end of file diff --git a/test/form/self-calling-function-with-effects/_expected/cjs.js b/test/form/self-calling-function-with-effects/_expected/cjs.js new file mode 100644 index 00000000000..83a7a207b11 --- /dev/null +++ b/test/form/self-calling-function-with-effects/_expected/cjs.js @@ -0,0 +1,18 @@ +'use strict'; + +function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); +} + +function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); +} + +function baz ( x ) { + bar( x - 1 ); +} + +foo( 10 ); +bar( 10 ); \ No newline at end of file diff --git a/test/form/self-calling-function-with-effects/_expected/es.js b/test/form/self-calling-function-with-effects/_expected/es.js new file mode 100644 index 00000000000..8e997b2d54c --- /dev/null +++ b/test/form/self-calling-function-with-effects/_expected/es.js @@ -0,0 +1,16 @@ +function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); +} + +function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); +} + +function baz ( x ) { + bar( x - 1 ); +} + +foo( 10 ); +bar( 10 ); \ No newline at end of file diff --git a/test/form/self-calling-function-with-effects/_expected/iife.js b/test/form/self-calling-function-with-effects/_expected/iife.js new file mode 100644 index 00000000000..bb848ad1ecb --- /dev/null +++ b/test/form/self-calling-function-with-effects/_expected/iife.js @@ -0,0 +1,21 @@ +(function () { + 'use strict'; + + function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); + } + + function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); + } + + function baz ( x ) { + bar( x - 1 ); + } + + foo( 10 ); + bar( 10 ); + +}()); \ No newline at end of file diff --git a/test/form/self-calling-function-with-effects/_expected/umd.js b/test/form/self-calling-function-with-effects/_expected/umd.js new file mode 100644 index 00000000000..a9fd5b2a2d4 --- /dev/null +++ b/test/form/self-calling-function-with-effects/_expected/umd.js @@ -0,0 +1,24 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); + } + + function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); + } + + function baz ( x ) { + bar( x - 1 ); + } + + foo( 10 ); + bar( 10 ); + +}))); \ No newline at end of file diff --git a/test/form/self-calling-function-with-effects/main.js b/test/form/self-calling-function-with-effects/main.js new file mode 100644 index 00000000000..7ec54d93035 --- /dev/null +++ b/test/form/self-calling-function-with-effects/main.js @@ -0,0 +1,16 @@ +function foo ( x ) { + effect( x ); + if ( x > 0 ) foo( x - 1 ); +} + +function bar ( x ) { + effect( x ); + if ( x > 0 ) baz( x ); +} + +function baz ( x ) { + bar( x - 1 ); +} + +foo( 10 ); +bar( 10 ); diff --git a/test/form/self-calling-function/_config.js b/test/form/self-calling-function/_config.js new file mode 100644 index 00000000000..3acb040a873 --- /dev/null +++ b/test/form/self-calling-function/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'discards a self-calling function without side-effects' +}; diff --git a/test/form/self-calling-function/_expected/amd.js b/test/form/self-calling-function/_expected/amd.js new file mode 100644 index 00000000000..ec759b11cba --- /dev/null +++ b/test/form/self-calling-function/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + + +}); \ No newline at end of file diff --git a/test/form/self-calling-function/_expected/cjs.js b/test/form/self-calling-function/_expected/cjs.js new file mode 100644 index 00000000000..eb109abbed0 --- /dev/null +++ b/test/form/self-calling-function/_expected/cjs.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/test/form/self-calling-function/_expected/es.js b/test/form/self-calling-function/_expected/es.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/form/self-calling-function/_expected/iife.js b/test/form/self-calling-function/_expected/iife.js new file mode 100644 index 00000000000..f3d1016ed3e --- /dev/null +++ b/test/form/self-calling-function/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +}()); \ No newline at end of file diff --git a/test/form/self-calling-function/_expected/umd.js b/test/form/self-calling-function/_expected/umd.js new file mode 100644 index 00000000000..d561e69c33b --- /dev/null +++ b/test/form/self-calling-function/_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'; + + + +}))); \ No newline at end of file diff --git a/test/form/self-calling-function/main.js b/test/form/self-calling-function/main.js new file mode 100644 index 00000000000..76ff6335142 --- /dev/null +++ b/test/form/self-calling-function/main.js @@ -0,0 +1,14 @@ +function foo ( x ) { + if ( x > 0 ) foo( x - 1 ); +} + +function bar ( x ) { + if ( x > 0 ) baz( x ); +} + +function baz ( x ) { + bar( x - 1 ); +} + +foo( 10 ); +bar( 10 ); diff --git a/test/form/self-contained-bundle/_expected/es6.js b/test/form/self-contained-bundle/_expected/es.js similarity index 100% rename from test/form/self-contained-bundle/_expected/es6.js rename to test/form/self-contained-bundle/_expected/es.js diff --git a/test/form/self-contained-bundle/_expected/umd.js b/test/form/self-contained-bundle/_expected/umd.js index f82853783e3..831b45c4bd3 100644 --- a/test/form/self-contained-bundle/_expected/umd.js +++ b/test/form/self-contained-bundle/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( bar() ); @@ -19,4 +19,4 @@ foo(); console.log( 3 ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/shorthand-properties/_expected/es6.js b/test/form/shorthand-properties/_expected/es.js similarity index 100% rename from test/form/shorthand-properties/_expected/es6.js rename to test/form/shorthand-properties/_expected/es.js diff --git a/test/form/shorthand-properties/_expected/umd.js b/test/form/shorthand-properties/_expected/umd.js index 1a19210bec8..9d64f6ad8c9 100644 --- a/test/form/shorthand-properties/_expected/umd.js +++ b/test/form/shorthand-properties/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function x () { return 'foo'; @@ -26,4 +26,4 @@ assert.equal( bar.x(), 'bar' ); assert.equal( baz.x(), 'baz' ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-b/_expected/es6.js b/test/form/side-effect-b/_expected/es.js similarity index 100% rename from test/form/side-effect-b/_expected/es6.js rename to test/form/side-effect-b/_expected/es.js diff --git a/test/form/side-effect-b/_expected/umd.js b/test/form/side-effect-b/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-b/_expected/umd.js +++ b/test/form/side-effect-b/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-c/_expected/es6.js b/test/form/side-effect-c/_expected/es.js similarity index 100% rename from test/form/side-effect-c/_expected/es6.js rename to test/form/side-effect-c/_expected/es.js diff --git a/test/form/side-effect-c/_expected/umd.js b/test/form/side-effect-c/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-c/_expected/umd.js +++ b/test/form/side-effect-c/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-d/_expected/es6.js b/test/form/side-effect-d/_expected/es.js similarity index 100% rename from test/form/side-effect-d/_expected/es6.js rename to test/form/side-effect-d/_expected/es.js diff --git a/test/form/side-effect-d/_expected/umd.js b/test/form/side-effect-d/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-d/_expected/umd.js +++ b/test/form/side-effect-d/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-e/_expected/es6.js b/test/form/side-effect-e/_expected/es.js similarity index 100% rename from test/form/side-effect-e/_expected/es6.js rename to test/form/side-effect-e/_expected/es.js diff --git a/test/form/side-effect-e/_expected/umd.js b/test/form/side-effect-e/_expected/umd.js index ef3393d96e2..4a3316f0a6b 100644 --- a/test/form/side-effect-e/_expected/umd.js +++ b/test/form/side-effect-e/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { var Object = { @@ -21,4 +21,4 @@ return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-f/_expected/es6.js b/test/form/side-effect-f/_expected/es.js similarity index 100% rename from test/form/side-effect-f/_expected/es6.js rename to test/form/side-effect-f/_expected/es.js diff --git a/test/form/side-effect-f/_expected/umd.js b/test/form/side-effect-f/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-f/_expected/umd.js +++ b/test/form/side-effect-f/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-g/_expected/es6.js b/test/form/side-effect-g/_expected/es.js similarity index 100% rename from test/form/side-effect-g/_expected/es6.js rename to test/form/side-effect-g/_expected/es.js diff --git a/test/form/side-effect-g/_expected/umd.js b/test/form/side-effect-g/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-g/_expected/umd.js +++ b/test/form/side-effect-g/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-h/_expected/es6.js b/test/form/side-effect-h/_expected/es.js similarity index 100% rename from test/form/side-effect-h/_expected/es6.js rename to test/form/side-effect-h/_expected/es.js diff --git a/test/form/side-effect-h/_expected/umd.js b/test/form/side-effect-h/_expected/umd.js index 16d2890d0c5..2194031a608 100644 --- a/test/form/side-effect-h/_expected/umd.js +++ b/test/form/side-effect-h/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var main = 42; return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-i/_expected/es6.js b/test/form/side-effect-i/_expected/es.js similarity index 100% rename from test/form/side-effect-i/_expected/es6.js rename to test/form/side-effect-i/_expected/es.js diff --git a/test/form/side-effect-i/_expected/umd.js b/test/form/side-effect-i/_expected/umd.js index b090f9af525..87d4d59dd29 100644 --- a/test/form/side-effect-i/_expected/umd.js +++ b/test/form/side-effect-i/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; if ( !ok ) { throw new Error( 'this will be included' ); @@ -12,4 +12,4 @@ return main; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-j/_expected/es6.js b/test/form/side-effect-j/_expected/es.js similarity index 100% rename from test/form/side-effect-j/_expected/es6.js rename to test/form/side-effect-j/_expected/es.js diff --git a/test/form/side-effect-j/_expected/umd.js b/test/form/side-effect-j/_expected/umd.js index 2da816b6ea8..1d7d72737c8 100644 --- a/test/form/side-effect-j/_expected/umd.js +++ b/test/form/side-effect-j/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var augment; augment = x => x.augmented = true; @@ -12,4 +12,4 @@ return x; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-k/_expected/amd.js b/test/form/side-effect-k/_expected/amd.js index e903a01ea37..abfcb9824c3 100644 --- a/test/form/side-effect-k/_expected/amd.js +++ b/test/form/side-effect-k/_expected/amd.js @@ -25,4 +25,4 @@ define(function () { 'use strict'; return x; -}); \ No newline at end of file +}); diff --git a/test/form/side-effect-k/_expected/cjs.js b/test/form/side-effect-k/_expected/cjs.js index 7ee74b0ee77..82190219573 100644 --- a/test/form/side-effect-k/_expected/cjs.js +++ b/test/form/side-effect-k/_expected/cjs.js @@ -23,4 +23,4 @@ function augment ( x ) { function x () {} augment( x.prototype ); -module.exports = x; \ No newline at end of file +module.exports = x; diff --git a/test/form/side-effect-k/_expected/es6.js b/test/form/side-effect-k/_expected/es.js similarity index 95% rename from test/form/side-effect-k/_expected/es6.js rename to test/form/side-effect-k/_expected/es.js index 0cbda655065..864798663d0 100644 --- a/test/form/side-effect-k/_expected/es6.js +++ b/test/form/side-effect-k/_expected/es.js @@ -21,4 +21,4 @@ function augment ( x ) { function x () {} augment( x.prototype ); -export default x; \ No newline at end of file +export default x; diff --git a/test/form/side-effect-k/_expected/iife.js b/test/form/side-effect-k/_expected/iife.js index bccee01aa97..eeb57d44a4b 100644 --- a/test/form/side-effect-k/_expected/iife.js +++ b/test/form/side-effect-k/_expected/iife.js @@ -26,4 +26,4 @@ var myBundle = (function () { return x; -}()); \ No newline at end of file +}()); diff --git a/test/form/side-effect-k/_expected/umd.js b/test/form/side-effect-k/_expected/umd.js index 5b7f3d63dde..302275aaa68 100644 --- a/test/form/side-effect-k/_expected/umd.js +++ b/test/form/side-effect-k/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.myBundle = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function augment ( x ) { var prop, source; @@ -29,4 +29,4 @@ return x; -})); \ No newline at end of file +}))); diff --git a/test/form/side-effect-l/_expected/es.js b/test/form/side-effect-l/_expected/es.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/form/side-effect-l/_expected/umd.js b/test/form/side-effect-l/_expected/umd.js index f3395b7d873..d561e69c33b 100644 --- a/test/form/side-effect-l/_expected/umd.js +++ b/test/form/side-effect-l/_expected/umd.js @@ -2,8 +2,8 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-m/_expected/amd.js b/test/form/side-effect-m/_expected/amd.js index 8c7787a690b..af4a5b52fe8 100644 --- a/test/form/side-effect-m/_expected/amd.js +++ b/test/form/side-effect-m/_expected/amd.js @@ -10,7 +10,7 @@ define(function () { 'use strict'; var foo = odd( 12 ); function even ( n ) { - alert( counter++ ) + alert( counter++ ); return n === 0 || odd( n - 1 ); } diff --git a/test/form/side-effect-m/_expected/cjs.js b/test/form/side-effect-m/_expected/cjs.js index 43eacf45998..1e7377fa74c 100644 --- a/test/form/side-effect-m/_expected/cjs.js +++ b/test/form/side-effect-m/_expected/cjs.js @@ -10,7 +10,7 @@ var counter = 0; var foo = odd( 12 ); function even ( n ) { - alert( counter++ ) + alert( counter++ ); return n === 0 || odd( n - 1 ); } diff --git a/test/form/side-effect-m/_expected/es6.js b/test/form/side-effect-m/_expected/es.js similarity index 91% rename from test/form/side-effect-m/_expected/es6.js rename to test/form/side-effect-m/_expected/es.js index 61bbbbf7730..d4df0daf1be 100644 --- a/test/form/side-effect-m/_expected/es6.js +++ b/test/form/side-effect-m/_expected/es.js @@ -8,7 +8,7 @@ var counter = 0; var foo = odd( 12 ); function even ( n ) { - alert( counter++ ) + alert( counter++ ); return n === 0 || odd( n - 1 ); } diff --git a/test/form/side-effect-m/_expected/iife.js b/test/form/side-effect-m/_expected/iife.js index d4be68e6de0..0d378a862a8 100644 --- a/test/form/side-effect-m/_expected/iife.js +++ b/test/form/side-effect-m/_expected/iife.js @@ -11,7 +11,7 @@ var foo = odd( 12 ); function even ( n ) { - alert( counter++ ) + alert( counter++ ); return n === 0 || odd( n - 1 ); } diff --git a/test/form/side-effect-m/_expected/umd.js b/test/form/side-effect-m/_expected/umd.js index 902026fa27d..38f9417a3ab 100644 --- a/test/form/side-effect-m/_expected/umd.js +++ b/test/form/side-effect-m/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function odd ( n ) { return n !== 0 && even( n - 1 ); @@ -14,7 +14,7 @@ var foo = odd( 12 ); function even ( n ) { - alert( counter++ ) + alert( counter++ ); return n === 0 || odd( n - 1 ); } @@ -22,4 +22,4 @@ console.log( counter ); -})); +}))); diff --git a/test/form/side-effect-n/_expected/es6.js b/test/form/side-effect-n/_expected/es.js similarity index 100% rename from test/form/side-effect-n/_expected/es6.js rename to test/form/side-effect-n/_expected/es.js diff --git a/test/form/side-effect-n/_expected/umd.js b/test/form/side-effect-n/_expected/umd.js index c792f48c80d..f83037e56cd 100644 --- a/test/form/side-effect-n/_expected/umd.js +++ b/test/form/side-effect-n/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'foo' ); @@ -14,4 +14,4 @@ ( Math.random() < 0.5 ? foo : bar )(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-o/_expected/es6.js b/test/form/side-effect-o/_expected/es.js similarity index 100% rename from test/form/side-effect-o/_expected/es6.js rename to test/form/side-effect-o/_expected/es.js diff --git a/test/form/side-effect-o/_expected/umd.js b/test/form/side-effect-o/_expected/umd.js index 80d69a35a3a..38b9a1d9cbd 100644 --- a/test/form/side-effect-o/_expected/umd.js +++ b/test/form/side-effect-o/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function fn () { return Math.random() < 0.5 ? foo : bar; @@ -18,4 +18,4 @@ fn()(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/side-effect-p/_config.js b/test/form/side-effect-p/_config.js new file mode 100644 index 00000000000..7a8d84b4c1e --- /dev/null +++ b/test/form/side-effect-p/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'detects mutation of globals' +}; diff --git a/test/form/side-effect-p/_expected/amd.js b/test/form/side-effect-p/_expected/amd.js new file mode 100644 index 00000000000..7a76cb7d7ff --- /dev/null +++ b/test/form/side-effect-p/_expected/amd.js @@ -0,0 +1,11 @@ +define(function () { 'use strict'; + + var bool = true; + + const hs = document.documentElement.style; + + if ( bool ) { + hs.color = "#222"; + } + +}); diff --git a/test/form/side-effect-p/_expected/cjs.js b/test/form/side-effect-p/_expected/cjs.js new file mode 100644 index 00000000000..9553e7dc160 --- /dev/null +++ b/test/form/side-effect-p/_expected/cjs.js @@ -0,0 +1,9 @@ +'use strict'; + +var bool = true; + +const hs = document.documentElement.style; + +if ( bool ) { + hs.color = "#222"; +} diff --git a/test/form/side-effect-p/_expected/es.js b/test/form/side-effect-p/_expected/es.js new file mode 100644 index 00000000000..c6eddb225a6 --- /dev/null +++ b/test/form/side-effect-p/_expected/es.js @@ -0,0 +1,7 @@ +var bool = true; + +const hs = document.documentElement.style; + +if ( bool ) { + hs.color = "#222"; +} diff --git a/test/form/side-effect-p/_expected/iife.js b/test/form/side-effect-p/_expected/iife.js new file mode 100644 index 00000000000..7ab23ea2032 --- /dev/null +++ b/test/form/side-effect-p/_expected/iife.js @@ -0,0 +1,12 @@ +(function () { + 'use strict'; + + var bool = true; + + const hs = document.documentElement.style; + + if ( bool ) { + hs.color = "#222"; + } + +}()); diff --git a/test/form/side-effect-p/_expected/umd.js b/test/form/side-effect-p/_expected/umd.js new file mode 100644 index 00000000000..57553d39b2b --- /dev/null +++ b/test/form/side-effect-p/_expected/umd.js @@ -0,0 +1,15 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var bool = true; + + const hs = document.documentElement.style; + + if ( bool ) { + hs.color = "#222"; + } + +}))); diff --git a/test/form/side-effect-p/bool.js b/test/form/side-effect-p/bool.js new file mode 100644 index 00000000000..ff3177babdd --- /dev/null +++ b/test/form/side-effect-p/bool.js @@ -0,0 +1 @@ +export default true; diff --git a/test/form/side-effect-p/main.js b/test/form/side-effect-p/main.js new file mode 100644 index 00000000000..1ee7791826c --- /dev/null +++ b/test/form/side-effect-p/main.js @@ -0,0 +1,7 @@ +import bool from './bool'; + +const hs = document.documentElement.style; + +if ( bool ) { + hs.color = "#222" +} diff --git a/test/form/side-effect-q/_config.js b/test/form/side-effect-q/_config.js new file mode 100644 index 00000000000..944a58aa309 --- /dev/null +++ b/test/form/side-effect-q/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'discards effects in conditional expressions with known test values' +}; diff --git a/test/form/side-effect-q/_expected/amd.js b/test/form/side-effect-q/_expected/amd.js new file mode 100644 index 00000000000..ec759b11cba --- /dev/null +++ b/test/form/side-effect-q/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + + +}); \ No newline at end of file diff --git a/test/form/side-effect-q/_expected/cjs.js b/test/form/side-effect-q/_expected/cjs.js new file mode 100644 index 00000000000..eb109abbed0 --- /dev/null +++ b/test/form/side-effect-q/_expected/cjs.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/test/form/side-effect-q/_expected/es.js b/test/form/side-effect-q/_expected/es.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/form/side-effect-q/_expected/iife.js b/test/form/side-effect-q/_expected/iife.js new file mode 100644 index 00000000000..f3d1016ed3e --- /dev/null +++ b/test/form/side-effect-q/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +}()); \ No newline at end of file diff --git a/test/form/side-effect-q/_expected/umd.js b/test/form/side-effect-q/_expected/umd.js new file mode 100644 index 00000000000..d561e69c33b --- /dev/null +++ b/test/form/side-effect-q/_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'; + + + +}))); \ No newline at end of file diff --git a/test/form/side-effect-q/main.js b/test/form/side-effect-q/main.js new file mode 100644 index 00000000000..2272edb8bfa --- /dev/null +++ b/test/form/side-effect-q/main.js @@ -0,0 +1,5 @@ +var x = true ? foo () : bar(); + +function foo () { + return 'should be removed, because x is unused'; +} diff --git a/test/form/side-effect-r/_config.js b/test/form/side-effect-r/_config.js new file mode 100644 index 00000000000..3a59976fa4e --- /dev/null +++ b/test/form/side-effect-r/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'discards unused function expression assigned to a variable that calls itself and a global' +}; diff --git a/test/form/side-effect-r/_expected/amd.js b/test/form/side-effect-r/_expected/amd.js new file mode 100644 index 00000000000..f9f8229aa40 --- /dev/null +++ b/test/form/side-effect-r/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + + +}); diff --git a/test/form/side-effect-r/_expected/cjs.js b/test/form/side-effect-r/_expected/cjs.js new file mode 100644 index 00000000000..eb109abbed0 --- /dev/null +++ b/test/form/side-effect-r/_expected/cjs.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/test/form/side-effect-r/_expected/es.js b/test/form/side-effect-r/_expected/es.js new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test/form/side-effect-r/_expected/es.js @@ -0,0 +1 @@ + diff --git a/test/form/side-effect-r/_expected/iife.js b/test/form/side-effect-r/_expected/iife.js new file mode 100644 index 00000000000..43ef5426880 --- /dev/null +++ b/test/form/side-effect-r/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +}()); diff --git a/test/form/side-effect-r/_expected/umd.js b/test/form/side-effect-r/_expected/umd.js new file mode 100644 index 00000000000..07ce27e42f1 --- /dev/null +++ b/test/form/side-effect-r/_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'; + + + +}))); diff --git a/test/form/side-effect-r/main.js b/test/form/side-effect-r/main.js new file mode 100644 index 00000000000..716ee31feaa --- /dev/null +++ b/test/form/side-effect-r/main.js @@ -0,0 +1,7 @@ +var foo = function foo() { + if ( whatever ) { + foo(); + } else { + bar(); + } +}; diff --git a/test/form/side-effect-s/_config.js b/test/form/side-effect-s/_config.js new file mode 100644 index 00000000000..457689e43bb --- /dev/null +++ b/test/form/side-effect-s/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'discards unused function expression assigned to a variable that calls itself and has side effects' +}; diff --git a/test/form/side-effect-s/_expected/amd.js b/test/form/side-effect-s/_expected/amd.js new file mode 100644 index 00000000000..f9f8229aa40 --- /dev/null +++ b/test/form/side-effect-s/_expected/amd.js @@ -0,0 +1,5 @@ +define(function () { 'use strict'; + + + +}); diff --git a/test/form/side-effect-s/_expected/cjs.js b/test/form/side-effect-s/_expected/cjs.js new file mode 100644 index 00000000000..eb109abbed0 --- /dev/null +++ b/test/form/side-effect-s/_expected/cjs.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/test/form/side-effect-s/_expected/es.js b/test/form/side-effect-s/_expected/es.js new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/test/form/side-effect-s/_expected/es.js @@ -0,0 +1 @@ + diff --git a/test/form/side-effect-s/_expected/iife.js b/test/form/side-effect-s/_expected/iife.js new file mode 100644 index 00000000000..43ef5426880 --- /dev/null +++ b/test/form/side-effect-s/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + + +}()); diff --git a/test/form/side-effect-s/_expected/umd.js b/test/form/side-effect-s/_expected/umd.js new file mode 100644 index 00000000000..07ce27e42f1 --- /dev/null +++ b/test/form/side-effect-s/_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'; + + + +}))); diff --git a/test/form/side-effect-s/main.js b/test/form/side-effect-s/main.js new file mode 100644 index 00000000000..3d63fdfd4af --- /dev/null +++ b/test/form/side-effect-s/main.js @@ -0,0 +1,7 @@ +var foo = function foo(param) { + if ( whatever ) { + foo(param); + } else { + param.foo = 1; + } +}; diff --git a/test/form/side-effect/_expected/es6.js b/test/form/side-effect/_expected/es.js similarity index 100% rename from test/form/side-effect/_expected/es6.js rename to test/form/side-effect/_expected/es.js diff --git a/test/form/side-effect/_expected/umd.js b/test/form/side-effect/_expected/umd.js index 79b4cc2646d..e0961e0680f 100644 --- a/test/form/side-effect/_expected/umd.js +++ b/test/form/side-effect/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var foo = 42; assert.equal( foo, 42 ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/skips-dead-branches-b/_config.js b/test/form/skips-dead-branches-b/_config.js new file mode 100644 index 00000000000..22c399cee0b --- /dev/null +++ b/test/form/skips-dead-branches-b/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (b)' +}; diff --git a/test/form/skips-dead-branches-b/_expected/amd.js b/test/form/skips-dead-branches-b/_expected/amd.js new file mode 100644 index 00000000000..c192900373e --- /dev/null +++ b/test/form/skips-dead-branches-b/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); diff --git a/test/form/skips-dead-branches-b/_expected/cjs.js b/test/form/skips-dead-branches-b/_expected/cjs.js new file mode 100644 index 00000000000..b3e974bb4e6 --- /dev/null +++ b/test/form/skips-dead-branches-b/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); diff --git a/test/form/skips-dead-branches-b/_expected/es.js b/test/form/skips-dead-branches-b/_expected/es.js new file mode 100644 index 00000000000..ec9eb20c919 --- /dev/null +++ b/test/form/skips-dead-branches-b/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); diff --git a/test/form/skips-dead-branches-b/_expected/iife.js b/test/form/skips-dead-branches-b/_expected/iife.js new file mode 100644 index 00000000000..3b894d92a46 --- /dev/null +++ b/test/form/skips-dead-branches-b/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); diff --git a/test/form/skips-dead-branches-b/_expected/umd.js b/test/form/skips-dead-branches-b/_expected/umd.js new file mode 100644 index 00000000000..b3926b0f8b0 --- /dev/null +++ b/test/form/skips-dead-branches-b/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); diff --git a/test/function/skips-dead-branches-b/main.js b/test/form/skips-dead-branches-b/main.js similarity index 100% rename from test/function/skips-dead-branches-b/main.js rename to test/form/skips-dead-branches-b/main.js diff --git a/test/form/skips-dead-branches-c/_config.js b/test/form/skips-dead-branches-c/_config.js new file mode 100644 index 00000000000..86741425441 --- /dev/null +++ b/test/form/skips-dead-branches-c/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (c)' +}; diff --git a/test/form/skips-dead-branches-c/_expected/amd.js b/test/form/skips-dead-branches-c/_expected/amd.js new file mode 100644 index 00000000000..9dc50f528f3 --- /dev/null +++ b/test/form/skips-dead-branches-c/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches-c/_expected/cjs.js b/test/form/skips-dead-branches-c/_expected/cjs.js new file mode 100644 index 00000000000..d6aa952d0e6 --- /dev/null +++ b/test/form/skips-dead-branches-c/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-c/_expected/es.js b/test/form/skips-dead-branches-c/_expected/es.js new file mode 100644 index 00000000000..f39bfec65a9 --- /dev/null +++ b/test/form/skips-dead-branches-c/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-c/_expected/iife.js b/test/form/skips-dead-branches-c/_expected/iife.js new file mode 100644 index 00000000000..8d6dcb52c0c --- /dev/null +++ b/test/form/skips-dead-branches-c/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches-c/_expected/umd.js b/test/form/skips-dead-branches-c/_expected/umd.js new file mode 100644 index 00000000000..67588d41402 --- /dev/null +++ b/test/form/skips-dead-branches-c/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); \ No newline at end of file diff --git a/test/function/skips-dead-branches-c/main.js b/test/form/skips-dead-branches-c/main.js similarity index 100% rename from test/function/skips-dead-branches-c/main.js rename to test/form/skips-dead-branches-c/main.js diff --git a/test/form/skips-dead-branches-d/_config.js b/test/form/skips-dead-branches-d/_config.js new file mode 100644 index 00000000000..97791399bf1 --- /dev/null +++ b/test/form/skips-dead-branches-d/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (d)' +}; diff --git a/test/form/skips-dead-branches-d/_expected/amd.js b/test/form/skips-dead-branches-d/_expected/amd.js new file mode 100644 index 00000000000..9dc50f528f3 --- /dev/null +++ b/test/form/skips-dead-branches-d/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches-d/_expected/cjs.js b/test/form/skips-dead-branches-d/_expected/cjs.js new file mode 100644 index 00000000000..d6aa952d0e6 --- /dev/null +++ b/test/form/skips-dead-branches-d/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-d/_expected/es.js b/test/form/skips-dead-branches-d/_expected/es.js new file mode 100644 index 00000000000..f39bfec65a9 --- /dev/null +++ b/test/form/skips-dead-branches-d/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-d/_expected/iife.js b/test/form/skips-dead-branches-d/_expected/iife.js new file mode 100644 index 00000000000..8d6dcb52c0c --- /dev/null +++ b/test/form/skips-dead-branches-d/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches-d/_expected/umd.js b/test/form/skips-dead-branches-d/_expected/umd.js new file mode 100644 index 00000000000..67588d41402 --- /dev/null +++ b/test/form/skips-dead-branches-d/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); \ No newline at end of file diff --git a/test/function/skips-dead-branches-d/main.js b/test/form/skips-dead-branches-d/main.js similarity index 100% rename from test/function/skips-dead-branches-d/main.js rename to test/form/skips-dead-branches-d/main.js diff --git a/test/form/skips-dead-branches-e/_config.js b/test/form/skips-dead-branches-e/_config.js new file mode 100644 index 00000000000..d290c80e60d --- /dev/null +++ b/test/form/skips-dead-branches-e/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (e)' +}; diff --git a/test/form/skips-dead-branches-e/_expected/amd.js b/test/form/skips-dead-branches-e/_expected/amd.js new file mode 100644 index 00000000000..9dc50f528f3 --- /dev/null +++ b/test/form/skips-dead-branches-e/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches-e/_expected/cjs.js b/test/form/skips-dead-branches-e/_expected/cjs.js new file mode 100644 index 00000000000..d6aa952d0e6 --- /dev/null +++ b/test/form/skips-dead-branches-e/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-e/_expected/es.js b/test/form/skips-dead-branches-e/_expected/es.js new file mode 100644 index 00000000000..f39bfec65a9 --- /dev/null +++ b/test/form/skips-dead-branches-e/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-e/_expected/iife.js b/test/form/skips-dead-branches-e/_expected/iife.js new file mode 100644 index 00000000000..8d6dcb52c0c --- /dev/null +++ b/test/form/skips-dead-branches-e/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches-e/_expected/umd.js b/test/form/skips-dead-branches-e/_expected/umd.js new file mode 100644 index 00000000000..67588d41402 --- /dev/null +++ b/test/form/skips-dead-branches-e/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); \ No newline at end of file diff --git a/test/function/skips-dead-branches-e/main.js b/test/form/skips-dead-branches-e/main.js similarity index 100% rename from test/function/skips-dead-branches-e/main.js rename to test/form/skips-dead-branches-e/main.js diff --git a/test/form/skips-dead-branches-f/_config.js b/test/form/skips-dead-branches-f/_config.js new file mode 100644 index 00000000000..9ac1d2340bf --- /dev/null +++ b/test/form/skips-dead-branches-f/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (f)' +}; diff --git a/test/form/skips-dead-branches-f/_expected/amd.js b/test/form/skips-dead-branches-f/_expected/amd.js new file mode 100644 index 00000000000..9dc50f528f3 --- /dev/null +++ b/test/form/skips-dead-branches-f/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches-f/_expected/cjs.js b/test/form/skips-dead-branches-f/_expected/cjs.js new file mode 100644 index 00000000000..d6aa952d0e6 --- /dev/null +++ b/test/form/skips-dead-branches-f/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-f/_expected/es.js b/test/form/skips-dead-branches-f/_expected/es.js new file mode 100644 index 00000000000..f39bfec65a9 --- /dev/null +++ b/test/form/skips-dead-branches-f/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches-f/_expected/iife.js b/test/form/skips-dead-branches-f/_expected/iife.js new file mode 100644 index 00000000000..8d6dcb52c0c --- /dev/null +++ b/test/form/skips-dead-branches-f/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches-f/_expected/umd.js b/test/form/skips-dead-branches-f/_expected/umd.js new file mode 100644 index 00000000000..67588d41402 --- /dev/null +++ b/test/form/skips-dead-branches-f/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); \ No newline at end of file diff --git a/test/function/skips-dead-branches-f/main.js b/test/form/skips-dead-branches-f/main.js similarity index 100% rename from test/function/skips-dead-branches-f/main.js rename to test/form/skips-dead-branches-f/main.js diff --git a/test/form/skips-dead-branches-g/_config.js b/test/form/skips-dead-branches-g/_config.js new file mode 100644 index 00000000000..f592e056c93 --- /dev/null +++ b/test/form/skips-dead-branches-g/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead conditional expression branch (g)' +}; diff --git a/test/form/skips-dead-branches-g/_expected/amd.js b/test/form/skips-dead-branches-g/_expected/amd.js new file mode 100644 index 00000000000..41371dd60ab --- /dev/null +++ b/test/form/skips-dead-branches-g/_expected/amd.js @@ -0,0 +1,10 @@ +define(function () { 'use strict'; + + var a = 0; + var b = 1; + var x = a; + var y = b; + + console.log( x + y ); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches-g/_expected/cjs.js b/test/form/skips-dead-branches-g/_expected/cjs.js new file mode 100644 index 00000000000..44cffbfd667 --- /dev/null +++ b/test/form/skips-dead-branches-g/_expected/cjs.js @@ -0,0 +1,8 @@ +'use strict'; + +var a = 0; +var b = 1; +var x = a; +var y = b; + +console.log( x + y ); \ No newline at end of file diff --git a/test/form/skips-dead-branches-g/_expected/es.js b/test/form/skips-dead-branches-g/_expected/es.js new file mode 100644 index 00000000000..93d519839c6 --- /dev/null +++ b/test/form/skips-dead-branches-g/_expected/es.js @@ -0,0 +1,6 @@ +var a = 0; +var b = 1; +var x = a; +var y = b; + +console.log( x + y ); \ No newline at end of file diff --git a/test/form/skips-dead-branches-g/_expected/iife.js b/test/form/skips-dead-branches-g/_expected/iife.js new file mode 100644 index 00000000000..ce654f4f6ca --- /dev/null +++ b/test/form/skips-dead-branches-g/_expected/iife.js @@ -0,0 +1,11 @@ +(function () { + 'use strict'; + + var a = 0; + var b = 1; + var x = a; + var y = b; + + console.log( x + y ); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches-g/_expected/umd.js b/test/form/skips-dead-branches-g/_expected/umd.js new file mode 100644 index 00000000000..40a0a544539 --- /dev/null +++ b/test/form/skips-dead-branches-g/_expected/umd.js @@ -0,0 +1,14 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var a = 0; + var b = 1; + var x = a; + var y = b; + + console.log( x + y ); + +}))); \ No newline at end of file diff --git a/test/form/skips-dead-branches-g/main.js b/test/form/skips-dead-branches-g/main.js new file mode 100644 index 00000000000..352481e2144 --- /dev/null +++ b/test/form/skips-dead-branches-g/main.js @@ -0,0 +1,8 @@ +var a = 0; +var b = 1; +var c = 2; + +var x = true ? a : b; +var y = false ? c : b; + +console.log( x + y ); diff --git a/test/form/skips-dead-branches-h/_config.js b/test/form/skips-dead-branches-h/_config.js new file mode 100644 index 00000000000..85e8fbe2647 --- /dev/null +++ b/test/form/skips-dead-branches-h/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (h)' +}; diff --git a/test/form/skips-dead-branches-h/_expected/amd.js b/test/form/skips-dead-branches-h/_expected/amd.js new file mode 100644 index 00000000000..6847fcb332d --- /dev/null +++ b/test/form/skips-dead-branches-h/_expected/amd.js @@ -0,0 +1,8 @@ +define(function () { 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}); diff --git a/test/form/skips-dead-branches-h/_expected/cjs.js b/test/form/skips-dead-branches-h/_expected/cjs.js new file mode 100644 index 00000000000..6f1ef21dc82 --- /dev/null +++ b/test/form/skips-dead-branches-h/_expected/cjs.js @@ -0,0 +1,6 @@ +'use strict'; + +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches-h/_expected/es.js b/test/form/skips-dead-branches-h/_expected/es.js new file mode 100644 index 00000000000..788788a71bd --- /dev/null +++ b/test/form/skips-dead-branches-h/_expected/es.js @@ -0,0 +1,4 @@ +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches-h/_expected/iife.js b/test/form/skips-dead-branches-h/_expected/iife.js new file mode 100644 index 00000000000..88532fd9b9a --- /dev/null +++ b/test/form/skips-dead-branches-h/_expected/iife.js @@ -0,0 +1,9 @@ +(function () { + 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}()); diff --git a/test/form/skips-dead-branches-h/_expected/umd.js b/test/form/skips-dead-branches-h/_expected/umd.js new file mode 100644 index 00000000000..6286b12c6e0 --- /dev/null +++ b/test/form/skips-dead-branches-h/_expected/umd.js @@ -0,0 +1,12 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}))); diff --git a/test/form/skips-dead-branches-h/main.js b/test/form/skips-dead-branches-h/main.js new file mode 100644 index 00000000000..7808b0ded63 --- /dev/null +++ b/test/form/skips-dead-branches-h/main.js @@ -0,0 +1,11 @@ +function bar(umm) { + umm = hmm(); + console.log("bar"); +} +function hmm() { + return true; +} +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches-i/_config.js b/test/form/skips-dead-branches-i/_config.js new file mode 100644 index 00000000000..85e8fbe2647 --- /dev/null +++ b/test/form/skips-dead-branches-i/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch (h)' +}; diff --git a/test/form/skips-dead-branches-i/_expected/amd.js b/test/form/skips-dead-branches-i/_expected/amd.js new file mode 100644 index 00000000000..6847fcb332d --- /dev/null +++ b/test/form/skips-dead-branches-i/_expected/amd.js @@ -0,0 +1,8 @@ +define(function () { 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}); diff --git a/test/form/skips-dead-branches-i/_expected/cjs.js b/test/form/skips-dead-branches-i/_expected/cjs.js new file mode 100644 index 00000000000..6f1ef21dc82 --- /dev/null +++ b/test/form/skips-dead-branches-i/_expected/cjs.js @@ -0,0 +1,6 @@ +'use strict'; + +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches-i/_expected/es.js b/test/form/skips-dead-branches-i/_expected/es.js new file mode 100644 index 00000000000..788788a71bd --- /dev/null +++ b/test/form/skips-dead-branches-i/_expected/es.js @@ -0,0 +1,4 @@ +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches-i/_expected/iife.js b/test/form/skips-dead-branches-i/_expected/iife.js new file mode 100644 index 00000000000..88532fd9b9a --- /dev/null +++ b/test/form/skips-dead-branches-i/_expected/iife.js @@ -0,0 +1,9 @@ +(function () { + 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}()); diff --git a/test/form/skips-dead-branches-i/_expected/umd.js b/test/form/skips-dead-branches-i/_expected/umd.js new file mode 100644 index 00000000000..6286b12c6e0 --- /dev/null +++ b/test/form/skips-dead-branches-i/_expected/umd.js @@ -0,0 +1,12 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function baz() { + console.log("baz"); + } + baz(); + +}))); diff --git a/test/form/skips-dead-branches-i/main.js b/test/form/skips-dead-branches-i/main.js new file mode 100644 index 00000000000..6380bcf7c5a --- /dev/null +++ b/test/form/skips-dead-branches-i/main.js @@ -0,0 +1,12 @@ +function bar() { + var t; + t = hmm(); + console.log("bar"); +} +function hmm() { + return true; +} +function baz() { + console.log("baz"); +} +baz(); diff --git a/test/form/skips-dead-branches/_config.js b/test/form/skips-dead-branches/_config.js new file mode 100644 index 00000000000..078856d2ef6 --- /dev/null +++ b/test/form/skips-dead-branches/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'skips a dead branch' +}; diff --git a/test/form/skips-dead-branches/_expected/amd.js b/test/form/skips-dead-branches/_expected/amd.js new file mode 100644 index 00000000000..9dc50f528f3 --- /dev/null +++ b/test/form/skips-dead-branches/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}); \ No newline at end of file diff --git a/test/form/skips-dead-branches/_expected/cjs.js b/test/form/skips-dead-branches/_expected/cjs.js new file mode 100644 index 00000000000..d6aa952d0e6 --- /dev/null +++ b/test/form/skips-dead-branches/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches/_expected/es.js b/test/form/skips-dead-branches/_expected/es.js new file mode 100644 index 00000000000..f39bfec65a9 --- /dev/null +++ b/test/form/skips-dead-branches/_expected/es.js @@ -0,0 +1,5 @@ +function bar () { + console.log( 'this should be included' ); +} + +bar(); \ No newline at end of file diff --git a/test/form/skips-dead-branches/_expected/iife.js b/test/form/skips-dead-branches/_expected/iife.js new file mode 100644 index 00000000000..8d6dcb52c0c --- /dev/null +++ b/test/form/skips-dead-branches/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}()); \ No newline at end of file diff --git a/test/form/skips-dead-branches/_expected/umd.js b/test/form/skips-dead-branches/_expected/umd.js new file mode 100644 index 00000000000..67588d41402 --- /dev/null +++ b/test/form/skips-dead-branches/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function bar () { + console.log( 'this should be included' ); + } + + bar(); + +}))); \ No newline at end of file diff --git a/test/function/skips-dead-branches/main.js b/test/form/skips-dead-branches/main.js similarity index 100% rename from test/function/skips-dead-branches/main.js rename to test/form/skips-dead-branches/main.js diff --git a/test/form/sourcemaps/_config.js b/test/form/sourcemaps-external/_config.js similarity index 100% rename from test/form/sourcemaps/_config.js rename to test/form/sourcemaps-external/_config.js diff --git a/test/form/sourcemaps/_expected/amd.js b/test/form/sourcemaps-external/_expected/amd.js similarity index 100% rename from test/form/sourcemaps/_expected/amd.js rename to test/form/sourcemaps-external/_expected/amd.js diff --git a/test/form/sourcemaps/_expected/amd.js.map b/test/form/sourcemaps-external/_expected/amd.js.map similarity index 100% rename from test/form/sourcemaps/_expected/amd.js.map rename to test/form/sourcemaps-external/_expected/amd.js.map diff --git a/test/form/sourcemaps/_expected/cjs.js b/test/form/sourcemaps-external/_expected/cjs.js similarity index 100% rename from test/form/sourcemaps/_expected/cjs.js rename to test/form/sourcemaps-external/_expected/cjs.js diff --git a/test/form/sourcemaps/_expected/cjs.js.map b/test/form/sourcemaps-external/_expected/cjs.js.map similarity index 100% rename from test/form/sourcemaps/_expected/cjs.js.map rename to test/form/sourcemaps-external/_expected/cjs.js.map diff --git a/test/form/sourcemaps/_expected/es6.js b/test/form/sourcemaps-external/_expected/es.js similarity index 84% rename from test/form/sourcemaps/_expected/es6.js rename to test/form/sourcemaps-external/_expected/es.js index f1d6ef7a664..c7263f8b99d 100644 --- a/test/form/sourcemaps/_expected/es6.js +++ b/test/form/sourcemaps-external/_expected/es.js @@ -10,4 +10,4 @@ console.log( 'hello from main.js' ); foo(); bar(); -//# sourceMappingURL=es6.js.map \ No newline at end of file +//# sourceMappingURL=es.js.map diff --git a/test/form/sourcemaps-external/_expected/es.js.map b/test/form/sourcemaps-external/_expected/es.js.map new file mode 100644 index 00000000000..ec8dd246b1c --- /dev/null +++ b/test/form/sourcemaps-external/_expected/es.js.map @@ -0,0 +1 @@ +{"version":3,"file":"es.js","sources":["../foo.js","../bar.js","../main.js"],"sourcesContent":["export default function foo () {\n\tconsole.log( 'hello from foo.js' );\n}\n","export default function bar () {\n\tconsole.log( 'hello from bar.js' );\n}\n","import foo from './foo';\nimport bar from './bar';\n\nconsole.log( 'hello from main.js' );\n\nfoo();\nbar();\n"],"names":[],"mappings":"AAAe,SAAS,GAAG,IAAI;CAC9B,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,CAAC;CACnC;;ACFc,SAAS,GAAG,IAAI;CAC9B,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,CAAC;CACnC;;ACCD,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,CAAC;;AAEpC,GAAG,EAAE,CAAC;AACN,GAAG,EAAE,CAAC"} diff --git a/test/form/sourcemaps/_expected/iife.js b/test/form/sourcemaps-external/_expected/iife.js similarity index 100% rename from test/form/sourcemaps/_expected/iife.js rename to test/form/sourcemaps-external/_expected/iife.js diff --git a/test/form/sourcemaps/_expected/iife.js.map b/test/form/sourcemaps-external/_expected/iife.js.map similarity index 100% rename from test/form/sourcemaps/_expected/iife.js.map rename to test/form/sourcemaps-external/_expected/iife.js.map diff --git a/test/form/sourcemaps/_expected/umd.js b/test/form/sourcemaps-external/_expected/umd.js similarity index 83% rename from test/form/sourcemaps/_expected/umd.js rename to test/form/sourcemaps-external/_expected/umd.js index 5e77403a482..118c0929313 100644 --- a/test/form/sourcemaps/_expected/umd.js +++ b/test/form/sourcemaps-external/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'hello from foo.js' ); @@ -17,5 +17,5 @@ foo(); bar(); -})); +}))); //# sourceMappingURL=umd.js.map \ No newline at end of file diff --git a/test/form/sourcemaps/_expected/umd.js.map b/test/form/sourcemaps-external/_expected/umd.js.map similarity index 100% rename from test/form/sourcemaps/_expected/umd.js.map rename to test/form/sourcemaps-external/_expected/umd.js.map diff --git a/test/form/sourcemaps/bar.js b/test/form/sourcemaps-external/bar.js similarity index 100% rename from test/form/sourcemaps/bar.js rename to test/form/sourcemaps-external/bar.js diff --git a/test/form/sourcemaps/foo.js b/test/form/sourcemaps-external/foo.js similarity index 100% rename from test/form/sourcemaps/foo.js rename to test/form/sourcemaps-external/foo.js diff --git a/test/form/sourcemaps/main.js b/test/form/sourcemaps-external/main.js similarity index 100% rename from test/form/sourcemaps/main.js rename to test/form/sourcemaps-external/main.js diff --git a/test/form/sourcemaps-inline/_expected/es.js b/test/form/sourcemaps-inline/_expected/es.js new file mode 100644 index 00000000000..b823f1da5fe --- /dev/null +++ b/test/form/sourcemaps-inline/_expected/es.js @@ -0,0 +1,13 @@ +function foo () { + console.log( 'hello from foo.js' ); +} + +function bar () { + console.log( 'hello from bar.js' ); +} + +console.log( 'hello from main.js' ); + +foo(); +bar(); +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXMuanMiLCJzb3VyY2VzIjpbIi4uL2Zvby5qcyIsIi4uL2Jhci5qcyIsIi4uL21haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gZm9vICgpIHtcblx0Y29uc29sZS5sb2coICdoZWxsbyBmcm9tIGZvby5qcycgKTtcbn1cbiIsImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGJhciAoKSB7XG5cdGNvbnNvbGUubG9nKCAnaGVsbG8gZnJvbSBiYXIuanMnICk7XG59XG4iLCJpbXBvcnQgZm9vIGZyb20gJy4vZm9vJztcbmltcG9ydCBiYXIgZnJvbSAnLi9iYXInO1xuXG5jb25zb2xlLmxvZyggJ2hlbGxvIGZyb20gbWFpbi5qcycgKTtcblxuZm9vKCk7XG5iYXIoKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBZSxTQUFTLEdBQUcsSUFBSTtDQUM5QixPQUFPLENBQUMsR0FBRyxFQUFFLG1CQUFtQixFQUFFLENBQUM7Q0FDbkM7O0FDRmMsU0FBUyxHQUFHLElBQUk7Q0FDOUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO0NBQ25DOztBQ0NELE9BQU8sQ0FBQyxHQUFHLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQzs7QUFFcEMsR0FBRyxFQUFFLENBQUM7QUFDTixHQUFHLEVBQUUsQ0FBQyJ9 diff --git a/test/form/sourcemaps-inline/_expected/es6.js b/test/form/sourcemaps-inline/_expected/es6.js deleted file mode 100644 index c07d67af173..00000000000 --- a/test/form/sourcemaps-inline/_expected/es6.js +++ /dev/null @@ -1,13 +0,0 @@ -function foo () { - console.log( 'hello from foo.js' ); -} - -function bar () { - console.log( 'hello from bar.js' ); -} - -console.log( 'hello from main.js' ); - -foo(); -bar(); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXM2LmpzIiwic291cmNlcyI6WyIuLi9mb28uanMiLCIuLi9iYXIuanMiLCIuLi9tYWluLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGZvbyAoKSB7XG5cdGNvbnNvbGUubG9nKCAnaGVsbG8gZnJvbSBmb28uanMnICk7XG59XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBiYXIgKCkge1xuXHRjb25zb2xlLmxvZyggJ2hlbGxvIGZyb20gYmFyLmpzJyApO1xufVxuIiwiaW1wb3J0IGZvbyBmcm9tICcuL2Zvbyc7XG5pbXBvcnQgYmFyIGZyb20gJy4vYmFyJztcblxuY29uc29sZS5sb2coICdoZWxsbyBmcm9tIG1haW4uanMnICk7XG5cbmZvbygpO1xuYmFyKCk7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWUsU0FBUyxHQUFHLElBQUk7Q0FDOUIsT0FBTyxDQUFDLEdBQUcsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO0NBQ25DOztBQ0ZjLFNBQVMsR0FBRyxJQUFJO0NBQzlCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztDQUNuQzs7QUNDRCxPQUFPLENBQUMsR0FBRyxFQUFFLG9CQUFvQixFQUFFLENBQUM7O0FBRXBDLEdBQUcsRUFBRSxDQUFDO0FBQ04sR0FBRyxFQUFFLENBQUMifQ== \ No newline at end of file diff --git a/test/form/sourcemaps-inline/_expected/umd.js b/test/form/sourcemaps-inline/_expected/umd.js index b93485431e5..ab7ebf40bac 100644 --- a/test/form/sourcemaps-inline/_expected/umd.js +++ b/test/form/sourcemaps-inline/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function foo () { console.log( 'hello from foo.js' ); @@ -17,5 +17,5 @@ foo(); bar(); -})); +}))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidW1kLmpzIiwic291cmNlcyI6WyIuLi9mb28uanMiLCIuLi9iYXIuanMiLCIuLi9tYWluLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGZvbyAoKSB7XG5cdGNvbnNvbGUubG9nKCAnaGVsbG8gZnJvbSBmb28uanMnICk7XG59XG4iLCJleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBiYXIgKCkge1xuXHRjb25zb2xlLmxvZyggJ2hlbGxvIGZyb20gYmFyLmpzJyApO1xufVxuIiwiaW1wb3J0IGZvbyBmcm9tICcuL2Zvbyc7XG5pbXBvcnQgYmFyIGZyb20gJy4vYmFyJztcblxuY29uc29sZS5sb2coICdoZWxsbyBmcm9tIG1haW4uanMnICk7XG5cbmZvbygpO1xuYmFyKCk7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0NBQWUsU0FBUyxHQUFHLElBQUk7QUFDL0IsQ0FBQSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztBQUNwQyxDQUFBLENBQUM7O0NDRmMsU0FBUyxHQUFHLElBQUk7QUFDL0IsQ0FBQSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztBQUNwQyxDQUFBLENBQUM7O0NDQ0QsT0FBTyxDQUFDLEdBQUcsRUFBRSxvQkFBb0IsRUFBRSxDQUFDOztBQUVwQyxDQUFBLEdBQUcsRUFBRSxDQUFDO0FBQ04sQ0FBQSxHQUFHLEVBQUUsQ0FBQyw7OyJ9 \ No newline at end of file diff --git a/test/form/sourcemaps/_expected/es6.js.map b/test/form/sourcemaps/_expected/es6.js.map deleted file mode 100644 index 2b48a490483..00000000000 --- a/test/form/sourcemaps/_expected/es6.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"es6.js","sources":["../foo.js","../bar.js","../main.js"],"sourcesContent":["export default function foo () {\n\tconsole.log( 'hello from foo.js' );\n}\n","export default function bar () {\n\tconsole.log( 'hello from bar.js' );\n}\n","import foo from './foo';\nimport bar from './bar';\n\nconsole.log( 'hello from main.js' );\n\nfoo();\nbar();\n"],"names":[],"mappings":"AAAe,SAAS,GAAG,IAAI;CAC9B,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,CAAC;CACnC;;ACFc,SAAS,GAAG,IAAI;CAC9B,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,CAAC;CACnC;;ACCD,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,CAAC;;AAEpC,GAAG,EAAE,CAAC;AACN,GAAG,EAAE,CAAC"} \ No newline at end of file diff --git a/test/form/spacing-after-function-with-semicolon/_expected/amd.js b/test/form/spacing-after-function-with-semicolon/_expected/amd.js index 37f42f3cfb2..4db965ceaa3 100644 --- a/test/form/spacing-after-function-with-semicolon/_expected/amd.js +++ b/test/form/spacing-after-function-with-semicolon/_expected/amd.js @@ -1,6 +1,6 @@ define(function () { 'use strict'; - function x () { return 'x' }; + function x () { return 'x' } assert.equal( x(), 'x' ); diff --git a/test/form/spacing-after-function-with-semicolon/_expected/cjs.js b/test/form/spacing-after-function-with-semicolon/_expected/cjs.js index 503ea739ec2..bac28c19265 100644 --- a/test/form/spacing-after-function-with-semicolon/_expected/cjs.js +++ b/test/form/spacing-after-function-with-semicolon/_expected/cjs.js @@ -1,5 +1,5 @@ 'use strict'; -function x () { return 'x' }; +function x () { return 'x' } assert.equal( x(), 'x' ); diff --git a/test/form/spacing-after-function-with-semicolon/_expected/es.js b/test/form/spacing-after-function-with-semicolon/_expected/es.js new file mode 100644 index 00000000000..f5b5029659d --- /dev/null +++ b/test/form/spacing-after-function-with-semicolon/_expected/es.js @@ -0,0 +1,3 @@ +function x () { return 'x' } + +assert.equal( x(), 'x' ); diff --git a/test/form/spacing-after-function-with-semicolon/_expected/es6.js b/test/form/spacing-after-function-with-semicolon/_expected/es6.js deleted file mode 100644 index 3b3f5e7cd70..00000000000 --- a/test/form/spacing-after-function-with-semicolon/_expected/es6.js +++ /dev/null @@ -1,3 +0,0 @@ -function x () { return 'x' }; - -assert.equal( x(), 'x' ); diff --git a/test/form/spacing-after-function-with-semicolon/_expected/iife.js b/test/form/spacing-after-function-with-semicolon/_expected/iife.js index 7ff78ec9c35..f8d69920288 100644 --- a/test/form/spacing-after-function-with-semicolon/_expected/iife.js +++ b/test/form/spacing-after-function-with-semicolon/_expected/iife.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function x () { return 'x' }; + function x () { return 'x' } assert.equal( x(), 'x' ); diff --git a/test/form/spacing-after-function-with-semicolon/_expected/umd.js b/test/form/spacing-after-function-with-semicolon/_expected/umd.js index 56bca25c373..75d31a1d04b 100644 --- a/test/form/spacing-after-function-with-semicolon/_expected/umd.js +++ b/test/form/spacing-after-function-with-semicolon/_expected/umd.js @@ -2,10 +2,10 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; - function x () { return 'x' }; + function x () { return 'x' } assert.equal( x(), 'x' ); -})); \ No newline at end of file +}))); diff --git a/test/form/string-indentation-b/_expected/amd.js b/test/form/string-indentation-b/_expected/amd.js index f646cb2e377..2eb44c97c16 100644 --- a/test/form/string-indentation-b/_expected/amd.js +++ b/test/form/string-indentation-b/_expected/amd.js @@ -2,7 +2,8 @@ define(function () { 'use strict'; var a = 'a'; var b = 'b'; + assert.equal( a, 'a' ); assert.equal( b, 'b' ); -}); \ No newline at end of file +}); diff --git a/test/form/string-indentation-b/_expected/cjs.js b/test/form/string-indentation-b/_expected/cjs.js index 7c799d31f16..8432e6e13a2 100644 --- a/test/form/string-indentation-b/_expected/cjs.js +++ b/test/form/string-indentation-b/_expected/cjs.js @@ -2,5 +2,6 @@ var a = 'a'; var b = 'b'; + assert.equal( a, 'a' ); -assert.equal( b, 'b' ); \ No newline at end of file +assert.equal( b, 'b' ); diff --git a/test/form/string-indentation-b/_expected/es6.js b/test/form/string-indentation-b/_expected/es.js similarity index 66% rename from test/form/string-indentation-b/_expected/es6.js rename to test/form/string-indentation-b/_expected/es.js index 7ab432c7e04..6cd3b5a9b59 100644 --- a/test/form/string-indentation-b/_expected/es6.js +++ b/test/form/string-indentation-b/_expected/es.js @@ -1,4 +1,5 @@ var a = 'a'; var b = 'b'; + assert.equal( a, 'a' ); -assert.equal( b, 'b' ); \ No newline at end of file +assert.equal( b, 'b' ); diff --git a/test/form/string-indentation-b/_expected/iife.js b/test/form/string-indentation-b/_expected/iife.js index ae8c969dcbd..6907cdb926d 100644 --- a/test/form/string-indentation-b/_expected/iife.js +++ b/test/form/string-indentation-b/_expected/iife.js @@ -3,7 +3,8 @@ var a = 'a'; var b = 'b'; + assert.equal( a, 'a' ); assert.equal( b, 'b' ); -}()); \ No newline at end of file +}()); diff --git a/test/form/string-indentation-b/_expected/umd.js b/test/form/string-indentation-b/_expected/umd.js index ad0bc29aa9f..47597be8f5e 100644 --- a/test/form/string-indentation-b/_expected/umd.js +++ b/test/form/string-indentation-b/_expected/umd.js @@ -2,11 +2,12 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var a = 'a'; var b = 'b'; + assert.equal( a, 'a' ); assert.equal( b, 'b' ); -})); \ No newline at end of file +}))); diff --git a/test/form/string-indentation/_expected/es6.js b/test/form/string-indentation/_expected/es.js similarity index 100% rename from test/form/string-indentation/_expected/es6.js rename to test/form/string-indentation/_expected/es.js diff --git a/test/form/string-indentation/_expected/umd.js b/test/form/string-indentation/_expected/umd.js index 285a53f5fc3..ac7131e15cb 100644 --- a/test/form/string-indentation/_expected/umd.js +++ b/test/form/string-indentation/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var a = '1\ 2'; @@ -21,4 +21,4 @@ assert.equal( c, '1\n 2' ); assert.equal( d, '1\n\t2' ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/this-is-undefined/_config.js b/test/form/this-is-undefined/_config.js new file mode 100644 index 00000000000..75134029384 --- /dev/null +++ b/test/form/this-is-undefined/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'top-level `this` expression is rewritten as `undefined`', + options: { + onwarn: () => {} + } +}; diff --git a/test/form/this-is-undefined/_expected/amd.js b/test/form/this-is-undefined/_expected/amd.js new file mode 100644 index 00000000000..c90e975185d --- /dev/null +++ b/test/form/this-is-undefined/_expected/amd.js @@ -0,0 +1,21 @@ +define(function () { 'use strict'; + + const fooContext = {}; + + function foo () { + // inside a function, `this` should be untouched... + assert.strictEqual( this, fooContext ); + } + + const bar = () => { + // ...unless it's an arrow function + assert.strictEqual( undefined, undefined ); + }; + + foo.call( fooContext ); + bar.call( {} ); + + // outside a function, `this` is undefined + assert.strictEqual( undefined, undefined ); + +}); diff --git a/test/form/this-is-undefined/_expected/cjs.js b/test/form/this-is-undefined/_expected/cjs.js new file mode 100644 index 00000000000..c99ffc5e3ef --- /dev/null +++ b/test/form/this-is-undefined/_expected/cjs.js @@ -0,0 +1,19 @@ +'use strict'; + +const fooContext = {}; + +function foo () { + // inside a function, `this` should be untouched... + assert.strictEqual( this, fooContext ); +} + +const bar = () => { + // ...unless it's an arrow function + assert.strictEqual( undefined, undefined ); +}; + +foo.call( fooContext ); +bar.call( {} ); + +// outside a function, `this` is undefined +assert.strictEqual( undefined, undefined ); diff --git a/test/form/this-is-undefined/_expected/es.js b/test/form/this-is-undefined/_expected/es.js new file mode 100644 index 00000000000..686db335da1 --- /dev/null +++ b/test/form/this-is-undefined/_expected/es.js @@ -0,0 +1,17 @@ +const fooContext = {}; + +function foo () { + // inside a function, `this` should be untouched... + assert.strictEqual( this, fooContext ); +} + +const bar = () => { + // ...unless it's an arrow function + assert.strictEqual( undefined, undefined ); +}; + +foo.call( fooContext ); +bar.call( {} ); + +// outside a function, `this` is undefined +assert.strictEqual( undefined, undefined ); diff --git a/test/form/this-is-undefined/_expected/iife.js b/test/form/this-is-undefined/_expected/iife.js new file mode 100644 index 00000000000..f82edce9c6c --- /dev/null +++ b/test/form/this-is-undefined/_expected/iife.js @@ -0,0 +1,22 @@ +(function () { + 'use strict'; + + const fooContext = {}; + + function foo () { + // inside a function, `this` should be untouched... + assert.strictEqual( this, fooContext ); + } + + const bar = () => { + // ...unless it's an arrow function + assert.strictEqual( undefined, undefined ); + }; + + foo.call( fooContext ); + bar.call( {} ); + + // outside a function, `this` is undefined + assert.strictEqual( undefined, undefined ); + +}()); diff --git a/test/form/this-is-undefined/_expected/umd.js b/test/form/this-is-undefined/_expected/umd.js new file mode 100644 index 00000000000..996e79856f4 --- /dev/null +++ b/test/form/this-is-undefined/_expected/umd.js @@ -0,0 +1,25 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + const fooContext = {}; + + function foo () { + // inside a function, `this` should be untouched... + assert.strictEqual( this, fooContext ); + } + + const bar = () => { + // ...unless it's an arrow function + assert.strictEqual( undefined, undefined ); + }; + + foo.call( fooContext ); + bar.call( {} ); + + // outside a function, `this` is undefined + assert.strictEqual( undefined, undefined ); + +}))); diff --git a/test/function/this-is-undefined/main.js b/test/form/this-is-undefined/main.js similarity index 93% rename from test/function/this-is-undefined/main.js rename to test/form/this-is-undefined/main.js index 5c82fb4facc..4fcdf42faf8 100644 --- a/test/function/this-is-undefined/main.js +++ b/test/form/this-is-undefined/main.js @@ -1,4 +1,4 @@ -const fooContext = {} +const fooContext = {}; function foo () { // inside a function, `this` should be untouched... diff --git a/test/form/transform-bundle-plugin-options/_config.js b/test/form/transform-bundle-plugin-options/_config.js new file mode 100644 index 00000000000..417e38fefae --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_config.js @@ -0,0 +1,12 @@ +module.exports = { + description: 'plugin .transformBundle gets passed options', + options: { + plugins: [ + { + transformBundle: function (code, options) { + return JSON.stringify(options); + } + } + ] + } +}; diff --git a/test/form/transform-bundle-plugin-options/_expected/amd.js b/test/form/transform-bundle-plugin-options/_expected/amd.js new file mode 100644 index 00000000000..69904ec5577 --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_expected/amd.js @@ -0,0 +1 @@ +{"format":"amd"} diff --git a/test/form/transform-bundle-plugin-options/_expected/cjs.js b/test/form/transform-bundle-plugin-options/_expected/cjs.js new file mode 100644 index 00000000000..72dd9eb36c9 --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_expected/cjs.js @@ -0,0 +1 @@ +{"format":"cjs"} diff --git a/test/form/transform-bundle-plugin-options/_expected/es.js b/test/form/transform-bundle-plugin-options/_expected/es.js new file mode 100644 index 00000000000..3a0913b1074 --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_expected/es.js @@ -0,0 +1 @@ +{"format":"es"} diff --git a/test/form/transform-bundle-plugin-options/_expected/iife.js b/test/form/transform-bundle-plugin-options/_expected/iife.js new file mode 100644 index 00000000000..9bdbe7bc46f --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_expected/iife.js @@ -0,0 +1 @@ +{"format":"iife"} diff --git a/test/form/transform-bundle-plugin-options/_expected/umd.js b/test/form/transform-bundle-plugin-options/_expected/umd.js new file mode 100644 index 00000000000..c7dad3087f0 --- /dev/null +++ b/test/form/transform-bundle-plugin-options/_expected/umd.js @@ -0,0 +1 @@ +{"format":"umd"} diff --git a/test/form/transform-bundle-plugin-options/main.js b/test/form/transform-bundle-plugin-options/main.js new file mode 100644 index 00000000000..934dee761bb --- /dev/null +++ b/test/form/transform-bundle-plugin-options/main.js @@ -0,0 +1 @@ +console.log( 1 + 1 ); diff --git a/test/form/transform-bundle-plugin/_config.js b/test/form/transform-bundle-plugin/_config.js index 6b54ad3803f..61af11dc73a 100644 --- a/test/form/transform-bundle-plugin/_config.js +++ b/test/form/transform-bundle-plugin/_config.js @@ -14,4 +14,4 @@ module.exports = { } ] } -} +}; diff --git a/test/form/transform-bundle-plugin/_expected/es6.js b/test/form/transform-bundle-plugin/_expected/es.js similarity index 100% rename from test/form/transform-bundle-plugin/_expected/es6.js rename to test/form/transform-bundle-plugin/_expected/es.js diff --git a/test/form/umd-noconflict/_config.js b/test/form/umd-noconflict/_config.js index 9bbcec618e1..9429457a659 100644 --- a/test/form/umd-noconflict/_config.js +++ b/test/form/umd-noconflict/_config.js @@ -1,5 +1,3 @@ -var assert = require( 'assert' ); - module.exports = { description: 'exports noConflict method for default umd when requested', options: { diff --git a/test/form/umd-noconflict/_expected/amd.js b/test/form/umd-noconflict/_expected/amd.js index 16ca4092bd4..f2fd756cbda 100644 --- a/test/form/umd-noconflict/_expected/amd.js +++ b/test/form/umd-noconflict/_expected/amd.js @@ -12,4 +12,6 @@ define(['exports'], function (exports) { 'use strict'; exports.number = number; exports.setting = setting; -}); \ No newline at end of file + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/form/umd-noconflict/_expected/cjs.js b/test/form/umd-noconflict/_expected/cjs.js index 4379f50946f..05952881691 100644 --- a/test/form/umd-noconflict/_expected/cjs.js +++ b/test/form/umd-noconflict/_expected/cjs.js @@ -1,5 +1,7 @@ 'use strict'; +Object.defineProperty(exports, '__esModule', { value: true }); + function doThings() { console.log( 'doing things...' ); } @@ -10,4 +12,4 @@ var setting = 'no'; exports.doThings = doThings; exports.number = number; -exports.setting = setting; \ No newline at end of file +exports.setting = setting; diff --git a/test/form/umd-noconflict/_expected/es6.js b/test/form/umd-noconflict/_expected/es.js similarity index 100% rename from test/form/umd-noconflict/_expected/es6.js rename to test/form/umd-noconflict/_expected/es.js diff --git a/test/form/umd-noconflict/_expected/umd.js b/test/form/umd-noconflict/_expected/umd.js index 5578ce99b33..89e044819da 100644 --- a/test/form/umd-noconflict/_expected/umd.js +++ b/test/form/umd-noconflict/_expected/umd.js @@ -7,7 +7,7 @@ global.FooBar = exports; exports.noConflict = function() { global.FooBar = current; return exports; }; })(); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; function doThings() { console.log( 'doing things...' ); @@ -21,4 +21,6 @@ exports.number = number; exports.setting = setting; -})); + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/test/form/unmodified-default-exports-function-argument/_expected/es6.js b/test/form/unmodified-default-exports-function-argument/_expected/es.js similarity index 100% rename from test/form/unmodified-default-exports-function-argument/_expected/es6.js rename to test/form/unmodified-default-exports-function-argument/_expected/es.js diff --git a/test/form/unmodified-default-exports-function-argument/_expected/umd.js b/test/form/unmodified-default-exports-function-argument/_expected/umd.js index 07f17818eef..81d4424b9bc 100644 --- a/test/form/unmodified-default-exports-function-argument/_expected/umd.js +++ b/test/form/unmodified-default-exports-function-argument/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var foo = function () { return 42; @@ -17,4 +17,4 @@ console.log( answer ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/unmodified-default-exports/_expected/es6.js b/test/form/unmodified-default-exports/_expected/es.js similarity index 100% rename from test/form/unmodified-default-exports/_expected/es6.js rename to test/form/unmodified-default-exports/_expected/es.js diff --git a/test/form/unmodified-default-exports/_expected/umd.js b/test/form/unmodified-default-exports/_expected/umd.js index d83a80644b0..f74ed8e373c 100644 --- a/test/form/unmodified-default-exports/_expected/umd.js +++ b/test/form/unmodified-default-exports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var Foo = function () { this.isFoo = true; @@ -16,4 +16,4 @@ var foo = new Foo(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/unused-called-import/_config.js b/test/form/unused-called-import/_config.js new file mode 100644 index 00000000000..0f1029d3236 --- /dev/null +++ b/test/form/unused-called-import/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not include called-in-unused-code import' +}; diff --git a/test/form/unused-called-import/_expected/amd.js b/test/form/unused-called-import/_expected/amd.js new file mode 100644 index 00000000000..f0cc768b22a --- /dev/null +++ b/test/form/unused-called-import/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + var foo = function() { return 'foo'; }; + + assert.equal( foo(), 'foo' ); + +}); diff --git a/test/form/unused-called-import/_expected/cjs.js b/test/form/unused-called-import/_expected/cjs.js new file mode 100644 index 00000000000..b808398bd07 --- /dev/null +++ b/test/form/unused-called-import/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +var foo = function() { return 'foo'; }; + +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-called-import/_expected/es.js b/test/form/unused-called-import/_expected/es.js new file mode 100644 index 00000000000..f24d6125f49 --- /dev/null +++ b/test/form/unused-called-import/_expected/es.js @@ -0,0 +1,3 @@ +var foo = function() { return 'foo'; }; + +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-called-import/_expected/iife.js b/test/form/unused-called-import/_expected/iife.js new file mode 100644 index 00000000000..bc7e275d644 --- /dev/null +++ b/test/form/unused-called-import/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + var foo = function() { return 'foo'; }; + + assert.equal( foo(), 'foo' ); + +}()); diff --git a/test/form/unused-called-import/_expected/umd.js b/test/form/unused-called-import/_expected/umd.js new file mode 100644 index 00000000000..1469ca3154f --- /dev/null +++ b/test/form/unused-called-import/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var foo = function() { return 'foo'; }; + + assert.equal( foo(), 'foo' ); + +}))); diff --git a/test/form/unused-called-import/dead.js b/test/form/unused-called-import/dead.js new file mode 100644 index 00000000000..56a0ceb3210 --- /dev/null +++ b/test/form/unused-called-import/dead.js @@ -0,0 +1 @@ +export default function() { return 'dead'; } diff --git a/test/form/unused-called-import/foo.js b/test/form/unused-called-import/foo.js new file mode 100644 index 00000000000..e19ff254dc3 --- /dev/null +++ b/test/form/unused-called-import/foo.js @@ -0,0 +1,5 @@ +import dead from './dead'; + +export default function() { return 'foo'; } + +export function foodead() { return 'foo' + dead(); } diff --git a/test/form/unused-called-import/main.js b/test/form/unused-called-import/main.js new file mode 100644 index 00000000000..3e476bbf4fb --- /dev/null +++ b/test/form/unused-called-import/main.js @@ -0,0 +1,2 @@ +import foo from './foo'; +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-called-with-side-effects/_config.js b/test/form/unused-called-with-side-effects/_config.js new file mode 100644 index 00000000000..0f1029d3236 --- /dev/null +++ b/test/form/unused-called-with-side-effects/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not include called-in-unused-code import' +}; diff --git a/test/form/unused-called-with-side-effects/_expected/amd.js b/test/form/unused-called-with-side-effects/_expected/amd.js new file mode 100644 index 00000000000..8be9631bd93 --- /dev/null +++ b/test/form/unused-called-with-side-effects/_expected/amd.js @@ -0,0 +1,9 @@ +define(function () { 'use strict'; + + function foo() { + return 'foo' + } + + assert.equal( foo(), 'foo' ); + +}); diff --git a/test/form/unused-called-with-side-effects/_expected/cjs.js b/test/form/unused-called-with-side-effects/_expected/cjs.js new file mode 100644 index 00000000000..9cd0d53904a --- /dev/null +++ b/test/form/unused-called-with-side-effects/_expected/cjs.js @@ -0,0 +1,7 @@ +'use strict'; + +function foo() { + return 'foo' +} + +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-called-with-side-effects/_expected/es.js b/test/form/unused-called-with-side-effects/_expected/es.js new file mode 100644 index 00000000000..1ea92fce8ae --- /dev/null +++ b/test/form/unused-called-with-side-effects/_expected/es.js @@ -0,0 +1,5 @@ +function foo() { + return 'foo' +} + +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-called-with-side-effects/_expected/iife.js b/test/form/unused-called-with-side-effects/_expected/iife.js new file mode 100644 index 00000000000..ccdb513770d --- /dev/null +++ b/test/form/unused-called-with-side-effects/_expected/iife.js @@ -0,0 +1,10 @@ +(function () { + 'use strict'; + + function foo() { + return 'foo' + } + + assert.equal( foo(), 'foo' ); + +}()); diff --git a/test/form/unused-called-with-side-effects/_expected/umd.js b/test/form/unused-called-with-side-effects/_expected/umd.js new file mode 100644 index 00000000000..e3ea51f9025 --- /dev/null +++ b/test/form/unused-called-with-side-effects/_expected/umd.js @@ -0,0 +1,13 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + function foo() { + return 'foo' + } + + assert.equal( foo(), 'foo' ); + +}))); diff --git a/test/form/unused-called-with-side-effects/main.js b/test/form/unused-called-with-side-effects/main.js new file mode 100644 index 00000000000..25de8d8bdfe --- /dev/null +++ b/test/form/unused-called-with-side-effects/main.js @@ -0,0 +1,13 @@ +function foo() { + return 'foo' +} + +function bar() { + dead(); +} + +function dead() { + console.log('dead'); +} + +assert.equal( foo(), 'foo' ); diff --git a/test/form/unused-default-exports/_expected/es6.js b/test/form/unused-default-exports/_expected/es.js similarity index 100% rename from test/form/unused-default-exports/_expected/es6.js rename to test/form/unused-default-exports/_expected/es.js diff --git a/test/form/unused-default-exports/_expected/umd.js b/test/form/unused-default-exports/_expected/umd.js index 8c9c2e00b5c..b38f629a8c4 100644 --- a/test/form/unused-default-exports/_expected/umd.js +++ b/test/form/unused-default-exports/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; var foo = { value: 1 }; @@ -15,4 +15,4 @@ assert.equal( foo.value, 2 ); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/form/unused-var/_config.js b/test/form/unused-var/_config.js new file mode 100644 index 00000000000..b89eb86733e --- /dev/null +++ b/test/form/unused-var/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'omits unused var declaration' +}; diff --git a/test/form/unused-var/_expected/amd.js b/test/form/unused-var/_expected/amd.js new file mode 100644 index 00000000000..babb23a74f1 --- /dev/null +++ b/test/form/unused-var/_expected/amd.js @@ -0,0 +1,7 @@ +define(function () { 'use strict'; + + var foo = 'lol'; + + console.log( foo ); + +}); \ No newline at end of file diff --git a/test/form/unused-var/_expected/cjs.js b/test/form/unused-var/_expected/cjs.js new file mode 100644 index 00000000000..8628267a89b --- /dev/null +++ b/test/form/unused-var/_expected/cjs.js @@ -0,0 +1,5 @@ +'use strict'; + +var foo = 'lol'; + +console.log( foo ); \ No newline at end of file diff --git a/test/form/unused-var/_expected/es.js b/test/form/unused-var/_expected/es.js new file mode 100644 index 00000000000..2e13c7578ab --- /dev/null +++ b/test/form/unused-var/_expected/es.js @@ -0,0 +1,3 @@ +var foo = 'lol'; + +console.log( foo ); \ No newline at end of file diff --git a/test/form/unused-var/_expected/iife.js b/test/form/unused-var/_expected/iife.js new file mode 100644 index 00000000000..a9b45dfc7b0 --- /dev/null +++ b/test/form/unused-var/_expected/iife.js @@ -0,0 +1,8 @@ +(function () { + 'use strict'; + + var foo = 'lol'; + + console.log( foo ); + +}()); \ No newline at end of file diff --git a/test/form/unused-var/_expected/umd.js b/test/form/unused-var/_expected/umd.js new file mode 100644 index 00000000000..71ba44f5d47 --- /dev/null +++ b/test/form/unused-var/_expected/umd.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory() : + typeof define === 'function' && define.amd ? define(factory) : + (factory()); +}(this, (function () { 'use strict'; + + var foo = 'lol'; + + console.log( foo ); + +}))); \ No newline at end of file diff --git a/test/form/unused-var/foo.js b/test/form/unused-var/foo.js new file mode 100644 index 00000000000..3b60a87fdc7 --- /dev/null +++ b/test/form/unused-var/foo.js @@ -0,0 +1,6 @@ +var foo = 'lol'; +var bar = 'wut'; + +var baz = bar || foo; + +export { foo }; diff --git a/test/form/unused-var/main.js b/test/form/unused-var/main.js new file mode 100644 index 00000000000..1b3e4096d6f --- /dev/null +++ b/test/form/unused-var/main.js @@ -0,0 +1,2 @@ +import { foo } from './foo.js'; +console.log( foo ); diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/es6.js b/test/form/whitespace-around-namespace-member-expression/_expected/es.js similarity index 100% rename from test/form/whitespace-around-namespace-member-expression/_expected/es6.js rename to test/form/whitespace-around-namespace-member-expression/_expected/es.js diff --git a/test/form/whitespace-around-namespace-member-expression/_expected/umd.js b/test/form/whitespace-around-namespace-member-expression/_expected/umd.js index ae6ce6feefa..e260775a114 100644 --- a/test/form/whitespace-around-namespace-member-expression/_expected/umd.js +++ b/test/form/whitespace-around-namespace-member-expression/_expected/umd.js @@ -2,7 +2,7 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory() : typeof define === 'function' && define.amd ? define(factory) : (factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; function yar() { console.log('yar?'); @@ -10,4 +10,4 @@ yar(); -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/test/function/adds-semicolons-if-necessary-b/_config.js b/test/function/adds-semicolons-if-necessary-b/_config.js new file mode 100644 index 00000000000..bb17123ec79 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'adds semi-colons if necessary' +}; diff --git a/test/function/adds-semicolons-if-necessary-b/foo.js b/test/function/adds-semicolons-if-necessary-b/foo.js new file mode 100644 index 00000000000..b2602d2645e --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/foo.js @@ -0,0 +1 @@ +assert.ok( true ) diff --git a/test/function/adds-semicolons-if-necessary-b/main.js b/test/function/adds-semicolons-if-necessary-b/main.js new file mode 100644 index 00000000000..c6ddba445ce --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-b/main.js @@ -0,0 +1,3 @@ +import './foo.js'; + +(function bar() {})(); diff --git a/test/function/adds-semicolons-if-necessary-c/_config.js b/test/function/adds-semicolons-if-necessary-c/_config.js new file mode 100644 index 00000000000..bb17123ec79 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-c/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'adds semi-colons if necessary' +}; diff --git a/test/function/adds-semicolons-if-necessary-c/foo.js b/test/function/adds-semicolons-if-necessary-c/foo.js new file mode 100644 index 00000000000..7dc88337ff1 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-c/foo.js @@ -0,0 +1,3 @@ +export default function () { + return 42; +} diff --git a/test/function/adds-semicolons-if-necessary-c/main.js b/test/function/adds-semicolons-if-necessary-c/main.js new file mode 100644 index 00000000000..ae0bdb21e50 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary-c/main.js @@ -0,0 +1,7 @@ +import foo from './foo.js'; + +(function bar() { + assert.ok( true ); +})(); + +assert.equal( foo(), 42 ); diff --git a/test/function/adds-semicolons-if-necessary/_config.js b/test/function/adds-semicolons-if-necessary/_config.js new file mode 100644 index 00000000000..bb17123ec79 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'adds semi-colons if necessary' +}; diff --git a/test/function/adds-semicolons-if-necessary/foo.js b/test/function/adds-semicolons-if-necessary/foo.js new file mode 100644 index 00000000000..14d0105c721 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/foo.js @@ -0,0 +1,3 @@ +export var foo = function () { + return 42; +} diff --git a/test/function/adds-semicolons-if-necessary/main.js b/test/function/adds-semicolons-if-necessary/main.js new file mode 100644 index 00000000000..2a031e5db48 --- /dev/null +++ b/test/function/adds-semicolons-if-necessary/main.js @@ -0,0 +1,7 @@ +import { foo } from './foo.js'; + +(function bar() { + assert.ok( true ); +})(); + +assert.equal( foo(), 42 ); diff --git a/test/function/allow-reserved/_config.js b/test/function/allow-reserved/_config.js new file mode 100644 index 00000000000..63f2a11c03f --- /dev/null +++ b/test/function/allow-reserved/_config.js @@ -0,0 +1,8 @@ +module.exports = { + description: 'allow reserved identifiers via custom acorn options', + options: { + acorn: { + allowReserved: true + } + } +}; diff --git a/test/function/allow-reserved/main.js b/test/function/allow-reserved/main.js new file mode 100644 index 00000000000..547a9a5311d --- /dev/null +++ b/test/function/allow-reserved/main.js @@ -0,0 +1,2 @@ +var x = function await () {} +assert.equal( x.name, 'await' ); diff --git a/test/function/assignment-patterns/_config.js b/test/function/assignment-patterns/_config.js index d4afdc36273..e21b4a0c7fb 100644 --- a/test/function/assignment-patterns/_config.js +++ b/test/function/assignment-patterns/_config.js @@ -1,4 +1,4 @@ module.exports = { description: 'allows reassigments to default parameters that shadow imports', - babel: true + buble: true }; diff --git a/test/function/braceless-arrow-function-returning-function/_config.js b/test/function/braceless-arrow-function-returning-function/_config.js new file mode 100644 index 00000000000..3204f3c6b30 --- /dev/null +++ b/test/function/braceless-arrow-function-returning-function/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'arrow function without braces returning a function (#1032)', + buble: true +}; diff --git a/test/function/braceless-arrow-function-returning-function/main.js b/test/function/braceless-arrow-function-returning-function/main.js new file mode 100644 index 00000000000..637a0eeb468 --- /dev/null +++ b/test/function/braceless-arrow-function-returning-function/main.js @@ -0,0 +1,7 @@ +const f = (a) => (b) => { return a * b } +function ff (a) { return f(a) } +assert.equal( ff(2)(3), 6 ); + +const g = (a) => { return (b) => { return a - b } } +function gg (a) { return g(a) } +assert.equal( gg(2)(3), -1 ); diff --git a/test/function/call-external-function/_config.js b/test/function/call-external-function/_config.js new file mode 100644 index 00000000000..96943141304 --- /dev/null +++ b/test/function/call-external-function/_config.js @@ -0,0 +1,11 @@ +module.exports = { + description: 'handles call of aliased external function (#957)', + warnings () {}, + context: { + require ( id ) { + if ( id === 'foo' ) { + return () => 42; + } + } + } +}; diff --git a/test/function/call-external-function/foo.js b/test/function/call-external-function/foo.js new file mode 100644 index 00000000000..a430876b7f3 --- /dev/null +++ b/test/function/call-external-function/foo.js @@ -0,0 +1,2 @@ +import foo from 'foo'; +export default foo; diff --git a/test/function/call-external-function/main.js b/test/function/call-external-function/main.js new file mode 100644 index 00000000000..766cb6ff2ed --- /dev/null +++ b/test/function/call-external-function/main.js @@ -0,0 +1,4 @@ +import foo_ from './foo.js'; + +var foo = foo_; +assert.equal( foo(), 42 ); diff --git a/test/function/check-resolve-for-entry/_config.js b/test/function/check-resolve-for-entry/_config.js new file mode 100644 index 00000000000..a06632dde8b --- /dev/null +++ b/test/function/check-resolve-for-entry/_config.js @@ -0,0 +1,11 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'checks that entry is resolved', + options: { + entry: '/not/a/path/that/actually/really/exists' + }, + error: function ( err ) { + assert.ok( /Could not resolve entry/.test( err.message ) ); + } +}; diff --git a/test/function/class-methods-not-renamed/_config.js b/test/function/class-methods-not-renamed/_config.js index 0b31fd0d3d7..99bfc6e77a6 100644 --- a/test/function/class-methods-not-renamed/_config.js +++ b/test/function/class-methods-not-renamed/_config.js @@ -3,5 +3,5 @@ module.exports = { options: { external: [ 'path' ] }, - babel: true + buble: true }; diff --git a/test/function/configure-relative-external-module/_config.js b/test/function/configure-relative-external-module/_config.js index bbcebcfef10..58e154c1266 100644 --- a/test/function/configure-relative-external-module/_config.js +++ b/test/function/configure-relative-external-module/_config.js @@ -11,7 +11,7 @@ module.exports = { external: [ path.join( __dirname, './nonexistent-relative-dependency.js') ] }, context: { - require: function() { + require: function () { return mockedValue; } }, diff --git a/test/function/confused-default-identifier/_config.js b/test/function/confused-default-identifier/_config.js index 1b0bbf2445b..3d2e2532960 100644 --- a/test/function/confused-default-identifier/_config.js +++ b/test/function/confused-default-identifier/_config.js @@ -1,5 +1,3 @@ -var assert = require( 'assert' ); - module.exports = { description: 'Rollup should not get confused and allow "default" as an identifier name', warnings: function () {} // suppress diff --git a/test/function/consistent-renaming-b/_config.js b/test/function/consistent-renaming-b/_config.js index 1b8b173386e..f1b3ee69460 100644 --- a/test/function/consistent-renaming-b/_config.js +++ b/test/function/consistent-renaming-b/_config.js @@ -1,3 +1,3 @@ module.exports = { description: 'consistent renaming test b' -}; \ No newline at end of file +}; diff --git a/test/function/consistent-renaming-b/altdir/two.js b/test/function/consistent-renaming-b/altdir/two.js index b97aab54ff9..bd84240303b 100644 --- a/test/function/consistent-renaming-b/altdir/two.js +++ b/test/function/consistent-renaming-b/altdir/two.js @@ -1,5 +1,6 @@ function two () { + // imported as _two by subdir/two.js return 2; } -export { two }; \ No newline at end of file +export { two }; diff --git a/test/function/consistent-renaming-b/subdir/one.js b/test/function/consistent-renaming-b/subdir/one.js index 0d1985f0d97..26a060ca6c7 100644 --- a/test/function/consistent-renaming-b/subdir/one.js +++ b/test/function/consistent-renaming-b/subdir/one.js @@ -1,5 +1,5 @@ import { two } from '../altdir/two'; export default function one () { - return two() - 1; + return two() - 1; } diff --git a/test/function/consistent-renaming-b/subdir/two.js b/test/function/consistent-renaming-b/subdir/two.js index b0004b7ad48..c31c2ff79a4 100644 --- a/test/function/consistent-renaming-b/subdir/two.js +++ b/test/function/consistent-renaming-b/subdir/two.js @@ -1,5 +1,6 @@ import { two as _two } from '../altdir/two'; export default function two () { - return _two(); + // imported as Two by main.js + return _two(); } diff --git a/test/function/consistent-renaming-e/_config.js b/test/function/consistent-renaming-e/_config.js index 4fa443e0d43..e93e16a086f 100644 --- a/test/function/consistent-renaming-e/_config.js +++ b/test/function/consistent-renaming-e/_config.js @@ -1,3 +1,3 @@ module.exports = { description: 'consistent renaming test e' -} \ No newline at end of file +}; \ No newline at end of file diff --git a/test/function/custom-path-resolver-on-entry/_config.js b/test/function/custom-path-resolver-on-entry/_config.js index 0766b6cf313..b41282b8971 100644 --- a/test/function/custom-path-resolver-on-entry/_config.js +++ b/test/function/custom-path-resolver-on-entry/_config.js @@ -8,7 +8,6 @@ var cachedModules = { module.exports = { description: 'applies custom resolver to entry point', - //solo: true, options: { plugins: [{ resolveId: function ( importee, importer ) { diff --git a/test/function/custom-path-resolver-plural-b/_config.js b/test/function/custom-path-resolver-plural-b/_config.js index 05cf37acb9d..cb2da0c701a 100644 --- a/test/function/custom-path-resolver-plural-b/_config.js +++ b/test/function/custom-path-resolver-plural-b/_config.js @@ -9,7 +9,7 @@ module.exports = { throw new Error( 'nope' ); }, load: function ( id ) { - if ( id === 'main' ) return 'assert.ok( false );' + if ( id === 'main' ) return 'assert.ok( false );'; } }, { diff --git a/test/function/cycles-pathological-2/_config.js b/test/function/cycles-pathological-2/_config.js new file mode 100644 index 00000000000..87ba7d6c44c --- /dev/null +++ b/test/function/cycles-pathological-2/_config.js @@ -0,0 +1,11 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'resolves even more pathological cyclical dependencies gracefully', + buble: true, + options: { + onwarn: function ( message ) { + assert.ok( /unable to evaluate without/.test( message ) ); + } + } +}; diff --git a/test/function/cycles-pathological-2/b.js b/test/function/cycles-pathological-2/b.js new file mode 100644 index 00000000000..1a4723ba370 --- /dev/null +++ b/test/function/cycles-pathological-2/b.js @@ -0,0 +1,11 @@ +import { a, av } from './main'; +import { d, dv } from './d'; +import { c, cv } from './c'; + +export function b() { + a(av); + d(dv); + c(cv); +}; + +export const bv = av + dv + cv; diff --git a/test/function/cycles-pathological-2/c.js b/test/function/cycles-pathological-2/c.js new file mode 100644 index 00000000000..da8f42edae6 --- /dev/null +++ b/test/function/cycles-pathological-2/c.js @@ -0,0 +1,9 @@ +import { b, bv } from './b'; +import { a, av } from './main'; + +export function c() { + a(av); + b(bv); +}; + +export const cv = av + bv; diff --git a/test/function/cycles-pathological-2/d.js b/test/function/cycles-pathological-2/d.js new file mode 100644 index 00000000000..b7d9f07968f --- /dev/null +++ b/test/function/cycles-pathological-2/d.js @@ -0,0 +1,7 @@ +import { c, cv } from './c'; + +export function d() { + c(cv); +}; + +export const dv = cv; diff --git a/test/function/cycles-pathological-2/main.js b/test/function/cycles-pathological-2/main.js new file mode 100644 index 00000000000..06bcc6e3e97 --- /dev/null +++ b/test/function/cycles-pathological-2/main.js @@ -0,0 +1,11 @@ +import { b, bv } from './b'; +import { d, dv } from './d'; +import { c, cv } from './c'; + +export function a() { + b(bv); + d(dv); + c(cv); +}; + +export const av = bv + dv + cv; diff --git a/test/function/cycles-pathological-3/_config.js b/test/function/cycles-pathological-3/_config.js new file mode 100644 index 00000000000..155e2f69c3d --- /dev/null +++ b/test/function/cycles-pathological-3/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'resolves more pathological cyclical dependencies gracefully' +}; diff --git a/test/function/cycles-pathological-3/a.js b/test/function/cycles-pathological-3/a.js new file mode 100644 index 00000000000..c77b86b6e14 --- /dev/null +++ b/test/function/cycles-pathological-3/a.js @@ -0,0 +1,3 @@ +import * as x from "./x.a.js"; +x.b(); +x.c(); \ No newline at end of file diff --git a/test/function/cycles-pathological-3/b.js b/test/function/cycles-pathological-3/b.js new file mode 100644 index 00000000000..b93201cc1b1 --- /dev/null +++ b/test/function/cycles-pathological-3/b.js @@ -0,0 +1,3 @@ +import * as x from "./x.b.js"; + +export function b() {} \ No newline at end of file diff --git a/test/function/cycles-pathological-3/c.js b/test/function/cycles-pathological-3/c.js new file mode 100644 index 00000000000..60a9826beae --- /dev/null +++ b/test/function/cycles-pathological-3/c.js @@ -0,0 +1,3 @@ +import * as x from "./x.c.js"; + +export function c() {} \ No newline at end of file diff --git a/test/function/cycles-pathological-3/main.js b/test/function/cycles-pathological-3/main.js new file mode 100644 index 00000000000..158061194e1 --- /dev/null +++ b/test/function/cycles-pathological-3/main.js @@ -0,0 +1 @@ +import './a.js'; \ No newline at end of file diff --git a/test/function/cycles-pathological-3/x.a.js b/test/function/cycles-pathological-3/x.a.js new file mode 100644 index 00000000000..e73df119765 --- /dev/null +++ b/test/function/cycles-pathological-3/x.a.js @@ -0,0 +1,2 @@ +export * from "./b.js"; +export * from "./c.js"; \ No newline at end of file diff --git a/test/function/cycles-pathological-3/x.b.js b/test/function/cycles-pathological-3/x.b.js new file mode 100644 index 00000000000..c3e2ed3d6d5 --- /dev/null +++ b/test/function/cycles-pathological-3/x.b.js @@ -0,0 +1,2 @@ +export * from "./a.js"; +export * from "./c.js"; \ No newline at end of file diff --git a/test/function/cycles-pathological-3/x.c.js b/test/function/cycles-pathological-3/x.c.js new file mode 100644 index 00000000000..2f495917b9b --- /dev/null +++ b/test/function/cycles-pathological-3/x.c.js @@ -0,0 +1,2 @@ +export * from "./a.js"; +export * from "./b.js"; \ No newline at end of file diff --git a/test/function/cycles-pathological/_config.js b/test/function/cycles-pathological/_config.js index 4e939af2234..f6d85267c37 100644 --- a/test/function/cycles-pathological/_config.js +++ b/test/function/cycles-pathological/_config.js @@ -1,17 +1,11 @@ var assert = require( 'assert' ); -var warned; - module.exports = { + skip: true, description: 'resolves pathological cyclical dependencies gracefully', - babel: true, - options: { - onwarn: function ( message ) { - assert.ok( /Module .+B\.js may be unable to evaluate without .+A\.js, but is included first due to a cyclical dependency. Consider swapping the import statements in .+main\.js to ensure correct ordering/.test( message ) ); - warned = true; - } - }, - runtimeError: function () { - assert.ok( warned ); + buble: true, + warnings: warnings => { + assert.equal( warnings.length, warnings ); + assert.ok( /Module .+B\.js may be unable to evaluate without .+A\.js, but is included first due to a cyclical dependency. Consider swapping the import statements in .+main\.js to ensure correct ordering/.test( warnings[0] ) ); } }; diff --git a/test/function/deconflicts-classes/_config.js b/test/function/deconflicts-classes/_config.js new file mode 100644 index 00000000000..633aaccce69 --- /dev/null +++ b/test/function/deconflicts-classes/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'deconflicts top-level classes', + buble: true +}; diff --git a/test/function/deconflicts-classes/a.js b/test/function/deconflicts-classes/a.js new file mode 100644 index 00000000000..8f88528bee8 --- /dev/null +++ b/test/function/deconflicts-classes/a.js @@ -0,0 +1,2 @@ +var Foo = function Foo () {}; +export { Foo }; diff --git a/test/function/deconflicts-classes/b.js b/test/function/deconflicts-classes/b.js new file mode 100644 index 00000000000..6f6f410d79e --- /dev/null +++ b/test/function/deconflicts-classes/b.js @@ -0,0 +1,2 @@ +class Foo {}; +export { Foo }; diff --git a/test/function/deconflicts-classes/main.js b/test/function/deconflicts-classes/main.js new file mode 100644 index 00000000000..89ff7de79d1 --- /dev/null +++ b/test/function/deconflicts-classes/main.js @@ -0,0 +1,4 @@ +import { Foo as A } from './a.js'; +import { Foo as B } from './b.js'; + +assert.notEqual( A, B ); diff --git a/test/function/deconstructed-exported-vars/_config.js b/test/function/deconstructed-exported-vars/_config.js index 04513420c84..a210a0f5aba 100644 --- a/test/function/deconstructed-exported-vars/_config.js +++ b/test/function/deconstructed-exported-vars/_config.js @@ -2,7 +2,7 @@ var assert = require( 'assert' ); module.exports = { description: 'allows destructuring in exported variable declarations, synthetic or otherwise', - babel: true, + buble: true, exports: function ( exports ) { assert.equal( exports.a, 1 ); assert.equal( exports.d, 4 ); diff --git a/test/function/default-export-is-not-bound-b/_config.js b/test/function/default-export-is-not-bound-b/_config.js index 92debd4b6a9..a1aed25945f 100644 --- a/test/function/default-export-is-not-bound-b/_config.js +++ b/test/function/default-export-is-not-bound-b/_config.js @@ -4,6 +4,5 @@ module.exports = { description: 'does not move default export statement above earlier statements', exports: function ( exports ) { assert.equal( exports.bar, 42 ); - }, - // solo: true + } }; diff --git a/test/function/default-not-reexported/_config.js b/test/function/default-not-reexported/_config.js new file mode 100644 index 00000000000..4280924d635 --- /dev/null +++ b/test/function/default-not-reexported/_config.js @@ -0,0 +1,8 @@ +const assert = require( 'assert' ); + +module.exports = { + description: 'default export is not re-exported with export *', + error ( error ) { + assert.equal( error.message, `'default' is not exported by foo.js (imported by main.js). For help fixing this error see https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module` ); + } +}; diff --git a/test/function/default-not-reexported/bar.js b/test/function/default-not-reexported/bar.js new file mode 100644 index 00000000000..f3f654724fa --- /dev/null +++ b/test/function/default-not-reexported/bar.js @@ -0,0 +1,2 @@ +export const named = 42; +export default 'should not be re-exported'; diff --git a/test/function/default-not-reexported/foo.js b/test/function/default-not-reexported/foo.js new file mode 100644 index 00000000000..a8e4f7c1e7b --- /dev/null +++ b/test/function/default-not-reexported/foo.js @@ -0,0 +1 @@ +export * from './bar.js'; diff --git a/test/function/default-not-reexported/main.js b/test/function/default-not-reexported/main.js new file mode 100644 index 00000000000..6aa8dfa22b5 --- /dev/null +++ b/test/function/default-not-reexported/main.js @@ -0,0 +1,3 @@ +import def from './foo.js'; + +console.log( def ); diff --git a/test/function/delete/_config.js b/test/function/delete/_config.js index 4a5902cbd07..3495183e618 100644 --- a/test/function/delete/_config.js +++ b/test/function/delete/_config.js @@ -1,3 +1,3 @@ module.exports = { - description: '`delete` operator at the top level is preserved' + description: '`delete` operator at the top level is preserved' }; diff --git a/test/function/does-not-mangle-entry-point/_config.js b/test/function/does-not-mangle-entry-point/_config.js new file mode 100644 index 00000000000..ef24d0113f7 --- /dev/null +++ b/test/function/does-not-mangle-entry-point/_config.js @@ -0,0 +1,24 @@ +var assert = require( 'assert' ); + +var modules = { + 'x\\y': 'export default 42;', + 'x/y': 'export default 24;' +}; + +module.exports = { + description: 'does not mangle entry point', + options: { + entry: 'x\\y', + plugins: [{ + resolveId: function ( importee ) { + return importee; + }, + load: function ( moduleId ) { + return modules[ moduleId ]; + } + }] + }, + exports: function ( exports ) { + assert.equal( exports, 42 ); + } +}; diff --git a/test/function/double-default-export/_config.js b/test/function/double-default-export/_config.js index 26e86e7e679..d5f525428a3 100644 --- a/test/function/double-default-export/_config.js +++ b/test/function/double-default-export/_config.js @@ -1,8 +1,9 @@ +const path = require( 'path' ); const assert = require( 'assert' ); module.exports = { description: 'throws on double default exports', error: err => { - assert.equal( err.message, 'A module can only have one default export' ); + assert.equal( err.message, `Duplicate export 'default' (2:7) in ${path.resolve(__dirname, 'foo.js')}` ); } }; diff --git a/test/function/double-named-export-from/_config.js b/test/function/double-named-export-from/_config.js new file mode 100644 index 00000000000..b3885d25b8e --- /dev/null +++ b/test/function/double-named-export-from/_config.js @@ -0,0 +1,13 @@ +const { resolve } = require('path'); +const assert = require( 'assert' ); + +const r = path => resolve( __dirname, path ); + +module.exports = { + description: 'throws on duplicate export * from', + warnings ( warnings ) { + assert.deepEqual( warnings, [ + `Conflicting namespaces: ${r('main.js')} re-exports 'foo' from both ${r('foo.js')} (will be ignored) and ${r('deep.js')}.` + ]); + } +}; diff --git a/test/function/double-named-export-from/bar.js b/test/function/double-named-export-from/bar.js new file mode 100644 index 00000000000..0dfd7e92d73 --- /dev/null +++ b/test/function/double-named-export-from/bar.js @@ -0,0 +1 @@ +export * from './deep.js'; \ No newline at end of file diff --git a/test/function/double-named-export-from/deep.js b/test/function/double-named-export-from/deep.js new file mode 100644 index 00000000000..a7b877b9002 --- /dev/null +++ b/test/function/double-named-export-from/deep.js @@ -0,0 +1 @@ +export var foo = 2; \ No newline at end of file diff --git a/test/function/double-named-export-from/foo.js b/test/function/double-named-export-from/foo.js new file mode 100644 index 00000000000..467f528ee3a --- /dev/null +++ b/test/function/double-named-export-from/foo.js @@ -0,0 +1 @@ +export var foo = 1; \ No newline at end of file diff --git a/test/function/double-named-export-from/main.js b/test/function/double-named-export-from/main.js new file mode 100644 index 00000000000..ae6aade26bd --- /dev/null +++ b/test/function/double-named-export-from/main.js @@ -0,0 +1,2 @@ +export * from './foo.js'; +export * from './bar.js'; \ No newline at end of file diff --git a/test/function/double-named-export/_config.js b/test/function/double-named-export/_config.js index 577b4218387..169ce76b965 100644 --- a/test/function/double-named-export/_config.js +++ b/test/function/double-named-export/_config.js @@ -1,8 +1,9 @@ +const path = require( 'path' ); const assert = require( 'assert' ); module.exports = { description: 'throws on duplicate named exports', error: err => { - assert.equal( err.message, `A module cannot have multiple exports with the same name ('foo')` ); + assert.equal( err.message, `Duplicate export 'foo' (3:9) in ${path.resolve(__dirname, 'foo.js')}` ); } }; diff --git a/test/function/double-named-reexport/_config.js b/test/function/double-named-reexport/_config.js index 577b4218387..169ce76b965 100644 --- a/test/function/double-named-reexport/_config.js +++ b/test/function/double-named-reexport/_config.js @@ -1,8 +1,9 @@ +const path = require( 'path' ); const assert = require( 'assert' ); module.exports = { description: 'throws on duplicate named exports', error: err => { - assert.equal( err.message, `A module cannot have multiple exports with the same name ('foo')` ); + assert.equal( err.message, `Duplicate export 'foo' (3:9) in ${path.resolve(__dirname, 'foo.js')}` ); } }; diff --git a/test/function/export-all-from-external/_config.js b/test/function/export-all-from-external/_config.js new file mode 100644 index 00000000000..4f880def711 --- /dev/null +++ b/test/function/export-all-from-external/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'allows `export *` from external module, internally', + options: { + external: [ 'path' ] + } +}; diff --git a/test/function/export-all-from-external/main.js b/test/function/export-all-from-external/main.js new file mode 100644 index 00000000000..3708aaa1676 --- /dev/null +++ b/test/function/export-all-from-external/main.js @@ -0,0 +1,4 @@ +import { dirname, isRelative } from './path-plus.js'; + +assert.equal( dirname( 'foo/bar' ), 'foo' ); +assert.ok( isRelative( './foo' ) ); diff --git a/test/function/export-all-from-external/path-plus.js b/test/function/export-all-from-external/path-plus.js new file mode 100644 index 00000000000..b2b80347c68 --- /dev/null +++ b/test/function/export-all-from-external/path-plus.js @@ -0,0 +1,5 @@ +export * from 'path'; + +export function isRelative ( path ) { + return path[0] === '.'; +} diff --git a/test/function/export-as-default/_config.js b/test/function/export-as-default/_config.js new file mode 100644 index 00000000000..d5de42561a5 --- /dev/null +++ b/test/function/export-as-default/_config.js @@ -0,0 +1,5 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'export { foo as default } does not create a live binding' +}; diff --git a/test/function/export-as-default/foo.js b/test/function/export-as-default/foo.js new file mode 100644 index 00000000000..3c5423077c1 --- /dev/null +++ b/test/function/export-as-default/foo.js @@ -0,0 +1,3 @@ +var foo = 1; +export { foo as default }; +foo = 2; diff --git a/test/function/export-as-default/main.js b/test/function/export-as-default/main.js new file mode 100644 index 00000000000..e2b1718ff8d --- /dev/null +++ b/test/function/export-as-default/main.js @@ -0,0 +1,3 @@ +import foo from './foo.js'; + +assert.equal( foo, 1 ); diff --git a/test/function/export-as/_config.js b/test/function/export-as/_config.js index 3171eedd925..ed89b856725 100644 --- a/test/function/export-as/_config.js +++ b/test/function/export-as/_config.js @@ -1,5 +1,3 @@ -var assert = require( 'assert' ); - module.exports = { description: 'allows export { x as y }' }; diff --git a/test/function/export-default-anonymous-function/_config.js b/test/function/export-default-anonymous-function/_config.js index 3cb321fb0a1..245bdaf7d18 100644 --- a/test/function/export-default-anonymous-function/_config.js +++ b/test/function/export-default-anonymous-function/_config.js @@ -9,7 +9,6 @@ module.exports = { return path.basename( importee ).replace( /\..+/, '' ); }, load: function ( id ) { - console.log( 'id', id ) return fs.readFileSync( path.join( __dirname, id + '.js' ), 'utf-8' ); } }] diff --git a/test/function/export-destruction/_config.js b/test/function/export-destruction/_config.js index 263c8d1bd11..1d77b9b10d7 100644 --- a/test/function/export-destruction/_config.js +++ b/test/function/export-destruction/_config.js @@ -2,7 +2,7 @@ var assert = require( 'assert' ); module.exports = { description: 'handle destruction patterns in export declarations', - babel: true, + buble: true, exports: function ( exports ) { assert.deepEqual( Object.keys( exports ), [ 'baz', 'quux' ] ); diff --git a/test/function/export-from-no-local-binding/_config.js b/test/function/export-from-no-local-binding/_config.js index 333c68b082c..7500be3ac77 100644 --- a/test/function/export-from-no-local-binding/_config.js +++ b/test/function/export-from-no-local-binding/_config.js @@ -1,5 +1,3 @@ -var assert = require( 'assert' ); - module.exports = { description: 'export from does not create a local binding' }; diff --git a/test/function/export-two-ways-default-b/_config.js b/test/function/export-two-ways-default-b/_config.js new file mode 100644 index 00000000000..4fa48888100 --- /dev/null +++ b/test/function/export-two-ways-default-b/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'side-effects are preserved if subject is exported in multiple ways, even if default export has no direct link to original (#733)' +}; diff --git a/test/function/export-two-ways-default-b/bar.js b/test/function/export-two-ways-default-b/bar.js new file mode 100644 index 00000000000..1ec6df4fc83 --- /dev/null +++ b/test/function/export-two-ways-default-b/bar.js @@ -0,0 +1,6 @@ +import { X } from './x.js'; + +X.prototype.bar = function () { + this.didBar = true; + return this; +}; diff --git a/test/function/export-two-ways-default-b/foo.js b/test/function/export-two-ways-default-b/foo.js new file mode 100644 index 00000000000..8c72ffc62fc --- /dev/null +++ b/test/function/export-two-ways-default-b/foo.js @@ -0,0 +1,8 @@ +export function X () {} + +X.prototype.foo = function () { + this.didFoo = true; + return this; +}; + +export default ( false || X ); diff --git a/test/function/export-two-ways-default-b/main.js b/test/function/export-two-ways-default-b/main.js new file mode 100644 index 00000000000..9b7c1d76ee4 --- /dev/null +++ b/test/function/export-two-ways-default-b/main.js @@ -0,0 +1,6 @@ +import { x } from './x.js'; +import './bar.js'; + +var result = x().foo().bar(); +assert.ok( result.didFoo ); +assert.ok( result.didBar ); diff --git a/test/function/export-two-ways-default-b/x.js b/test/function/export-two-ways-default-b/x.js new file mode 100644 index 00000000000..dcbe278cf12 --- /dev/null +++ b/test/function/export-two-ways-default-b/x.js @@ -0,0 +1,6 @@ +export { default as X } from './foo.js'; +import { X } from './foo.js'; + +export function x () { + return new X(); +} diff --git a/test/function/export-two-ways-default/_config.js b/test/function/export-two-ways-default/_config.js new file mode 100644 index 00000000000..88b207f4bca --- /dev/null +++ b/test/function/export-two-ways-default/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'side-effects are preserved if subject is exported in multiple ways (#733)' +}; diff --git a/test/function/export-two-ways-default/bar.js b/test/function/export-two-ways-default/bar.js new file mode 100644 index 00000000000..1ec6df4fc83 --- /dev/null +++ b/test/function/export-two-ways-default/bar.js @@ -0,0 +1,6 @@ +import { X } from './x.js'; + +X.prototype.bar = function () { + this.didBar = true; + return this; +}; diff --git a/test/function/export-two-ways-default/foo.js b/test/function/export-two-ways-default/foo.js new file mode 100644 index 00000000000..499b3326ab2 --- /dev/null +++ b/test/function/export-two-ways-default/foo.js @@ -0,0 +1,8 @@ +export function X () {} + +X.prototype.foo = function () { + this.didFoo = true; + return this; +}; + +export default X; diff --git a/test/function/export-two-ways-default/main.js b/test/function/export-two-ways-default/main.js new file mode 100644 index 00000000000..9b7c1d76ee4 --- /dev/null +++ b/test/function/export-two-ways-default/main.js @@ -0,0 +1,6 @@ +import { x } from './x.js'; +import './bar.js'; + +var result = x().foo().bar(); +assert.ok( result.didFoo ); +assert.ok( result.didBar ); diff --git a/test/function/export-two-ways-default/x.js b/test/function/export-two-ways-default/x.js new file mode 100644 index 00000000000..dcbe278cf12 --- /dev/null +++ b/test/function/export-two-ways-default/x.js @@ -0,0 +1,6 @@ +export { default as X } from './foo.js'; +import { X } from './foo.js'; + +export function x () { + return new X(); +} diff --git a/test/function/has-resolved-ids/_config.js b/test/function/has-resolved-ids/_config.js new file mode 100644 index 00000000000..b2f3e1af759 --- /dev/null +++ b/test/function/has-resolved-ids/_config.js @@ -0,0 +1,13 @@ +var path = require( 'path' ); +var assert = require( 'assert' ); + +module.exports = { + description: 'user-facing bundle has resolvedIds map in every modules', + bundle: function ( bundle ) { + assert.ok( bundle.modules[ 0 ].resolvedIds ); + assert.ok( bundle.modules[ 1 ].resolvedIds ); + assert.equal( Object.keys( bundle.modules[ 0 ].resolvedIds ).length, 0 ); + assert.equal( Object.keys( bundle.modules[ 1 ].resolvedIds ).length, 1 ); + assert.equal( bundle.modules[ 1 ].resolvedIds[ './foo' ], path.resolve( __dirname, 'foo.js' ) ); + } +}; diff --git a/test/function/has-resolved-ids/foo.js b/test/function/has-resolved-ids/foo.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/function/has-resolved-ids/foo.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/function/has-resolved-ids/main.js b/test/function/has-resolved-ids/main.js new file mode 100644 index 00000000000..3206f53821c --- /dev/null +++ b/test/function/has-resolved-ids/main.js @@ -0,0 +1,2 @@ +import foo from './foo'; +assert.equal( foo, 42 ); diff --git a/test/function/identifiers-in-template-literals/_config.js b/test/function/identifiers-in-template-literals/_config.js new file mode 100644 index 00000000000..51b503d3466 --- /dev/null +++ b/test/function/identifiers-in-template-literals/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'identifiers in template literals are rendered correctly', + buble: true +}; diff --git a/test/function/identifiers-in-template-literals/a.js b/test/function/identifiers-in-template-literals/a.js new file mode 100644 index 00000000000..26a1db8a221 --- /dev/null +++ b/test/function/identifiers-in-template-literals/a.js @@ -0,0 +1,7 @@ +function x ( keypath ) { + return 'a'; +} + +export default function a () { + return x(); +} diff --git a/test/function/identifiers-in-template-literals/b.js b/test/function/identifiers-in-template-literals/b.js new file mode 100644 index 00000000000..7511028ed73 --- /dev/null +++ b/test/function/identifiers-in-template-literals/b.js @@ -0,0 +1,7 @@ +function x ( name ) { + return 'b'; +} + +export default function b () { + return `${x()}`; +} diff --git a/test/function/identifiers-in-template-literals/main.js b/test/function/identifiers-in-template-literals/main.js new file mode 100644 index 00000000000..eedb4fb9c2c --- /dev/null +++ b/test/function/identifiers-in-template-literals/main.js @@ -0,0 +1,5 @@ +import a from './a.js'; +import b from './b.js'; + +assert.equal( a(), 'a' ); +assert.equal( b(), 'b' ); diff --git a/test/function/if-statement-with-assignment/_config.js b/test/function/if-statement-with-assignment/_config.js new file mode 100644 index 00000000000..6c573d5e7bf --- /dev/null +++ b/test/function/if-statement-with-assignment/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'update assignments to names are preserved (#930)' +}; diff --git a/test/function/if-statement-with-assignment/main.js b/test/function/if-statement-with-assignment/main.js new file mode 100644 index 00000000000..e885c22faaa --- /dev/null +++ b/test/function/if-statement-with-assignment/main.js @@ -0,0 +1,6 @@ +var result = 0; +if ( Math.random() <= 1 ) { + if ( Math.random() <= 1 ) result += 1; +} + +assert.equal( result, 1 ); diff --git a/test/function/if-statement-with-false-condition/_config.js b/test/function/if-statement-with-false-condition/_config.js new file mode 100644 index 00000000000..b7eda7a022f --- /dev/null +++ b/test/function/if-statement-with-false-condition/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'if statements with false condition do not break render (#973)' +}; diff --git a/test/function/if-statement-with-false-condition/main.js b/test/function/if-statement-with-false-condition/main.js new file mode 100644 index 00000000000..59bf4fdf166 --- /dev/null +++ b/test/function/if-statement-with-false-condition/main.js @@ -0,0 +1,47 @@ +export function whileIf(x) { + while (x) + if (false) + // replaced with {} + x = 0; +} + +export function whileBlockIf(x) { + while (x) { + if (false) + // removed + x = 0; + } +} + +export function ifWhile(x) { + if (x) + while (false) + // not optimized + x = 0; +} + +export function ifFalseElse(x) { + if (false) { + // removed + } else { + // kept + } +} + +export function elseIfFalse(x) { + if (x) { + // kept + } else if (false) { + // replaced with {} + } +} + +export function elseIfFalseElse(x) { + if (x) { + // kept + } else if (false) { + // removed + } else { + // kept + } +} diff --git a/test/function/if-statement-with-update/_config.js b/test/function/if-statement-with-update/_config.js new file mode 100644 index 00000000000..8601e12f716 --- /dev/null +++ b/test/function/if-statement-with-update/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'updates to names are preserved (#930)' +}; diff --git a/test/function/if-statement-with-update/main.js b/test/function/if-statement-with-update/main.js new file mode 100644 index 00000000000..7ab305586d0 --- /dev/null +++ b/test/function/if-statement-with-update/main.js @@ -0,0 +1,6 @@ +var result = 0; +if ( Math.random() <= 1 ) { + if ( Math.random() <= 1 ) ++result; +} + +assert.equal( result, 1 ); diff --git a/test/function/iife-strong-dependencies/_config.js b/test/function/iife-strong-dependencies/_config.js index f1d7ee1af55..110fa77440a 100644 --- a/test/function/iife-strong-dependencies/_config.js +++ b/test/function/iife-strong-dependencies/_config.js @@ -1,16 +1,10 @@ var assert = require( 'assert' ); -var warned; - module.exports = { + skip: true, description: 'does not treat references inside IIFEs as weak dependencies', // edge case encountered in THREE.js codebase - options: { - onwarn: function ( message ) { - assert.ok( /Module .+D\.js may be unable to evaluate without .+C\.js, but is included first due to a cyclical dependency. Consider swapping the import statements in .+main\.js to ensure correct ordering/.test( message ) ); - warned = true; - } - }, - runtimeError: function () { - assert.ok( warned ); + warnings: warnings => { + assert.equal( warnings.length, 1 ); + assert.ok( /Module .+D\.js may be unable to evaluate without .+C\.js, but is included first due to a cyclical dependency. Consider swapping the import statements in .+main\.js to ensure correct ordering/.test( warnings[0] ) ); } }; diff --git a/test/function/import-chain-as/main.js b/test/function/import-chain-as/main.js index d1dc2b90c06..3672452332d 100644 --- a/test/function/import-chain-as/main.js +++ b/test/function/import-chain-as/main.js @@ -1,5 +1,4 @@ import * as second from './second'; assert.equal( second.first.value, 42 ); -console.log( 'second', second ) assert.deepEqual( second, { first: { value: 42 } }); diff --git a/test/function/import-default-class/_config.js b/test/function/import-default-class/_config.js index 5e59ef17ed6..e3201e1cb1a 100644 --- a/test/function/import-default-class/_config.js +++ b/test/function/import-default-class/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'imports a default class', - babel: true + buble: true }; // test copied from https://github.com/esnext/es6-module-transpiler/tree/master/test/examples/export-default-class diff --git a/test/function/import-dependency-in-same-module/_config.js b/test/function/import-dependency-in-same-module/_config.js index 622d7d9d1b7..a08ff3cdab7 100644 --- a/test/function/import-dependency-in-same-module/_config.js +++ b/test/function/import-dependency-in-same-module/_config.js @@ -1,3 +1,3 @@ module.exports = { description: 'imports a dependency from the same module' -}; \ No newline at end of file +}; diff --git a/test/function/import-named-class/_config.js b/test/function/import-named-class/_config.js index e7749d03818..02a6302b468 100644 --- a/test/function/import-named-class/_config.js +++ b/test/function/import-named-class/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'imports a named class', - babel: true + buble: true }; // test copied from https://github.com/esnext/es6-module-transpiler/tree/master/test/examples/export-named-class diff --git a/test/function/import-nameless-class-expression/_config.js b/test/function/import-nameless-class-expression/_config.js index 562c561157c..e6cacefd4ca 100644 --- a/test/function/import-nameless-class-expression/_config.js +++ b/test/function/import-nameless-class-expression/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'imports a nameless class expression', - babel: true + buble: true }; // test copied from https://github.com/esnext/es6-module-transpiler/tree/master/test/examples/export-class-expression diff --git a/test/function/import-of-unexported-fails/_config.js b/test/function/import-of-unexported-fails/_config.js index 3027ba9f418..10d11a6df40 100644 --- a/test/function/import-of-unexported-fails/_config.js +++ b/test/function/import-of-unexported-fails/_config.js @@ -3,6 +3,6 @@ var assert = require( 'assert' ); module.exports = { description: 'marking an imported, but unexported, identifier should throw', error: function ( err ) { - assert.ok( /Module .+empty\.js does not export default \(imported by .+main\.js\)/.test( err.message ) ); + assert.equal( err.message, `'default' is not exported by empty.js (imported by main.js). For help fixing this error see https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module` ); } }; diff --git a/test/function/includes-internally-used-default-export/_config.js b/test/function/includes-internally-used-default-export/_config.js new file mode 100644 index 00000000000..3eab34086ad --- /dev/null +++ b/test/function/includes-internally-used-default-export/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'includes default exports that are only used internally' +}; diff --git a/test/function/includes-internally-used-default-export/main.js b/test/function/includes-internally-used-default-export/main.js new file mode 100644 index 00000000000..c196b1000d8 --- /dev/null +++ b/test/function/includes-internally-used-default-export/main.js @@ -0,0 +1,3 @@ +import { b } from './module.js'; + +assert.equal(b(), 15); diff --git a/test/function/includes-internally-used-default-export/module.js b/test/function/includes-internally-used-default-export/module.js new file mode 100644 index 00000000000..ba2c4eeb901 --- /dev/null +++ b/test/function/includes-internally-used-default-export/module.js @@ -0,0 +1,7 @@ +export default function a() { + return 5; +} + +export function b() { + return a() + 10; +} diff --git a/test/function/includes-superclass/_config.js b/test/function/includes-superclass/_config.js new file mode 100644 index 00000000000..e226472462b --- /dev/null +++ b/test/function/includes-superclass/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'includes superclass (#932)', + buble: true +}; diff --git a/test/function/includes-superclass/base.js b/test/function/includes-superclass/base.js new file mode 100644 index 00000000000..c3747945252 --- /dev/null +++ b/test/function/includes-superclass/base.js @@ -0,0 +1,5 @@ +export class Base { + foo () { + return true; + } +} diff --git a/test/function/includes-superclass/main.js b/test/function/includes-superclass/main.js new file mode 100644 index 00000000000..bfb78e8418d --- /dev/null +++ b/test/function/includes-superclass/main.js @@ -0,0 +1,6 @@ +import { Thing } from './thing'; + +const thing = new Thing(); + +assert.ok( thing.foo() ); +assert.ok( thing.bar() ); diff --git a/test/function/includes-superclass/thing.js b/test/function/includes-superclass/thing.js new file mode 100644 index 00000000000..97b3be8d85a --- /dev/null +++ b/test/function/includes-superclass/thing.js @@ -0,0 +1,7 @@ +import { Base } from './base.js'; + +export class Thing extends Base { + bar () { + return true; + } +} diff --git a/test/function/legal-suggested-names/_config.js b/test/function/legal-suggested-names/_config.js new file mode 100644 index 00000000000..d68f4e75b25 --- /dev/null +++ b/test/function/legal-suggested-names/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'illegal name suggestions are ignored' +}; diff --git a/test/function/legal-suggested-names/bar.js b/test/function/legal-suggested-names/bar.js new file mode 100644 index 00000000000..a6071dfa1f3 --- /dev/null +++ b/test/function/legal-suggested-names/bar.js @@ -0,0 +1,5 @@ +import * as helpers from './helpers.js'; + +export default function bar ( a ) { + return helpers.typeof( a ); +} diff --git a/test/function/legal-suggested-names/foo.js b/test/function/legal-suggested-names/foo.js new file mode 100644 index 00000000000..91a1fb73682 --- /dev/null +++ b/test/function/legal-suggested-names/foo.js @@ -0,0 +1,5 @@ +import * as helpers from './helpers.js'; + +export default function foo ( a ) { + return helpers.typeof( a ); +} diff --git a/test/function/legal-suggested-names/helpers.js b/test/function/legal-suggested-names/helpers.js new file mode 100644 index 00000000000..1938dee2e5d --- /dev/null +++ b/test/function/legal-suggested-names/helpers.js @@ -0,0 +1,5 @@ +var _typeof = function ( thing ) { + return typeof thing; +}; + +export { _typeof as typeof }; diff --git a/test/function/legal-suggested-names/main.js b/test/function/legal-suggested-names/main.js new file mode 100644 index 00000000000..7c478046041 --- /dev/null +++ b/test/function/legal-suggested-names/main.js @@ -0,0 +1,8 @@ +import * as helpers from './helpers.js'; +import foo from './foo.js'; +import bar from './bar.js'; + +assert.equal( helpers.typeof( foo ), 'function' ); +assert.equal( helpers.typeof( bar ), 'function' ); +assert.equal( foo( 1 ), 'number' ); +assert.equal( bar( 2 ), 'number' ); diff --git a/test/function/load-returns-string-or-null/main.js b/test/function/load-returns-string-or-null/main.js new file mode 100644 index 00000000000..422c08460a8 --- /dev/null +++ b/test/function/load-returns-string-or-null/main.js @@ -0,0 +1 @@ +throw new Error('should not be reached'); diff --git a/test/function/member-expression-assignment-in-function/_config.js b/test/function/member-expression-assignment-in-function/_config.js index bf7e6fc0d89..3166462b59b 100644 --- a/test/function/member-expression-assignment-in-function/_config.js +++ b/test/function/member-expression-assignment-in-function/_config.js @@ -7,4 +7,4 @@ module.exports = { assert.equal( code.indexOf( 'set("bar", 2);' ) >= 0, true, code ); assert.equal( code.indexOf( 'set("qux", 3);' ) >= 0, true, code ); } -} +}; diff --git a/test/function/module-tree/_config.js b/test/function/module-tree/_config.js new file mode 100644 index 00000000000..553ab2babda --- /dev/null +++ b/test/function/module-tree/_config.js @@ -0,0 +1,37 @@ +const path = require( 'path' ); +const assert = require( 'assert' ); + +module.exports = { + description: 'bundle.modules includes dependencies (#903)', + bundle ( bundle ) { + const modules = bundle.modules.map( module => { + return { + id: path.relative( __dirname, module.id ), + dependencies: module.dependencies.map( id => path.relative( __dirname, id ) ) + }; + }); + + assert.deepEqual( modules, [ + { + id: path.normalize( 'nested/qux.js' ), + dependencies: [] + }, + { + id: path.normalize( 'nested/baz.js' ), + dependencies: [ path.normalize( 'nested/qux.js' ) ] + }, + { + id: 'bar.js', + dependencies: [ path.normalize( 'nested/baz.js' ) ] + }, + { + id: 'foo.js', + dependencies: [ 'bar.js' ] + }, + { + id: 'main.js', + dependencies: [ 'foo.js', 'bar.js' ] + } + ]); + } +}; diff --git a/test/function/module-tree/bar.js b/test/function/module-tree/bar.js new file mode 100644 index 00000000000..76340f68f08 --- /dev/null +++ b/test/function/module-tree/bar.js @@ -0,0 +1 @@ +import './nested/baz.js'; diff --git a/test/function/module-tree/foo.js b/test/function/module-tree/foo.js new file mode 100644 index 00000000000..1df02c2f525 --- /dev/null +++ b/test/function/module-tree/foo.js @@ -0,0 +1 @@ +import './bar.js'; diff --git a/test/function/module-tree/main.js b/test/function/module-tree/main.js new file mode 100644 index 00000000000..f2570225ccb --- /dev/null +++ b/test/function/module-tree/main.js @@ -0,0 +1,2 @@ +import './foo.js'; +import './bar.js'; diff --git a/test/function/module-tree/nested/baz.js b/test/function/module-tree/nested/baz.js new file mode 100644 index 00000000000..0ff2bf963ed --- /dev/null +++ b/test/function/module-tree/nested/baz.js @@ -0,0 +1 @@ +import qux from './qux.js'; diff --git a/test/function/module-tree/nested/qux.js b/test/function/module-tree/nested/qux.js new file mode 100644 index 00000000000..6d70feca8ec --- /dev/null +++ b/test/function/module-tree/nested/qux.js @@ -0,0 +1 @@ +export default 'whatever'; diff --git a/test/function/namespace-missing-export/_config.js b/test/function/namespace-missing-export/_config.js index 69f14053f1e..6ecf3b9cdfa 100644 --- a/test/function/namespace-missing-export/_config.js +++ b/test/function/namespace-missing-export/_config.js @@ -1,10 +1,9 @@ var assert = require( 'assert' ); -var path = require( 'path' ); module.exports = { options: { onwarn: function ( msg ) { - assert.ok( /Export 'foo' is not defined by/.test( msg ) ); + assert.equal( msg, `main.js (3:21) 'foo' is not exported by 'empty.js'. See https://github.com/rollup/rollup/wiki/Troubleshooting#name-is-not-exported-by-module` ); } } }; diff --git a/test/function/namespacing-collisions-2/Material.js b/test/function/namespacing-collisions-2/Material.js new file mode 100644 index 00000000000..b6d1881edfd --- /dev/null +++ b/test/function/namespacing-collisions-2/Material.js @@ -0,0 +1,3 @@ +export function Material() { + return 'Material'; +} diff --git a/test/function/namespacing-collisions-2/MaterialAgain.js b/test/function/namespacing-collisions-2/MaterialAgain.js new file mode 100644 index 00000000000..170cfff1cd4 --- /dev/null +++ b/test/function/namespacing-collisions-2/MaterialAgain.js @@ -0,0 +1,3 @@ +export function MaterialAgain() { + return 'MaterialAgain'; +} diff --git a/test/function/namespacing-collisions-2/Something.js b/test/function/namespacing-collisions-2/Something.js new file mode 100644 index 00000000000..64cbdcacd9d --- /dev/null +++ b/test/function/namespacing-collisions-2/Something.js @@ -0,0 +1,6 @@ +import * as Material from './Material'; + +export function Something() { + console.log(Material); + return 'Something'; +} \ No newline at end of file diff --git a/test/function/namespacing-collisions-2/SomethingAgain.js b/test/function/namespacing-collisions-2/SomethingAgain.js new file mode 100644 index 00000000000..1efaca71d0b --- /dev/null +++ b/test/function/namespacing-collisions-2/SomethingAgain.js @@ -0,0 +1,6 @@ +import * as Material from './MaterialAgain'; + +export function SomethingAgain() { + console.log(Material); + return 'SomethingAgain'; +} \ No newline at end of file diff --git a/test/function/namespacing-collisions-2/_config.js b/test/function/namespacing-collisions-2/_config.js new file mode 100644 index 00000000000..468429692fc --- /dev/null +++ b/test/function/namespacing-collisions-2/_config.js @@ -0,0 +1,8 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'correctly namespaces when using * exports, take two (#910)', + exports: function ( exports ) { + assert.deepEqual( exports, ['Material', 'MaterialAgain', 'Something', 'SomethingAgain'] ); + } +}; diff --git a/test/function/namespacing-collisions-2/main.js b/test/function/namespacing-collisions-2/main.js new file mode 100644 index 00000000000..c69a6e475cf --- /dev/null +++ b/test/function/namespacing-collisions-2/main.js @@ -0,0 +1,7 @@ +import { Something } from './Something'; +import { SomethingAgain } from './SomethingAgain'; +import { Material } from './Material'; +import { MaterialAgain } from './MaterialAgain'; + +var result = [Material(), MaterialAgain(), Something(), SomethingAgain()] +export default result; diff --git a/test/function/namespacing-collisions/Material.js b/test/function/namespacing-collisions/Material.js new file mode 100644 index 00000000000..b6d1881edfd --- /dev/null +++ b/test/function/namespacing-collisions/Material.js @@ -0,0 +1,3 @@ +export function Material() { + return 'Material'; +} diff --git a/test/function/namespacing-collisions/Something.js b/test/function/namespacing-collisions/Something.js new file mode 100644 index 00000000000..64cbdcacd9d --- /dev/null +++ b/test/function/namespacing-collisions/Something.js @@ -0,0 +1,6 @@ +import * as Material from './Material'; + +export function Something() { + console.log(Material); + return 'Something'; +} \ No newline at end of file diff --git a/test/function/namespacing-collisions/_config.js b/test/function/namespacing-collisions/_config.js new file mode 100644 index 00000000000..02c772fec9b --- /dev/null +++ b/test/function/namespacing-collisions/_config.js @@ -0,0 +1,8 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'correctly namespaces when using * exports (#910)', + exports: function ( exports ) { + assert.deepEqual( exports, [ 'Material', 'Something' ] ); + } +}; diff --git a/test/function/namespacing-collisions/main.js b/test/function/namespacing-collisions/main.js new file mode 100644 index 00000000000..8746123476a --- /dev/null +++ b/test/function/namespacing-collisions/main.js @@ -0,0 +1,5 @@ +import { Something } from './Something'; +import { Material } from './Material'; + +var result = [Material(), Something()] +export default result; \ No newline at end of file diff --git a/test/function/namespacing-in-sub-functions/_config.js b/test/function/namespacing-in-sub-functions/_config.js new file mode 100644 index 00000000000..025b117db53 --- /dev/null +++ b/test/function/namespacing-in-sub-functions/_config.js @@ -0,0 +1,8 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'correctly namespaces sub-functions (#910)', + exports: function ( exports ) { + assert.equal( exports, 'foobar' ); + } +}; diff --git a/test/function/namespacing-in-sub-functions/main.js b/test/function/namespacing-in-sub-functions/main.js new file mode 100644 index 00000000000..ac9d9daf41d --- /dev/null +++ b/test/function/namespacing-in-sub-functions/main.js @@ -0,0 +1,11 @@ +import { problematicFunc as otherFunc } from './problematicFunc'; +function innerFunc() { + function problematicFunc () { + return otherFunc(); + } + return problematicFunc(); +} + +var res = innerFunc(); + +export default res; \ No newline at end of file diff --git a/test/function/namespacing-in-sub-functions/problematicFunc.js b/test/function/namespacing-in-sub-functions/problematicFunc.js new file mode 100644 index 00000000000..1fbecc0a5ad --- /dev/null +++ b/test/function/namespacing-in-sub-functions/problematicFunc.js @@ -0,0 +1,5 @@ +function problematicFunc() { + return 'foobar'; +} + +export { problematicFunc }; \ No newline at end of file diff --git a/test/function/newline-after-comment/_config.js b/test/function/newline-after-comment/_config.js index 76ebc5747c6..85191d64cda 100644 --- a/test/function/newline-after-comment/_config.js +++ b/test/function/newline-after-comment/_config.js @@ -4,6 +4,5 @@ module.exports = { description: 'inserts newline after comment', exports: function ( exports ) { assert.equal( exports(), 42 ); - }, - // solo: true + } }; diff --git a/test/function/no-imports/_config.js b/test/function/no-imports/_config.js index 47ae3de8e85..be6c448555e 100644 --- a/test/function/no-imports/_config.js +++ b/test/function/no-imports/_config.js @@ -1,3 +1,3 @@ module.exports = { description: 'creates a bundle from a module with no imports' -}; \ No newline at end of file +}; diff --git a/test/function/no-relative-external/_config.js b/test/function/no-relative-external/_config.js index 37f86dfa369..b5c37e0a3c1 100644 --- a/test/function/no-relative-external/_config.js +++ b/test/function/no-relative-external/_config.js @@ -3,6 +3,6 @@ var assert = require( 'assert' ); module.exports = { description: 'missing relative imports are an error, not a warning', error: function ( err ) { - assert.ok( /Could not resolve \.\/missing\.js from/.test( err.message ) ); + assert.ok( /Could not resolve '\.\/missing\.js' from/.test( err.message ) ); } }; diff --git a/test/function/object-destructuring-renaming/_config.js b/test/function/object-destructuring-renaming/_config.js index 4a1b8b6c57c..cae5239e451 100644 --- a/test/function/object-destructuring-renaming/_config.js +++ b/test/function/object-destructuring-renaming/_config.js @@ -4,7 +4,7 @@ module.exports = { description: 'renaming destructured object properties should request the correct property (#527)', // we must transpile the object destructuring to test it - babel: true, + buble: true, exports: function ( exports ) { assert.equal( exports.env, process.env ); diff --git a/test/function/object-dynamic-properties/_config.js b/test/function/object-dynamic-properties/_config.js index 001b48f2ac9..1bcd2fa3611 100644 --- a/test/function/object-dynamic-properties/_config.js +++ b/test/function/object-dynamic-properties/_config.js @@ -1,5 +1,3 @@ -var assert = require('assert'); - module.exports = { description: 'dynamic object assignments should be imported' }; diff --git a/test/function/paths-are-case-sensitive/Foo.js b/test/function/paths-are-case-sensitive/Foo.js new file mode 100644 index 00000000000..81baecbd917 --- /dev/null +++ b/test/function/paths-are-case-sensitive/Foo.js @@ -0,0 +1,3 @@ +export default function () { + assert.ok( false ); +} diff --git a/test/function/paths-are-case-sensitive/_config.js b/test/function/paths-are-case-sensitive/_config.js new file mode 100644 index 00000000000..3f81b80c2a7 --- /dev/null +++ b/test/function/paths-are-case-sensitive/_config.js @@ -0,0 +1,8 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'insists on correct casing for imports', + error: function ( err ) { + assert.ok( /Could not resolve/.test( err.message ) ); + } +}; diff --git a/test/function/paths-are-case-sensitive/main.js b/test/function/paths-are-case-sensitive/main.js new file mode 100644 index 00000000000..e1fb5c4a3e2 --- /dev/null +++ b/test/function/paths-are-case-sensitive/main.js @@ -0,0 +1,3 @@ +import foo from './foo.js'; + +foo(); diff --git a/test/function/plugins-can-manipulate-options/_config.js b/test/function/plugins-can-manipulate-options/_config.js index a0e607cdb17..15e95984ddd 100644 --- a/test/function/plugins-can-manipulate-options/_config.js +++ b/test/function/plugins-can-manipulate-options/_config.js @@ -15,4 +15,4 @@ module.exports = { exports: function ( answer ) { assert.equal( answer, 42 ); } -} +}; diff --git a/test/function/reassign-import-fails/_config.js b/test/function/reassign-import-fails/_config.js index e01d0903017..22591fe7dbd 100644 --- a/test/function/reassign-import-fails/_config.js +++ b/test/function/reassign-import-fails/_config.js @@ -4,9 +4,9 @@ var assert = require( 'assert' ); module.exports = { description: 'disallows assignments to imported bindings', error: function ( err ) { + assert.ok( /Illegal reassignment/.test( err.message ) ); assert.equal( path.normalize(err.file), path.resolve( __dirname, 'main.js' ) ); assert.deepEqual( err.loc, { line: 8, column: 0 }); - assert.ok( /Illegal reassignment/.test( err.message ) ); } }; diff --git a/test/function/reassign-parameter/_config.js b/test/function/reassign-parameter/_config.js new file mode 100644 index 00000000000..1701a6f8311 --- /dev/null +++ b/test/function/reassign-parameter/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'parameters can be reassigned/updated' +}; diff --git a/test/function/reassign-parameter/main.js b/test/function/reassign-parameter/main.js new file mode 100644 index 00000000000..6c680612cb7 --- /dev/null +++ b/test/function/reassign-parameter/main.js @@ -0,0 +1,7 @@ +function numbers ( i ) { + var array = new Array( i ); + while ( i-- ) array[i] = i + 1; + return array; +} + +assert.deepEqual( numbers( 5 ), [ 1, 2, 3, 4, 5 ] ); diff --git a/test/function/rename-conditional-expression-children/_config.js b/test/function/rename-conditional-expression-children/_config.js new file mode 100644 index 00000000000..d159c95ec04 --- /dev/null +++ b/test/function/rename-conditional-expression-children/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'correctly renders children of ConditionalExpressions', + buble: true +}; diff --git a/test/function/rename-conditional-expression-children/foo.js b/test/function/rename-conditional-expression-children/foo.js new file mode 100644 index 00000000000..7fe4a4da703 --- /dev/null +++ b/test/function/rename-conditional-expression-children/foo.js @@ -0,0 +1,2 @@ +export const bar = 42; +export const baz = 43; diff --git a/test/function/rename-conditional-expression-children/main.js b/test/function/rename-conditional-expression-children/main.js new file mode 100644 index 00000000000..16bfa0f9807 --- /dev/null +++ b/test/function/rename-conditional-expression-children/main.js @@ -0,0 +1,3 @@ +import * as foo from './foo.js'; + +assert.equal( true ? foo.bar : foo.baz, 42 ); diff --git a/test/function/resolves-namespace-default/_config.js b/test/function/resolves-namespace-default/_config.js index 4e280792755..46de4e10d24 100644 --- a/test/function/resolves-namespace-default/_config.js +++ b/test/function/resolves-namespace-default/_config.js @@ -1,9 +1,9 @@ var assert = require('assert'); module.exports = { - description: "namespace's 'default' properties should be available", + description: "namespace's 'default' properties should be available", - exports: function ( exports ) { - assert.equal( exports, 42 ); - } + exports: function ( exports ) { + assert.equal( exports, 42 ); + } }; diff --git a/test/function/skips-dead-branches-b/_config.js b/test/function/skips-dead-branches-b/_config.js deleted file mode 100644 index bb15b4926dd..00000000000 --- a/test/function/skips-dead-branches-b/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch (b)', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/skips-dead-branches-c/_config.js b/test/function/skips-dead-branches-c/_config.js deleted file mode 100644 index 47111d5cc61..00000000000 --- a/test/function/skips-dead-branches-c/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch (c)', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/skips-dead-branches-d/_config.js b/test/function/skips-dead-branches-d/_config.js deleted file mode 100644 index 3cc97d3b746..00000000000 --- a/test/function/skips-dead-branches-d/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch (d)', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/skips-dead-branches-e/_config.js b/test/function/skips-dead-branches-e/_config.js deleted file mode 100644 index 15deabfacf9..00000000000 --- a/test/function/skips-dead-branches-e/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch (e)', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/skips-dead-branches-f/_config.js b/test/function/skips-dead-branches-f/_config.js deleted file mode 100644 index e43c622c8ef..00000000000 --- a/test/function/skips-dead-branches-f/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch (f)', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/skips-dead-branches-g/_config.js b/test/function/skips-dead-branches-g/_config.js deleted file mode 100644 index d1e507d6e52..00000000000 --- a/test/function/skips-dead-branches-g/_config.js +++ /dev/null @@ -1,9 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead conditional expression branch (g)', - code: function ( code ) { - assert.ok( code.indexOf( 'var c = a;' ) >= 0, code ); - assert.ok( code.indexOf( 'var d = b;' ) >= 0, code ); - } -}; diff --git a/test/function/skips-dead-branches-g/main.js b/test/function/skips-dead-branches-g/main.js deleted file mode 100644 index 0c271f4fe77..00000000000 --- a/test/function/skips-dead-branches-g/main.js +++ /dev/null @@ -1,6 +0,0 @@ -var a = 0; -var b = 1; -var c = true ? a : b; -var d = false ? a : b; - -console.log( c + d ); diff --git a/test/function/skips-dead-branches/_config.js b/test/function/skips-dead-branches/_config.js deleted file mode 100644 index 1278d359db3..00000000000 --- a/test/function/skips-dead-branches/_config.js +++ /dev/null @@ -1,8 +0,0 @@ -var assert = require( 'assert' ); - -module.exports = { - description: 'skips a dead branch', - code: function ( code ) { - assert.equal( code.indexOf( 'obj.foo = function' ), -1, code ); - } -} diff --git a/test/function/this-is-undefined/_config.js b/test/function/this-is-undefined/_config.js deleted file mode 100644 index 750d99a7f7d..00000000000 --- a/test/function/this-is-undefined/_config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - description: 'this at top level is undefined', - babel: true -}; diff --git a/test/function/throws-not-found-module/_config.js b/test/function/throws-not-found-module/_config.js new file mode 100644 index 00000000000..04963a3d210 --- /dev/null +++ b/test/function/throws-not-found-module/_config.js @@ -0,0 +1,9 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + +module.exports = { + description: 'throws error if module is not found', + error: function ( err ) { + assert.equal( err.message, 'Could not resolve \'./mod\' from ' + path.resolve( __dirname, 'main.js' ) ); + } +}; \ No newline at end of file diff --git a/test/function/throws-not-found-module/main.js b/test/function/throws-not-found-module/main.js new file mode 100644 index 00000000000..9ed266ef173 --- /dev/null +++ b/test/function/throws-not-found-module/main.js @@ -0,0 +1 @@ +import './mod'; \ No newline at end of file diff --git a/test/function/throws-only-first-transform-bundle/_config.js b/test/function/throws-only-first-transform-bundle/_config.js new file mode 100644 index 00000000000..9097f521c09 --- /dev/null +++ b/test/function/throws-only-first-transform-bundle/_config.js @@ -0,0 +1,25 @@ +var assert = require( 'assert' ); + +module.exports = { + description: 'throws error only with first plugin transformBundle', + options: { + plugins: [ + { + name: 'plugin1', + transformBundle: function () { + throw Error('Something happend 1'); + } + }, + { + name: 'plugin2', + transformBundle: function () { + throw Error('Something happend 2'); + } + } + ] + }, + generateError: function ( err ) { + assert.equal( err.plugin, 'plugin1' ); + assert.equal( err.message, 'Error transforming bundle with \'plugin1\' plugin: Something happend 1' ); + } +}; \ No newline at end of file diff --git a/test/function/throws-only-first-transform-bundle/main.js b/test/function/throws-only-first-transform-bundle/main.js new file mode 100644 index 00000000000..4e2e0f51157 --- /dev/null +++ b/test/function/throws-only-first-transform-bundle/main.js @@ -0,0 +1 @@ +console.log(1); \ No newline at end of file diff --git a/test/function/throws-only-first-transform/_config.js b/test/function/throws-only-first-transform/_config.js new file mode 100644 index 00000000000..c97907ed7ba --- /dev/null +++ b/test/function/throws-only-first-transform/_config.js @@ -0,0 +1,29 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + +module.exports = { + description: 'throws error only with first plugin transform', + options: { + plugins: [ + { + name: 'plugin1', + transform: function () { + throw Error('Something happend 1'); + } + }, + { + name: 'plugin2', + transform: function () { + throw Error('Something happend 2'); + } + } + ] + }, + error: function ( err ) { + var id = path.resolve( __dirname, 'main.js' ); + assert.equal( err.rollupTransform, true ); + assert.equal( err.id, id ); + assert.equal( err.plugin, 'plugin1' ); + assert.equal( err.message, 'Error transforming ' + id + ' with \'plugin1\' plugin: Something happend 1' ); + } +}; \ No newline at end of file diff --git a/test/function/throws-only-first-transform/main.js b/test/function/throws-only-first-transform/main.js new file mode 100644 index 00000000000..4e2e0f51157 --- /dev/null +++ b/test/function/throws-only-first-transform/main.js @@ -0,0 +1 @@ +console.log(1); \ No newline at end of file diff --git a/test/function/top-level-arrow-function/_config.js b/test/function/top-level-arrow-function/_config.js index 6ce4fd3695c..5bdf0bc71ef 100644 --- a/test/function/top-level-arrow-function/_config.js +++ b/test/function/top-level-arrow-function/_config.js @@ -1,4 +1,4 @@ module.exports = { description: 'handles naked return value from top-level arrow function expression (#403)', - babel: true + buble: true }; diff --git a/test/function/tracks-alias-mutations-b/_config.js b/test/function/tracks-alias-mutations-b/_config.js new file mode 100644 index 00000000000..dde47e2ff86 --- /dev/null +++ b/test/function/tracks-alias-mutations-b/_config.js @@ -0,0 +1,13 @@ +const assert = require( 'assert' ); + +const foo = {}; + +module.exports = { + description: 'tracks mutations of aliased objects', + context: { + foo + }, + exports () { + assert.equal( foo.x, 42 ); + } +}; diff --git a/test/function/tracks-alias-mutations-b/main.js b/test/function/tracks-alias-mutations-b/main.js new file mode 100644 index 00000000000..81ef7f7ffbf --- /dev/null +++ b/test/function/tracks-alias-mutations-b/main.js @@ -0,0 +1,2 @@ +var _foo = foo; +_foo.x = 42; diff --git a/test/function/tracks-alias-mutations/bar.js b/test/function/tracks-alias-mutations/bar.js index 4ec51400773..88a92e5d8bc 100644 --- a/test/function/tracks-alias-mutations/bar.js +++ b/test/function/tracks-alias-mutations/bar.js @@ -1,6 +1,8 @@ import { foo } from './foo'; -var f = foo; -f.wasMutated = true; +var f = Math.random() <= 1 ? foo : {}; +var f2; +f2 = Math.random() <= 1 ? f : {}; +f2.wasMutated = true; export var bar = 'whatever'; diff --git a/test/function/transformer-async/_config.js b/test/function/transformer-async/_config.js index 960eb69f38c..cd9afd0951b 100644 --- a/test/function/transformer-async/_config.js +++ b/test/function/transformer-async/_config.js @@ -1,5 +1,3 @@ -var Promise = require( 'es6-promise' ).Promise; - module.exports = { description: 'transformers can be asynchronous', options: { diff --git a/test/function/transformer-multiple/_config.js b/test/function/transformer-multiple/_config.js index e9aab9ad93b..916d71e4cea 100644 --- a/test/function/transformer-multiple/_config.js +++ b/test/function/transformer-multiple/_config.js @@ -22,4 +22,4 @@ module.exports = { exports: function ( exports ) { assert.equal( exports.magicNumber, 6 ); } -} +}; diff --git a/test/function/transformer-single/_config.js b/test/function/transformer-single/_config.js index 93a1364e02b..fb99d249dbc 100644 --- a/test/function/transformer-single/_config.js +++ b/test/function/transformer-single/_config.js @@ -12,4 +12,4 @@ module.exports = { exports: function ( exports ) { assert.equal( exports.magicNumber, 3 ); } -} +}; diff --git a/test/function/vars-in-for-loop-head/_config.js b/test/function/vars-in-for-loop-head/_config.js new file mode 100644 index 00000000000..166d6eea4e8 --- /dev/null +++ b/test/function/vars-in-for-loop-head/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'does not break apart vars in for loop head' +}; diff --git a/test/function/vars-in-for-loop-head/main.js b/test/function/vars-in-for-loop-head/main.js new file mode 100644 index 00000000000..0b35f91806b --- /dev/null +++ b/test/function/vars-in-for-loop-head/main.js @@ -0,0 +1,10 @@ +function clone ( things ) { + var result = []; + for ( var i = 0, list = things; i < list.length; i += 1 ) { + var thing = list[i]; + result.push( thing ); + } + return result; +} + +assert.deepEqual( clone([ 1, 2, 3 ]), [ 1, 2, 3 ] ); diff --git a/test/function/warn-on-eval/_config.js b/test/function/warn-on-eval/_config.js index 169171c8294..d6ac89f9799 100644 --- a/test/function/warn-on-eval/_config.js +++ b/test/function/warn-on-eval/_config.js @@ -1,4 +1,3 @@ -var path = require( 'path' ); var assert = require( 'assert' ); var warned = false; diff --git a/test/function/warn-on-top-level-this/_config.js b/test/function/warn-on-top-level-this/_config.js new file mode 100644 index 00000000000..99c3f2c4320 --- /dev/null +++ b/test/function/warn-on-top-level-this/_config.js @@ -0,0 +1,13 @@ +const assert = require( 'assert' ); + +module.exports = { + description: 'warns on top-level this (#770)', + warnings: warnings => { + assert.deepEqual( warnings, [ + `main.js (3:1) The 'this' keyword is equivalent to 'undefined' at the top level of an ES module, and has been rewritten. See https://github.com/rollup/rollup/wiki/Troubleshooting#this-is-undefined for more information` + ]); + }, + runtimeError: err => { + assert.equal( err.message, `Cannot set property 'foo' of undefined` ); + } +}; diff --git a/test/function/warn-on-top-level-this/main.js b/test/function/warn-on-top-level-this/main.js new file mode 100644 index 00000000000..e3ca378b6e9 --- /dev/null +++ b/test/function/warn-on-top-level-this/main.js @@ -0,0 +1,3 @@ +const someVariableJustToCheckOnCorrectLineNumber = true; // eslint-disable-line + +this.foo = 'bar'; diff --git a/test/function/warn-on-unused-missing-imports/_config.js b/test/function/warn-on-unused-missing-imports/_config.js new file mode 100644 index 00000000000..1fca512302d --- /dev/null +++ b/test/function/warn-on-unused-missing-imports/_config.js @@ -0,0 +1,11 @@ +const path = require( 'path' ); +const assert = require( 'assert' ); + +module.exports = { + description: 'warns on missing (but unused) imports', + warnings: warnings => { + assert.deepEqual( warnings, [ + `Non-existent export 'b' is imported from ${path.resolve(__dirname, 'foo.js')} by ${path.resolve(__dirname, 'main.js')}` + ]); + } +}; diff --git a/test/function/warn-on-unused-missing-imports/foo.js b/test/function/warn-on-unused-missing-imports/foo.js new file mode 100644 index 00000000000..18e60c877a3 --- /dev/null +++ b/test/function/warn-on-unused-missing-imports/foo.js @@ -0,0 +1 @@ +export var a = 42; diff --git a/test/function/warn-on-unused-missing-imports/main.js b/test/function/warn-on-unused-missing-imports/main.js new file mode 100644 index 00000000000..7eaceb925f9 --- /dev/null +++ b/test/function/warn-on-unused-missing-imports/main.js @@ -0,0 +1,3 @@ +import { a, b } from './foo.js'; + +assert.equal( a, 42 ); diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 00000000000..078771efab4 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--compilers js:buble/register diff --git a/test/sourcemaps/basic-support/_config.js b/test/sourcemaps/basic-support/_config.js index d2910f75926..53a452630af 100644 --- a/test/sourcemaps/basic-support/_config.js +++ b/test/sourcemaps/basic-support/_config.js @@ -1,4 +1,3 @@ -var path = require( 'path' ); var assert = require( 'assert' ); var getLocation = require( '../../utils/getLocation' ); var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer; @@ -7,7 +6,7 @@ module.exports = { description: 'basic sourcemap support', test: function ( code, map ) { assert.equal( map.version, 3 ); - assert.equal( map.file, 'bundle.js' ); + assert.ok( /^bundle\.(\w+)\.js/.test( map.file ) ); var smc = new SourceMapConsumer( map ); var generatedLoc, originalLoc; diff --git a/test/sourcemaps/excludes-plugin-helpers/_config.js b/test/sourcemaps/excludes-plugin-helpers/_config.js new file mode 100644 index 00000000000..2014d88baa2 --- /dev/null +++ b/test/sourcemaps/excludes-plugin-helpers/_config.js @@ -0,0 +1,28 @@ +const fs = require( 'fs' ); +const path = require( 'path' ); +const assert = require( 'assert' ); + +const HELPER = '\0helper'; + +module.exports = { + description: 'excludes plugin helpers from sources', + options: { + format: 'cjs', + plugins: [{ + resolveId ( id ) { + if ( id === HELPER ) return id; + }, + + load ( id ) { + if ( id === HELPER ) { + return fs.readFileSync( path.join( __dirname, 'helper.js' ), 'utf-8' ); + } + } + }] + }, + test: ( code, map ) => { + assert.equal( map.sources.length, 1 ); + assert.equal( map.sourcesContent.length, 1 ); + assert.ok( /main/.test( map.sources[0] ) ); + } +}; diff --git a/test/sourcemaps/excludes-plugin-helpers/helper.js b/test/sourcemaps/excludes-plugin-helpers/helper.js new file mode 100644 index 00000000000..40205b6373c --- /dev/null +++ b/test/sourcemaps/excludes-plugin-helpers/helper.js @@ -0,0 +1,3 @@ +export default function foo ( input ) { + assert.equal( input, 42 ); +} diff --git a/test/sourcemaps/excludes-plugin-helpers/main.js b/test/sourcemaps/excludes-plugin-helpers/main.js new file mode 100644 index 00000000000..64577b6750e --- /dev/null +++ b/test/sourcemaps/excludes-plugin-helpers/main.js @@ -0,0 +1,3 @@ +import foo from '\0helper'; + +foo( 42 ); diff --git a/test/sourcemaps/loaders/_config.js b/test/sourcemaps/loaders/_config.js new file mode 100644 index 00000000000..57ff117f3c6 --- /dev/null +++ b/test/sourcemaps/loaders/_config.js @@ -0,0 +1,67 @@ +var buble = require( 'buble' ); +var fs = require( 'fs' ); +var assert = require( 'assert' ); +var getLocation = require( '../../utils/getLocation' ); +var SourceMapConsumer = require( 'source-map' ).SourceMapConsumer; + +module.exports = { + description: 'preserves sourcemap chains when transforming', + options: { + plugins: [ + { + load: function ( id ) { + if ( /foo.js$/.test( id ) ) { + id = id.replace( /foo.js$/, 'bar.js' ); + } else if ( /bar.js$/.test( id ) ) { + id = id.replace( /bar.js$/, 'foo.js' ); + } + + var code = fs.readFileSync( id, 'utf-8' ); + + var out = buble.transform( code, { + transforms: { modules: false }, + sourceMap: true, + source: id + }); + + if ( /main.js$/.test( id ) ) { + delete out.map.sources; + } else { + const slash = out.map.sources[0].lastIndexOf( '/' ) + 1; + out.map.sources = out.map.sources.map( source => '../' + source.slice( slash ) ); + out.map.sourceRoot = 'fake'; + } + + return { code: out.code, map: out.map }; + } + } + ] + }, + test: function ( code, map ) { + var smc = new SourceMapConsumer( map ); + var generatedLoc; + var originalLoc; + + generatedLoc = getLocation( code, code.indexOf( '22' ) ); + originalLoc = smc.originalPositionFor( generatedLoc ); + + assert.equal( originalLoc.source, '../foo.js' ); + assert.equal( originalLoc.line, 1 ); + assert.equal( originalLoc.column, 32 ); + + generatedLoc = getLocation( code, code.indexOf( '20' ) ); + originalLoc = smc.originalPositionFor( generatedLoc ); + + assert.equal( originalLoc.source, '../bar.js' ); + assert.equal( originalLoc.line, 1 ); + assert.equal( originalLoc.column, 37 ); + + generatedLoc = getLocation( code, code.indexOf( 'log' ) ); + originalLoc = smc.originalPositionFor( generatedLoc ); + + assert.equal( originalLoc.source, '../main.js' ); + assert.ok( /columns/.test( smc.sourceContentFor( '../main.js' ) ) ); + assert.equal( originalLoc.line, 4 ); + assert.equal( originalLoc.column, 19 ); + } +}; diff --git a/test/sourcemaps/loaders/bar.js b/test/sourcemaps/loaders/bar.js new file mode 100644 index 00000000000..6c3e77f6838 --- /dev/null +++ b/test/sourcemaps/loaders/bar.js @@ -0,0 +1 @@ +/*misalign*/export const foo = () => 20; diff --git a/test/sourcemaps/loaders/foo.js b/test/sourcemaps/loaders/foo.js new file mode 100644 index 00000000000..9ce428359f0 --- /dev/null +++ b/test/sourcemaps/loaders/foo.js @@ -0,0 +1 @@ +/*the*/export const bar = () => 22; diff --git a/test/sourcemaps/loaders/main.js b/test/sourcemaps/loaders/main.js new file mode 100644 index 00000000000..df7e27ab76e --- /dev/null +++ b/test/sourcemaps/loaders/main.js @@ -0,0 +1,4 @@ +import { foo } from './foo'; +import { bar } from './bar'; + +/*columns*/console.log( `the answer is ${foo() + bar()}` ); diff --git a/test/sourcemaps/reified-namespace/_config.js b/test/sourcemaps/reified-namespace/_config.js new file mode 100644 index 00000000000..8870098b7d1 --- /dev/null +++ b/test/sourcemaps/reified-namespace/_config.js @@ -0,0 +1,22 @@ +const fs = require( 'fs' ); +const path = require( 'path' ); +const assert = require( 'assert' ); +const getLocation = require( '../../utils/getLocation' ); +const SourceMapConsumer = require( 'source-map' ).SourceMapConsumer; + +module.exports = { + description: 'generates correct sourcemap with reified namespace (#668)', + test: ( code, map ) => { + const smc = new SourceMapConsumer( map ); + + const main = fs.readFileSync( path.join( __dirname, 'main.js' ), 'utf-8' ); + const generatedLoc = getLocation( code, 'deepEqual' ); + + const actual = smc.originalPositionFor( generatedLoc ); + const expected = getLocation( main, 'deepEqual' ); + + assert.equal( actual.line, expected.line ); + assert.equal( actual.column, expected.column ); + assert.equal( actual.source, '../main.js' ); + } +}; diff --git a/test/sourcemaps/reified-namespace/foo.js b/test/sourcemaps/reified-namespace/foo.js new file mode 100644 index 00000000000..ab0c7db207f --- /dev/null +++ b/test/sourcemaps/reified-namespace/foo.js @@ -0,0 +1 @@ +export var bar = 42; diff --git a/test/sourcemaps/reified-namespace/main.js b/test/sourcemaps/reified-namespace/main.js new file mode 100644 index 00000000000..565c1ebf329 --- /dev/null +++ b/test/sourcemaps/reified-namespace/main.js @@ -0,0 +1,3 @@ +import * as foo from './foo.js'; + +assert.deepEqual( foo, { bar: 42 }); diff --git a/test/sourcemaps/relative-paths/_config.js b/test/sourcemaps/relative-paths/_config.js index 5c12d05731d..1d72cda225d 100644 --- a/test/sourcemaps/relative-paths/_config.js +++ b/test/sourcemaps/relative-paths/_config.js @@ -1,13 +1,11 @@ var path = require( 'path' ); var assert = require( 'assert' ); -var pathRelativeToCwd = path.relative( process.cwd(), path.resolve( __dirname, '_actual/bundle.js' ) ); - module.exports = { - description: 'source paths are relative (#344)', + description: 'source paths are relative with relative dest (#344)', options: { moduleName: 'myModule', - dest: pathRelativeToCwd + dest: path.resolve( '_actual/bundle.js' ) }, test: function ( code, map ) { assert.deepEqual( map.sources, [ '../main.js' ]); diff --git a/test/sourcemaps/transform-without-sourcemap/_config.js b/test/sourcemaps/transform-without-sourcemap/_config.js new file mode 100644 index 00000000000..ad33354878a --- /dev/null +++ b/test/sourcemaps/transform-without-sourcemap/_config.js @@ -0,0 +1,26 @@ +const assert = require( 'assert' ); + +let warnings = []; + +module.exports = { + description: 'preserves sourcemap chains when transforming', + before: () => warnings = [], // reset + options: { + plugins: [ + { + name: 'fake plugin', + transform: function ( code ) { + return code; + } + } + ], + onwarn ( msg ) { + warnings.push( msg ); + } + }, + test: () => { + assert.deepEqual( warnings, [ + `Sourcemap is likely to be incorrect: a plugin ('fake plugin') was used to transform files, but didn't generate a sourcemap for the transformation. Consult https://github.com/rollup/rollup/wiki/Troubleshooting and the plugin documentation for more information` + ]); + } +}; diff --git a/test/sourcemaps/transform-without-sourcemap/main.js b/test/sourcemaps/transform-without-sourcemap/main.js new file mode 100644 index 00000000000..5c72ff35124 --- /dev/null +++ b/test/sourcemaps/transform-without-sourcemap/main.js @@ -0,0 +1 @@ +console.log( 42 ); diff --git a/test/sourcemaps/transforms/_config.js b/test/sourcemaps/transforms/_config.js index b76a885eee4..77b9354975f 100644 --- a/test/sourcemaps/transforms/_config.js +++ b/test/sourcemaps/transforms/_config.js @@ -1,4 +1,4 @@ -var babel = require( 'babel-core' ); +var buble = require( 'buble' ); var MagicString = require( 'magic-string' ); var assert = require( 'assert' ); var getLocation = require( '../../utils/getLocation' ); @@ -10,9 +10,8 @@ module.exports = { plugins: [ { transform: function ( source, id ) { - return babel.transform( source, { - blacklist: [ 'es6.modules' ], - sourceMap: true + return buble.transform( source, { + transforms: { modules: false } }); } }, diff --git a/test/test.js b/test/test.js index 22239fe25c9..8b2b66f9b2c 100644 --- a/test/test.js +++ b/test/test.js @@ -1,30 +1,30 @@ require( 'source-map-support' ).install(); require( 'console-group' ).install(); -var path = require( 'path' ); -var os = require( 'os' ); -var sander = require( 'sander' ); -var assert = require( 'assert' ); -var exec = require( 'child_process' ).exec; -var babel = require( 'babel-core' ); -var rollup = require( '../dist/rollup' ); - -var FUNCTION = path.resolve( __dirname, 'function' ); -var FORM = path.resolve( __dirname, 'form' ); -var SOURCEMAPS = path.resolve( __dirname, 'sourcemaps' ); -var CLI = path.resolve( __dirname, 'cli' ); - -var PROFILES = [ +const path = require( 'path' ); +const sander = require( 'sander' ); +const assert = require( 'assert' ); +const { exec } = require( 'child_process' ); +const buble = require( 'buble' ); +const acorn = require( 'acorn' ); +const rollup = require( '../dist/rollup' ); + +const FUNCTION = path.resolve( __dirname, 'function' ); +const FORM = path.resolve( __dirname, 'form' ); +const SOURCEMAPS = path.resolve( __dirname, 'sourcemaps' ); +const CLI = path.resolve( __dirname, 'cli' ); + +const PROFILES = [ { format: 'amd' }, { format: 'cjs' }, - { format: 'es6' }, + { format: 'es' }, { format: 'iife' }, { format: 'umd' } ]; function extend ( target ) { - [].slice.call( arguments, 1 ).forEach( function ( source ) { - source && Object.keys( source ).forEach( function ( key ) { + [].slice.call( arguments, 1 ).forEach( source => { + source && Object.keys( source ).forEach( key => { target[ key ] = source[ key ]; }); }); @@ -40,103 +40,158 @@ function loadConfig ( path ) { try { return require( path ); } catch ( err ) { - throw new Error( 'Failed to load ' + path + '. An old test perhaps? You should probably delete the directory' ); + console.error( err.message ); + console.error( err.stack ); + throw new Error( `Failed to load ${path}. An old test perhaps? You should probably delete the directory` ); } } +function loader ( modules ) { + return { + resolveId ( id ) { + return id; + }, + + load ( id ) { + return modules[ id ]; + } + }; +} + describe( 'rollup', function () { this.timeout( 10000 ); - describe( 'sanity checks', function () { - it( 'exists', function () { + describe( 'sanity checks', () => { + it( 'exists', () => { assert.ok( !!rollup ); }); - it( 'has a rollup method', function () { + it( 'has a rollup method', () => { assert.equal( typeof rollup.rollup, 'function' ); }); - it( 'fails without options', function () { - return rollup.rollup().then( function () { + it( 'fails without options', () => { + return rollup.rollup().then( () => { throw new Error( 'Missing expected error' ); - }, function (err) { + }, err => { assert.equal( 'You must supply options.entry to rollup', err.message ); }); }); - it( 'fails without options.entry', function () { - return rollup.rollup({}).then( function () { + it( 'fails without options.entry', () => { + return rollup.rollup({}).then( () => { throw new Error( 'Missing expected error' ); - }, function (err) { + }, err => { assert.equal( 'You must supply options.entry to rollup', err.message ); }); }); - it( 'fails with invalid keys', function () { - return rollup.rollup({ entry: 'x', plUgins: [] }).then( function () { + it( 'fails with invalid keys', () => { + return rollup.rollup({ entry: 'x', plUgins: [] }).then( () => { throw new Error( 'Missing expected error' ); - }, function ( err ) { - assert.equal( err.message, 'Unexpected key \'plUgins\' found, expected one of: banner, dest, entry, exports, external, footer, format, globals, indent, intro, moduleId, moduleName, noConflict, onwarn, outro, plugins, preferConst, sourceMap, treeshake, useStrict' ); + }, err => { + assert.equal( err.message, 'Unexpected key \'plUgins\' found, expected one of: acorn, banner, cache, context, dest, entry, exports, external, footer, format, globals, indent, interop, intro, legacy, moduleContext, moduleId, moduleName, noConflict, onwarn, outro, paths, plugins, preferConst, sourceMap, sourceMapFile, targets, treeshake, useStrict' ); + }); + }); + + it( 'treats Literals as leaf nodes, even if first literal encountered is null', () => { + // this test has to be up here, otherwise the bug doesn't have + // an opportunity to present itself + return rollup.rollup({ + entry: 'x', + plugins: [ loader({ x: `var a = null; a = 'a string';` }) ] + }); + }); + + it( 'includes a newline at the end of the bundle', () => { + return rollup.rollup({ + entry: 'x', + plugins: [ loader({ x: `console.log( 42 );` }) ] + }).then( bundle => { + const { code } = bundle.generate({ format: 'iife' }); + assert.ok( code[ code.length - 1 ] === '\n' ); }); }); }); - describe( 'bundle.write()', function () { - it( 'fails without options or options.dest', function () { + describe( 'bundle.write()', () => { + it( 'fails without options or options.dest', () => { return rollup.rollup({ entry: 'x', plugins: [{ - resolveId: function () { return 'test'; }, - load: function () { + resolveId: () => { return 'test'; }, + load: () => { return '// empty'; } }] - }).then( function ( bundle ) { - assert.throws( function () { + }).then( bundle => { + assert.throws( () => { bundle.write(); }, /must supply options\.dest/ ); - assert.throws( function () { + assert.throws( () => { bundle.write({}); }, /must supply options\.dest/ ); }); }); - it( 'expects options.moduleName for IIFE and UMD bundles', function () { + it( 'expects options.moduleName for IIFE and UMD bundles', () => { return rollup.rollup({ entry: 'x', plugins: [{ - resolveId: function () { return 'test'; }, - load: function () { + resolveId: () => { return 'test'; }, + load: () => { return 'export var foo = 42;'; } }] - }).then( function ( bundle ) { - assert.throws( function () { + }).then( bundle => { + assert.throws( () => { bundle.generate({ format: 'umd' }); }, /You must supply options\.moduleName for UMD bundles/ ); - assert.throws( function () { + assert.throws( () => { bundle.generate({ format: 'iife' }); }, /You must supply options\.moduleName for IIFE bundles/ ); }); }); + + it( 'warns on es6 format', () => { + let warned; + + return rollup.rollup({ + entry: 'x', + plugins: [{ + resolveId: () => { return 'test'; }, + load: () => { + return '// empty'; + } + }], + onwarn: msg => { + if ( /The es6 format is deprecated/.test( msg ) ) warned = true; + } + }).then( bundle => { + bundle.generate({ format: 'es6' }); + assert.ok( warned ); + }); + }); }); - describe( 'function', function () { - sander.readdirSync( FUNCTION ).sort().forEach( function ( dir ) { + describe( 'function', () => { + sander.readdirSync( FUNCTION ).sort().forEach( dir => { if ( dir[0] === '.' ) return; // .DS_Store... - var config = loadConfig( FUNCTION + '/' + dir + '/_config.js' ); - ( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () { - var warnings = []; - var captureWarning = msg => warnings.push( msg ); + const config = loadConfig( FUNCTION + '/' + dir + '/_config.js' ); + ( config.skip ? it.skip : config.solo ? it.only : it )( dir, () => { + process.chdir( FUNCTION + '/' + dir ); + + const warnings = []; + const captureWarning = msg => warnings.push( msg ); - var options = extend( { + const options = extend( { entry: FUNCTION + '/' + dir + '/main.js', onwarn: captureWarning }, config.options ); @@ -144,17 +199,18 @@ describe( 'rollup', function () { if ( config.solo ) console.group( dir ); return rollup.rollup( options ) - .then( function ( bundle ) { - var unintendedError; + .then( bundle => { + let unintendedError; if ( config.error ) { throw new Error( 'Expected an error while rolling up' ); } + let result; + // try to generate output try { - if(config.bundleOptions) { console.log(config.bundleOptions); } - var result = bundle.generate( extend( {}, config.bundleOptions, { + result = bundle.generate( extend( {}, config.bundleOptions, { format: 'cjs' })); @@ -172,37 +228,27 @@ describe( 'rollup', function () { if ( unintendedError ) throw unintendedError; if ( config.error || config.generateError ) return; - var code; + let code = result.code; - if ( config.babel ) { - code = babel.transform( result.code, { - blacklist: [ 'es6.modules' ], - loose: [ 'es6.classes' ] + if ( config.buble ) { + code = buble.transform( code, { + transforms: { modules: false } }).code; - } else { - code = result.code; } if ( config.code ) config.code( code ); - var module = { + const module = { exports: {} }; - var context = extend({ - require: require, - module: module, - exports: module.exports, - assert: assert - }, config.context || {} ); + const context = extend({ require, module, assert, exports: module.exports }, config.context || {} ); - var contextKeys = Object.keys( context ); - var contextValues = contextKeys.map( function ( key ) { - return context[ key ]; - }); + const contextKeys = Object.keys( context ); + const contextValues = contextKeys.map( key => context[ key ] ); try { - var fn = new Function( contextKeys, code ); + const fn = new Function( contextKeys, code ); fn.apply( {}, contextValues ); if ( config.runtimeError ) { @@ -219,20 +265,20 @@ describe( 'rollup', function () { } } + if ( config.show || unintendedError ) { + console.log( result.code + '\n\n\n' ); + } + if ( config.warnings ) { config.warnings( warnings ); } else if ( warnings.length ) { throw new Error( `Got unexpected warnings:\n${warnings.join('\n')}` ); } - if ( config.show || unintendedError ) { - console.log( code + '\n\n\n' ); - } - if ( config.solo ) console.groupEnd(); if ( unintendedError ) throw unintendedError; - }, function ( err ) { + }, err => { if ( config.error ) { config.error( err ); } else { @@ -243,32 +289,48 @@ describe( 'rollup', function () { }); }); - describe( 'form', function () { - sander.readdirSync( FORM ).sort().forEach( function ( dir ) { + describe( 'form', () => { + sander.readdirSync( FORM ).sort().forEach( dir => { if ( dir[0] === '.' ) return; // .DS_Store... - var config = loadConfig( FORM + '/' + dir + '/_config.js' ); + const config = loadConfig( FORM + '/' + dir + '/_config.js' ); if ( config.skipIfWindows && process.platform === 'win32' ) return; - - var options = extend( {}, config.options, { - entry: FORM + '/' + dir + '/main.js' - }); - - ( config.skip ? describe.skip : config.solo ? describe.only : describe)( dir, function () { - PROFILES.forEach( function ( profile ) { - it( 'generates ' + profile.format, function () { - return rollup.rollup( options ).then( function ( bundle ) { - var options = extend( {}, config.options, { + if ( !config.options ) { + config.options = {}; + } + if ( !( 'indent' in config.options ) ) { + config.options.indent = true; + } + + const options = extend( {}, { + entry: FORM + '/' + dir + '/main.js', + onwarn: msg => { + if ( /No name was provided for/.test( msg ) ) return; + if ( /as external dependency/.test( msg ) ) return; + console.error( msg ); + } + }, config.options ); + + ( config.skip ? describe.skip : config.solo ? describe.only : describe )( dir, () => { + let promise; + const createBundle = () => ( promise || ( promise = rollup.rollup( options ) ) ); + + PROFILES.forEach( profile => { + it( 'generates ' + profile.format, () => { + process.chdir( FORM + '/' + dir ); + + return createBundle().then( bundle => { + const options = extend( {}, config.options, { dest: FORM + '/' + dir + '/_actual/' + profile.format + '.js', format: profile.format }); - return bundle.write( options ).then( function () { - var actualCode = normaliseOutput( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ) ); - var expectedCode; - var actualMap; - var expectedMap; + return bundle.write( options ).then( () => { + const actualCode = normaliseOutput( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js' ) ); + let expectedCode; + let actualMap; + let expectedMap; try { expectedCode = normaliseOutput( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js' ) ); @@ -279,12 +341,16 @@ describe( 'rollup', function () { try { actualMap = JSON.parse( sander.readFileSync( FORM, dir, '_actual', profile.format + '.js.map' ).toString() ); actualMap.sourcesContent = actualMap.sourcesContent.map( normaliseOutput ); - } catch ( err ) {} + } catch ( err ) { + assert.equal( err.code, 'ENOENT' ); + } try { expectedMap = JSON.parse( sander.readFileSync( FORM, dir, '_expected', profile.format + '.js.map' ).toString() ); expectedMap.sourcesContent = expectedMap.sourcesContent.map( normaliseOutput ); - } catch ( err ) {} + } catch ( err ) { + assert.equal( err.code, 'ENOENT' ); + } if ( config.show ) { console.log( actualCode + '\n\n\n' ); @@ -300,32 +366,33 @@ describe( 'rollup', function () { }); }); - describe( 'sourcemaps', function () { - sander.readdirSync( SOURCEMAPS ).sort().forEach( function ( dir ) { + describe( 'sourcemaps', () => { + sander.readdirSync( SOURCEMAPS ).sort().forEach( dir => { if ( dir[0] === '.' ) return; // .DS_Store... - describe( dir, function () { - var config = loadConfig( SOURCEMAPS + '/' + dir + '/_config.js' ); + describe( dir, () => { + process.chdir( SOURCEMAPS + '/' + dir ); + const config = loadConfig( SOURCEMAPS + '/' + dir + '/_config.js' ); - var entry = path.resolve( SOURCEMAPS, dir, 'main.js' ); - var dest = path.resolve( SOURCEMAPS, dir, '_actual/bundle.js' ); + const entry = path.resolve( SOURCEMAPS, dir, 'main.js' ); + const dest = path.resolve( SOURCEMAPS, dir, '_actual/bundle' ); - var options = extend( {}, config.options, { - entry: entry - }); + const options = extend( {}, config.options, { entry }); - PROFILES.forEach( function ( profile ) { - ( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () { - return rollup.rollup( options ).then( function ( bundle ) { - var options = extend( {}, { + PROFILES.forEach( profile => { + ( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, () => { + process.chdir( SOURCEMAPS + '/' + dir ); + return rollup.rollup( options ).then( bundle => { + const options = extend( {}, { format: profile.format, sourceMap: true, - dest: dest + dest: `${dest}.${profile.format}.js` }, config.options ); bundle.write( options ); - var result = bundle.generate( options ); + if ( config.before ) config.before(); + const result = bundle.generate( options ); config.test( result.code, result.map ); }); }); @@ -334,45 +401,42 @@ describe( 'rollup', function () { }); }); - describe( 'cli', function () { - sander.readdirSync( CLI ).sort().forEach( function ( dir ) { + describe( 'cli', () => { + sander.readdirSync( CLI ).sort().forEach( dir => { if ( dir[0] === '.' ) return; // .DS_Store... - describe( dir, function () { - var config = loadConfig( CLI + '/' + dir + '/_config.js' ); + describe( dir, () => { + const config = loadConfig( CLI + '/' + dir + '/_config.js' ); - ( config.skip ? it.skip : config.solo ? it.only : it )( dir, function ( done ) { - process.chdir( path.resolve( CLI, dir ) ); + ( config.skip ? it.skip : config.solo ? it.only : it )( dir, done => { + process.chdir( config.cwd || path.resolve( CLI, dir ) ); - if (os.platform() === 'win32') { - config.command = "node " + path.resolve( __dirname, '../bin' ) + path.sep + config.command; - } + const command = 'node ' + path.resolve( __dirname, '../bin' ) + path.sep + config.command; - exec( config.command, { - env: { - PATH: path.resolve( __dirname, '../bin' ) + path.delimiter + process.env.PATH - } - }, function ( err, code, stderr ) { - if ( err || config.error ) { - config.error( err ); - return done(); + exec( command, {}, ( err, code, stderr ) => { + if ( err ) { + if ( config.error ) { + config.error( err ); + return done(); + } else { + throw err; + } } if ( stderr ) console.error( stderr ); - var unintendedError; + let unintendedError; if ( config.execute ) { try { - if ( config.babel ) { - code = babel.transform( code, { - blacklist: [ 'es6.modules' ], - loose: [ 'es6.classes' ] + if ( config.buble ) { + code = buble.transform( code, { + transforms: { modules: false } }).code; } - var fn = new Function( 'require', 'module', 'exports', 'assert', code ); - var module = { + const fn = new Function( 'require', 'module', 'exports', 'assert', code ); + const module = { exports: {} }; fn( require, module, module.exports, assert ); @@ -404,13 +468,28 @@ describe( 'rollup', function () { else if ( config.result ) { try { config.result( code ); + done(); } catch ( err ) { done( err ); } } + else if ( sander.existsSync( '_expected' ) && sander.statSync( '_expected' ).isDirectory() ) { + let error = null; + sander.readdirSync( '_expected' ).forEach( child => { + const expected = sander.readFileSync( path.join( '_expected', child ) ).toString(); + const actual = sander.readFileSync( path.join( '_actual', child ) ).toString(); + try { + assert.equal( normaliseOutput( actual ), normaliseOutput( expected ) ); + } catch ( err ) { + error = err; + } + }); + done( error ); + } + else { - var expected = sander.readFileSync( '_expected.js' ).toString(); + const expected = sander.readFileSync( '_expected.js' ).toString(); try { assert.equal( normaliseOutput( code ), normaliseOutput( expected ) ); done(); @@ -423,4 +502,224 @@ describe( 'rollup', function () { }); }); }); + + describe( 'incremental', () => { + function executeBundle ( bundle ) { + const cjs = bundle.generate({ format: 'cjs' }); + const m = new Function( 'module', 'exports', cjs.code ); + + const module = { exports: {} }; + m( module, module.exports ); + + return module.exports; + } + + let resolveIdCalls; + let transformCalls; + let modules; + + const plugin = { + resolveId: id => { + resolveIdCalls += 1; + return id; + }, + + load: id => { + return modules[ id ]; + }, + + transform: code => { + transformCalls += 1; + return code; + } + }; + + beforeEach( () => { + resolveIdCalls = 0; + transformCalls = 0; + + modules = { + entry: `import foo from 'foo'; export default foo;`, + foo: `export default 42`, + bar: `export default 21` + }; + }); + + it('does not resolves id and transforms in the second time', () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + assert.equal( resolveIdCalls, 2 ); + assert.equal( transformCalls, 2 ); + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ], + cache: bundle + }); + }).then( bundle => { + assert.equal( resolveIdCalls, 3 ); // +1 for entry point which is resolved every time + assert.equal( transformCalls, 2 ); + assert.equal( executeBundle( bundle ), 42 ); + }); + }); + + it('transforms modified sources', () => { + let cache; + + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + assert.equal( transformCalls, 2 ); + assert.equal( executeBundle( bundle ), 42 ); + + modules.foo = `export default 43`; + cache = bundle; + }).then( () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ], + cache + }); + }).then( bundle => { + assert.equal( transformCalls, 3 ); + assert.equal( executeBundle( bundle ), 43 ); + }); + }); + + it('resolves id of new imports', () => { + let cache; + + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + assert.equal( resolveIdCalls, 2 ); + assert.equal( executeBundle( bundle ), 42 ); + + modules.entry = `import bar from 'bar'; export default bar;`; + cache = bundle; + }).then( () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ], + cache + }); + }).then( bundle => { + assert.equal( resolveIdCalls, 4 ); + assert.equal( executeBundle( bundle ), 21 ); + }); + }); + + it( 'keeps ASTs between runs', () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + const asts = {}; + bundle.modules.forEach( module => { + asts[ module.id ] = module.ast; + }); + + assert.deepEqual( asts.entry, acorn.parse( modules.entry, { sourceType: 'module' }) ); + assert.deepEqual( asts.foo, acorn.parse( modules.foo, { sourceType: 'module' }) ); + }); + }); + }); + + describe( 'hooks', () => { + it( 'passes bundle & output object to ongenerate & onwrite hooks', () => { + const dest = path.join( __dirname, 'tmp/bundle.js' ); + + return rollup.rollup({ + entry: 'entry', + plugins: [ + loader({ entry: `alert('hello')` }), + { + ongenerate ( bundle, out ) { + out.ongenerate = true; + }, + + onwrite (bundle, out ) { + assert.equal(out.ongenerate, true); + } + } + ] + }).then( bundle => { + return bundle.write({ + dest + }); + }).then( () => { + return sander.unlink( dest ); + }); + }); + + it( 'calls ongenerate hooks in sequence', () => { + const result = []; + + return rollup.rollup({ + entry: 'entry', + plugins: [ + loader({ entry: `alert('hello')` }), + { + ongenerate ( info ) { + result.push({ a: info.format }); + } + }, + { + ongenerate ( info ) { + result.push({ b: info.format }); + } + } + ] + }).then( bundle => { + bundle.generate({ format: 'cjs' }); + + assert.deepEqual( result, [ + { a: 'cjs' }, + { b: 'cjs' } + ]); + }); + }); + + it( 'calls onwrite hooks in sequence', () => { + const result = []; + const dest = path.join( __dirname, 'tmp/bundle.js' ); + + return rollup.rollup({ + entry: 'entry', + plugins: [ + loader({ entry: `alert('hello')` }), + { + onwrite ( info ) { + return new Promise( ( fulfil ) => { + result.push({ a: info.dest, format: info.format }); + fulfil(); + }); + } + }, + { + onwrite ( info ) { + result.push({ b: info.dest, format: info.format }); + } + } + ] + }).then( bundle => { + return bundle.write({ + dest, + format: 'cjs' + }); + + + }).then( () => { + assert.deepEqual( result, [ + { a: dest, format: 'cjs' }, + { b: dest, format: 'cjs' } + ]); + + return sander.unlink( dest ); + }); + }); + }); }); diff --git a/test/utils/getLocation.js b/test/utils/getLocation.js index 49939976551..034e00ec206 100644 --- a/test/utils/getLocation.js +++ b/test/utils/getLocation.js @@ -1,10 +1,12 @@ -module.exports = function getLocation ( source, charIndex ) { +module.exports = function getLocation ( source, search ) { var lines = source.split( '\n' ); var len = lines.length; var lineStart = 0; var i; + const charIndex = typeof search === 'number' ? search : source.indexOf( search ); + for ( i = 0; i < len; i += 1 ) { var line = lines[i]; var lineEnd = lineStart + line.length + 1; // +1 for newline @@ -17,4 +19,4 @@ module.exports = function getLocation ( source, charIndex ) { } throw new Error( 'Could not determine location of character' ); -} +};