diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..6df029f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +test/* +!test/test.js diff --git a/.eslintrc b/.eslintrc index 0f98dff..d9150f9 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 0000000..4e2b499 --- /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 0000000..d2882ac --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ + diff --git a/.gitignore b/.gitignore index 55804cb..f5abf8d 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 9a040ed..83d1bca 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 03d0f1a..ef52701 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 ae037ce..ec3180a 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 6e02e51..25d1958 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 1cc19b6..0000000 --- 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 0000000..80892fd --- /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 46886c7..58482d5 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 0000000..cbc8123 --- /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 0000000..84cd3da --- /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 0000000..e7c4265 --- /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 0000000..279ba66 --- /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 06b8309..0000000 --- a/browser/promise.js +++ /dev/null @@ -1 +0,0 @@ -export default window.Promise; diff --git a/package.json b/package.json index be499e9..ea85120 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 adee949..95977b4 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 0000000..982f6b0 --- /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 521d614..cc0b9ba 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 95c0d10..9c6b44d 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 0601606..88f5553 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 db9c062..e532f25 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 175ecd5..ecb22f8 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 5c5c3e9..0000000 --- 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 3c00c36..0000000 --- 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 0000000..6a80ede --- /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 0dc48ec..0000000 --- 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 51fc28a..0000000 --- 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 b21e4d4..0000000 --- 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 e767dbd..0000000 --- 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 0000000..6a86dab --- /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 a1573e7..0000000 --- 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 0000000..194ccf7 --- /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 3696fd1..0000000 --- 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 0000000..ff60919 --- /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 0000000..8d9a3d2 --- /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 0000000..bbbb7d0 --- /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 0000000..da3d4da --- /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 0000000..d83d321 --- /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 0000000..720e866 --- /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 0000000..f1a1daa --- /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 0000000..63f1399 --- /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 0000000..9c7b444 --- /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 0000000..5f7309c --- /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 0000000..a0f5308 --- /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 0000000..94c2784 --- /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 0000000..3f9ba4e --- /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 0000000..7198541 --- /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 0000000..1872b96 --- /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 0000000..a5225f8 --- /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 0000000..11e98e5 --- /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 0000000..dffed95 --- /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 0000000..4d170af --- /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 0000000..836462b --- /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 0000000..fe83a78 --- /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 0000000..0edc68b --- /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 0000000..3b54f14 --- /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 0000000..eca57a2 --- /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 0000000..8bfbb33 --- /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 0000000..724cb00 --- /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 0000000..bff5ae1 --- /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 0000000..b25ef48 --- /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 0000000..ae35173 --- /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 0000000..4e9047b --- /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 0000000..9be1c2c --- /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 0000000..9fcea9d --- /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 0000000..77f4433 --- /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 0000000..dc35bff --- /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 0000000..1c3ba4c --- /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 0000000..5667652 --- /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 0000000..2ec7d17 --- /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 0000000..6df76d1 --- /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 0000000..a40969f --- /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 0000000..d33561a --- /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 3642a05..3301085 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 0000000..6c0f0ea --- /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 0000000..5a18d6f --- /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 0000000..2c250a8 --- /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 0cecbde..2000c89 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 0000000..b23de12 --- /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 0000000..dadd74a --- /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 7f63305..64adffd 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 f6302ff..e89ef32 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 bd3f93f..8251fe3 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 adb7019..01d1325 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 3ada90a..1089ccb 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 0000000..7764bdc --- /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 972da59..5a7f34f 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 67a26d7..6ecdba0 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 0000000..72ad1bb --- /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 0ec344e..dd8b9c6 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 77a97bd..cf79500 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 0000000..c7910e2 --- /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 ff86eaf..7a504ba 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 d52553e..2dc0b74 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 21d6fe3..7246246 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 0000000..9f32e45 --- /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 2afe00b..db790a9 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 f37ff1e..a3d00a0 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 8ad7b55..5130ed8 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 fd75ee8..846c42e 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 49e0942..6ce7293 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 5c8fd33..0000000 --- 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 b4e1ff1..947c8e1 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 ec749a4..d2ce64d 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 1730de8..096343c 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 0000000..e26bd02 --- /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 3e91d63..0000000 --- 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 b401370..2f0c167 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 f82bfb6..8569ad5 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 3ff51cd..d717b0a 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 e4491c2..0000000 --- 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 0000000..3f85d4c --- /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 2e30a3c..2d67639 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 0000000..c0df3fc --- /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 0000000..df16c1b --- /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 0000000..3cc995e --- /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 0000000..9f21d96 --- /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 0000000..d760df4 --- /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 0000000..cfefa8c --- /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 0000000..1036220 --- /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 0000000..9f3e784 --- /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 0000000..dcd8569 --- /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 a9d1307..e37aead 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 414587c..343dda2 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 da790e4..ca5d167 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 4a351ac..2f71587 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 0000000..6d7125c --- /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 0000000..d3b3eb0 --- /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 0000000..d88316a --- /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 0000000..9c36d9f --- /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 0000000..6cc964b --- /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 0000000..7f810d3 --- /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 0000000..1a2d8a1 --- /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 0000000..73d5d28 --- /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 0000000..98deb0c --- /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 0000000..d326592 --- /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 0000000..7f810d3 --- /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 0000000..f12e0c7 --- /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 0000000..cc870f8 --- /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 0000000..1b363c9 --- /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 0000000..ff8b4c5 --- /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 0000000..a1b8d7d --- /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 0000000..72d4a32 --- /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 0000000..d7c1012 --- /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 0000000..5c72ff3 --- /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 18d8b69..be25c45 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 0000000..88b1368 --- /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 0000000..b5aa08a --- /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 0000000..df16c1b --- /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 0000000..3cc995e --- /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 0000000..fbd4901 --- /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 0000000..88b1368 --- /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 0000000..b5aa08a --- /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 0000000..df16c1b --- /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 0000000..3cc995e --- /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 0000000..fbd4901 --- /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 0000000..1427619 --- /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 0000000..5c72ff3 --- /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 0000000..a2f129c --- /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 0000000..4718f2e --- /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 0000000..473b57e --- /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 0000000..0415d2c --- /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 0000000..cb9df4a --- /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 0000000..611df0c --- /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 0000000..3223031 --- /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 0000000..f0b4f66 --- /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 0f3d2ef..f7296e0 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 c2d0691..b6e6ac9 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 b062474..d291984 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 0000000..d4297e6 --- /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 08e82c9..0000000 --- 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 fa37538..09261c7 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 bbefc87..33b2140 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 0000000..3c9f6d4 --- /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 0000000..6f8d4d8 --- /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 0000000..9de4215 --- /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 0000000..e6c6e5f --- /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 0000000..3ac6c5f --- /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 0000000..80039f9 --- /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 0000000..bd12ed8 --- /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 1432418..1e1367f 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 3e3bef0..29d8c60 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 356ff47..9fa72aa 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 c00edfa..6afff4a 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 0000000..a748fa0 --- /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 0000000..464893d --- /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 0000000..f2e4fde --- /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 0000000..63ee4e5 --- /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 0000000..2214bd4 --- /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 0000000..9840021 --- /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 0000000..3aa7b7e --- /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 0000000..823ac63 --- /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 0000000..8ee5782 --- /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 0000000..04e5550 --- /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 0000000..1c21cb3 --- /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 0000000..7d1e8f9 --- /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 0000000..9d40700 --- /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 0000000..3595594 --- /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 0000000..b3747d0 --- /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 0000000..d8169ae --- /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 0ccd4d8..cafa262 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 443bab3..77f714c 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 ae57683..2939979 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 8254c77..8d6ea73 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 0000000..84f2dbd --- /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 0000000..a160d17 --- /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 0000000..f42cf3c --- /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 0000000..fa83c3d --- /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 0000000..a41619e --- /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 0000000..a73a22c --- /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 0000000..169f08b --- /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 0000000..c15118e --- /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 0000000..9274799 --- /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 0000000..35a5b08 --- /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 0000000..a6903e0 --- /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 0000000..7926fe6 --- /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 0000000..22fa605 --- /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 0000000..a5a991d --- /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 0000000..1323b68 --- /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 0000000..f5d68d2 --- /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 0000000..9274799 --- /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 0000000..35a5b08 --- /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 0000000..a6903e0 --- /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 0000000..7926fe6 --- /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 0000000..22fa605 --- /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 0000000..a5a991d --- /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 0000000..1323b68 --- /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 7f52eda..a503cb3 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 fd4138b..ede4836 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 06be0e7..f6ef0fe 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 0000000..4c3038c --- /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 0000000..b43e2a4 --- /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 0000000..e47b61a --- /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 0000000..cacf6d2 --- /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 0000000..106066a --- /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 0000000..4574799 --- /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 0000000..1eabb5b --- /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 0000000..79abe74 --- /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 0000000..a7c1b48 --- /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 0000000..51c5f3b --- /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 0000000..0aafee1 --- /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 0000000..406ab3a --- /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 0000000..33518c0 --- /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 0000000..7ba1241 --- /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 0000000..79abe74 --- /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 0000000..c252e26 --- /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 0000000..197b73e --- /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 0000000..3869419 --- /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 0000000..7ca26c8 --- /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 0000000..08ef206 --- /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 0000000..122bf0f --- /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 0000000..283b0b6 --- /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 0000000..6036f28 --- /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 0000000..33f9de0 --- /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 0000000..472e544 --- /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 0000000..08a84a9 --- /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 0000000..0aae43f --- /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 0000000..edca010 --- /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 0000000..00672ed --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..8b04429 --- /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 0000000..b95837c --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..cb706f7 --- /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 0000000..4a7bd91 --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..e591dde --- /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 0000000..f448ddf --- /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 0000000..6036f28 --- /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 0000000..33f9de0 --- /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 0000000..472e544 --- /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 0000000..08a84a9 --- /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 0000000..0aae43f --- /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 0000000..3b5d176 --- /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 0000000..abea889 --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..6db9dc1 --- /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 0000000..dc10538 --- /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 0000000..9114028 --- /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 0000000..9b5e04a --- /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 0000000..04006b3 --- /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 0000000..45b92d8 --- /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 0000000..08026c7 --- /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 0000000..b6b36cf --- /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 0000000..76e4fa3 --- /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 0000000..d7ee383 --- /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 0000000..2ad8cd2 --- /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 0000000..b149085 --- /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 0000000..c9dbff5 --- /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 0000000..e97ebff --- /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 0000000..43f7037 --- /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 0000000..29c0517 --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..58da4d4 --- /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 0000000..70bf652 --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..52ed8c1 --- /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 0000000..8db2e7f --- /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 0000000..e44e556 --- /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 0000000..1afb143 --- /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 0000000..f97f3d0 --- /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 0000000..39aedbf --- /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 0000000..0445193 --- /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 0000000..c499a7f --- /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 6499b90..4b402c7 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 aa4b949..01c96f9 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 34c4e2e..ee4eace 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 4233cfe..8a8d65e 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 d11bd9f..94dee16 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 d5cd1bd..457d3c2 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 6b0c47e..c3acbb0 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 869bba0..e208b74 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 b249cc6..5b39537 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 69c5a70..73b73a1 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 69c5a70..73b73a1 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 9158c43..c880afb 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 60037db..9cf5968 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 872c0d8..6e689d4 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 16d2890..2194031 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 663cb1e..fe8a09d 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 2612901..7138aff 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 57d55d3..f62037c 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 e9cbc8d..c6b382b 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 7be513d..29b64b4 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 1018b8a..c9464dd 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 07642a1..d57479b 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 1c632ef..59d2b5e 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 3feb767..4b3fbbf 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 0000000..3fc4a67 --- /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 0000000..a07e3e0 --- /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 0000000..f94dff7 --- /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 0000000..1690f25 --- /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 0000000..2217234 --- /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 0000000..3e90731 --- /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 0000000..5e492f8 --- /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 5655595..07d61c1 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 ddcdcbd..bd10a35 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 f3395b7..d561e69 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 0000000..30ffc5e --- /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 0000000..ec759b1 --- /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 0000000..eb109ab --- /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 0000000..f3d1016 --- /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 0000000..d561e69 --- /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 0000000..d98c18c --- /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 0000000..0b45d9e --- /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 0000000..b0ff512 --- /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 d09a506..c0289b0 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 fbc898e..51032c8 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 a2b634e..786d82b 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 a07cece..b6d7f90 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 0000000..0076e3a --- /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 0000000..9245883 --- /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 0000000..8396bc7 --- /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 0000000..d5e775e --- /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 0000000..d94c432 --- /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 0000000..5c9be13 --- /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 0000000..a6b1040 --- /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 36b7a9d..410d586 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 a58ac95..ca940e4 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 662c938..6c68e67 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 0000000..2da2a74 --- /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 c017a45..0000000 --- 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 15a21d9..2c716d3 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 c08f507..232db4e 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 3b5a604..663ee99 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 0000000..591c08e --- /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 0000000..4aba57b --- /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 0000000..3b66561 --- /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 0000000..f2c9a6a --- /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 0000000..a588fbb --- /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 0000000..aa0b4f7 --- /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 0000000..9f3d71c --- /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 0000000..2791550 --- /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 0000000..1905df3 --- /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 0000000..5fb5bd2 --- /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 0000000..10ecf7c --- /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 0000000..7b52e33 --- /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 0000000..9b60efd --- /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 0000000..fe542c0 --- /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 0000000..5585c1e --- /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 0000000..46fe09d --- /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 0000000..a461d8e --- /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 0000000..c1b004a --- /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 0000000..f904af3 --- /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 0000000..dab29e5 --- /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 0000000..19f8c91 --- /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 0000000..7c98779 --- /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 0000000..d434187 --- /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 0000000..e3a53f2 --- /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 0000000..5681881 --- /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 0000000..69586a0 --- /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 0000000..796e3ef --- /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 0000000..3ee7d0b --- /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 0000000..7445d49 --- /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 0000000..3382219 --- /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 0000000..816d625 --- /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 0000000..31fe8d4 --- /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 0000000..69586a0 --- /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 0000000..796e3ef --- /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 0000000..3ee7d0b --- /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 0000000..2f7b7b2 --- /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 0000000..22c8010 --- /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 0000000..816d625 --- /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 0000000..c466b88 --- /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 0000000..69586a0 --- /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 0000000..796e3ef --- /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 0000000..3ee7d0b --- /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 0000000..5eb1062 --- /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 0000000..8d90ff6 --- /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 0000000..816d625 --- /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 2ebff3b..0d70786 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 1968b8b..a5fbd76 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 30a54d6..4ccb2ba 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 30c5406..e2582cc 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 3ee6869..a826df2 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 8346d0d..85c15d8 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 6aeb1cd..6c497f5 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 866a3bd..7a2c4b0 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 a244c47..95231f1 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 b52a7e5..33a83e9 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 0000000..297521e --- /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 8bee044..0000000 --- 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 206c237..64673c9 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 67adf52..bf379ef 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 e902244..6b955f7 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 b06132b..9bc5096 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 21429fd..cec0f51 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 4b8935f..f58e06d 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 9a0f47d..474db1f 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 5c8c7d3..2a478bf 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 7bbe64b..eb4f6ca 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 c188f06..c65e700 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 54f2add..ddcec9b 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 2136453..cb1b283 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 0000000..92803d7 --- /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 0000000..aaad1ff --- /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 0000000..ef9e375 --- /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 0000000..9f19ab6 --- /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 0000000..611fa6e --- /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 0000000..9015af2 --- /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 0000000..9f19ab6 --- /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 a3e661b..3a1aeb7 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 0000000..2d1f055 --- /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 0000000..0893293 --- /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 0000000..4bb0804 --- /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 0000000..74bfea3 --- /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 0000000..28acdd1 --- /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 0000000..e86e892 --- /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 0000000..2b26e36 --- /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 0000000..2895b21 --- /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 0000000..a13383c --- /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 0000000..f80ea9b --- /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 0000000..2462c87 --- /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 0000000..28acdd1 --- /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 0000000..02bcdaf --- /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 0000000..c01e9a1 --- /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 0000000..1d6ed03 --- /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 0000000..0893293 --- /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 0000000..4bb0804 --- /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 0000000..74bfea3 --- /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 0000000..28acdd1 --- /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 0000000..e86e892 --- /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 0000000..2b26e36 --- /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 0c54878..0ec9750 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 dd19c2d..a6ca635 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 82a0a52..8271ac9 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 8b15cd1..723b1cb 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 13a54bf..b1cc6a5 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 0000000..677bef1 --- /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 0000000..538e97a --- /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 0000000..1b74d56 --- /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 0000000..fe8f7cf --- /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 0000000..a0efcee --- /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 0000000..5ab1989 --- /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 0000000..750ac95 --- /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 e614344..b89e399 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 d7a8df2..1152d76 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 c458828..0ef1000 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 5867d0f..cac12fb 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 ef0186e..9a6706d 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 0000000..d20f89b --- /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 0000000..ad714bd --- /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 0000000..83a7a20 --- /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 0000000..8e997b2 --- /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 0000000..bb848ad --- /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 0000000..a9fd5b2 --- /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 0000000..7ec54d9 --- /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 0000000..3acb040 --- /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 0000000..ec759b1 --- /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 0000000..eb109ab --- /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 0000000..e69de29 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 0000000..f3d1016 --- /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 0000000..d561e69 --- /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 0000000..76ff633 --- /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 f828537..831b45c 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 1a19210..9d64f6a 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 16d2890..2194031 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 16d2890..2194031 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 16d2890..2194031 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 ef3393d..4a3316f 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 16d2890..2194031 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 16d2890..2194031 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 16d2890..2194031 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 b090f9a..87d4d59 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 2da816b..1d7d727 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 e903a01..abfcb98 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 7ee74b0..8219021 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 0cbda65..8647986 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 bccee01..eeb57d4 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 5b7f3d6..302275a 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 0000000..e69de29 diff --git a/test/form/side-effect-l/_expected/umd.js b/test/form/side-effect-l/_expected/umd.js index f3395b7..d561e69 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 8c7787a..af4a5b5 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 43eacf4..1e7377f 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 61bbbbf..d4df0da 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 d4be68e..0d378a8 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 902026f..38f9417 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 c792f48..f83037e 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 80d69a3..38b9a1d 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 0000000..7a8d84b --- /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 0000000..7a76cb7 --- /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 0000000..9553e7d --- /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 0000000..c6eddb2 --- /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 0000000..7ab23ea --- /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 0000000..57553d3 --- /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 0000000..ff3177b --- /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 0000000..1ee7791 --- /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 0000000..944a58a --- /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 0000000..ec759b1 --- /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 0000000..eb109ab --- /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 0000000..e69de29 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 0000000..f3d1016 --- /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 0000000..d561e69 --- /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 0000000..2272edb --- /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 0000000..3a59976 --- /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 0000000..f9f8229 --- /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 0000000..eb109ab --- /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 0000000..8b13789 --- /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 0000000..43ef542 --- /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 0000000..07ce27e --- /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 0000000..716ee31 --- /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 0000000..457689e --- /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 0000000..f9f8229 --- /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 0000000..eb109ab --- /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 0000000..8b13789 --- /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 0000000..43ef542 --- /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 0000000..07ce27e --- /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 0000000..3d63fdf --- /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 79b4cc2..e0961e0 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 0000000..22c399c --- /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 0000000..c192900 --- /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 0000000..b3e974b --- /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 0000000..ec9eb20 --- /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 0000000..3b894d9 --- /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 0000000..b3926b0 --- /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 0000000..8674142 --- /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 0000000..9dc50f5 --- /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 0000000..d6aa952 --- /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 0000000..f39bfec --- /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 0000000..8d6dcb5 --- /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 0000000..67588d4 --- /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 0000000..9779139 --- /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 0000000..9dc50f5 --- /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 0000000..d6aa952 --- /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 0000000..f39bfec --- /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 0000000..8d6dcb5 --- /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 0000000..67588d4 --- /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 0000000..d290c80 --- /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 0000000..9dc50f5 --- /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 0000000..d6aa952 --- /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 0000000..f39bfec --- /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 0000000..8d6dcb5 --- /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 0000000..67588d4 --- /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 0000000..9ac1d23 --- /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 0000000..9dc50f5 --- /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 0000000..d6aa952 --- /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 0000000..f39bfec --- /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 0000000..8d6dcb5 --- /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 0000000..67588d4 --- /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 0000000..f592e05 --- /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 0000000..41371dd --- /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 0000000..44cffbf --- /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 0000000..93d5198 --- /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 0000000..ce654f4 --- /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 0000000..40a0a54 --- /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 0000000..352481e --- /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 0000000..85e8fbe --- /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 0000000..6847fcb --- /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 0000000..6f1ef21 --- /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 0000000..788788a --- /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 0000000..88532fd --- /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 0000000..6286b12 --- /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 0000000..7808b0d --- /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 0000000..85e8fbe --- /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 0000000..6847fcb --- /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 0000000..6f1ef21 --- /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 0000000..788788a --- /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 0000000..88532fd --- /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 0000000..6286b12 --- /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 0000000..6380bcf --- /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 0000000..078856d --- /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 0000000..9dc50f5 --- /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 0000000..d6aa952 --- /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 0000000..f39bfec --- /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 0000000..8d6dcb5 --- /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 0000000..67588d4 --- /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 f1d6ef7..c7263f8 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 0000000..ec8dd24 --- /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 5e77403..118c092 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 0000000..b823f1d --- /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 c07d67a..0000000 --- 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 b934854..ab7ebf4 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 2b48a49..0000000 --- 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 37f42f3..4db965c 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 503ea73..bac28c1 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 0000000..f5b5029 --- /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 3b3f5e7..0000000 --- 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 7ff78ec..f8d6992 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 56bca25..75d31a1 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 f646cb2..2eb44c9 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 7c799d3..8432e6e 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 7ab432c..6cd3b5a 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 ae8c969..6907cdb 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 ad0bc29..47597be 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 285a53f..ac7131e 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 0000000..7513402 --- /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 0000000..c90e975 --- /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 0000000..c99ffc5 --- /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 0000000..686db33 --- /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 0000000..f82edce --- /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 0000000..996e798 --- /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 5c82fb4..4fcdf42 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 0000000..417e38f --- /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 0000000..69904ec --- /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 0000000..72dd9eb --- /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 0000000..3a0913b --- /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 0000000..9bdbe7b --- /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 0000000..c7dad30 --- /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 0000000..934dee7 --- /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 6b54ad3..61af11d 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 9bbcec6..9429457 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 16ca409..f2fd756 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 4379f50..0595288 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 5578ce9..89e0448 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 07f1781..81d4424 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 d83a806..f74ed8e 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 0000000..0f1029d --- /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 0000000..f0cc768 --- /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 0000000..b808398 --- /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 0000000..f24d612 --- /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 0000000..bc7e275 --- /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 0000000..1469ca3 --- /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 0000000..56a0ceb --- /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 0000000..e19ff25 --- /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 0000000..3e476bb --- /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 0000000..0f1029d --- /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 0000000..8be9631 --- /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 0000000..9cd0d53 --- /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 0000000..1ea92fc --- /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 0000000..ccdb513 --- /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 0000000..e3ea51f --- /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 0000000..25de8d8 --- /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 8c9c2e0..b38f629 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 0000000..b89eb86 --- /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 0000000..babb23a --- /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 0000000..8628267 --- /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 0000000..2e13c75 --- /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 0000000..a9b45df --- /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 0000000..71ba44f --- /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 0000000..3b60a87 --- /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 0000000..1b3e409 --- /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 ae6ce6f..e260775 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 0000000..bb17123 --- /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 0000000..b2602d2 --- /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 0000000..c6ddba4 --- /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 0000000..bb17123 --- /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 0000000..7dc8833 --- /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 0000000..ae0bdb2 --- /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 0000000..bb17123 --- /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 0000000..14d0105 --- /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 0000000..2a031e5 --- /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 0000000..63f2a11 --- /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 0000000..547a9a5 --- /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 d4afdc3..e21b4a0 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 0000000..3204f3c --- /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 0000000..637a0ee --- /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 0000000..9694314 --- /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 0000000..a430876 --- /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 0000000..766cb6f --- /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 0000000..a06632d --- /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 0b31fd0..99bfc6e 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 bbcebcf..58e154c 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 1b0bbf2..3d2e253 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 1b8b173..f1b3ee6 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 b97aab5..bd84240 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 0d1985f..26a060c 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 b0004b7..c31c2ff 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 4fa443e..e93e16a 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 0766b6c..b41282b 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 05cf37a..cb2da0c 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 0000000..87ba7d6 --- /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 0000000..1a4723b --- /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 0000000..da8f42e --- /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 0000000..b7d9f07 --- /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 0000000..06bcc6e --- /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 0000000..155e2f6 --- /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 0000000..c77b86b --- /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 0000000..b93201c --- /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 0000000..60a9826 --- /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 0000000..1580611 --- /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 0000000..e73df11 --- /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 0000000..c3e2ed3 --- /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 0000000..2f49591 --- /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 4e939af..f6d8526 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 0000000..633aacc --- /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 0000000..8f88528 --- /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 0000000..6f6f410 --- /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 0000000..89ff7de --- /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 0451342..a210a0f 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 92debd4..a1aed25 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 0000000..4280924 --- /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 0000000..f3f6547 --- /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 0000000..a8e4f7c --- /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 0000000..6aa8dfa --- /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 4a5902c..3495183 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 0000000..ef24d01 --- /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 26e86e7..d5f5254 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 0000000..b3885d2 --- /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 0000000..0dfd7e9 --- /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 0000000..a7b877b --- /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 0000000..467f528 --- /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 0000000..ae6aade --- /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 577b421..169ce76 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 577b421..169ce76 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 0000000..4f880de --- /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 0000000..3708aaa --- /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 0000000..b2b8034 --- /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 0000000..d5de425 --- /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 0000000..3c54230 --- /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 0000000..e2b1718 --- /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 3171eed..ed89b85 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 3cb321f..245bdaf 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 263c8d1..1d77b9b 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 333c68b..7500be3 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 0000000..4fa4888 --- /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 0000000..1ec6df4 --- /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 0000000..8c72ffc --- /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 0000000..9b7c1d7 --- /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 0000000..dcbe278 --- /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 0000000..88b207f --- /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 0000000..1ec6df4 --- /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 0000000..499b332 --- /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 0000000..9b7c1d7 --- /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 0000000..dcbe278 --- /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 0000000..b2f3e1a --- /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 0000000..7a4e8a7 --- /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 0000000..3206f53 --- /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 0000000..51b503d --- /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 0000000..26a1db8 --- /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 0000000..7511028 --- /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 0000000..eedb4fb --- /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 0000000..6c573d5 --- /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 0000000..e885c22 --- /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 0000000..b7eda7a --- /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 0000000..59bf4fd --- /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 0000000..8601e12 --- /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 0000000..7ab3055 --- /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 f1d7ee1..110fa77 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 d1dc2b9..3672452 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 5e59ef1..e3201e1 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 622d7d9..a08ff3c 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 e7749d0..02a6302 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 562c561..e6cacef 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 3027ba9..10d11a6 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 0000000..3eab340 --- /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 0000000..c196b10 --- /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 0000000..ba2c4ee --- /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 0000000..e226472 --- /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 0000000..c374794 --- /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 0000000..bfb78e8 --- /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 0000000..97b3be8 --- /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 0000000..d68f4e7 --- /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 0000000..a6071df --- /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 0000000..91a1fb7 --- /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 0000000..1938dee --- /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 0000000..7c47804 --- /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 0000000..422c084 --- /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 bf7e6fc..3166462 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 0000000..553ab2b --- /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 0000000..76340f6 --- /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 0000000..1df02c2 --- /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 0000000..f257022 --- /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 0000000..0ff2bf9 --- /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 0000000..6d70fec --- /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 69f1405..6ecf3b9 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 0000000..b6d1881 --- /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 0000000..170cfff --- /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 0000000..64cbdca --- /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 0000000..1efaca7 --- /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 0000000..4684296 --- /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 0000000..c69a6e4 --- /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 0000000..b6d1881 --- /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 0000000..64cbdca --- /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 0000000..02c772f --- /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 0000000..8746123 --- /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 0000000..025b117 --- /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 0000000..ac9d9da --- /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 0000000..1fbecc0 --- /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 76ebc57..85191d6 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 47ae3de..be6c448 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 37f86df..b5c37e0 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 4a1b8b6..cae5239 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 001b48f..1bcd2fa 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 0000000..81baecb --- /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 0000000..3f81b80 --- /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 0000000..e1fb5c4 --- /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 a0e607c..15e9598 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 e01d090..22591fe 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 0000000..1701a6f --- /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 0000000..6c68061 --- /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 0000000..d159c95 --- /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 0000000..7fe4a4d --- /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 0000000..16bfa0f --- /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 4e28079..46de4e1 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 bb15b49..0000000 --- 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 47111d5..0000000 --- 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 3cc97d3..0000000 --- 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 15deabf..0000000 --- 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 e43c622..0000000 --- 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 d1e507d..0000000 --- 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 0c271f4..0000000 --- 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 1278d35..0000000 --- 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 750d99a..0000000 --- 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 0000000..04963a3 --- /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 0000000..9ed266e --- /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 0000000..9097f52 --- /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 0000000..4e2e0f5 --- /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 0000000..c97907e --- /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 0000000..4e2e0f5 --- /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 6ce4fd3..5bdf0bc 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 0000000..dde47e2 --- /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 0000000..81ef7f7 --- /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 4ec5140..88a92e5 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 960eb69..cd9afd0 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 e9aab9a..916d71e 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 93a1364..fb99d24 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 0000000..166d6ee --- /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 0000000..0b35f91 --- /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 169171c..d6ac89f 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 0000000..99c3f2c --- /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 0000000..e3ca378 --- /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 0000000..1fca512 --- /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 0000000..18e60c8 --- /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 0000000..7eaceb9 --- /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 0000000..078771e --- /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 d2910f7..53a4526 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 0000000..2014d88 --- /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 0000000..40205b6 --- /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 0000000..64577b6 --- /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 0000000..57ff117 --- /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 0000000..6c3e77f --- /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 0000000..9ce4283 --- /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 0000000..df7e27a --- /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 0000000..8870098 --- /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 0000000..ab0c7db --- /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 0000000..565c1eb --- /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 5c12d05..1d72cda 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 0000000..ad33354 --- /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 0000000..5c72ff3 --- /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 b76a885..77b9354 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 22239fe..8b2b66f 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 4993997..034e00e 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' ); -} +};