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