Skip to content
This repository was archived by the owner on Dec 5, 2019. It is now read-only.

Commit 726874b

Browse files
refactor: code and tests (#333)
* refactor: stuff * refactor: equal name convention for tests * refactor: move test from `invalid` option to `UglifyJsPlugin` test * refactor: more tests * refactor: sort validate option as in docs
1 parent 24fe22b commit 726874b

25 files changed

+277
-241
lines changed

src/index.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import ModuleFilenameHelpers from 'webpack/lib/ModuleFilenameHelpers';
1010
import validateOptions from 'schema-utils';
1111
import schema from './options.json';
1212
import Runner from './uglify/Runner';
13-
import versions from './uglify/versions';
14-
import utils from './utils';
1513

1614
const warningRegex = /\[.+:([0-9]+),([0-9]+)\]/;
1715

@@ -56,8 +54,18 @@ class UglifyJsPlugin {
5654
};
5755
}
5856

57+
static isSourceMap(input) {
58+
// All required options for `new SourceMapConsumer(...options)`
59+
// https://github.com/mozilla/source-map#new-sourcemapconsumerrawsourcemap
60+
return Boolean(input &&
61+
input.version &&
62+
input.sources &&
63+
Array.isArray(input.sources) &&
64+
typeof input.mappings === 'string');
65+
}
66+
5967
static buildSourceMap(inputSourceMap) {
60-
if (!inputSourceMap || !utils.isSourceMap(inputSourceMap)) {
68+
if (!inputSourceMap || !UglifyJsPlugin.isSourceMap(inputSourceMap)) {
6169
return null;
6270
}
6371

@@ -71,13 +79,15 @@ class UglifyJsPlugin {
7179
line: err.line,
7280
column: err.col,
7381
});
82+
7483
if (original && original.source) {
7584
return new Error(`${file} from UglifyJs\n${err.message} [${requestShortener.shorten(original.source)}:${original.line},${original.column}][${file}:${err.line},${err.col}]`);
7685
}
7786
return new Error(`${file} from UglifyJs\n${err.message} [${file}:${err.line},${err.col}]`);
7887
} else if (err.stack) {
7988
return new Error(`${file} from UglifyJs\n${err.stack}`);
8089
}
90+
8191
return new Error(`${file} from UglifyJs\n${err.message}`);
8292
}
8393

@@ -129,7 +139,9 @@ class UglifyJsPlugin {
129139
.filter(ModuleFilenameHelpers.matchObject.bind(null, this.options))
130140
.forEach((file) => {
131141
let inputSourceMap;
142+
132143
const asset = compilation.assets[file];
144+
133145
if (uglifiedAssets.has(asset)) {
134146
return;
135147
}
@@ -142,7 +154,7 @@ class UglifyJsPlugin {
142154

143155
input = source;
144156

145-
if (utils.isSourceMap(map)) {
157+
if (UglifyJsPlugin.isSourceMap(map)) {
146158
inputSourceMap = map;
147159
} else {
148160
inputSourceMap = map;
@@ -157,8 +169,10 @@ class UglifyJsPlugin {
157169

158170
// Handling comment extraction
159171
let commentsFile = false;
172+
160173
if (this.options.extractComments) {
161174
commentsFile = this.options.extractComments.filename || `${file}.LICENSE`;
175+
162176
if (typeof commentsFile === 'function') {
163177
commentsFile = commentsFile(file);
164178
}
@@ -176,8 +190,10 @@ class UglifyJsPlugin {
176190

177191
if (this.options.cache) {
178192
const defaultCacheKeys = {
179-
'uglify-es': versions.uglify,
180-
'uglifyjs-webpack-plugin': versions.plugin,
193+
// eslint-disable-next-line global-require
194+
'uglify-es': require('uglify-es/package.json').version,
195+
// eslint-disable-next-line global-require
196+
'uglifyjs-webpack-plugin': require('../package.json').version,
181197
'uglifyjs-webpack-plugin-options': this.options,
182198
path: compiler.outputPath ? `${compiler.outputPath}/${file}` : file,
183199
hash: crypto.createHash('md4').update(input).digest('hex'),
@@ -202,6 +218,7 @@ class UglifyJsPlugin {
202218
runner.runTasks(tasks, (tasksError, results) => {
203219
if (tasksError) {
204220
compilation.errors.push(tasksError);
221+
205222
return;
206223
}
207224

@@ -231,6 +248,7 @@ class UglifyJsPlugin {
231248
}
232249

233250
let outputSource;
251+
234252
if (map) {
235253
outputSource = new SourceMapSource(
236254
code,

src/options.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
{ "type": "integer" }
2020
]
2121
},
22-
"warningsFilter": {},
23-
"extractComments": {},
2422
"sourceMap": {
2523
"type": "boolean"
2624
},
@@ -67,7 +65,9 @@
6765
"type": ["object", "null"]
6866
}
6967
}
70-
}
68+
},
69+
"extractComments": {},
70+
"warningsFilter": {}
7171
},
7272
"additionalProperties": false
7373
}

src/uglify/versions.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/utils/index.js

Lines changed: 0 additions & 13 deletions
This file was deleted.

test/UglifyJsPlugin.test.js

Lines changed: 232 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,238 @@
11
import UglifyJsPlugin from '../src/index';
2+
import { cleanErrorStack, compile, createCompiler } from './helpers';
23

34
describe('UglifyJsPlugin', () => {
4-
it('has apply function', () => {
5+
it('export as function', () => {
56
expect(typeof new UglifyJsPlugin().apply).toBe('function');
67
});
8+
9+
it('validation errors', () => {
10+
/* eslint-disable no-new */
11+
expect(() => {
12+
new UglifyJsPlugin({ test: /foo/ });
13+
}).not.toThrow('Validation Error');
14+
15+
expect(() => {
16+
new UglifyJsPlugin({ test: [/foo/] });
17+
}).not.toThrow('Validation Error');
18+
19+
expect(() => {
20+
new UglifyJsPlugin({ include: /foo/ });
21+
}).not.toThrow('Validation Error');
22+
23+
expect(() => {
24+
new UglifyJsPlugin({ include: [/foo/] });
25+
}).not.toThrow('Validation Error');
26+
27+
expect(() => {
28+
new UglifyJsPlugin({ exclude: /foo/ });
29+
}).not.toThrow('Validation Error');
30+
31+
expect(() => {
32+
new UglifyJsPlugin({ exclude: [/foo/] });
33+
}).not.toThrow('Validation Error');
34+
35+
expect(() => {
36+
new UglifyJsPlugin({ doesntExist: true });
37+
}).toThrowErrorMatchingSnapshot();
38+
39+
expect(() => {
40+
new UglifyJsPlugin({ cache: true });
41+
}).not.toThrow('Validation Error');
42+
43+
expect(() => {
44+
new UglifyJsPlugin({ cache: false });
45+
}).not.toThrow('Validation Error');
46+
47+
expect(() => {
48+
new UglifyJsPlugin({ cache: 'path/to/cache/directory' });
49+
}).not.toThrow('Validation Error');
50+
51+
expect(() => {
52+
new UglifyJsPlugin({ cache: {} });
53+
}).toThrowErrorMatchingSnapshot();
54+
55+
expect(() => {
56+
new UglifyJsPlugin({ cacheKeys() {} });
57+
}).not.toThrow('Validation Error');
58+
59+
expect(() => {
60+
new UglifyJsPlugin({ parallel: true });
61+
}).not.toThrow('Validation Error');
62+
63+
expect(() => {
64+
new UglifyJsPlugin({ parallel: false });
65+
}).not.toThrow('Validation Error');
66+
67+
expect(() => {
68+
new UglifyJsPlugin({ parallel: 2 });
69+
}).not.toThrow('Validation Error');
70+
71+
expect(() => {
72+
new UglifyJsPlugin({ parallel: '2' });
73+
}).toThrowErrorMatchingSnapshot();
74+
75+
expect(() => {
76+
new UglifyJsPlugin({ parallel: {} });
77+
}).toThrowErrorMatchingSnapshot();
78+
79+
expect(() => {
80+
new UglifyJsPlugin({ sourceMap: true });
81+
}).not.toThrow('Validation Error');
82+
83+
expect(() => {
84+
new UglifyJsPlugin({ sourceMap: false });
85+
}).not.toThrow('Validation Error');
86+
87+
expect(() => {
88+
new UglifyJsPlugin({ sourceMap: 'true' });
89+
}).toThrowErrorMatchingSnapshot();
90+
91+
expect(() => {
92+
new UglifyJsPlugin({ minify() {} });
93+
}).not.toThrow('Validation Error');
94+
95+
expect(() => {
96+
new UglifyJsPlugin({ uglifyOptions: null });
97+
}).toThrowErrorMatchingSnapshot();
98+
99+
expect(() => {
100+
new UglifyJsPlugin({ uglifyOptions: {} });
101+
}).not.toThrow('Validation Error');
102+
103+
expect(() => {
104+
new UglifyJsPlugin({
105+
uglifyOptions: {
106+
ecma: 5,
107+
warnings: false,
108+
parse: {},
109+
compress: true,
110+
mangle: { inline: false },
111+
output: { comments: /^\**!|@preserve|@license|@cc_on/ },
112+
toplevel: false,
113+
nameCache: {},
114+
ie8: false,
115+
keep_classnames: false,
116+
keep_fnames: false,
117+
safari10: false,
118+
},
119+
});
120+
}).not.toThrow('Validation Error');
121+
122+
expect(() => {
123+
new UglifyJsPlugin({ uglifyOptions: { ie8: false } });
124+
}).not.toThrow('Validation Error');
125+
126+
expect(() => {
127+
new UglifyJsPlugin({ uglifyOptions: { ie8: true } });
128+
}).not.toThrow('Validation Error');
129+
130+
expect(() => {
131+
new UglifyJsPlugin({ uglifyOptions: { ie8: 'false' } });
132+
}).toThrowErrorMatchingSnapshot();
133+
134+
expect(() => {
135+
new UglifyJsPlugin({ uglifyOptions: { emca: 5 } });
136+
}).not.toThrow();
137+
138+
expect(() => {
139+
new UglifyJsPlugin({ uglifyOptions: { emca: 8 } });
140+
}).not.toThrow();
141+
142+
expect(() => {
143+
new UglifyJsPlugin({ uglifyOptions: { ecma: 7.5 } });
144+
}).toThrowErrorMatchingSnapshot();
145+
146+
expect(() => {
147+
new UglifyJsPlugin({ uglifyOptions: { ecma: true } });
148+
}).toThrowErrorMatchingSnapshot();
149+
150+
expect(() => {
151+
new UglifyJsPlugin({ uglifyOptions: { ecma: '5' } });
152+
}).toThrowErrorMatchingSnapshot();
153+
154+
expect(() => {
155+
new UglifyJsPlugin({ uglifyOptions: { ecma: 3 } });
156+
}).toThrowErrorMatchingSnapshot();
157+
158+
expect(() => {
159+
new UglifyJsPlugin({ uglifyOptions: { ecma: 10 } });
160+
}).toThrowErrorMatchingSnapshot();
161+
162+
expect(() => {
163+
new UglifyJsPlugin({ extractComments: true });
164+
}).not.toThrow('Validation Error');
165+
166+
expect(() => {
167+
new UglifyJsPlugin({ extractComments: false });
168+
}).not.toThrow('Validation Error');
169+
170+
expect(() => {
171+
new UglifyJsPlugin({ extractComments: /comment/ });
172+
}).not.toThrow('Validation Error');
173+
174+
expect(() => {
175+
new UglifyJsPlugin({ extractComments() {} });
176+
}).not.toThrow('Validation Error');
177+
178+
expect(() => {
179+
new UglifyJsPlugin({ warningsFilter() {} });
180+
}).not.toThrow('Validation Error');
181+
});
182+
183+
it('contain errors when uglify has unknown option', () => {
184+
const compiler = createCompiler();
185+
new UglifyJsPlugin({
186+
uglifyOptions: {
187+
output: {
188+
unknown: true,
189+
},
190+
},
191+
}).apply(compiler);
192+
193+
return compile(compiler).then((stats) => {
194+
const errors = stats.compilation.errors.map(cleanErrorStack);
195+
const warnings = stats.compilation.warnings.map(cleanErrorStack);
196+
197+
expect(errors).toMatchSnapshot('errors');
198+
expect(warnings).toMatchSnapshot('warnings');
199+
200+
for (const file in stats.compilation.assets) {
201+
if (Object.prototype.hasOwnProperty.call(stats.compilation.assets, file)) {
202+
expect(stats.compilation.assets[file].source()).toMatchSnapshot(file);
203+
}
204+
}
205+
});
206+
});
207+
208+
it('isSourceMap method', () => {
209+
const rawSourceMap = {
210+
version: 3,
211+
file: 'min.js',
212+
names: ['bar', 'baz', 'n'],
213+
sources: ['one.js', 'two.js'],
214+
sourceRoot: 'http://example.com/www/js/',
215+
mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA',
216+
};
217+
const emptyRawSourceMap = {
218+
version: 3,
219+
sources: [],
220+
mappings: '',
221+
};
222+
223+
expect(UglifyJsPlugin.isSourceMap(null)).toBe(false);
224+
expect(UglifyJsPlugin.isSourceMap()).toBe(false);
225+
expect(UglifyJsPlugin.isSourceMap({})).toBe(false);
226+
expect(UglifyJsPlugin.isSourceMap([])).toBe(false);
227+
expect(UglifyJsPlugin.isSourceMap('foo')).toBe(false);
228+
expect(UglifyJsPlugin.isSourceMap({ version: 3 })).toBe(false);
229+
expect(UglifyJsPlugin.isSourceMap({ sources: '' })).toBe(false);
230+
expect(UglifyJsPlugin.isSourceMap({ mappings: [] })).toBe(false);
231+
expect(UglifyJsPlugin.isSourceMap({ version: 3, sources: '' })).toBe(false);
232+
expect(UglifyJsPlugin.isSourceMap({ version: 3, mappings: [] })).toBe(false);
233+
expect(UglifyJsPlugin.isSourceMap({ sources: '', mappings: [] })).toBe(false);
234+
expect(UglifyJsPlugin.isSourceMap({ version: 3, sources: '', mappings: [] })).toBe(false);
235+
expect(UglifyJsPlugin.isSourceMap(rawSourceMap)).toBe(true);
236+
expect(UglifyJsPlugin.isSourceMap(emptyRawSourceMap)).toBe(true);
237+
});
7238
});

0 commit comments

Comments
 (0)