├── .eslintrc.json ├── .gitattributes ├── .huskyrc ├── .lintstagedrc ├── .prettierrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── appveyor.yml ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── ast-utils.js ├── default-resolver.js ├── helpers.js ├── index.js ├── is-cjs.js ├── resolve-id.js ├── transform.js └── utils.js └── test ├── form ├── async-function │ ├── input.js │ └── output.js ├── constant-template-literal │ ├── input.js │ └── output.js ├── dynamic-template-literal │ ├── input.js │ └── output.js ├── ignore-ids-function │ ├── _config.js │ ├── input.js │ └── output.js ├── ignore-ids │ ├── _config.js │ ├── input.js │ └── output.js ├── multiple-var-declarations-b │ ├── input.js │ └── output.js ├── multiple-var-declarations-c │ ├── input.js │ └── output.js ├── multiple-var-declarations │ ├── input.js │ └── output.js ├── no-toplevel-return │ ├── input.js │ └── output.js ├── optimised-default-export-function-double-assign │ ├── input.js │ └── output.js ├── optimised-default-export-function │ ├── input.js │ └── output.js ├── optimised-default-export-iife │ ├── input.js │ └── output.js ├── optimised-default-export │ ├── input.js │ └── output.js ├── optimised-named-export-conflicts │ ├── input.js │ └── output.js ├── optimised-named-export │ ├── input.js │ └── output.js ├── require-collision │ ├── input.js │ └── output.js ├── typeof-module-exports │ ├── input.js │ └── output.js ├── unambiguous-with-default-export │ ├── input.js │ └── output.js ├── unambiguous-with-import │ ├── input.js │ └── output.js └── unambiguous-with-named-export │ ├── input.js │ └── output.js ├── function ├── __esModule │ ├── answer.js │ └── main.js ├── assign-properties-to-default-export │ ├── foo.js │ └── main.js ├── assumed-globals │ ├── _config.js │ ├── document.js │ └── main.js ├── bare-import-comment │ ├── bar.js │ ├── foo.js │ └── main.js ├── bare-import │ ├── _config.js │ ├── bar.js │ ├── foo.js │ └── main.js ├── basic │ ├── _config.js │ ├── foo.js │ └── main.js ├── deconflict-export-and-local │ ├── index.js │ ├── main.js │ └── someValue.js ├── dot │ ├── foo.bar.js │ └── main.js ├── duplicate-default-exports-b │ ├── main.js │ └── x.js ├── duplicate-default-exports-c │ ├── exports.js │ └── main.js ├── duplicate-default-exports │ ├── main.js │ └── x.js ├── export-default-from │ ├── _config.js │ ├── imported.js │ ├── main.js │ └── reexporter.js ├── exports │ ├── _config.js │ ├── foo.js │ └── main.js ├── external-imports │ ├── _config.js │ └── main.js ├── fallback-no-default │ ├── foo.js │ └── main.js ├── global-not-overwritten │ ├── _config.js │ ├── encode.js │ └── main.js ├── global-var │ └── main.js ├── index │ ├── foo │ │ └── index.js │ └── main.js ├── inline │ ├── _config.js │ ├── foo.js │ ├── main.js │ └── multiply.js ├── named-exports │ ├── foo.js │ └── main.js ├── optional-require │ ├── _config.js │ └── main.js ├── ordering │ ├── bar.js │ ├── foo.js │ ├── main.js │ └── shared.js ├── react-apollo │ ├── commonjs-bar.js │ ├── commonjs-foo.js │ └── main.js ├── reassignment │ ├── foo.js │ └── main.js ├── reexports │ ├── _config.js │ ├── bar.js │ ├── foo.js │ └── main.js ├── resolve-is-cjs-extension │ ├── _config.js │ ├── main.js │ └── second.x ├── resolve-is-cjs-filtered │ ├── _config.js │ ├── main.js │ └── second.js ├── shadowing │ └── main.js ├── skips-dead-branches │ ├── _config.js │ ├── a.js │ ├── b.js │ ├── c.js │ └── main.js ├── strict-fn-duplicates │ └── main.js ├── strict-should-fail │ ├── _config.js │ └── main.js ├── this │ ├── foo.js │ └── main.js ├── toplevel-return-complex │ ├── _config.js │ ├── bar.js │ ├── foo.js │ └── main.js ├── toplevel-return │ ├── _config.js │ ├── foo.js │ └── main.js ├── trailing-slash │ ├── foo │ │ └── index.js │ └── main.js └── typeof-require │ ├── foo.js │ └── main.js ├── node_modules ├── .gitkeep ├── bar │ └── index.js ├── baz │ └── index.js ├── external │ └── index.js └── foo │ └── index.js ├── samples ├── corejs │ └── literal-with-default.js ├── custom-named-exports-false-positive │ ├── main.js │ └── other.js ├── custom-named-exports │ ├── main.js │ └── secret-named-exporter.js ├── deconflict-helpers │ └── main.js ├── define-is-undefined │ ├── foo.js │ └── main.js ├── es-modules-without-default-export │ ├── main.js │ └── other.js ├── extension │ ├── foo.coffee │ └── main.coffee ├── external │ └── main.js ├── global-in-if-block │ └── main.js ├── global │ └── main.js ├── ignore-global │ ├── firstpass.js │ ├── identifier.js │ ├── main.js │ └── this.js ├── ignore-virtual-modules │ └── main.js ├── invalid-syntax │ └── main.js ├── multiple-entry-points │ ├── 2.js │ ├── 3.js │ ├── 4.js │ ├── b.js │ └── c.js ├── named-exports-from-object-literal │ ├── a.js │ ├── main.js │ └── other.js ├── other-transforms │ ├── bar.js │ ├── foo.js │ └── main.js ├── paren-expression │ └── index.js ├── reexport │ ├── export.js │ ├── main.js │ └── reexport.js ├── rename-index │ ├── invalid-var │ │ └── index.js │ ├── main.js │ ├── other │ │ └── nonIndex.js │ └── validVar │ │ └── index.js ├── reserved-as-property │ └── main.js ├── sourcemap │ ├── foo.js │ └── main.js ├── umd │ ├── correct-scoping.js │ ├── protobuf.js │ └── sinon.js └── use-own-output │ ├── from-rollup.js │ └── main.js └── test.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "rules": { 4 | "indent": [ 2, "tab", { "SwitchCase": 1 } ], 5 | "semi": [ 2, "always" ], 6 | "keyword-spacing": [ 2, { "before": true, "after": true } ], 7 | "space-before-blocks": [ 2, "always" ], 8 | "no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ], 9 | "no-cond-assign": 0, 10 | "no-unused-vars": 2, 11 | "object-shorthand": [ 2, "always" ], 12 | "no-const-assign": 2, 13 | "no-class-assign": 2, 14 | "no-this-before-super": 2, 15 | "no-var": 2, 16 | "no-unreachable": 2, 17 | "valid-typeof": 2, 18 | "quote-props": [ 2, "as-needed" ], 19 | "one-var": [ 2, "never" ], 20 | "prefer-arrow-callback": 2, 21 | "prefer-const": [ 2, { "destructuring": "all" } ], 22 | "arrow-spacing": 2 23 | }, 24 | "env": { 25 | "es6": true, 26 | "browser": true, 27 | "node": true 28 | }, 29 | "extends": [ 30 | "eslint:recommended", 31 | "plugin:import/errors", 32 | "plugin:import/warnings" 33 | ], 34 | "parserOptions": { 35 | "ecmaVersion": 8, 36 | "sourceType": "module" 37 | }, 38 | "settings": { 39 | "import/ignore": [ 0, [ 40 | "\\.path.js$" 41 | ] ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.huskyrc: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "post-commit": "git reset", 4 | "pre-commit": "lint-staged" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "{src/**/*,test/test,test/**/_config}.js": [ 3 | "prettier --write", 4 | "eslint --fix", 5 | "git add" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "useTabs": true, 4 | "printWidth": 100 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "8" 5 | - "10" 6 | env: 7 | global: 8 | - BUILD_TIMEOUT=10000 9 | install: npm install 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # rollup-plugin-commonjs changelog 2 | 3 | ## 9.2.0 4 | *2018-10-10* 5 | * Fix missing default warning, produce better code when importing known ESM default exports ([#349](https://github.com/rollup/rollup-plugin-commonjs/issues/349)) 6 | * Refactor code and add prettier ([#346](https://github.com/rollup/rollup-plugin-commonjs/issues/346)) 7 | 8 | ## 9.1.8 9 | *2018-09-18* 10 | * Ignore virtual modules created by other plugins ([#327](https://github.com/rollup/rollup-plugin-commonjs/issues/327)) 11 | * Add "location" and "process" to reserved words ([#330](https://github.com/rollup/rollup-plugin-commonjs/issues/330)) 12 | 13 | ## 9.1.6 14 | *2018-08-24* 15 | * Keep commonJS detection between instantiations ([#338](https://github.com/rollup/rollup-plugin-commonjs/issues/338)) 16 | 17 | ## 9.1.5 18 | *2018-08-09* 19 | * Handle object form of input ([#329](https://github.com/rollup/rollup-plugin-commonjs/issues/329)) 20 | 21 | ## 9.1.4 22 | *2018-07-27* 23 | * Make "from" a reserved word ([#320](https://github.com/rollup/rollup-plugin-commonjs/issues/320)) 24 | 25 | ## 9.1.3 26 | *2018-04-30* 27 | * Fix a caching issue ([#316](https://github.com/rollup/rollup-plugin-commonjs/issues/316)) 28 | 29 | ## 9.1.2 30 | *2018-04-30* 31 | * Re-publication of 9.1.0 32 | 33 | ## 9.1.1 34 | *2018-04-30* 35 | * Fix ordering of modules when using rollup 0.58 ([#302](https://github.com/rollup/rollup-plugin-commonjs/issues/302)) 36 | 37 | ## 9.1.0 38 | 39 | * Do not automatically wrap modules with return statements in top level arrow functions ([#302](https://github.com/rollup/rollup-plugin-commonjs/issues/302)) 40 | 41 | ## 9.0.0 42 | 43 | * Make rollup a peer dependency with a version range ([#300](https://github.com/rollup/rollup-plugin-commonjs/issues/300)) 44 | 45 | ## 8.4.1 46 | 47 | * Re-release of 8.3.0 as #287 was actually a breaking change 48 | 49 | ## 8.4.0 50 | 51 | * Better handle non-CJS files that contain CJS keywords ([#285](https://github.com/rollup/rollup-plugin-commonjs/issues/285)) 52 | * Use rollup's plugin context`parse` function ([#287](https://github.com/rollup/rollup-plugin-commonjs/issues/287)) 53 | * Improve error handling ([#288](https://github.com/rollup/rollup-plugin-commonjs/issues/288)) 54 | 55 | ## 8.3.0 56 | 57 | * Handle multiple entry points ([#283](https://github.com/rollup/rollup-plugin-commonjs/issues/283)) 58 | * Extract named exports from exported object literals ([#272](https://github.com/rollup/rollup-plugin-commonjs/issues/272)) 59 | * Fix when `options.external` is modified by other plugins ([#264](https://github.com/rollup/rollup-plugin-commonjs/issues/264)) 60 | * Recognize static template strings in require statements ([#271](https://github.com/rollup/rollup-plugin-commonjs/issues/271)) 61 | 62 | ## 8.2.4 63 | 64 | * Don't import default from ES modules that don't export default ([#206](https://github.com/rollup/rollup-plugin-commonjs/issues/206)) 65 | 66 | ## 8.2.3 67 | 68 | * Prevent duplicate default exports ([#230](https://github.com/rollup/rollup-plugin-commonjs/pull/230)) 69 | * Only include default export when it exists ([#226](https://github.com/rollup/rollup-plugin-commonjs/pull/226)) 70 | * Deconflict `require` aliases ([#232](https://github.com/rollup/rollup-plugin-commonjs/issues/232)) 71 | 72 | ## 8.2.1 73 | 74 | * Fix magic-string deprecation warning 75 | 76 | ## 8.2.0 77 | 78 | * Avoid using `index` as a variable name ([#208](https://github.com/rollup/rollup-plugin-commonjs/pull/208)) 79 | 80 | ## 8.1.1 81 | 82 | * Compatibility with 0.48 ([#220](https://github.com/rollup/rollup-plugin-commonjs/issues/220)) 83 | 84 | ## 8.1.0 85 | 86 | * Handle `options.external` correctly ([#212](https://github.com/rollup/rollup-plugin-commonjs/pull/212)) 87 | * Support top-level return ([#195](https://github.com/rollup/rollup-plugin-commonjs/pull/195)) 88 | 89 | ## 8.0.2 90 | 91 | * Fix another `var` rewrite bug ([#181](https://github.com/rollup/rollup-plugin-commonjs/issues/181)) 92 | 93 | ## 8.0.1 94 | 95 | * Remove declarators within a var declaration correctly ([#179](https://github.com/rollup/rollup-plugin-commonjs/issues/179)) 96 | 97 | ## 8.0.0 98 | 99 | * Prefer the names dependencies are imported by for the common `var foo = require('foo')` pattern ([#176](https://github.com/rollup/rollup-plugin-commonjs/issues/176)) 100 | 101 | ## 7.1.0 102 | 103 | * Allow certain `require` statements to pass through unmolested ([#174](https://github.com/rollup/rollup-plugin-commonjs/issues/174)) 104 | 105 | ## 7.0.2 106 | 107 | * Handle duplicate default exports ([#158](https://github.com/rollup/rollup-plugin-commonjs/issues/158)) 108 | 109 | ## 7.0.1 110 | 111 | * Fix exports with parentheses ([#168](https://github.com/rollup/rollup-plugin-commonjs/issues/168)) 112 | 113 | ## 7.0.0 114 | 115 | * Rewrite `typeof module`, `typeof module.exports` and `typeof exports` as `'object'` ([#151](https://github.com/rollup/rollup-plugin-commonjs/issues/151)) 116 | 117 | ## 6.0.1 118 | 119 | * Don't overwrite globals ([#127](https://github.com/rollup/rollup-plugin-commonjs/issues/127)) 120 | 121 | ## 6.0.0 122 | 123 | * Rewrite top-level `define` as `undefined`, so AMD-first UMD blocks do not cause breakage ([#144](https://github.com/rollup/rollup-plugin-commonjs/issues/144)) 124 | * Support ES2017 syntax ([#132](https://github.com/rollup/rollup-plugin-commonjs/issues/132)) 125 | * Deconflict exported reserved keywords ([#116](https://github.com/rollup/rollup-plugin-commonjs/issues/116)) 126 | 127 | ## 5.0.5 128 | * Fix parenthesis wrapped exports ([#120](https://github.com/rollup/rollup-plugin-commonjs/issues/120)) 129 | 130 | ## 5.0.4 131 | 132 | * Ensure named exports are added to default export in optimised modules ([#112](https://github.com/rollup/rollup-plugin-commonjs/issues/112)) 133 | 134 | ## 5.0.3 135 | 136 | * Respect custom `namedExports` in optimised modules ([#35](https://github.com/rollup/rollup-plugin-commonjs/issues/35)) 137 | 138 | ## 5.0.2 139 | 140 | * Replace `require` (outside call expressions) with `commonjsRequire` helper ([#77](https://github.com/rollup/rollup-plugin-commonjs/issues/77), [#83](https://github.com/rollup/rollup-plugin-commonjs/issues/83)) 141 | 142 | ## 5.0.1 143 | 144 | * Deconflict against globals ([#84](https://github.com/rollup/rollup-plugin-commonjs/issues/84)) 145 | 146 | ## 5.0.0 147 | 148 | * Optimise modules that don't need to be wrapped in a function ([#106](https://github.com/rollup/rollup-plugin-commonjs/pull/106)) 149 | * Ignore modules containing `import` and `export` statements ([#96](https://github.com/rollup/rollup-plugin-commonjs/pull/96)) 150 | 151 | ## 4.1.0 152 | 153 | * Ignore dead branches ([#93](https://github.com/rollup/rollup-plugin-commonjs/issues/93)) 154 | 155 | ## 4.0.1 156 | 157 | * Fix `ignoreGlobal` option ([#86](https://github.com/rollup/rollup-plugin-commonjs/pull/86)) 158 | 159 | ## 4.0.0 160 | 161 | * Better interop and smaller output ([#92](https://github.com/rollup/rollup-plugin-commonjs/pull/92)) 162 | 163 | ## 3.3.1 164 | 165 | * Deconflict export and local module ([rollup/rollup#554](https://github.com/rollup/rollup/issues/554)) 166 | 167 | ## 3.3.0 168 | 169 | * Keep the order of execution for require calls ([#43](https://github.com/rollup/rollup-plugin-commonjs/pull/43)) 170 | * Use interopDefault as helper ([#42](https://github.com/rollup/rollup-plugin-commonjs/issues/42)) 171 | 172 | ## 3.2.0 173 | 174 | * Use named exports as a function when no default export is defined ([#524](https://github.com/rollup/rollup/issues/524)) 175 | 176 | ## 3.1.0 177 | 178 | * Replace `typeof require` with `'function'` ([#38](https://github.com/rollup/rollup-plugin-commonjs/issues/38)) 179 | * Don't attempt to resolve entry file relative to importer ([#63](https://github.com/rollup/rollup-plugin-commonjs/issues/63)) 180 | 181 | ## 3.0.2 182 | 183 | * Handle multiple references to `global` 184 | 185 | ## 3.0.1 186 | 187 | * Return a `name` 188 | 189 | ## 3.0.0 190 | 191 | * Make `transform` stateless ([#71](https://github.com/rollup/rollup-plugin-commonjs/pull/71)) 192 | * Support web worker `global` ([#50](https://github.com/rollup/rollup-plugin-commonjs/issues/50)) 193 | * Ignore global with `options.ignoreGlobal` ([#48](https://github.com/rollup/rollup-plugin-commonjs/issues/48)) 194 | 195 | ## 2.2.1 196 | 197 | * Prevent false positives with `namedExports` ([#36](https://github.com/rollup/rollup-plugin-commonjs/issues/36)) 198 | 199 | ## 2.2.0 200 | 201 | * Rewrite top-level `this` expressions to mean the same as `global` ([#31](https://github.com/rollup/rollup-plugin-commonjs/issues/31)) 202 | 203 | ## 2.1.0 204 | 205 | * Optimised module wrappers ([#20](https://github.com/rollup/rollup-plugin-commonjs/pull/20)) 206 | * Allow control over named exports via `options.namedExports` ([#18](https://github.com/rollup/rollup-plugin-commonjs/issues/18)) 207 | * Handle bare imports correctly ([#23](https://github.com/rollup/rollup-plugin-commonjs/issues/23)) 208 | * Blacklist all reserved words as export names ([#21](https://github.com/rollup/rollup-plugin-commonjs/issues/21)) 209 | * Configure allowed file extensions via `options.extensions` ([#27](https://github.com/rollup/rollup-plugin-commonjs/pull/27)) 210 | 211 | ## 2.0.0 212 | 213 | * Support for transpiled modules – `exports.default` is used as the default export in place of `module.exports`, if applicable, and `__esModule` is not exported ([#16](https://github.com/rollup/rollup-plugin-commonjs/pull/16)) 214 | 215 | ## 1.4.0 216 | 217 | * Generate sourcemaps by default 218 | 219 | ## 1.3.0 220 | 221 | * Handle references to `global` ([#6](https://github.com/rollup/rollup-plugin-commonjs/issues/6)) 222 | 223 | ## 1.2.0 224 | 225 | * Generate named exports where possible ([#5](https://github.com/rollup/rollup-plugin-commonjs/issues/5)) 226 | * Handle shadowed `require`/`module`/`exports` 227 | 228 | ## 1.1.0 229 | 230 | * Handle dots in filenames ([#3](https://github.com/rollup/rollup-plugin-commonjs/issues/3)) 231 | * Wrap modules in IIFE for more readable output 232 | 233 | ## 1.0.0 234 | 235 | * Stable release, now that Rollup supports plugins 236 | 237 | ## 0.2.1 238 | 239 | * Allow mixed CommonJS/ES6 imports/exports 240 | * Use `var` instead of `let` 241 | 242 | ## 0.2.0 243 | 244 | * Sourcemap support 245 | * Support `options.include` and `options.exclude` 246 | * Bail early if module is obviously not a CommonJS module 247 | 248 | ## 0.1.1 249 | 250 | Add dist files to package (whoops!) 251 | 252 | ## 0.1.0 253 | 254 | * First release 255 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 drylikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | drylikov 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rollup_plugin_CommonJS_modules [![Build Status][travis-img]][travis] 2 | 3 | [travis-img]: https://travis-ci.org/rollup/rollup-plugin-commonjs.svg 4 | [travis]: https://travis-ci.org/rollup/rollup-plugin-commonjs 5 | 6 | Convert CommonJS modules to ES6, so they can be included in a Rollup bundle 7 | 8 | 9 | ## Installation 10 | 11 | ```bash 12 | npm install --save-dev rollup-plugin-commonjs 13 | ``` 14 | 15 | 16 | ## Usage 17 | 18 | Typically, you would use this plugin alongside [rollup-plugin-node-resolve](https://github.com/rollup/rollup-plugin-node-resolve), so that you could bundle your CommonJS dependencies in `node_modules`. 19 | 20 | ```js 21 | // rollup.config.js 22 | import commonjs from 'rollup-plugin-commonjs'; 23 | import nodeResolve from 'rollup-plugin-node-resolve'; 24 | 25 | export default { 26 | input: 'main.js', 27 | output: { 28 | file: 'bundle.js', 29 | format: 'iife' 30 | }, 31 | plugins: [ 32 | nodeResolve({ 33 | jsnext: true, 34 | main: true 35 | }), 36 | 37 | commonjs({ 38 | // non-CommonJS modules will be ignored, but you can also 39 | // specifically include/exclude files 40 | include: 'node_modules/**', // Default: undefined 41 | exclude: [ 'node_modules/foo/**', 'node_modules/bar/**' ], // Default: undefined 42 | // these values can also be regular expressions 43 | // include: /node_modules/ 44 | 45 | // search for files other than .js files (must already 46 | // be transpiled by a previous plugin!) 47 | extensions: [ '.js', '.coffee' ], // Default: [ '.js' ] 48 | 49 | // if true then uses of `global` won't be dealt with by this plugin 50 | ignoreGlobal: false, // Default: false 51 | 52 | // if false then skip sourceMap generation for CommonJS modules 53 | sourceMap: false, // Default: true 54 | 55 | // explicitly specify unresolvable named exports 56 | // (see below for more details) 57 | namedExports: { './module.js': ['foo', 'bar' ] }, // Default: undefined 58 | 59 | // sometimes you have to leave require statements 60 | // unconverted. Pass an array containing the IDs 61 | // or a `id => boolean` function. Only use this 62 | // option if you know what you're doing! 63 | ignore: [ 'conditional-runtime-dependency' ] 64 | }) 65 | ] 66 | }; 67 | ``` 68 | 69 | ### Custom named exports 70 | 71 | This plugin will attempt to create named exports, where appropriate, so you can do this... 72 | 73 | ```js 74 | // importer.js 75 | import { named } from './exporter.js'; 76 | 77 | // exporter.js 78 | module.exports = { named: 42 }; // or `exports.named = 42;` 79 | ``` 80 | 81 | ...but that's not always possible: 82 | 83 | ```js 84 | // importer.js 85 | import { named } from 'my-lib'; 86 | 87 | // my-lib.js 88 | var myLib = exports; 89 | myLib.named = 'you can\'t see me'; 90 | ``` 91 | 92 | In those cases, you can specify custom named exports: 93 | 94 | ```js 95 | commonjs({ 96 | namedExports: { 97 | // left-hand side can be an absolute path, a path 98 | // relative to the current directory, or the name 99 | // of a module in node_modules 100 | 'node_modules/my-lib/index.js': [ 'named' ] 101 | } 102 | }) 103 | ``` 104 | 105 | 106 | ## Strict mode 107 | 108 | ES modules are *always* parsed in strict mode. That means that certain non-strict constructs (like octal literals) will be treated as syntax errors when Rollup parses modules that use them. Some older CommonJS modules depend on those constructs, and if you depend on them your bundle will blow up. There's basically nothing we can do about that. 109 | 110 | Luckily, there is absolutely no good reason *not* to use strict mode for everything — so the solution to this problem is to lobby the authors of those modules to update them. 111 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # http://www.appveyor.com/docs/appveyor-yml 2 | 3 | version: "{build}" 4 | 5 | clone_depth: 10 6 | 7 | init: 8 | - git config --global core.autocrlf false 9 | 10 | environment: 11 | matrix: 12 | # node.js 13 | - nodejs_version: 8 14 | 15 | install: 16 | - ps: Install-Product node $env:nodejs_version 17 | - IF %nodejs_version% LSS 7 npm -g install npm@4 18 | - npm install 19 | 20 | build: off 21 | 22 | test_script: 23 | - node --version && npm --version 24 | - npm test 25 | 26 | matrix: 27 | fast_finish: false 28 | 29 | # cache: 30 | # - C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache 31 | # - node_modules -> package.json # local npm modules 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rollup-plugin-commonjs", 3 | "version": "9.2.0", 4 | "description": "Convert CommonJS modules to ES2015", 5 | "main": "dist/rollup-plugin-commonjs.cjs.js", 6 | "module": "dist/rollup-plugin-commonjs.es.js", 7 | "jsnext:main": "dist/rollup-plugin-commonjs.es.js", 8 | "scripts": { 9 | "test": "npm run test:only", 10 | "test:only": "mocha", 11 | "pretest": "npm run build", 12 | "build": "shx rm -rf dist/* && rollup -c", 13 | "dev": "rollup -c -w", 14 | "lint": "prettier --write src/**/*.js test/test.js test/**/_config.js && eslint --fix src/**/*.js test/test.js test/**/_config.js", 15 | "prepublishOnly": "npm run lint && npm run test:only", 16 | "prepare": "npm run build" 17 | }, 18 | "files": [ 19 | "src", 20 | "dist", 21 | "README.md" 22 | ], 23 | "peerDependencies": { 24 | "rollup": ">=0.56.0" 25 | }, 26 | "dependencies": { 27 | "estree-walker": "^0.5.2", 28 | "magic-string": "^0.25.1", 29 | "resolve": "^1.8.1", 30 | "rollup-pluginutils": "^2.3.3" 31 | }, 32 | "devDependencies": { 33 | "acorn": "^6.0.2", 34 | "eslint": "^5.6.1", 35 | "eslint-plugin-import": "^2.14.0", 36 | "husky": "^1.1.0", 37 | "lint-staged": "^7.3.0", 38 | "locate-character": "^2.0.5", 39 | "mocha": "^5.2.0", 40 | "prettier": "^1.14.3", 41 | "require-relative": "^0.8.7", 42 | "rollup": "^0.66.3", 43 | "rollup-plugin-buble": "^0.19.2", 44 | "rollup-plugin-node-resolve": "^3.4.0", 45 | "shx": "^0.3.2", 46 | "source-map": "^0.7.3", 47 | "source-map-support": "^0.5.9" 48 | }, 49 | "repository": "rollup/rollup-plugin-commonjs", 50 | "author": "Rich Harris", 51 | "license": "MIT", 52 | "bugs": { 53 | "url": "https://github.com/rollup/rollup-plugin-commonjs/issues" 54 | }, 55 | "homepage": "https://github.com/rollup/rollup-plugin-commonjs" 56 | } 57 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import buble from 'rollup-plugin-buble'; 2 | import pkg from './package.json'; 3 | 4 | export default { 5 | input: 'src/index.js', 6 | plugins: [ 7 | buble({ 8 | transforms: { dangerousForOf: true } 9 | }) 10 | ], 11 | external: Object.keys( pkg.dependencies ).concat([ 'fs', 'path' ]), 12 | output: [ 13 | { 14 | format: 'es', 15 | file: pkg.module, 16 | sourcemap: true 17 | }, 18 | { 19 | format: 'cjs', 20 | file: pkg.main, 21 | sourcemap: true 22 | } 23 | ] 24 | }; 25 | -------------------------------------------------------------------------------- /src/ast-utils.js: -------------------------------------------------------------------------------- 1 | export function isReference(node, parent) { 2 | if (parent.type === 'MemberExpression') return parent.computed || node === parent.object; 3 | 4 | // disregard the `bar` in { bar: foo } 5 | if (parent.type === 'Property' && node !== parent.value) return false; 6 | 7 | // disregard the `bar` in `class Foo { bar () {...} }` 8 | if (parent.type === 'MethodDefinition') return false; 9 | 10 | // disregard the `bar` in `export { foo as bar }` 11 | if (parent.type === 'ExportSpecifier' && node !== parent.local) return false; 12 | 13 | return true; 14 | } 15 | 16 | export function flatten(node) { 17 | const parts = []; 18 | 19 | while (node.type === 'MemberExpression') { 20 | if (node.computed) return null; 21 | 22 | parts.unshift(node.property.name); 23 | node = node.object; 24 | } 25 | 26 | if (node.type !== 'Identifier') return null; 27 | 28 | const name = node.name; 29 | parts.unshift(name); 30 | 31 | return { name, keypath: parts.join('.') }; 32 | } 33 | 34 | export function extractNames(node) { 35 | const names = []; 36 | extractors[node.type](names, node); 37 | return names; 38 | } 39 | 40 | function getExtractor (type) { 41 | const extractor = extractors[type]; 42 | if (!extractor) 43 | throw new SyntaxError(`${type} pattern not supported.`); 44 | return extractor; 45 | } 46 | 47 | const extractors = { 48 | Identifier(names, node) { 49 | names.push(node.name); 50 | }, 51 | 52 | ObjectPattern(names, node) { 53 | node.properties.forEach(prop => { 54 | getExtractor(prop.value.type)(names, prop.value); 55 | }); 56 | }, 57 | 58 | ArrayPattern(names, node) { 59 | node.elements.forEach(element => { 60 | if (!element) return; 61 | getExtractor(element.type)(names, element); 62 | }); 63 | }, 64 | 65 | RestElement(names, node) { 66 | getExtractor(node.argument.type)(names, node.argument); 67 | }, 68 | 69 | AssignmentPattern(names, node) { 70 | getExtractor(node.left.type)(names, node.left); 71 | } 72 | }; 73 | 74 | export function isTruthy(node) { 75 | if (node.type === 'Literal') return !!node.value; 76 | if (node.type === 'ParenthesizedExpression') return isTruthy(node.expression); 77 | if (node.operator in operators) return operators[node.operator](node); 78 | } 79 | 80 | export function isFalsy(node) { 81 | return not(isTruthy(node)); 82 | } 83 | 84 | function not(value) { 85 | return value === undefined ? value : !value; 86 | } 87 | 88 | function equals(a, b, strict) { 89 | if (a.type !== b.type) return undefined; 90 | if (a.type === 'Literal') return strict ? a.value === b.value : a.value == b.value; 91 | } 92 | 93 | const operators = { 94 | '==': x => { 95 | return equals(x.left, x.right, false); 96 | }, 97 | 98 | '!=': x => not(operators['=='](x)), 99 | 100 | '===': x => { 101 | return equals(x.left, x.right, true); 102 | }, 103 | 104 | '!==': x => not(operators['==='](x)), 105 | 106 | '!': x => isFalsy(x.argument), 107 | 108 | '&&': x => isTruthy(x.left) && isTruthy(x.right), 109 | 110 | '||': x => isTruthy(x.left) || isTruthy(x.right) 111 | }; 112 | -------------------------------------------------------------------------------- /src/default-resolver.js: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import {dirname, resolve} from 'path'; 3 | 4 | function isFile(file) { 5 | try { 6 | const stats = fs.statSync(file); 7 | return stats.isFile(); 8 | } catch (err) { 9 | return false; 10 | } 11 | } 12 | 13 | function addJsExtensionIfNecessary(file) { 14 | if (isFile(file)) return file; 15 | 16 | file += '.js'; 17 | if (isFile(file)) return file; 18 | 19 | return null; 20 | } 21 | 22 | const absolutePath = /^(?:\/|(?:[A-Za-z]:)?[\\|/])/; 23 | 24 | function isAbsolute(path) { 25 | return absolutePath.test(path); 26 | } 27 | 28 | export default function defaultResolver(importee, importer) { 29 | // absolute paths are left untouched 30 | if (isAbsolute(importee)) return addJsExtensionIfNecessary(resolve(importee)); 31 | 32 | // if this is the entry point, resolve against cwd 33 | if (importer === undefined) return addJsExtensionIfNecessary(resolve(process.cwd(), importee)); 34 | 35 | // external modules are skipped at this stage 36 | if (importee[0] !== '.') return null; 37 | 38 | return addJsExtensionIfNecessary(resolve(dirname(importer), importee)); 39 | } 40 | -------------------------------------------------------------------------------- /src/helpers.js: -------------------------------------------------------------------------------- 1 | export const PROXY_PREFIX = '\0commonjs-proxy:'; 2 | export const EXTERNAL_PREFIX = '\0commonjs-external:'; 3 | export const HELPERS_ID = '\0commonjsHelpers'; 4 | 5 | export const HELPERS = ` 6 | export var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 7 | 8 | export function commonjsRequire () { 9 | throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs'); 10 | } 11 | 12 | export function unwrapExports (x) { 13 | return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x; 14 | } 15 | 16 | export function createCommonjsModule(fn, module) { 17 | return module = { exports: {} }, fn(module, module.exports), module.exports; 18 | } 19 | 20 | export function getCjsExportFromNamespace (n) { 21 | return n && n.default || n; 22 | } 23 | 24 | export function notFoundRequire (id) { 25 | var e = new Error("Cannot find module '" + id + "'."); 26 | e.code = 'MODULE_NOT_FOUND'; 27 | throw e; 28 | } 29 | `; 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { extname, resolve } from 'path'; 2 | import { sync as nodeResolveSync } from 'resolve'; 3 | import { createFilter } from 'rollup-pluginutils'; 4 | import { EXTERNAL_PREFIX, HELPERS, HELPERS_ID, PROXY_PREFIX } from './helpers.js'; 5 | import { getIsCjsPromise, setIsCjsPromise } from './is-cjs'; 6 | import { getResolveId } from './resolve-id'; 7 | import { checkEsModule, transformCommonjs } from './transform.js'; 8 | import { getName } from './utils.js'; 9 | 10 | export default function commonjs(options = {}) { 11 | const extensions = options.extensions || ['.js']; 12 | const filter = createFilter(options.include, options.exclude); 13 | const ignoreGlobal = options.ignoreGlobal; 14 | 15 | const customNamedExports = {}; 16 | if (options.namedExports) { 17 | Object.keys(options.namedExports).forEach(id => { 18 | let resolvedId; 19 | 20 | try { 21 | resolvedId = nodeResolveSync(id, { basedir: process.cwd() }); 22 | } catch (err) { 23 | resolvedId = resolve(id); 24 | } 25 | 26 | customNamedExports[resolvedId] = options.namedExports[id]; 27 | }); 28 | } 29 | 30 | const esModulesWithoutDefaultExport = Object.create(null); 31 | const esModulesWithDefaultExport = Object.create(null); 32 | const allowDynamicRequire = !!options.ignore; // TODO maybe this should be configurable? 33 | 34 | const ignoreRequire = 35 | typeof options.ignore === 'function' 36 | ? options.ignore 37 | : Array.isArray(options.ignore) 38 | ? id => options.ignore.includes(id) 39 | : () => false; 40 | 41 | let entryModuleIdsPromise = null; 42 | 43 | const resolveId = getResolveId(extensions); 44 | 45 | const sourceMap = options.sourceMap !== false; 46 | 47 | return { 48 | name: 'commonjs', 49 | 50 | options(options) { 51 | resolveId.setRollupOptions(options); 52 | const input = options.input || options.entry; 53 | const entryModules = Array.isArray(input) 54 | ? input 55 | : typeof input === 'object' && input !== null 56 | ? Object.values(input) 57 | : [input]; 58 | entryModuleIdsPromise = Promise.all(entryModules.map(entry => resolveId(entry))); 59 | }, 60 | 61 | resolveId, 62 | 63 | load(id) { 64 | if (id === HELPERS_ID) return HELPERS; 65 | 66 | // generate proxy modules 67 | if (id.startsWith(EXTERNAL_PREFIX)) { 68 | const actualId = id.slice(EXTERNAL_PREFIX.length); 69 | const name = getName(actualId); 70 | 71 | return `import ${name} from ${JSON.stringify(actualId)}; export default ${name};`; 72 | } 73 | 74 | if (id.startsWith(PROXY_PREFIX)) { 75 | const actualId = id.slice(PROXY_PREFIX.length); 76 | const name = getName(actualId); 77 | 78 | return getIsCjsPromise(actualId).then(isCjs => { 79 | if (isCjs) 80 | return `import { __moduleExports } from ${JSON.stringify( 81 | actualId 82 | )}; export default __moduleExports;`; 83 | else if (esModulesWithoutDefaultExport[actualId]) 84 | return `import * as ${name} from ${JSON.stringify(actualId)}; export default ${name};`; 85 | else if (esModulesWithDefaultExport[actualId]) { 86 | return `export {default} from ${JSON.stringify(actualId)};`; 87 | } 88 | else 89 | return `import * as ${name} from ${JSON.stringify( 90 | actualId 91 | )}; import {getCjsExportFromNamespace} from "${HELPERS_ID}"; export default getCjsExportFromNamespace(${name})`; 92 | }); 93 | } 94 | }, 95 | 96 | transform(code, id) { 97 | if (!filter(id) || extensions.indexOf(extname(id)) === -1) { 98 | setIsCjsPromise(id, Promise.resolve(null)); 99 | return null; 100 | } 101 | 102 | const transformPromise = entryModuleIdsPromise 103 | .then(entryModuleIds => { 104 | const { isEsModule, hasDefaultExport, ast } = checkEsModule(this.parse, code, id); 105 | if (isEsModule) { 106 | (hasDefaultExport ? esModulesWithDefaultExport : esModulesWithoutDefaultExport)[id] = true; 107 | return null; 108 | } 109 | 110 | const namedExports = customNamedExports[id]; 111 | return transformCommonjs.call( 112 | this, 113 | code, 114 | ast, 115 | id, 116 | entryModuleIds.indexOf(id) !== -1, 117 | ignoreGlobal, 118 | ignoreRequire, 119 | namedExports, 120 | sourceMap, 121 | allowDynamicRequire 122 | ) 123 | .then(transformed => { 124 | if (!transformed) { 125 | if (namedExports && Object.keys(namedExports).length) { 126 | throw new Error( 127 | `Custom named exports were specified for ${id} but it does not appear to be a CommonJS module` 128 | ); 129 | } 130 | esModulesWithoutDefaultExport[id] = true; 131 | return null; 132 | } 133 | return transformed; 134 | }); 135 | }) 136 | .catch(err => { 137 | this.error(err, err.loc); 138 | }); 139 | 140 | setIsCjsPromise(id, transformPromise.then(Boolean, () => false)); 141 | return transformPromise; 142 | } 143 | }; 144 | } 145 | -------------------------------------------------------------------------------- /src/is-cjs.js: -------------------------------------------------------------------------------- 1 | const isCjsPromises = Object.create(null); 2 | 3 | export function getIsCjsPromise(id) { 4 | let isCjsPromise = isCjsPromises[id]; 5 | if (isCjsPromise) return isCjsPromise.promise; 6 | 7 | const promise = new Promise(resolve => { 8 | isCjsPromises[id] = isCjsPromise = { 9 | resolve, 10 | promise: undefined 11 | }; 12 | }); 13 | isCjsPromise.promise = promise; 14 | 15 | return promise; 16 | } 17 | 18 | export function setIsCjsPromise(id, promise) { 19 | const isCjsPromise = isCjsPromises[id]; 20 | if (isCjsPromise) { 21 | if (isCjsPromise.resolve) { 22 | isCjsPromise.resolve(promise); 23 | isCjsPromise.resolve = undefined; 24 | } 25 | } else { 26 | isCjsPromises[id] = { promise, resolve: undefined }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/resolve-id.js: -------------------------------------------------------------------------------- 1 | import {statSync} from 'fs'; 2 | import {dirname, resolve, sep} from 'path'; 3 | import defaultResolver from './default-resolver'; 4 | import {EXTERNAL_PREFIX, PROXY_PREFIX} from './helpers'; 5 | import {first} from './utils'; 6 | 7 | function getCandidatesForExtension(resolved, extension) { 8 | return [resolved + extension, resolved + `${sep}index${extension}`]; 9 | } 10 | 11 | function getCandidates(resolved, extensions) { 12 | return extensions.reduce( 13 | (paths, extension) => paths.concat(getCandidatesForExtension(resolved, extension)), 14 | [resolved] 15 | ); 16 | } 17 | 18 | export function getResolveId(extensions) { 19 | let resolveUsingOtherResolvers; 20 | 21 | function resolveId(importee, importer) { 22 | const isProxyModule = importee.startsWith(PROXY_PREFIX); 23 | if (isProxyModule) { 24 | importee = importee.slice(PROXY_PREFIX.length); 25 | } else if (importee.startsWith('\0')) { 26 | return importee; 27 | } 28 | 29 | if (importer && importer.startsWith(PROXY_PREFIX)) { 30 | importer = importer.slice(PROXY_PREFIX.length); 31 | } 32 | 33 | return resolveUsingOtherResolvers(importee, importer).then(resolved => { 34 | if (resolved) return isProxyModule ? PROXY_PREFIX + resolved : resolved; 35 | 36 | resolved = defaultResolver(importee, importer); 37 | 38 | if (isProxyModule) { 39 | if (resolved) return PROXY_PREFIX + resolved; 40 | return EXTERNAL_PREFIX + importee; // external 41 | } 42 | 43 | return resolved; 44 | }); 45 | } 46 | 47 | resolveId.setRollupOptions = function(options) { 48 | const resolvers = (options.plugins || []) 49 | .map(plugin => { 50 | if (plugin.resolveId === resolveId) { 51 | // substitute CommonJS resolution logic 52 | return (importee, importer) => { 53 | if (importee[0] !== '.' || !importer) return; // not our problem 54 | 55 | const resolved = resolve(dirname(importer), importee); 56 | const candidates = getCandidates(resolved, extensions); 57 | 58 | for (let i = 0; i < candidates.length; i += 1) { 59 | try { 60 | const stats = statSync(candidates[i]); 61 | if (stats.isFile()) return candidates[i]; 62 | } catch (err) { 63 | /* noop */ 64 | } 65 | } 66 | }; 67 | } 68 | 69 | return plugin.resolveId; 70 | }) 71 | .filter(Boolean); 72 | 73 | const isExternal = id => 74 | options.external 75 | ? Array.isArray(options.external) 76 | ? options.external.includes(id) 77 | : options.external(id) 78 | : false; 79 | 80 | resolvers.unshift(id => (isExternal(id) ? false : null)); 81 | 82 | resolveUsingOtherResolvers = first(resolvers); 83 | }; 84 | 85 | return resolveId; 86 | } 87 | -------------------------------------------------------------------------------- /src/transform.js: -------------------------------------------------------------------------------- 1 | import { walk } from 'estree-walker'; 2 | import MagicString from 'magic-string'; 3 | import { attachScopes, makeLegalIdentifier } from 'rollup-pluginutils'; 4 | import { extractNames, flatten, isFalsy, isReference, isTruthy } from './ast-utils.js'; 5 | import { HELPERS_ID, PROXY_PREFIX } from './helpers.js'; 6 | import { getName } from './utils.js'; 7 | 8 | const reserved = 'process location abstract arguments boolean break byte case catch char class const continue debugger default delete do double else enum eval export extends false final finally float for from function goto if implements import in instanceof int interface let long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var void volatile while with yield'.split( 9 | ' ' 10 | ); 11 | const blacklist = { __esModule: true }; 12 | reserved.forEach(word => (blacklist[word] = true)); 13 | 14 | const exportsPattern = /^(?:module\.)?exports(?:\.([a-zA-Z_$][a-zA-Z_$0-9]*))?$/; 15 | 16 | const importExportDeclaration = /^(?:Import|Export(?:Named|Default))Declaration/; 17 | const functionType = /^(?:FunctionDeclaration|FunctionExpression|ArrowFunctionExpression)$/; 18 | 19 | function deconflict(scope, globals, identifier) { 20 | let i = 1; 21 | let deconflicted = identifier; 22 | 23 | while (scope.contains(deconflicted) || globals.has(deconflicted) || deconflicted in blacklist) 24 | deconflicted = `${identifier}_${i++}`; 25 | scope.declarations[deconflicted] = true; 26 | 27 | return deconflicted; 28 | } 29 | 30 | function tryParse(parse, code, id, module) { 31 | try { 32 | return parse(code, { allowReturnOutsideFunction: true, sourceType: module ? 'module' : 'script' }); 33 | } catch (err) { 34 | err.message += ` in ${id}`; 35 | throw err; 36 | } 37 | } 38 | 39 | export function checkEsModule(parse, code, id) { 40 | // first try parse as "script", falling back to "module" 41 | try { 42 | const ast = tryParse(parse, code, id, false); 43 | return { isEsModoule: false, hasDefaultExport: false, ast }; 44 | } 45 | catch (e) { 46 | if (e instanceof SyntaxError === false) 47 | throw e; 48 | let isEsModule = false; 49 | const ast = tryParse(parse, code, id, true); 50 | for (const node of ast.body) { 51 | if (node.type === 'ExportDefaultDeclaration') 52 | return { isEsModule: true, hasDefaultExport: true, ast }; 53 | if (node.type === 'ExportNamedDeclaration') { 54 | isEsModule = true; 55 | for (const specifier of node.specifiers) { 56 | if (specifier.exported.name === 'default') { 57 | return { isEsModule: true, hasDefaultExport: true, ast }; 58 | } 59 | } 60 | } else if (importExportDeclaration.test(node.type)) isEsModule = true; 61 | } 62 | return { isEsModule, hasDefaultExport: false, ast }; 63 | } 64 | } 65 | 66 | export function transformCommonjs( 67 | code, 68 | ast, 69 | id, 70 | isEntry, 71 | ignoreGlobal, 72 | ignoreRequire, 73 | customNamedExports, 74 | sourceMap, 75 | allowDynamicRequire 76 | ) { 77 | if (!ast) 78 | throw new Error('The AST must be provided'); 79 | 80 | const isStrict = ast.body[0] && ast.body[0].directive === 'use strict'; 81 | 82 | return Promise.resolve() 83 | .then(() => { 84 | const magicString = new MagicString(code); 85 | 86 | const required = {}; 87 | // Because objects have no guaranteed ordering, yet we need it, 88 | // we need to keep track of the order in a array 89 | const sources = []; 90 | 91 | let uid = 0; 92 | 93 | let scope = attachScopes(ast, 'scope'); 94 | const uses = { module: false, exports: false, global: false, require: false }; 95 | 96 | let lexicalDepth = 0; 97 | let programDepth = 0; 98 | let tryCatchDepth = 0; 99 | 100 | const globals = new Set(); 101 | 102 | const HELPERS_NAME = deconflict(scope, globals, 'commonjsHelpers'); // TODO technically wrong since globals isn't populated yet, but ¯\_(ツ)_/¯ 103 | 104 | const namedExports = {}; 105 | 106 | // TODO handle transpiled modules 107 | let shouldWrap = /__esModule/.test(code); 108 | 109 | function isRequireStatement(node) { 110 | if (!node) return; 111 | if (node.type !== 'CallExpression') return; 112 | if (node.callee.name !== 'require' || scope.contains('require')) return; 113 | if (node.arguments.length === 0) return; // Weird case of require() without arguments 114 | return true; 115 | } 116 | 117 | function hasDynamicArguments(node) { 118 | return ( 119 | node.arguments.length > 1 || 120 | (node.arguments[0].type !== 'Literal' && 121 | (node.arguments[0].type !== 'TemplateLiteral' || node.arguments[0].expressions.length > 0)) 122 | ); 123 | } 124 | 125 | function isStaticRequireStatement(node) { 126 | if (!isRequireStatement(node)) return; 127 | if (hasDynamicArguments(node)) return; 128 | if (ignoreRequire(node.arguments[0].value)) return; 129 | return true; 130 | } 131 | 132 | function getRequireStringArg(node) { 133 | return node.arguments[0].type === 'Literal' 134 | ? node.arguments[0].value 135 | : node.arguments[0].quasis[0].value.cooked; 136 | } 137 | 138 | function getRequired(node, name) { 139 | const sourceId = getRequireStringArg(node); 140 | let require = required[sourceId]; 141 | if (require === undefined) { 142 | if (!name) { 143 | do name = `require$$${uid++}`; 144 | while (scope.contains(name)); 145 | } 146 | sources.push(sourceId); 147 | require = required[sourceId] = { source: sourceId, name, importsDefault: false, optional: [] }; 148 | } 149 | 150 | if (tryCatchDepth > 0) 151 | require.optional.push(node); 152 | 153 | return require; 154 | } 155 | 156 | // do a first pass, see which names are assigned to. This is necessary to prevent 157 | // illegally replacing `var foo = require('foo')` with `import foo from 'foo'`, 158 | // where `foo` is later reassigned. (This happens in the wild. CommonJS, sigh) 159 | let hasCjsKeywords = false; 160 | // "function x () {}; function x () {}" supported in non-strict 161 | // so we catch these duplicate cases for strict conversion 162 | let hasDuplicateFunctionDecls = false; 163 | const assignedTo = new Set(); 164 | const functionDecls = new Map(); 165 | walk(ast, { 166 | enter(node) { 167 | programDepth += 1; 168 | 169 | if (!hasCjsKeywords && node.type === 'Identifier') { 170 | if (node.name === 'require' || node.name === 'exports' || node.name === 'module' || !ignoreGlobal && node.name === 'global') 171 | hasCjsKeywords = true; 172 | } 173 | 174 | if (!isStrict && programDepth === 2 && node.type === 'FunctionDeclaration') { 175 | if (functionDecls.has(node.id.name)) 176 | hasDuplicateFunctionDecls = true; 177 | functionDecls.set(node.id.name, node); 178 | return; 179 | } 180 | 181 | if (node.type !== 'AssignmentExpression') return; 182 | if (node.left.type === 'MemberExpression') return; 183 | 184 | extractNames(node.left).forEach(name => { 185 | assignedTo.add(name); 186 | }); 187 | }, 188 | leave () { 189 | programDepth -= 1; 190 | } 191 | }); 192 | 193 | // Early return when further transformation (CJS or strict conversion) isn't necessary. 194 | if (!hasCjsKeywords && !hasDuplicateFunctionDecls) 195 | return null; 196 | 197 | walk(ast, { 198 | enter(node, parent) { 199 | if (sourceMap) { 200 | magicString.addSourcemapLocation(node.start); 201 | magicString.addSourcemapLocation(node.end); 202 | } 203 | 204 | if (node.type === 'BlockStatement' && parent.type === 'TryStatement') 205 | tryCatchDepth++; 206 | 207 | // skip dead branches 208 | if (parent && (parent.type === 'IfStatement' || parent.type === 'ConditionalExpression')) { 209 | if (node === parent.consequent && isFalsy(parent.test)) return this.skip(); 210 | if (node === parent.alternate && isTruthy(parent.test)) return this.skip(); 211 | } 212 | 213 | if (node._skip) return this.skip(); 214 | 215 | programDepth += 1; 216 | 217 | if (node.scope) scope = node.scope; 218 | if (functionType.test(node.type)) lexicalDepth += 1; 219 | 220 | // if toplevel return, we need to wrap it 221 | if (node.type === 'ReturnStatement' && lexicalDepth === 0) { 222 | shouldWrap = true; 223 | } 224 | 225 | // rewrite `this` as `commonjsHelpers.commonjsGlobal` 226 | if (node.type === 'ThisExpression' && lexicalDepth === 0) { 227 | uses.global = true; 228 | if (!ignoreGlobal) 229 | magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsGlobal`, { 230 | storeName: true 231 | }); 232 | return; 233 | } 234 | 235 | // rewrite `typeof module`, `typeof module.exports` and `typeof exports` (https://github.com/rollup/rollup-plugin-commonjs/issues/151) 236 | if (node.type === 'UnaryExpression' && node.operator === 'typeof') { 237 | const flattened = flatten(node.argument); 238 | if (!flattened) return; 239 | 240 | if (scope.contains(flattened.name)) return; 241 | 242 | if ( 243 | flattened.keypath === 'module.exports' || 244 | flattened.keypath === 'module' || 245 | flattened.keypath === 'exports' 246 | ) { 247 | magicString.overwrite(node.start, node.end, `'object'`, { storeName: false }); 248 | } 249 | } 250 | 251 | // rewrite `require` (if not already handled) `global` and `define`, and handle free references to 252 | // `module` and `exports` as these mean we need to wrap the module in commonjsHelpers.createCommonjsModule 253 | if (node.type === 'Identifier') { 254 | if (isReference(node, parent) && !scope.contains(node.name)) { 255 | if (node.name in uses) { 256 | if (node.name === 'require') { 257 | if (allowDynamicRequire) return; 258 | magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsRequire`, { 259 | storeName: true 260 | }); 261 | } 262 | 263 | uses[node.name] = true; 264 | if (node.name === 'global' && !ignoreGlobal) { 265 | magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsGlobal`, { 266 | storeName: true 267 | }); 268 | } 269 | 270 | // if module or exports are used outside the context of an assignment 271 | // expression, we need to wrap the module 272 | if (node.name === 'module' || node.name === 'exports') { 273 | shouldWrap = true; 274 | } 275 | } 276 | 277 | if (node.name === 'define') { 278 | magicString.overwrite(node.start, node.end, 'undefined', { storeName: true }); 279 | } 280 | 281 | globals.add(node.name); 282 | } 283 | 284 | return; 285 | } 286 | 287 | // Is this an assignment to exports or module.exports? 288 | if (node.type === 'AssignmentExpression') { 289 | if (node.left.type !== 'MemberExpression') return; 290 | 291 | const flattened = flatten(node.left); 292 | if (!flattened) return; 293 | 294 | if (scope.contains(flattened.name)) return; 295 | 296 | const match = exportsPattern.exec(flattened.keypath); 297 | if (!match || flattened.keypath === 'exports') return; 298 | 299 | uses[flattened.name] = true; 300 | 301 | // we're dealing with `module.exports = ...` or `[module.]exports.foo = ...` – 302 | // if this isn't top-level, we'll need to wrap the module 303 | if (programDepth > 3) shouldWrap = true; 304 | 305 | node.left._skip = true; 306 | 307 | if (flattened.keypath === 'module.exports' && node.right.type === 'ObjectExpression') { 308 | return node.right.properties.forEach(prop => { 309 | if (prop.computed || prop.key.type !== 'Identifier') return; 310 | const name = prop.key.name; 311 | if (name === makeLegalIdentifier(name)) namedExports[name] = true; 312 | }); 313 | } 314 | 315 | if (match[1]) namedExports[match[1]] = true; 316 | return; 317 | } 318 | 319 | // if this is `var x = require('x')`, we can do `import x from 'x'` 320 | if ( 321 | node.type === 'VariableDeclarator' && 322 | node.id.type === 'Identifier' && 323 | isStaticRequireStatement(node.init) 324 | ) { 325 | // for now, only do this for top-level requires. maybe fix this in future 326 | if (scope.parent) return; 327 | 328 | // edge case — CJS allows you to assign to imports. ES doesn't 329 | if (assignedTo.has(node.id.name)) return; 330 | 331 | const required = getRequired(node.init, node.id.name); 332 | required.importsDefault = true; 333 | 334 | if (required.name === node.id.name) { 335 | node._shouldRemove = true; 336 | } 337 | } 338 | 339 | if (!isStaticRequireStatement(node)) return; 340 | 341 | const required = getRequired(node); 342 | 343 | if (parent.type === 'ExpressionStatement') { 344 | // is a bare import, e.g. `require('foo');` 345 | magicString.remove(parent.start, parent.end); 346 | } else { 347 | required.importsDefault = true; 348 | magicString.overwrite(node.start, node.end, required.name); 349 | } 350 | 351 | node.callee._skip = true; 352 | }, 353 | 354 | leave(node, parent) { 355 | programDepth -= 1; 356 | if (node.scope) scope = scope.parent; 357 | if (functionType.test(node.type)) lexicalDepth -= 1; 358 | 359 | if (node.type === 'BlockStatement' && parent.type === 'TryStatement') 360 | tryCatchDepth--; 361 | 362 | if (!isStrict && programDepth === 1 && node.type === 'FunctionDeclaration' && hasDuplicateFunctionDecls && functionDecls.get(node.id.name) !== node) { 363 | magicString.remove(node.start, node.end); 364 | } else if (node.type === 'VariableDeclaration') { 365 | let keepDeclaration = false; 366 | let c = node.declarations[0].start; 367 | 368 | for (let i = 0; i < node.declarations.length; i += 1) { 369 | const declarator = node.declarations[i]; 370 | 371 | if (declarator._shouldRemove) { 372 | magicString.remove(c, declarator.end); 373 | } else { 374 | if (!keepDeclaration) { 375 | magicString.remove(c, declarator.start); 376 | keepDeclaration = true; 377 | } 378 | 379 | c = declarator.end; 380 | } 381 | } 382 | 383 | if (!keepDeclaration) { 384 | magicString.remove(node.start, node.end); 385 | } 386 | } 387 | } 388 | }); 389 | 390 | if ( 391 | !sources.length && 392 | !uses.module && 393 | !uses.exports && 394 | !uses.require && 395 | (ignoreGlobal || !uses.global) && 396 | !hasDuplicateFunctionDecls 397 | ) { 398 | return null; // not a CommonJS module 399 | } 400 | 401 | let includeHelpers = shouldWrap || uses.global || uses.require; 402 | return Promise.resolve() 403 | .then(() => { 404 | // before constructing the import block, remove any optional dependencies that won't resolve 405 | let toError = []; 406 | return Promise.all(sources.map((source, index) => { 407 | if (required[source].optional.length) { 408 | return this.resolveId(source, id) 409 | .then(x => { 410 | if (!x) 411 | toError.push(index) 412 | }) 413 | .catch(() => { 414 | toError.push(index); 415 | }); 416 | } 417 | })) 418 | .then(function () { 419 | let removed = 0; 420 | if (toError.length) 421 | includeHelpers = true; 422 | toError.sort().forEach(index => { 423 | const source = sources[index]; 424 | required[source].optional.forEach(node => { 425 | magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.notFoundRequire('${source}')`); 426 | }); 427 | sources.splice(index - removed, 1); 428 | removed++; 429 | }); 430 | }); 431 | }) 432 | .then(() => { 433 | return (includeHelpers ? [`import * as ${HELPERS_NAME} from '${HELPERS_ID}';`] : []) 434 | .concat( 435 | sources.map(source => { 436 | // import the actual module before the proxy, so that we know 437 | // what kind of proxy to build 438 | return `import '${source}';`; 439 | }), 440 | sources.map(source => { 441 | const { name, importsDefault } = required[source]; 442 | return `import ${importsDefault ? `${name} from ` : ``}'${PROXY_PREFIX}${source}';`; 443 | }) 444 | ) 445 | .join('\n') + '\n\n'; 446 | }) 447 | .then(importBlock => { 448 | const namedExportDeclarations = []; 449 | let wrapperStart = ''; 450 | let wrapperEnd = ''; 451 | 452 | const moduleName = deconflict(scope, globals, getName(id)); 453 | if (!isEntry) { 454 | const exportModuleExports = { 455 | str: `export { ${moduleName} as __moduleExports };`, 456 | name: '__moduleExports' 457 | }; 458 | 459 | namedExportDeclarations.push(exportModuleExports); 460 | } 461 | 462 | const name = getName(id); 463 | 464 | function addExport(x) { 465 | const deconflicted = deconflict(scope, globals, name); 466 | 467 | const declaration = 468 | deconflicted === name 469 | ? `export var ${x} = ${moduleName}.${x};` 470 | : `var ${deconflicted} = ${moduleName}.${x};\nexport { ${deconflicted} as ${x} };`; 471 | 472 | namedExportDeclarations.push({ 473 | str: declaration, 474 | name: x 475 | }); 476 | } 477 | 478 | if (customNamedExports) customNamedExports.forEach(addExport); 479 | 480 | const defaultExportPropertyAssignments = []; 481 | let hasDefaultExport = false; 482 | 483 | if (shouldWrap) { 484 | const args = `module${uses.exports ? ', exports' : ''}`; 485 | 486 | wrapperStart = `var ${moduleName} = ${HELPERS_NAME}.createCommonjsModule(function (${args}) {\n`; 487 | wrapperEnd = `\n});`; 488 | } else { 489 | const names = []; 490 | 491 | ast.body.forEach(node => { 492 | if (node.type === 'ExpressionStatement' && node.expression.type === 'AssignmentExpression') { 493 | const left = node.expression.left; 494 | const flattened = flatten(left); 495 | 496 | if (!flattened) return; 497 | 498 | const match = exportsPattern.exec(flattened.keypath); 499 | if (!match) return; 500 | 501 | if (flattened.keypath === 'module.exports') { 502 | hasDefaultExport = true; 503 | magicString.overwrite(left.start, left.end, `var ${moduleName}`); 504 | } else { 505 | const name = match[1]; 506 | const deconflicted = deconflict(scope, globals, name); 507 | 508 | names.push({ name, deconflicted }); 509 | 510 | magicString.overwrite(node.start, left.end, `var ${deconflicted}`); 511 | 512 | const declaration = 513 | name === deconflicted 514 | ? `export { ${name} };` 515 | : `export { ${deconflicted} as ${name} };`; 516 | 517 | if (name !== 'default') { 518 | namedExportDeclarations.push({ 519 | str: declaration, 520 | name 521 | }); 522 | delete namedExports[name]; 523 | } 524 | 525 | defaultExportPropertyAssignments.push(`${moduleName}.${name} = ${deconflicted};`); 526 | } 527 | } 528 | }); 529 | 530 | if (!hasDefaultExport) { 531 | wrapperEnd = `\n\nvar ${moduleName} = {\n${names 532 | .map(({ name, deconflicted }) => `\t${name}: ${deconflicted}`) 533 | .join(',\n')}\n};`; 534 | } 535 | } 536 | Object.keys(namedExports) 537 | .filter(key => !blacklist[key]) 538 | .forEach(addExport); 539 | 540 | const defaultExport = /__esModule/.test(code) 541 | ? `export default ${HELPERS_NAME}.unwrapExports(${moduleName});` 542 | : `export default ${moduleName};`; 543 | 544 | const named = namedExportDeclarations 545 | .filter(x => x.name !== 'default' || !hasDefaultExport) 546 | .map(x => x.str); 547 | 548 | const exportBlock = 549 | '\n\n' + 550 | [defaultExport] 551 | .concat(named) 552 | .concat(hasDefaultExport ? defaultExportPropertyAssignments : []) 553 | .join('\n'); 554 | 555 | magicString 556 | .trim() 557 | .prepend(importBlock + wrapperStart) 558 | .trim() 559 | .append(wrapperEnd + exportBlock); 560 | 561 | code = magicString.toString(); 562 | const map = sourceMap ? magicString.generateMap() : null; 563 | 564 | return { code, map }; 565 | }); 566 | }); 567 | } 568 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import {basename, dirname, extname, sep} from 'path'; 2 | import {makeLegalIdentifier} from 'rollup-pluginutils'; 3 | 4 | export function getName(id) { 5 | const name = makeLegalIdentifier(basename(id, extname(id))); 6 | if (name !== 'index') { 7 | return name; 8 | } else { 9 | const segments = dirname(id).split(sep); 10 | return makeLegalIdentifier(segments[segments.length - 1]); 11 | } 12 | } 13 | 14 | // Return the first non-falsy result from an array of 15 | // maybe-sync, maybe-promise-returning functions 16 | export function first(candidates) { 17 | return function(...args) { 18 | return candidates.reduce((promise, candidate) => { 19 | return promise.then( 20 | result => (result != null ? result : Promise.resolve(candidate(...args))) 21 | ); 22 | }, Promise.resolve()); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /test/form/async-function/input.js: -------------------------------------------------------------------------------- 1 | module.exports = async function () { 2 | // TODO 3 | }; 4 | -------------------------------------------------------------------------------- /test/form/async-function/output.js: -------------------------------------------------------------------------------- 1 | var input = async function () { 2 | // TODO 3 | }; 4 | 5 | export default input; 6 | export { input as __moduleExports }; 7 | -------------------------------------------------------------------------------- /test/form/constant-template-literal/input.js: -------------------------------------------------------------------------------- 1 | var foo = require(`tape`); 2 | console.log(foo); 3 | -------------------------------------------------------------------------------- /test/form/constant-template-literal/output.js: -------------------------------------------------------------------------------- 1 | import 'tape'; 2 | import foo from 'commonjs-proxy:tape'; 3 | 4 | console.log(foo); 5 | 6 | var input = { 7 | 8 | }; 9 | 10 | export default input; 11 | export { input as __moduleExports }; 12 | -------------------------------------------------------------------------------- /test/form/dynamic-template-literal/input.js: -------------------------------------------------------------------------------- 1 | var pe = 'pe'; 2 | var foo = require(`ta${pe}`); 3 | console.log(foo); 4 | -------------------------------------------------------------------------------- /test/form/dynamic-template-literal/output.js: -------------------------------------------------------------------------------- 1 | import * as commonjsHelpers from 'commonjsHelpers'; 2 | 3 | var pe = 'pe'; 4 | var foo = commonjsHelpers.commonjsRequire(`ta${pe}`); 5 | console.log(foo); 6 | 7 | var input = { 8 | 9 | }; 10 | 11 | export default input; 12 | export { input as __moduleExports }; 13 | -------------------------------------------------------------------------------- /test/form/ignore-ids-function/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | options: { 3 | ignore: id => id === 'foo' 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /test/form/ignore-ids-function/input.js: -------------------------------------------------------------------------------- 1 | var foo = require( 'foo' ); 2 | var bar = require( 'bar' ); -------------------------------------------------------------------------------- /test/form/ignore-ids-function/output.js: -------------------------------------------------------------------------------- 1 | import 'bar'; 2 | import bar from 'commonjs-proxy:bar'; 3 | 4 | var foo = require( 'foo' ); 5 | 6 | var input = { 7 | 8 | }; 9 | 10 | export default input; 11 | export { input as __moduleExports }; -------------------------------------------------------------------------------- /test/form/ignore-ids/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | options: { 3 | ignore: ['foo'] 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /test/form/ignore-ids/input.js: -------------------------------------------------------------------------------- 1 | var foo = require( 'foo' ); 2 | var bar = require( 'bar' ); -------------------------------------------------------------------------------- /test/form/ignore-ids/output.js: -------------------------------------------------------------------------------- 1 | import 'bar'; 2 | import bar from 'commonjs-proxy:bar'; 3 | 4 | var foo = require( 'foo' ); 5 | 6 | var input = { 7 | 8 | }; 9 | 10 | export default input; 11 | export { input as __moduleExports }; -------------------------------------------------------------------------------- /test/form/multiple-var-declarations-b/input.js: -------------------------------------------------------------------------------- 1 | var a = require('./a') 2 | , b = 42; 3 | 4 | console.log( a, b ); -------------------------------------------------------------------------------- /test/form/multiple-var-declarations-b/output.js: -------------------------------------------------------------------------------- 1 | import './a'; 2 | import a from 'commonjs-proxy:./a'; 3 | 4 | var b = 42; 5 | 6 | console.log( a, b ); 7 | 8 | var input = { 9 | 10 | }; 11 | 12 | export default input; 13 | export { input as __moduleExports }; -------------------------------------------------------------------------------- /test/form/multiple-var-declarations-c/input.js: -------------------------------------------------------------------------------- 1 | var a = 'a' 2 | , b = require( './b' ) 3 | , c = 'c'; 4 | 5 | console.log( a, b, c ); -------------------------------------------------------------------------------- /test/form/multiple-var-declarations-c/output.js: -------------------------------------------------------------------------------- 1 | import './b'; 2 | import b from 'commonjs-proxy:./b'; 3 | 4 | var a = 'a' 5 | , c = 'c'; 6 | 7 | console.log( a, b, c ); 8 | 9 | var input = { 10 | 11 | }; 12 | 13 | export default input; 14 | export { input as __moduleExports }; -------------------------------------------------------------------------------- /test/form/multiple-var-declarations/input.js: -------------------------------------------------------------------------------- 1 | var a = require('./a')() 2 | , b = require('./b'); 3 | 4 | console.log( a, b ); -------------------------------------------------------------------------------- /test/form/multiple-var-declarations/output.js: -------------------------------------------------------------------------------- 1 | import './a'; 2 | import './b'; 3 | import require$$0 from 'commonjs-proxy:./a'; 4 | import b from 'commonjs-proxy:./b'; 5 | 6 | var a = require$$0(); 7 | 8 | console.log( a, b ); 9 | 10 | var input = { 11 | 12 | }; 13 | 14 | export default input; 15 | export { input as __moduleExports }; -------------------------------------------------------------------------------- /test/form/no-toplevel-return/input.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | return; 3 | }; 4 | 5 | var bar = () => { 6 | return; 7 | }; 8 | 9 | function baz () { 10 | return; 11 | } 12 | 13 | module.exports = 42; 14 | -------------------------------------------------------------------------------- /test/form/no-toplevel-return/output.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | return; 3 | }; 4 | 5 | var bar = () => { 6 | return; 7 | }; 8 | 9 | function baz () { 10 | return; 11 | } 12 | 13 | var input = 42; 14 | 15 | export default input; 16 | export { input as __moduleExports }; 17 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-function-double-assign/input.js: -------------------------------------------------------------------------------- 1 | var bar; 2 | module.exports = bar = function foo () {}; 3 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-function-double-assign/output.js: -------------------------------------------------------------------------------- 1 | var bar; 2 | var input = bar = function foo () {}; 3 | 4 | export default input; 5 | export { input as __moduleExports }; 6 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-function/input.js: -------------------------------------------------------------------------------- 1 | module.exports = function foo () {}; 2 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-function/output.js: -------------------------------------------------------------------------------- 1 | var input = function foo () {}; 2 | 3 | export default input; 4 | export { input as __moduleExports }; 5 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-iife/input.js: -------------------------------------------------------------------------------- 1 | module.exports = (function foo () { 2 | return function fooChild() {}; 3 | }()); 4 | -------------------------------------------------------------------------------- /test/form/optimised-default-export-iife/output.js: -------------------------------------------------------------------------------- 1 | var input = (function foo () { 2 | return function fooChild() {}; 3 | }()); 4 | 5 | export default input; 6 | export { input as __moduleExports }; 7 | -------------------------------------------------------------------------------- /test/form/optimised-default-export/input.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /test/form/optimised-default-export/output.js: -------------------------------------------------------------------------------- 1 | var input = 42; 2 | 3 | export default input; 4 | export { input as __moduleExports }; 5 | -------------------------------------------------------------------------------- /test/form/optimised-named-export-conflicts/input.js: -------------------------------------------------------------------------------- 1 | var foo = 1; 2 | var bar = 2; 3 | 4 | exports.foo = 'a'; 5 | module.exports.bar = 'b'; 6 | -------------------------------------------------------------------------------- /test/form/optimised-named-export-conflicts/output.js: -------------------------------------------------------------------------------- 1 | var foo = 1; 2 | var bar = 2; 3 | 4 | var foo_1 = 'a'; 5 | var bar_1 = 'b'; 6 | 7 | var input = { 8 | foo: foo_1, 9 | bar: bar_1 10 | }; 11 | 12 | export default input; 13 | export { input as __moduleExports }; 14 | export { foo_1 as foo }; 15 | export { bar_1 as bar }; 16 | -------------------------------------------------------------------------------- /test/form/optimised-named-export/input.js: -------------------------------------------------------------------------------- 1 | exports.foo = 'a'; 2 | module.exports.bar = 'b'; 3 | -------------------------------------------------------------------------------- /test/form/optimised-named-export/output.js: -------------------------------------------------------------------------------- 1 | var foo = 'a'; 2 | var bar = 'b'; 3 | 4 | var input = { 5 | foo: foo, 6 | bar: bar 7 | }; 8 | 9 | export default input; 10 | export { input as __moduleExports }; 11 | export { foo }; 12 | export { bar }; 13 | -------------------------------------------------------------------------------- /test/form/require-collision/input.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var foo = require("foo"); 3 | var require$$0 = "FAIL"; 4 | console.log(foo); 5 | })(); 6 | -------------------------------------------------------------------------------- /test/form/require-collision/output.js: -------------------------------------------------------------------------------- 1 | import 'foo'; 2 | import require$$1 from 'commonjs-proxy:foo'; 3 | 4 | (function() { 5 | var foo = require$$1; 6 | var require$$0 = "FAIL"; 7 | console.log(foo); 8 | })(); 9 | 10 | var input = { 11 | 12 | }; 13 | 14 | export default input; 15 | export { input as __moduleExports }; 16 | -------------------------------------------------------------------------------- /test/form/typeof-module-exports/input.js: -------------------------------------------------------------------------------- 1 | var foo = 42; 2 | 3 | if ( typeof exports === 'object' && typeof module === 'object' ) { 4 | module.exports = foo; 5 | } else if ( typeof define === 'function' && define.amd ) { 6 | define([], function () { return foo; }); 7 | } else { 8 | window.foo = foo; 9 | } 10 | -------------------------------------------------------------------------------- /test/form/typeof-module-exports/output.js: -------------------------------------------------------------------------------- 1 | import * as commonjsHelpers from 'commonjsHelpers'; 2 | 3 | var input = commonjsHelpers.createCommonjsModule(function (module, exports) { 4 | var foo = 42; 5 | 6 | if ( 'object' === 'object' && 'object' === 'object' ) { 7 | module.exports = foo; 8 | } else if ( typeof undefined === 'function' && undefined.amd ) { 9 | undefined([], function () { return foo; }); 10 | } else { 11 | window.foo = foo; 12 | } 13 | }); 14 | 15 | export default input; 16 | export { input as __moduleExports }; 17 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-default-export/input.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-default-export/output.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | export default {}; 4 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-import/input.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | import './bar.js'; 4 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-import/output.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | import './bar.js'; 4 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-named-export/input.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | export {}; 4 | -------------------------------------------------------------------------------- /test/form/unambiguous-with-named-export/output.js: -------------------------------------------------------------------------------- 1 | require( './foo.js' ); 2 | 3 | export {}; 4 | -------------------------------------------------------------------------------- /test/function/__esModule/answer.js: -------------------------------------------------------------------------------- 1 | exports.__esModule = true; 2 | exports.answer = 42; 3 | -------------------------------------------------------------------------------- /test/function/__esModule/main.js: -------------------------------------------------------------------------------- 1 | import * as x from './answer'; 2 | 3 | assert.ok( 'answer' in x ); 4 | assert.ok( 'default' in x ); // TODO is this right? 5 | assert.ok( !( '__esModule' in x ) ); 6 | -------------------------------------------------------------------------------- /test/function/assign-properties-to-default-export/foo.js: -------------------------------------------------------------------------------- 1 | var foo = {}; 2 | 3 | module.exports = foo; 4 | module.exports.bar = 1; 5 | exports.baz = 2; 6 | -------------------------------------------------------------------------------- /test/function/assign-properties-to-default-export/main.js: -------------------------------------------------------------------------------- 1 | import foo from './foo.js'; 2 | 3 | assert.equal( foo.bar, 1 ); 4 | assert.equal( foo.baz, 2 ); 5 | -------------------------------------------------------------------------------- /test/function/assumed-globals/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | document: { real: true } 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /test/function/assumed-globals/document.js: -------------------------------------------------------------------------------- 1 | if ( typeof document !== 'undefined' ) { 2 | module.exports = document; 3 | } else { 4 | module.exports = { fake: true }; 5 | } 6 | -------------------------------------------------------------------------------- /test/function/assumed-globals/main.js: -------------------------------------------------------------------------------- 1 | import document from './document.js'; 2 | 3 | assert.deepEqual( document, { real: true }); 4 | -------------------------------------------------------------------------------- /test/function/bare-import-comment/bar.js: -------------------------------------------------------------------------------- 1 | // Great module 2 | Math.bar = 42; 3 | -------------------------------------------------------------------------------- /test/function/bare-import-comment/foo.js: -------------------------------------------------------------------------------- 1 | require( './bar.js' ); 2 | -------------------------------------------------------------------------------- /test/function/bare-import-comment/main.js: -------------------------------------------------------------------------------- 1 | import './foo.js'; 2 | 3 | assert.equal( Math.bar, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/bare-import/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /test/function/bare-import/bar.js: -------------------------------------------------------------------------------- 1 | Math.bar = 42; 2 | -------------------------------------------------------------------------------- /test/function/bare-import/foo.js: -------------------------------------------------------------------------------- 1 | require( './bar.js' ); 2 | -------------------------------------------------------------------------------- /test/function/bare-import/main.js: -------------------------------------------------------------------------------- 1 | import './foo.js'; 2 | 3 | assert.equal( Math.bar, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/basic/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports, 42); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/basic/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = 21; 2 | -------------------------------------------------------------------------------- /test/function/basic/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo' ); 2 | module.exports = foo * 2; 3 | -------------------------------------------------------------------------------- /test/function/deconflict-export-and-local/index.js: -------------------------------------------------------------------------------- 1 | var someValueModule = require('./someValue'); 2 | 3 | exports.someValue = someValueModule.someValue; 4 | -------------------------------------------------------------------------------- /test/function/deconflict-export-and-local/main.js: -------------------------------------------------------------------------------- 1 | import { someValue } from './index.js'; 2 | 3 | assert.equal( someValue, 10 ); 4 | -------------------------------------------------------------------------------- /test/function/deconflict-export-and-local/someValue.js: -------------------------------------------------------------------------------- 1 | exports.someValue = 10; 2 | -------------------------------------------------------------------------------- /test/function/dot/foo.bar.js: -------------------------------------------------------------------------------- 1 | module.exports = 'fubar'; 2 | -------------------------------------------------------------------------------- /test/function/dot/main.js: -------------------------------------------------------------------------------- 1 | var status = require( './foo.bar' ); 2 | 3 | assert.equal( status, 'fubar' ); 4 | -------------------------------------------------------------------------------- /test/function/duplicate-default-exports-b/main.js: -------------------------------------------------------------------------------- 1 | import x from './x'; 2 | 3 | assert.deepEqual( x, { default: 42 }); -------------------------------------------------------------------------------- /test/function/duplicate-default-exports-b/x.js: -------------------------------------------------------------------------------- 1 | var x = {}; 2 | 3 | module.exports = x; 4 | module.exports.default = 42; -------------------------------------------------------------------------------- /test/function/duplicate-default-exports-c/exports.js: -------------------------------------------------------------------------------- 1 | exports.Foo = 1; 2 | exports.var = 'VAR'; 3 | exports.default = { 4 | Foo: 2, 5 | default: 3 6 | }; 7 | -------------------------------------------------------------------------------- /test/function/duplicate-default-exports-c/main.js: -------------------------------------------------------------------------------- 1 | import E from './exports.js'; 2 | import { Foo } from './exports.js'; 3 | import { var as Var } from './exports.js'; 4 | 5 | assert.strictEqual( E.Foo, 1 ); 6 | assert.strictEqual( E.var, 'VAR' ); 7 | assert.deepEqual( E.default, { Foo: 2, default: 3 }); 8 | assert.strictEqual( E.default.Foo, 2 ); 9 | assert.strictEqual( E.default.default, 3 ); 10 | assert.strictEqual( Foo, 1 ); 11 | assert.strictEqual( Var, 'VAR' ); 12 | -------------------------------------------------------------------------------- /test/function/duplicate-default-exports/main.js: -------------------------------------------------------------------------------- 1 | import x from './x'; 2 | 3 | assert.strictEqual( x.default, x ); -------------------------------------------------------------------------------- /test/function/duplicate-default-exports/x.js: -------------------------------------------------------------------------------- 1 | var x = {}; 2 | 3 | module.exports = x; 4 | module.exports.default = x; -------------------------------------------------------------------------------- /test/function/export-default-from/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; 2 | -------------------------------------------------------------------------------- /test/function/export-default-from/imported.js: -------------------------------------------------------------------------------- 1 | export default 'default export'; 2 | -------------------------------------------------------------------------------- /test/function/export-default-from/main.js: -------------------------------------------------------------------------------- 1 | assert.equal(require('./reexporter'), 'default export'); 2 | -------------------------------------------------------------------------------- /test/function/export-default-from/reexporter.js: -------------------------------------------------------------------------------- 1 | export {default} from './imported'; 2 | -------------------------------------------------------------------------------- /test/function/exports/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports, 'BARBAZ'); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/exports/foo.js: -------------------------------------------------------------------------------- 1 | exports.bar = 'BAR'; 2 | exports.baz = 'BAZ'; 3 | -------------------------------------------------------------------------------- /test/function/exports/main.js: -------------------------------------------------------------------------------- 1 | var bar = require( './foo' ).bar; 2 | var baz = require( './foo' ).baz; 3 | 4 | module.exports = bar + baz; 5 | -------------------------------------------------------------------------------- /test/function/external-imports/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | options: { 5 | external: ['foo'] 6 | }, 7 | exports: exports => { 8 | assert.equal(exports, 'foo'); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /test/function/external-imports/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( 'foo' ); 2 | 3 | module.exports = foo; 4 | -------------------------------------------------------------------------------- /test/function/fallback-no-default/foo.js: -------------------------------------------------------------------------------- 1 | export var one = 1; 2 | 3 | export var two = 2; 4 | -------------------------------------------------------------------------------- /test/function/fallback-no-default/main.js: -------------------------------------------------------------------------------- 1 | var foo = require('./foo.js'); 2 | 3 | assert.equal( foo.one, 1 ); 4 | assert.equal( foo.two, 2 ); 5 | -------------------------------------------------------------------------------- /test/function/global-not-overwritten/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports(exports) { 5 | assert.equal(exports.encoded, encodeURIComponent('test string')); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/global-not-overwritten/encode.js: -------------------------------------------------------------------------------- 1 | exports.encodeURIComponent = function () { 2 | return encodeURIComponent( this.str ); 3 | }; 4 | 5 | global.foo = exports; // to ensure module is wrapped 6 | -------------------------------------------------------------------------------- /test/function/global-not-overwritten/main.js: -------------------------------------------------------------------------------- 1 | import { encodeURIComponent } from './encode.js'; 2 | 3 | var foo = { 4 | str: 'test string', 5 | encodeURIComponent 6 | }; 7 | 8 | export var encoded = foo.encodeURIComponent(); 9 | -------------------------------------------------------------------------------- /test/function/global-var/main.js: -------------------------------------------------------------------------------- 1 | function foo () { 2 | var a = 1, global = {}; 3 | global.modified = true; 4 | return global; 5 | } 6 | 7 | var notGlobal = foo(); 8 | assert.ok( notGlobal.modified ); 9 | assert.ok( !global.modified ); 10 | 11 | module.exports = {}; 12 | -------------------------------------------------------------------------------- /test/function/index/foo/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /test/function/index/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo' ); 2 | 3 | assert.equal( foo, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/inline/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports(), 2); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/inline/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = 1; 2 | -------------------------------------------------------------------------------- /test/function/inline/main.js: -------------------------------------------------------------------------------- 1 | module.exports = function () { 2 | return require( './multiply' )( 2, require( './foo' ) ); 3 | }; 4 | -------------------------------------------------------------------------------- /test/function/inline/multiply.js: -------------------------------------------------------------------------------- 1 | module.exports = function ( a, b ) { 2 | return a * b; 3 | }; 4 | -------------------------------------------------------------------------------- /test/function/named-exports/foo.js: -------------------------------------------------------------------------------- 1 | exports.a = 1; 2 | module.exports.b = 2; 3 | -------------------------------------------------------------------------------- /test/function/named-exports/main.js: -------------------------------------------------------------------------------- 1 | import { a, b } from './foo.js'; 2 | 3 | assert.equal( a, 1 ); 4 | assert.equal( b, 2 ); 5 | -------------------------------------------------------------------------------- /test/function/optional-require/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports.caughtOk, true); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/optional-require/main.js: -------------------------------------------------------------------------------- 1 | try { 2 | require('does-not-exist'); 3 | } 4 | catch (err) { 5 | if (err instanceof Error && err.message === 'Cannot find module \'does-not-exist\'.') 6 | exports.caughtOk = true; 7 | } -------------------------------------------------------------------------------- /test/function/ordering/bar.js: -------------------------------------------------------------------------------- 1 | var shared = require('./shared'); 2 | 3 | module.exports = shared.fooLoaded 4 | -------------------------------------------------------------------------------- /test/function/ordering/foo.js: -------------------------------------------------------------------------------- 1 | var shared = require('./shared'); 2 | 3 | // Mutate the shared module 4 | shared.fooLoaded = true; 5 | -------------------------------------------------------------------------------- /test/function/ordering/main.js: -------------------------------------------------------------------------------- 1 | require('./foo'); 2 | 3 | var fooLoaded = require('./bar'); 4 | 5 | assert.ok( fooLoaded ); 6 | -------------------------------------------------------------------------------- /test/function/ordering/shared.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | fooLoaded: false 3 | }; 4 | -------------------------------------------------------------------------------- /test/function/react-apollo/commonjs-bar.js: -------------------------------------------------------------------------------- 1 | function Bar () { 2 | this.x = 42; 3 | } 4 | 5 | exports.__esModule = true; 6 | exports.default = Bar; 7 | -------------------------------------------------------------------------------- /test/function/react-apollo/commonjs-foo.js: -------------------------------------------------------------------------------- 1 | var Bar = require( './commonjs-bar' ); 2 | 3 | exports.__esModule = true; 4 | exports.Bar = Bar.default; 5 | -------------------------------------------------------------------------------- /test/function/react-apollo/main.js: -------------------------------------------------------------------------------- 1 | import { Bar } from './commonjs-foo.js'; 2 | 3 | assert.equal( new Bar().x, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/reassignment/foo.js: -------------------------------------------------------------------------------- 1 | function foo () {} 2 | foo.something = false; 3 | 4 | module.exports = foo; 5 | -------------------------------------------------------------------------------- /test/function/reassignment/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo.js' ); 2 | 3 | if ( !foo.something ) { 4 | foo = function somethingElse () {} 5 | foo.something = true; 6 | } 7 | 8 | assert.ok( foo.something ); 9 | -------------------------------------------------------------------------------- /test/function/reexports/_config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | pluginOptions: { 5 | namedExports: { 6 | [path.resolve(__dirname, 'foo.js')]: ['named'] 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /test/function/reexports/bar.js: -------------------------------------------------------------------------------- 1 | exports.named = 42; 2 | -------------------------------------------------------------------------------- /test/function/reexports/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = require( './bar.js' ); 2 | -------------------------------------------------------------------------------- /test/function/reexports/main.js: -------------------------------------------------------------------------------- 1 | import { named } from './foo.js'; 2 | 3 | assert.equal( named, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-extension/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | description: 'always resolve cjs detection even if an imported file has an unknown extension', 3 | options: { 4 | plugins: [ 5 | { 6 | resolveId(importee) { 7 | if (importee === 'second') { 8 | return `${__dirname}/second.x`; 9 | } 10 | } 11 | } 12 | ] 13 | }, 14 | pluginOptions: {} 15 | }; 16 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-extension/main.js: -------------------------------------------------------------------------------- 1 | assert.equal(require('second').result, 'second' ); 2 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-extension/second.x: -------------------------------------------------------------------------------- 1 | export const result = 'second'; 2 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-filtered/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | description: 'always resolve cjs detection even if an imported file is filtered', 3 | options: { 4 | plugins: [ 5 | { 6 | resolveId(importee) { 7 | if (importee === 'second') { 8 | return `${__dirname}/second.js`; 9 | } 10 | } 11 | } 12 | ] 13 | }, 14 | pluginOptions: { 15 | include: ['function/resolve-is-cjs-filtered/main.js'] 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-filtered/main.js: -------------------------------------------------------------------------------- 1 | assert.equal(require('second').result, 'second' ); 2 | -------------------------------------------------------------------------------- /test/function/resolve-is-cjs-filtered/second.js: -------------------------------------------------------------------------------- 1 | export const result = 'second'; 2 | -------------------------------------------------------------------------------- /test/function/shadowing/main.js: -------------------------------------------------------------------------------- 1 | function foo ( require ) { 2 | require( 'not-an-actual-require-statement' ); 3 | } 4 | 5 | var result; 6 | 7 | foo( function ( msg ) { 8 | result = msg; 9 | }); 10 | 11 | assert.equal( result, 'not-an-actual-require-statement' ); 12 | -------------------------------------------------------------------------------- /test/function/skips-dead-branches/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | global: global => { 5 | assert.equal(global.a, undefined); 6 | assert.equal(global.b, 2); 7 | assert.equal(global.c, undefined); 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /test/function/skips-dead-branches/a.js: -------------------------------------------------------------------------------- 1 | global.a = 1; 2 | -------------------------------------------------------------------------------- /test/function/skips-dead-branches/b.js: -------------------------------------------------------------------------------- 1 | global.b = 2; 2 | module.exports = 'b'; 3 | -------------------------------------------------------------------------------- /test/function/skips-dead-branches/c.js: -------------------------------------------------------------------------------- 1 | global.c = 3; 2 | module.exports = 'c'; 3 | -------------------------------------------------------------------------------- /test/function/skips-dead-branches/main.js: -------------------------------------------------------------------------------- 1 | if ( 'development' === 'production' ) { 2 | require( './a.js' ); 3 | } 4 | 5 | module.exports = true ? 6 | require( './b.js' ) : 7 | require( './c.js' ); 8 | -------------------------------------------------------------------------------- /test/function/strict-fn-duplicates/main.js: -------------------------------------------------------------------------------- 1 | function x () { 'a' } 2 | function x () { 'b' } 3 | x(); -------------------------------------------------------------------------------- /test/function/strict-should-fail/_config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | err: "Identifier 'x' has already been declared" 3 | }; 4 | -------------------------------------------------------------------------------- /test/function/strict-should-fail/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | function x () { 'a' } 3 | function x () { 'b' } 4 | x(); -------------------------------------------------------------------------------- /test/function/this/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = function augmentThis () { 2 | this.x = 'x'; 3 | }; 4 | 5 | this.y = 'y'; 6 | -------------------------------------------------------------------------------- /test/function/this/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo' ); 2 | 3 | var obj = {}; 4 | foo.call( obj ); 5 | 6 | assert.equal( obj.x, 'x' ); 7 | assert.equal( this.y, 'y' ); 8 | -------------------------------------------------------------------------------- /test/function/toplevel-return-complex/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports, 'bar'); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/toplevel-return-complex/bar.js: -------------------------------------------------------------------------------- 1 | module.exports = function () { 2 | return true; 3 | }; 4 | -------------------------------------------------------------------------------- /test/function/toplevel-return-complex/foo.js: -------------------------------------------------------------------------------- 1 | var bar = require('./bar'); 2 | module.exports = 'bar'; 3 | if (bar()) { 4 | return; 5 | } 6 | module.exports = 'foo'; 7 | -------------------------------------------------------------------------------- /test/function/toplevel-return-complex/main.js: -------------------------------------------------------------------------------- 1 | var foo = require('./foo'); 2 | 3 | module.exports = foo; 4 | -------------------------------------------------------------------------------- /test/function/toplevel-return/_config.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | module.exports = { 4 | exports: exports => { 5 | assert.equal(exports, 'foo'); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /test/function/toplevel-return/foo.js: -------------------------------------------------------------------------------- 1 | module.exports = 'foo'; 2 | return; 3 | -------------------------------------------------------------------------------- /test/function/toplevel-return/main.js: -------------------------------------------------------------------------------- 1 | var foo = require('./foo'); 2 | 3 | module.exports = 'foo'; 4 | -------------------------------------------------------------------------------- /test/function/trailing-slash/foo/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 42; 2 | -------------------------------------------------------------------------------- /test/function/trailing-slash/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo/' ); 2 | 3 | assert.equal( foo, 42 ); 4 | -------------------------------------------------------------------------------- /test/function/typeof-require/foo.js: -------------------------------------------------------------------------------- 1 | if ( typeof require === 'function' && require ) { 2 | module.exports = 1; 3 | } else { 4 | module.exports = 2; 5 | } 6 | -------------------------------------------------------------------------------- /test/function/typeof-require/main.js: -------------------------------------------------------------------------------- 1 | import foo from './foo.js'; 2 | 3 | assert.equal( foo, 1 ); 4 | -------------------------------------------------------------------------------- /test/node_modules/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drylikov/Rollup_plugin_CommonJS_modules/c2ba853b66e2bbb42f156616c4ce10305c868b05/test/node_modules/.gitkeep -------------------------------------------------------------------------------- /test/node_modules/bar/index.js: -------------------------------------------------------------------------------- 1 | const baz = require('baz'); 2 | module.exports = function () { 3 | return baz; 4 | }; -------------------------------------------------------------------------------- /test/node_modules/baz/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'hello'; -------------------------------------------------------------------------------- /test/node_modules/external/index.js: -------------------------------------------------------------------------------- 1 | var externalLib = exports; 2 | externalLib.message = 'it works'; 3 | -------------------------------------------------------------------------------- /test/node_modules/foo/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'foo'; -------------------------------------------------------------------------------- /test/samples/corejs/literal-with-default.js: -------------------------------------------------------------------------------- 1 | module.exports = { default: 'foobar', __esModule: true }; 2 | -------------------------------------------------------------------------------- /test/samples/custom-named-exports-false-positive/main.js: -------------------------------------------------------------------------------- 1 | import { thing } from './other.js'; 2 | assert.equal( thing, 'yes' ); 3 | -------------------------------------------------------------------------------- /test/samples/custom-named-exports-false-positive/other.js: -------------------------------------------------------------------------------- 1 | /* require (https://github.com/rollup/rollup-plugin-commonjs/issues/36) */ 2 | export var thing = 'yes'; 3 | -------------------------------------------------------------------------------- /test/samples/custom-named-exports/main.js: -------------------------------------------------------------------------------- 1 | import { named } from './secret-named-exporter.js'; 2 | import { message } from 'external'; 3 | 4 | assert.equal( named, 42 ); 5 | assert.equal( message, 'it works' ); 6 | -------------------------------------------------------------------------------- /test/samples/custom-named-exports/secret-named-exporter.js: -------------------------------------------------------------------------------- 1 | var myLib = exports; 2 | myLib.named = 42; 3 | -------------------------------------------------------------------------------- /test/samples/deconflict-helpers/main.js: -------------------------------------------------------------------------------- 1 | var commonjsHelpers = { commonjsGlobal: 'nope' }; 2 | module.exports = global; 3 | -------------------------------------------------------------------------------- /test/samples/define-is-undefined/foo.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof define === 'function' && define.amd ? define(factory) : 3 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 4 | (global.foo = factory()); 5 | }(this, (function () { 'use strict'; 6 | 7 | return 42; 8 | 9 | }))); 10 | -------------------------------------------------------------------------------- /test/samples/define-is-undefined/main.js: -------------------------------------------------------------------------------- 1 | import foo from './foo.js'; 2 | 3 | export default 42; 4 | -------------------------------------------------------------------------------- /test/samples/es-modules-without-default-export/main.js: -------------------------------------------------------------------------------- 1 | const { a } = require('./other.js'); 2 | 3 | assert.equal( a, 1 ); 4 | -------------------------------------------------------------------------------- /test/samples/es-modules-without-default-export/other.js: -------------------------------------------------------------------------------- 1 | export const a = 1; 2 | -------------------------------------------------------------------------------- /test/samples/extension/foo.coffee: -------------------------------------------------------------------------------- 1 | module.exports = 21; 2 | -------------------------------------------------------------------------------- /test/samples/extension/main.coffee: -------------------------------------------------------------------------------- 1 | var foo = require( './foo' ); 2 | module.exports = foo * 2; 3 | -------------------------------------------------------------------------------- /test/samples/external/main.js: -------------------------------------------------------------------------------- 1 | import bar from 'bar'; 2 | 3 | export default bar().toUpperCase(); -------------------------------------------------------------------------------- /test/samples/global-in-if-block/main.js: -------------------------------------------------------------------------------- 1 | if (!global.count) { 2 | global.count = 0; 3 | } 4 | 5 | global.count += 1; 6 | -------------------------------------------------------------------------------- /test/samples/global/main.js: -------------------------------------------------------------------------------- 1 | global.foo = 'bar'; 2 | -------------------------------------------------------------------------------- /test/samples/ignore-global/firstpass.js: -------------------------------------------------------------------------------- 1 | export var immediate = typeof global.setImmediate === 'function' ? 2 | global.setImmediate : global.setTimeout; 3 | -------------------------------------------------------------------------------- /test/samples/ignore-global/identifier.js: -------------------------------------------------------------------------------- 1 | // require (firstpass) 2 | 3 | export var immediate = typeof global.setImmediate === 'function' ? 4 | global.setImmediate : global.setTimeout; 5 | -------------------------------------------------------------------------------- /test/samples/ignore-global/main.js: -------------------------------------------------------------------------------- 1 | export { immediate as immediate1 } from './firstpass'; 2 | export { immediate as immediate2 } from './identifier'; 3 | export { immediate as immediate3 } from './this'; 4 | -------------------------------------------------------------------------------- /test/samples/ignore-global/this.js: -------------------------------------------------------------------------------- 1 | // require (firstpass) 2 | 3 | // "this" will be rewritten with "undefined" by rollup 4 | export var immediate = typeof this === 'undefined' ? 5 | null : typeof this.setImmediate === 'function' ? 6 | this.setImmediate : this.setTimeout; 7 | -------------------------------------------------------------------------------- /test/samples/ignore-virtual-modules/main.js: -------------------------------------------------------------------------------- 1 | module.exports = require('\0virtual'); 2 | -------------------------------------------------------------------------------- /test/samples/invalid-syntax/main.js: -------------------------------------------------------------------------------- 1 | export const foo = 2, -------------------------------------------------------------------------------- /test/samples/multiple-entry-points/2.js: -------------------------------------------------------------------------------- 1 | function second () { 2 | console.log('second'); 3 | } 4 | exports.second = second; -------------------------------------------------------------------------------- /test/samples/multiple-entry-points/3.js: -------------------------------------------------------------------------------- 1 | function third () { 2 | console.log('third'); 3 | } 4 | 5 | exports.third = third; 6 | -------------------------------------------------------------------------------- /test/samples/multiple-entry-points/4.js: -------------------------------------------------------------------------------- 1 | export function fourth () { 2 | console.log('fourth'); 3 | } 4 | -------------------------------------------------------------------------------- /test/samples/multiple-entry-points/b.js: -------------------------------------------------------------------------------- 1 | import { second } from './2'; 2 | import { third } from './3'; 3 | 4 | second(); 5 | third(); 6 | -------------------------------------------------------------------------------- /test/samples/multiple-entry-points/c.js: -------------------------------------------------------------------------------- 1 | import { second } from './2'; 2 | import { third } from './3'; 3 | import { fourth } from './4'; 4 | 5 | second(); 6 | third(); 7 | fourth(); 8 | -------------------------------------------------------------------------------- /test/samples/named-exports-from-object-literal/a.js: -------------------------------------------------------------------------------- 1 | module.exports = 1; 2 | -------------------------------------------------------------------------------- /test/samples/named-exports-from-object-literal/main.js: -------------------------------------------------------------------------------- 1 | import { a, b, c } from './other.js'; 2 | 3 | assert.equal( a, 1 ); 4 | assert.equal( b, 2 ); 5 | assert.equal( c, 3 ); 6 | -------------------------------------------------------------------------------- /test/samples/named-exports-from-object-literal/other.js: -------------------------------------------------------------------------------- 1 | var a = require( './a.js' ); 2 | var b = 2; 3 | 4 | module.exports = { 5 | a: a, 6 | b: b, 7 | c: a + b, 8 | 2: 1 + 1 9 | }; 10 | -------------------------------------------------------------------------------- /test/samples/other-transforms/bar.js: -------------------------------------------------------------------------------- 1 | module.exports = 40; 2 | -------------------------------------------------------------------------------- /test/samples/other-transforms/foo.js: -------------------------------------------------------------------------------- 1 | var bar = require( './bar.js' ); 2 | 3 | module.exports = bar + 1; 4 | -------------------------------------------------------------------------------- /test/samples/other-transforms/main.js: -------------------------------------------------------------------------------- 1 | import foo from './foo.js'; 2 | 3 | assert.equal( foo, 42 ); 4 | -------------------------------------------------------------------------------- /test/samples/paren-expression/index.js: -------------------------------------------------------------------------------- 1 | module.exports = (42); 2 | -------------------------------------------------------------------------------- /test/samples/reexport/export.js: -------------------------------------------------------------------------------- 1 | exports.named = 2; 2 | -------------------------------------------------------------------------------- /test/samples/reexport/main.js: -------------------------------------------------------------------------------- 1 | import { named } from './reexport.js'; 2 | 3 | assert.equal(named, 2); 4 | -------------------------------------------------------------------------------- /test/samples/reexport/reexport.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./export.js'); 2 | -------------------------------------------------------------------------------- /test/samples/rename-index/invalid-var/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'invalid'; 2 | -------------------------------------------------------------------------------- /test/samples/rename-index/main.js: -------------------------------------------------------------------------------- 1 | import invalid from './invalid-var'; 2 | import valid from './validVar'; 3 | import other from './other/nonIndex'; 4 | 5 | console.log(invalid, valid, other); 6 | -------------------------------------------------------------------------------- /test/samples/rename-index/other/nonIndex.js: -------------------------------------------------------------------------------- 1 | module.exports = 'not an index file'; 2 | -------------------------------------------------------------------------------- /test/samples/rename-index/validVar/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 'valid'; 2 | -------------------------------------------------------------------------------- /test/samples/reserved-as-property/main.js: -------------------------------------------------------------------------------- 1 | module.exports.delete = 'foo'; 2 | -------------------------------------------------------------------------------- /test/samples/sourcemap/foo.js: -------------------------------------------------------------------------------- 1 | export default 42; 2 | -------------------------------------------------------------------------------- /test/samples/sourcemap/main.js: -------------------------------------------------------------------------------- 1 | var foo = require( './foo' ); 2 | console.log( foo ); 3 | -------------------------------------------------------------------------------- /test/samples/umd/correct-scoping.js: -------------------------------------------------------------------------------- 1 | if ( typeof require === 'function' ) { 2 | module.exports = function ( require ) { 3 | return typeof require; 4 | }( {} ); 5 | } 6 | -------------------------------------------------------------------------------- /test/samples/umd/protobuf.js: -------------------------------------------------------------------------------- 1 | // From https://github.com/rollup/rollup-plugin-commonjs/issues/38 2 | (function(global, factory) { 3 | /* AMD */ if (typeof define === 'function' && define["amd"]) 4 | define(["foo"], factory); 5 | /* CommonJS */ else if (typeof require === "function" && typeof module === "object" && module && module["exports"]) 6 | module["exports"] = factory(require("foo"), true); 7 | /* Global */ else 8 | (global["dcodeIO"] = global["dcodeIO"] || {})["ProtoBuf"] = factory(global["dcodeIO"]["ByteBuffer"]); 9 | })(this, function(ByteBuffer, isCommonJS) { 10 | return isCommonJS; 11 | }) 12 | -------------------------------------------------------------------------------- /test/samples/umd/sinon.js: -------------------------------------------------------------------------------- 1 | // From https://github.com/rollup/rollup-plugin-commonjs/issues/38 2 | var sinon = (function () { // eslint-disable-line no-unused-vars 3 | "use strict"; 4 | 5 | var sinonModule; 6 | var isNode = typeof module !== "undefined" && module.exports && typeof require === "function"; 7 | var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd; 8 | 9 | function loadDependencies(require, exports, module) { 10 | sinonModule = module.exports = require("./sinon/util/core"); 11 | require("./sinon/extend"); 12 | require("./sinon/walk"); 13 | require("./sinon/typeOf"); 14 | require("./sinon/times_in_words"); 15 | require("./sinon/spy"); 16 | require("./sinon/call"); 17 | require("./sinon/behavior"); 18 | require("./sinon/stub"); 19 | require("./sinon/mock"); 20 | require("./sinon/collection"); 21 | require("./sinon/assert"); 22 | require("./sinon/sandbox"); 23 | require("./sinon/test"); 24 | require("./sinon/test_case"); 25 | require("./sinon/match"); 26 | require("./sinon/format"); 27 | require("./sinon/log_error"); 28 | } 29 | 30 | if (isAMD) { 31 | define(loadDependencies); 32 | } else if (isNode) { 33 | loadDependencies(require, module.exports, module); 34 | sinonModule = module.exports; 35 | } else { 36 | sinonModule = {}; 37 | } 38 | 39 | return sinonModule; 40 | }()); 41 | -------------------------------------------------------------------------------- /test/samples/use-own-output/from-rollup.js: -------------------------------------------------------------------------------- 1 | Object.defineProperty(exports, '__esModule', { value: true }); 2 | exports.x = 10 3 | -------------------------------------------------------------------------------- /test/samples/use-own-output/main.js: -------------------------------------------------------------------------------- 1 | import * as b from "./from-rollup"; 2 | window.b = b; 3 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | /* eslint-env mocha */ 2 | /* eslint-disable no-console */ 3 | 4 | const acorn = require('acorn'); 5 | const path = require('path'); 6 | const fs = require('fs'); 7 | const assert = require('assert'); 8 | const relative = require('require-relative'); 9 | const { SourceMapConsumer } = require('source-map'); 10 | const { getLocator } = require('locate-character'); 11 | const { rollup } = require('rollup'); 12 | const resolve = require('rollup-plugin-node-resolve'); 13 | 14 | function commonjs(options) { 15 | delete require.cache[require.resolve('..')]; 16 | return require('..')(options); 17 | } 18 | 19 | require('source-map-support').install(); 20 | 21 | process.chdir(__dirname); 22 | 23 | function execute(code, context = {}) { 24 | let fn; 25 | const contextKeys = Object.keys(context); 26 | const argNames = contextKeys.concat('module', 'exports', 'require', 'global', 'assert', code); 27 | 28 | try { 29 | fn = new Function(...argNames); 30 | } catch (err) { 31 | // syntax error 32 | console.log(code); 33 | throw err; 34 | } 35 | 36 | const module = { exports: {} }; 37 | const global = {}; 38 | 39 | const argValues = contextKeys 40 | .map(key => context[key]) 41 | .concat(module, module.exports, name => relative(name, 'test/x.js'), global, assert); 42 | 43 | fn(...argValues); 44 | 45 | return { 46 | code, 47 | exports: module.exports, 48 | global 49 | }; 50 | } 51 | 52 | const getOutputFromGenerated = generated => (generated.output ? generated.output[0] : generated); 53 | 54 | async function getCodeFromBundle(bundle, customOptions = {}) { 55 | const options = Object.assign({ format: 'cjs' }, customOptions); 56 | return getOutputFromGenerated(await bundle.generate(options)).code; 57 | } 58 | 59 | async function executeBundle(bundle, { context, exports } = {}) { 60 | const code = await getCodeFromBundle(bundle, exports ? { exports } : {}); 61 | return execute(code, context); 62 | } 63 | 64 | const transformContext = { 65 | parse: (input, options) => 66 | acorn.parse( 67 | input, 68 | Object.assign( 69 | { 70 | ecmaVersion: 9, 71 | sourceType: 'module' 72 | }, 73 | options 74 | ) 75 | ) 76 | }; 77 | 78 | describe('rollup-plugin-commonjs', () => { 79 | describe('form', () => { 80 | fs.readdirSync('form').forEach(dir => { 81 | let config; 82 | 83 | try { 84 | config = require(`./form/${dir}/_config.js`); 85 | } catch (err) { 86 | config = {}; 87 | } 88 | 89 | (config.solo ? it.only : it)(dir, () => { 90 | const { transform, options } = commonjs(config.options); 91 | options({ input: 'main.js' }); 92 | 93 | const input = fs.readFileSync(`form/${dir}/input.js`, 'utf-8'); 94 | 95 | let outputFile = `form/${dir}/output`; 96 | if (fs.existsSync(`${outputFile}.${process.platform}.js`)) { 97 | outputFile += `.${process.platform}.js`; 98 | } else { 99 | outputFile += '.js'; 100 | } 101 | 102 | const expected = fs.readFileSync(outputFile, 'utf-8').trim(); 103 | 104 | return transform.call(transformContext, input, 'input.js').then(transformed => { 105 | const actual = (transformed ? transformed.code : input).trim().replace(/\0/g, ''); 106 | assert.equal(actual, expected); 107 | }); 108 | }); 109 | }); 110 | }); 111 | 112 | describe('function', () => { 113 | fs.readdirSync('function').forEach(dir => { 114 | let config; 115 | 116 | try { 117 | config = require(`./function/${dir}/_config.js`); 118 | } catch (err) { 119 | config = {}; 120 | } 121 | 122 | (config.solo ? it.only : it)(dir, async () => { 123 | const options = Object.assign( 124 | { 125 | input: `function/${dir}/main.js` 126 | }, 127 | config.options || {}, 128 | { 129 | plugins: [ 130 | ...((config.options && config.options.plugins) || []), 131 | commonjs(config.pluginOptions) 132 | ] 133 | } 134 | ); 135 | 136 | let bundle; 137 | try { 138 | bundle = await rollup(options); 139 | } catch (err) { 140 | if (!config.err) throw err; 141 | if (config.err !== err.message) 142 | throw new Error('Expected error: "' + config.err + '" but got "' + err.message + '"'); 143 | return; 144 | } 145 | const code = await getCodeFromBundle(bundle); 146 | if (config.show || config.solo) { 147 | console.error(code); 148 | } 149 | 150 | const { exports, global } = execute(code, config.context); 151 | 152 | if (config.exports) config.exports(exports); 153 | if (config.global) config.global(global); 154 | }); 155 | }); 156 | }); 157 | 158 | describe('misc tests', () => { 159 | // most of these should be moved over to function... 160 | it('generates a sourcemap', async () => { 161 | const bundle = await rollup({ 162 | input: 'samples/sourcemap/main.js', 163 | plugins: [commonjs({ sourceMap: true })] 164 | }); 165 | 166 | const { code, map } = getOutputFromGenerated( 167 | await bundle.generate({ 168 | format: 'cjs', 169 | sourcemap: true, 170 | sourcemapFile: path.resolve('bundle.js') 171 | }) 172 | ); 173 | 174 | await SourceMapConsumer.with(map, null, async smc => { 175 | const locator = getLocator(code, { offsetLine: 1 }); 176 | 177 | let generatedLoc = locator('42'); 178 | let loc = smc.originalPositionFor(generatedLoc); // 42 179 | assert.equal(loc.source, 'samples/sourcemap/foo.js'); 180 | assert.equal(loc.line, 1); 181 | assert.equal(loc.column, 15); 182 | 183 | generatedLoc = locator('log'); 184 | loc = smc.originalPositionFor(generatedLoc); // log 185 | assert.equal(loc.source, 'samples/sourcemap/main.js'); 186 | assert.equal(loc.line, 2); 187 | assert.equal(loc.column, 8); 188 | }); 189 | }); 190 | 191 | it('supports an array of multiple entry points for experimentalCodeSplitting', async () => { 192 | const bundle = await rollup({ 193 | input: ['samples/multiple-entry-points/b.js', 'samples/multiple-entry-points/c.js'], 194 | experimentalCodeSplitting: true, 195 | plugins: [commonjs()] 196 | }); 197 | 198 | const { output } = await bundle.generate({ 199 | format: 'cjs', 200 | chunkFileNames: '[name].js' 201 | }); 202 | if (Array.isArray(output)) { 203 | assert.equal(output.length, 3); 204 | assert.ok(output.find(({ fileName }) => fileName === 'b.js')); 205 | assert.ok(output.find(({ fileName }) => fileName === 'c.js')); 206 | } else { 207 | assert.equal(Object.keys(output).length, 3); 208 | assert.equal('b.js' in output, true); 209 | assert.equal('c.js' in output, true); 210 | } 211 | }); 212 | 213 | it('supports an object of multiple entry points as object for experimentalCodeSplitting', async () => { 214 | const bundle = await rollup({ 215 | input: { 216 | b: require.resolve('./samples/multiple-entry-points/b.js'), 217 | c: require.resolve('./samples/multiple-entry-points/c.js') 218 | }, 219 | experimentalCodeSplitting: true, 220 | plugins: [resolve(), commonjs()] 221 | }); 222 | 223 | const { output } = await bundle.generate({ 224 | format: 'cjs', 225 | chunkFileNames: '[name].js' 226 | }); 227 | 228 | if (Array.isArray(output)) { 229 | assert.equal(output.length, 3); 230 | assert.ok(output.find(({ fileName }) => fileName === 'b.js')); 231 | assert.ok(output.find(({ fileName }) => fileName === 'c.js')); 232 | } else { 233 | assert.equal(Object.keys(output).length, 3); 234 | assert.equal('b.js' in output, true); 235 | assert.equal('c.js' in output, true); 236 | } 237 | }); 238 | 239 | it('handles references to `global`', async () => { 240 | const bundle = await rollup({ 241 | input: 'samples/global/main.js', 242 | plugins: [commonjs()] 243 | }); 244 | 245 | const code = await getCodeFromBundle(bundle); 246 | 247 | const mockWindow = {}; 248 | const mockGlobal = {}; 249 | const mockSelf = {}; 250 | 251 | const fn = new Function('module', 'window', 'global', 'self', code); 252 | 253 | fn({}, mockWindow, mockGlobal, mockSelf); 254 | assert.equal(mockWindow.foo, 'bar', code); 255 | assert.equal(mockGlobal.foo, undefined, code); 256 | assert.equal(mockSelf.foo, undefined, code); 257 | 258 | fn({}, undefined, mockGlobal, mockSelf); 259 | assert.equal(mockGlobal.foo, 'bar', code); 260 | assert.equal(mockSelf.foo, undefined, code); 261 | 262 | fn({}, undefined, undefined, mockSelf); 263 | assert.equal(mockSelf.foo, 'bar', code); 264 | }); 265 | 266 | it('handles multiple references to `global`', async () => { 267 | const bundle = await rollup({ 268 | input: 'samples/global-in-if-block/main.js', 269 | plugins: [commonjs()] 270 | }); 271 | 272 | const code = await getCodeFromBundle(bundle); 273 | const fn = new Function('module', 'exports', 'window', code); 274 | const module = { exports: {} }; 275 | const window = {}; 276 | 277 | fn(module, module.exports, window); 278 | assert.equal(window.count, 1); 279 | 280 | fn(module, module.exports, window); 281 | assert.equal(window.count, 2); 282 | }); 283 | 284 | it('handles transpiled CommonJS modules', async () => { 285 | const bundle = await rollup({ 286 | input: 'samples/corejs/literal-with-default.js', 287 | plugins: [commonjs()] 288 | }); 289 | 290 | const code = await getCodeFromBundle(bundle); 291 | const module = { exports: {} }; 292 | 293 | const fn = new Function('module', 'exports', code); 294 | fn(module, module.exports); 295 | 296 | assert.equal(module.exports, 'foobar', code); 297 | }); 298 | 299 | it('handles successive builds', async () => { 300 | const plugin = commonjs(); 301 | let bundle = await rollup({ 302 | input: 'samples/corejs/literal-with-default.js', 303 | plugins: [plugin] 304 | }); 305 | await bundle.generate({ 306 | format: 'cjs' 307 | }); 308 | 309 | bundle = await rollup({ 310 | input: 'samples/corejs/literal-with-default.js', 311 | plugins: [plugin] 312 | }); 313 | const code = await getCodeFromBundle(bundle); 314 | 315 | const module = { exports: {} }; 316 | 317 | const fn = new Function('module', 'exports', code); 318 | fn(module, module.exports); 319 | 320 | assert.equal(module.exports, 'foobar', code); 321 | }); 322 | 323 | it('allows named exports to be added explicitly via config', async () => { 324 | const bundle = await rollup({ 325 | input: 'samples/custom-named-exports/main.js', 326 | plugins: [ 327 | resolve({ main: true }), 328 | commonjs({ 329 | namedExports: { 330 | 'samples/custom-named-exports/secret-named-exporter.js': ['named'], 331 | external: ['message'] 332 | } 333 | }) 334 | ] 335 | }); 336 | 337 | await executeBundle(bundle); 338 | }); 339 | 340 | it('ignores false positives with namedExports (#36)', async () => { 341 | const bundle = await rollup({ 342 | input: 'samples/custom-named-exports-false-positive/main.js', 343 | plugins: [ 344 | resolve({ main: true }), 345 | commonjs({ 346 | namedExports: { 347 | irrelevant: ['lol'] 348 | } 349 | }) 350 | ] 351 | }); 352 | 353 | await executeBundle(bundle); 354 | }); 355 | 356 | it('converts a CommonJS module with custom file extension', async () => { 357 | const bundle = await rollup({ 358 | input: 'samples/extension/main.coffee', 359 | plugins: [commonjs({ extensions: ['.coffee'] })] 360 | }); 361 | 362 | assert.equal((await executeBundle(bundle)).exports, 42); 363 | }); 364 | 365 | it('identifies named exports from object literals', async () => { 366 | const bundle = await rollup({ 367 | input: 'samples/named-exports-from-object-literal/main.js', 368 | plugins: [commonjs()] 369 | }); 370 | 371 | const { code } = await bundle.generate({ 372 | format: 'cjs' 373 | }); 374 | 375 | const fn = new Function('module', 'assert', code); 376 | fn({}, assert); 377 | }); 378 | 379 | it('can ignore references to `global`', async () => { 380 | const bundle = await rollup({ 381 | input: 'samples/ignore-global/main.js', 382 | plugins: [commonjs({ ignoreGlobal: true })], 383 | onwarn: warning => { 384 | if (warning.code === 'THIS_IS_UNDEFINED') return; 385 | console.warn(warning.message); 386 | } 387 | }); 388 | 389 | const code = await getCodeFromBundle(bundle); 390 | const { exports, global } = await executeBundle(bundle); 391 | 392 | assert.equal(exports.immediate1, global.setImmediate, code); 393 | assert.equal(exports.immediate2, global.setImmediate, code); 394 | assert.equal(exports.immediate3, null, code); 395 | }); 396 | 397 | it('can handle parens around right have node while producing default export', async () => { 398 | const bundle = await rollup({ 399 | input: 'samples/paren-expression/index.js', 400 | plugins: [commonjs()] 401 | }); 402 | 403 | assert.equal((await executeBundle(bundle)).exports, 42); 404 | }); 405 | 406 | describe('typeof transforms', () => { 407 | it('correct-scoping', async () => { 408 | const bundle = await rollup({ 409 | input: 'samples/umd/correct-scoping.js', 410 | plugins: [commonjs()] 411 | }); 412 | 413 | assert.equal((await executeBundle(bundle)).exports, 'object'); 414 | }); 415 | 416 | it('protobuf', async () => { 417 | const bundle = await rollup({ 418 | input: 'samples/umd/protobuf.js', 419 | external: ['bytebuffer'], 420 | plugins: [commonjs()] 421 | }); 422 | 423 | assert.equal((await executeBundle(bundle)).exports, true); 424 | }); 425 | 426 | it('sinon', async () => { 427 | const bundle = await rollup({ 428 | input: 'samples/umd/sinon.js', 429 | plugins: [commonjs()] 430 | }); 431 | 432 | const { code } = getOutputFromGenerated(await bundle.generate({ format: 'es' })); 433 | 434 | assert.equal(code.indexOf('typeof require'), -1, code); 435 | // assert.notEqual( code.indexOf( 'typeof module' ), -1, code ); // #151 breaks this test 436 | // assert.notEqual( code.indexOf( 'typeof define' ), -1, code ); // #144 breaks this test 437 | }); 438 | }); 439 | 440 | it('deconflicts helper name', async () => { 441 | const bundle = await rollup({ 442 | input: 'samples/deconflict-helpers/main.js', 443 | plugins: [commonjs()] 444 | }); 445 | 446 | const { exports } = await executeBundle(bundle); 447 | assert.notEqual(exports, 'nope'); 448 | }); 449 | 450 | it('deconflicts reserved keywords', async () => { 451 | const bundle = await rollup({ 452 | input: 'samples/reserved-as-property/main.js', 453 | plugins: [commonjs()] 454 | }); 455 | 456 | const reservedProp = (await executeBundle(bundle, { exports: 'named' })).exports.delete; 457 | assert.equal(reservedProp, 'foo'); 458 | }); 459 | 460 | it('does not process the entry file when it has a leading "." (issue #63)', async () => { 461 | const bundle = await rollup({ 462 | input: './function/basic/main.js', 463 | plugins: [commonjs()] 464 | }); 465 | 466 | await executeBundle(bundle); 467 | }); 468 | 469 | it('does not reexport named contents', async () => { 470 | try { 471 | await rollup({ 472 | input: 'samples/reexport/main.js', 473 | plugins: [commonjs()] 474 | }); 475 | } catch (error) { 476 | assert.equal( 477 | error.message, 478 | `'named' is not exported by samples${path.sep}reexport${path.sep}reexport.js` 479 | ); 480 | } 481 | }); 482 | 483 | it('respects other plugins', async () => { 484 | const bundle = await rollup({ 485 | input: 'samples/other-transforms/main.js', 486 | plugins: [ 487 | { 488 | transform(code, id) { 489 | if (id[0] === '\0') return null; 490 | return code.replace('40', '41'); 491 | } 492 | }, 493 | commonjs() 494 | ] 495 | }); 496 | 497 | await executeBundle(bundle); 498 | }); 499 | 500 | it('rewrites top-level defines', async () => { 501 | const bundle = await rollup({ 502 | input: 'samples/define-is-undefined/main.js', 503 | plugins: [commonjs()] 504 | }); 505 | 506 | function define() { 507 | throw new Error('nope'); 508 | } 509 | 510 | define.amd = true; 511 | 512 | const { exports } = await executeBundle(bundle, { context: { define } }); 513 | assert.equal(exports, 42); 514 | }); 515 | 516 | it('respects options.external', async () => { 517 | const bundle = await rollup({ 518 | input: 'samples/external/main.js', 519 | plugins: [resolve(), commonjs()], 520 | external: ['baz'] 521 | }); 522 | 523 | const code = await getCodeFromBundle(bundle); 524 | assert.equal(code.indexOf('hello'), -1); 525 | 526 | const { exports } = await executeBundle(bundle); 527 | assert.equal(exports, 'HELLO'); 528 | }); 529 | 530 | it('prefers to set name using directory for index files', async () => { 531 | const bundle = await rollup({ 532 | input: 'samples/rename-index/main.js', 533 | plugins: [commonjs()] 534 | }); 535 | 536 | const code = await getCodeFromBundle(bundle); 537 | assert.equal(code.indexOf('var index'), -1); 538 | assert.notEqual(code.indexOf('var invalidVar'), -1); 539 | assert.notEqual(code.indexOf('var validVar'), -1); 540 | assert.notEqual(code.indexOf('var nonIndex'), -1); 541 | }); 542 | 543 | it('does not misassign default when consuming rollup output', async () => { 544 | // Issue #224 545 | const bundle = await rollup({ 546 | input: 'samples/use-own-output/main.js', 547 | plugins: [commonjs()] 548 | }); 549 | 550 | const window = {}; 551 | await executeBundle(bundle, { context: { window } }); 552 | assert.notEqual(window.b.default, undefined); 553 | }); 554 | 555 | it('does not warn even if the ES module not export "default"', async () => { 556 | const warns = []; 557 | await rollup({ 558 | input: 'samples/es-modules-without-default-export/main.js', 559 | plugins: [commonjs()], 560 | onwarn: warn => warns.push(warn) 561 | }); 562 | assert.equal(warns.length, 0); 563 | 564 | await rollup({ 565 | input: 'function/bare-import/bar.js', 566 | plugins: [commonjs()], 567 | onwarn: warn => warns.push(warn) 568 | }); 569 | assert.equal(warns.length, 0); 570 | 571 | await rollup({ 572 | input: 'function/bare-import-comment/main.js', 573 | plugins: [commonjs()], 574 | onwarn: warn => warns.push(warn) 575 | }); 576 | assert.equal(warns.length, 0); 577 | }); 578 | 579 | it('compiles with cache', async () => { 580 | // specific commonjs require() to ensure same instance is used 581 | const commonjs = require('..'); 582 | 583 | const bundle = await rollup({ 584 | input: 'function/index/main.js', 585 | plugins: [commonjs()] 586 | }); 587 | 588 | await rollup({ 589 | input: 'function/index/main.js', 590 | plugins: [commonjs()], 591 | cache: bundle 592 | }); 593 | }); 594 | 595 | it('creates an error with a code frame when parsing fails', async () => { 596 | try { 597 | await rollup({ 598 | input: 'samples/invalid-syntax/main.js', 599 | plugins: [commonjs()] 600 | }); 601 | } catch (error) { 602 | assert.equal(error.frame, '1: export const foo = 2,\n ^'); 603 | } 604 | }); 605 | 606 | it('ignores virtual modules', async () => { 607 | const bundle = await rollup({ 608 | input: 'samples/ignore-virtual-modules/main.js', 609 | plugins: [ 610 | commonjs(), 611 | { 612 | load(id) { 613 | if (id === '\0virtual') { 614 | return 'export default "Virtual export"'; 615 | } 616 | } 617 | } 618 | ] 619 | }); 620 | assert.equal((await executeBundle(bundle)).exports, 'Virtual export'); 621 | }); 622 | 623 | it('does not produce warnings when importing .mjs without default export', async () => { 624 | const bundle = await rollup({ 625 | input: 'main.mjs', 626 | onwarn(warning) { 627 | // The interop should not trigger a "default is not exported" warning 628 | throw new Error(`Unexpected warning: ${warning.message}`); 629 | }, 630 | plugins: [ 631 | commonjs(), 632 | { 633 | load(id) { 634 | if (id === 'main.mjs') { 635 | return 'import cjs from "cjs.js"; export default cjs;'; 636 | } 637 | if (id === 'cjs.js') { 638 | // CJS libraries expect to receive a CJS file here 639 | return 'module.exports = require("fromNodeModules");'; 640 | } 641 | if (id === 'fromNodeModules.mjs') { 642 | return 'export const result = "from esm";'; 643 | } 644 | }, 645 | resolveId(id) { 646 | // rollup-plugin-node-resolve usually prefers ESM versions 647 | if (id === 'fromNodeModules') { 648 | return 'fromNodeModules.mjs'; 649 | } 650 | return id; 651 | } 652 | } 653 | ] 654 | }); 655 | assert.deepEqual((await executeBundle(bundle)).exports, { result: 'from esm' }); 656 | }); 657 | 658 | it('produces optimized code when importing esm with a known default export', async () => { 659 | const bundle = await rollup({ 660 | input: 'main.js', 661 | plugins: [ 662 | commonjs(), 663 | { 664 | load(id) { 665 | if (id === 'main.js') { 666 | return 'module.exports = require("esm.js")'; 667 | } 668 | if (id === 'esm.js') { 669 | return 'export const ignored = "ignored"; export default "default"'; 670 | } 671 | }, 672 | resolveId(id) { 673 | return id; 674 | } 675 | } 676 | ] 677 | }); 678 | const code = await getCodeFromBundle(bundle); 679 | assert.equal( 680 | code, 681 | `'use strict'; 682 | 683 | var require$$0 = "default"; 684 | 685 | var main = require$$0; 686 | 687 | module.exports = main; 688 | ` 689 | ); 690 | }); 691 | 692 | it('produces optimized code when importing esm without a default export', async () => { 693 | const bundle = await rollup({ 694 | input: 'main.js', 695 | plugins: [ 696 | commonjs(), 697 | { 698 | load(id) { 699 | if (id === 'main.js') { 700 | return 'module.exports = require("esm.js")'; 701 | } 702 | if (id === 'esm.js') { 703 | return 'export const value = "value";'; 704 | } 705 | }, 706 | resolveId(id) { 707 | return id; 708 | } 709 | } 710 | ] 711 | }); 712 | const code = await getCodeFromBundle(bundle); 713 | assert.equal( 714 | code, 715 | `'use strict'; 716 | 717 | const value = "value"; 718 | 719 | var esm = /*#__PURE__*/Object.freeze({ 720 | value: value 721 | }); 722 | 723 | var main = esm; 724 | 725 | module.exports = main; 726 | ` 727 | ); 728 | }); 729 | }); 730 | }); 731 | --------------------------------------------------------------------------------