From b31b5744d7e1500b179e854ca8902e738c348e80 Mon Sep 17 00:00:00 2001 From: Evilebot Tnawi Date: Fri, 16 Mar 2018 14:39:02 +0300 Subject: [PATCH] fix(index): don't remove legal comments by default (`options.extractComments`) (#250) --- src/index.js | 2 +- .../extract-comments-options.test.js.snap | 117 +++++---- test/extract-comments-options.test.js | 243 ++++++++++++------ 3 files changed, 235 insertions(+), 127 deletions(-) diff --git a/src/index.js b/src/index.js index aa876e88..145a83ca 100644 --- a/src/index.js +++ b/src/index.js @@ -42,7 +42,7 @@ class UglifyJsPlugin { exclude, uglifyOptions: { output: { - comments: false, + comments: extractComments ? false : /^\**!|@preserve|@license|@cc_on/, }, ...uglifyOptions, }, diff --git a/test/__snapshots__/extract-comments-options.test.js.snap b/test/__snapshots__/extract-comments-options.test.js.snap index aa83de00..d7031d01 100644 --- a/test/__snapshots__/extract-comments-options.test.js.snap +++ b/test/__snapshots__/extract-comments-options.test.js.snap @@ -1,107 +1,130 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`errors 1`] = `Array []`; +exports[`"options.extractComments" is "boolean" - "true": errors 1`] = `Array []`; -exports[`errors 2`] = `Array []`; +exports[`"options.extractComments" is "boolean" - "true": test.js 1`] = `"var foo=1;"`; -exports[`errors 3`] = `Array []`; - -exports[`errors 4`] = `Array []`; - -exports[`errors 5`] = `Array []`; - -exports[`nested/nested/test1.js 1`] = ` +exports[`"options.extractComments" is "boolean" - "true": test1.js 1`] = ` "/*! For license information please see test1.js.LICENSE */ var foo=1;" `; -exports[`nested/nested/test1.js.LICENSE 1`] = ` -"/* Comment */ +exports[`"options.extractComments" is "boolean" - "true": test1.js.LICENSE 1`] = ` +"/*! Legal Comment */ " `; -exports[`nested/test.js 1`] = ` +exports[`"options.extractComments" is "boolean" - "true": warnings 1`] = `Array []`; + +exports[`"options.extractComments" is "function": errors 1`] = `Array []`; + +exports[`"options.extractComments" is "function": test.js 1`] = ` "/*! For license information please see test.js.LICENSE */ var foo=1;" `; -exports[`nested/test1.js.LICENSE 1`] = ` +exports[`"options.extractComments" is "function": test.js.LICENSE 1`] = ` "// Comment " `; -exports[`test.js 1`] = `"var foo=1;"`; - -exports[`test.js 2`] = `"var foo=1;"`; - -exports[`test.js 3`] = ` -"/*! For license information please see test.js.LICENSE */ +exports[`"options.extractComments" is "function": test1.js 1`] = ` +"/*! For license information please see test1.js.LICENSE */ var foo=1;" `; -exports[`test.js 4`] = ` -"/*! For license information please see test.js.LICENSE */ -var foo=1;" +exports[`"options.extractComments" is "function": test1.js.LICENSE 1`] = ` +"/* Comment */ +" `; -exports[`test.js 5`] = ` -"/*! For license information please see test1.js.LICENSE */ -var foo=1;" -`; +exports[`"options.extractComments" is "function": warnings 1`] = `Array []`; + +exports[`"options.extractComments" is "object": errors 1`] = `Array []`; -exports[`test.js 6`] = ` +exports[`"options.extractComments" is "object": test.js 1`] = ` "/*! License information can be found in test.license.js */ var foo=1;" `; -exports[`test.js.LICENSE 1`] = ` +exports[`"options.extractComments" is "object": test.license.js 1`] = ` "// Comment " `; -exports[`test.js.LICENSE 2`] = ` -"// Comment -" +exports[`"options.extractComments" is "object": warnings 1`] = `Array []`; + +exports[`"options.extractComments" is "regex": errors 1`] = `Array []`; + +exports[`"options.extractComments" is "regex": test.js 1`] = `"var foo=1;"`; + +exports[`"options.extractComments" is "regex": test1.js 1`] = ` +"/*! For license information please see test1.js.LICENSE */ +var foo=1;" `; -exports[`test.license.js 1`] = ` -"// Comment +exports[`"options.extractComments" is "regex": test1.js.LICENSE 1`] = ` +"// foo " `; -exports[`test1.js 1`] = `"var foo=1;"`; +exports[`"options.extractComments" is "regex": warnings 1`] = `Array []`; -exports[`test1.js 2`] = ` +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: errors 1`] = `Array []`; + +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: nested/nested/test1.js 1`] = ` "/*! For license information please see test1.js.LICENSE */ var foo=1;" `; -exports[`test1.js 3`] = ` -"/*! For license information please see test1.js.LICENSE */ +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: nested/nested/test1.js.LICENSE 1`] = ` +"/* Comment */ +" +`; + +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: nested/test.js 1`] = ` +"/*! For license information please see test.js.LICENSE */ var foo=1;" `; -exports[`test1.js.LICENSE 1`] = ` -"// foo +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: nested/test.js.LICENSE 1`] = ` +"// Comment " `; -exports[`test1.js.LICENSE 2`] = ` -"/* Comment */ +exports[`"options.extractComments" is "string" - "all" and license file should be relative source file: warnings 1`] = `Array []`; + +exports[`"options.extractComments" is "string": errors 1`] = `Array []`; + +exports[`"options.extractComments" is "string": test.js 1`] = ` +"/*! For license information please see test.js.LICENSE */ +var foo=1;" +`; + +exports[`"options.extractComments" is "string": test.js.LICENSE 1`] = ` +"// Comment " `; -exports[`test1.js.LICENSE 3`] = ` +exports[`"options.extractComments" is "string": test1.js 1`] = ` +"/*! For license information please see test1.js.LICENSE */ +var foo=1;" +`; + +exports[`"options.extractComments" is "string": test1.js.LICENSE 1`] = ` "/* Comment */ " `; -exports[`warnings 1`] = `Array []`; +exports[`"options.extractComments" is "string": warnings 1`] = `Array []`; -exports[`warnings 2`] = `Array []`; +exports[`"options.extractComments" is not specify: errors 1`] = `Array []`; -exports[`warnings 3`] = `Array []`; +exports[`"options.extractComments" is not specify: test.js 1`] = `"var foo=1;"`; -exports[`warnings 4`] = `Array []`; +exports[`"options.extractComments" is not specify: test1.js 1`] = ` +"/*! Legal Comment */ +var foo=1;" +`; -exports[`warnings 5`] = `Array []`; +exports[`"options.extractComments" is not specify: warnings 1`] = `Array []`; diff --git a/test/extract-comments-options.test.js b/test/extract-comments-options.test.js index 2dfa09d4..7fb6b02f 100644 --- a/test/extract-comments-options.test.js +++ b/test/extract-comments-options.test.js @@ -2,10 +2,7 @@ import UglifyJsPlugin from '../src/index'; import { PluginEnvironment } from './helpers'; describe('when options.extractComments', () => { - let compilation; - let compilationEventBinding; - - beforeEach(() => { + it('normalizes extractConmments', () => { const pluginEnvironment = new PluginEnvironment(); const compilerEnv = pluginEnvironment.getEnvironmentStub(); compilerEnv.context = ''; @@ -26,7 +23,7 @@ describe('when options.extractComments', () => { const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - compilation = chunkPluginEnvironment.getEnvironmentStub(); + const compilation = chunkPluginEnvironment.getEnvironmentStub(); compilation.assets = { 'test.js': { source: () => 'var foo = 1;', @@ -47,10 +44,8 @@ describe('when options.extractComments', () => { compilation.errors = []; eventBinding.handler(compilation); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); - }); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); - it('normalizes extractConmments', () => { compilationEventBinding.handler([{ files: ['test.js'], }], () => { @@ -59,6 +54,49 @@ describe('when options.extractComments', () => { }); it('outputs warnings for unreachable code', () => { + const pluginEnvironment = new PluginEnvironment(); + const compilerEnv = pluginEnvironment.getEnvironmentStub(); + compilerEnv.context = ''; + + const plugin = new UglifyJsPlugin({ + uglifyOptions: { + warnings: true, + mangle: { + properties: { + builtins: true, + }, + }, + }, + extractComments: true, + }); + plugin.apply(compilerEnv); + + const [eventBinding] = pluginEnvironment.getEventBindings(); + const chunkPluginEnvironment = new PluginEnvironment(); + + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { + 'test.js': { + source: () => 'var foo = 1;', + }, + 'test1.js': { + source: () => 'function foo(x) { if (x) { return bar(); not_called1(); } }', + map: () => { + return { + version: 3, + sources: ['test1.js'], + names: ['foo', 'x', 'bar', 'not_called1'], + mappings: 'AAAA,QAASA,KAAIC,GACT,GAAIA,EAAG,CACH,MAAOC,MACPC', + }; + }, + }, + }; + compilation.warnings = []; + compilation.errors = []; + + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + compilationEventBinding.handler([{ files: ['test.js', 'test1.js'], }], () => { @@ -68,7 +106,44 @@ describe('when options.extractComments', () => { }); }); - it('normalizes when options.extractComments is boolean', () => { + it('normalizes when options.extractComments is not specify', () => { + const pluginEnvironment = new PluginEnvironment(); + const compilerEnv = pluginEnvironment.getEnvironmentStub(); + compilerEnv.context = ''; + + const plugin = new UglifyJsPlugin(); + plugin.apply(compilerEnv); + const [eventBinding] = pluginEnvironment.getEventBindings(); + const chunkPluginEnvironment = new PluginEnvironment(); + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { + 'test.js': { + source: () => '// Comment\nvar foo = 1;', + }, + 'test1.js': { + source: () => '/*! Legal Comment */\nvar foo = 1;', + }, + }; + compilation.warnings = []; + compilation.errors = []; + + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + + compilationEventBinding.handler([{ + files: ['test.js', 'test1.js'], + }], () => { + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is not specify: ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is not specify: errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is not specify: warnings'); + }); + }); + + it('normalizes when options.extractComments is boolean - "true"', () => { const pluginEnvironment = new PluginEnvironment(); const compilerEnv = pluginEnvironment.getEnvironmentStub(); compilerEnv.context = ''; @@ -79,29 +154,31 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'test.js': { source: () => '// Comment\nvar foo = 1;', }, 'test1.js': { - source: () => '/* Comment */\nvar foo = 1;', + source: () => '/*! Legal Comment */\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['test.js', 'test1.js'], }], () => { - expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js'); - expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "boolean" - "true": ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "boolean" - "true": errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "boolean" - "true": warnings'); }); }); @@ -116,8 +193,8 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'test.js': { source: () => '// Comment\nvar foo = 1;', }, @@ -125,20 +202,22 @@ describe('when options.extractComments', () => { source: () => '// foo\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['test.js', 'test1.js'], }], () => { - expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js'); - expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "regex": ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "regex": errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "regex": warnings'); }); }); @@ -153,8 +232,8 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'test.js': { source: () => '// Comment\nvar foo = 1;', }, @@ -162,21 +241,22 @@ describe('when options.extractComments', () => { source: () => '/* Comment */\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['test.js', 'test1.js'], }], () => { - expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test.js.LICENSE'].source()).toMatchSnapshot('test.js.LICENSE'); - expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test1.js'); - expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "string": ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "string": errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "string": warnings'); }); }); @@ -191,8 +271,8 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'test.js': { source: () => '// Comment\nvar foo = 1;', }, @@ -200,21 +280,22 @@ describe('when options.extractComments', () => { source: () => '/* Comment */\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['test.js', 'test1.js'], }], () => { - expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test1.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test.js.LICENSE'].source()).toMatchSnapshot('test.js.LICENSE'); - expect(compilation2.assets['test1.js.LICENSE'].source()).toMatchSnapshot('test1.js.LICENSE'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "function": ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "function": errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "function": warnings'); }); }); @@ -237,29 +318,32 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'test.js': { source: () => '// Comment\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['test.js'], }], () => { - expect(compilation2.assets['test.js'].source()).toMatchSnapshot('test.js'); - expect(compilation2.assets['test.license.js'].source()).toMatchSnapshot('test.license.js'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "object": ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "object": errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "object": warnings'); }); }); - it('output respect nested directories', () => { + it('normalizes when options.extractComments is string - "all" && license file should be relative source file', () => { const pluginEnvironment = new PluginEnvironment(); const compilerEnv = pluginEnvironment.getEnvironmentStub(); compilerEnv.context = ''; @@ -270,8 +354,8 @@ describe('when options.extractComments', () => { plugin.apply(compilerEnv); const [eventBinding] = pluginEnvironment.getEventBindings(); const chunkPluginEnvironment = new PluginEnvironment(); - const compilation2 = chunkPluginEnvironment.getEnvironmentStub(); - compilation2.assets = { + const compilation = chunkPluginEnvironment.getEnvironmentStub(); + compilation.assets = { 'nested/test.js': { source: () => '// Comment\nvar foo = 1;', }, @@ -279,21 +363,22 @@ describe('when options.extractComments', () => { source: () => '/* Comment */\nvar foo = 1;', }, }; - compilation2.warnings = []; - compilation2.errors = []; + compilation.warnings = []; + compilation.errors = []; - eventBinding.handler(compilation2); - [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); + eventBinding.handler(compilation); + const [compilationEventBinding] = chunkPluginEnvironment.getEventBindings(); compilationEventBinding.handler([{ files: ['nested/test.js', 'nested/nested/test1.js'], }], () => { - expect(compilation2.assets['nested/test.js'].source()).toMatchSnapshot('nested/test.js'); - expect(compilation2.assets['nested/test.js.LICENSE'].source()).toMatchSnapshot('nested/test1.js.LICENSE'); - expect(compilation2.assets['nested/nested/test1.js'].source()).toMatchSnapshot('nested/nested/test1.js'); - expect(compilation2.assets['nested/nested/test1.js.LICENSE'].source()).toMatchSnapshot('nested/nested/test1.js.LICENSE'); - expect(compilation2.errors).toMatchSnapshot('errors'); - expect(compilation2.warnings).toMatchSnapshot('warnings'); + for (const file in compilation.assets) { + if (Object.prototype.hasOwnProperty.call(compilation.assets, file)) { + expect(compilation.assets[file].source()).toMatchSnapshot(`"options.extractComments" is "string" - "all" and license file should be relative source file: ${file}`); + } + } + expect(compilation.errors).toMatchSnapshot('"options.extractComments" is "string" - "all" and license file should be relative source file: errors'); + expect(compilation.warnings).toMatchSnapshot('"options.extractComments" is "string" - "all" and license file should be relative source file: warnings'); }); }); });