From 254fe4f8ade0956aa98f41aadf99f44bbab520a0 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Wed, 29 Jan 2020 11:40:15 +0100 Subject: [PATCH] [v2.0.0] Remove active deprecations (#3352) * Remove active deprecations * Make inactive deprecations active * Improve coverage * Improve coverage * Refine transformer * Improve coverage * Refactoring option normalization * Improve coverage --- cli/help.md | 1 - cli/run/index.ts | 16 +- cli/run/loadConfigFile.ts | 4 +- cli/run/watch.ts | 42 +- docs/05-plugin-development.md | 15 +- src/Chunk.ts | 1 - src/Graph.ts | 25 +- src/ast/nodes/MetaProperty.ts | 4 +- src/rollup/rollup.ts | 143 ++---- src/rollup/types.d.ts | 43 +- src/utils/FileEmitter.ts | 2 +- src/utils/PluginCache.ts | 38 +- src/utils/PluginContext.ts | 41 +- src/utils/PluginDriver.ts | 17 +- src/utils/error.ts | 3 +- src/utils/mergeOptions.ts | 274 ++---------- src/utils/parseOptions.ts | 212 +++++++++ src/utils/pluginUtils.ts | 6 +- src/utils/renderChunk.ts | 38 +- src/utils/timers.ts | 5 +- src/utils/transform.ts | 67 +-- src/watch/watch-proxy.ts | 2 +- src/watch/watch.ts | 7 +- .../deprecated/configure-asset-url/_config.js | 1 + .../_config.js | 1 + .../samples/deprecated/emit-asset/_config.js | 1 + .../deprecated/emit-chunk-existing/_config.js | 1 + .../deprecated/emit-chunk-facade/_config.js | 1 + .../deprecated/emit-chunk-named/_config.js | 1 + .../deprecated/emit-chunk-worker/_config.js | 1 + .../deprecated/emit-chunk-worklet/_config.js | 1 + .../samples/deprecated/emit-chunk/_config.js | 1 + .../dynamic-import-inlining-object/_config.js | 7 + .../_expected/amd/entry.js | 17 + .../_expected/cjs/entry.js | 15 + .../_expected/es/entry.js | 11 + .../_expected/system/entry.js | 18 + .../dynamic-import-inlining-object/foo.js | 1 + .../dynamic-import-inlining-object/main.js | 2 + .../rollup-config-foo/lib/config.js | 11 - .../rollup-config-foo/package.json | 3 - .../bar}/lib/config.js | 0 .../bar}/package.json | 0 .../node_modules_rename_me/foo/lib/config.js | 11 - .../node_modules_rename_me/foo/package.json | 3 - .../duplicate-import-options/_config.js | 10 + .../samples/duplicate-import-options/main.js | 1 + .../external-modules-auto-global/_config.js | 10 +- .../external-modules-auto-global/main.js | 2 + test/cli/samples/external-modules/_config.js | 9 +- .../merge-deprecations/rollup.config.js | 2 - .../node-config-auto-prefix/_config.js | 2 +- .../samples/node-config-not-found/_config.js | 10 + .../node-config-not-found/_expected.js | 11 + .../cli/samples/node-config-not-found/main.js | 1 + test/cli/samples/node-config/_config.js | 2 +- .../warn-unknown-options/rollup.config.js | 2 +- .../deprecated/configure-asset-url/_config.js | 1 + .../deprecated/emit-asset-hacky/_config.js | 1 + .../samples/deprecated/emit-asset/_config.js | 1 + .../prune-pure-unused-import-array/_config.js | 1 + .../_config.js | 2 +- .../prune-pure-unused-import/_config.js | 2 +- .../_config.js | 20 - .../_expected/amd.js | 1 - .../_expected/cjs.js | 1 - .../_expected/es.js | 1 - .../_expected/iife.js | 1 - .../_expected/system.js | 1 - .../_expected/umd.js | 1 - .../transform-bundle-plugin-options/main.js | 1 - .../transform-bundle-plugin/_config.js | 19 - .../transform-bundle-plugin/_expected/amd.js | 2 - .../transform-bundle-plugin/_expected/cjs.js | 2 - .../transform-bundle-plugin/_expected/es.js | 2 - .../transform-bundle-plugin/_expected/iife.js | 2 - .../_expected/system.js | 2 - .../transform-bundle-plugin/_expected/umd.js | 2 - .../transform-bundle-plugin/main.js | 1 - .../dynamic-import-inlining-array/_config.js | 7 + .../_expected.js | 11 + .../dynamic-import-inlining-array/foo.js | 1 + .../dynamic-import-inlining-array/main.js | 2 + .../samples/banner-and-footer/_config.js | 6 +- .../samples/default-on-warn/_config.js | 27 ++ test/function/samples/default-on-warn/main.js | 2 + .../bundle-transformer-async/_config.js | 43 -- .../bundle-transformer-async/main.js | 1 - .../deprecated/context-resolve-id/_config.js | 20 +- .../deprecated/emit-chunk/no-input/_config.js | 10 +- .../_config.js | 8 +- .../_config.js | 26 -- .../main.js | 1 - .../deprecations/ongenerate/_config.js | 14 - .../samples/deprecations/ongenerate/main.js | 11 - .../samples/deprecations/onwrite/_config.js | 14 - .../samples/deprecations/onwrite/main.js | 11 - .../transform-dependencies/_config.js | 22 - .../transform-dependencies/main.js | 11 - .../deprecations/transformBundle/_config.js | 16 - .../deprecations/transformBundle/main.js | 11 - .../deprecations/transformChunk/_config.js | 16 - .../deprecations/transformChunk/main.js | 11 - .../dynamic-import-duplicates/_config.js | 10 +- .../dynamic-import-existing/_config.js | 10 - .../dynamic-import-expression/_config.js | 2 +- .../dynamic-import-inlining/_config.js | 10 +- .../dynamic-import-rewriting/_config.js | 2 +- .../samples/fallback-on-warn/_config.js | 20 + .../function/samples/fallback-on-warn/main.js | 1 + .../_config.js | 2 +- .../lib.js | 0 .../main.js | 0 .../_config.js | 11 + .../lib.js | 1 + .../main.js | 1 + test/function/samples/plugin-warn/_config.js | 7 +- .../warns-for-invalid-options/_config.js | 23 + .../samples/warns-for-invalid-options/main.js | 1 + test/hooks/index.js | 257 ++--------- test/misc/deprecations.js | 24 - test/misc/sanity-checks.js | 26 +- test/misc/write-bundle.js | 22 - .../deprecated/names-transformed/_config.js | 71 --- .../samples/deprecated/names-transformed/a.js | 4 - .../samples/deprecated/names-transformed/b.js | 4 - .../deprecated/names-transformed/main.js | 5 - .../transform-bundle-babili/_config.js | 45 -- .../transform-bundle-babili/babili-results.js | 5 - .../transform-bundle-babili/main.js | 1 - .../deprecated/transform-bundle/_config.js | 48 -- .../deprecated/transform-bundle/main.js | 1 - .../transform-without-sourcemap/_config.js | 37 -- .../transform-without-sourcemap/main.js | 1 - test/watch/index.js | 417 ++---------------- test/watch/samples/dependencies/dep1.js | 1 + test/watch/samples/dependencies/dep2.js | 1 + test/watch/samples/dependencies/main.js | 3 + 138 files changed, 724 insertions(+), 1895 deletions(-) create mode 100644 src/utils/parseOptions.ts create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/_config.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/_expected/amd/entry.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/_expected/cjs/entry.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/_expected/es/entry.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/_expected/system/entry.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/foo.js create mode 100644 test/chunking-form/samples/dynamic-import-inlining-object/main.js delete mode 100644 test/cli/node_modules/rollup-config-foo/lib/config.js delete mode 100644 test/cli/node_modules/rollup-config-foo/package.json rename test/cli/{node_modules/foo => node_modules_rename_me/bar}/lib/config.js (100%) rename test/cli/{node_modules/foo => node_modules_rename_me/bar}/package.json (100%) delete mode 100644 test/cli/node_modules_rename_me/foo/lib/config.js delete mode 100644 test/cli/node_modules_rename_me/foo/package.json create mode 100644 test/cli/samples/duplicate-import-options/_config.js create mode 100644 test/cli/samples/duplicate-import-options/main.js create mode 100644 test/cli/samples/node-config-not-found/_config.js create mode 100644 test/cli/samples/node-config-not-found/_expected.js create mode 100644 test/cli/samples/node-config-not-found/main.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_config.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/amd.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/cjs.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/es.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/iife.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/system.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/_expected/umd.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin-options/main.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_config.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/amd.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/cjs.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/es.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/iife.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/system.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/_expected/umd.js delete mode 100644 test/form/samples/deprecated/transform-bundle-plugin/main.js create mode 100644 test/form/samples/dynamic-import-inlining-array/_config.js create mode 100644 test/form/samples/dynamic-import-inlining-array/_expected.js create mode 100644 test/form/samples/dynamic-import-inlining-array/foo.js create mode 100644 test/form/samples/dynamic-import-inlining-array/main.js create mode 100644 test/function/samples/default-on-warn/_config.js create mode 100644 test/function/samples/default-on-warn/main.js delete mode 100644 test/function/samples/deprecated/bundle-transformer-async/_config.js delete mode 100644 test/function/samples/deprecated/bundle-transformer-async/main.js delete mode 100644 test/function/samples/deprecated/plugin-error-only-first-transform-bundle/_config.js delete mode 100644 test/function/samples/deprecated/plugin-error-only-first-transform-bundle/main.js delete mode 100644 test/function/samples/deprecations/ongenerate/_config.js delete mode 100644 test/function/samples/deprecations/ongenerate/main.js delete mode 100644 test/function/samples/deprecations/onwrite/_config.js delete mode 100644 test/function/samples/deprecations/onwrite/main.js delete mode 100644 test/function/samples/deprecations/transform-dependencies/_config.js delete mode 100644 test/function/samples/deprecations/transform-dependencies/main.js delete mode 100644 test/function/samples/deprecations/transformBundle/_config.js delete mode 100644 test/function/samples/deprecations/transformBundle/main.js delete mode 100644 test/function/samples/deprecations/transformChunk/_config.js delete mode 100644 test/function/samples/deprecations/transformChunk/main.js create mode 100644 test/function/samples/fallback-on-warn/_config.js create mode 100644 test/function/samples/fallback-on-warn/main.js rename test/function/samples/{inline-imports-with-multiple => inline-imports-with-multiple-array}/_config.js (68%) rename test/function/samples/{inline-imports-with-multiple => inline-imports-with-multiple-array}/lib.js (100%) rename test/function/samples/{inline-imports-with-multiple => inline-imports-with-multiple-array}/main.js (100%) create mode 100644 test/function/samples/inline-imports-with-multiple-object/_config.js create mode 100644 test/function/samples/inline-imports-with-multiple-object/lib.js create mode 100644 test/function/samples/inline-imports-with-multiple-object/main.js create mode 100644 test/function/samples/warns-for-invalid-options/_config.js create mode 100644 test/function/samples/warns-for-invalid-options/main.js delete mode 100644 test/sourcemaps/samples/deprecated/names-transformed/_config.js delete mode 100644 test/sourcemaps/samples/deprecated/names-transformed/a.js delete mode 100644 test/sourcemaps/samples/deprecated/names-transformed/b.js delete mode 100644 test/sourcemaps/samples/deprecated/names-transformed/main.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-bundle-babili/_config.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-bundle-babili/babili-results.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-bundle-babili/main.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-bundle/_config.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-bundle/main.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js delete mode 100644 test/sourcemaps/samples/deprecated/transform-without-sourcemap/main.js create mode 100644 test/watch/samples/dependencies/dep1.js create mode 100644 test/watch/samples/dependencies/dep2.js create mode 100644 test/watch/samples/dependencies/main.js diff --git a/cli/help.md b/cli/help.md index 0e7520d1ae2..644278ab178 100644 --- a/cli/help.md +++ b/cli/help.md @@ -55,7 +55,6 @@ Basic options: --no-treeshake Disable tree-shaking optimisations --no-treeshake.annotations Ignore pure call annotations --no-treeshake.propertyReadSideEffects Ignore property access side-effects ---treeshake.pureExternalModules Assume side-effect free externals Examples: diff --git a/cli/run/index.ts b/cli/run/index.ts index d44a32a101b..dc6616ce064 100644 --- a/cli/run/index.ts +++ b/cli/run/index.ts @@ -1,7 +1,7 @@ import { realpathSync } from 'fs'; import relative from 'require-relative'; -import { WarningHandler } from '../../src/rollup/types'; -import mergeOptions, { GenericConfigObject } from '../../src/utils/mergeOptions'; +import { mergeOptions } from '../../src/utils/mergeOptions'; +import { GenericConfigObject } from '../../src/utils/parseOptions'; import { getAliasName } from '../../src/utils/relativeId'; import { handleError } from '../logging'; import batchWarnings from './batchWarnings'; @@ -16,7 +16,7 @@ export default function runRollup(command: any) { if (command.input) { handleError({ code: 'DUPLICATE_IMPORT_OPTIONS', - message: 'use --input, or pass input path as argument' + message: 'Either use --input, or pass input path as argument' }); } inputSource = command._; @@ -107,14 +107,8 @@ async function execute( } else { for (const config of configs) { const warnings = batchWarnings(); - const { inputOptions, outputOptions, optionError } = mergeOptions({ - command, - config, - defaultOnWarnHandler: warnings.add - }); - if (optionError) { - (inputOptions.onwarn as WarningHandler)({ code: 'UNKNOWN_OPTION', message: optionError }); - } + const { inputOptions, outputOptions } = mergeOptions(config, command, + warnings.add); if (command.stdin !== false) { inputOptions.plugins!.push(stdinPlugin()); } diff --git a/cli/run/loadConfigFile.ts b/cli/run/loadConfigFile.ts index da7a911fc95..c9e02d1160a 100644 --- a/cli/run/loadConfigFile.ts +++ b/cli/run/loadConfigFile.ts @@ -2,7 +2,7 @@ import path from 'path'; import tc from 'turbocolor'; import * as rollup from '../../src/node-entry'; import { RollupBuild, RollupOutput } from '../../src/rollup/types'; -import { GenericConfigObject } 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'; @@ -73,4 +73,4 @@ export default function loadConfigFile( return Array.isArray(configs) ? configs : [configs]; }); }); -} \ No newline at end of file +} diff --git a/cli/run/watch.ts b/cli/run/watch.ts index e437c71abc9..9397eb73948 100644 --- a/cli/run/watch.ts +++ b/cli/run/watch.ts @@ -4,12 +4,9 @@ import ms from 'pretty-ms'; import onExit from 'signal-exit'; import tc from 'turbocolor'; import * as rollup from '../../src/node-entry'; -import { - RollupWatcher, - RollupWatchOptions, - WarningHandler -} from '../../src/rollup/types'; -import mergeOptions, { GenericConfigObject } from '../../src/utils/mergeOptions'; +import { RollupWatcher, RollupWatchOptions } from '../../src/rollup/types'; +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'; @@ -26,9 +23,7 @@ export default function watch( const isTTY = Boolean(process.stderr.isTTY); const warnings = batchWarnings(); const initialConfigs = processConfigs(configs); - const clearScreen = initialConfigs.every( - config => config.watch!.clearScreen !== false - ); + const clearScreen = initialConfigs.every(config => config.watch!.clearScreen !== false); const resetScreen = getResetScreen(isTTY && clearScreen); let watcher: RollupWatcher; @@ -36,25 +31,12 @@ export default function watch( function processConfigs(configs: GenericConfigObject[]): RollupWatchOptions[] { return configs.map(options => { - const merged = mergeOptions({ - command, - config: options, - defaultOnWarnHandler: warnings.add - }); - + const { inputOptions, outputOptions } = mergeOptions(options, command, warnings.add); const result: RollupWatchOptions = { - ...merged.inputOptions, - output: merged.outputOptions + ...inputOptions, + output: outputOptions }; - if (!result.watch) result.watch = {}; - - if (merged.optionError) - (merged.inputOptions.onwarn as WarningHandler)({ - code: 'UNKNOWN_OPTION', - message: merged.optionError - }); - return result; }); } @@ -87,9 +69,7 @@ export default function watch( } stderr( tc.cyan( - `bundles ${tc.bold(input)} → ${tc.bold( - event.output.map(relativeId).join(', ') - )}...` + `bundles ${tc.bold(input)} → ${tc.bold(event.output.map(relativeId).join(', '))}...` ) ); } @@ -100,9 +80,9 @@ export default function watch( if (!silent) stderr( tc.green( - `created ${tc.bold( - event.output.map(relativeId).join(', ') - )} in ${tc.bold(ms(event.duration))}` + `created ${tc.bold(event.output.map(relativeId).join(', '))} in ${tc.bold( + ms(event.duration) + )}` ) ); if (event.result && event.result.getTimings) { diff --git a/docs/05-plugin-development.md b/docs/05-plugin-development.md index 7b2a6562472..3a5bf662c4e 100644 --- a/docs/05-plugin-development.md +++ b/docs/05-plugin-development.md @@ -397,22 +397,9 @@ Called only at the end of `bundle.write()` once all files have been written. Sim ☢️ These hooks have been deprecated and may be removed in a future Rollup version. -- `ongenerate` - _**Use [`generateBundle`](guide/en/#generatebundle)**_ - Function hook -called when `bundle.generate()` is being executed. - -- `onwrite` - _**Use [`generateBundle`](guide/en/#generatebundle)**_ - Function hook -called when `bundle.write()` is being executed, after the file has been written -to disk. - - `resolveAssetUrl` - _**Use [`resolveFileUrl`](guide/en/#resolvefileurl)**_ - Function hook that allows to customize the generated code for asset URLs. -- `transformBundle` – _**Use [`renderChunk`](guide/en/#renderchunk)**_ - A `( source, { format } ) => -code` or `( source, { format } ) => { code, map }` bundle transformer function. - -- `transformChunk` – _**Use [`renderChunk`](guide/en/#renderchunk)**_ - A `( source, outputOptions, -chunk ) => code | { code, map}` chunk transformer function. - -More properties may be supported in future, as and when they prove necessary. +More properties may be supported in the future, as and when they prove necessary. ### Plugin Context diff --git a/src/Chunk.ts b/src/Chunk.ts index 59fc3a0f8d3..e4e28ffbad9 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -733,7 +733,6 @@ export default class Chunk { const chunkSourcemapChain: DecodedSourceMapOrMissing[] = []; return renderChunk({ - chunk: this, code: prevCode, options, outputPluginDriver, diff --git a/src/Graph.ts b/src/Graph.ts index e8285ed260f..23589c518d7 100644 --- a/src/Graph.ts +++ b/src/Graph.ts @@ -30,17 +30,6 @@ import { PluginDriver } from './utils/PluginDriver'; import relativeId from './utils/relativeId'; import { timeEnd, timeStart } from './utils/timers'; -function makeOnwarn() { - const warned = Object.create(null); - - return (warning: any) => { - const str = warning.toString(); - if (str in warned) return; - console.error(str); - warned[str] = true; - }; -} - function normalizeEntryModules( entryModules: string | string[] | Record ): UnresolvedModule[] { @@ -84,7 +73,7 @@ export default class Graph { private strictDeprecations: boolean; constructor(options: InputOptions, watcher: RollupWatcher | null) { - this.onwarn = (options.onwarn as WarningHandler) || makeOnwarn(); + this.onwarn = options.onwarn as WarningHandler; this.deoptimizationTracker = new PathTracker(); this.cachedModules = new Map(); if (options.cache) { @@ -126,7 +115,7 @@ export default class Graph { if (typeof this.treeshakingOptions.pureExternalModules !== 'undefined') { this.warnDeprecation( `The "treeshake.pureExternalModules" option is deprecated. The "treeshake.moduleSideEffects" option should be used instead. "treeshake.pureExternalModules: true" is equivalent to "treeshake.moduleSideEffects: 'no-external'"`, - false + true ); } } @@ -142,8 +131,7 @@ export default class Graph { this, options.plugins!, this.pluginCache, - options.preserveSymlinks === true, - watcher + options.preserveSymlinks === true ); if (watcher) { @@ -240,13 +228,6 @@ export default class Graph { // Phase 3 – marking. We include all statements that should be included timeStart('mark included statements', 2); - if (inlineDynamicImports) { - if (entryModules.length > 1) { - throw new Error( - 'Internal Error: can only inline dynamic imports for single-file builds.' - ); - } - } for (const module of entryModules) { module.includeAllExports(); } diff --git a/src/ast/nodes/MetaProperty.ts b/src/ast/nodes/MetaProperty.ts index 7a9d68674fe..3b29cb38b4d 100644 --- a/src/ast/nodes/MetaProperty.ts +++ b/src/ast/nodes/MetaProperty.ts @@ -80,14 +80,14 @@ export default class MetaProperty extends NodeBase { } else if (metaProperty.startsWith(ASSET_PREFIX)) { this.context.warnDeprecation( `Using the "${ASSET_PREFIX}" prefix to reference files is deprecated. Use the "${FILE_PREFIX}" prefix instead.`, - false + true ); assetReferenceId = metaProperty.substr(ASSET_PREFIX.length); fileName = outputPluginDriver.getFileName(assetReferenceId); } else { this.context.warnDeprecation( `Using the "${CHUNK_PREFIX}" prefix to reference files is deprecated. Use the "${FILE_PREFIX}" prefix instead.`, - false + true ); chunkReferenceId = metaProperty.substr(CHUNK_PREFIX.length); fileName = outputPluginDriver.getFileName(chunkReferenceId); diff --git a/src/rollup/rollup.ts b/src/rollup/rollup.ts index fca26101ae4..cf965527798 100644 --- a/src/rollup/rollup.ts +++ b/src/rollup/rollup.ts @@ -5,15 +5,15 @@ import Graph from '../Graph'; import { createAddons } from '../utils/addons'; import { assignChunkIds } from '../utils/assignChunkIds'; import commondir from '../utils/commondir'; -import { - errCannotEmitFromOptionsHook, - errDeprecation, - errInvalidExportOptionValue, - error -} from '../utils/error'; +import { errCannotEmitFromOptionsHook, errInvalidExportOptionValue, error } from '../utils/error'; import { writeFile } from '../utils/fs'; import getExportMode from '../utils/getExportMode'; -import mergeOptions, { ensureArray, GenericConfigObject } from '../utils/mergeOptions'; +import { + ensureArray, + GenericConfigObject, + parseInputOptions, + parseOutputOptions +} from '../utils/parseOptions'; import { basename, dirname, isAbsolute, resolve } from '../utils/path'; import { PluginDriver } from '../utils/PluginDriver'; import { ANONYMOUS_OUTPUT_PLUGIN_PREFIX, ANONYMOUS_PLUGIN_PREFIX } from '../utils/pluginUtils'; @@ -34,15 +34,6 @@ import { } from './types'; function checkOutputOptions(options: OutputOptions) { - if ((options.format as string) === 'es6') { - return error( - errDeprecation({ - message: 'The "es6" output format is deprecated – use "esm" instead', - url: `https://rollupjs.org/guide/en/#output-format` - }) - ); - } - if (['amd', 'cjs', 'system', 'es', 'iife', 'umd'].indexOf(options.format as string) < 0) { return error({ message: `You must specify "output.format", which can be one of "amd", "cjs", "system", "esm", "iife" or "umd".`, @@ -67,12 +58,6 @@ function getAbsoluteEntryModulePaths(chunks: Chunk[]): string[] { return absoluteEntryModulePaths; } -const throwAsyncGenerateError = { - get() { - throw new Error(`bundle.generate(...) now returns a Promise instead of a { code, map } object`); - } -}; - function applyOptionHook(inputOptions: InputOptions, plugin: Plugin) { if (plugin.options) return plugin.options.call({ meta: { rollupVersion } }, inputOptions) || inputOptions; @@ -95,13 +80,7 @@ function getInputOptions(rawInputOptions: GenericConfigObject): InputOptions { if (!rawInputOptions) { throw new Error('You must supply an options object to rollup'); } - let { inputOptions, optionError } = mergeOptions({ - config: rawInputOptions - }); - - if (optionError) - (inputOptions.onwarn as WarningHandler)({ message: optionError, code: 'UNKNOWN_OPTION' }); - + let inputOptions = parseInputOptions(rawInputOptions); inputOptions = inputOptions.plugins!.reduce(applyOptionHook, inputOptions); inputOptions.plugins = normalizePlugins(inputOptions.plugins!, ANONYMOUS_PLUGIN_PREFIX); @@ -287,11 +266,6 @@ export async function rollupInternal( .then(rendered => { outputChunk.code = rendered.code; outputChunk.map = rendered.map; - - return outputPluginDriver.hookParallel('ongenerate', [ - { bundle: outputChunk, ...outputOptions }, - outputChunk - ]); }); }) ); @@ -305,7 +279,7 @@ export async function rollupInternal( if (!file.type) { graph.warnDeprecation( 'A plugin is directly adding properties to the bundle object in the "generateBundle" hook. This is deprecated and will be removed in a future Rollup version, please use "this.emitFile" instead.', - false + true ); file.type = 'asset'; } @@ -319,21 +293,18 @@ export async function rollupInternal( const cache = useCache ? graph.getCache() : undefined; const result: RollupBuild = { cache: cache!, - generate: ((rawOutputOptions: GenericConfigObject) => { + generate: (rawOutputOptions: OutputOptions) => { const { outputOptions, outputPluginDriver } = getOutputOptionsAndPluginDriver( - rawOutputOptions + rawOutputOptions as GenericConfigObject ); - const promise = generate(outputOptions, false, outputPluginDriver).then(result => + return generate(outputOptions, false, outputPluginDriver).then(result => createOutput(result) ); - Object.defineProperty(promise, 'code', throwAsyncGenerateError); - Object.defineProperty(promise, 'map', throwAsyncGenerateError); - return promise; - }) as any, + }, watchFiles: Object.keys(graph.watchFiles), - write: ((rawOutputOptions: GenericConfigObject) => { + write: (rawOutputOptions: OutputOptions) => { const { outputOptions, outputPluginDriver } = getOutputOptionsAndPluginDriver( - rawOutputOptions + rawOutputOptions as GenericConfigObject ); if (!outputOptions.dir && !outputOptions.file) { return error({ @@ -342,39 +313,13 @@ export async function rollupInternal( }); } return generate(outputOptions, true, outputPluginDriver).then(async bundle => { - let chunkCount = 0; - for (const fileName of Object.keys(bundle)) { - const file = bundle[fileName]; - if (file.type === 'asset') continue; - chunkCount++; - if (chunkCount > 1) break; - } - if (chunkCount > 1) { - if (outputOptions.sourcemapFile) - return error({ - code: 'INVALID_OPTION', - message: '"output.sourcemapFile" is only supported for single-file builds.' - }); - if (typeof outputOptions.file === 'string') - return error({ - code: 'INVALID_OPTION', - message: - 'When building multiple chunks, the "output.dir" option must be used, not "output.file".' + - (typeof inputOptions.input !== 'string' || - inputOptions.inlineDynamicImports === true - ? '' - : ' To inline dynamic imports, set the "inlineDynamicImports" option.') - }); - } await Promise.all( - Object.keys(bundle).map(chunkId => - writeOutputFile(result, bundle[chunkId], outputOptions, outputPluginDriver) - ) + Object.keys(bundle).map(chunkId => writeOutputFile(bundle[chunkId], outputOptions)) ); await outputPluginDriver.hookParallel('writeBundle', [bundle]); return createOutput(bundle); }); - }) as any + } }; if (inputOptions.perf === true) result.getTimings = getTimings; return result; @@ -413,13 +358,11 @@ function createOutput(outputBundle: Record { + outputOptions: OutputOptions +): Promise { const fileName = resolve(outputOptions.dir || dirname(outputOptions.file!), outputFile.fileName); - let writeSourceMapPromise: Promise; + let writeSourceMapPromise: Promise | undefined; let source: string | Buffer; if (outputFile.type === 'asset') { source = outputFile.source; @@ -439,20 +382,7 @@ function writeOutputFile( } } - return writeFile(fileName, source) - .then(() => writeSourceMapPromise) - .then( - (): any => - outputFile.type === 'chunk' && - outputPluginDriver.hookSeq('onwrite', [ - { - bundle: build, - ...outputOptions - }, - outputFile - ]) - ) - .then(() => {}); + return Promise.all([writeFile(fileName, source), writeSourceMapPromise]); } function normalizeOutputOptions( @@ -461,25 +391,16 @@ function normalizeOutputOptions( hasMultipleChunks: boolean, outputPluginDriver: PluginDriver ): OutputOptions { - const mergedOptions = mergeOptions({ - config: { - output: { - ...rawOutputOptions, - ...(rawOutputOptions.output as object), - ...(inputOptions.output as object) - } - } - }); - - if (mergedOptions.optionError) throw new Error(mergedOptions.optionError); - - // now outputOptions is an array, but rollup.rollup API doesn't support arrays - const mergedOutputOptions = mergedOptions.outputOptions[0]; + const outputOptionBase = rawOutputOptions.output || inputOptions.output || rawOutputOptions; + let outputOptions = parseOutputOptions( + outputOptionBase as GenericConfigObject, + inputOptions.onwarn as WarningHandler + ); const outputOptionsReducer = (outputOptions: OutputOptions, result: OutputOptions) => result || outputOptions; - const outputOptions = outputPluginDriver.hookReduceArg0Sync( + outputOptions = outputPluginDriver.hookReduceArg0Sync( 'outputOptions', - [mergedOutputOptions], + [outputOptions], outputOptionsReducer, pluginContext => { const emitError = () => pluginContext.error(errCannotEmitFromOptionsHook()); @@ -524,7 +445,13 @@ function normalizeOutputOptions( return error({ code: 'INVALID_OPTION', message: - 'You must set "output.dir" instead of "output.file" when generating multiple chunks.' + 'When building multiple chunks, the "output.dir" option must be used, not "output.file". ' + + 'To inline dynamic imports, set the "inlineDynamicImports" option.' + }); + if (outputOptions.sourcemapFile) + return error({ + code: 'INVALID_OPTION', + message: '"output.sourcemapFile" is only supported for single-file builds.' }); } diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 1c520256a5b..df1e4c9468c 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -1,5 +1,4 @@ import * as ESTree from 'estree'; -import { EventEmitter } from 'events'; export const VERSION: string; @@ -96,10 +95,6 @@ export interface SourceDescription { syntheticNamedExports?: boolean; } -export interface TransformSourceDescription extends SourceDescription { - dependencies?: string[]; -} - export interface TransformModuleJSON { ast: ESTree.Program; code: string; @@ -189,8 +184,6 @@ export interface PluginContext extends MinimalPluginContext { resolveId: (source: string, importer: string) => Promise; setAssetSource: (assetReferenceId: string, source: string | Buffer) => void; warn: (warning: RollupWarning | string, pos?: number | { column: number; line: number }) => void; - /** @deprecated Use `this.addWatchFile` and the `watchChange` hook instead */ - watcher: EventEmitter; } export interface PluginContextMeta { @@ -237,7 +230,7 @@ type LoadResult = SourceDescription | string | null | undefined; export type LoadHook = (this: PluginContext, id: string) => Promise | LoadResult; -export type TransformResult = string | null | undefined | TransformSourceDescription; +export type TransformResult = string | null | undefined | SourceDescription; export type TransformHook = ( this: PluginContext, @@ -245,16 +238,6 @@ export type TransformHook = ( id: string ) => Promise | TransformResult; -export type TransformChunkHook = ( - this: PluginContext, - code: string, - options: OutputOptions -) => - | Promise<{ code: string; map?: SourceMapInput } | null | undefined> - | { code: string; map?: SourceMapInput } - | null - | undefined; - export type RenderChunkHook = ( this: PluginContext, code: string, @@ -329,14 +312,6 @@ export interface OutputBundleWithPlaceholders { [fileName: string]: OutputAsset | OutputChunk | FilePlaceholder; } -interface OnGenerateOptions extends OutputOptions { - bundle: OutputChunk; -} - -interface OnWriteOptions extends OutputOptions { - bundle: RollupBuild; -} - interface OutputPluginHooks { augmentChunkHash: (this: PluginContext, chunk: PreRenderedChunk) => string | void; generateBundle: ( @@ -345,18 +320,6 @@ interface OutputPluginHooks { bundle: OutputBundle, isWrite: boolean ) => void | Promise; - /** @deprecated Use `generateBundle` instead */ - ongenerate: ( - this: PluginContext, - options: OnGenerateOptions, - chunk: OutputChunk - ) => void | Promise; - /** @deprecated Use `writeBundle` instead */ - onwrite: ( - this: PluginContext, - options: OnWriteOptions, - chunk: OutputChunk - ) => void | Promise; outputOptions: (this: PluginContext, options: OutputOptions) => OutputOptions | null | undefined; renderChunk: RenderChunkHook; renderError: (this: PluginContext, err?: Error) => Promise | void; @@ -369,10 +332,6 @@ interface OutputPluginHooks { resolveAssetUrl: ResolveAssetUrlHook; resolveDynamicImport: ResolveDynamicImportHook; resolveFileUrl: ResolveFileUrlHook; - /** @deprecated Use `renderChunk` instead */ - transformBundle: TransformChunkHook; - /** @deprecated Use `renderChunk` instead */ - transformChunk: TransformChunkHook; writeBundle: (this: PluginContext, bundle: OutputBundle) => void | Promise; } diff --git a/src/utils/FileEmitter.ts b/src/utils/FileEmitter.ts index d12ddc9b435..39d0b972256 100644 --- a/src/utils/FileEmitter.ts +++ b/src/utils/FileEmitter.ts @@ -330,7 +330,7 @@ export class FileEmitter { get isAsset(): true { graph.warnDeprecation( 'Accessing "isAsset" on files in the bundle is deprecated, please use "type === \'asset\'" instead', - false + true ); return true; diff --git a/src/utils/PluginCache.ts b/src/utils/PluginCache.ts index 54feb3cbcf6..ecd51148847 100644 --- a/src/utils/PluginCache.ts +++ b/src/utils/PluginCache.ts @@ -25,29 +25,25 @@ export function createPluginCache(cache: SerializablePluginCache): PluginCache { }; } -export function getTrackedPluginCache(pluginCache: PluginCache) { - const trackedCache = { - cache: { - has(id: string) { - trackedCache.used = true; - return pluginCache.has(id); - }, - get(id: string) { - trackedCache.used = true; - return pluginCache.get(id); - }, - set(id: string, value: any) { - trackedCache.used = true; - return pluginCache.set(id, value); - }, - delete(id: string) { - trackedCache.used = true; - return pluginCache.delete(id); - } +export function getTrackedPluginCache(pluginCache: PluginCache, onUse: () => void): PluginCache { + return { + has(id: string) { + onUse(); + return pluginCache.has(id); + }, + get(id: string) { + onUse(); + return pluginCache.get(id); }, - used: false + set(id: string, value: any) { + onUse(); + return pluginCache.set(id, value); + }, + delete(id: string) { + onUse(); + return pluginCache.delete(id); + } }; - return trackedCache; } export const NO_CACHE: PluginCache = { diff --git a/src/utils/PluginContext.ts b/src/utils/PluginContext.ts index 5b2f14ec1cf..449bb51917d 100644 --- a/src/utils/PluginContext.ts +++ b/src/utils/PluginContext.ts @@ -1,4 +1,3 @@ -import { EventEmitter } from 'events'; import { version as rollupVersion } from 'package.json'; import ExternalModule from '../ExternalModule'; import Graph from '../Graph'; @@ -8,7 +7,6 @@ import { PluginCache, PluginContext, RollupWarning, - RollupWatcher, SerializablePluginCache } from '../rollup/types'; import { BuildPhase } from './buildPhase'; @@ -48,8 +46,7 @@ function getDeprecatedContextHandler( export function getPluginContexts( pluginCache: Record | void, graph: Graph, - fileEmitter: FileEmitter, - watcher: RollupWatcher | null + fileEmitter: FileEmitter ): (plugin: Plugin, pluginIndex: number) => PluginContext { const existingPluginNames = new Set(); return (plugin, pidx) => { @@ -92,7 +89,7 @@ export function getPluginContexts( 'emitAsset', 'emitFile', plugin.name, - false, + true, graph ), emitChunk: getDeprecatedContextHandler( @@ -101,7 +98,7 @@ export function getPluginContexts( 'emitChunk', 'emitFile', plugin.name, - false, + true, graph ), emitFile: fileEmitter.emitFile, @@ -113,7 +110,7 @@ export function getPluginContexts( 'getAssetFileName', 'getFileName', plugin.name, - false, + true, graph ), getChunkFileName: getDeprecatedContextHandler( @@ -121,7 +118,7 @@ export function getPluginContexts( 'getChunkFileName', 'getFileName', plugin.name, - false, + true, graph ), getFileName: fileEmitter.getFileName, @@ -148,7 +145,7 @@ export function getPluginContexts( 'isExternal', 'resolve', plugin.name, - false, + true, graph ), meta: { @@ -173,7 +170,7 @@ export function getPluginContexts( 'resolveId', 'resolve', plugin.name, - false, + true, graph ), setAssetSource: fileEmitter.setAssetSource, @@ -183,29 +180,7 @@ export function getPluginContexts( warning.code = 'PLUGIN_WARNING'; warning.plugin = plugin.name; graph.warn(warning); - }, - watcher: watcher - ? (() => { - let deprecationWarningShown = false; - - function deprecatedWatchListener(event: string, handler: () => void): EventEmitter { - if (!deprecationWarningShown) { - context.warn({ - code: 'PLUGIN_WATCHER_DEPRECATED', - message: `this.watcher usage is deprecated in plugins. Use the watchChange plugin hook and this.addWatchFile() instead.` - }); - deprecationWarningShown = true; - } - return watcher!.on(event as any, handler); - } - - return { - ...(watcher as EventEmitter), - addListener: deprecatedWatchListener, - on: deprecatedWatchListener - }; - })() - : (undefined as any) + } }; return context; }; diff --git a/src/utils/PluginDriver.ts b/src/utils/PluginDriver.ts index a3003de71af..0879bf14b5b 100644 --- a/src/utils/PluginDriver.ts +++ b/src/utils/PluginDriver.ts @@ -5,7 +5,6 @@ import { Plugin, PluginContext, PluginHooks, - RollupWatcher, SerializablePluginCache } from '../rollup/types'; import { getRollupDefaultPlugin } from './defaultPlugin'; @@ -36,21 +35,18 @@ export class PluginDriver { private plugins: Plugin[]; private preserveSymlinks: boolean; private previousHooks = new Set(['options']); - private watcher: RollupWatcher | null; constructor( graph: Graph, userPlugins: Plugin[], pluginCache: Record | undefined, preserveSymlinks: boolean, - watcher: RollupWatcher | null, basePluginDriver?: PluginDriver ) { warnDeprecatedHooks(userPlugins, graph); this.graph = graph; this.pluginCache = pluginCache; this.preserveSymlinks = preserveSymlinks; - this.watcher = watcher; this.fileEmitter = new FileEmitter(graph, basePluginDriver && basePluginDriver.fileEmitter); this.emitFile = this.fileEmitter.emitFile; this.getFileName = this.fileEmitter.getFileName; @@ -59,9 +55,7 @@ export class PluginDriver { this.plugins = userPlugins.concat( basePluginDriver ? basePluginDriver.plugins : [getRollupDefaultPlugin(preserveSymlinks)] ); - this.pluginContexts = this.plugins.map( - getPluginContexts(pluginCache, graph, this.fileEmitter, watcher) - ); + this.pluginContexts = this.plugins.map(getPluginContexts(pluginCache, graph, this.fileEmitter)); if (basePluginDriver) { for (const plugin of userPlugins) { for (const hook of basePluginDriver.previousHooks) { @@ -74,14 +68,7 @@ export class PluginDriver { } public createOutputPluginDriver(plugins: Plugin[]): PluginDriver { - return new PluginDriver( - this.graph, - plugins, - this.pluginCache, - this.preserveSymlinks, - this.watcher, - this - ); + return new PluginDriver(this.graph, plugins, this.pluginCache, this.preserveSymlinks, this); } // chains, first non-null result stops and returns diff --git a/src/utils/error.ts b/src/utils/error.ts index 3bacdd45afb..90942250564 100644 --- a/src/utils/error.ts +++ b/src/utils/error.ts @@ -4,9 +4,8 @@ import { RollupError, RollupWarning } from '../rollup/types'; import getCodeFrame from './getCodeFrame'; import relativeId from './relativeId'; -export function error(base: Error | RollupError, props?: RollupError): never { +export function error(base: Error | RollupError): never { if (!(base instanceof Error)) base = Object.assign(new Error(base.message), base); - if (props) Object.assign(base, props); throw base; } diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index 46f71f43d23..419e6a633f0 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -1,91 +1,12 @@ +import { InputOptions, OutputOptions, WarningHandler } from '../rollup/types'; import { - InputOptions, - OutputOptions, - WarningHandler, - WarningHandlerWithDefault -} from '../rollup/types'; - -export interface GenericConfigObject { - [key: string]: unknown; -} - -export interface CommandConfigObject { - external: string[]; - globals: { [id: string]: string } | undefined; - [key: string]: unknown; -} - -const createGetOption = (config: GenericConfigObject, command: GenericConfigObject) => ( - name: string, - defaultValue?: unknown -): any => - command[name] !== undefined - ? command[name] - : config[name] !== undefined - ? config[name] - : defaultValue; - -const normalizeObjectOptionValue = (optionValue: any) => { - if (!optionValue) { - return optionValue; - } - if (typeof optionValue !== 'object') { - return {}; - } - return optionValue; -}; - -const getObjectOption = ( - config: GenericConfigObject, - command: GenericConfigObject, - name: string -) => { - const commandOption = normalizeObjectOptionValue(command[name]); - const configOption = normalizeObjectOptionValue(config[name]); - if (commandOption !== undefined) { - return commandOption && configOption ? { ...configOption, ...commandOption } : commandOption; - } - return configOption; -}; - -export function ensureArray(items: (T | null | undefined)[] | T | null | undefined): T[] { - if (Array.isArray(items)) { - return items.filter(Boolean) as T[]; - } - if (items) { - return [items]; - } - return []; -} - -const defaultOnWarn: WarningHandler = warning => { - if (typeof warning === 'string') { - console.warn(warning); - } else { - console.warn(warning.message); - } -}; - -const getOnWarn = ( - config: GenericConfigObject, - defaultOnWarnHandler: WarningHandler = defaultOnWarn -): WarningHandler => - config.onwarn - ? warning => (config.onwarn as WarningHandlerWithDefault)(warning, defaultOnWarnHandler) - : defaultOnWarnHandler; - -const getExternal = (config: GenericConfigObject, command: CommandConfigObject) => { - const configExternal = config.external; - return typeof configExternal === 'function' - ? (id: string, ...rest: string[]) => - configExternal(id, ...rest) || command.external.indexOf(id) !== -1 - : (typeof config.external === 'string' - ? [configExternal] - : Array.isArray(configExternal) - ? configExternal - : [] - ).concat(command.external); -}; + CommandConfigObject, + ensureArray, + GenericConfigObject, + parseInputOptions, + parseOutputOptions, + warnUnknownOptions +} from './parseOptions'; export const commandAliases: { [key: string]: string } = { c: 'config', @@ -102,95 +23,46 @@ export const commandAliases: { [key: string]: string } = { w: 'watch' }; -export default function mergeOptions({ - config = {}, - command: rawCommandOptions = {}, - defaultOnWarnHandler -}: { - command?: GenericConfigObject; - config: GenericConfigObject; - defaultOnWarnHandler?: WarningHandler; -}): { +export function mergeOptions( + config: GenericConfigObject, + rawCommandOptions: GenericConfigObject = { external: [], globals: undefined }, + defaultOnWarnHandler?: WarningHandler +): { inputOptions: InputOptions; - optionError: string | null; - outputOptions: any; + outputOptions: OutputOptions[]; } { const command = getCommandOptions(rawCommandOptions); - const inputOptions = getInputOptions(config, command, defaultOnWarnHandler as WarningHandler); - + const inputOptions = parseInputOptions(config, command, defaultOnWarnHandler); + const warn = inputOptions.onwarn as WarningHandler; if (command.output) { Object.assign(command, command.output); } - - const output = config.output; - const normalizedOutputOptions = Array.isArray(output) ? output : output ? [output] : []; - if (normalizedOutputOptions.length === 0) normalizedOutputOptions.push({}); - const outputOptions = normalizedOutputOptions.map(singleOutputOptions => - getOutputOptions(singleOutputOptions, command) - ); - - const unknownOptionErrors: string[] = []; - const validInputOptions = Object.keys(inputOptions); - addUnknownOptionErrors( - unknownOptionErrors, - Object.keys(config), - validInputOptions, - 'input option', - /^output$/ - ); - - const validOutputOptions = Object.keys(outputOptions[0]); - addUnknownOptionErrors( - unknownOptionErrors, - outputOptions.reduce((allKeys, options) => allKeys.concat(Object.keys(options)), []), - validOutputOptions, - 'output option' + const outputOptionsArray = ensureArray(config.output) as GenericConfigObject[]; + if (outputOptionsArray.length === 0) outputOptionsArray.push({}); + const outputOptions = outputOptionsArray.map(singleOutputOptions => + parseOutputOptions(singleOutputOptions, warn, command) ); - const validCliOutputOptions = validOutputOptions.filter( - option => option !== 'sourcemapPathTransform' - ); - addUnknownOptionErrors( - unknownOptionErrors, - Object.keys(command), - validInputOptions.concat( - validCliOutputOptions, + warnUnknownOptions( + command, + Object.keys(inputOptions).concat( + Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapPathTransform'), Object.keys(commandAliases), 'config', 'environment', 'silent', 'stdin' ), - 'CLI flag', - /^_|output|(config.*)$/ + 'CLI flags', + warn, + /^_$|output$|config/ ); - return { inputOptions, - optionError: unknownOptionErrors.length > 0 ? unknownOptionErrors.join('\n') : null, outputOptions }; } -function addUnknownOptionErrors( - errors: string[], - options: string[], - validOptions: string[], - optionType: string, - ignoredKeys: RegExp = /$./ -) { - const validOptionSet = new Set(validOptions); - const unknownOptions = options.filter(key => !validOptionSet.has(key) && !ignoredKeys.test(key)); - if (unknownOptions.length > 0) - errors.push( - `Unknown ${optionType}: ${unknownOptions.join(', ')}. Allowed options: ${Array.from( - validOptionSet - ) - .sort() - .join(', ')}` - ); -} - function getCommandOptions(rawCommandOptions: GenericConfigObject): CommandConfigObject { const external = rawCommandOptions.external && typeof rawCommandOptions.external === 'string' @@ -212,95 +84,3 @@ function getCommandOptions(rawCommandOptions: GenericConfigObject): CommandConfi : undefined }; } - -function getInputOptions( - config: GenericConfigObject, - command: CommandConfigObject = { external: [], globals: undefined }, - defaultOnWarnHandler: WarningHandler -): InputOptions { - const getOption = createGetOption(config, command); - const inputOptions: InputOptions = { - acorn: config.acorn, - acornInjectPlugins: config.acornInjectPlugins as any, - cache: getOption('cache'), - chunkGroupingSize: getOption('chunkGroupingSize', 5000), - context: getOption('context'), - experimentalCacheExpiry: getOption('experimentalCacheExpiry', 10), - experimentalOptimizeChunks: getOption('experimentalOptimizeChunks'), - external: getExternal(config, command) as any, - inlineDynamicImports: getOption('inlineDynamicImports', false), - input: getOption('input', []), - manualChunks: getOption('manualChunks'), - moduleContext: config.moduleContext as any, - onwarn: getOnWarn(config, defaultOnWarnHandler), - perf: getOption('perf', false), - plugins: ensureArray(config.plugins as any), - preserveModules: getOption('preserveModules'), - preserveSymlinks: getOption('preserveSymlinks'), - shimMissingExports: getOption('shimMissingExports'), - strictDeprecations: getOption('strictDeprecations', false), - treeshake: getObjectOption(config, command, 'treeshake'), - watch: config.watch as any - }; - - // support rollup({ cache: prevBuildObject }) - if (inputOptions.cache && (inputOptions.cache as any).cache) - inputOptions.cache = (inputOptions.cache as any).cache; - - return inputOptions; -} - -function getOutputOptions( - config: GenericConfigObject, - command: GenericConfigObject = {} -): OutputOptions { - const getOption = createGetOption(config, command); - let format = getOption('format'); - - // Handle format aliases - switch (format) { - case undefined: - case 'esm': - case 'module': - format = 'es'; - break; - case 'commonjs': - format = 'cjs'; - } - - return { - amd: { ...(config.amd as object), ...(command.amd as object) } as any, - assetFileNames: getOption('assetFileNames'), - banner: getOption('banner'), - chunkFileNames: getOption('chunkFileNames'), - compact: getOption('compact', false), - dir: getOption('dir'), - dynamicImportFunction: getOption('dynamicImportFunction'), - entryFileNames: getOption('entryFileNames'), - esModule: getOption('esModule', true), - exports: getOption('exports'), - extend: getOption('extend'), - externalLiveBindings: getOption('externalLiveBindings', true), - file: getOption('file'), - footer: getOption('footer'), - format, - freeze: getOption('freeze', true), - globals: getOption('globals'), - hoistTransitiveImports: getOption('hoistTransitiveImports', true), - indent: getOption('indent', true), - interop: getOption('interop', true), - intro: getOption('intro'), - name: getOption('name'), - namespaceToStringTag: getOption('namespaceToStringTag', false), - noConflict: getOption('noConflict'), - outro: getOption('outro'), - paths: getOption('paths'), - plugins: ensureArray(config.plugins as any), - preferConst: getOption('preferConst'), - sourcemap: getOption('sourcemap'), - sourcemapExcludeSources: getOption('sourcemapExcludeSources'), - sourcemapFile: getOption('sourcemapFile'), - sourcemapPathTransform: getOption('sourcemapPathTransform'), - strict: getOption('strict', true) - }; -} diff --git a/src/utils/parseOptions.ts b/src/utils/parseOptions.ts new file mode 100644 index 00000000000..9a15f762063 --- /dev/null +++ b/src/utils/parseOptions.ts @@ -0,0 +1,212 @@ +import { + InputOptions, + OutputOptions, + WarningHandler, + WarningHandlerWithDefault +} from '../rollup/types'; + +export interface GenericConfigObject { + [key: string]: unknown; +} + +export interface CommandConfigObject { + external: string[]; + globals: { [id: string]: string } | undefined; + [key: string]: unknown; +} + +const createGetOption = (config: GenericConfigObject, overrides: GenericConfigObject) => ( + name: string, + defaultValue?: unknown +): any => + overrides[name] !== undefined + ? overrides[name] + : config[name] !== undefined + ? config[name] + : defaultValue; + +const normalizeObjectOptionValue = (optionValue: any) => { + if (!optionValue) { + return optionValue; + } + if (typeof optionValue !== 'object') { + return {}; + } + return optionValue; +}; + +const getObjectOption = ( + config: GenericConfigObject, + overrides: GenericConfigObject, + name: string +) => { + const commandOption = normalizeObjectOptionValue(overrides[name]); + const configOption = normalizeObjectOptionValue(config[name]); + if (commandOption !== undefined) { + return commandOption && { ...configOption, ...commandOption }; + } + return configOption; +}; + +export function ensureArray(items: (T | null | undefined)[] | T | null | undefined): T[] { + if (Array.isArray(items)) { + return items.filter(Boolean) as T[]; + } + if (items) { + return [items]; + } + return []; +} + +const defaultOnWarn: WarningHandler = warning => { + if (typeof warning === 'string') { + console.warn(warning); + } else { + console.warn(warning.message); + } +}; + +const getOnWarn = ( + config: GenericConfigObject, + defaultOnWarnHandler: WarningHandler +): WarningHandler => + config.onwarn + ? warning => (config.onwarn as WarningHandlerWithDefault)(warning, defaultOnWarnHandler) + : defaultOnWarnHandler; + +const getExternal = (config: GenericConfigObject, overrides: CommandConfigObject) => { + const configExternal = config.external; + return typeof configExternal === 'function' + ? (id: string, ...rest: string[]) => + configExternal(id, ...rest) || overrides.external.indexOf(id) !== -1 + : (typeof config.external === 'string' + ? [configExternal] + : Array.isArray(configExternal) + ? configExternal + : [] + ).concat(overrides.external); +}; + +export function parseInputOptions( + config: GenericConfigObject, + overrides: CommandConfigObject = { external: [], globals: undefined }, + defaultOnWarnHandler: WarningHandler = defaultOnWarn +): InputOptions { + const getOption = createGetOption(config, overrides); + const inputOptions: InputOptions = { + acorn: config.acorn, + acornInjectPlugins: config.acornInjectPlugins as any, + cache: getOption('cache'), + chunkGroupingSize: getOption('chunkGroupingSize', 5000), + context: getOption('context'), + experimentalCacheExpiry: getOption('experimentalCacheExpiry', 10), + experimentalOptimizeChunks: getOption('experimentalOptimizeChunks'), + external: getExternal(config, overrides) as any, + inlineDynamicImports: getOption('inlineDynamicImports', false), + input: getOption('input', []), + manualChunks: getOption('manualChunks'), + moduleContext: config.moduleContext as any, + onwarn: getOnWarn(config, defaultOnWarnHandler), + perf: getOption('perf', false), + plugins: ensureArray(config.plugins as any), + preserveModules: getOption('preserveModules'), + preserveSymlinks: getOption('preserveSymlinks'), + shimMissingExports: getOption('shimMissingExports'), + strictDeprecations: getOption('strictDeprecations', false), + treeshake: getObjectOption(config, overrides, 'treeshake'), + watch: config.watch as any + }; + + // support rollup({ cache: prevBuildObject }) + if (inputOptions.cache && (inputOptions.cache as any).cache) + inputOptions.cache = (inputOptions.cache as any).cache; + + warnUnknownOptions( + config, + Object.keys(inputOptions), + 'input options', + inputOptions.onwarn as WarningHandler, + /^output$/ + ); + return inputOptions; +} + +export function parseOutputOptions( + config: GenericConfigObject, + warn: WarningHandler, + overrides: GenericConfigObject = {} +): OutputOptions { + const getOption = createGetOption(config, overrides); + let format = getOption('format'); + + // Handle format aliases + switch (format) { + case undefined: + case 'esm': + case 'module': + format = 'es'; + break; + case 'commonjs': + format = 'cjs'; + } + const outputOptions = { + amd: { ...(config.amd as object), ...(overrides.amd as object) } as any, + assetFileNames: getOption('assetFileNames'), + banner: getOption('banner'), + chunkFileNames: getOption('chunkFileNames'), + compact: getOption('compact', false), + dir: getOption('dir'), + dynamicImportFunction: getOption('dynamicImportFunction'), + entryFileNames: getOption('entryFileNames'), + esModule: getOption('esModule', true), + exports: getOption('exports'), + extend: getOption('extend'), + externalLiveBindings: getOption('externalLiveBindings', true), + file: getOption('file'), + footer: getOption('footer'), + format, + freeze: getOption('freeze', true), + globals: getOption('globals'), + hoistTransitiveImports: getOption('hoistTransitiveImports', true), indent: getOption('indent', true), + interop: getOption('interop', true), + intro: getOption('intro'), + name: getOption('name'), + namespaceToStringTag: getOption('namespaceToStringTag', false), + noConflict: getOption('noConflict'), + outro: getOption('outro'), + paths: getOption('paths'), + plugins: ensureArray(config.plugins as any), + preferConst: getOption('preferConst'), + sourcemap: getOption('sourcemap'), + sourcemapExcludeSources: getOption('sourcemapExcludeSources'), + sourcemapFile: getOption('sourcemapFile'), + sourcemapPathTransform: getOption('sourcemapPathTransform'), + strict: getOption('strict', true) + }; + + warnUnknownOptions(config, Object.keys(outputOptions), 'output options', warn); + return outputOptions; +} + +export function warnUnknownOptions( + passedOptions: GenericConfigObject, + validOptions: string[], + optionType: string, + warn: WarningHandler, + ignoredKeys: RegExp = /$./ +): void { + const validOptionSet = new Set(validOptions); + const unknownOptions = Object.keys(passedOptions).filter( + key => !(validOptionSet.has(key) || ignoredKeys.test(key)) + ); + if (unknownOptions.length > 0) { + warn({ + code: 'UNKNOWN_OPTION', + message: `Unknown ${optionType}: ${unknownOptions.join(', ')}. Allowed options: ${Array.from( + validOptionSet + ) + .sort() + .join(', ')}` + }); + } +} diff --git a/src/utils/pluginUtils.ts b/src/utils/pluginUtils.ts index e855212bf4b..441eeb05c37 100644 --- a/src/utils/pluginUtils.ts +++ b/src/utils/pluginUtils.ts @@ -26,11 +26,7 @@ export function throwPluginError( } export const deprecatedHooks: { active: boolean; deprecated: string; replacement: string }[] = [ - { active: true, deprecated: 'ongenerate', replacement: 'generateBundle' }, - { active: true, deprecated: 'onwrite', replacement: 'generateBundle/writeBundle' }, - { active: true, deprecated: 'transformBundle', replacement: 'renderChunk' }, - { active: true, deprecated: 'transformChunk', replacement: 'renderChunk' }, - { active: false, deprecated: 'resolveAssetUrl', replacement: 'resolveFileUrl' } + { active: true, deprecated: 'resolveAssetUrl', replacement: 'resolveFileUrl' } ]; export function warnDeprecatedHooks(plugins: Plugin[], graph: Graph) { diff --git a/src/utils/renderChunk.ts b/src/utils/renderChunk.ts index 64e58abf9f5..f901984a253 100644 --- a/src/utils/renderChunk.ts +++ b/src/utils/renderChunk.ts @@ -1,4 +1,3 @@ -import Chunk from '../Chunk'; import { DecodedSourceMapOrMissing, OutputOptions, @@ -7,18 +6,15 @@ import { SourceMapInput } from '../rollup/types'; import { decodedSourcemap } from './decodedSourcemap'; -import { error } from './error'; import { PluginDriver } from './PluginDriver'; export default function renderChunk({ - chunk, code, options, outputPluginDriver, renderChunk, sourcemapChain }: { - chunk: Chunk; code: string; options: OutputOptions; outputPluginDriver: PluginDriver; @@ -47,33 +43,9 @@ export default function renderChunk({ return result.code; }; - let inTransformBundle = false; - let inRenderChunk = true; - return outputPluginDriver - .hookReduceArg0('renderChunk', [code, renderChunk, options], renderChunkReducer) - .then(code => { - inRenderChunk = false; - return outputPluginDriver.hookReduceArg0( - 'transformChunk', - [code, options, chunk], - renderChunkReducer - ); - }) - .then(code => { - inTransformBundle = true; - return outputPluginDriver.hookReduceArg0( - 'transformBundle', - [code, options, chunk], - renderChunkReducer - ); - }) - .catch(err => { - if (inRenderChunk) throw err; - return error(err, { - code: inTransformBundle ? 'BAD_BUNDLE_TRANSFORMER' : 'BAD_CHUNK_TRANSFORMER', - message: `Error transforming ${(inTransformBundle ? 'bundle' : 'chunk') + - (err.plugin ? ` with '${err.plugin}' plugin` : '')}: ${err.message}`, - plugin: err.plugin - }); - }); + return outputPluginDriver.hookReduceArg0( + 'renderChunk', + [code, renderChunk, options], + renderChunkReducer + ); } diff --git a/src/utils/timers.ts b/src/utils/timers.ts index ad886db561e..1c87ad10f3e 100644 --- a/src/utils/timers.ts +++ b/src/utils/timers.ts @@ -87,12 +87,9 @@ export let timeStart: (label: string, level?: number) => void = NOOP, const TIMED_PLUGIN_HOOKS: { [hook: string]: boolean } = { load: true, - ongenerate: true, - onwrite: true, resolveDynamicImport: true, resolveId: true, - transform: true, - transformBundle: true + transform: true }; function getPluginWithTimers(plugin: any, index: number): Plugin { diff --git a/src/utils/transform.ts b/src/utils/transform.ts index bf92a76677d..b4945a49728 100644 --- a/src/utils/transform.ts +++ b/src/utils/transform.ts @@ -5,24 +5,22 @@ import { DecodedSourceMapOrMissing, EmittedFile, Plugin, - PluginCache, PluginContext, RollupError, RollupWarning, + SourceDescription, TransformModuleJSON, - TransformResult, - TransformSourceDescription + TransformResult } from '../rollup/types'; import { collapseSourcemap } from './collapseSourcemaps'; import { decodedSourcemap } from './decodedSourcemap'; import { augmentCodeLocation } from './error'; -import { dirname, resolve } from './path'; import { getTrackedPluginCache } from './PluginCache'; import { throwPluginError } from './pluginUtils'; export default function transform( graph: Graph, - source: TransformSourceDescription, + source: SourceDescription, module: Module ): Promise { const id = module.id; @@ -34,9 +32,9 @@ export default function transform( const transformDependencies: string[] = []; const emittedFiles: EmittedFile[] = []; let customTransformCache = false; + const useCustomTransformCache = () => (customTransformCache = true); let moduleSideEffects: boolean | null = null; let syntheticNamedExports: boolean | null = null; - let trackedPluginCache: { cache: PluginCache; used: boolean }; let curPlugin: Plugin; const curSource: string = source.code; @@ -46,30 +44,6 @@ export default function transform( result: TransformResult, plugin: Plugin ) { - // track which plugins use the custom this.cache to opt-out of transform caching - if (!customTransformCache && trackedPluginCache.used) customTransformCache = true; - if (customTransformCache) { - if (result && typeof result === 'object' && Array.isArray(result.dependencies)) { - for (const dep of result.dependencies) { - graph.watchFiles[resolve(dirname(id), dep)] = true; - } - } - } else { - // files emitted by a transform hook need to be emitted again if the hook is skipped - if (emittedFiles.length) module.transformFiles = emittedFiles; - if (result && typeof result === 'object' && Array.isArray(result.dependencies)) { - // not great, but a useful way to track this without assuming WeakMap - if (!(curPlugin as any).warnedTransformDependencies) - graph.warnDeprecation( - `Returning "dependencies" from the "transform" hook as done by plugin ${plugin.name} is deprecated. The "this.addWatchFile" plugin context function should be used instead.`, - true - ); - (curPlugin as any).warnedTransformDependencies = true; - for (const dep of result.dependencies) - transformDependencies.push(resolve(dirname(id), dep)); - } - } - if (typeof result === 'string') { result = { ast: undefined, @@ -90,7 +64,8 @@ export default function transform( return code; } - // strict null check allows 'null' maps to not be pushed to the chain, while 'undefined' gets the missing map warning + // strict null check allows 'null' maps to not be pushed to the chain, + // while 'undefined' gets the missing map warning if (result.map !== null) { const map = decodedSourcemap(result.map); sourcemapChain.push(map || { missing: true, plugin: plugin.name }); @@ -101,8 +76,6 @@ export default function transform( return result.code; } - let setAssetSourceErr: any; - return graph.pluginDriver .hookReduceArg0( 'transform', @@ -110,11 +83,11 @@ export default function transform( transformReducer, (pluginContext, plugin) => { curPlugin = plugin; - if (curPlugin.cacheKey) customTransformCache = true; - else trackedPluginCache = getTrackedPluginCache(pluginContext.cache); return { ...pluginContext, - cache: trackedPluginCache ? trackedPluginCache.cache : pluginContext.cache, + cache: customTransformCache + ? pluginContext.cache + : getTrackedPluginCache(pluginContext.cache, useCustomTransformCache), warn(warning: RollupWarning | string, pos?: number | { column: number; line: number }) { if (typeof warning === 'string') warning = { message: warning } as RollupWarning; if (pos) augmentCodeLocation(warning, pos, curSource, id); @@ -147,18 +120,11 @@ export default function transform( transformDependencies.push(id); pluginContext.addWatchFile(id); }, - setAssetSource(assetReferenceId, source) { - pluginContext.setAssetSource(assetReferenceId, source); - if (!customTransformCache && !setAssetSourceErr) { - try { - return this.error({ - code: 'INVALID_SETASSETSOURCE', - message: `setAssetSource cannot be called in transform for caching reasons. Use emitFile with a source, or call setAssetSource in another hook.` - }); - } catch (err) { - setAssetSourceErr = err; - } - } + setAssetSource() { + return this.error({ + code: 'INVALID_SETASSETSOURCE', + message: `setAssetSource cannot be called in transform for caching reasons. Use emitFile with a source, or call setAssetSource in another hook.` + }); }, getCombinedSourcemap() { const combinedMap = collapseSourcemap( @@ -187,7 +153,10 @@ export default function transform( ) .catch(err => throwPluginError(err, curPlugin.name, { hook: 'transform', id })) .then(code => { - if (!customTransformCache && setAssetSourceErr) throw setAssetSourceErr; + if (!customTransformCache) { + // files emitted by a transform hook need to be emitted again if the hook is skipped + if (emittedFiles.length) module.transformFiles = emittedFiles; + } return { ast: ast!, diff --git a/src/watch/watch-proxy.ts b/src/watch/watch-proxy.ts index 66bf7e4499d..f8daa8d3f72 100644 --- a/src/watch/watch-proxy.ts +++ b/src/watch/watch-proxy.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'events'; import { RollupWatcher } from '../rollup/types'; -import { GenericConfigObject } from '../utils/mergeOptions'; +import { GenericConfigObject } from '../utils/parseOptions'; import { loadFsEvents } from './fsevents-importer'; class WatchEmitter extends EventEmitter { diff --git a/src/watch/watch.ts b/src/watch/watch.ts index f62bb129a7e..7bf3981ebfb 100644 --- a/src/watch/watch.ts +++ b/src/watch/watch.ts @@ -9,7 +9,8 @@ import { RollupWatcher, WatcherOptions } from '../rollup/types'; -import mergeOptions, { GenericConfigObject } from '../utils/mergeOptions'; +import { mergeOptions } from '../utils/mergeOptions'; +import { GenericConfigObject } from '../utils/parseOptions'; import { FileWatcher } from './fileWatcher'; const DELAY = 200; @@ -116,9 +117,7 @@ export class Task { this.closed = false; this.watched = new Set(); - const { inputOptions, outputOptions } = mergeOptions({ - config - }); + const { inputOptions, outputOptions } = mergeOptions(config); this.inputOptions = inputOptions; this.outputs = outputOptions; this.outputFiles = this.outputs.map(output => { diff --git a/test/chunking-form/samples/deprecated/configure-asset-url/_config.js b/test/chunking-form/samples/deprecated/configure-asset-url/_config.js index 534304866a5..c867fee7ed1 100644 --- a/test/chunking-form/samples/deprecated/configure-asset-url/_config.js +++ b/test/chunking-form/samples/deprecated/configure-asset-url/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'allows to configure asset urls', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, output: { diff --git a/test/chunking-form/samples/deprecated/configure-file-url-for-assets-and-chunks/_config.js b/test/chunking-form/samples/deprecated/configure-file-url-for-assets-and-chunks/_config.js index 81c4557c73b..187178aed06 100644 --- a/test/chunking-form/samples/deprecated/configure-file-url-for-assets-and-chunks/_config.js +++ b/test/chunking-form/samples/deprecated/configure-file-url-for-assets-and-chunks/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'allows to configure file urls', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, output: { diff --git a/test/chunking-form/samples/deprecated/emit-asset/_config.js b/test/chunking-form/samples/deprecated/emit-asset/_config.js index 6a83f6f385e..97c48676d28 100644 --- a/test/chunking-form/samples/deprecated/emit-asset/_config.js +++ b/test/chunking-form/samples/deprecated/emit-asset/_config.js @@ -3,6 +3,7 @@ const path = require('path'); module.exports = { description: 'supports emitting assets from plugin hooks', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: ['main.js'], diff --git a/test/chunking-form/samples/deprecated/emit-chunk-existing/_config.js b/test/chunking-form/samples/deprecated/emit-chunk-existing/_config.js index 677af2b6b15..a472740a55a 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk-existing/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk-existing/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'allows adding modules already in the graph as entry points', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: { diff --git a/test/chunking-form/samples/deprecated/emit-chunk-facade/_config.js b/test/chunking-form/samples/deprecated/emit-chunk-facade/_config.js index a328ed9dd13..780dd15d602 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk-facade/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk-facade/_config.js @@ -3,6 +3,7 @@ let referenceId; module.exports = { description: 'retrieves the correct name of an emitted chunk in case a facade is created', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: 'main', diff --git a/test/chunking-form/samples/deprecated/emit-chunk-named/_config.js b/test/chunking-form/samples/deprecated/emit-chunk-named/_config.js index 2bd85d2be9a..522a2687e28 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk-named/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk-named/_config.js @@ -3,6 +3,7 @@ let referenceId; module.exports = { description: 'allows naming emitted chunks', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: 'main', diff --git a/test/chunking-form/samples/deprecated/emit-chunk-worker/_config.js b/test/chunking-form/samples/deprecated/emit-chunk-worker/_config.js index c77be10c7a7..5e1a2ba5b27 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk-worker/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk-worker/_config.js @@ -5,6 +5,7 @@ let proxyId; module.exports = { description: 'allows adding additional chunks to be used in workers', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: 'main', diff --git a/test/chunking-form/samples/deprecated/emit-chunk-worklet/_config.js b/test/chunking-form/samples/deprecated/emit-chunk-worklet/_config.js index bb9d858bbed..5c77d304c82 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk-worklet/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk-worklet/_config.js @@ -2,6 +2,7 @@ const REGISTER_WORKLET = 'register-paint-worklet:'; module.exports = { description: 'allows adding additional chunks to be used in worklets', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: 'main', diff --git a/test/chunking-form/samples/deprecated/emit-chunk/_config.js b/test/chunking-form/samples/deprecated/emit-chunk/_config.js index 7652c7357cc..f99cdb68e91 100644 --- a/test/chunking-form/samples/deprecated/emit-chunk/_config.js +++ b/test/chunking-form/samples/deprecated/emit-chunk/_config.js @@ -3,6 +3,7 @@ let referenceId; module.exports = { description: 'allows adding additional chunks and retrieving their file name', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, input: 'main', diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/_config.js b/test/chunking-form/samples/dynamic-import-inlining-object/_config.js new file mode 100644 index 00000000000..5adf9230f61 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'supports an object with a single entry when inlining dynamic imports', + options: { + inlineDynamicImports: true, + input: { entry: 'main' } + } +}; diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/_expected/amd/entry.js b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/amd/entry.js new file mode 100644 index 00000000000..87c533f4a08 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/amd/entry.js @@ -0,0 +1,17 @@ +define(['exports'], function (exports) { 'use strict'; + + const bar = 2; + Promise.resolve().then(function () { return foo$1; }); + + const foo = 1; + + var foo$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + foo: foo + }); + + exports.bar = bar; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}); diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/_expected/cjs/entry.js b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/cjs/entry.js new file mode 100644 index 00000000000..188ad126796 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/cjs/entry.js @@ -0,0 +1,15 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +const bar = 2; +Promise.resolve().then(function () { return foo$1; }); + +const foo = 1; + +var foo$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + foo: foo +}); + +exports.bar = bar; diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/_expected/es/entry.js b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/es/entry.js new file mode 100644 index 00000000000..ae434046e6c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/es/entry.js @@ -0,0 +1,11 @@ +const bar = 2; +Promise.resolve().then(function () { return foo$1; }); + +const foo = 1; + +var foo$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + foo: foo +}); + +export { bar }; diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/_expected/system/entry.js b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/system/entry.js new file mode 100644 index 00000000000..0ac064e426c --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/_expected/system/entry.js @@ -0,0 +1,18 @@ +System.register([], function (exports) { + 'use strict'; + return { + execute: function () { + + const bar = exports('bar', 2); + Promise.resolve().then(function () { return foo$1; }); + + const foo = 1; + + var foo$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + foo: foo + }); + + } + }; +}); diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/foo.js b/test/chunking-form/samples/dynamic-import-inlining-object/foo.js new file mode 100644 index 00000000000..6a8018af412 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/foo.js @@ -0,0 +1 @@ +export const foo = 1; \ No newline at end of file diff --git a/test/chunking-form/samples/dynamic-import-inlining-object/main.js b/test/chunking-form/samples/dynamic-import-inlining-object/main.js new file mode 100644 index 00000000000..ee3e6a770d6 --- /dev/null +++ b/test/chunking-form/samples/dynamic-import-inlining-object/main.js @@ -0,0 +1,2 @@ +export const bar = 2; +import('./foo.js'); diff --git a/test/cli/node_modules/rollup-config-foo/lib/config.js b/test/cli/node_modules/rollup-config-foo/lib/config.js deleted file mode 100644 index db00f465db4..00000000000 --- a/test/cli/node_modules/rollup-config-foo/lib/config.js +++ /dev/null @@ -1,11 +0,0 @@ -var replace = require( 'rollup-plugin-replace' ); - -module.exports = { - input: 'main.js', - output: { - format: 'cjs' - }, - plugins: [ - replace( { 'ANSWER': 42 } ) - ] -}; diff --git a/test/cli/node_modules/rollup-config-foo/package.json b/test/cli/node_modules/rollup-config-foo/package.json deleted file mode 100644 index fbd490130d0..00000000000 --- a/test/cli/node_modules/rollup-config-foo/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "lib/config.js" -} diff --git a/test/cli/node_modules/foo/lib/config.js b/test/cli/node_modules_rename_me/bar/lib/config.js similarity index 100% rename from test/cli/node_modules/foo/lib/config.js rename to test/cli/node_modules_rename_me/bar/lib/config.js diff --git a/test/cli/node_modules/foo/package.json b/test/cli/node_modules_rename_me/bar/package.json similarity index 100% rename from test/cli/node_modules/foo/package.json rename to test/cli/node_modules_rename_me/bar/package.json diff --git a/test/cli/node_modules_rename_me/foo/lib/config.js b/test/cli/node_modules_rename_me/foo/lib/config.js deleted file mode 100644 index db00f465db4..00000000000 --- a/test/cli/node_modules_rename_me/foo/lib/config.js +++ /dev/null @@ -1,11 +0,0 @@ -var replace = require( 'rollup-plugin-replace' ); - -module.exports = { - input: 'main.js', - output: { - format: 'cjs' - }, - plugins: [ - replace( { 'ANSWER': 42 } ) - ] -}; diff --git a/test/cli/node_modules_rename_me/foo/package.json b/test/cli/node_modules_rename_me/foo/package.json deleted file mode 100644 index fbd490130d0..00000000000 --- a/test/cli/node_modules_rename_me/foo/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "main": "lib/config.js" -} diff --git a/test/cli/samples/duplicate-import-options/_config.js b/test/cli/samples/duplicate-import-options/_config.js new file mode 100644 index 00000000000..00eded60316 --- /dev/null +++ b/test/cli/samples/duplicate-import-options/_config.js @@ -0,0 +1,10 @@ +const { assertStderrIncludes } = require('../../../utils.js'); + +module.exports = { + description: 'throws if different types of entries are combined', + command: 'rollup main.js --format es --input main.js', + error: () => true, + stderr(stderr) { + assertStderrIncludes(stderr, '[!] Either use --input, or pass input path as argument'); + } +}; diff --git a/test/cli/samples/duplicate-import-options/main.js b/test/cli/samples/duplicate-import-options/main.js new file mode 100644 index 00000000000..17eee8f1f7e --- /dev/null +++ b/test/cli/samples/duplicate-import-options/main.js @@ -0,0 +1 @@ +assert.equal( 1 + 1, 2 ); diff --git a/test/cli/samples/external-modules-auto-global/_config.js b/test/cli/samples/external-modules-auto-global/_config.js index 9f3e784156f..8163c5ad414 100644 --- a/test/cli/samples/external-modules-auto-global/_config.js +++ b/test/cli/samples/external-modules-auto-global/_config.js @@ -1,5 +1,11 @@ +const assert = require('assert'); + module.exports = { description: 'populates options.external with --global keys', - command: 'rollup main.js --format iife --globals mathematics:Math', - execute: true + command: + 'rollup main.js --format iife --globals mathematics:Math,promises:Promise --external promises', + execute: true, + stderr(stderr) { + assert.strictEqual(stderr.indexOf('(!)'), -1); + } }; diff --git a/test/cli/samples/external-modules-auto-global/main.js b/test/cli/samples/external-modules-auto-global/main.js index dcd8569f77f..ad436c33986 100644 --- a/test/cli/samples/external-modules-auto-global/main.js +++ b/test/cli/samples/external-modules-auto-global/main.js @@ -1,3 +1,5 @@ import { max } from 'mathematics'; +import { resolve } from 'promises'; assert.equal( max( 1, 2, 3 ), 3 ); +assert.ok( resolve().then ); diff --git a/test/cli/samples/external-modules/_config.js b/test/cli/samples/external-modules/_config.js index 8117a61be71..dbae8e93f67 100644 --- a/test/cli/samples/external-modules/_config.js +++ b/test/cli/samples/external-modules/_config.js @@ -1,5 +1,10 @@ +const assert = require('assert'); + module.exports = { description: 'allows external modules to be specified with --external=foo,bar,baz', - command: 'rollup main.js --format cjs --external path,util', - execute: true + command: 'rollup main.js --format cjs --external=path,util', + execute: true, + stderr(stderr) { + assert.strictEqual(stderr.indexOf('(!)'), -1); + } }; diff --git a/test/cli/samples/merge-deprecations/rollup.config.js b/test/cli/samples/merge-deprecations/rollup.config.js index 5a846aebd89..67003241f2d 100644 --- a/test/cli/samples/merge-deprecations/rollup.config.js +++ b/test/cli/samples/merge-deprecations/rollup.config.js @@ -1,7 +1,5 @@ var replace = require( 'rollup-plugin-replace' ); -let warnings = []; - module.exports = { entry: 'main.js', input: 'main.js', diff --git a/test/cli/samples/node-config-auto-prefix/_config.js b/test/cli/samples/node-config-auto-prefix/_config.js index 88b1368e750..084ade901da 100644 --- a/test/cli/samples/node-config-auto-prefix/_config.js +++ b/test/cli/samples/node-config-auto-prefix/_config.js @@ -1,5 +1,5 @@ module.exports = { - description: 'uses config file installed from npm', + description: 'uses config file installed from npm, automatically adding a rollup-config- prefix', command: 'rollup --config node:foo', execute: true }; diff --git a/test/cli/samples/node-config-not-found/_config.js b/test/cli/samples/node-config-not-found/_config.js new file mode 100644 index 00000000000..cf53bf19d71 --- /dev/null +++ b/test/cli/samples/node-config-not-found/_config.js @@ -0,0 +1,10 @@ +const { assertStderrIncludes } = require('../../../utils.js'); + +module.exports = { + description: 'throws if a config in node_modules cannot be found', + command: 'rollup --config node:baz', + error: () => true, + stderr(stderr) { + assertStderrIncludes(stderr, '[!] Could not resolve config file node:baz'); + } +}; diff --git a/test/cli/samples/node-config-not-found/_expected.js b/test/cli/samples/node-config-not-found/_expected.js new file mode 100644 index 00000000000..b5aa08a6ad6 --- /dev/null +++ b/test/cli/samples/node-config-not-found/_expected.js @@ -0,0 +1,11 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.myBundle = factory(); +}(this, function () { 'use strict'; + + var main = 42; + + return main; + +})); diff --git a/test/cli/samples/node-config-not-found/main.js b/test/cli/samples/node-config-not-found/main.js new file mode 100644 index 00000000000..df16c1b06b9 --- /dev/null +++ b/test/cli/samples/node-config-not-found/main.js @@ -0,0 +1 @@ +assert.equal( ANSWER, 42 ); diff --git a/test/cli/samples/node-config/_config.js b/test/cli/samples/node-config/_config.js index c17da4b1e3a..fdd13b0cc98 100644 --- a/test/cli/samples/node-config/_config.js +++ b/test/cli/samples/node-config/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'uses config file installed from npm', - command: 'rollup --config node:foo', + command: 'rollup --config node:bar', cwd: __dirname, execute: true }; diff --git a/test/cli/samples/warn-unknown-options/rollup.config.js b/test/cli/samples/warn-unknown-options/rollup.config.js index beb9fb29c69..60b281e8f61 100644 --- a/test/cli/samples/warn-unknown-options/rollup.config.js +++ b/test/cli/samples/warn-unknown-options/rollup.config.js @@ -18,7 +18,7 @@ module.exports = commands => ({ assert.equal(warning.code, 'UNKNOWN_OPTION'); assert.equal( warning.message, - `Unknown CLI flag: unknownOption. Allowed options: ${ + `Unknown CLI flags: unknownOption. Allowed options: ${ require('../../../misc/optionList').flags }` ); diff --git a/test/form/samples/deprecated/configure-asset-url/_config.js b/test/form/samples/deprecated/configure-asset-url/_config.js index 02d27c5fe02..56f8d0d0398 100644 --- a/test/form/samples/deprecated/configure-asset-url/_config.js +++ b/test/form/samples/deprecated/configure-asset-url/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'allows to configure asset urls', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, plugins: [ diff --git a/test/form/samples/deprecated/emit-asset-hacky/_config.js b/test/form/samples/deprecated/emit-asset-hacky/_config.js index d40ed2b503a..15b90c920a6 100644 --- a/test/form/samples/deprecated/emit-asset-hacky/_config.js +++ b/test/form/samples/deprecated/emit-asset-hacky/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'supports emitting assets in a hacky way by editing the bundle object', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, plugins: { diff --git a/test/form/samples/deprecated/emit-asset/_config.js b/test/form/samples/deprecated/emit-asset/_config.js index d0a017cbd02..e17ea0f8934 100644 --- a/test/form/samples/deprecated/emit-asset/_config.js +++ b/test/form/samples/deprecated/emit-asset/_config.js @@ -4,6 +4,7 @@ const assert = require('assert'); module.exports = { description: 'supports emitting assets from plugin hooks', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, plugins: { diff --git a/test/form/samples/deprecated/prune-pure-unused-import-array/_config.js b/test/form/samples/deprecated/prune-pure-unused-import-array/_config.js index a7450452ab4..6dd4090563a 100644 --- a/test/form/samples/deprecated/prune-pure-unused-import-array/_config.js +++ b/test/form/samples/deprecated/prune-pure-unused-import-array/_config.js @@ -1,5 +1,6 @@ module.exports = { description: 'prunes pure unused external imports ([#1352])', + expectedWarnings: ['DEPRECATED_FEATURE'], options: { strictDeprecations: false, external: ['external', 'other'], diff --git a/test/form/samples/deprecated/prune-pure-unused-import-function/_config.js b/test/form/samples/deprecated/prune-pure-unused-import-function/_config.js index e480fbdff5f..ca46cdf2ddd 100644 --- a/test/form/samples/deprecated/prune-pure-unused-import-function/_config.js +++ b/test/form/samples/deprecated/prune-pure-unused-import-function/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'prunes pure unused external imports ([#1352])', - expectedWarnings: ['EMPTY_BUNDLE'], + expectedWarnings: ['DEPRECATED_FEATURE', 'EMPTY_BUNDLE'], options: { strictDeprecations: false, external: ['external', 'other'], diff --git a/test/form/samples/deprecated/prune-pure-unused-import/_config.js b/test/form/samples/deprecated/prune-pure-unused-import/_config.js index 4a5e9c38281..fe513326305 100644 --- a/test/form/samples/deprecated/prune-pure-unused-import/_config.js +++ b/test/form/samples/deprecated/prune-pure-unused-import/_config.js @@ -1,6 +1,6 @@ module.exports = { description: 'prunes pure unused external imports ([#1352])', - expectedWarnings: ['EMPTY_BUNDLE'], + expectedWarnings: ['DEPRECATED_FEATURE', 'EMPTY_BUNDLE'], options: { strictDeprecations: false, external: ['external', 'other'], diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_config.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_config.js deleted file mode 100644 index f9c01aa37ba..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_config.js +++ /dev/null @@ -1,20 +0,0 @@ -const assert = require('assert'); - -module.exports = { - description: 'plugin .transformBundle gets passed options', - expectedWarnings: ['DEPRECATED_FEATURE'], - options: { - strictDeprecations: false, - plugins: [ - { - transformBundle(code, options) { - assert.strictEqual( - Object.keys(options).join(', '), - require('../../../../misc/optionList').output - ); - return options.format; - } - } - ] - } -}; diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/amd.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/amd.js deleted file mode 100644 index 7f4650356b2..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/amd.js +++ /dev/null @@ -1 +0,0 @@ -amd diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/cjs.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/cjs.js deleted file mode 100644 index 0d69873e8d4..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/cjs.js +++ /dev/null @@ -1 +0,0 @@ -cjs diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/es.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/es.js deleted file mode 100644 index 8357fcaaed4..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/es.js +++ /dev/null @@ -1 +0,0 @@ -es diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/iife.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/iife.js deleted file mode 100644 index afd51ee73b2..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/iife.js +++ /dev/null @@ -1 +0,0 @@ -iife diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/system.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/system.js deleted file mode 100644 index bec3a35ee8b..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/system.js +++ /dev/null @@ -1 +0,0 @@ -system diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/umd.js b/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/umd.js deleted file mode 100644 index 3dc8f1c9e17..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/_expected/umd.js +++ /dev/null @@ -1 +0,0 @@ -umd diff --git a/test/form/samples/deprecated/transform-bundle-plugin-options/main.js b/test/form/samples/deprecated/transform-bundle-plugin-options/main.js deleted file mode 100644 index 934dee761bb..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin-options/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log( 1 + 1 ); diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_config.js b/test/form/samples/deprecated/transform-bundle-plugin/_config.js deleted file mode 100644 index f5987a924d0..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_config.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = { - description: 'allows plugins to transform bundle', - expectedWarnings: ['DEPRECATED_FEATURE'], - options: { - strictDeprecations: false, - plugins: [ - { - transformBundle() { - return '/* first plugin */'; - } - }, - { - transformBundle(code) { - return code + '\n/* second plugin */'; - } - } - ] - } -}; diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/amd.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/amd.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/amd.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/cjs.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/cjs.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/cjs.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/es.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/es.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/es.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/iife.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/iife.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/iife.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/system.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/system.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/system.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/_expected/umd.js b/test/form/samples/deprecated/transform-bundle-plugin/_expected/umd.js deleted file mode 100644 index 6dd9ebb24b6..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/_expected/umd.js +++ /dev/null @@ -1,2 +0,0 @@ -/* first plugin */ -/* second plugin */ diff --git a/test/form/samples/deprecated/transform-bundle-plugin/main.js b/test/form/samples/deprecated/transform-bundle-plugin/main.js deleted file mode 100644 index 934dee761bb..00000000000 --- a/test/form/samples/deprecated/transform-bundle-plugin/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log( 1 + 1 ); diff --git a/test/form/samples/dynamic-import-inlining-array/_config.js b/test/form/samples/dynamic-import-inlining-array/_config.js new file mode 100644 index 00000000000..f426fa668a1 --- /dev/null +++ b/test/form/samples/dynamic-import-inlining-array/_config.js @@ -0,0 +1,7 @@ +module.exports = { + description: 'supports an array with a single entry when inlining dynamic imports', + options: { + inlineDynamicImports: true, + input: ['main'] + } +}; diff --git a/test/form/samples/dynamic-import-inlining-array/_expected.js b/test/form/samples/dynamic-import-inlining-array/_expected.js new file mode 100644 index 00000000000..ae434046e6c --- /dev/null +++ b/test/form/samples/dynamic-import-inlining-array/_expected.js @@ -0,0 +1,11 @@ +const bar = 2; +Promise.resolve().then(function () { return foo$1; }); + +const foo = 1; + +var foo$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + foo: foo +}); + +export { bar }; diff --git a/test/form/samples/dynamic-import-inlining-array/foo.js b/test/form/samples/dynamic-import-inlining-array/foo.js new file mode 100644 index 00000000000..6a8018af412 --- /dev/null +++ b/test/form/samples/dynamic-import-inlining-array/foo.js @@ -0,0 +1 @@ +export const foo = 1; \ No newline at end of file diff --git a/test/form/samples/dynamic-import-inlining-array/main.js b/test/form/samples/dynamic-import-inlining-array/main.js new file mode 100644 index 00000000000..ee3e6a770d6 --- /dev/null +++ b/test/form/samples/dynamic-import-inlining-array/main.js @@ -0,0 +1,2 @@ +export const bar = 2; +import('./foo.js'); diff --git a/test/function/samples/banner-and-footer/_config.js b/test/function/samples/banner-and-footer/_config.js index b9b035d9318..40d3b05b3c8 100644 --- a/test/function/samples/banner-and-footer/_config.js +++ b/test/function/samples/banner-and-footer/_config.js @@ -1,8 +1,10 @@ module.exports = { description: 'adds a banner/footer', options: { - banner: '/* this is a banner */', - footer: () => Promise.resolve('/* this is a footer */'), + output: { + banner: '/* this is a banner */', + footer: () => Promise.resolve('/* this is a footer */') + }, plugins: [ { banner: '/* first banner */', diff --git a/test/function/samples/default-on-warn/_config.js b/test/function/samples/default-on-warn/_config.js new file mode 100644 index 00000000000..2ad6c83bb07 --- /dev/null +++ b/test/function/samples/default-on-warn/_config.js @@ -0,0 +1,27 @@ +const assert = require('assert'); +let oldConsoleWarn; +const warnings = []; + +module.exports = { + description: 'provides a default handler for warnings to onwarn that handles strings and objects', + options: { + onwarn(warning, defaultHandler) { + if (warning.code === 'EVAL') { + defaultHandler(warning); + } else { + defaultHandler(warning.message); + } + } + }, + before() { + oldConsoleWarn = console.warn; + console.warn = msg => warnings.push(msg); + }, + after() { + console.warn = oldConsoleWarn; + assert.deepStrictEqual(warnings, [ + 'Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification', + 'Entry module "main.js" is using named and default exports together. Consumers of your bundle will have to use `chunk["default"]` to access the default export, which may not be what you want. Use `output.exports: "named"` to disable this warning' + ]); + } +}; diff --git a/test/function/samples/default-on-warn/main.js b/test/function/samples/default-on-warn/main.js new file mode 100644 index 00000000000..dbf5aa85027 --- /dev/null +++ b/test/function/samples/default-on-warn/main.js @@ -0,0 +1,2 @@ +export const x = eval('42'); +export default 42; diff --git a/test/function/samples/deprecated/bundle-transformer-async/_config.js b/test/function/samples/deprecated/bundle-transformer-async/_config.js deleted file mode 100644 index 4d84050dc9f..00000000000 --- a/test/function/samples/deprecated/bundle-transformer-async/_config.js +++ /dev/null @@ -1,43 +0,0 @@ -module.exports = { - description: 'bundle transformers can be asynchronous', - options: { - strictDeprecations: false, - plugins: [ - { - transformBundle(code) { - return Promise.resolve(code.replace('x', 1)); - } - }, - { - transformBundle(code) { - return code.replace('1', 2); - } - }, - { - transformBundle(code) { - return Promise.resolve(code.replace('2', 3)); - } - } - ] - }, - warnings: [ - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - }, - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 2 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 2' - }, - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 3 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 3' - } - ] -}; diff --git a/test/function/samples/deprecated/bundle-transformer-async/main.js b/test/function/samples/deprecated/bundle-transformer-async/main.js deleted file mode 100644 index a09d9954e25..00000000000 --- a/test/function/samples/deprecated/bundle-transformer-async/main.js +++ /dev/null @@ -1 +0,0 @@ -assert.equal( x, 3 ); diff --git a/test/function/samples/deprecated/context-resolve-id/_config.js b/test/function/samples/deprecated/context-resolve-id/_config.js index feedd3f9114..b4b3c82b97c 100644 --- a/test/function/samples/deprecated/context-resolve-id/_config.js +++ b/test/function/samples/deprecated/context-resolve-id/_config.js @@ -17,10 +17,22 @@ module.exports = { } } }, - warnings(warnings) { - assert.strictEqual(warnings.length, 1); - assert.strictEqual(warnings[0].code, 'UNRESOLVED_IMPORT'); - }, + warnings: [ + { + code: 'DEPRECATED_FEATURE', + message: + 'The "this.resolveId" plugin context function used by plugin at position 1 is deprecated. The "this.resolve" plugin context function should be used instead.', + plugin: 'at position 1' + }, + { + code: 'UNRESOLVED_IMPORT', + importer: 'main.js', + message: + "'resolveto-unresolved' is imported by main.js, but could not be resolved – treating it as an external dependency", + source: 'resolveto-unresolved', + url: 'https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency' + } + ], options: { strictDeprecations: false, plugins: [ diff --git a/test/function/samples/deprecated/emit-chunk/no-input/_config.js b/test/function/samples/deprecated/emit-chunk/no-input/_config.js index 6b66a172055..7536323ba6a 100644 --- a/test/function/samples/deprecated/emit-chunk/no-input/_config.js +++ b/test/function/samples/deprecated/emit-chunk/no-input/_config.js @@ -9,5 +9,13 @@ module.exports = { this.emitChunk('chunk.js'); } } - } + }, + warnings: [ + { + code: 'DEPRECATED_FEATURE', + message: + 'The "this.emitChunk" plugin context function used by plugin test-plugin is deprecated. The "this.emitFile" plugin context function should be used instead.', + plugin: 'test-plugin' + } + ] }; diff --git a/test/function/samples/deprecated/keep-used-imports-from-pure-external-modules/_config.js b/test/function/samples/deprecated/keep-used-imports-from-pure-external-modules/_config.js index 9fdbec06592..45fe156dc40 100644 --- a/test/function/samples/deprecated/keep-used-imports-from-pure-external-modules/_config.js +++ b/test/function/samples/deprecated/keep-used-imports-from-pure-external-modules/_config.js @@ -14,5 +14,11 @@ module.exports = { if (id === 'warning') return arg => assert.equal(arg, 'hi'); throw new Error('Unexpected import', id); } - } + }, + warnings: [ + { + code: 'DEPRECATED_FEATURE', + message: `The "treeshake.pureExternalModules" option is deprecated. The "treeshake.moduleSideEffects" option should be used instead. "treeshake.pureExternalModules: true" is equivalent to "treeshake.moduleSideEffects: 'no-external'"` + } + ] }; diff --git a/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/_config.js b/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/_config.js deleted file mode 100644 index cb1bbbaa746..00000000000 --- a/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/_config.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - description: 'throws error only with first plugin transformBundle', - options: { - strictDeprecations: false, - plugins: [ - { - name: 'plugin1', - transformBundle() { - throw Error('Something happened 1'); - } - }, - { - name: 'plugin2', - transformBundle() { - throw Error('Something happened 2'); - } - } - ] - }, - generateError: { - code: 'BAD_BUNDLE_TRANSFORMER', - plugin: 'plugin1', - hook: 'transformBundle', - message: `Error transforming bundle with 'plugin1' plugin: Something happened 1` - } -}; diff --git a/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/main.js b/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/main.js deleted file mode 100644 index 296d5492b00..00000000000 --- a/test/function/samples/deprecated/plugin-error-only-first-transform-bundle/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log(1); diff --git a/test/function/samples/deprecations/ongenerate/_config.js b/test/function/samples/deprecations/ongenerate/_config.js deleted file mode 100644 index 4dcff7dd373..00000000000 --- a/test/function/samples/deprecations/ongenerate/_config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - description: 'marks the ongenerate hook as deprecated', - options: { - plugins: { - ongenerate() {} - } - }, - error: { - code: 'DEPRECATED_FEATURE', - message: - 'The "ongenerate" hook used by plugin at position 1 is deprecated. The "generateBundle" hook should be used instead.', - plugin: 'at position 1' - } -}; diff --git a/test/function/samples/deprecations/ongenerate/main.js b/test/function/samples/deprecations/ongenerate/main.js deleted file mode 100644 index f8a2d88d245..00000000000 --- a/test/function/samples/deprecations/ongenerate/main.js +++ /dev/null @@ -1,11 +0,0 @@ -const foo = {}; - -function doIt(x) { - if (foo[x]) { - return true; - } - foo[x] = true; -} - -doIt('x'); -assert.ok(doIt('x'), 'foo was not reassigned'); diff --git a/test/function/samples/deprecations/onwrite/_config.js b/test/function/samples/deprecations/onwrite/_config.js deleted file mode 100644 index 8a2a99d6c15..00000000000 --- a/test/function/samples/deprecations/onwrite/_config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - description: 'marks the onwrite hook as deprecated', - options: { - plugins: { - onwrite() {} - } - }, - error: { - code: 'DEPRECATED_FEATURE', - message: - 'The "onwrite" hook used by plugin at position 1 is deprecated. The "generateBundle/writeBundle" hook should be used instead.', - plugin: 'at position 1' - } -}; diff --git a/test/function/samples/deprecations/onwrite/main.js b/test/function/samples/deprecations/onwrite/main.js deleted file mode 100644 index f8a2d88d245..00000000000 --- a/test/function/samples/deprecations/onwrite/main.js +++ /dev/null @@ -1,11 +0,0 @@ -const foo = {}; - -function doIt(x) { - if (foo[x]) { - return true; - } - foo[x] = true; -} - -doIt('x'); -assert.ok(doIt('x'), 'foo was not reassigned'); diff --git a/test/function/samples/deprecations/transform-dependencies/_config.js b/test/function/samples/deprecations/transform-dependencies/_config.js deleted file mode 100644 index 91482c8b692..00000000000 --- a/test/function/samples/deprecations/transform-dependencies/_config.js +++ /dev/null @@ -1,22 +0,0 @@ -const path = require('path'); - -module.exports = { - description: 'marks transform dependencies as deprecated', - options: { - plugins: { - transform(code) { - return { code, dependencies: [] }; - } - } - }, - error: { - code: 'PLUGIN_ERROR', - hook: 'transform', - id: path.resolve(__dirname, 'main.js'), - message: - 'Returning "dependencies" from the "transform" hook as done by plugin at position 1 is deprecated. The "this.addWatchFile" plugin context function should be used instead.', - plugin: 'at position 1', - pluginCode: 'DEPRECATED_FEATURE', - watchFiles: [path.resolve(__dirname, 'main.js')] - } -}; diff --git a/test/function/samples/deprecations/transform-dependencies/main.js b/test/function/samples/deprecations/transform-dependencies/main.js deleted file mode 100644 index f8a2d88d245..00000000000 --- a/test/function/samples/deprecations/transform-dependencies/main.js +++ /dev/null @@ -1,11 +0,0 @@ -const foo = {}; - -function doIt(x) { - if (foo[x]) { - return true; - } - foo[x] = true; -} - -doIt('x'); -assert.ok(doIt('x'), 'foo was not reassigned'); diff --git a/test/function/samples/deprecations/transformBundle/_config.js b/test/function/samples/deprecations/transformBundle/_config.js deleted file mode 100644 index 3e2752922ce..00000000000 --- a/test/function/samples/deprecations/transformBundle/_config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - description: 'marks the transformBundle hook as deprecated', - options: { - plugins: { - transformBundle() { - return ''; - } - } - }, - error: { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - } -}; diff --git a/test/function/samples/deprecations/transformBundle/main.js b/test/function/samples/deprecations/transformBundle/main.js deleted file mode 100644 index f8a2d88d245..00000000000 --- a/test/function/samples/deprecations/transformBundle/main.js +++ /dev/null @@ -1,11 +0,0 @@ -const foo = {}; - -function doIt(x) { - if (foo[x]) { - return true; - } - foo[x] = true; -} - -doIt('x'); -assert.ok(doIt('x'), 'foo was not reassigned'); diff --git a/test/function/samples/deprecations/transformChunk/_config.js b/test/function/samples/deprecations/transformChunk/_config.js deleted file mode 100644 index 3d637c4f4dd..00000000000 --- a/test/function/samples/deprecations/transformChunk/_config.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - description: 'marks the transformChunk hook as deprecated', - options: { - plugins: { - transformChunk() { - return ''; - } - } - }, - error: { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformChunk" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - } -}; diff --git a/test/function/samples/deprecations/transformChunk/main.js b/test/function/samples/deprecations/transformChunk/main.js deleted file mode 100644 index f8a2d88d245..00000000000 --- a/test/function/samples/deprecations/transformChunk/main.js +++ /dev/null @@ -1,11 +0,0 @@ -const foo = {}; - -function doIt(x) { - if (foo[x]) { - return true; - } - foo[x] = true; -} - -doIt('x'); -assert.ok(doIt('x'), 'foo was not reassigned'); diff --git a/test/function/samples/dynamic-import-duplicates/_config.js b/test/function/samples/dynamic-import-duplicates/_config.js index 738fe24c655..9fd9be2f7c6 100644 --- a/test/function/samples/dynamic-import-duplicates/_config.js +++ b/test/function/samples/dynamic-import-duplicates/_config.js @@ -1,17 +1,9 @@ const assert = require('assert'); -const path = require('path'); module.exports = { description: 'Dynamic import inlining', options: { - inlineDynamicImports: true, - plugins: [ - { - resolveDynamicImport(specifier, parent) { - if (specifier === './main') return path.resolve(__dirname, 'main.js'); - } - } - ] + inlineDynamicImports: true }, exports(exports) { assert.equal(exports.x, 41); diff --git a/test/function/samples/dynamic-import-existing/_config.js b/test/function/samples/dynamic-import-existing/_config.js index 45b90f8f6e3..cc0a31d2825 100644 --- a/test/function/samples/dynamic-import-existing/_config.js +++ b/test/function/samples/dynamic-import-existing/_config.js @@ -1,17 +1,7 @@ const assert = require('assert'); -const path = require('path'); module.exports = { description: 'Dynamic import inlining when resolution id is a module in the bundle', - options: { - plugins: [ - { - resolveDynamicImport(specifier, parent) { - if (specifier === './main') return path.resolve(__dirname, 'main.js'); - } - } - ] - }, exports(exports) { assert.equal(exports.y, 42); return Promise.resolve(exports.promise).then(val => { diff --git a/test/function/samples/dynamic-import-expression/_config.js b/test/function/samples/dynamic-import-expression/_config.js index e759d62c9af..b06c2ee080f 100644 --- a/test/function/samples/dynamic-import-expression/_config.js +++ b/test/function/samples/dynamic-import-expression/_config.js @@ -5,7 +5,7 @@ module.exports = { options: { plugins: [ { - resolveDynamicImport(specifier, parent) { + resolveDynamicImport(specifier) { if (typeof specifier !== 'string') { // string literal concatenation if ( diff --git a/test/function/samples/dynamic-import-inlining/_config.js b/test/function/samples/dynamic-import-inlining/_config.js index 738fe24c655..9fd9be2f7c6 100644 --- a/test/function/samples/dynamic-import-inlining/_config.js +++ b/test/function/samples/dynamic-import-inlining/_config.js @@ -1,17 +1,9 @@ const assert = require('assert'); -const path = require('path'); module.exports = { description: 'Dynamic import inlining', options: { - inlineDynamicImports: true, - plugins: [ - { - resolveDynamicImport(specifier, parent) { - if (specifier === './main') return path.resolve(__dirname, 'main.js'); - } - } - ] + inlineDynamicImports: true }, exports(exports) { assert.equal(exports.x, 41); diff --git a/test/function/samples/dynamic-import-rewriting/_config.js b/test/function/samples/dynamic-import-rewriting/_config.js index a34764a8406..3680137bc34 100644 --- a/test/function/samples/dynamic-import-rewriting/_config.js +++ b/test/function/samples/dynamic-import-rewriting/_config.js @@ -6,7 +6,7 @@ module.exports = { external: ['asdf'], plugins: [ { - resolveDynamicImport(specifier, parent) { + resolveDynamicImport() { return 'asdf'; } } diff --git a/test/function/samples/fallback-on-warn/_config.js b/test/function/samples/fallback-on-warn/_config.js new file mode 100644 index 00000000000..ee7da5de099 --- /dev/null +++ b/test/function/samples/fallback-on-warn/_config.js @@ -0,0 +1,20 @@ +const assert = require('assert'); +let oldConsoleWarn; +const warnings = []; + +module.exports = { + description: 'logs as a fallback if no onwarn handler is provided', + options: { + onwarn: null + }, + before() { + oldConsoleWarn = console.warn; + console.warn = msg => warnings.push(msg); + }, + after() { + console.warn = oldConsoleWarn; + assert.deepStrictEqual(warnings, [ + 'Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification' + ]); + } +}; diff --git a/test/function/samples/fallback-on-warn/main.js b/test/function/samples/fallback-on-warn/main.js new file mode 100644 index 00000000000..8972e2933ec --- /dev/null +++ b/test/function/samples/fallback-on-warn/main.js @@ -0,0 +1 @@ +export const x = eval('42'); diff --git a/test/function/samples/inline-imports-with-multiple/_config.js b/test/function/samples/inline-imports-with-multiple-array/_config.js similarity index 68% rename from test/function/samples/inline-imports-with-multiple/_config.js rename to test/function/samples/inline-imports-with-multiple-array/_config.js index 4b5bfd77774..4164867fe1c 100644 --- a/test/function/samples/inline-imports-with-multiple/_config.js +++ b/test/function/samples/inline-imports-with-multiple-array/_config.js @@ -1,5 +1,5 @@ module.exports = { - description: 'Having multiple inputs is not supported when inlining dynamic imports', + description: 'Having multiple inputs in an array is not supported when inlining dynamic imports', options: { input: ['main.js', 'lib.js'], inlineDynamicImports: true diff --git a/test/function/samples/inline-imports-with-multiple/lib.js b/test/function/samples/inline-imports-with-multiple-array/lib.js similarity index 100% rename from test/function/samples/inline-imports-with-multiple/lib.js rename to test/function/samples/inline-imports-with-multiple-array/lib.js diff --git a/test/function/samples/inline-imports-with-multiple/main.js b/test/function/samples/inline-imports-with-multiple-array/main.js similarity index 100% rename from test/function/samples/inline-imports-with-multiple/main.js rename to test/function/samples/inline-imports-with-multiple-array/main.js diff --git a/test/function/samples/inline-imports-with-multiple-object/_config.js b/test/function/samples/inline-imports-with-multiple-object/_config.js new file mode 100644 index 00000000000..417b1ccdc15 --- /dev/null +++ b/test/function/samples/inline-imports-with-multiple-object/_config.js @@ -0,0 +1,11 @@ +module.exports = { + description: 'Having multiple inputs in an object is not supported when inlining dynamic imports', + options: { + input: { main: 'main.js', lib: 'lib.js' }, + inlineDynamicImports: true + }, + error: { + code: 'INVALID_OPTION', + message: 'Multiple inputs are not supported for "inlineDynamicImports".' + } +}; diff --git a/test/function/samples/inline-imports-with-multiple-object/lib.js b/test/function/samples/inline-imports-with-multiple-object/lib.js new file mode 100644 index 00000000000..46d3ca8c61f --- /dev/null +++ b/test/function/samples/inline-imports-with-multiple-object/lib.js @@ -0,0 +1 @@ +export const value = 42; diff --git a/test/function/samples/inline-imports-with-multiple-object/main.js b/test/function/samples/inline-imports-with-multiple-object/main.js new file mode 100644 index 00000000000..4869dc82f38 --- /dev/null +++ b/test/function/samples/inline-imports-with-multiple-object/main.js @@ -0,0 +1 @@ +import('./lib').then(({value}) => assert.equal(value, 42)); diff --git a/test/function/samples/plugin-warn/_config.js b/test/function/samples/plugin-warn/_config.js index 80cf24b78d6..ff0640f12ab 100644 --- a/test/function/samples/plugin-warn/_config.js +++ b/test/function/samples/plugin-warn/_config.js @@ -6,8 +6,8 @@ module.exports = { plugins: [ { name: 'test', - transform(code, id) { - this.warn({ message: 'foo' }); + transform() { + this.warn({ message: 'foo', code: 'CODE' }); this.warn('bar', 22); return 'assert.equal( 21 * 2, 42 );'; } @@ -20,7 +20,8 @@ module.exports = { id: path.resolve(__dirname, 'main.js'), hook: 'transform', plugin: 'test', - message: 'foo' + message: 'foo', + pluginCode: 'CODE' }, { code: 'PLUGIN_WARNING', diff --git a/test/function/samples/warns-for-invalid-options/_config.js b/test/function/samples/warns-for-invalid-options/_config.js new file mode 100644 index 00000000000..d4bdcdbefb7 --- /dev/null +++ b/test/function/samples/warns-for-invalid-options/_config.js @@ -0,0 +1,23 @@ +module.exports = { + description: 'warns for invalid options', + options: { + myInvalidInputOption: true, + output: { + myInvalidOutputOption: true + } + }, + warnings: [ + { + code: 'UNKNOWN_OPTION', + message: + 'Unknown input options: myInvalidInputOption. Allowed options: ' + + require('../../../misc/optionList').input + }, + { + code: 'UNKNOWN_OPTION', + message: + 'Unknown output options: myInvalidOutputOption. Allowed options: ' + + require('../../../misc/optionList').output + } + ] +}; diff --git a/test/function/samples/warns-for-invalid-options/main.js b/test/function/samples/warns-for-invalid-options/main.js new file mode 100644 index 00000000000..7a4e8a723a4 --- /dev/null +++ b/test/function/samples/warns-for-invalid-options/main.js @@ -0,0 +1 @@ +export default 42; diff --git a/test/hooks/index.js b/test/hooks/index.js index 904775bef7f..873a9a1906c 100644 --- a/test/hooks/index.js +++ b/test/hooks/index.js @@ -786,6 +786,12 @@ describe('hooks', () => { this.cache.set('asdf', 'asdf'); return `alert('hello world')`; } + }, + { + name: 'y', + transform(code) { + return code + `;alert('world')`; + } } ] }) @@ -804,6 +810,12 @@ describe('hooks', () => { assert.ok(!this.cache.has('asdf')); return `alert('hello')`; } + }, + { + name: 'y', + transform(code) { + return code + `;alert('world')`; + } } ] }) @@ -814,7 +826,7 @@ describe('hooks', () => { }) ) .then(({ output }) => { - assert.strictEqual(output[0].code.trim(), `alert('hello');`); + assert.strictEqual(output[0].code.trim(), `alert('hello');alert('world');`); })); it('supports renderStart hook', () => { @@ -890,51 +902,6 @@ describe('hooks', () => { }); }); - it('Warns once when using deprecated this.watcher in plugins', () => { - const warnings = []; - const watcher = rollup.watch({ - input: 'input', - onwarn(warning) { - warnings.push(warning); - }, - output: { - format: 'esm' - }, - plugins: [ - loader({ input: `alert('hello')` }), - { - name: 'x', - buildStart() { - this.watcher.on('change', () => {}); - this.watcher.on('change', () => {}); - } - } - ] - }); - return new Promise((resolve, reject) => { - watcher.on('event', event => { - if (event.code === 'BUNDLE_END') resolve(); - else if (event.code === 'ERROR') reject(event.error); - }); - }) - .catch(err => { - watcher.close(); - assert.strictEqual( - err.message, - 'You must specify "output.file" or "output.dir" for the build.' - ); - assert.strictEqual(warnings.length, 1); - const warning = warnings[0]; - assert.strictEqual(warning.code, 'PLUGIN_WARNING'); - assert.strictEqual(warning.pluginCode, 'PLUGIN_WATCHER_DEPRECATED'); - assert.strictEqual( - warning.message, - 'this.watcher usage is deprecated in plugins. Use the watchChange plugin hook and this.addWatchFile() instead.' - ); - }) - .then(() => watcher.close()); - }); - it('Throws when not specifying "file" or "dir"', () => { const watcher = rollup.watch({ input: 'input', @@ -978,7 +945,7 @@ describe('hooks', () => { watcher.close(); assert.strictEqual( err.message, - 'You must set "output.dir" instead of "output.file" when generating multiple chunks.' + 'When building multiple chunks, the "output.dir" option must be used, not "output.file". To inline dynamic imports, set the "inlineDynamicImports" option.' ); }) .then(() => watcher.close()); @@ -1077,7 +1044,7 @@ describe('hooks', () => { input: `alert('hello')` }), { - augmentChunkHash(update) { + augmentChunkHash() { augmentChunkHashCalls++; assert(this.meta); assert(this.meta.rollupVersion); @@ -1097,184 +1064,30 @@ describe('hooks', () => { }); }); - describe('deprecated', () => { - it('passes bundle & output object to ongenerate & onwrite hooks, with deprecation warnings', () => { - let deprecationCnt = 0; - - return rollup - .rollup({ - input: 'input', - onwarn(warning) { - deprecationCnt++; - if (deprecationCnt === 1) { - assert.strictEqual(warning.code, 'DEPRECATED_FEATURE'); - assert.strictEqual( - warning.message, - 'The "ongenerate" hook used by plugin at position 2 is deprecated. The "generateBundle" hook should be used instead.' - ); - } else { - assert.strictEqual(warning.code, 'DEPRECATED_FEATURE'); + it('passes bundle object to generateBundle hook', () => + rollup + .rollup({ + input: 'input', + plugins: [ + loader({ input: `alert('hello')` }), + { + transform() { + const assetId = this.emitAsset('test.ext', 'hello world'); + return `export default import.meta.ROLLUP_ASSET_URL_${assetId};`; + }, + generateBundle(options, outputBundle, isWrite) { + assert.strictEqual(outputBundle['assets/test-0a676135.ext'].source, 'hello world'); assert.strictEqual( - warning.message, - 'The "onwrite" hook used by plugin at position 2 is deprecated. The "generateBundle/writeBundle" hook should be used instead.' + outputBundle['input.js'].code, + `var input = new URL('assets/test-0a676135.ext', import.meta.url).href;\n\nexport default input;\n` ); } - }, - plugins: [ - loader({ input: `alert('hello')` }), - { - ongenerate(bundle, out) { - out.ongenerate = true; - }, - - onwrite(bundle, out) { - assert.strictEqual(out.ongenerate, true); - } - } - ] - }) - .then(bundle => - bundle.write({ - file: path.join(TEMP_DIR, 'bundle.js'), - format: 'es' - }) - ) - .then(() => { - assert.strictEqual(deprecationCnt, 2); - return sander.rimraf(TEMP_DIR); - }); - }); - - it('calls ongenerate hooks in sequence', () => { - const result = []; - - return rollup - .rollup({ - input: 'input', - plugins: [ - loader({ input: `alert('hello')` }), - { - ongenerate(info) { - result.push({ a: info.format }); - } - }, - { - ongenerate(info) { - result.push({ b: info.format }); - } - } - ] - }) - .then(bundle => bundle.generate({ format: 'cjs' })) - .then(() => { - assert.deepEqual(result, [{ a: 'cjs' }, { b: 'cjs' }]); - }); - }); - - it('calls onwrite hooks in sequence', () => { - const result = []; - const file = path.join(TEMP_DIR, 'bundle.js'); - - return rollup - .rollup({ - input: 'input', - plugins: [ - loader({ input: `alert('hello')` }), - { - onwrite(info) { - return new Promise(fulfil => { - setTimeout(() => { - result.push({ a: info.file, format: info.format }); - fulfil(); - }, 10); - }); - } - }, - { - onwrite(info) { - result.push({ b: info.file, format: info.format }); - } - } - ] - }) - .then(bundle => - bundle.write({ - file, - format: 'cjs' - }) - ) - .then(() => { - assert.deepEqual(result, [ - { a: file, format: 'cjs' }, - { b: file, format: 'cjs' } - ]); - return sander.rimraf(TEMP_DIR); - }); - }); - - it('supports transformChunk in place of transformBundle, with deprecation warning', () => { - let calledHook = false; - let deprecationCnt = 0; - return rollup - .rollup({ - input: 'input', - onwarn(warning) { - deprecationCnt++; - assert.strictEqual(warning.code, 'DEPRECATED_FEATURE'); - assert.strictEqual( - warning.message, - 'The "transformChunk" hook used by plugin at position 2 is deprecated. The "renderChunk" hook should be used instead.' - ); - }, - plugins: [ - loader({ input: `alert('hello')` }), - { - transformChunk(code, id) { - calledHook = true; - try { - this.emitAsset('test.ext', 'hello world'); - } catch (e) { - assert.strictEqual(e.code, 'ASSETS_ALREADY_FINALISED'); - } - } - } - ] - }) - .then(bundle => - bundle.generate({ - format: 'es', - assetFileNames: '[name][extname]' - }) - ) - .then(() => { - assert.strictEqual(deprecationCnt, 1); - assert.strictEqual(calledHook, true); - }); - }); - - it('passes bundle object to generateBundle hook', () => - rollup - .rollup({ - input: 'input', - plugins: [ - loader({ input: `alert('hello')` }), - { - transform() { - const assetId = this.emitAsset('test.ext', 'hello world'); - return `export default import.meta.ROLLUP_ASSET_URL_${assetId};`; - }, - generateBundle(options, outputBundle, isWrite) { - assert.strictEqual(outputBundle['assets/test-0a676135.ext'].source, 'hello world'); - assert.strictEqual( - outputBundle['input.js'].code, - `var input = new URL('assets/test-0a676135.ext', import.meta.url).href;\n\nexport default input;\n` - ); - } - } - ] - }) - .then(bundle => bundle.generate({ format: 'es' }))); + } + ] + }) + .then(bundle => bundle.generate({ format: 'es' }))); + describe('deprecated', () => { it('caches chunk emission in transform hook', () => { let cache; return rollup diff --git a/test/misc/deprecations.js b/test/misc/deprecations.js index d09dce716ba..ff6e0a6e2b1 100644 --- a/test/misc/deprecations.js +++ b/test/misc/deprecations.js @@ -3,30 +3,6 @@ const rollup = require('../../dist/rollup'); const { loader } = require('../utils.js'); describe('deprecations', () => { - it('throws a useful error on accessing code/map properties of bundle.generate promise', () => { - return rollup - .rollup({ - input: 'x', - plugins: [loader({ x: `console.log( 42 );` })] - }) - .then(bundle => { - let errored = false; - - try { - const { code, map } = bundle.generate({ format: 'es' }); - console.log(code, map); - } catch (err) { - assert.equal( - err.message, - `bundle.generate(...) now returns a Promise instead of a { code, map } object` - ); - errored = true; - } - - assert.ok(errored); - }); - }); - it('supports esm format alias', () => { return rollup .rollup({ input: 'x', plugins: [loader({ x: 'export const x = function () {}' })] }) diff --git a/test/misc/sanity-checks.js b/test/misc/sanity-checks.js index 7ac9a17c1e3..e5371fb98a0 100644 --- a/test/misc/sanity-checks.js +++ b/test/misc/sanity-checks.js @@ -27,7 +27,7 @@ describe('sanity checks', () => { return rollup .rollup({ input: 'x', - plugins: [loader({ x: `console.log( 42 );` }), { ongenerate() {} }], + plugins: [loader({ x: `eval(42);` })], onwarn(warning, onwarn) { args = [warning, onwarn]; } @@ -36,10 +36,10 @@ describe('sanity checks', () => { return bundle.generate({ format: 'es' }); }) .then(() => { - assert.equal(args[0].code, 'DEPRECATED_FEATURE'); + assert.equal(args[0].code, 'EVAL'); assert.equal( args[0].message, - 'The "ongenerate" hook used by plugin at position 2 is deprecated. The "generateBundle" hook should be used instead.' + 'Use of eval is strongly discouraged, as it poses security risks and may cause issues with minification' ); assert.equal(typeof args[1], 'function'); }); @@ -56,22 +56,6 @@ describe('sanity checks', () => { }); }); - it('fails with invalid keys', () => { - const warnings = []; - const onwarn = warning => warnings.push(warning); - return rollup - .rollup({ input: 'x', onwarn, plUgins: [], plugins: [loader({ x: `console.log( 42 );` })] }) - .then(() => { - assert.deepEqual(warnings, [ - { - code: 'UNKNOWN_OPTION', - message: - 'Unknown input option: plUgins. Allowed options: ' + require('./optionList').input - } - ]); - }); - }); - it('treats Literals as leaf nodes, even if first literal encountered is null', () => { // this test has to be up here, otherwise the bug doesn't have // an opportunity to present itself @@ -184,7 +168,7 @@ describe('sanity checks', () => { .then(bundle => { assert.throws(() => { bundle.generate({ file: 'x', format: 'es' }); - }, /You must set "output\.dir" instead of "output\.file" when generating multiple chunks\./); + }, /When building multiple chunks, the "output\.dir" option must be used, not "output\.file"\. To inline dynamic imports, set the "inlineDynamicImports" option\./); }); }); @@ -212,7 +196,7 @@ describe('sanity checks', () => { .then(bundle => { assert.throws(() => { bundle.generate({ file: 'x', format: 'es' }); - }, /You must set "output\.dir" instead of "output\.file" when generating multiple chunks\./); + }, /When building multiple chunks, the "output\.dir" option must be used, not "output\.file"\. To inline dynamic imports, set the "inlineDynamicImports" option\./); }); }); diff --git a/test/misc/write-bundle.js b/test/misc/write-bundle.js index 6df9bf9bcff..6b2e4adc474 100644 --- a/test/misc/write-bundle.js +++ b/test/misc/write-bundle.js @@ -25,28 +25,6 @@ describe('bundle.write()', () => { }); }); - it('throws on es6 format', () => { - return rollup - .rollup({ - input: 'x', - plugins: [ - { - resolveId: () => { - return 'test'; - }, - load: () => { - return '// empty'; - } - } - ] - }) - .then(bundle => { - assert.throws(() => { - return bundle.generate({ format: 'es6' }); - }, /The "es6" output format is deprecated – use "esm" instead/); - }); - }); - it('works when output options is an array', () => { const warnings = []; const options = { diff --git a/test/sourcemaps/samples/deprecated/names-transformed/_config.js b/test/sourcemaps/samples/deprecated/names-transformed/_config.js deleted file mode 100644 index 07d57c3868e..00000000000 --- a/test/sourcemaps/samples/deprecated/names-transformed/_config.js +++ /dev/null @@ -1,71 +0,0 @@ -const assert = require('assert'); -const terser = require('terser'); -const MagicString = require('magic-string'); -const getLocation = require('../../../getLocation'); -const SourceMapConsumer = require('source-map').SourceMapConsumer; - -module.exports = { - description: 'names are recovered if transformBundle is used', - options: { - strictDeprecations: false, - plugins: [ - { - transform(code) { - const s = new MagicString(code); - const pattern = /mangleMe/g; - let match; - - while ((match = pattern.exec(code))) { - s.overwrite(match.index, match.index + match[0].length, 'mangleMePlease', { - storeName: true, - contentOnly: false - }); - } - - return { - code: s.toString(), - map: s.generateMap({ hires: true }) - }; - }, - transformBundle(code) { - return terser.minify(code, { - sourceMap: { - filename: 'x' - } - }); - } - } - ] - }, - warnings: [ - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - } - ], - test(code, map) { - const smc = new SourceMapConsumer(map); - - let generatedLoc = getLocation(code, /\w+=["']this/.exec(code).index); - let originalLoc = smc.originalPositionFor(generatedLoc); - - assert.deepEqual(originalLoc, { - source: '../a.js', - line: 1, - column: 4, - name: 'mangleMe' - }); - - generatedLoc = getLocation(code, /\w+=["']nor/.exec(code).index); - originalLoc = smc.originalPositionFor(generatedLoc); - - assert.deepEqual(originalLoc, { - source: '../b.js', - line: 1, - column: 4, - name: 'mangleMe' - }); - } -}; diff --git a/test/sourcemaps/samples/deprecated/names-transformed/a.js b/test/sourcemaps/samples/deprecated/names-transformed/a.js deleted file mode 100644 index 2f669b00807..00000000000 --- a/test/sourcemaps/samples/deprecated/names-transformed/a.js +++ /dev/null @@ -1,4 +0,0 @@ -var mangleMe = "this string should not be inlined".toLowerCase(); -export default function () { - assert.equal( mangleMe, 1 ); -} diff --git a/test/sourcemaps/samples/deprecated/names-transformed/b.js b/test/sourcemaps/samples/deprecated/names-transformed/b.js deleted file mode 100644 index 94a508a7471..00000000000 --- a/test/sourcemaps/samples/deprecated/names-transformed/b.js +++ /dev/null @@ -1,4 +0,0 @@ -var mangleMe = "nor should this one".toLowerCase(); -export default function () { - assert.equal( mangleMe, 2 ); -} diff --git a/test/sourcemaps/samples/deprecated/names-transformed/main.js b/test/sourcemaps/samples/deprecated/names-transformed/main.js deleted file mode 100644 index 1cc1b21f1a8..00000000000 --- a/test/sourcemaps/samples/deprecated/names-transformed/main.js +++ /dev/null @@ -1,5 +0,0 @@ -import a from './a.js'; -import b from './b.js'; - -a(); -b(); diff --git a/test/sourcemaps/samples/deprecated/transform-bundle-babili/_config.js b/test/sourcemaps/samples/deprecated/transform-bundle-babili/_config.js deleted file mode 100644 index 646d5590c83..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-bundle-babili/_config.js +++ /dev/null @@ -1,45 +0,0 @@ -const babiliResults = require('./babili-results'); -const assert = require('assert'); -const getLocation = require('../../../getLocation'); -const SourceMapConsumer = require('source-map').SourceMapConsumer; - -module.exports = { - description: 'generates valid sourcemap when source could not be determined via transformBundle', - options: { - strictDeprecations: false, - plugins: [ - { - transformBundle(code, options) { - const format = options.format; - - return babiliResults[format]; - } - } - ], - output: { indent: false } - }, - warnings: [ - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - } - ], - test(code, map) { - const smc = new SourceMapConsumer(map); - - let generatedLoc = getLocation(code, code.indexOf('42')); - let originalLoc = smc.originalPositionFor(generatedLoc); - - assert.ok(/main/.test(originalLoc.source)); - assert.equal(originalLoc.line, 1); - assert.equal(originalLoc.column, 13); - - generatedLoc = getLocation(code, code.indexOf('log')); - originalLoc = smc.originalPositionFor(generatedLoc); - - assert.equal(originalLoc.line, 1); - assert.equal(originalLoc.column, 8); - } -}; diff --git a/test/sourcemaps/samples/deprecated/transform-bundle-babili/babili-results.js b/test/sourcemaps/samples/deprecated/transform-bundle-babili/babili-results.js deleted file mode 100644 index 765981f3528..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-bundle-babili/babili-results.js +++ /dev/null @@ -1,5 +0,0 @@ -exports.amd = {"code":"define(function(){'use strict';console.log(42)});","map":{"version":3,"sources":["unknown"],"names":["define","console","log"],"mappings":"AAAAA,OAAO,UAAY,CAAE,aAErBC,QAAQC,GAAR,CAAa,EAAb,CAEC,CAJD,C","file":"unknown","sourcesContent":["define(function () { 'use strict';\n\nconsole.log( 42 );\n\n});"]}}; -exports.cjs = {"code":"'use strict';console.log(42);","map":{"version":3,"sources":["unknown"],"names":["console","log"],"mappings":"AAAA,aAEAA,QAAQC,GAAR,CAAa,EAAb,C","file":"unknown","sourcesContent":["'use strict';\n\nconsole.log( 42 );"]}}; -exports.es = {"code":"console.log(42);","map":{"version":3,"sources":["unknown"],"names":["console","log"],"mappings":"AAAAA,QAAQC,GAAR,CAAa,EAAb,C","file":"unknown","sourcesContent":["console.log( 42 );"]}}; -exports.iife = {"code":"(function(){'use strict';console.log(42)})();","map":{"version":3,"sources":["unknown"],"names":["console","log"],"mappings":"AAAC,WAAY,CACb,aAEAA,QAAQC,GAAR,CAAa,EAAb,CAEC,CALA,G","file":"unknown","sourcesContent":["(function () {\n'use strict';\n\nconsole.log( 42 );\n\n}());"]}}; -exports.umd = {"code":"(function(a){'function'==typeof define&&define.amd?define(a):a()})(function(){'use strict';console.log(42)});","map":{"version":3,"sources":["unknown"],"names":["define","amd","console","log"],"mappings":"AAAC,YAAmB,CACF,UAAlB,QAAOA,OAAP,EAAgCA,OAAOC,GAAvC,CAA6CD,SAA7C,CACA,GACC,CAHA,EAGC,UAAY,CAAE,aAEhBE,QAAQC,GAAR,CAAa,EAAb,CAEC,CAPA,C","file":"main.js","sourcesContent":["(function (factory) {\ntypeof define === 'function' && define.amd ? define(factory) :\nfactory();\n}(function () { 'use strict';\n\nconsole.log( 42 );\n\n}));\n"]}}; diff --git a/test/sourcemaps/samples/deprecated/transform-bundle-babili/main.js b/test/sourcemaps/samples/deprecated/transform-bundle-babili/main.js deleted file mode 100644 index 5c72ff35124..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-bundle-babili/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log( 42 ); diff --git a/test/sourcemaps/samples/deprecated/transform-bundle/_config.js b/test/sourcemaps/samples/deprecated/transform-bundle/_config.js deleted file mode 100644 index c96e12cb2e9..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-bundle/_config.js +++ /dev/null @@ -1,48 +0,0 @@ -const terser = require('terser'); -const assert = require('assert'); -const getLocation = require('../../../getLocation'); -const SourceMapConsumer = require('source-map').SourceMapConsumer; - -module.exports = { - description: 'preserves sourcemap chains when transforming the bundle', - options: { - strictDeprecations: false, - plugins: [ - { - transformBundle(code) { - const options = { - sourceMap: { - filename: 'x' // trigger sourcemap generation - } - }; - - return terser.minify(code, options); - } - } - ] - }, - warnings: [ - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin at position 1 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'at position 1' - } - ], - test(code, map) { - const smc = new SourceMapConsumer(map); - - let generatedLoc = getLocation(code, code.indexOf('42')); - let originalLoc = smc.originalPositionFor(generatedLoc); - - assert.ok(/main/.test(originalLoc.source)); - assert.equal(originalLoc.line, 1); - assert.equal(originalLoc.column, 13); - - generatedLoc = getLocation(code, code.indexOf('log')); - originalLoc = smc.originalPositionFor(generatedLoc); - - assert.equal(originalLoc.line, 1); - assert.equal(originalLoc.column, 8); - } -}; diff --git a/test/sourcemaps/samples/deprecated/transform-bundle/main.js b/test/sourcemaps/samples/deprecated/transform-bundle/main.js deleted file mode 100644 index 5c72ff35124..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-bundle/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log( 42 ); diff --git a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js deleted file mode 100644 index 7c99723aa26..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/_config.js +++ /dev/null @@ -1,37 +0,0 @@ -module.exports = { - description: 'preserves sourcemap chains when transforming the bundle', - options: { - strictDeprecations: false, - plugins: [ - { - name: 'fake plugin 1', - transform(code) { - return code; - } - }, - { - name: 'fake plugin 2', - transform(code) { - return { code, map: null }; - }, - transformBundle(code) { - return { code, map: null }; - } - } - ] - }, - warnings: [ - { - code: 'DEPRECATED_FEATURE', - message: - 'The "transformBundle" hook used by plugin fake plugin 2 is deprecated. The "renderChunk" hook should be used instead.', - plugin: 'fake plugin 2' - }, - { - code: `SOURCEMAP_BROKEN`, - plugin: 'fake plugin 1', - message: `Sourcemap is likely to be incorrect: a plugin (fake plugin 1) was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help`, - url: `https://rollupjs.org/guide/en/#warning-sourcemap-is-likely-to-be-incorrect` - } - ] -}; diff --git a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/main.js b/test/sourcemaps/samples/deprecated/transform-without-sourcemap/main.js deleted file mode 100644 index 5c72ff35124..00000000000 --- a/test/sourcemaps/samples/deprecated/transform-without-sourcemap/main.js +++ /dev/null @@ -1 +0,0 @@ -console.log( 42 ); diff --git a/test/watch/index.js b/test/watch/index.js index bc85b481177..ce65f700f8c 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -1051,6 +1051,8 @@ describe('rollup.watch', () => { } } }); + const events = []; + watcher.on('event', event => events.push(event.code)); return sequence(watcher, [ 'START', @@ -1059,6 +1061,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 'initial'); + addWatchFile = false; sander.writeFileSync('test/_tmp/input/watched', 'next'); }, 'START', @@ -1072,7 +1075,8 @@ describe('rollup.watch', () => { }); }); - it('respects changed watched files in the transform hook', () => { + it('respects changed watched files in the transform hook and removes them if they are no longer watched', () => { + let addWatchFile = true; return sander .copydir('test/watch/samples/watch-files') .to('test/_tmp/input') @@ -1098,7 +1102,9 @@ describe('rollup.watch', () => { if (id.endsWith('main.js')) { return `export { value as default } from 'dep';`; } else { - this.addWatchFile('test/_tmp/input/watched'); + if (addWatchFile) { + this.addWatchFile('test/_tmp/input/watched'); + } return `export const value = "${sander .readFileSync('test/_tmp/input/watched') .toString() @@ -1123,6 +1129,9 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 'next'); + sander.writeFileSync('test/_tmp/input/watched', 'other'); + events.length = 0; + return wait(400).then(() => assert.deepStrictEqual(events, [])); } ]); }); @@ -1130,7 +1139,7 @@ describe('rollup.watch', () => { it('respects changed watched modules that are already part of the graph in the transform hook', () => { return sander - .copydir('test/watch/samples/watch-files') + .copydir('test/watch/samples/dependencies') .to('test/_tmp/input') .then(() => { watcher = rollup.watch({ @@ -1140,12 +1149,15 @@ describe('rollup.watch', () => { format: 'cjs' }, plugins: { - transform() { - this.addWatchFile('test/_tmp/input/main.js'); - return `export default "${sander - .readFileSync('test/_tmp/input/main.js') - .toString() - .trim()}"`; + transform(code, id) { + if (id.endsWith('dep1.js')) { + this.addWatchFile(path.resolve('test/_tmp/input/dep2.js')); + const text = sander + .readFileSync('test/_tmp/input/dep2.js') + .toString() + .trim(); + return `export default ${JSON.stringify(text)}`; + } } } }); @@ -1156,15 +1168,21 @@ describe('rollup.watch', () => { 'BUNDLE_END', 'END', () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'export default 42;'); - sander.writeFileSync('test/_tmp/input/main.js', 'next'); + assert.strictEqual( + run('../_tmp/output/bundle.js'), + `dep1: "export default 'dep2';", dep2: "dep2"` + ); + sander.writeFileSync('test/_tmp/input/dep2.js', 'export default "next";'); }, 'START', 'BUNDLE_START', 'BUNDLE_END', 'END', () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'next'); + assert.strictEqual( + run('../_tmp/output/bundle.js'), + `dep1: "export default "next";", dep2: "next"` + ); } ]); }); @@ -1259,379 +1277,4 @@ describe('rollup.watch', () => { }); }); }); - - describe('deprecated features', () => { - it('provides the watcher through the plugin context', () => { - const events = []; - return sander - .copydir('test/watch/samples/basic') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - onwarn(warning) { - assert.strictEqual( - warning.message, - 'this.watcher usage is deprecated in plugins. Use the watchChange plugin hook and this.addWatchFile() instead.' - ); - }, - plugins: { - buildStart(id) { - if (!this.watcher) throw new Error('No Watcher'); - - this.watcher.on('event', event => { - events.push(event); - }); - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(events.length, 2); - assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 43); - assert.strictEqual(events.length, 8); - } - ]); - }); - }); - - it('watches and rebuilds transform dependencies', () => { - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform() { - return { - code: `export default "${sander - .readFileSync('test/_tmp/input/watched') - .toString() - .trim()}"`, - dependencies: ['./watched'] - }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'initial'); - sander.writeFileSync('test/_tmp/input/watched', 'next'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'next'); - } - ]); - }); - }); - - it('watches and rebuilds transform dependencies that are modules', () => { - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform() { - const dependencies = ['./main.js']; - const text = sander - .readFileSync('test/_tmp/input/main.js') - .toString() - .trim(); - return { code: `export default "${text}"`, dependencies }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'export default 42;'); - sander.writeFileSync('test/_tmp/input/main.js', 'next'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 'next'); - } - ]); - }); - }); - - it('watches and rebuilds transform dependencies directories', () => { - let v = 1; - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform() { - const dependencies = ['./']; - return { code: `export default ${v++}`, dependencies }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 1); - sander.unlinkSync('test/_tmp/input/watched'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 2); - watcher.close(); - } - ]); - }); - }); - - it('watches and rebuilds transform dependencies, with transform cache opt-out for custom cache', () => { - const file = 'test/_tmp/input/watched'; - let v = 1; - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - name: 'x', - buildStart() { - try { - const text = sander.readFileSync(file).toString(); - this.emitAsset('test', text); - } catch (err) { - if (err.code !== 'ENOENT') throw err; - } - }, - transform() { - this.cache.set('someValue', 'someContent'); - return { code: `export default ${v++}`, dependencies: [path.resolve(file)] }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 1); - sander.unlinkSync('test/_tmp/input/watched'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 2); - } - ]); - }); - }); - - it('watches and rebuilds asset transform dependencies', () => { - let v = 1; - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform() { - const file = 'test/_tmp/input/watched'; - try { - const text = sander.readFileSync(file).toString(); - this.emitAsset('test', text); - } catch (err) { - if (err.code !== 'ENOENT') throw err; - this.emitAsset('test', 'test'); - } - return { - code: `export default ${v++}`, - dependencies: v === 2 ? [path.resolve(file)] : [] - }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 1); - sander.unlinkSync('test/_tmp/input/watched'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 2); - } - ]); - }); - }); - - it('watches and rebuilds transform dependencies created and removed between runs', () => { - let v = 1; - return sander - .copydir('test/watch/samples/watch-files') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/main.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform() { - let dependencies = []; - if (v === 2) dependencies = ['./watched']; - return { code: `export default ${v++}`, dependencies }; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 1); - sander.writeFileSync('test/_tmp/input/main.js', 'next'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 2); - sander.unlinkSync('test/_tmp/input/watched'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.strictEqual(run('../_tmp/output/bundle.js'), 3); - sander.writeFileSync('test/_tmp/input/watched', 'ignored'); - return new Promise(resolve => setTimeout(resolve, 50)); - } - ]); - }); - }); - - it('watches transform dependencies when there are multiple modules', () => { - let v = 1; - return sander - .copydir('test/watch/samples/watch-files-multiple') - .to('test/_tmp/input') - .then(() => { - watcher = rollup.watch({ - input: 'test/_tmp/input/index.js', - output: { - file: 'test/_tmp/output/bundle.js', - format: 'cjs' - }, - plugins: { - transform(code, id) { - if (!id.includes('dep.txt')) { - return; - } - this.addWatchFile('test/_tmp/input/depdep.txt'); - return `export default ${v++};`; - } - } - }); - - return sequence(watcher, [ - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.deepStrictEqual(run('../_tmp/output/bundle.js'), { dep: 1, first: 'b' }); - sander.writeFileSync('test/_tmp/input/depdep.txt', 'changed'); - }, - 'START', - 'BUNDLE_START', - 'BUNDLE_END', - 'END', - () => { - assert.deepStrictEqual(run('../_tmp/output/bundle.js'), { dep: 2, first: 'b' }); - } - ]); - }); - }); - }); }); diff --git a/test/watch/samples/dependencies/dep1.js b/test/watch/samples/dependencies/dep1.js new file mode 100644 index 00000000000..0abd7bb7ffa --- /dev/null +++ b/test/watch/samples/dependencies/dep1.js @@ -0,0 +1 @@ +export default 'dep1'; diff --git a/test/watch/samples/dependencies/dep2.js b/test/watch/samples/dependencies/dep2.js new file mode 100644 index 00000000000..266c5ae80a5 --- /dev/null +++ b/test/watch/samples/dependencies/dep2.js @@ -0,0 +1 @@ +export default 'dep2'; diff --git a/test/watch/samples/dependencies/main.js b/test/watch/samples/dependencies/main.js new file mode 100644 index 00000000000..07bf4267103 --- /dev/null +++ b/test/watch/samples/dependencies/main.js @@ -0,0 +1,3 @@ +import dep1 from './dep1.js'; +import dep2 from './dep2.js'; +export default `dep1: "${dep1}", dep2: "${dep2}"`;