`reduce_vars` enables substitution of variables but did not clone the value's `AST_Node`.
This confuses `collapse_vars` and result in invalid AST and subsequent crash.
fixes#1609
As patched in #1597, `make_node_from_constant()` makes inconsistent and sometimes incorrect calls to `optimize()` and `transform()`.
Fix those issues properly by changing the semantics of `evaluate()` and `make_node_from_constant()`, with the side effect that `evaluate()` no longer eagerly converts constant to `AST_Node`.
Liberal use of `Compressor.transform()` and `AST_Node.optimize()` presents an issue for look-up operations like `TreeWalker.in_boolean_context()` and `TreeWalker.parent()`.
This is an incremental fix such that `AST_Node.optimize()` would now contain the correct stack information when called correctly.
Self-referenced function has non-fixed values assigned to its parameters.
Let `unused` & `!keep_fnames` do the scanning, then apply `reduce_vars` only to unnamed functions.
fixes#1595
As patched on `harmony`, `statement()` is the only user of `embed_tokens()` with a missing error branch.
Updated test case and match up with `harmony` to facilitate future merging.
- one-use function call => IIFE should take `eval()` & `arguments` into account
- if unused parameter cannot be eliminated, replace it with `0`
fixes#1583
those were not optimised for `unused` before, which made it necessary for `reduce_vars` to have separate steps for `keep_fnames`
docs update by @kzc
closes#1577
Function expression can be assigned to a variable and be given a name. Ensure function name is the reduced variable before clearing it out.
fixes#1573fixes#1575
- omitting trailing semi-colon in do-while breaks non-browser parser, e.g. uglify-js 1.x
- trailing semi-colon only breaks IE8 if followed by `else` or `while`
- always use braces in do-while body to workaround 2nd case with no size loss in compression
fixes#1568
`AST_Label.references` get `.initialize()` to `[]` every time after `.clone()`
So walk down the tree to pick up the cloned `AST_LoopControl` pieces and put it back together.
`unsafe` turns undefined keyword into a variable of the same name if found, but that interferes with other related optimisations.
Keep track of such transformations to ensure zero information loss in the process.
Bookmarklet for instance implicitedly assumes a "completion value" without using `return`.
The `expression` option now supports such use cases.
Optimisations on IIFEs also enhanced.
fixes#354fixes#543fixes#625fixes#628fixes#640closes#1293
Avoid variable substitution in the following cases:
- use of variable before declaration
- declaration within conditional code blocks
- declaration within loop body
fixes#1518fixes#1525
Patched up `make_node()` without `orig`.
There may be other cases where `start` could be missing, so make it print "undefined" instead of crashing.
fixes#1518
Modules like webpack and grunt-contrib-uglify still uses `ast.transform(compressor)` before `Compressor.compress(ast)` was introduced.
Workaround this compatibility issue by deactivating `reduce_vars` in such case.
Also fix use case with omitted `options` when calling `Compressor()`.
fixes#1516
A function call or IIFE with an immediately preceding comment
containing `@__PURE__` or `#__PURE__` is deemed to be a
side-effect-free pure function call and can potentially be
dropped.
Depends on `side_effects` option.
`[#@]__PURE__` hint will be removed from comment when pure
call is dropped.
fixes#1261closes#1448
- support arrays, objects & AST_Node
- support `"a.b":1` on both cli & API
- emit warning if variable is modified
- override top-level variables
fixes#1416closes#1198closes#1469
- remove extra tree scanning phase for `negate_iife`
- `negate_iife` now only deals with the narrowest form, i.e. IIFE sitting directly under `AST_SimpleStatement`
- `booleans`, `conditionals` etc. will now take care the rest via more accurate accounting
- `a(); void b();` => `a(); b();`
fixes#1288closes#1451
- assign statement does not count towards variable usage by default
- only works with assignments on the same scope level as declaration
- can be disabled with `unused` set to "keep_assign"
- `toplevel` to drop unused top-level variables and/or functions
- `top_retain` to whitelist top-level exceptions
closes#1450
- remove call to evaluate() in is_constant() and let nested optimize() does its job instead
- reject RegExp in is_constant() and remove special case logic under collapse_vars
- operands to conditionals optimisation are now always evaluate()-ed
- throw error in constant_value() instead of returning undefined to catch possible bugs, similar to make_node_from_constant()
- optimise binary boolean operators under `evaluate` instead of `conditionals`
If using `inSourceMap` this fix will ensure the copying of `sourcesContent` is based on potentially normalized `sources` values (https://github.com/mozilla/source-map/blob/master/lib/source-map-consumer.js#L304-L309).
For example `normalize` (https://github.com/mozilla/source-map/blob/master/lib/util.js#L80-L123) will rewrite `./dist/mySource.js` to `dist/mySource.js` in the target `_sources` of the `SourceMapConsumer`. As a result `orig_map.sourceContentFor(source, true);` would return `null` since the orginal `source` was no longer available in the consumer. By using the keys generating from the `SourceMapConsumer.constructor` consistency is ensured.
Using the symbol declaration tracking of UglifyJS doesn't make sense here
anyway, `arguments` always comes from something in the current scope.
fixes#1299
Fixes: #1247
Fix --mangle-props and --name-cache inconsistency.
AST_Dot and AST_Sub properties are now mangled by --mangle-props
without regard to being used in an assignment statement.
Note: if --mangle-props is used then *all* javascript files used must
be uglified with the same mangle options.
Fix the ignore_quoted=true mangle option, also known as
`--mangle-props=unquoted`. If a given property is quoted anywhere
it will not be mangled in any quoted or non-quoted context.