UNPKG

53.7 kBMarkdownView Raw
1UglifyJS 3
2==========
3
4UglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.
5
6#### Note:
7- `uglify-js` supports JavaScript and most language features in ECMAScript.
8- For more exotic parts of ECMAScript, process your source file with transpilers
9 like [Babel](https://babeljs.io/) before passing onto `uglify-js`.
10- `uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage)
11 that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x).
12
13Install
14-------
15
16First make sure you have installed the latest version of [node.js](http://nodejs.org/)
17(You may need to restart your computer after this step).
18
19From NPM for use as a command line app:
20
21 npm install uglify-js -g
22
23From NPM for programmatic use:
24
25 npm install uglify-js
26
27# Command line usage
28
29 uglifyjs [input files] [options]
30
31UglifyJS can take multiple input files. It's recommended that you pass the
32input files first, then pass the options. UglifyJS will parse input files
33in sequence and apply any compression options. The files are parsed in the
34same global scope, that is, a reference from a file to some
35variable/function declared in another file will be matched properly.
36
37If no input file is specified, UglifyJS will read from STDIN.
38
39If you wish to pass your options before the input files, separate the two with
40a double dash to prevent input files being used as option arguments:
41
42 uglifyjs --compress --mangle -- input.js
43
44### Command line options
45
46```
47 -h, --help Print usage information.
48 `--help options` for details on available options.
49 -V, --version Print version number.
50 -p, --parse <options> Specify parser options:
51 `acorn` Use Acorn for parsing.
52 `bare_returns` Allow return outside of functions.
53 Useful when minifying CommonJS
54 modules and Userscripts that may
55 be anonymous function wrapped (IIFE)
56 by the .user.js engine `caller`.
57 `expression` Parse a single expression, rather than
58 a program (for parsing JSON).
59 `spidermonkey` Assume input files are SpiderMonkey
60 AST format (as JSON).
61 -c, --compress [options] Enable compressor/specify compressor options:
62 `pure_funcs` List of functions that can be safely
63 removed when their return values are
64 not used.
65 -m, --mangle [options] Mangle names/specify mangler options:
66 `reserved` List of names that should not be mangled.
67 --mangle-props [options] Mangle properties/specify mangler options:
68 `builtins` Mangle property names that overlaps
69 with standard JavaScript globals.
70 `debug` Add debug prefix and suffix.
71 `domprops` Mangle property names that overlaps
72 with DOM properties.
73 `keep_quoted` Only mangle unquoted properties.
74 `regex` Only mangle matched property names.
75 `reserved` List of names that should not be mangled.
76 -b, --beautify [options] Beautify output/specify output options:
77 `beautify` Enabled with `--beautify` by default.
78 `preamble` Preamble to prepend to the output. You
79 can use this to insert a comment, for
80 example for licensing information.
81 This will not be parsed, but the source
82 map will adjust for its presence.
83 `quote_style` Quote style:
84 0 - auto
85 1 - single
86 2 - double
87 3 - original
88 `wrap_iife` Wrap IIFEs in parentheses. Note: you may
89 want to disable `negate_iife` under
90 compressor options.
91 -O, --output-opts [options] Specify output options (`beautify` disabled by default).
92 -o, --output <file> Output file path (default STDOUT). Specify `ast` or
93 `spidermonkey` to write UglifyJS or SpiderMonkey AST
94 as JSON to STDOUT respectively.
95 --annotations Process and preserve comment annotations.
96 (`/*@__PURE__*/` or `/*#__PURE__*/`)
97 --no-annotations Ignore and discard comment annotations.
98 --comments [filter] Preserve copyright comments in the output. By
99 default this works like Google Closure, keeping
100 JSDoc-style comments that contain "@license" or
101 "@preserve". You can optionally pass one of the
102 following arguments to this flag:
103 - "all" to keep all comments
104 - a valid JS RegExp like `/foo/` or `/^!/` to
105 keep only matching comments.
106 Note that currently not *all* comments can be
107 kept when compression is on, because of dead
108 code removal or cascading statements into
109 sequences.
110 --config-file <file> Read `minify()` options from JSON file.
111 -d, --define <expr>[=value] Global definitions.
112 -e, --enclose [arg[:value]] Embed everything in a big function, with configurable
113 argument(s) & value(s).
114 --ie Support non-standard Internet Explorer.
115 Equivalent to setting `ie: true` in `minify()`
116 for `compress`, `mangle` and `output` options.
117 By default UglifyJS will not try to be IE-proof.
118 --keep-fnames Do not mangle/drop function names. Useful for
119 code relying on Function.prototype.name.
120 --name-cache <file> File to hold mangled name mappings.
121 --self Build UglifyJS as a library (implies --wrap UglifyJS)
122 --source-map [options] Enable source map/specify source map options:
123 `base` Path to compute relative paths from input files.
124 `content` Input source map, useful if you're compressing
125 JS that was generated from some other original
126 code. Specify "inline" if the source map is
127 included within the sources.
128 `filename` Filename and/or location of the output source
129 (sets `file` attribute in source map).
130 `includeSources` Pass this flag if you want to include
131 the content of source files in the
132 source map as sourcesContent property.
133 `names` Include symbol names in the source map.
134 `root` Path to the original source to be included in
135 the source map.
136 `url` If specified, path to the source map to append in
137 `//# sourceMappingURL`.
138 --timings Display operations run time on STDERR.
139 --toplevel Compress and/or mangle variables in top level scope.
140 --v8 Support non-standard Chrome & Node.js
141 Equivalent to setting `v8: true` in `minify()`
142 for `mangle` and `output` options.
143 By default UglifyJS will not try to be v8-proof.
144 --verbose Print diagnostic messages.
145 --warn Print warning messages.
146 --webkit Support non-standard Safari/Webkit.
147 Equivalent to setting `webkit: true` in `minify()`
148 for `mangle` and `output` options.
149 By default UglifyJS will not try to be Safari-proof.
150 --wrap <name> Embed everything in a big function, making the
151 “exports” and “global” variables available. You
152 need to pass an argument to this option to
153 specify the name that your module will take
154 when included in, say, a browser.
155```
156
157Specify `--output` (`-o`) to declare the output file. Otherwise the output
158goes to STDOUT.
159
160## CLI source map options
161
162UglifyJS can generate a source map file, which is highly useful for
163debugging your compressed JavaScript. To get a source map, pass
164`--source-map --output output.js` (source map will be written out to
165`output.js.map`).
166
167Additional options:
168
169- `--source-map "filename='<NAME>'"` to specify the name of the source map. The value of
170 `filename` is only used to set `file` attribute (see [the spec][sm-spec])
171 in source map file.
172
173- `--source-map "root='<URL>'"` to pass the URL where the original files can be found.
174
175- `--source-map "names=false"` to omit symbol names if you want to reduce size
176 of the source map file.
177
178- `--source-map "url='<URL>'"` to specify the URL where the source map can be found.
179 Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the
180 `//# sourceMappingURL=` directive.
181
182For example:
183
184 uglifyjs js/file1.js js/file2.js \
185 -o foo.min.js -c -m \
186 --source-map "root='http://foo.com/src',url='foo.min.js.map'"
187
188The above will compress and mangle `file1.js` and `file2.js`, will drop the
189output in `foo.min.js` and the source map in `foo.min.js.map`. The source
190mapping will refer to `http://foo.com/src/js/file1.js` and
191`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`
192as the source map root, and the original files as `js/file1.js` and
193`js/file2.js`).
194
195### Composed source map
196
197When you're compressing JS code that was output by a compiler such as
198CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd
199like to map back to the original code (i.e. CoffeeScript). UglifyJS has an
200option to take an input source map. Assuming you have a mapping from
201CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →
202compressed JS by mapping every token in the compiled JS to its original
203location.
204
205To use this feature pass `--source-map "content='/path/to/input/source.map'"`
206or `--source-map "content=inline"` if the source map is included inline with
207the sources.
208
209## CLI compress options
210
211You need to pass `--compress` (`-c`) to enable the compressor. Optionally
212you can pass a comma-separated list of [compress options](#compress-options).
213
214Options are in the form `foo=bar`, or just `foo` (the latter implies
215a boolean option that you want to set `true`; it's effectively a
216shortcut for `foo=true`).
217
218Example:
219
220 uglifyjs file.js -c toplevel,sequences=false
221
222## CLI mangle options
223
224To enable the mangler you need to pass `--mangle` (`-m`). The following
225(comma-separated) options are supported:
226
227- `eval` (default: `false`) — mangle names visible in scopes where `eval` or
228 `with` are used.
229
230- `reserved` (default: `[]`) — when mangling is enabled but you want to
231 prevent certain names from being mangled, you can declare those names with
232 `--mangle reserved` — pass a comma-separated list of names. For example:
233
234 uglifyjs ... -m reserved=['$','require','exports']
235
236 to prevent the `require`, `exports` and `$` names from being changed.
237
238### CLI mangling property names (`--mangle-props`)
239
240**Note:** THIS WILL PROBABLY BREAK YOUR CODE. Mangling property names
241is a separate step, different from variable name mangling. Pass
242`--mangle-props` to enable it. It will mangle all properties in the
243input code with the exception of built in DOM properties and properties
244in core JavaScript classes. For example:
245
246```javascript
247// example.js
248var x = {
249 baz_: 0,
250 foo_: 1,
251 calc: function() {
252 return this.foo_ + this.baz_;
253 }
254};
255x.bar_ = 2;
256x["baz_"] = 3;
257console.log(x.calc());
258```
259Mangle all properties (except for JavaScript `builtins`):
260```bash
261$ uglifyjs example.js -c -m --mangle-props
262```
263```javascript
264var x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());
265```
266Mangle all properties except for `reserved` properties:
267```bash
268$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]
269```
270```javascript
271var x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());
272```
273Mangle all properties matching a `regex`:
274```bash
275$ uglifyjs example.js -c -m --mangle-props regex=/_$/
276```
277```javascript
278var x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());
279```
280
281Combining mangle properties options:
282```bash
283$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]
284```
285```javascript
286var x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());
287```
288
289In order for this to be of any use, we avoid mangling standard JS names by
290default (`--mangle-props builtins` to override).
291
292A default exclusion file is provided in `tools/domprops.json` which should
293cover most standard JS and DOM properties defined in various browsers. Pass
294`--mangle-props domprops` to disable this feature.
295
296A regular expression can be used to define which property names should be
297mangled. For example, `--mangle-props regex=/^_/` will only mangle property
298names that start with an underscore.
299
300When you compress multiple files using this option, in order for them to
301work together in the end we need to ensure somehow that one property gets
302mangled to the same name in all of them. For this, pass `--name-cache filename.json`
303and UglifyJS will maintain these mappings in a file which can then be reused.
304It should be initially empty. Example:
305
306```bash
307$ rm -f /tmp/cache.json # start fresh
308$ uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js
309$ uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js
310```
311
312Now, `part1.js` and `part2.js` will be consistent with each other in terms
313of mangled property names.
314
315Using the name cache is not necessary if you compress all your files in a
316single call to UglifyJS.
317
318### Mangling unquoted names (`--mangle-props keep_quoted`)
319
320Using quoted property name (`o["foo"]`) reserves the property name (`foo`)
321so that it is not mangled throughout the entire script even when used in an
322unquoted style (`o.foo`). Example:
323
324```javascript
325// stuff.js
326var o = {
327 "foo": 1,
328 bar: 3
329};
330o.foo += o.bar;
331console.log(o.foo);
332```
333```bash
334$ uglifyjs stuff.js --mangle-props keep_quoted -c -m
335```
336```javascript
337var o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);
338```
339
340### Debugging property name mangling
341
342You can also pass `--mangle-props debug` in order to mangle property names
343without completely obscuring them. For example the property `o.foo`
344would mangle to `o._$foo$_` with this option. This allows property mangling
345of a large codebase while still being able to debug the code and identify
346where mangling is breaking things.
347
348```bash
349$ uglifyjs stuff.js --mangle-props debug -c -m
350```
351```javascript
352var o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);
353```
354
355You can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then
356mangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a
357script to identify how a property got mangled. One technique is to pass a
358random number on every compile to simulate mangling changing with different
359inputs (e.g. as you update the input script with new properties), and to help
360identify mistakes like writing mangled keys to storage.
361
362
363# API Reference
364
365Assuming installation via NPM, you can load UglifyJS in your application
366like this:
367```javascript
368var UglifyJS = require("uglify-js");
369```
370
371There is a single high level function, **`minify(code, options)`**,
372which will perform all minification [phases](#minify-options) in a configurable
373manner. By default `minify()` will enable the options [`compress`](#compress-options)
374and [`mangle`](#mangle-options). Example:
375```javascript
376var code = "function add(first, second) { return first + second; }";
377var result = UglifyJS.minify(code);
378console.log(result.error); // runtime error, or `undefined` if no error
379console.log(result.code); // minified output: function add(n,d){return n+d}
380```
381
382You can `minify` more than one JavaScript file at a time by using an object
383for the first argument where the keys are file names and the values are source
384code:
385```javascript
386var code = {
387 "file1.js": "function add(first, second) { return first + second; }",
388 "file2.js": "console.log(add(1 + 2, 3 + 4));"
389};
390var result = UglifyJS.minify(code);
391console.log(result.code);
392// function add(d,n){return d+n}console.log(add(3,7));
393```
394
395The `toplevel` option:
396```javascript
397var code = {
398 "file1.js": "function add(first, second) { return first + second; }",
399 "file2.js": "console.log(add(1 + 2, 3 + 4));"
400};
401var options = { toplevel: true };
402var result = UglifyJS.minify(code, options);
403console.log(result.code);
404// console.log(3+7);
405```
406
407The `nameCache` option:
408```javascript
409var options = {
410 mangle: {
411 toplevel: true,
412 },
413 nameCache: {}
414};
415var result1 = UglifyJS.minify({
416 "file1.js": "function add(first, second) { return first + second; }"
417}, options);
418var result2 = UglifyJS.minify({
419 "file2.js": "console.log(add(1 + 2, 3 + 4));"
420}, options);
421console.log(result1.code);
422// function n(n,r){return n+r}
423console.log(result2.code);
424// console.log(n(3,7));
425```
426
427You may persist the name cache to the file system in the following way:
428```javascript
429var cacheFileName = "/tmp/cache.json";
430var options = {
431 mangle: {
432 properties: true,
433 },
434 nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
435};
436fs.writeFileSync("part1.js", UglifyJS.minify({
437 "file1.js": fs.readFileSync("file1.js", "utf8"),
438 "file2.js": fs.readFileSync("file2.js", "utf8")
439}, options).code, "utf8");
440fs.writeFileSync("part2.js", UglifyJS.minify({
441 "file3.js": fs.readFileSync("file3.js", "utf8"),
442 "file4.js": fs.readFileSync("file4.js", "utf8")
443}, options).code, "utf8");
444fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
445```
446
447An example of a combination of `minify()` options:
448```javascript
449var code = {
450 "file1.js": "function add(first, second) { return first + second; }",
451 "file2.js": "console.log(add(1 + 2, 3 + 4));"
452};
453var options = {
454 toplevel: true,
455 compress: {
456 global_defs: {
457 "@console.log": "alert"
458 },
459 passes: 2
460 },
461 output: {
462 beautify: false,
463 preamble: "/* uglified */"
464 }
465};
466var result = UglifyJS.minify(code, options);
467console.log(result.code);
468// /* uglified */
469// alert(10);"
470```
471
472To produce warnings:
473```javascript
474var code = "function f(){ var u; return 2 + 3; }";
475var options = { warnings: true };
476var result = UglifyJS.minify(code, options);
477console.log(result.error); // runtime error, `undefined` in this case
478console.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]
479console.log(result.code); // function f(){return 5}
480```
481
482An error example:
483```javascript
484var result = UglifyJS.minify({"foo.js" : "if (0) else console.log(1);"});
485console.log(JSON.stringify(result.error));
486// {"message":"Unexpected token: keyword (else)","filename":"foo.js","line":1,"col":7,"pos":7}
487```
488Note: unlike `uglify-js@2.x`, the `3.x` API does not throw errors. To
489achieve a similar effect one could do the following:
490```javascript
491var result = UglifyJS.minify(code, options);
492if (result.error) throw result.error;
493```
494
495## Minify options
496
497- `annotations` — pass `false` to ignore all comment annotations and elide them
498 from output. Useful when, for instance, external tools incorrectly applied
499 `/*@__PURE__*/` or `/*#__PURE__*/`. Pass `true` to both compress and retain
500 comment annotations in output to allow for further processing downstream.
501
502- `compress` (default: `{}`) — pass `false` to skip compressing entirely.
503 Pass an object to specify custom [compress options](#compress-options).
504
505- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.
506
507- `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling
508 of function names. Useful for code relying on `Function.prototype.name`.
509
510- `mangle` (default: `true`) — pass `false` to skip mangling names, or pass
511 an object to specify [mangle options](#mangle-options) (see below).
512
513 - `mangle.properties` (default: `false`) — a subcategory of the mangle option.
514 Pass an object to specify custom [mangle property options](#mangle-properties-options).
515
516- `nameCache` (default: `null`) — pass an empty object `{}` or a previously
517 used `nameCache` object if you wish to cache mangled variable and
518 property names across multiple invocations of `minify()`. Note: this is
519 a read/write property. `minify()` will read the name cache state of this
520 object and update it during minification so that it may be
521 reused or externally persisted by the user.
522
523- `output` (default: `null`) — pass an object if you wish to specify
524 additional [output options](#output-options). The defaults are optimized
525 for best compression.
526
527- `parse` (default: `{}`) — pass an object if you wish to specify some
528 additional [parse options](#parse-options).
529
530- `sourceMap` (default: `false`) — pass an object if you wish to specify
531 [source map options](#source-map-options).
532
533- `toplevel` (default: `false`) — set to `true` if you wish to enable top level
534 variable and function name mangling and to drop unused variables and functions.
535
536- `v8` (default: `false`) — enable workarounds for Chrome & Node.js bugs.
537
538- `warnings` (default: `false`) — pass `true` to return compressor warnings
539 in `result.warnings`. Use the value `"verbose"` for more detailed warnings.
540
541- `webkit` (default: `false`) — enable workarounds for Safari/WebKit bugs.
542 PhantomJS users should set this option to `true`.
543
544## Minify options structure
545
546```javascript
547{
548 parse: {
549 // parse options
550 },
551 compress: {
552 // compress options
553 },
554 mangle: {
555 // mangle options
556
557 properties: {
558 // mangle property options
559 }
560 },
561 output: {
562 // output options
563 },
564 sourceMap: {
565 // source map options
566 },
567 nameCache: null, // or specify a name cache object
568 toplevel: false,
569 warnings: false,
570}
571```
572
573### Source map options
574
575To generate a source map:
576```javascript
577var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
578 sourceMap: {
579 filename: "out.js",
580 url: "out.js.map"
581 }
582});
583console.log(result.code); // minified output
584console.log(result.map); // source map
585```
586
587Note that the source map is not saved in a file, it's just returned in
588`result.map`. The value passed for `sourceMap.url` is only used to set
589`//# sourceMappingURL=out.js.map` in `result.code`. The value of
590`filename` is only used to set `file` attribute (see [the spec][sm-spec])
591in source map file.
592
593You can set option `sourceMap.url` to be `"inline"` and source map will
594be appended to code.
595
596You can also specify sourceRoot property to be included in source map:
597```javascript
598var result = UglifyJS.minify({"file1.js": "var a = function() {};"}, {
599 sourceMap: {
600 root: "http://example.com/src",
601 url: "out.js.map"
602 }
603});
604```
605
606If you're compressing compiled JavaScript and have a source map for it, you
607can use `sourceMap.content`:
608```javascript
609var result = UglifyJS.minify({"compiled.js": "compiled code"}, {
610 sourceMap: {
611 content: "content from compiled.js.map",
612 url: "minified.js.map"
613 }
614});
615// same as before, it returns `code` and `map`
616```
617
618If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.
619
620If you wish to reduce file size of the source map, set option `sourceMap.names`
621to be `false` and all symbol names will be omitted.
622
623## Parse options
624
625- `bare_returns` (default: `false`) — support top level `return` statements
626
627- `html5_comments` (default: `true`)
628
629- `shebang` (default: `true`) — support `#!command` as the first line
630
631## Compress options
632
633- `annotations` (default: `true`) — Pass `false` to disable potentially dropping
634 functions marked as "pure". A function call is marked as "pure" if a comment
635 annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For
636 example: `/*@__PURE__*/foo();`
637
638- `arguments` (default: `true`) — replace `arguments[index]` with function
639 parameter name whenever possible.
640
641- `arrows` (default: `true`) — apply optimizations to arrow functions
642
643- `assignments` (default: `true`) — apply optimizations to assignment expressions
644
645- `awaits` (default: `true`) — apply optimizations to `await` expressions
646
647- `booleans` (default: `true`) — various optimizations for boolean context,
648 for example `!!a ? b : c → a ? b : c`
649
650- `collapse_vars` (default: `true`) — Collapse single-use non-constant variables,
651 side effects permitting.
652
653- `comparisons` (default: `true`) — apply certain optimizations to binary nodes,
654 e.g. `!(a <= b) → a > b`, attempts to negate binary nodes, e.g.
655 `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.
656
657- `conditionals` (default: `true`) — apply optimizations for `if`-s and conditional
658 expressions
659
660- `dead_code` (default: `true`) — remove unreachable code
661
662- `default_values` (default: `true`) — drop overshadowed default values
663
664- `directives` (default: `true`) — remove redundant or non-standard directives
665
666- `drop_console` (default: `false`) — Pass `true` to discard calls to
667 `console.*` functions. If you wish to drop a specific function call
668 such as `console.info` and/or retain side effects from function arguments
669 after dropping the function call then use `pure_funcs` instead.
670
671- `drop_debugger` (default: `true`) — remove `debugger;` statements
672
673- `evaluate` (default: `true`) — Evaluate expression for shorter constant
674 representation. Pass `"eager"` to always replace function calls whenever
675 possible, or a positive integer to specify an upper bound for each individual
676 evaluation in number of characters.
677
678- `expression` (default: `false`) — Pass `true` to preserve completion values
679 from terminal statements without `return`, e.g. in bookmarklets.
680
681- `functions` (default: `true`) — convert declarations from `var` to `function`
682 whenever possible.
683
684- `global_defs` (default: `{}`) — see [conditional compilation](#conditional-compilation)
685
686- `hoist_exports` (default: `true`) — hoist `export` statements to facilitate
687 various `compress` and `mangle` optimizations.
688
689- `hoist_funs` (default: `false`) — hoist function declarations
690
691- `hoist_props` (default: `true`) — hoist properties from constant object and
692 array literals into regular variables subject to a set of constraints. For example:
693 `var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`
694 works best with `toplevel` and `mangle` enabled, alongside with `compress` option
695 `passes` set to `2` or higher.
696
697- `hoist_vars` (default: `false`) — hoist `var` declarations (this is `false`
698 by default because it seems to increase the size of the output in general)
699
700- `if_return` (default: `true`) — optimizations for if/return and if/continue
701
702- `imports` (default: `true`) — drop unreferenced import symbols when used with `unused`
703
704- `inline` (default: `true`) — inline calls to function with simple/`return` statement:
705 - `false` — same as `0`
706 - `0` — disabled inlining
707 - `1` — inline simple functions
708 - `2` — inline functions with arguments
709 - `3` — inline functions with arguments and variables
710 - `true` — same as `3`
711
712- `join_vars` (default: `true`) — join consecutive `var` statements
713
714- `keep_fargs` (default: `false`) — discard unused function arguments except
715 when unsafe to do so, e.g. code which relies on `Function.prototype.length`.
716 Pass `true` to always retain function arguments.
717
718- `keep_infinity` (default: `false`) — Pass `true` to prevent `Infinity` from
719 being compressed into `1/0`, which may cause performance issues on Chrome.
720
721- `loops` (default: `true`) — optimizations for `do`, `while` and `for` loops
722 when we can statically determine the condition.
723
724- `merge_vars` (default: `true`) — combine and reuse variables.
725
726- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
727 where the return value is discarded, to avoid the parens that the
728 code generator would insert.
729
730- `objects` (default: `true`) — compact duplicate keys in object literals.
731
732- `passes` (default: `1`) — The maximum number of times to run compress.
733 In some cases more than one pass leads to further compressed code. Keep in
734 mind more passes will take more time.
735
736- `properties` (default: `true`) — rewrite property access using the dot notation, for
737 example `foo["bar"] → foo.bar`
738
739- `pure_funcs` (default: `null`) — You can pass an array of names and
740 UglifyJS will assume that those functions do not produce side
741 effects. DANGER: will not check if the name is redefined in scope.
742 An example case here, for instance `var q = Math.floor(a/b)`. If
743 variable `q` is not used elsewhere, UglifyJS will drop it, but will
744 still keep the `Math.floor(a/b)`, not knowing what it does. You can
745 pass `pure_funcs: [ 'Math.floor' ]` to let it know that this
746 function won't produce any side effect, in which case the whole
747 statement would get discarded. The current implementation adds some
748 overhead (compression will be slower). Make sure symbols under `pure_funcs`
749 are also under `mangle.reserved` to avoid mangling.
750
751- `pure_getters` (default: `"strict"`) — If you pass `true` for
752 this, UglifyJS will assume that object property access
753 (e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
754 Specify `"strict"` to treat `foo.bar` as side-effect-free only when
755 `foo` is certain to not throw, i.e. not `null` or `undefined`.
756
757- `reduce_funcs` (default: `true`) — Allows single-use functions to be
758 inlined as function expressions when permissible allowing further
759 optimization. Enabled by default. Option depends on `reduce_vars`
760 being enabled. Some code runs faster in the Chrome V8 engine if this
761 option is disabled. Does not negatively impact other major browsers.
762
763- `reduce_vars` (default: `true`) — Improve optimization on variables assigned with and
764 used as constant values.
765
766- `rests` (default: `true`) — apply optimizations to rest parameters
767
768- `sequences` (default: `true`) — join consecutive simple statements using the
769 comma operator. May be set to a positive integer to specify the maximum number
770 of consecutive comma sequences that will be generated. If this option is set to
771 `true` then the default `sequences` limit is `200`. Set option to `false` or `0`
772 to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`
773 is grandfathered to be equivalent to `true` and as such means `200`. On rare
774 occasions the default sequences limit leads to very slow compress times in which
775 case a value of `20` or less is recommended.
776
777- `side_effects` (default: `true`) — drop extraneous code which does not affect
778 outcome of runtime execution.
779
780- `spreads` (default: `true`) — flatten spread expressions.
781
782- `strings` (default: `true`) — compact string concatenations.
783
784- `switches` (default: `true`) — de-duplicate and remove unreachable `switch` branches
785
786- `templates` (default: `true`) — compact template literals by embedding expressions
787 and/or converting to string literals, e.g. `` `foo ${42}` → "foo 42"``
788
789- `top_retain` (default: `null`) — prevent specific toplevel functions and
790 variables from `unused` removal (can be array, comma-separated, RegExp or
791 function. Implies `toplevel`)
792
793- `toplevel` (default: `false`) — drop unreferenced functions (`"funcs"`) and/or
794 variables (`"vars"`) in the top level scope (`false` by default, `true` to drop
795 both unreferenced functions and variables)
796
797- `typeofs` (default: `true`) — compress `typeof` expressions, e.g.
798 `typeof foo == "undefined" → void 0 === foo`
799
800- `unsafe` (default: `false`) — apply "unsafe" transformations (discussion below)
801
802- `unsafe_comps` (default: `false`) — compress expressions like `a <= b` assuming
803 none of the operands can be (coerced to) `NaN`.
804
805- `unsafe_Function` (default: `false`) — compress and mangle `Function(args, code)`
806 when both `args` and `code` are string literals.
807
808- `unsafe_math` (default: `false`) — optimize numerical expressions like
809 `2 * x * 3` into `6 * x`, which may give imprecise floating point results.
810
811- `unsafe_proto` (default: `false`) — optimize expressions like
812 `Array.prototype.slice.call(a)` into `[].slice.call(a)`
813
814- `unsafe_regexp` (default: `false`) — enable substitutions of variables with
815 `RegExp` values the same way as if they are constants.
816
817- `unsafe_undefined` (default: `false`) — substitute `void 0` if there is a
818 variable named `undefined` in scope (variable name will be mangled, typically
819 reduced to a single character)
820
821- `unused` (default: `true`) — drop unreferenced functions and variables (simple
822 direct variable assignments do not count as references unless set to `"keep_assign"`)
823
824- `varify` (default: `true`) — convert block-scoped declaractions into `var`
825 whenever safe to do so
826
827- `yields` (default: `true`) — apply optimizations to `yield` expressions
828
829## Mangle options
830
831- `eval` (default: `false`) — Pass `true` to mangle names visible in scopes
832 where `eval` or `with` are used.
833
834- `reserved` (default: `[]`) — Pass an array of identifiers that should be
835 excluded from mangling. Example: `["foo", "bar"]`.
836
837- `toplevel` (default: `false`) — Pass `true` to mangle names declared in the
838 top level scope.
839
840Examples:
841
842```javascript
843// test.js
844var globalVar;
845function funcName(firstLongName, anotherLongName) {
846 var myVariable = firstLongName + anotherLongName;
847}
848```
849```javascript
850var code = fs.readFileSync("test.js", "utf8");
851
852UglifyJS.minify(code).code;
853// 'function funcName(a,n){}var globalVar;'
854
855UglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;
856// 'function funcName(firstLongName,a){}var globalVar;'
857
858UglifyJS.minify(code, { mangle: { toplevel: true } }).code;
859// 'function n(n,a){}var a;'
860```
861
862### Mangle properties options
863
864- `builtins` (default: `false`) — Use `true` to allow the mangling of builtin
865 DOM properties. Not recommended to override this setting.
866
867- `debug` (default: `false`) — Mangle names with the original name still present.
868 Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
869
870- `keep_quoted` (default: `false`) — Only mangle unquoted property names.
871
872- `regex` (default: `null`) — Pass a RegExp literal to only mangle property
873 names matching the regular expression.
874
875- `reserved` (default: `[]`) — Do not mangle property names listed in the
876 `reserved` array.
877
878## Output options
879
880The code generator tries to output shortest code possible by default. In
881case you want beautified output, pass `--beautify` (`-b`). Optionally you
882can pass additional arguments that control the code output:
883
884- `annotations` (default: `false`) — pass `true` to retain comment annotations
885 `/*@__PURE__*/` or `/*#__PURE__*/`, otherwise they will be discarded even if
886 `comments` is set.
887
888- `ascii_only` (default: `false`) — escape Unicode characters in strings and
889 regexps (affects directives with non-ascii characters becoming invalid)
890
891- `beautify` (default: `true`) — whether to actually beautify the output.
892 Passing `-b` will set this to true, but you might need to pass `-b` even
893 when you want to generate minified code, in order to specify additional
894 arguments, so you can use `-b beautify=false` to override it.
895
896- `braces` (default: `false`) — always insert braces in `if`, `for`,
897 `do`, `while` or `with` statements, even if their body is a single
898 statement.
899
900- `comments` (default: `false`) — pass `true` or `"all"` to preserve all
901 comments, `"some"` to preserve multi-line comments that contain `@cc_on`,
902 `@license`, or `@preserve` (case-insensitive), a regular expression string
903 (e.g. `/^!/`), or a function which returns `boolean`, e.g.
904 ```javascript
905 function(node, comment) {
906 return comment.value.indexOf("@type " + node.TYPE) >= 0;
907 }
908 ```
909
910- `galio` (default: `false`) — enable workarounds for ANT Galio bugs
911
912- `indent_level` (default: `4`)
913
914- `indent_start` (default: `0`) — prefix all lines by that many spaces
915
916- `inline_script` (default: `true`) — escape HTML comments and the slash in
917 occurrences of `</script>` in strings
918
919- `keep_quoted_props` (default: `false`) — when turned on, prevents stripping
920 quotes from property names in object literals.
921
922- `max_line_len` (default: `false`) — maximum line length (for uglified code)
923
924- `preamble` (default: `null`) — when passed it must be a string and
925 it will be prepended to the output literally. The source map will
926 adjust for this text. Can be used to insert a comment containing
927 licensing information, for example.
928
929- `preserve_line` (default: `false`) — pass `true` to retain line numbering on
930 a best effort basis.
931
932- `quote_keys` (default: `false`) — pass `true` to quote all keys in literal
933 objects
934
935- `quote_style` (default: `0`) — preferred quote style for strings (affects
936 quoted property names and directives as well):
937 - `0` — prefers double quotes, switches to single quotes when there are
938 more double quotes in the string itself. `0` is best for gzip size.
939 - `1` — always use single quotes
940 - `2` — always use double quotes
941 - `3` — always use the original quotes
942
943- `semicolons` (default: `true`) — separate statements with semicolons. If
944 you pass `false` then whenever possible we will use a newline instead of a
945 semicolon, leading to more readable output of uglified code (size before
946 gzip could be smaller; size after gzip insignificantly larger).
947
948- `shebang` (default: `true`) — preserve shebang `#!` in preamble (bash scripts)
949
950- `width` (default: `80`) — only takes effect when beautification is on, this
951 specifies an (orientative) line width that the beautifier will try to
952 obey. It refers to the width of the line text (excluding indentation).
953 It doesn't work very well currently, but it does make the code generated
954 by UglifyJS more readable.
955
956- `wrap_iife` (default: `false`) — pass `true` to wrap immediately invoked
957 function expressions. See
958 [#640](https://github.com/mishoo/UglifyJS/issues/640) for more details.
959
960# Miscellaneous
961
962### Keeping copyright notices or other comments
963
964You can pass `--comments` to retain certain comments in the output. By
965default it will keep JSDoc-style comments that contain "@preserve",
966"@license" or "@cc_on" (conditional compilation for IE). You can pass
967`--comments all` to keep all the comments, or a valid JavaScript regexp to
968keep only comments that match this regexp. For example `--comments /^!/`
969will keep comments like `/*! Copyright Notice */`.
970
971Note, however, that there might be situations where comments are lost. For
972example:
973```javascript
974function f() {
975 /** @preserve Foo Bar */
976 function g() {
977 // this function is never called
978 }
979 return something();
980}
981```
982
983Even though it has "@preserve", the comment will be lost because the inner
984function `g` (which is the AST node to which the comment is attached to) is
985discarded by the compressor as not referenced.
986
987The safest comments where to place copyright information (or other info that
988needs to be kept in the output) are comments attached to toplevel nodes.
989
990### The `unsafe` `compress` option
991
992It enables some transformations that *might* break code logic in certain
993contrived cases, but should be fine for most code. You might want to try it
994on your own code, it should reduce the minified size. Here's what happens
995when this flag is on:
996
997- `new Array(1, 2, 3)` or `Array(1, 2, 3)``[ 1, 2, 3 ]`
998- `new Object()``{}`
999- `String(exp)` or `exp.toString()``"" + exp`
1000- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
1001
1002### Conditional compilation
1003
1004You can use the `--define` (`-d`) switch in order to declare global
1005variables that UglifyJS will assume to be constants (unless defined in
1006scope). For example if you pass `--define DEBUG=false` then, coupled with
1007dead code removal UglifyJS will discard the following from the output:
1008```javascript
1009if (DEBUG) {
1010 console.log("debug stuff");
1011}
1012```
1013
1014You can specify nested constants in the form of `--define env.DEBUG=false`.
1015
1016UglifyJS will warn about the condition being always false and about dropping
1017unreachable code; for now there is no option to turn off only this specific
1018warning, you can pass `warnings=false` to turn off *all* warnings.
1019
1020Another way of doing that is to declare your globals as constants in a
1021separate file and include it into the build. For example you can have a
1022`build/defines.js` file with the following:
1023```javascript
1024var DEBUG = false;
1025var PRODUCTION = true;
1026// etc.
1027```
1028
1029and build your code like this:
1030
1031 uglifyjs build/defines.js js/foo.js js/bar.js... -c
1032
1033UglifyJS will notice the constants and, since they cannot be altered, it
1034will evaluate references to them to the value itself and drop unreachable
1035code as usual. The build will contain the `const` declarations if you use
1036them. If you are targeting < ES6 environments which does not support `const`,
1037using `var` with `reduce_vars` (enabled by default) should suffice.
1038
1039### Conditional compilation API
1040
1041You can also use conditional compilation via the programmatic API. With the difference that the
1042property name is `global_defs` and is a compressor property:
1043
1044```javascript
1045var result = UglifyJS.minify(fs.readFileSync("input.js", "utf8"), {
1046 compress: {
1047 dead_code: true,
1048 global_defs: {
1049 DEBUG: false
1050 }
1051 }
1052});
1053```
1054
1055To replace an identifier with an arbitrary non-constant expression it is
1056necessary to prefix the `global_defs` key with `"@"` to instruct UglifyJS
1057to parse the value as an expression:
1058```javascript
1059UglifyJS.minify("alert('hello');", {
1060 compress: {
1061 global_defs: {
1062 "@alert": "console.log"
1063 }
1064 }
1065}).code;
1066// returns: 'console.log("hello");'
1067```
1068
1069Otherwise it would be replaced as string literal:
1070```javascript
1071UglifyJS.minify("alert('hello');", {
1072 compress: {
1073 global_defs: {
1074 "alert": "console.log"
1075 }
1076 }
1077}).code;
1078// returns: '"console.log"("hello");'
1079```
1080
1081### Using native Uglify AST with `minify()`
1082```javascript
1083// example: parse only, produce native Uglify AST
1084
1085var result = UglifyJS.minify(code, {
1086 parse: {},
1087 compress: false,
1088 mangle: false,
1089 output: {
1090 ast: true,
1091 code: false // optional - faster if false
1092 }
1093});
1094
1095// result.ast contains native Uglify AST
1096```
1097```javascript
1098// example: accept native Uglify AST input and then compress and mangle
1099// to produce both code and native AST.
1100
1101var result = UglifyJS.minify(ast, {
1102 compress: {},
1103 mangle: {},
1104 output: {
1105 ast: true,
1106 code: true // optional - faster if false
1107 }
1108});
1109
1110// result.ast contains native Uglify AST
1111// result.code contains the minified code in string form.
1112```
1113
1114### Working with Uglify AST
1115
1116Transversal and transformation of the native AST can be performed through
1117[`TreeWalker`](https://github.com/mishoo/UglifyJS/blob/master/lib/ast.js) and
1118[`TreeTransformer`](https://github.com/mishoo/UglifyJS/blob/master/lib/transform.js)
1119respectively.
1120
1121### ESTree / SpiderMonkey AST
1122
1123UglifyJS has its own abstract syntax tree format; for
1124[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)
1125we can't easily change to using the SpiderMonkey AST internally. However,
1126UglifyJS now has a converter which can import a SpiderMonkey AST.
1127
1128For example [Acorn][acorn] is a super-fast parser that produces a
1129SpiderMonkey AST. It has a small CLI utility that parses one file and dumps
1130the AST in JSON on the standard output. To use UglifyJS to mangle and
1131compress that:
1132
1133 acorn file.js | uglifyjs -p spidermonkey -m -c
1134
1135The `-p spidermonkey` option tells UglifyJS that all input files are not
1136JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
1137don't use our own parser in this case, but just transform that AST into our
1138internal AST.
1139
1140### Use Acorn for parsing
1141
1142More for fun, I added the `-p acorn` option which will use Acorn to do all
1143the parsing. If you pass this option, UglifyJS will `require("acorn")`.
1144
1145Acorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but
1146converting the SpiderMonkey tree that Acorn produces takes another 150ms so
1147in total it's a bit more than just using UglifyJS's own parser.
1148
1149[acorn]: https://github.com/ternjs/acorn
1150[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
1151
1152### Uglify Fast Minify Mode
1153
1154It's not well known, but whitespace removal and symbol mangling accounts
1155for 95% of the size reduction in minified code for most JavaScript - not
1156elaborate code transforms. One can simply disable `compress` to speed up
1157Uglify builds by 3 to 5 times.
1158
1159| d3.js | minify size | gzip size | minify time (seconds) |
1160| --- | ---: | ---: | ---: |
1161| original | 511,371 | 119,932 | - |
1162| uglify-js@3.13.0 mangle=false, compress=false | 363,988 | 95,695 | 0.56 |
1163| uglify-js@3.13.0 mangle=true, compress=false | 253,305 | 81,281 | 0.99 |
1164| uglify-js@3.13.0 mangle=true, compress=true | 244,436 | 79,854 | 5.30 |
1165
1166To enable fast minify mode from the CLI use:
1167```
1168uglifyjs file.js -m
1169```
1170To enable fast minify mode with the API use:
1171```javascript
1172UglifyJS.minify(code, { compress: false, mangle: true });
1173```
1174
1175### Source maps and debugging
1176
1177Various `compress` transforms that simplify, rearrange, inline and remove code
1178are known to have an adverse effect on debugging with source maps. This is
1179expected as code is optimized and mappings are often simply not possible as
1180some code no longer exists. For highest fidelity in source map debugging
1181disable the Uglify `compress` option and just use `mangle`.
1182
1183### Compiler assumptions
1184
1185To allow for better optimizations, the compiler makes various assumptions:
1186
1187- The code does not rely on preserving its runtime performance characteristics.
1188 Typically uglified code will run faster due to less instructions and easier
1189 inlining, but may be slower on rare occasions for a specific platform, e.g.
1190 see [`reduce_funcs`](#compress-options).
1191- `.toString()` and `.valueOf()` don't have side effects, and for built-in
1192 objects they have not been overridden.
1193- `undefined`, `NaN` and `Infinity` have not been externally redefined.
1194- `arguments.callee`, `arguments.caller` and `Function.prototype.caller` are not used.
1195- The code doesn't expect the contents of `Function.prototype.toString()` or
1196 `Error.prototype.stack` to be anything in particular.
1197- Getting and setting properties on a plain object does not cause other side effects
1198 (using `.watch()` or `Proxy`).
1199- Object properties can be added, removed and modified (not prevented with
1200 `Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,
1201 `Object.preventExtensions()` or `Object.seal()`).
1202- If array destructuring is present, index-like properties in `Array.prototype`
1203 have not been overridden:
1204 ```javascript
1205 Object.prototype[0] = 42;
1206 var [ a ] = [];
1207 var { 0: b } = {};
1208 // 42 undefined
1209 console.log([][0], a);
1210 // 42 42
1211 console.log({}[0], b);
1212 ```
1213- Earlier versions of JavaScript will throw `SyntaxError` with the following:
1214 ```javascript
1215 ({
1216 p: 42,
1217 get p() {},
1218 });
1219 // SyntaxError: Object literal may not have data and accessor property with
1220 // the same name
1221 ```
1222 UglifyJS may modify the input which in turn may suppress those errors.
1223- Iteration order of keys over an object which contains spread syntax in later
1224 versions of Chrome and Node.js may be altered.
1225- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped
1226 within `function(){ ... }`, thus forbids aliasing of declared global variables:
1227 ```javascript
1228 A = "FAIL";
1229 var B = "FAIL";
1230 // can be `global`, `self`, `window` etc.
1231 var top = function() {
1232 return this;
1233 }();
1234 // "PASS"
1235 top.A = "PASS";
1236 console.log(A);
1237 // "FAIL" after compress and/or mangle
1238 top.B = "PASS";
1239 console.log(B);
1240 ```
1241- Use of `arguments` alongside destructuring as function parameters, e.g.
1242 `function({}, arguments) {}` will result in `SyntaxError` in earlier versions
1243 of Chrome and Node.js - UglifyJS may modify the input which in turn may
1244 suppress those errors.
1245- Earlier versions of Chrome and Node.js will throw `ReferenceError` with the
1246 following:
1247 ```javascript
1248 var a;
1249 try {
1250 throw 42;
1251 } catch ({
1252 [a]: b,
1253 // ReferenceError: a is not defined
1254 }) {
1255 let a;
1256 }
1257 ```
1258 UglifyJS may modify the input which in turn may suppress those errors.
1259- Later versions of JavaScript will throw `SyntaxError` with the following:
1260 ```javascript
1261 a => {
1262 let a;
1263 };
1264 // SyntaxError: Identifier 'a' has already been declared
1265 ```
1266 UglifyJS may modify the input which in turn may suppress those errors.
1267- Later versions of JavaScript will throw `SyntaxError` with the following:
1268 ```javascript
1269 try {
1270 // ...
1271 } catch ({ message: a }) {
1272 var a;
1273 }
1274 // SyntaxError: Identifier 'a' has already been declared
1275 ```
1276 UglifyJS may modify the input which in turn may suppress those errors.
1277- Some versions of Chrome and Node.js will throw `ReferenceError` with the
1278 following:
1279 ```javascript
1280 console.log(((a, b = function() {
1281 return a;
1282 // ReferenceError: a is not defined
1283 }()) => b)());
1284 ```
1285 UglifyJS may modify the input which in turn may suppress those errors.
1286- Some arithmetic operations with `BigInt` may throw `TypeError`:
1287 ```javascript
1288 1n + 1;
1289 // TypeError: can't convert BigInt to number
1290 ```
1291 UglifyJS may modify the input which in turn may suppress those errors.
1292- Some versions of JavaScript will throw `SyntaxError` with the
1293 following:
1294 ```javascript
1295 console.log(String.raw`\uFo`);
1296 // SyntaxError: Invalid Unicode escape sequence
1297 ```
1298 UglifyJS may modify the input which in turn may suppress those errors.
1299- Some versions of JavaScript will throw `SyntaxError` with the
1300 following:
1301 ```javascript
1302 try {} catch (e) {
1303 for (var e of []);
1304 }
1305 // SyntaxError: Identifier 'e' has already been declared
1306 ```
1307 UglifyJS may modify the input which in turn may suppress those errors.
1308- Some versions of Chrome and Node.js will give incorrect results with the
1309 following:
1310 ```javascript
1311 console.log({
1312 ...{
1313 set 42(v) {},
1314 42: "PASS",
1315 },
1316 });
1317 // Expected: { '42': 'PASS' }
1318 // Actual: { '42': undefined }
1319 ```
1320 UglifyJS may modify the input which in turn may suppress those errors.
1321- Later versions of JavaScript will throw `SyntaxError` with the following:
1322 ```javascript
1323 var await;
1324 async function f() {
1325 class A {
1326 static p = await;
1327 }
1328 }
1329 // SyntaxError: Unexpected reserved word
1330 ```
1331 UglifyJS may modify the input which in turn may suppress those errors.
1332- Later versions of JavaScript will throw `SyntaxError` with the following:
1333 ```javascript
1334 var async;
1335 for (async of []);
1336 // SyntaxError: The left-hand side of a for-of loop may not be 'async'.
1337 ```
1338 UglifyJS may modify the input which in turn may suppress those errors.
1339- Later versions of Chrome and Node.js will give incorrect results with the
1340 following:
1341 ```javascript
1342 console.log({
1343 ...console,
1344 get 42() {
1345 return "FAIL";
1346 },
1347 [42]: "PASS",
1348 }[42]);
1349 // Expected: "PASS"
1350 // Actual: "FAIL"
1351 ```
1352 UglifyJS may modify the input which in turn may suppress those errors.
1353- Earlier versions of JavaScript will throw `TypeError` with the following:
1354 ```javascript
1355 (function() {
1356 {
1357 const a = "foo";
1358 }
1359 {
1360 const a = "bar";
1361 }
1362 })();
1363 // TypeError: const 'a' has already been declared
1364 ```
1365 UglifyJS may modify the input which in turn may suppress those errors.
1366
\No newline at end of file