diff --git a/.circleci/config.yml b/.circleci/config.yml index bc4f2e17b15..944cb9bc2a3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,6 +31,16 @@ jobs: - run: name: Running tests command: npm run ci:test + node-v12-latest: + docker: + - image: rollupcabal/circleci-node-v12:latest + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: Running tests + command: npm run ci:test:only - store_artifacts: name: Storing browser build for REPL path: /home/circleci/project/dist/rollup.browser.js @@ -38,9 +48,9 @@ jobs: - run: name: Post REPL comment command: ./scripts/post-comment.js - node-v12-latest: + node-v13-latest: docker: - - image: rollupcabal/circleci-node-v12:latest + - image: lukastaegert/circleci-node-v13:latest steps: - checkout - restore_cache: @@ -70,3 +80,9 @@ workflows: filters: tags: only: /.*/ + - node-v13-latest: + requires: + - analysis + filters: + tags: + only: /.*/ diff --git a/.github/workflows/node-windows.yml b/.github/workflows/node-windows.yml index 62c8e5ca682..318d4d86d09 100644 --- a/.github/workflows/node-windows.yml +++ b/.github/workflows/node-windows.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node: ['12', '10'] + node: ['13', '12', '10'] name: ${{ matrix.node }} (Windows) steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d62b61cfa6..3023267d960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ * Do not strip `.js` extensions from AMD imports when the import is a user-supplied replacement for a non-resolvable dynamic import target (#3453) ### Pull Requests -* [#3449](https://github.com/rollup/rollup/pull/3449): Avoid the assumption of Buffer in browser envs (@lukastaegert) +* [#3449](https://github.com/rollup/rollup/pull/3449): Add hook to rewrite dynamic import expressions (@lukastaegert) * [#3452](https://github.com/rollup/rollup/pull/3452): Avoid the assumption of Buffer in browser envs (@JoviDeCroock) * [#3453](https://github.com/rollup/rollup/pull/3453): fix types since watch accepts single or array config (@lukeed) * [#3456](https://github.com/rollup/rollup/pull/3456): fix SystemJS url in tutorial (@guybedford) diff --git a/build-plugins/conditional-fsevents-import.js b/build-plugins/conditional-fsevents-import.js index ddab24bd9ca..38d08dcf99d 100644 --- a/build-plugins/conditional-fsevents-import.js +++ b/build-plugins/conditional-fsevents-import.js @@ -4,10 +4,12 @@ const FSEVENTS_REQUIRE = "require('fsevents')"; const REPLACEMENT = "require('../../../src/watch/fsevents-importer').getFsEvents()"; export default function conditionalFsEventsImport() { + let transformed = false; return { name: 'conditional-fs-events-import', transform(code, id) { if (id.endsWith('fsevents-handler.js')) { + transformed = true; const requireStatementPos = code.indexOf(FSEVENTS_REQUIRE); if (requireStatementPos < 0) { throw new Error(`Could not find expected fsevents import "${FSEVENTS_REQUIRE}"`); @@ -20,6 +22,11 @@ export default function conditionalFsEventsImport() { ); return { code: magicString.toString(), map: magicString.generateMap({ hires: true }) }; } + }, + buildEnd() { + if (!transformed) { + throw new Error('Could not find "fsevents-handler.js", was the file renamed?'); + } } }; } diff --git a/build-plugins/esm-dynamic-import.js b/build-plugins/esm-dynamic-import.js new file mode 100644 index 00000000000..5bc8b8ea444 --- /dev/null +++ b/build-plugins/esm-dynamic-import.js @@ -0,0 +1,19 @@ +export default function addBinShebangAndEsmImport() { + let importFound = false; + return { + name: 'esm-dynamic-import', + renderDynamicImport({ moduleId }) { + importFound = true; + if (moduleId.endsWith('loadConfigFile.ts')) { + return { left: 'import(', right: ')' }; + } + }, + generateBundle() { + if (!importFound) { + throw new Error( + 'Could not find dynamic import in "loadConfigFile.ts", was the file renamed?' + ); + } + } + }; +} diff --git a/build-plugins/fix-acorn-esm-import.js b/build-plugins/fix-acorn-esm-import.js deleted file mode 100644 index bdb5284ce98..00000000000 --- a/build-plugins/fix-acorn-esm-import.js +++ /dev/null @@ -1,23 +0,0 @@ -const expectedAcornImport = "import acorn, { Parser } from 'acorn';"; -const newAcornImport = "import * as acorn from 'acorn';\nimport { Parser } from 'acorn';"; - -// by default, rollup-plugin-commonjs will translate require statements as default imports -// which can cause issues for secondary tools that use the ESM version of acorn -export default function fixAcornEsmImport() { - let found = false; - - return { - name: 'fix-acorn-esm-import', - renderChunk(code) { - return code.replace(expectedAcornImport, () => { - found = true; - return newAcornImport; - }); - }, - writeBundle() { - if (!found) { - this.error('Could not find expected acorn import, please examine generated code.'); - } - } - }; -} diff --git a/cli/run/build.ts b/cli/run/build.ts index f90707954e0..da027f1e576 100644 --- a/cli/run/build.ts +++ b/cli/run/build.ts @@ -1,23 +1,22 @@ import color from 'colorette'; import ms from 'pretty-ms'; import * as rollup from '../../src/node-entry'; -import { InputOptions, OutputOptions, RollupBuild } from '../../src/rollup/types'; +import { MergedRollupOptions } from '../../src/rollup/types'; import relativeId from '../../src/utils/relativeId'; import { handleError, stderr } from '../logging'; import SOURCEMAPPING_URL from '../sourceMappingUrl'; import { BatchWarnings } from './batchWarnings'; import { printTimings } from './timings'; -export default function build( - inputOptions: InputOptions, - outputOptions: OutputOptions[], +export default async function build( + inputOptions: MergedRollupOptions, warnings: BatchWarnings, silent = false ): Promise { + const outputOptions = inputOptions.output; const useStdout = !outputOptions[0].file && !outputOptions[0].dir; - const start = Date.now(); - const files = useStdout ? ['stdout'] : outputOptions.map(t => relativeId(t.file || t.dir!)); + const files = useStdout ? ['stdout'] : outputOptions.map((t) => relativeId(t.file || t.dir!)); if (!silent) { let inputFiles: string | undefined; if (typeof inputOptions.input === 'string') { @@ -26,54 +25,53 @@ export default function build( inputFiles = inputOptions.input.join(', '); } else if (typeof inputOptions.input === 'object' && inputOptions.input !== null) { inputFiles = Object.keys(inputOptions.input) - .map(name => (inputOptions.input as Record)[name]) + .map((name) => (inputOptions.input as Record)[name]) .join(', '); } stderr(color.cyan(`\n${color.bold(inputFiles!)} → ${color.bold(files.join(', '))}...`)); } - return rollup - .rollup(inputOptions as any) - .then((bundle: RollupBuild) => { - if (useStdout) { - const output = outputOptions[0]; - if (output.sourcemap && output.sourcemap !== 'inline') { - handleError({ - code: 'MISSING_OUTPUT_OPTION', - message: 'You must specify a --file (-o) option when creating a file with a sourcemap' - }); - } - - return bundle.generate(output).then(({ output: outputs }) => { - for (const file of outputs) { - let source: string | Uint8Array; - if (file.type === 'asset') { - source = file.source; - } else { - source = file.code; - if (output.sourcemap === 'inline') { - source += `\n//# ${SOURCEMAPPING_URL}=${file.map!.toUrl()}\n`; - } - } - if (outputs.length > 1) - process.stdout.write('\n' + color.cyan(color.bold('//→ ' + file.fileName + ':')) + '\n'); - process.stdout.write(source); - } - return null; - }); - } + const bundle = await rollup.rollup(inputOptions as any); + if (useStdout) { + const output = outputOptions[0]; + if (output.sourcemap && output.sourcemap !== 'inline') { + handleError({ + code: 'ONLY_INLINE_SOURCEMAPS', + message: 'Only inline sourcemaps are supported when bundling to stdout.', + }); + } - return Promise.all(outputOptions.map(output => bundle.write(output))).then(() => bundle); - }) - .then((bundle: RollupBuild | null) => { - if (!silent) { - warnings.flush(); - stderr( - color.green(`created ${color.bold(files.join(', '))} in ${color.bold(ms(Date.now() - start))}`) - ); - if (bundle && bundle.getTimings) { - printTimings(bundle.getTimings()); + const { output: outputs } = await bundle.generate(output); + for (const file of outputs) { + let source: string | Uint8Array; + if (file.type === 'asset') { + source = file.source; + } else { + source = file.code; + if (output.sourcemap === 'inline') { + source += `\n//# ${SOURCEMAPPING_URL}=${file.map!.toUrl()}\n`; } } - }); + if (outputs.length > 1) + process.stdout.write(`\n${color.cyan(color.bold(`//→ ${file.fileName}:`))}\n`); + process.stdout.write(source); + } + if (!silent) { + warnings.flush(); + } + return; + } + + await Promise.all(outputOptions.map(bundle.write)); + if (!silent) { + warnings.flush(); + stderr( + color.green( + `created ${color.bold(files.join(', '))} in ${color.bold(ms(Date.now() - start))}` + ) + ); + if (bundle && bundle.getTimings) { + printTimings(bundle.getTimings()); + } + } } diff --git a/cli/run/commandPlugins.ts b/cli/run/commandPlugins.ts new file mode 100644 index 00000000000..55b9aa3ce37 --- /dev/null +++ b/cli/run/commandPlugins.ts @@ -0,0 +1,74 @@ +import * as path from 'path'; +import { InputOptions } from '../../src/rollup/types'; +import { stdinPlugin } from './stdin'; + +export function addCommandPluginsToInputOptions( + inputOptions: InputOptions, + command: any +) { + if (command.stdin !== false) { + inputOptions.plugins!.push(stdinPlugin()); + } + const commandPlugin = command.plugin; + if (commandPlugin) { + const plugins = Array.isArray(commandPlugin) ? commandPlugin : [commandPlugin]; + for (const plugin of plugins) { + if (/[={}]/.test(plugin)) { + // -p plugin=value + // -p "{transform(c,i){...}}" + loadAndRegisterPlugin(inputOptions, plugin); + } else { + // split out plugins joined by commas + // -p node-resolve,commonjs,buble + plugin.split(',').forEach((plugin: string) => loadAndRegisterPlugin(inputOptions, plugin)); + } + } + } +} + +function loadAndRegisterPlugin(inputOptions: InputOptions, pluginText: string) { + let plugin: any = null; + let pluginArg: any = undefined; + if (pluginText[0] === '{') { + // -p "{transform(c,i){...}}" + plugin = new Function('return ' + pluginText); + } else { + const match = pluginText.match(/^([@.\/\\\w|^{}|-]+)(=(.*))?$/); + if (match) { + // -p plugin + // -p plugin=arg + pluginText = match[1]; + pluginArg = new Function('return ' + match[3])(); + } else { + throw new Error(`Invalid --plugin argument format: ${JSON.stringify(pluginText)}`); + } + if (!/^\.|^rollup-plugin-|[@\/\\]/.test(pluginText)) { + // Try using plugin prefix variations first if applicable. + // Prefix order is significant - left has higher precedence. + for (const prefix of ['@rollup/plugin-', 'rollup-plugin-']) { + try { + plugin = require(prefix + pluginText); + break; + } catch (ex) { + // if this does not work, we try requiring the actual name below + } + } + } + if (!plugin) { + try { + if (pluginText[0] == '.') pluginText = path.resolve(pluginText); + plugin = require(pluginText); + } catch (ex) { + throw new Error(`Cannot load plugin "${pluginText}"`); + } + } + } + if (typeof plugin === 'object' && pluginText in plugin) { + // some plugins do not use `export default` for their entry point. + // attempt to use the plugin name as the named import name. + plugin = plugin[pluginText]; + } + inputOptions.plugins!.push( + typeof plugin === 'function' ? plugin.call(plugin, pluginArg) : plugin + ); +} diff --git a/cli/run/getConfigPath.ts b/cli/run/getConfigPath.ts new file mode 100644 index 00000000000..8fb6ad7f6ad --- /dev/null +++ b/cli/run/getConfigPath.ts @@ -0,0 +1,41 @@ +import { readdirSync, realpathSync } from 'fs'; +import * as path from 'path'; +import relative from 'require-relative'; +import { handleError } from '../logging'; + +const DEFAULT_CONFIG_BASE = 'rollup.config'; + +export function getConfigPath(commandConfig: any): string { + const cwd = process.cwd(); + if (commandConfig === true) { + return path.join(cwd, findConfigFileNameInCwd()); + } + if (commandConfig.slice(0, 5) === 'node:') { + const pkgName = commandConfig.slice(5); + try { + return relative.resolve(`rollup-config-${pkgName}`, cwd); + } catch (err) { + try { + return relative.resolve(pkgName, cwd); + } catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + handleError({ + code: 'MISSING_EXTERNAL_CONFIG', + message: `Could not resolve config file "${commandConfig}"` + }); + } + throw err; + } + } + } + return realpathSync(commandConfig); +} + +function findConfigFileNameInCwd(): string { + const filesInWorkingDir = new Set(readdirSync(process.cwd())); + for (const extension of ['mjs', 'cjs']) { + const fileName = `${DEFAULT_CONFIG_BASE}.${extension}`; + if (filesInWorkingDir.has(fileName)) return fileName; + } + return `${DEFAULT_CONFIG_BASE}.js`; +} diff --git a/cli/run/index.ts b/cli/run/index.ts index a7826f69409..8d5c5ff1c72 100644 --- a/cli/run/index.ts +++ b/cli/run/index.ts @@ -1,24 +1,20 @@ -import { realpathSync } from 'fs'; -import * as path from 'path'; -import relative from 'require-relative'; -import { InputOptions } from '../../src/rollup/types'; -import { mergeOptions } from '../../src/utils/mergeOptions'; -import { GenericConfigObject } from '../../src/utils/parseOptions'; +import { MergedRollupOptions } from '../../src/rollup/types'; import { getAliasName } from '../../src/utils/relativeId'; import { handleError } from '../logging'; -import batchWarnings from './batchWarnings'; +import { BatchWarnings } from './batchWarnings'; import build from './build'; -import loadConfigFile from './loadConfigFile'; -import { stdinName, stdinPlugin } from './stdin'; +import { getConfigPath } from './getConfigPath'; +import loadAndParseConfigFile from './loadConfigFile'; +import loadConfigFromCommand from './loadConfigFromCommand'; import watch from './watch'; -export default function runRollup(command: any) { +export default async function runRollup(command: any) { let inputSource; if (command._.length > 0) { if (command.input) { handleError({ code: 'DUPLICATE_IMPORT_OPTIONS', - message: 'Either use --input, or pass input path as argument' + message: 'Either use --input, or pass input path as argument', }); } inputSource = command._; @@ -60,129 +56,32 @@ export default function runRollup(command: any) { }); } - let configFile = command.config === true ? 'rollup.config.js' : command.config; - - if (configFile) { - if (configFile.slice(0, 5) === 'node:') { - const pkgName = configFile.slice(5); - try { - configFile = relative.resolve(`rollup-config-${pkgName}`, process.cwd()); - } catch (err) { - try { - configFile = relative.resolve(pkgName, process.cwd()); - } catch (err) { - if (err.code === 'MODULE_NOT_FOUND') { - handleError({ - code: 'MISSING_EXTERNAL_CONFIG', - message: `Could not resolve config file ${configFile}` - }); - } - - throw err; - } - } - } else { - // find real path of config so it matches what Node provides to callbacks in require.extensions - configFile = realpathSync(configFile); - } - - if (command.watch) process.env.ROLLUP_WATCH = 'true'; - - return loadConfigFile(configFile, command) - .then(configs => execute(configFile, configs, command)) - .catch(handleError); - } else { - if (!command.input && (command.stdin || !process.stdin.isTTY)) { - command.input = stdinName; - } - return execute(configFile, [{ input: [] }], command); - } -} - -async function execute( - configFile: string, - configs: GenericConfigObject[], - command: any -): Promise { if (command.watch) { - watch(configFile, configs, command, command.silent); + watch(command); } else { - for (const config of configs) { - const warnings = batchWarnings(); + try { + const { options, warnings } = await getConfigs(command); try { - const { inputOptions, outputOptions } = mergeOptions(config, command, - warnings.add); - if (command.stdin !== false) { - inputOptions.plugins!.push(stdinPlugin()); + for (const inputOptions of options) { + await build(inputOptions, warnings, command.silent); } - if (command.plugin) { - const plugins = Array.isArray(command.plugin) ? command.plugin : [command.plugin]; - for (const plugin of plugins) { - if (/[={}]/.test(plugin)) { - // -p plugin=value - // -p "{transform(c,i){...}}" - loadAndRegisterPlugin(inputOptions, plugin); - } else { - // split out plugins joined by commas - // -p node-resolve,commonjs,buble - plugin - .split(',') - .forEach((plugin: string) => loadAndRegisterPlugin(inputOptions, plugin)); - } - } - } - await build(inputOptions, outputOptions, warnings, command.silent); } catch (err) { warnings.flush(); handleError(err); } + } catch (err) { + handleError(err); } } } -function loadAndRegisterPlugin(inputOptions: InputOptions, pluginText: string) { - let plugin: any = null; - let pluginArg: any = undefined; - if (pluginText[0] === '{') { - // -p "{transform(c,i){...}}" - plugin = new Function('return ' + pluginText); - } else { - const match = pluginText.match(/^([@.\/\\\w|^{}|-]+)(=(.*))?$/); - if (match) { - // -p plugin - // -p plugin=arg - pluginText = match[1]; - pluginArg = new Function('return ' + match[3])(); - } else { - throw new Error(`Invalid --plugin argument format: ${JSON.stringify(pluginText)}`); - } - if (!/^\.|^rollup-plugin-|[@\/\\]/.test(pluginText)) { - // Try using plugin prefix variations first if applicable. - // Prefix order is significant - left has higher precedence. - for (const prefix of ['@rollup/plugin-', 'rollup-plugin-']) { - try { - plugin = require(prefix + pluginText); - break; - } catch (ex) { - // if this does not work, we try requiring the actual name below - } - } - } - if (!plugin) { - try { - if (pluginText[0] == '.') pluginText = path.resolve(pluginText); - plugin = require(pluginText); - } catch (ex) { - throw new Error(`Cannot load plugin "${pluginText}"`); - } - } - } - if (typeof plugin === 'object' && pluginText in plugin) { - // some plugins do not use `export default` for their entry point. - // attempt to use the plugin name as the named import name. - plugin = plugin[pluginText]; +async function getConfigs( + command: any +): Promise<{ options: MergedRollupOptions[]; warnings: BatchWarnings }> { + if (command.config) { + const configFile = getConfigPath(command.config); + const { options, warnings } = await loadAndParseConfigFile(configFile, command); + return { options, warnings }; } - inputOptions.plugins!.push( - typeof plugin === 'function' ? plugin.call(plugin, pluginArg) : plugin - ); + return loadConfigFromCommand(command); } diff --git a/cli/run/loadConfigFile.ts b/cli/run/loadConfigFile.ts index 142121e8263..649a302bafb 100644 --- a/cli/run/loadConfigFile.ts +++ b/cli/run/loadConfigFile.ts @@ -1,76 +1,124 @@ import color from 'colorette'; import * as path from 'path'; +import { pathToFileURL } from 'url'; import * as rollup from '../../src/node-entry'; -import { RollupBuild, RollupOutput } from '../../src/rollup/types'; +import { MergedRollupOptions } from '../../src/rollup/types'; +import { error } from '../../src/utils/error'; +import { mergeOptions } from '../../src/utils/mergeOptions'; import { GenericConfigObject } from '../../src/utils/parseOptions'; import relativeId from '../../src/utils/relativeId'; -import { handleError, stderr } from '../logging'; -import batchWarnings from './batchWarnings'; +import { stderr } from '../logging'; +import batchWarnings, { BatchWarnings } from './batchWarnings'; +import { addCommandPluginsToInputOptions } from './commandPlugins'; + +function supportsNativeESM() { + return Number(/^v(\d+)/.exec(process.version)![1]) >= 13; +} interface NodeModuleWithCompile extends NodeModule { _compile(code: string, filename: string): any; } -export default function loadConfigFile( - configFile: string, +export default async function loadAndParseConfigFile( + fileName: string, commandOptions: any = {} -): Promise { - const silent = commandOptions.silent || false; +): Promise<{options: MergedRollupOptions[], warnings: BatchWarnings}> { + const configs = await loadConfigFile(fileName, commandOptions); const warnings = batchWarnings(); + try { + const normalizedConfigs = configs.map((config) => { + const options = mergeOptions(config, commandOptions, warnings.add); + addCommandPluginsToInputOptions(options, commandOptions); + return options; + }); + return {options: normalizedConfigs, warnings}; + } catch (err) { + warnings.flush(); + throw err; + } +} - return rollup - .rollup({ - external: (id: string) => - (id[0] !== '.' && !path.isAbsolute(id)) || id.slice(-5, id.length) === '.json', - input: configFile, - onwarn: warnings.add, - treeshake: false - }) - .then((bundle: RollupBuild) => { - if (!silent && warnings.count > 0) { - stderr(color.bold(`loaded ${relativeId(configFile)} with warnings`)); - warnings.flush(); - } - - return bundle.generate({ - exports: 'named', - format: 'cjs' - }); - }) - .then(({ output: [{ code }] }: RollupOutput) => { - // temporarily override require - const extension = path.extname(configFile); - const defaultLoader = require.extensions[extension]; - require.extensions[extension] = (module: NodeModule, filename: string) => { - if (filename === configFile) { - (module as NodeModuleWithCompile)._compile(code, filename); - } else { - defaultLoader(module, filename); - } - }; +async function loadConfigFile( + fileName: string, + commandOptions: any +): Promise { + const extension = path.extname(fileName); + const configFileExport = await (extension === '.mjs' && supportsNativeESM() + ? (await import(pathToFileURL(fileName).href)).default + : extension === '.cjs' + ? getDefaultFromCjs(require(fileName)) + : getDefaultFromTranspiledConfigFile(fileName, commandOptions.silent)); + return getConfigList(configFileExport, commandOptions); +} - delete require.cache[configFile]; +function getDefaultFromCjs(namespace: GenericConfigObject) { + return namespace.__esModule ? namespace.default : namespace; +} - return Promise.resolve(require(configFile)) - .then(configFileContent => { - if (configFileContent.default) configFileContent = configFileContent.default; - if (typeof configFileContent === 'function') { - return configFileContent(commandOptions); - } - return configFileContent; - }) - .then(configs => { - if (Object.keys(configs).length === 0) { - handleError({ - code: 'MISSING_CONFIG', - message: 'Config file must export an options object, or an array of options objects', - url: 'https://rollupjs.org/guide/en/#configuration-files' - }); - } +async function getDefaultFromTranspiledConfigFile( + fileName: string, + silent: boolean +): Promise { + const warnings = batchWarnings(); + const bundle = await rollup.rollup({ + external: (id: string) => + (id[0] !== '.' && !path.isAbsolute(id)) || id.slice(-5, id.length) === '.json', + input: fileName, + onwarn: warnings.add, + treeshake: false, + }); + if (!silent && warnings.count > 0) { + stderr(color.bold(`loaded ${relativeId(fileName)} with warnings`)); + warnings.flush(); + } + const { + output: [{ code }], + } = await bundle.generate({ + exports: 'named', + format: 'cjs', + }); + return loadConfigFromBundledFile(fileName, code); +} - require.extensions[extension] = defaultLoader; +async function loadConfigFromBundledFile(fileName: string, bundledCode: string) { + const extension = path.extname(fileName); + const defaultLoader = require.extensions[extension]; + require.extensions[extension] = (module: NodeModule, filename: string) => { + if (filename === fileName) { + (module as NodeModuleWithCompile)._compile(bundledCode, filename); + } else { + defaultLoader(module, filename); + } + }; + delete require.cache[fileName]; + try { + const config = getDefaultFromCjs(require(fileName)); + require.extensions[extension] = defaultLoader; + return config; + } catch (err) { + if (err.code === 'ERR_REQUIRE_ESM') { + return error({ + code: 'TRANSPILED_ESM_CONFIG', + message: `While loading the Rollup configuration from "${relativeId( + fileName + )}", Node tried to require an ES module from a CommonJS file, which is not supported. A common cause is if there is a package.json file with "type": "module" in the same folder. You can try to fix this by changing the extension of your configuration file to ".cjs" or ".mjs" depending on the content, which will prevent Rollup from trying to preprocess the file but rather hand it to Node directly.`, + url: 'https://rollupjs.org/guide/en/#using-untranspiled-config-files', + }); + } + throw err; + } +} - return Array.isArray(configs) ? configs : [configs]; - }); +function getConfigList(configFileExport: any, commandOptions: any) { + const defaultExport = configFileExport.default || configFileExport; + const config = + typeof defaultExport === 'function' ? defaultExport(commandOptions) : defaultExport; + if (Object.keys(config).length === 0) { + return error({ + code: 'MISSING_CONFIG', + message: 'Config file must export an options object, or an array of options objects', + url: 'https://rollupjs.org/guide/en/#configuration-files', }); + } + return Array.isArray(config) ? config : [config]; } diff --git a/cli/run/loadConfigFromCommand.ts b/cli/run/loadConfigFromCommand.ts new file mode 100644 index 00000000000..9320d0f0aa7 --- /dev/null +++ b/cli/run/loadConfigFromCommand.ts @@ -0,0 +1,17 @@ +import { MergedRollupOptions } from '../../src/rollup/types'; +import { mergeOptions } from '../../src/utils/mergeOptions'; +import batchWarnings, { BatchWarnings } from './batchWarnings'; +import { addCommandPluginsToInputOptions } from './commandPlugins'; +import { stdinName } from './stdin'; + +export default function loadConfigFromCommand( + command: any +): { options: MergedRollupOptions[]; warnings: BatchWarnings } { + const warnings = batchWarnings(); + if (!command.input && (command.stdin || !process.stdin.isTTY)) { + command.input = stdinName; + } + const options = mergeOptions({ input: [] }, command, warnings.add); + addCommandPluginsToInputOptions(options, command); + return { options: [options], warnings }; +} diff --git a/cli/run/resetScreen.ts b/cli/run/resetScreen.ts index fc946fce8e4..c057a84e9e6 100644 --- a/cli/run/resetScreen.ts +++ b/cli/run/resetScreen.ts @@ -1,8 +1,15 @@ +import { MergedRollupOptions } from '../../src/rollup/types'; import { stderr } from '../logging'; const CLEAR_SCREEN = '\u001Bc'; -export function getResetScreen(clearScreen: boolean) { +export function getResetScreen(configs: MergedRollupOptions[], allowClearScreen: boolean) { + let clearScreen = allowClearScreen; + for (const config of configs) { + if (config.watch && config.watch.clearScreen === false) { + clearScreen = false; + } + } if (clearScreen) { return (heading: string) => stderr(CLEAR_SCREEN + heading); } diff --git a/cli/run/watch.ts b/cli/run/watch.ts index 361cfc61a59..8562f218a81 100644 --- a/cli/run/watch.ts +++ b/cli/run/watch.ts @@ -4,47 +4,88 @@ import fs from 'fs'; import ms from 'pretty-ms'; import onExit from 'signal-exit'; import * as rollup from '../../src/node-entry'; -import { RollupWatcher, RollupWatchOptions } from '../../src/rollup/types'; -import { mergeOptions } from '../../src/utils/mergeOptions'; -import { GenericConfigObject } from '../../src/utils/parseOptions'; +import { MergedRollupOptions, RollupWatcher } from '../../src/rollup/types'; import relativeId from '../../src/utils/relativeId'; import { handleError, stderr } from '../logging'; -import batchWarnings from './batchWarnings'; -import loadConfigFile from './loadConfigFile'; +import { BatchWarnings } from './batchWarnings'; +import { getConfigPath } from './getConfigPath'; +import loadAndParseConfigFile from './loadConfigFile'; +import loadConfigFromCommand from './loadConfigFromCommand'; import { getResetScreen } from './resetScreen'; import { printTimings } from './timings'; -export default function watch( - configFile: string, - configs: GenericConfigObject[], - command: any, - silent = false -) { - const isTTY = Boolean(process.stderr.isTTY); - const warnings = batchWarnings(); - const initialConfigs = processConfigs(configs); - const clearScreen = initialConfigs.every(config => config.watch!.clearScreen !== false); - - const resetScreen = getResetScreen(isTTY && clearScreen); +export default async function watch(command: any) { + process.env.ROLLUP_WATCH = 'true'; + const isTTY = process.stderr.isTTY; + const silent = command.silent; + let configs: MergedRollupOptions[]; + let warnings: BatchWarnings; let watcher: RollupWatcher; - let configWatcher: RollupWatcher; - - function processConfigs(configs: GenericConfigObject[]): RollupWatchOptions[] { - return configs.map(options => { - const { inputOptions, outputOptions } = mergeOptions(options, command, warnings.add); - const result: RollupWatchOptions = { - ...inputOptions, - output: outputOptions - }; - if (!result.watch) result.watch = {}; - return result; + let configWatcher: fs.FSWatcher; + const configFile = command.config ? getConfigPath(command.config) : null; + + onExit(close); + process.on('uncaughtException', close); + // only listen to stdin if it is a pipe + if (!process.stdin.isTTY) { + process.stdin.on('end', close); + } + + if (configFile) { + let reloadingConfig = false; + let aborted = false; + let configFileData: string | null = null; + + configWatcher = fs.watch(configFile, (event: string) => { + if (event === 'change') reloadConfigFile(); }); + + await reloadConfigFile(); + + async function reloadConfigFile() { + try { + const newConfigFileData = fs.readFileSync(configFile!, 'utf-8'); + if (newConfigFileData === configFileData) { + return; + } + if (reloadingConfig) { + aborted = true; + return; + } + if (configFileData) { + stderr(`\nReloading updated config...`); + } + configFileData = newConfigFileData; + reloadingConfig = true; + ({ options: configs, warnings } = await loadAndParseConfigFile(configFile!, command)); + reloadingConfig = false; + if (aborted) { + aborted = false; + reloadConfigFile(); + } else { + if (watcher) { + watcher.close(); + } + start(configs); + } + } catch (err) { + configs = []; + reloadingConfig = false; + handleError(err, true); + } + } + } else { + ({ options: configs, warnings } = await loadConfigFromCommand(command)); + start(configs); } - function start(configs: RollupWatchOptions[]) { + // tslint:disable-next-line:no-unnecessary-type-assertion + const resetScreen = getResetScreen(configs!, isTTY); + + function start(configs: MergedRollupOptions[]) { watcher = rollup.watch(configs as any); - watcher.on('event', event => { + watcher.on('event', (event) => { switch (event.code) { case 'ERROR': warnings.flush(); @@ -64,12 +105,14 @@ export default function watch( input = Array.isArray(input) ? input.join(', ') : Object.keys(input as Record) - .map(key => (input as Record)[key]) + .map((key) => (input as Record)[key]) .join(', '); } stderr( color.cyan( - `bundles ${color.bold(input)} → ${color.bold(event.output.map(relativeId).join(', '))}...` + `bundles ${color.bold(input)} → ${color.bold( + event.output.map(relativeId).join(', ') + )}...` ) ); } @@ -98,74 +141,17 @@ export default function watch( }); } - // catch ctrl+c, kill, and uncaught errors - const removeOnExit = onExit(close); - process.on('uncaughtException', close); - - // only listen to stdin if it is a pipe - if (!process.stdin.isTTY) { - process.stdin.on('end', close); // in case we ever support stdin! - } - function close(err: Error) { - removeOnExit(); process.removeListener('uncaughtException', close); // removing a non-existent listener is a no-op process.stdin.removeListener('end', close); if (watcher) watcher.close(); - if (configWatcher) configWatcher.close(); if (err) { - console.error(err); + stderr(err); process.exit(1); } } - - try { - start(initialConfigs); - } catch (err) { - close(err); - return; - } - - if (configFile && !configFile.startsWith('node:')) { - let restarting = false; - let aborted = false; - let configFileData = fs.readFileSync(configFile, 'utf-8'); - - const restart = () => { - const newConfigFileData = fs.readFileSync(configFile, 'utf-8'); - if (newConfigFileData === configFileData) return; - configFileData = newConfigFileData; - - if (restarting) { - aborted = true; - return; - } - - restarting = true; - - loadConfigFile(configFile, command) - .then(() => { - restarting = false; - - if (aborted) { - aborted = false; - restart(); - } else { - watcher.close(); - start(initialConfigs); - } - }) - .catch((err: Error) => { - handleError(err, true); - }); - }; - - configWatcher = fs.watch(configFile, (event: string) => { - if (event === 'change') restart(); - }) as RollupWatcher; - } } diff --git a/docs/01-command-line-reference.md b/docs/01-command-line-reference.md index c113a7112d8..8847df40d79 100755 --- a/docs/01-command-line-reference.md +++ b/docs/01-command-line-reference.md @@ -6,14 +6,10 @@ Rollup should typically be used from the command line. You can provide an optio ### Configuration Files -Rollup configuration files are optional, but they are powerful and convenient and thus **recommended**. - -A config file is an ES module that exports a default object with the desired options. Typically, it is called `rollup.config.js` and sits in the root directory of your project. - -Also you can use CJS modules syntax for the config file. +Rollup configuration files are optional, but they are powerful and convenient and thus **recommended**. A config file is an ES module that exports a default object with the desired options: ```javascript -module.exports = { +export default { input: 'src/main.js', output: { file: 'bundle.js', @@ -22,9 +18,11 @@ module.exports = { }; ``` -It may be pertinent if you want to use the config file not only from the command line, but also from your custom scripts programmatically. +Typically, it is called `rollup.config.js` and sits in the root directory of your project. Behind the scenes, Rollup will transpile and bundle this file and its relative dependencies to CommonJS before requiring it, which has the advantage that you can share code with an ES module code base while having full interoperability with the Node ecosystem. -Consult the [big list of options](guide/en/#big-list-of-options) for details on each option you can include in your config file. +If you want to write your config as a CommonJS module using `require` and `module.exports`, you should change the file extension to `.cjs`, which will prevent Rollup from trying to transpile the file. Furthermore if you are on Node 13+, changing the file extension to `.mjs` will also prevent Rollup from transpiling it but import the file as an ES module instead. See [using untranspiled config files](guide/en/#using-untranspiled-config-files) for more details and why you might want to do this. + +Config files support the options listed below. Consult the [big list of options](guide/en/#big-list-of-options) for details on each option: ```javascript // rollup.config.js @@ -150,22 +148,16 @@ export default Promise.all([ ]) ``` -You *must* use a configuration file in order to do any of the following: - -- bundle one project into multiple output files -- use Rollup plugins, such as [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve) and [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/master/packages/commonjs) which let you load CommonJS modules from the Node.js ecosystem - -To use Rollup with a configuration file, pass the `--config` or `-c` flags. +To use Rollup with a configuration file, pass the `--config` or `-c` flags: ``` -# use Rollup with a rollup.config.js file -rollup --config - -# alternatively, specify a custom config file location +# pass a custom config file location to Rollup rollup --config my.config.js -# .js and .mjs are supported -rollup --config my.config.mjs +# if you do not pass a file name, Rollup will try to load +# configuration files in the following order: +# rollup.config.mjs -> rollup.config.cjs -> rollup.config.js +rollup --config ``` You can also export a function that returns any of the above configuration formats. This function will be passed the current command line arguments so that you can dynamically adapt your configuration to respect e.g. [`--silent`](guide/en/#--silent). You can even define your own command line options if you prefix them with `config`: @@ -201,6 +193,64 @@ export default commandLineArgs => { } ``` +### Differences to the JavaScript API + +By default, Rollup will try to bundle and transpile your configuration file to CommonJS before requiring it. While this process is very fast and allows for better interoperability with +If you want to switch from config files to using the [JavaScript API](guide/en/#javascript-api) at some point, there are some important differences to be aware of: + +- When using the JavaScript API, the configuration passed to `rollup.rollup` must be an object and cannot be wrapped in a Promise or a function. +- You can no longer use an array of configurations. Instead, you should run `rollup.rollup` once for each set of `inputOptions`. +- The `output` option will be ignored. Instead, you should run `bundle.generate(outputOptions)` or `bundle.write(outputOptions)` once for each set of `outputOptions`. + +### Loading a configuration from a Node package + +For interoperability, Rollup also supports loading configuration files from packages installed into `node_modules`: + +``` +# this will first try to load the package "rollup-config-my-special-config"; +# if that fails, it will then try to load "my-special-config" +rollup --config node:my-special-config +``` + +### Using untranspiled config files + +By default, Rollup will expect config files to be ES modules and bundle and transpile them and their relative imports to CommonJS before requiring them. This is a fast process and has the advantage that it is easy to share code between your configuration and an ES module code base. If you want to write your configuration as CommonJS instead, you can skip this process by using the `.cjs` extension: + +```javascript +// rollup.config.cjs +module.exports = { + input: 'src/main.js', + output: { + file: 'bundle.js', + format: 'cjs' + } +}; +``` + +It may be pertinent if you want to use the config file not only from the command line, but also from your custom scripts programmatically. + +On the other hand if you are using at least Node 13 and have `"type": "module"` in your `package.json` file, Rollup's transpilation will prevent your configuration file from importing packages that are themselves ES modules. In that case, changing your file extension to `.mjs` will instruct Rollup to import your configuration directly as an ES module. However note that this is specific to Node 13+; on older Node versions, `.mjs` is treated just like `.js`. + +There are some potential gotchas when using `.mjs` on Node 13+: + +- You will only get a default export from CommonJS plugins +- You may not be able to import JSON files such as your `package.json file`. There are two ways to go around this: + - run Rollup CLI via + + ``` + node --experimental-json-modules ./node_modules/.bin/rollup --config + ``` + + - create a CommonJS wrapper that requires the JSON file: + + ```js + // load-package.cjs + module.exports = require('./package.json'); + + // rollup.config.mjs + import pkg from './load-package.cjs'; + ... + ``` ### Command line flags diff --git a/docs/02-javascript-api.md b/docs/02-javascript-api.md index 0ed7b888b29..b6b1a6fe156 100755 --- a/docs/02-javascript-api.md +++ b/docs/02-javascript-api.md @@ -6,7 +6,9 @@ Rollup provides a JavaScript API which is usable from Node.js. You will rarely n ### rollup.rollup -The `rollup.rollup` function returns a Promise that resolves to a `bundle` object with various properties and methods shown here: +The `rollup.rollup` function receives an input options object as parameter and returns a Promise that resolves to a `bundle` object with various properties and methods as shown below. During this step, Rollup will build the module graph and perform tree-shaking, but will not generate any output. + +On a `bundle` object, you can call `bundle.generate` multiple times with different output options objects to generate different bundles in-memory. If you directly want to write them to disk, use `bundle.write` instead. ```javascript const rollup = require('rollup'); @@ -21,7 +23,8 @@ async function build() { console.log(bundle.watchFiles); // an array of file names this bundle depends on - // generate code + // generate output specific code in-memory + // you can call this function multiple times on the same bundle object const { output } = await bundle.generate(outputOptions); for (const chunkOrAsset of output) { @@ -189,3 +192,36 @@ const watchOptions = { ``` See above for details on `inputOptions` and `outputOptions`, or consult the [big list of options](guide/en/#big-list-of-options) for info on `chokidar`, `include` and `exclude`. + +#### Programmatically loading a config file + +In order to aid in generating such a config, rollup exposes the helper it uses to load config files in its command line interface via a separate entry-point. This helper receives a resolved `fileName` and optionally an object containing command line parameters: + +```js +const loadConfigFile = require('rollup/dist/loadConfigFile'); +const path = require('path'); +const rollup = require('rollup'); + +// load the config file next to the current script; +// the provided config object has the same effect as passing "--format es" +// on the command line and will override the format of all outputs +loadConfigFile(path.resolve(__dirname, 'rollup.config.js'), { format: 'es' }) + .then(async ({options, warnings}) => { + // "warnings" wraps the default `onwarn` handler passed by the CLI. + // This prints all warnings up to this point: + console.log(`We currently have ${warnings.count} warnings`); + + // This prints all deferred warnings + warnings.flush(); + + // options is an "inputOptions" object with an additional "output" + // property that contains an array of "outputOptions". + // The following will generate all outputs and write them to disk the same + // way the CLI does it: + const bundle = await rollup.rollup(options); + await Promise.all(options.output.map(bundle.write)); + + // You can also pass this directly to "rollup.watch" + rollup.watch(options); + }) +``` diff --git a/package-lock.json b/package-lock.json index 3bd784ba6e1..20242b7d27a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,22 +14,23 @@ } }, "@babel/core": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.7.tgz", - "integrity": "sha512-rBlqF3Yko9cynC5CCFy6+K/w2N+Sq/ff2BPy+Krp7rHlABIr5epbA7OxVeKoMHB39LZOp1UY5SuLjy6uWi35yA==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.7", - "@babel/helpers": "^7.8.4", - "@babel/parser": "^7.8.7", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", "@babel/template": "^7.8.6", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.7", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", - "json5": "^2.1.0", + "json5": "^2.1.2", "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", @@ -51,12 +52,12 @@ } }, "@babel/generator": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.8.tgz", - "integrity": "sha512-HKyUVu69cZoclptr8t8U5b6sx6zoWjh8jiUhnuj3MpZuKT2dJ8zPTuiy31luq32swhI0SpwItCIlU8XW7BZeJg==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", + "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", "dev": true, "requires": { - "@babel/types": "^7.8.7", + "@babel/types": "^7.9.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -96,6 +97,70 @@ "@babel/types": "^7.8.3" } }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", + "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.0", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, "@babel/helper-split-export-declaration": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", @@ -105,38 +170,44 @@ "@babel/types": "^7.8.3" } }, + "@babel/helper-validator-identifier": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", + "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "dev": true + }, "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", + "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", "dev": true, "requires": { "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3" + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.8.tgz", - "integrity": "sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", "dev": true }, "@babel/runtime": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", - "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", + "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -154,17 +225,17 @@ } }, "@babel/traverse": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.6.tgz", - "integrity": "sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", + "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.6", + "@babel/generator": "^7.9.0", "@babel/helper-function-name": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -179,12 +250,12 @@ } }, "@babel/types": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.7.tgz", - "integrity": "sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", + "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", "dev": true, "requires": { - "esutils": "^2.0.2", + "@babel/helper-validator-identifier": "^7.9.0", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } @@ -422,9 +493,9 @@ "dev": true }, "@types/node": { - "version": "13.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz", - "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==", + "version": "13.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.3.tgz", + "integrity": "sha512-01s+ac4qerwd6RHD+mVbOEsraDHSgUaefQlEdBbUolnQFjKwCr7luvAlEwW1RFojh67u0z4OUTjPn9LEl4zIkA==", "dev": true }, "@types/parse-json": { @@ -443,9 +514,9 @@ } }, "@types/rimraf": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.3.tgz", - "integrity": "sha512-dZfyfL/u9l/oi984hEXdmAjX3JHry7TLWw43u1HQ8HhPv6KtfxnrZ3T/bleJ0GEvnk9t5sM7eePkgMqz3yBcGg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.4.tgz", + "integrity": "sha512-8gBudvllD2A/c0CcEX/BivIDorHFt5UI5m46TsNj8DjWCCTTZT74kEe4g+QsY7P/B9WdO98d82zZgXO/RQzu2Q==", "dev": true, "requires": { "@types/glob": "*", @@ -698,7 +769,7 @@ "acorn-jsx": "^5.0.1", "chalk": "^2.4.2", "magic-string": "^0.25.3", - "minimist": "^1.2.3", + "minimist": "^1.2.0", "os-homedir": "^2.0.0", "regexpu-core": "^4.5.4" }, @@ -977,12 +1048,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "console-group": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/console-group/-/console-group-0.3.3.tgz", - "integrity": "sha1-bY62uda3V6KJUoT2LQnHrUPyu84=", - "dev": true - }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -1196,9 +1261,9 @@ } }, "es-abstract": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", - "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", @@ -1226,9 +1291,9 @@ } }, "es5-shim": { - "version": "4.5.13", - "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.13.tgz", - "integrity": "sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw==", + "version": "4.5.14", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.5.14.tgz", + "integrity": "sha512-7SwlpL+2JpymWTt8sNLuC2zdhhc+wrfe5cMPI2j0o6WsPdfAiPwmFy2f0AocPB4RQVBOZ9kNTgi5YF7TdhkvEg==", "dev": true }, "es6-error": { @@ -1444,12 +1509,20 @@ "dev": true }, "esquery": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", - "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", + "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.0.0" + }, + "dependencies": { + "estraverse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", + "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", + "dev": true + } } }, "esrecurse": { @@ -1866,9 +1939,9 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -1972,9 +2045,9 @@ "dev": true }, "html-escaper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.1.tgz", + "integrity": "sha512-hNX23TjWwD3q56HpWjUHOKj1+4KKlnjv9PcmBUYKVpga+2cnb9nDx/B1o0yO4n+RZXZdiNxzx6B24C9aNMTkkQ==", "dev": true }, "http-proxy-agent": { @@ -2726,9 +2799,9 @@ } }, "lint-staged": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.8.tgz", - "integrity": "sha512-Oa9eS4DJqvQMVdywXfEor6F4vP+21fPHF8LUXgBbVWUSWBddjqsvO6Bv1LwMChmgQZZqwUvgJSHlu8HFHAPZmA==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.0.9.tgz", + "integrity": "sha512-NKJHYgRa8oI9c4Ic42ZtF2XA6Ps7lFbXwg3q0ZEP0r55Tw3YWykCW1RzW6vu+QIGqbsy7DxndvKu93Wtr5vPQw==", "dev": true, "requires": { "chalk": "^3.0.0", @@ -3280,18 +3353,18 @@ "dev": true }, "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "dev": true, "requires": { "minimist": "^1.2.5" } }, "mocha": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.0.tgz", - "integrity": "sha512-MymHK8UkU0K15Q/zX7uflZgVoRWiTjy0fXE/QjKts6mowUvGxOdPhZ2qj3b0iZdUrNZlW9LAIMFHB4IW+2b3EQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz", + "integrity": "sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -3307,7 +3380,7 @@ "js-yaml": "3.13.1", "log-symbols": "3.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", + "mkdirp": "0.5.3", "ms": "2.1.1", "node-environment-flags": "1.0.6", "object.assign": "4.1.0", @@ -3315,8 +3388,8 @@ "supports-color": "6.0.0", "which": "1.3.1", "wide-align": "1.1.3", - "yargs": "13.3.0", - "yargs-parser": "13.1.1", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", "yargs-unparser": "1.6.0" }, "dependencies": { @@ -3379,12 +3452,12 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", "dev": true, "requires": { - "minimist": "^1.2.3" + "minimist": "^1.2.5" } }, "ms": { @@ -3442,9 +3515,9 @@ } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -3959,9 +4032,9 @@ } }, "picomatch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pify": { @@ -3995,9 +4068,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz", + "integrity": "sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==", "dev": true }, "pretty-bytes": { @@ -4247,9 +4320,9 @@ } }, "rollup": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.0.6.tgz", - "integrity": "sha512-P42IlI6a/bxh52ed8hEXXe44LcHfep2f26OZybMJPN1TTQftibvQEl3CWeOmJrzqGbFxOA000QXDWO9WJaOQpA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.2.0.tgz", + "integrity": "sha512-iAu/j9/WJ0i+zT0sAMuQnsEbmOKzdQ4Yxu5rbPs9aUCyqveI1Kw3H4Fi9NWfCOpb8luEySD2lDyFWL9CrLE8iw==", "dev": true, "requires": { "fsevents": "~2.1.2" @@ -4313,6 +4386,12 @@ "terser": "^4.6.2" } }, + "rollup-plugin-thatworks": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/rollup-plugin-thatworks/-/rollup-plugin-thatworks-1.0.4.tgz", + "integrity": "sha512-RxlYx/oolwXW7akleFzRmJ8gQrWUK4NSZw8E+LHJTWHiA1mhseIMurz8IkyDAG4fwensXHocNYvKUHivhN9EXw==", + "dev": true + }, "rollup-plugin-typescript": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-1.0.1.tgz", @@ -4444,7 +4523,7 @@ "dev": true, "requires": { "es6-object-assign": "^1.0.3", - "minimist": "^1.2.3", + "minimist": "^1.2.0", "shelljs": "^0.8.1" } }, @@ -5212,18 +5291,18 @@ "dev": true }, "yaml": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.2.tgz", - "integrity": "sha512-omakb0d7FjMo3R1D2EbTKVIk6dAVLRxFXdLZMEUToeAvuqgG/YuHMuQOZ5fgk+vQ8cx+cnGKwyg+8g8PNT0xQg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.8.3.tgz", + "integrity": "sha512-X/v7VDnK+sxbQ2Imq4Jt2PRUsRsP7UcpSl3Llg6+NRRqWLIvxkMFYtH1FmvwNGYRKKPa+EPA4qDBlI9WVG1UKw==", "dev": true, "requires": { "@babel/runtime": "^7.8.7" } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { "cliui": "^5.0.0", @@ -5235,7 +5314,7 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^13.1.2" }, "dependencies": { "emoji-regex": { diff --git a/package.json b/package.json index c12e4a6feb1..72d9af87328 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "build:bootstrap": "dist/bin/rollup -c && shx cp src/rollup/types.d.ts dist/rollup.d.ts && shx chmod a+x dist/bin/rollup", "ci:lint": "npm run lint:nofix", "ci:test": "npm run build:test && npm run build:bootstrap && npm run test:all", + "ci:test:only": "npm run build:test && npm run build:bootstrap && npm run test:only", "ci:coverage": "npm run build:test && nyc --reporter lcovonly mocha && codecov", "lint": "npm run lint:ts -- --fix && npm run lint:js -- --fix && npm run lint:markdown", "lint:nofix": "npm run lint:ts && npm run lint:js && npm run lint:markdown", @@ -70,7 +71,7 @@ "@rollup/plugin-node-resolve": "^7.1.1", "@rollup/plugin-replace": "^2.3.1", "@types/micromatch": "^4.0.1", - "@types/node": "^13.9.1", + "@types/node": "^13.9.3", "@types/yargs-parser": "^15.0.0", "acorn": "^7.1.1", "acorn-export-ns-from": "^0.1.0", @@ -81,11 +82,10 @@ "chokidar": "^3.3.1", "codecov": "^3.6.5", "colorette": "^1.1.0", - "console-group": "^0.3.3", "core-js": "^3.6.4", "cross-os": "^1.3.0", "date-time": "^3.1.0", - "es5-shim": "^4.5.13", + "es5-shim": "^4.5.14", "es6-shim": "^0.35.5", "eslint": "^6.8.0", "eslint-plugin-import": "^2.20.1", @@ -94,23 +94,24 @@ "hash.js": "^1.1.7", "husky": "^4.2.3", "is-reference": "^1.1.4", - "lint-staged": "^10.0.8", + "lint-staged": "^10.0.9", "locate-character": "^2.0.5", "magic-string": "^0.25.7", "markdownlint-cli": "^0.22.0", "micromatch": "^4.0.2", - "mocha": "^7.1.0", + "mocha": "^7.1.1", "node-fetch": "^2.6.0", "nyc": "^15.0.0", - "prettier": "^1.19.1", + "prettier": "^2.0.2", "pretty-bytes": "^5.3.0", "pretty-ms": "^6.0.1", "require-relative": "^0.8.7", "requirejs": "^2.3.6", - "rollup": "^2.0.6", + "rollup": "^2.2.0", "rollup-plugin-license": "^0.13.0", "rollup-plugin-string": "^3.0.0", "rollup-plugin-terser": "^5.3.0", + "rollup-plugin-thatworks": "^1.0.4", "rollup-plugin-typescript": "^1.0.1", "rollup-pluginutils": "^2.8.2", "sander": "^0.6.0", diff --git a/rollup.config.js b/rollup.config.js index 22cca564245..ba2159c5a9e 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -7,9 +7,10 @@ import path from 'path'; import { string } from 'rollup-plugin-string'; import { terser } from 'rollup-plugin-terser'; import typescript from 'rollup-plugin-typescript'; -import addBinShebang from './build-plugins/add-bin-shebang'; +import addBinShebang from './build-plugins/add-bin-shebang.js'; import conditionalFsEventsImport from './build-plugins/conditional-fsevents-import'; import emitModulePackageFile from './build-plugins/emit-module-package-file.js'; +import esmDynamicImport from './build-plugins/esm-dynamic-import.js'; import getLicenseHandler from './build-plugins/generate-license-file'; import pkg from './package.json'; @@ -73,10 +74,11 @@ export default command => { const commonJSBuild = { input: { 'rollup.js': 'src/node-entry.ts', - 'bin/rollup': 'cli/index.ts' + 'bin/rollup': 'cli/index.ts', + 'loadConfigFile.js': 'cli/run/loadConfigFile.ts' }, onwarn, - plugins: [...nodePlugins, addBinShebang(), !command.configTest && collectLicenses()], + plugins: [...nodePlugins, addBinShebang(), esmDynamicImport(), !command.configTest && collectLicenses()], // fsevents is a dependency of chokidar that cannot be bundled as it contains binary code external: [ 'assert', @@ -88,6 +90,7 @@ export default command => { 'path', 'os', 'stream', + 'url', 'util' ], treeshake, diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 17a61eff786..265a6237b47 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -589,6 +589,10 @@ export interface RollupOptions extends InputOptions { output?: OutputOptions | OutputOptions[]; } +export interface MergedRollupOptions extends InputOptions { + output: OutputOptions[]; +} + export function rollup(options: RollupOptions): Promise; export interface ChokidarOptions { diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index a74e98d4d23..18aaf277262 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -1,11 +1,11 @@ -import { InputOptions, OutputOptions, WarningHandler } from '../rollup/types'; +import { MergedRollupOptions, WarningHandler } from '../rollup/types'; import { CommandConfigObject, ensureArray, GenericConfigObject, parseInputOptions, parseOutputOptions, - warnUnknownOptions + warnUnknownOptions, } from './parseOptions'; export const commandAliases: { [key: string]: string } = { @@ -21,17 +21,14 @@ export const commandAliases: { [key: string]: string } = { o: 'file', p: 'plugin', v: 'version', - w: 'watch' + w: 'watch', }; export function mergeOptions( config: GenericConfigObject, rawCommandOptions: GenericConfigObject = { external: [], globals: undefined }, defaultOnWarnHandler?: WarningHandler -): { - inputOptions: InputOptions; - outputOptions: OutputOptions[]; -} { +): MergedRollupOptions { const command = getCommandOptions(rawCommandOptions); const inputOptions = parseInputOptions(config, command, defaultOnWarnHandler); const warn = inputOptions.onwarn as WarningHandler; @@ -40,14 +37,14 @@ export function mergeOptions( } const outputOptionsArray = ensureArray(config.output) as GenericConfigObject[]; if (outputOptionsArray.length === 0) outputOptionsArray.push({}); - const outputOptions = outputOptionsArray.map(singleOutputOptions => + const outputOptions = outputOptionsArray.map((singleOutputOptions) => parseOutputOptions(singleOutputOptions, warn, command) ); warnUnknownOptions( command, Object.keys(inputOptions).concat( - Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapPathTransform'), + Object.keys(outputOptions[0]).filter((option) => option !== 'sourcemapPathTransform'), Object.keys(commandAliases), 'config', 'environment', @@ -59,10 +56,8 @@ export function mergeOptions( warn, /^_$|output$|config/ ); - return { - inputOptions, - outputOptions - }; + (inputOptions as MergedRollupOptions).output = outputOptions; + return inputOptions as MergedRollupOptions; } function getCommandOptions(rawCommandOptions: GenericConfigObject): CommandConfigObject { @@ -83,6 +78,6 @@ function getCommandOptions(rawCommandOptions: GenericConfigObject): CommandConfi } return globals; }, Object.create(null)) - : undefined + : undefined, }; } diff --git a/src/watch/watch.ts b/src/watch/watch.ts index e2171e3491b..96b36521467 100644 --- a/src/watch/watch.ts +++ b/src/watch/watch.ts @@ -2,15 +2,15 @@ import * as path from 'path'; import createFilter from 'rollup-pluginutils/src/createFilter'; import { rollupInternal } from '../rollup/rollup'; import { - InputOptions, + MergedRollupOptions, OutputOptions, RollupBuild, RollupCache, RollupWatcher, - WatcherOptions + WatcherOptions, } from '../rollup/types'; import { mergeOptions } from '../utils/mergeOptions'; -import { GenericConfigObject } from '../utils/parseOptions'; +import { ensureArray, GenericConfigObject } from '../utils/parseOptions'; import { FileWatcher } from './fileWatcher'; const DELAY = 200; @@ -27,9 +27,7 @@ export class Watcher { constructor(configs: GenericConfigObject[] | GenericConfigObject, emitter: RollupWatcher) { this.emitter = emitter; emitter.close = this.close.bind(this); - this.tasks = (Array.isArray(configs) ? configs : configs ? [configs] : []).map( - config => new Task(this, config) - ); + this.tasks = ensureArray(configs).map((config) => new Task(this, config)); this.running = true; process.nextTick(() => this.run()); } @@ -72,7 +70,7 @@ export class Watcher { this.running = true; this.emit('event', { - code: 'START' + code: 'START', }); try { @@ -81,13 +79,13 @@ export class Watcher { } this.running = false; this.emit('event', { - code: 'END' + code: 'END', }); } catch (error) { this.running = false; this.emit('event', { code: 'ERROR', - error + error, }); } @@ -105,8 +103,8 @@ export class Task { private closed: boolean; private fileWatcher: FileWatcher; private filter: (id: string) => boolean; - private inputOptions: InputOptions; private invalidated = true; + private options: MergedRollupOptions; private outputFiles: string[]; private outputs: OutputOptions[]; private skipWrite: boolean; @@ -119,20 +117,19 @@ export class Task { this.watched = new Set(); this.skipWrite = config.watch && !!(config.watch as GenericConfigObject).skipWrite; - const { inputOptions, outputOptions } = mergeOptions(config); - this.inputOptions = inputOptions; - this.outputs = outputOptions; - this.outputFiles = this.outputs.map(output => { + this.options = mergeOptions(config); + this.outputs = this.options.output; + this.outputFiles = this.outputs.map((output) => { if (output.file || output.dir) return path.resolve(output.file || output.dir!); return undefined as any; }); - const watchOptions: WatcherOptions = inputOptions.watch || {}; + const watchOptions: WatcherOptions = this.options.watch || {}; this.filter = createFilter(watchOptions.include, watchOptions.exclude); this.fileWatcher = new FileWatcher(this, { ...watchOptions.chokidar, disableGlobbing: true, - ignoreInitial: true + ignoreInitial: true, }); } @@ -158,16 +155,16 @@ export class Task { this.invalidated = false; const options = { - ...this.inputOptions, - cache: this.cache + ...this.options, + cache: this.cache, }; const start = Date.now(); this.watcher.emit('event', { code: 'BUNDLE_START', - input: this.inputOptions.input, - output: this.outputFiles + input: this.options.input, + output: this.outputFiles, }); try { @@ -176,13 +173,13 @@ export class Task { return; } this.updateWatchedFiles(result); - this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output)))); + this.skipWrite || (await Promise.all(this.outputs.map((output) => result.write(output)))); this.watcher.emit('event', { code: 'BUNDLE_END', duration: Date.now() - start, - input: this.inputOptions.input, + input: this.options.input, output: this.outputFiles, - result + result, }); } catch (error) { if (this.closed) { @@ -195,7 +192,7 @@ export class Task { } } if (error.id) { - this.cache.modules = this.cache.modules.filter(module => module.id !== error.id); + this.cache.modules = this.cache.modules.filter((module) => module.id !== error.id); } throw error; } @@ -225,7 +222,7 @@ export class Task { if (!this.filter(id)) return; this.watched.add(id); - if (this.outputFiles.some(file => file === id)) { + if (this.outputFiles.some((file) => file === id)) { throw new Error('Cannot import the generated bundle'); } diff --git a/test/cli/index.js b/test/cli/index.js index 5a922c1f3b3..62852932a79 100644 --- a/test/cli/index.js +++ b/test/cli/index.js @@ -5,7 +5,7 @@ const { exec } = require('child_process'); const { normaliseOutput, runTestSuiteWithSamples, - assertDirectoriesAreEqual + assertDirectoriesAreEqual, } = require('../utils.js'); const cwd = process.cwd(); @@ -19,8 +19,9 @@ runTestSuiteWithSamples( (dir, config) => { (config.skip ? it.skip : config.solo ? it.only : it)( path.basename(dir) + ': ' + config.description, - done => { + (done) => { process.chdir(config.cwd || dir); + if (config.before) config.before(); const command = config.command.replace( /(^| )rollup($| )/g, @@ -31,9 +32,10 @@ runTestSuiteWithSamples( command, { timeout: 40000, - env: Object.assign({}, process.env, { FORCE_COLOR: '0' }, config.env) + env: Object.assign({}, process.env, { FORCE_COLOR: '0' }, config.env), }, (err, code, stderr) => { + if (config.after) config.after(); if (err && !err.killed) { if (config.error) { const shouldContinue = config.error(err); @@ -44,7 +46,7 @@ runTestSuiteWithSamples( } if ('stderr' in config) { - const shouldContinue = config.stderr(stderr.trim()); + const shouldContinue = config.stderr(stderr); if (!shouldContinue) return done(); } else if (stderr) { console.error(stderr); @@ -56,7 +58,7 @@ runTestSuiteWithSamples( try { const fn = new Function('require', 'module', 'exports', 'assert', code); const module = { - exports: {} + exports: {}, }; fn(require, module, module.exports, assert); @@ -118,7 +120,7 @@ runTestSuiteWithSamples( } ); - childProcess.stderr.on('data', data => { + childProcess.stderr.on('data', (data) => { if (config.abortOnStderr && config.abortOnStderr(data)) { childProcess.kill('SIGINT'); } diff --git a/test/cli/samples/config-cjs-dirname/_config.js b/test/cli/samples/config-cjs-dirname/_config.js new file mode 100644 index 00000000000..7b8f251fc3e --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'does not transpile cjs configs and provides correct __filename', + command: 'rollup -c' +}; diff --git a/test/cli/samples/config-cjs-dirname/_expected.js b/test/cli/samples/config-cjs-dirname/_expected.js new file mode 100644 index 00000000000..6e0be4aa7be --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/_expected.js @@ -0,0 +1,5 @@ +console.log('nested/plugin.js'); +console.log('plugin.js'); +var main = 42; + +export default main; diff --git a/test/cli/samples/config-cjs-dirname/main.js b/test/cli/samples/config-cjs-dirname/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/cli/samples/config-cjs-dirname/nested/plugin.js b/test/cli/samples/config-cjs-dirname/nested/plugin.js new file mode 100644 index 00000000000..9c83bf93188 --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/nested/plugin.js @@ -0,0 +1,9 @@ +const path = require('path'); + +module.exports = () => ({ + transform(code) { + return `console.log('${path + .relative(process.cwd(), __filename) + .replace('\\', '/')}');\n${code}`; + } +}); diff --git a/test/cli/samples/config-cjs-dirname/plugin.js b/test/cli/samples/config-cjs-dirname/plugin.js new file mode 100644 index 00000000000..9c83bf93188 --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/plugin.js @@ -0,0 +1,9 @@ +const path = require('path'); + +module.exports = () => ({ + transform(code) { + return `console.log('${path + .relative(process.cwd(), __filename) + .replace('\\', '/')}');\n${code}`; + } +}); diff --git a/test/cli/samples/config-cjs-dirname/rollup.config.cjs b/test/cli/samples/config-cjs-dirname/rollup.config.cjs new file mode 100644 index 00000000000..fb6dfc8cae0 --- /dev/null +++ b/test/cli/samples/config-cjs-dirname/rollup.config.cjs @@ -0,0 +1,8 @@ +const plugin = require('./plugin'); +const nestedPlugin = require('./nested/plugin'); + +module.exports = { + input: 'main.js', + output: { format: 'esm' }, + plugins: [plugin(), nestedPlugin()] +}; diff --git a/test/cli/samples/config-cwd-case-insensitive/_config.js b/test/cli/samples/config-cwd-case-insensitive/_config.js index 13ab909b2bd..aa70c6ca632 100644 --- a/test/cli/samples/config-cwd-case-insensitive/_config.js +++ b/test/cli/samples/config-cwd-case-insensitive/_config.js @@ -1,11 +1,9 @@ -const os = require('os'); - function toggleCase(s) { return s == s.toLowerCase() ? s.toUpperCase() : s.toLowerCase(); } module.exports = { - skip: os.platform() !== 'win32', + onlyWindows: true, description: "can load config with cwd that doesn't match realpath", command: 'rollup -c', cwd: __dirname.replace(/^[A-Z]:\\/i, toggleCase), diff --git a/test/cli/samples/config-mjs-plugins/_config.js b/test/cli/samples/config-mjs-plugins/_config.js new file mode 100644 index 00000000000..e12031215b1 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/_config.js @@ -0,0 +1,5 @@ +module.exports = { + description: 'supports native esm as well as CJS plugins when using .mjs in Node 13+', + minNodeVersion: 13, + command: 'rollup -c' +}; diff --git a/test/cli/samples/config-mjs-plugins/_expected.js b/test/cli/samples/config-mjs-plugins/_expected.js new file mode 100644 index 00000000000..a5830649f64 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/_expected.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node +'use strict'; + +console.log('nested/plugin.mjs'); +console.log('plugin.mjs'); +var main = 42; + +module.exports = main; diff --git a/test/cli/samples/config-mjs-plugins/main.js b/test/cli/samples/config-mjs-plugins/main.js new file mode 100644 index 00000000000..427e820e808 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/main.js @@ -0,0 +1 @@ +export default ANSWER; diff --git a/test/cli/samples/config-mjs-plugins/nested/plugin.mjs b/test/cli/samples/config-mjs-plugins/nested/plugin.mjs new file mode 100644 index 00000000000..7ecc957ef55 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/nested/plugin.mjs @@ -0,0 +1,11 @@ +import { relative } from 'path'; +import { fileURLToPath } from 'url'; + +export default () => ({ + transform(code) { + return `console.log('${relative(process.cwd(), fileURLToPath(import.meta.url)).replace( + '\\', + '/' + )}');\n${code}`; + } +}); diff --git a/test/cli/samples/config-mjs-plugins/plugin.mjs b/test/cli/samples/config-mjs-plugins/plugin.mjs new file mode 100644 index 00000000000..7ecc957ef55 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/plugin.mjs @@ -0,0 +1,11 @@ +import { relative } from 'path'; +import { fileURLToPath } from 'url'; + +export default () => ({ + transform(code) { + return `console.log('${relative(process.cwd(), fileURLToPath(import.meta.url)).replace( + '\\', + '/' + )}');\n${code}`; + } +}); diff --git a/test/cli/samples/config-mjs-plugins/rollup.config.mjs b/test/cli/samples/config-mjs-plugins/rollup.config.mjs new file mode 100644 index 00000000000..68abe406bb5 --- /dev/null +++ b/test/cli/samples/config-mjs-plugins/rollup.config.mjs @@ -0,0 +1,12 @@ +// This is a CJS plugin +import replace from '@rollup/plugin-replace/dist/rollup-plugin-replace.cjs.js'; +// This is an ESM plugin +import { shebang } from 'rollup-plugin-thatworks'; +import nestedPlugin from './nested/plugin.mjs'; +import plugin from './plugin.mjs'; + +export default { + input: 'main.js', + output: { format: 'cjs' }, + plugins: [shebang(), replace({ ANSWER: 42 }), plugin(), nestedPlugin()] +}; diff --git a/test/cli/samples/config-no-module/_config.js b/test/cli/samples/config-no-module/_config.js new file mode 100644 index 00000000000..71e4f63ec01 --- /dev/null +++ b/test/cli/samples/config-no-module/_config.js @@ -0,0 +1,17 @@ +const { assertStderrIncludes } = require('../../../utils.js'); + +module.exports = { + description: 'provides a helpful error message if a transpiled config is interpreted as "module"', + minNodeVersion: 13, + command: 'cd sub && rollup -c', + error: () => true, + stderr: (stderr) => + assertStderrIncludes( + stderr, + '[!] Error: While loading the Rollup configuration from "rollup.config.js", Node tried to require an ES module from a CommonJS ' + + 'file, which is not supported. A common cause is if there is a package.json file with "type": "module" in the same folder. You can ' + + 'try to fix this by changing the extension of your configuration file to ".cjs" or ".mjs" depending on the content, which will ' + + 'prevent Rollup from trying to preprocess the file but rather hand it to Node directly.\n' + + 'https://rollupjs.org/guide/en/#using-untranspiled-config-files' + ), +}; diff --git a/test/cli/samples/config-no-module/sub/main.js b/test/cli/samples/config-no-module/sub/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/cli/samples/config-no-module/sub/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/cli/samples/config-no-module/sub/package.json b/test/cli/samples/config-no-module/sub/package.json new file mode 100644 index 00000000000..bedb411a912 --- /dev/null +++ b/test/cli/samples/config-no-module/sub/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/cli/samples/config-no-module/sub/rollup.config.js b/test/cli/samples/config-no-module/sub/rollup.config.js new file mode 100644 index 00000000000..28f443866ee --- /dev/null +++ b/test/cli/samples/config-no-module/sub/rollup.config.js @@ -0,0 +1,7 @@ +import { shebang } from 'rollup-plugin-thatworks'; + +export default { + input: 'main.js', + output: { format: 'cjs' }, + plugins: [shebang()] +}; diff --git a/test/cli/samples/config-promise-cjs/_config.js b/test/cli/samples/config-promise-cjs/_config.js new file mode 100644 index 00000000000..75219d417ed --- /dev/null +++ b/test/cli/samples/config-promise-cjs/_config.js @@ -0,0 +1,5 @@ +module.exports = { + description: 'uses cjs config file which returns a Promise', + command: 'rollup --config rollup.config.cjs', + execute: true +}; diff --git a/test/cli/samples/config-promise-cjs/main.js b/test/cli/samples/config-promise-cjs/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/samples/config-promise-cjs/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/samples/config-promise-cjs/rollup.config.cjs b/test/cli/samples/config-promise-cjs/rollup.config.cjs new file mode 100644 index 00000000000..e9f06d4fe87 --- /dev/null +++ b/test/cli/samples/config-promise-cjs/rollup.config.cjs @@ -0,0 +1,9 @@ +const replace = require('@rollup/plugin-replace'); + +module.exports = Promise.resolve({ + input: 'main.js', + output: { + format: 'cjs' + }, + plugins: [replace({ ANSWER: 42 })] +}); diff --git a/test/cli/samples/config-promise-mjs/_config.js b/test/cli/samples/config-promise-mjs/_config.js new file mode 100644 index 00000000000..7cfdef3e2d7 --- /dev/null +++ b/test/cli/samples/config-promise-mjs/_config.js @@ -0,0 +1,6 @@ +module.exports = { + description: 'uses mjs config file which returns a Promise', + minNodeVersion: 13, + command: 'rollup --config rollup.config.mjs', + execute: true +}; diff --git a/test/cli/samples/config-promise-mjs/main.js b/test/cli/samples/config-promise-mjs/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/samples/config-promise-mjs/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/samples/config-promise-mjs/rollup.config.mjs b/test/cli/samples/config-promise-mjs/rollup.config.mjs new file mode 100644 index 00000000000..1fbb95608c9 --- /dev/null +++ b/test/cli/samples/config-promise-mjs/rollup.config.mjs @@ -0,0 +1,9 @@ +import replace from '@rollup/plugin-replace'; + +export default Promise.resolve({ + input: 'main.js', + output: { + format: 'cjs' + }, + plugins: [replace({ ANSWER: 42 })] +}); diff --git a/test/cli/samples/config-promise/rollup.config.js b/test/cli/samples/config-promise/rollup.config.js index 610ca587908..e0552b574ee 100644 --- a/test/cli/samples/config-promise/rollup.config.js +++ b/test/cli/samples/config-promise/rollup.config.js @@ -1,11 +1,11 @@ -var replace = require( '@rollup/plugin-replace' ); +import replace from '@rollup/plugin-replace'; -module.exports = Promise.resolve( { +export const ignored = 'forces named exports mode'; + +export default Promise.resolve({ input: 'main.js', output: { format: 'cjs' }, - plugins: [ - replace( { 'ANSWER': 42 } ) - ] -} ); + plugins: [replace({ ANSWER: 42 })] +}); diff --git a/test/cli/samples/config-warnings/_config.js b/test/cli/samples/config-warnings/_config.js new file mode 100644 index 00000000000..923075c58bb --- /dev/null +++ b/test/cli/samples/config-warnings/_config.js @@ -0,0 +1,11 @@ +const { assertStderrIncludes } = require('../../../utils.js'); + +module.exports = { + description: 'displays warnings when a config is loaded', + command: 'rollup -c', + stderr: stderr => + assertStderrIncludes( + stderr, + 'loaded rollup.config.js with warnings\n(!) Use of eval is strongly discouraged' + ) +}; diff --git a/test/cli/samples/watch/_expected.js b/test/cli/samples/config-warnings/_expected.js similarity index 100% rename from test/cli/samples/watch/_expected.js rename to test/cli/samples/config-warnings/_expected.js diff --git a/test/cli/samples/config-warnings/main.js b/test/cli/samples/config-warnings/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/cli/samples/config-warnings/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/cli/samples/config-warnings/rollup.config.js b/test/cli/samples/config-warnings/rollup.config.js new file mode 100644 index 00000000000..d3c2a1bd70c --- /dev/null +++ b/test/cli/samples/config-warnings/rollup.config.js @@ -0,0 +1,6 @@ +export default { + input: eval('"main.js"'), + output: { + format: 'cjs' + } +}; diff --git a/test/cli/samples/node-config-not-found/_config.js b/test/cli/samples/node-config-not-found/_config.js index cf53bf19d71..264996d5fd0 100644 --- a/test/cli/samples/node-config-not-found/_config.js +++ b/test/cli/samples/node-config-not-found/_config.js @@ -5,6 +5,6 @@ module.exports = { command: 'rollup --config node:baz', error: () => true, stderr(stderr) { - assertStderrIncludes(stderr, '[!] Could not resolve config file node:baz'); + assertStderrIncludes(stderr, '[!] Could not resolve config file "node:baz"'); } }; diff --git a/test/cli/samples/stdout-code-splitting/_config.js b/test/cli/samples/stdout-code-splitting/_config.js index bf359a58f15..d924cb990fe 100644 --- a/test/cli/samples/stdout-code-splitting/_config.js +++ b/test/cli/samples/stdout-code-splitting/_config.js @@ -5,7 +5,10 @@ const STANDARD = '\u001b[22m\u001b[39m'; module.exports = { description: 'bundles multiple files to stdout while adding file names', - command: 'node wrapper.js -i main1.js -i main2.js -f es', + skipIfWindows: true, + command: + 'node wrapper.js -i main1.js -i main2.js -f es ' + + `-p '{buildStart(){this.emitFile({type: "asset",source:"Hello"})}}'`, env: { FORCE_COLOR: '1', TERM: 'xterm' }, result(code) { assert.equal( @@ -15,8 +18,10 @@ module.exports = { "console.log('main1');\n" + '\n' + `${COLOR}//→ main2.js:${STANDARD}\n` + - "console.log('main2');" + - '\n' + "console.log('main2');\n" + + '\n' + + `${COLOR}//→ assets/asset-74b448a5:${STANDARD}\n` + + 'Hello' ); - } + }, }; diff --git a/test/cli/samples/stdout-only-inline-sourcemaps/_config.js b/test/cli/samples/stdout-only-inline-sourcemaps/_config.js new file mode 100644 index 00000000000..65fcc021d22 --- /dev/null +++ b/test/cli/samples/stdout-only-inline-sourcemaps/_config.js @@ -0,0 +1,13 @@ +const { assertStderrIncludes } = require('../../../utils.js'); + +module.exports = { + description: 'fails when using non-inline sourcemaps when bundling to stdout', + command: 'rollup -i main.js -f es -m', + error: () => true, + stderr: (stderr) => { + assertStderrIncludes( + stderr, + '[!] Only inline sourcemaps are supported when bundling to stdout.\n' + ); + }, +}; diff --git a/test/cli/samples/stdout-only-inline-sourcemaps/_expected.js b/test/cli/samples/stdout-only-inline-sourcemaps/_expected.js new file mode 100644 index 00000000000..70449540ecd --- /dev/null +++ b/test/cli/samples/stdout-only-inline-sourcemaps/_expected.js @@ -0,0 +1,3 @@ +console.log( 42 ); + +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibWFpbi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZyggNDIgKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSJ9 diff --git a/test/cli/samples/stdout-only-inline-sourcemaps/main.js b/test/cli/samples/stdout-only-inline-sourcemaps/main.js new file mode 100644 index 00000000000..5c72ff35124 --- /dev/null +++ b/test/cli/samples/stdout-only-inline-sourcemaps/main.js @@ -0,0 +1 @@ +console.log( 42 ); diff --git a/test/cli/samples/stdout-single-input/_config.js b/test/cli/samples/stdout-single-input/_config.js index 79a9fa5ac9e..10177e23ba0 100644 --- a/test/cli/samples/stdout-single-input/_config.js +++ b/test/cli/samples/stdout-single-input/_config.js @@ -1,9 +1,4 @@ -const assert = require('assert'); - module.exports = { description: 'bundles a single input to stdout without modifications', - command: 'rollup -i main.js -f es', - result(code) { - assert.equal(code, 'console.log( 42 );\n'); - } + command: 'rollup -i main.js -f es -m inline', }; diff --git a/test/cli/samples/stdout-single-input/_expected.js b/test/cli/samples/stdout-single-input/_expected.js new file mode 100644 index 00000000000..70449540ecd --- /dev/null +++ b/test/cli/samples/stdout-single-input/_expected.js @@ -0,0 +1,3 @@ +console.log( 42 ); + +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibWFpbi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZyggNDIgKTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSJ9 diff --git a/test/cli/samples/watch/_config.js b/test/cli/samples/watch/_config.js deleted file mode 100644 index 85833195535..00000000000 --- a/test/cli/samples/watch/_config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - description: 'does not fail in watch-mode with clearScreen: false', - command: 'rollup -cw', - abortOnStderr(data) { - if (data.includes('created')) { - return true; - } - } -}; diff --git a/test/cli/samples/watch/bundle-error/_config.js b/test/cli/samples/watch/bundle-error/_config.js new file mode 100644 index 00000000000..18b65f1bfd0 --- /dev/null +++ b/test/cli/samples/watch/bundle-error/_config.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const path = require('path'); + +let mainFile; + +module.exports = { + description: 'recovers from errors during bundling', + command: 'rollup -cw', + before() { + mainFile = path.resolve(__dirname, 'main.js'); + fs.writeFileSync(mainFile, '<=>'); + }, + abortOnStderr(data) { + if (data.includes('Error: Unexpected token')) { + setTimeout(() => fs.writeFileSync(mainFile, 'export default 42;'), 50); + return false; + } + if (data.includes('created _actual')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/bundle-error/_expected/main.js b/test/cli/samples/watch/bundle-error/_expected/main.js new file mode 100644 index 00000000000..d862de816a3 --- /dev/null +++ b/test/cli/samples/watch/bundle-error/_expected/main.js @@ -0,0 +1,3 @@ +var main = 42; + +export default main; diff --git a/test/cli/samples/watch/bundle-error/main.js b/test/cli/samples/watch/bundle-error/main.js new file mode 100644 index 00000000000..a4012bff06c --- /dev/null +++ b/test/cli/samples/watch/bundle-error/main.js @@ -0,0 +1 @@ +export default 42; \ No newline at end of file diff --git a/test/cli/samples/watch/bundle-error/rollup.config.js b/test/cli/samples/watch/bundle-error/rollup.config.js new file mode 100644 index 00000000000..0c8c1cb886e --- /dev/null +++ b/test/cli/samples/watch/bundle-error/rollup.config.js @@ -0,0 +1,7 @@ +export default { + input: 'main.js', + output: { + dir: "_actual", + format: "es" + } +}; diff --git a/test/cli/samples/watch/clearScreen/_config.js b/test/cli/samples/watch/clearScreen/_config.js new file mode 100644 index 00000000000..ebf0d62a40b --- /dev/null +++ b/test/cli/samples/watch/clearScreen/_config.js @@ -0,0 +1,22 @@ +const assert = require('assert'); + +const CLEAR_SCREEN = '\u001bc'; +const UNDERLINE = '\u001b[4m'; +const NO_UNDERLINE = '\u001b[24m'; + +module.exports = { + description: 'clears the screen before bundling', + command: 'node wrapper.js -cw', + env: { FORCE_COLOR: '1', TERM: 'xterm' }, + abortOnStderr(data) { + if (data.includes('waiting for changes')) { + return true; + } + }, + stderr(stderr) { + assert.strictEqual( + stderr.slice(0, 25), + `${CLEAR_SCREEN}${UNDERLINE}rollup v2.2.0${NO_UNDERLINE}\n` + ); + }, +}; diff --git a/test/cli/samples/watch/clearScreen/main.js b/test/cli/samples/watch/clearScreen/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/cli/samples/watch/clearScreen/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/cli/samples/watch/rollup.config.js b/test/cli/samples/watch/clearScreen/rollup.config.js similarity index 72% rename from test/cli/samples/watch/rollup.config.js rename to test/cli/samples/watch/clearScreen/rollup.config.js index 9dcbc4192f0..e0f7e4d8711 100644 --- a/test/cli/samples/watch/rollup.config.js +++ b/test/cli/samples/watch/clearScreen/rollup.config.js @@ -3,8 +3,5 @@ export default { output: { file: '_actual.js', format: 'es' - }, - watch: { - clearScreen: false } }; diff --git a/test/cli/samples/watch/clearScreen/wrapper.js b/test/cli/samples/watch/clearScreen/wrapper.js new file mode 100755 index 00000000000..8f733cc8815 --- /dev/null +++ b/test/cli/samples/watch/clearScreen/wrapper.js @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +process.stdout.isTTY = true; +process.stderr.isTTY = true; +require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/main.js b/test/cli/samples/watch/main.js deleted file mode 100644 index 8ab8dbd37ef..00000000000 --- a/test/cli/samples/watch/main.js +++ /dev/null @@ -1,3 +0,0 @@ -import { foo } from './foo.js'; - -assert.equal( foo, 42 ); diff --git a/test/cli/samples/watch/no-clearScreen/_config.js b/test/cli/samples/watch/no-clearScreen/_config.js new file mode 100644 index 00000000000..af0cfc3f356 --- /dev/null +++ b/test/cli/samples/watch/no-clearScreen/_config.js @@ -0,0 +1,18 @@ +const assert = require('assert'); + +const UNDERLINE = '\u001b[4m'; +const NO_UNDERLINE = '\u001b[24m'; + +module.exports = { + description: 'allows disabling clearing the screen', + command: 'node wrapper.js -cw', + env: { FORCE_COLOR: '1', TERM: 'xterm' }, + abortOnStderr(data) { + if (data.includes('waiting for changes')) { + return true; + } + }, + stderr(stderr) { + assert.strictEqual(stderr.slice(0, 23), `${UNDERLINE}rollup v2.2.0${NO_UNDERLINE}\n`); + }, +}; diff --git a/test/cli/samples/watch/no-clearScreen/_expected.js b/test/cli/samples/watch/no-clearScreen/_expected.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/cli/samples/watch/foo.js b/test/cli/samples/watch/no-clearScreen/foo.js similarity index 100% rename from test/cli/samples/watch/foo.js rename to test/cli/samples/watch/no-clearScreen/foo.js diff --git a/test/cli/samples/watch/no-clearScreen/main.js b/test/cli/samples/watch/no-clearScreen/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/cli/samples/watch/no-clearScreen/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/cli/samples/watch/no-clearScreen/rollup.config.js b/test/cli/samples/watch/no-clearScreen/rollup.config.js new file mode 100644 index 00000000000..a171128d7c0 --- /dev/null +++ b/test/cli/samples/watch/no-clearScreen/rollup.config.js @@ -0,0 +1,22 @@ +export default [ + { + input: 'main.js', + output: { + file: '_actual.js', + format: 'es', + }, + watch: { + clearScreen: true, + }, + }, + { + input: 'main.js', + output: { + file: '_actual.js', + format: 'es', + }, + watch: { + clearScreen: false, + }, + }, +]; diff --git a/test/cli/samples/watch/no-clearScreen/wrapper.js b/test/cli/samples/watch/no-clearScreen/wrapper.js new file mode 100755 index 00000000000..8f733cc8815 --- /dev/null +++ b/test/cli/samples/watch/no-clearScreen/wrapper.js @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +process.stdout.isTTY = true; +process.stderr.isTTY = true; +require('../../../../../dist/bin/rollup'); diff --git a/test/cli/samples/watch/no-config-file/_config.js b/test/cli/samples/watch/no-config-file/_config.js new file mode 100644 index 00000000000..f3f030d4806 --- /dev/null +++ b/test/cli/samples/watch/no-config-file/_config.js @@ -0,0 +1,9 @@ +module.exports = { + description: 'watches without a config file', + command: 'rollup main.js --watch --format es --file _actual/main.js', + abortOnStderr(data) { + if (data.includes('created _actual/main.js')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/no-config-file/_expected/main.js b/test/cli/samples/watch/no-config-file/_expected/main.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/no-config-file/_expected/main.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/no-config-file/main.js b/test/cli/samples/watch/no-config-file/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/no-config-file/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/node-config-file/_config.js b/test/cli/samples/watch/node-config-file/_config.js new file mode 100644 index 00000000000..76205f3ea1b --- /dev/null +++ b/test/cli/samples/watch/node-config-file/_config.js @@ -0,0 +1,9 @@ +module.exports = { + description: 'watches using a node_modules config files', + command: 'rollup --watch --config node:custom', + abortOnStderr(data) { + if (data.includes('created _actual/main.js')) { + return true; + } + }, +}; diff --git a/test/cli/samples/watch/node-config-file/_expected/main.js b/test/cli/samples/watch/node-config-file/_expected/main.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/_expected/main.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/node-config-file/main.js b/test/cli/samples/watch/node-config-file/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js new file mode 100644 index 00000000000..acb52c3147d --- /dev/null +++ b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/index.js @@ -0,0 +1,7 @@ +module.exports = { + input: 'main.js', + output: { + file: '_actual/main.js', + format: 'es', + }, +}; diff --git a/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json new file mode 100644 index 00000000000..6b2fdf69cc5 --- /dev/null +++ b/test/cli/samples/watch/node-config-file/node_modules/rollup-config-custom/package.json @@ -0,0 +1,5 @@ +{ + "name": "rollup-config-custom", + "version": "1.0.0", + "main": "index.js" +} diff --git a/test/cli/samples/watch/watch-config-early-update/_config.js b/test/cli/samples/watch/watch-config-early-update/_config.js new file mode 100644 index 00000000000..badd5165a8e --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_config.js @@ -0,0 +1,73 @@ +const fs = require('fs'); +const path = require('path'); + +let configFile; +let messageFile; +let reloadTriggered = false; + +module.exports = { + description: 'immediately reloads the config file if a change happens while it is parsed', + command: 'rollup -cw', + before() { + configFile = path.resolve(__dirname, 'rollup.config.js'); + messageFile = path.resolve(__dirname, '_actual', 'message.txt'); + fs.mkdirSync(path.resolve(__dirname, '_actual')); + fs.writeFileSync(messageFile, 'initial'); + fs.writeFileSync( + configFile, + ` + import path from 'path'; + import fs from 'fs'; + const messageFile = path.resolve(__dirname, '_actual', 'message.txt'); + export default new Promise(resolve => { + fs.writeFileSync(messageFile, 'loading'); + const watcher = fs.watch(messageFile, event => { + if (event === 'change') { + const content = fs.readFileSync(messageFile, 'utf8'); + if (content === 'loaded') { + watcher.close(); + fs.writeFileSync(messageFile, 'resolved'); + resolve({ + input: {output1: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }); + } + } + }); + }); + ` + ); + const watcher = fs.watch(messageFile, (event) => { + if (event === 'change') { + const content = fs.readFileSync(messageFile, 'utf8'); + if (content === 'loading') { + watcher.close(); + fs.writeFileSync( + configFile, + ` + export default { + input: {output2: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }; + ` + ); + fs.writeFileSync(messageFile, 'loaded'); + } + } + }); + }, + abortOnStderr(data) { + if (reloadTriggered && data.includes('created _actual')) { + return true; + } else if (data.includes('Reloading updated config')) { + reloadTriggered = true; + return false; + } + }, +}; diff --git a/test/cli/samples/watch/watch-config-early-update/_expected/message.txt b/test/cli/samples/watch/watch-config-early-update/_expected/message.txt new file mode 100644 index 00000000000..5dd54033a94 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_expected/message.txt @@ -0,0 +1 @@ +resolved \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config-early-update/_expected/output2.js b/test/cli/samples/watch/watch-config-early-update/_expected/output2.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/_expected/output2.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config-early-update/main.js b/test/cli/samples/watch/watch-config-early-update/main.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/main.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/watch-config-early-update/rollup.config.js b/test/cli/samples/watch/watch-config-early-update/rollup.config.js new file mode 100644 index 00000000000..ec6ec213bce --- /dev/null +++ b/test/cli/samples/watch/watch-config-early-update/rollup.config.js @@ -0,0 +1,9 @@ + + export default { + input: {output2: "main.js"}, + output: { + dir: "_actual", + format: "es" + } + }; + \ No newline at end of file diff --git a/test/cli/samples/watch/watch-config/_config.js b/test/cli/samples/watch/watch-config/_config.js new file mode 100644 index 00000000000..6cf722c1153 --- /dev/null +++ b/test/cli/samples/watch/watch-config/_config.js @@ -0,0 +1,67 @@ +const fs = require('fs'); +const path = require('path'); + +let configFile; +let currentlyBundling; + +const updateConfigDelayed = (content) => + setTimeout(() => fs.writeFileSync(configFile, content), 100); + +module.exports = { + description: 'watches the config file', + command: 'rollup -cw', + before() { + configFile = path.resolve(__dirname, 'rollup.config.js'); + fs.writeFileSync(configFile, 'throw new Error("Config contains initial errors");'); + }, + abortOnStderr(data) { + if (data.includes('→ _actual')) { + currentlyBundling = /bundles([^→]+)→ _actual/.exec(data)[1].trim(); + return false; + } + if (data.includes('Config contains initial errors')) { + updateConfigDelayed( + 'export default {\n' + + '\tinput: "main1.js",\n' + + '\toutput: {\n' + + '\t\tdir: "_actual",\n' + + '\t\tformat: "es"\n' + + '\t}\n' + + '};' + ); + return false; + } + if (data.includes('Config contains further errors')) { + updateConfigDelayed( + 'export default {\n' + + '\tinput: ["main2.js", "main3.js"],\n' + + '\toutput: {\n' + + '\t\tdir: "_actual",\n' + + '\t\tformat: "es"\n' + + '\t}\n' + + '};' + ); + return false; + } + if (data.includes('created _actual')) { + switch (currentlyBundling) { + case 'main1.js': + updateConfigDelayed('throw new Error("Config contains further errors");'); + return false; + case 'main2.js, main3.js': + updateConfigDelayed( + 'export default {\n' + + '\tinput: {output: "main4.js"},\n' + + '\toutput: {\n' + + '\t\tdir: "_actual",\n' + + '\t\tformat: "es"\n' + + '\t}\n' + + '};' + ); + return false; + case 'main4.js': + return true; + } + } + }, +}; diff --git a/test/cli/samples/watch/watch-config/_expected/main1.js b/test/cli/samples/watch/watch-config/_expected/main1.js new file mode 100644 index 00000000000..b72a22eac84 --- /dev/null +++ b/test/cli/samples/watch/watch-config/_expected/main1.js @@ -0,0 +1,3 @@ +const foo = 42; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config/_expected/main2.js b/test/cli/samples/watch/watch-config/_expected/main2.js new file mode 100644 index 00000000000..3cf62c189e5 --- /dev/null +++ b/test/cli/samples/watch/watch-config/_expected/main2.js @@ -0,0 +1,3 @@ +const foo = 43; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config/_expected/main3.js b/test/cli/samples/watch/watch-config/_expected/main3.js new file mode 100644 index 00000000000..746e6c75311 --- /dev/null +++ b/test/cli/samples/watch/watch-config/_expected/main3.js @@ -0,0 +1,3 @@ +const foo = 44; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config/_expected/output.js b/test/cli/samples/watch/watch-config/_expected/output.js new file mode 100644 index 00000000000..eeb2e2e8ce4 --- /dev/null +++ b/test/cli/samples/watch/watch-config/_expected/output.js @@ -0,0 +1,3 @@ +const foo = 45; + +export { foo }; diff --git a/test/cli/samples/watch/watch-config/main1.js b/test/cli/samples/watch/watch-config/main1.js new file mode 100644 index 00000000000..9d7381d29f6 --- /dev/null +++ b/test/cli/samples/watch/watch-config/main1.js @@ -0,0 +1 @@ +export const foo = 42; diff --git a/test/cli/samples/watch/watch-config/main2.js b/test/cli/samples/watch/watch-config/main2.js new file mode 100644 index 00000000000..db30b94fa36 --- /dev/null +++ b/test/cli/samples/watch/watch-config/main2.js @@ -0,0 +1 @@ +export const foo = 43; diff --git a/test/cli/samples/watch/watch-config/main3.js b/test/cli/samples/watch/watch-config/main3.js new file mode 100644 index 00000000000..122348925b3 --- /dev/null +++ b/test/cli/samples/watch/watch-config/main3.js @@ -0,0 +1 @@ +export const foo = 44; diff --git a/test/cli/samples/watch/watch-config/main4.js b/test/cli/samples/watch/watch-config/main4.js new file mode 100644 index 00000000000..24d60140ee9 --- /dev/null +++ b/test/cli/samples/watch/watch-config/main4.js @@ -0,0 +1 @@ +export const foo = 45; diff --git a/test/cli/samples/watch/watch-config/rollup.config.js b/test/cli/samples/watch/watch-config/rollup.config.js new file mode 100644 index 00000000000..2f5615a36b2 --- /dev/null +++ b/test/cli/samples/watch/watch-config/rollup.config.js @@ -0,0 +1,7 @@ +export default { + input: {output: "main4.js"}, + output: { + dir: "_actual", + format: "es" + } +}; \ No newline at end of file diff --git a/test/form/samples/supports-es5-shim/_expected.js b/test/form/samples/supports-es5-shim/_expected.js index 9256991f4c1..490bfa942b1 100644 --- a/test/form/samples/supports-es5-shim/_expected.js +++ b/test/form/samples/supports-es5-shim/_expected.js @@ -10,7 +10,7 @@ var es5Shim = createCommonjsModule(function (module, exports) { // see https://github.com/umdjs/umd/blob/master/templates/returnExports.js (function (root, factory) { - /* global define, exports, module */ + /* global define */ { // Node. Does not work with strict CommonJS, but // only CommonJS-like enviroments that support module.exports, @@ -54,7 +54,6 @@ var es5Shim = createCommonjsModule(function (module, exports) { // Having a toString local variable name breaks in Opera so use to_string. var to_string = ObjectPrototype.toString; - /* global Symbol */ /* eslint-disable one-var-declaration-per-line, no-redeclare, max-statements-per-line */ var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol'; var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, constructorRegex = /^\s*class /, isES6ClassFn = function isES6ClassFn(value) { try { var fnStr = fnToStr.call(value); var singleStripped = fnStr.replace(/\/\/.*\n/g, ''); var multiStripped = singleStripped.replace(/\/\*[.\s\S]*\*\//g, ''); var spaceStripped = multiStripped.replace(/\n/mg, ' ').replace(/ {2}/g, ' '); return constructorRegex.test(spaceStripped); } catch (e) { return false; /* not a function */ } }, tryFunctionObject = function tryFunctionObject(value) { try { if (isES6ClassFn(value)) { return false; } fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]', isCallable = function isCallable(value) { if (!value) { return false; } if (typeof value !== 'function' && typeof value !== 'object') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } if (isES6ClassFn(value)) { return false; } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; }; @@ -97,7 +96,7 @@ var es5Shim = createCommonjsModule(function (module, exports) { if (!forceAssign && (name in object)) { return; } - object[name] = method; + object[name] = method; // eslint-disable-line no-param-reassign }; } return function defineProperties(object, map, forceAssign) { @@ -812,7 +811,11 @@ var es5Shim = createCommonjsModule(function (module, exports) { var len = ES.ToUint32(O.length); var relativeStart = ES.ToInteger(start); var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len); - var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart); + var actualDeleteCount = arguments.length === 0 + ? 0 + : arguments.length === 1 + ? len - actualStart + : min(max(ES.ToInteger(deleteCount), 0), len - actualStart); var k = 0; var from; @@ -1442,7 +1445,6 @@ var es5Shim = createCommonjsModule(function (module, exports) { if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) { // XXX global assignment won't work in embeddings that use // an alternate object for the context. - /* global Date: true */ var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1; var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime()); // eslint-disable-next-line no-implicit-globals, no-global-assign @@ -1602,7 +1604,6 @@ var es5Shim = createCommonjsModule(function (module, exports) { return DateShim; }(Date)); - /* global Date: false */ } // ES5 15.9.4.4 @@ -1923,9 +1924,9 @@ var es5Shim = createCommonjsModule(function (module, exports) { var wrappedReplaceValue = function (match) { var length = arguments.length; var originalLastIndex = searchValue.lastIndex; - searchValue.lastIndex = 0; + searchValue.lastIndex = 0; // eslint-disable-line no-param-reassign var args = searchValue.exec(match) || []; - searchValue.lastIndex = originalLastIndex; + searchValue.lastIndex = originalLastIndex; // eslint-disable-line no-param-reassign pushCall(args, arguments[length - 2], arguments[length - 1]); return replaceValue.apply(this, args); }; @@ -2007,7 +2008,7 @@ var es5Shim = createCommonjsModule(function (module, exports) { // ES-5 15.1.2.2 // eslint-disable-next-line radix if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) { - /* global parseInt: true */ + // eslint-disable-next-line no-global-assign, no-implicit-globals parseInt = (function (origParseInt) { var hexRegex = /^[-+]?0[xX]/; return function parseInt(str, radix) { @@ -2026,7 +2027,7 @@ var es5Shim = createCommonjsModule(function (module, exports) { // https://es5.github.io/#x15.1.2.3 if (1 / parseFloat('-0') !== -Infinity) { - /* global parseFloat: true */ + // eslint-disable-next-line no-global-assign, no-implicit-globals, no-native-reassign parseFloat = (function (origParseFloat) { return function parseFloat(string) { var inputString = trim(String(string)); diff --git a/test/load-config-file/index.js b/test/load-config-file/index.js new file mode 100644 index 00000000000..9f3eeb112a1 --- /dev/null +++ b/test/load-config-file/index.js @@ -0,0 +1,44 @@ +const loadConfigFile = require('../../dist/loadConfigFile.js'); +const assert = require('assert'); +const path = require('path'); + +describe('loadConfigFile', () => { + it('loads a config file', async () => { + const { options, warnings } = await loadConfigFile( + path.resolve(__dirname, 'samples/basic/rollup.config.js') + ); + assert.strictEqual(warnings.count, 0); + assert.deepStrictEqual(JSON.parse(JSON.stringify(options)), [ + { + experimentalCacheExpiry: 10, + external: [], + inlineDynamicImports: false, + input: 'my-input', + output: [ + { + amd: {}, + compact: false, + esModule: true, + externalLiveBindings: true, + file: 'my-file', + format: 'es', + freeze: true, + hoistTransitiveImports: true, + indent: true, + interop: true, + namespaceToStringTag: false, + plugins: [], + strict: true, + }, + ], + perf: false, + plugins: [ + { + name: 'stdin', + }, + ], + strictDeprecations: false, + }, + ]); + }); +}); diff --git a/test/load-config-file/samples/basic/rollup.config.js b/test/load-config-file/samples/basic/rollup.config.js new file mode 100644 index 00000000000..93cadf7eab5 --- /dev/null +++ b/test/load-config-file/samples/basic/rollup.config.js @@ -0,0 +1,7 @@ +export default { + input: 'my-input', + output: { + file: 'my-file', + format: 'esm' + } +} diff --git a/test/test.js b/test/test.js index af4c00f7d90..f3950d9d94f 100644 --- a/test/test.js +++ b/test/test.js @@ -1,7 +1,6 @@ require('source-map-support').install(); -// require('console-group').install(); -describe('rollup', function() { +describe('rollup', function () { this.timeout(10000); require('./misc/index.js'); require('./function/index.js'); @@ -11,6 +10,7 @@ describe('rollup', function() { require('./sourcemaps/index.js'); require('./incremental/index.js'); require('./hooks/index.js'); + require('./load-config-file/index.js'); require('./cli/index.js'); require('./watch/index.js'); }); diff --git a/test/utils.js b/test/utils.js index 8049916d419..0b3fafbae31 100644 --- a/test/utils.js +++ b/test/utils.js @@ -190,7 +190,13 @@ function runTestsInDir(dir, runTest) { function loadConfigAndRunTest(dir, runTest) { const config = loadConfig(dir + '/_config.js'); - if (config && (!config.skipIfWindows || process.platform !== 'win32')) runTest(dir, config); + if ( + config && + (!config.skipIfWindows || process.platform !== 'win32') && + (!config.onlyWindows || process.platform === 'win32') && + (!config.minNodeVersion || config.minNodeVersion <= Number(/^v(\d+)/.exec(process.version)[1])) + ) + runTest(dir, config); } function assertDirectoriesAreEqual(actualDir, expectedDir) {