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