diff --git a/src/index.js b/src/index.js index 2b2cbb9..d4aa5ec 100644 --- a/src/index.js +++ b/src/index.js @@ -559,8 +559,6 @@ class TerserPlugin { `${name} from Terser plugin\nMinimizer doesn't return result`, ), ); - - return; } if (output.warnings && output.warnings.length > 0) { @@ -598,99 +596,104 @@ class TerserPlugin { ); } - let shebang; - - if ( - /** @type {ExtractCommentsObject} */ - (this.options.extractComments).banner !== false && - output.extractedComments && - output.extractedComments.length > 0 && - output.code.startsWith("#!") - ) { - const firstNewlinePosition = output.code.indexOf("\n"); - - shebang = output.code.slice(0, Math.max(0, firstNewlinePosition)); - output.code = output.code.slice( - Math.max(0, firstNewlinePosition + 1), - ); - } + if (output.code) { + let shebang; - if (output.map) { - output.source = new SourceMapSource( - output.code, - name, - output.map, - input, - /** @type {RawSourceMap} */ - (inputSourceMap), - true, - ); - } else { - output.source = new RawSource(output.code); - } - - if (output.extractedComments && output.extractedComments.length > 0) { - const commentsFilename = + if ( /** @type {ExtractCommentsObject} */ - (this.options.extractComments).filename || - "[file].LICENSE.txt[query]"; - - let query = ""; - let filename = name; - - const querySplit = filename.indexOf("?"); + (this.options.extractComments).banner !== false && + output.extractedComments && + output.extractedComments.length > 0 && + output.code.startsWith("#!") + ) { + const firstNewlinePosition = output.code.indexOf("\n"); - if (querySplit >= 0) { - query = filename.slice(querySplit); - filename = filename.slice(0, querySplit); + shebang = output.code.slice(0, Math.max(0, firstNewlinePosition)); + output.code = output.code.slice( + Math.max(0, firstNewlinePosition + 1), + ); } - const lastSlashIndex = filename.lastIndexOf("/"); - const basename = - lastSlashIndex === -1 - ? filename - : filename.slice(lastSlashIndex + 1); - const data = { filename, basename, query }; - - output.commentsFilename = compilation.getPath( - commentsFilename, - data, - ); - - let banner; + if (output.map) { + output.source = new SourceMapSource( + output.code, + name, + output.map, + input, + /** @type {RawSourceMap} */ + (inputSourceMap), + true, + ); + } else { + output.source = new RawSource(output.code); + } - // Add a banner to the original file if ( - /** @type {ExtractCommentsObject} */ - (this.options.extractComments).banner !== false + output.extractedComments && + output.extractedComments.length > 0 ) { - banner = + const commentsFilename = /** @type {ExtractCommentsObject} */ - (this.options.extractComments).banner || - `For license information please see ${path - .relative(path.dirname(name), output.commentsFilename) - .replace(/\\/g, "/")}`; + (this.options.extractComments).filename || + "[file].LICENSE.txt[query]"; - if (typeof banner === "function") { - banner = banner(output.commentsFilename); + let query = ""; + let filename = name; + + const querySplit = filename.indexOf("?"); + + if (querySplit >= 0) { + query = filename.slice(querySplit); + filename = filename.slice(0, querySplit); } - if (banner) { - output.source = new ConcatSource( - shebang ? `${shebang}\n` : "", - `/*! ${banner} */\n`, - output.source, - ); + const lastSlashIndex = filename.lastIndexOf("/"); + const basename = + lastSlashIndex === -1 + ? filename + : filename.slice(lastSlashIndex + 1); + const data = { filename, basename, query }; + + output.commentsFilename = compilation.getPath( + commentsFilename, + data, + ); + + let banner; + + // Add a banner to the original file + if ( + /** @type {ExtractCommentsObject} */ + (this.options.extractComments).banner !== false + ) { + banner = + /** @type {ExtractCommentsObject} */ + (this.options.extractComments).banner || + `For license information please see ${path + .relative(path.dirname(name), output.commentsFilename) + .replace(/\\/g, "/")}`; + + if (typeof banner === "function") { + banner = banner(output.commentsFilename); + } + + if (banner) { + output.source = new ConcatSource( + shebang ? `${shebang}\n` : "", + `/*! ${banner} */\n`, + output.source, + ); + } } - } - const extractedCommentsString = output.extractedComments - .sort() - .join("\n\n"); + const extractedCommentsString = output.extractedComments + .sort() + .join("\n\n"); - output.extractedCommentsSource = new RawSource( - `${extractedCommentsString}\n`, - ); + output.extractedCommentsSource = new RawSource( + `${extractedCommentsString}\n`, + ); + } } await cacheItem.storePromise({ @@ -714,6 +717,10 @@ class TerserPlugin { } } + if (!output.source) { + return; + } + /** @type {AssetInfo} */ const newInfo = { minimized: true }; const { source, extractedCommentsSource } = output; diff --git a/src/utils.js b/src/utils.js index f8f327e..191fed9 100644 --- a/src/utils.js +++ b/src/utils.js @@ -523,7 +523,6 @@ async function uglifyJsMinify( return { code: result.code, - map: result.map ? JSON.parse(result.map) : undefined, errors: result.error ? [result.error] : [], warnings: result.warnings || [], diff --git a/test/__snapshots__/TerserPlugin.test.js.snap b/test/__snapshots__/TerserPlugin.test.js.snap index 220ecff..4f20bc0 100644 --- a/test/__snapshots__/TerserPlugin.test.js.snap +++ b/test/__snapshots__/TerserPlugin.test.js.snap @@ -3377,8 +3377,14 @@ exports[`TerserPlugin should work, extract comments in one file and use memory c exports[`TerserPlugin should write stdout and stderr of workers to stdout and stderr of main process in not parallel mode: assets 1`] = ` Object { - "one.js": "", - "two.js": "", + "one.js": "/******/ (() => { // webpackBootstrap + +/******/ })() +;", + "two.js": "/******/ (() => { // webpackBootstrap + +/******/ })() +;", } `; @@ -3400,8 +3406,14 @@ exports[`TerserPlugin should write stdout and stderr of workers to stdout and st exports[`TerserPlugin should write stdout and stderr of workers to stdout and stderr of main process in parallel mode: assets 1`] = ` Object { - "one.js": "", - "two.js": "", + "one.js": "/******/ (() => { // webpackBootstrap + +/******/ })() +;", + "two.js": "/******/ (() => { // webpackBootstrap + +/******/ })() +;", } `; diff --git a/test/__snapshots__/minify-option.test.js.snap b/test/__snapshots__/minify-option.test.js.snap index 24d295a..4e0448b 100644 --- a/test/__snapshots__/minify-option.test.js.snap +++ b/test/__snapshots__/minify-option.test.js.snap @@ -1,5 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`minify option should output errors and warning: errors 1`] = ` +Array [ + "Error: main.js from Terser plugin +Minimizer doesn't return result", + "Error: main.js from Terser plugin +error", +] +`; + +exports[`minify option should output errors and warning: warnings 1`] = ` +Array [ + "Warning: warning", +] +`; + exports[`minify option should snapshot with extracting comments: assets 1`] = ` Object { "main.js": "/*! For license information please see main.js.LICENSE.txt */ @@ -400,6 +415,8 @@ exports[`minify option should work using when the \`minify\` option is \`uglifyJ Array [ "Error: broken.js from Terser plugin Minimizer doesn't return result", + "Error: broken.js from Terser plugin +Unterminated template literal [broken.js:1,undefined]", ] `; diff --git a/test/minify-option.test.js b/test/minify-option.test.js index b480a22..c0ca6e3 100644 --- a/test/minify-option.test.js +++ b/test/minify-option.test.js @@ -157,6 +157,22 @@ describe("minify option", () => { expect(getWarnings(stats)).toMatchSnapshot("warnings"); }); + it("should output errors and warning", async () => { + const compiler = getCompiler(); + + new TerserPlugin({ + minify: () => ({ + errors: ["error"], + warnings: ["warning"], + }), + }).apply(compiler); + + const stats = await compile(compiler); + + expect(getErrors(stats)).toMatchSnapshot("errors"); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + }); + it("should snapshot with extracting comments", async () => { const compiler = getCompiler({ entry: path.resolve(__dirname, "./fixtures/minify/es5.js"),