terser 5.18.0 → 5.18.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -1
- package/README.md +33 -7
- package/dist/bundle.min.js +72 -24
- package/lib/compress/reduce-vars.js +76 -28
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
##
|
3
|
+
## v5.18.2
|
4
|
+
- Stop using recursion in hoisted defuns fix.
|
5
|
+
|
6
|
+
## v5.18.1
|
7
|
+
- Fix major performance issue caused by hoisted defuns' scopes bugfix.
|
8
|
+
|
9
|
+
## v5.18.0
|
4
10
|
- Add new `/*@__MANGLE_PROP__*/` annotation, to mark properties that should be mangled.
|
5
11
|
|
6
12
|
## v5.17.7
|
package/README.md
CHANGED
@@ -52,7 +52,9 @@ From NPM for programmatic use:
|
|
52
52
|
|
53
53
|
<!-- CLI_USAGE:START -->
|
54
54
|
|
55
|
-
|
55
|
+
```
|
56
|
+
terser [input files] [options]
|
57
|
+
```
|
56
58
|
|
57
59
|
Terser can take multiple input files. It's recommended that you pass the
|
58
60
|
input files first, then pass the options. Terser will parse input files
|
@@ -674,6 +676,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|
674
676
|
|
675
677
|
If you happen to need the source map as a raw object, set `sourceMap.asObject` to `true`.
|
676
678
|
|
679
|
+
<!-- API_REFERENCE:END -->
|
680
|
+
|
681
|
+
<!-- OPTIONS:START -->
|
682
|
+
|
677
683
|
## Parse options
|
678
684
|
|
679
685
|
- `bare_returns` (default `false`) -- support top level `return` statements
|
@@ -1062,8 +1068,14 @@ as "output options".
|
|
1062
1068
|
function expressions that are passed as arguments, in parenthesis. See
|
1063
1069
|
[OptimizeJS](https://github.com/nolanlawson/optimize-js) for more details.
|
1064
1070
|
|
1071
|
+
|
1072
|
+
<!-- OPTIONS:END -->
|
1073
|
+
|
1074
|
+
|
1065
1075
|
# Miscellaneous
|
1066
1076
|
|
1077
|
+
<!-- MISCELLANEOUS:START -->
|
1078
|
+
|
1067
1079
|
### Keeping copyright notices or other comments
|
1068
1080
|
|
1069
1081
|
You can pass `--comments` to retain certain comments in the output. By
|
@@ -1328,19 +1340,27 @@ $ rm -rf node_modules yarn.lock
|
|
1328
1340
|
$ yarn
|
1329
1341
|
```
|
1330
1342
|
|
1331
|
-
<!--
|
1343
|
+
<!-- MISCELLANEOUS:END -->
|
1332
1344
|
|
1333
1345
|
# Reporting issues
|
1334
1346
|
|
1335
|
-
|
1347
|
+
<!-- REPORTING_ISSUES:START -->
|
1348
|
+
|
1349
|
+
## A minimal, reproducible example
|
1350
|
+
|
1351
|
+
You're expected to provide a [minimal reproducible example] of input code that will demonstrate your issue.
|
1352
|
+
|
1353
|
+
To get to this example, you can remove bits of your code and stop if your issue ceases to reproduce.
|
1336
1354
|
|
1337
1355
|
## Obtaining the source code given to Terser
|
1338
1356
|
|
1339
|
-
Because users often don't control the call to `await minify()` or its arguments, Terser provides a `TERSER_DEBUG_DIR` environment variable to make terser output some debug logs.
|
1357
|
+
Because users often don't control the call to `await minify()` or its arguments, Terser provides a `TERSER_DEBUG_DIR` environment variable to make terser output some debug logs.
|
1340
1358
|
|
1341
|
-
|
1342
|
-
|
1343
|
-
|
1359
|
+
These logs will contain the input code and options of each `minify()` call.
|
1360
|
+
|
1361
|
+
```bash
|
1362
|
+
TERSER_DEBUG_DIR=/tmp/terser-log-dir command-that-uses-terser
|
1363
|
+
ls /tmp/terser-log-dir
|
1344
1364
|
terser-debug-123456.log
|
1345
1365
|
```
|
1346
1366
|
|
@@ -1350,6 +1370,12 @@ If you're not sure how to set an environment variable on your shell (the above e
|
|
1350
1370
|
> npx cross-env TERSER_DEBUG_DIR=/path/to/logs command-that-uses-terser
|
1351
1371
|
```
|
1352
1372
|
|
1373
|
+
## Stack traces
|
1374
|
+
|
1375
|
+
In the terser CLI we use [source-map-support](https://npmjs.com/source-map-support) to produce good error stacks. In your own app, you're expected to enable source-map-support (read their docs) to have nice stack traces that will help you write good issues.
|
1376
|
+
|
1377
|
+
<!-- REPORTING_ISSUES:END -->
|
1378
|
+
|
1353
1379
|
# README.md Patrons:
|
1354
1380
|
|
1355
1381
|
*note*: <s>You can support this project on patreon: [link]</s> **The Terser Patreon is shutting down in favor of opencollective**. Check out [PATRONS.md](https://github.com/terser/terser/blob/master/PATRONS.md) for our first-tier patrons.
|
package/dist/bundle.min.js
CHANGED
@@ -15934,6 +15934,10 @@ function handle_defined_after_hoist(parent) {
|
|
15934
15934
|
) return true;
|
15935
15935
|
});
|
15936
15936
|
|
15937
|
+
const symbols_of_interest = new Set();
|
15938
|
+
const defuns_of_interest = new Set();
|
15939
|
+
const potential_conflicts = [];
|
15940
|
+
|
15937
15941
|
for (const defun of defuns) {
|
15938
15942
|
const fname_def = defun.name.definition();
|
15939
15943
|
const found_self_ref_in_other_defuns = defuns.some(
|
@@ -15963,35 +15967,79 @@ function handle_defined_after_hoist(parent) {
|
|
15963
15967
|
continue;
|
15964
15968
|
}
|
15965
15969
|
|
15966
|
-
//
|
15967
|
-
|
15968
|
-
|
15969
|
-
|
15970
|
-
|
15971
|
-
|
15970
|
+
// for the slower checks below this loop
|
15971
|
+
potential_conflicts.push({ defun, def, fname_def });
|
15972
|
+
symbols_of_interest.add(def.id);
|
15973
|
+
symbols_of_interest.add(fname_def.id);
|
15974
|
+
defuns_of_interest.add(defun);
|
15975
|
+
}
|
15976
|
+
}
|
15972
15977
|
|
15973
|
-
|
15974
|
-
|
15975
|
-
|
15976
|
-
|
15977
|
-
|
15978
|
-
|
15979
|
-
|
15978
|
+
// linearize all symbols, and locate defs that are read after the defun
|
15979
|
+
if (potential_conflicts.length) {
|
15980
|
+
// All "symbols of interest", that is, defuns or defs, that we found.
|
15981
|
+
// These are placed in order so we can check which is after which.
|
15982
|
+
const found_symbols = [];
|
15983
|
+
// Indices of `found_symbols` which are writes
|
15984
|
+
const found_symbol_writes = new Set();
|
15985
|
+
// Defun ranges are recorded because we don't care if a function uses the def internally
|
15986
|
+
const defun_ranges = new Map();
|
15987
|
+
|
15988
|
+
let tw;
|
15989
|
+
parent.walk((tw = new TreeWalker((node, descend) => {
|
15990
|
+
if (node instanceof AST_Defun && defuns_of_interest.has(node)) {
|
15991
|
+
const start = found_symbols.length;
|
15992
|
+
descend();
|
15993
|
+
const end = found_symbols.length;
|
15994
|
+
|
15995
|
+
defun_ranges.set(node, { start, end });
|
15996
|
+
return true;
|
15997
|
+
}
|
15998
|
+
// if we found a defun on the list, mark IN_DEFUN=id and descend
|
15999
|
+
|
16000
|
+
if (node instanceof AST_Symbol && node.thedef) {
|
16001
|
+
const id = node.definition().id;
|
16002
|
+
if (symbols_of_interest.has(id)) {
|
16003
|
+
if (node instanceof AST_SymbolDeclaration || is_lhs(node, tw)) {
|
16004
|
+
found_symbol_writes.add(found_symbols.length);
|
16005
|
+
}
|
16006
|
+
found_symbols.push(id);
|
15980
16007
|
}
|
16008
|
+
}
|
16009
|
+
})));
|
15981
16010
|
|
15982
|
-
|
15983
|
-
|
15984
|
-
|
15985
|
-
|
15986
|
-
|
15987
|
-
|
15988
|
-
|
15989
|
-
|
15990
|
-
|
16011
|
+
for (const { def, defun, fname_def } of potential_conflicts) {
|
16012
|
+
const defun_range = defun_ranges.get(defun);
|
16013
|
+
|
16014
|
+
// find the index in `found_symbols`, with some special rules:
|
16015
|
+
const find = (sym_id, starting_at = 0, must_be_write = false) => {
|
16016
|
+
let index = starting_at;
|
16017
|
+
|
16018
|
+
for (;;) {
|
16019
|
+
index = found_symbols.indexOf(sym_id, index);
|
16020
|
+
|
16021
|
+
if (index === -1) {
|
16022
|
+
break;
|
16023
|
+
} else if (index >= defun_range.start && index < defun_range.end) {
|
16024
|
+
index = defun_range.end;
|
16025
|
+
continue;
|
16026
|
+
} else if (must_be_write && !found_symbol_writes.has(index)) {
|
16027
|
+
index++;
|
16028
|
+
continue;
|
16029
|
+
} else {
|
16030
|
+
break;
|
16031
|
+
}
|
15991
16032
|
}
|
15992
|
-
});
|
15993
16033
|
|
15994
|
-
|
16034
|
+
return index;
|
16035
|
+
};
|
16036
|
+
|
16037
|
+
const read_defun_at = find(fname_def.id);
|
16038
|
+
const wrote_def_at = find(def.id, read_defun_at + 1, true);
|
16039
|
+
|
16040
|
+
const wrote_def_after_reading_defun = read_defun_at != -1 && wrote_def_at != -1 && wrote_def_at > read_defun_at;
|
16041
|
+
|
16042
|
+
if (wrote_def_after_reading_defun) {
|
15995
16043
|
def.fixed = false;
|
15996
16044
|
}
|
15997
16045
|
}
|
@@ -93,10 +93,10 @@ import {
|
|
93
93
|
AST_Yield,
|
94
94
|
|
95
95
|
walk,
|
96
|
-
walk_parent,
|
97
|
-
walk_abort,
|
98
96
|
walk_body,
|
99
97
|
|
98
|
+
TreeWalker,
|
99
|
+
|
100
100
|
_INLINE,
|
101
101
|
_NOINLINE,
|
102
102
|
_PURE
|
@@ -513,6 +513,10 @@ function handle_defined_after_hoist(parent) {
|
|
513
513
|
) return true;
|
514
514
|
});
|
515
515
|
|
516
|
+
const symbols_of_interest = new Set();
|
517
|
+
const defuns_of_interest = new Set();
|
518
|
+
const potential_conflicts = [];
|
519
|
+
|
516
520
|
for (const defun of defuns) {
|
517
521
|
const fname_def = defun.name.definition();
|
518
522
|
const found_self_ref_in_other_defuns = defuns.some(
|
@@ -542,35 +546,79 @@ function handle_defined_after_hoist(parent) {
|
|
542
546
|
continue;
|
543
547
|
}
|
544
548
|
|
545
|
-
//
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
// Step 1: find `call_defun()` or other refs to the defun
|
553
|
-
if (
|
554
|
-
!found_defun_ref
|
555
|
-
&& node.thedef === fname_def
|
556
|
-
&& node instanceof AST_Symbol
|
557
|
-
) {
|
558
|
-
found_defun_ref = true;
|
559
|
-
}
|
549
|
+
// for the slower checks below this loop
|
550
|
+
potential_conflicts.push({ defun, def, fname_def });
|
551
|
+
symbols_of_interest.add(def.id);
|
552
|
+
symbols_of_interest.add(fname_def.id);
|
553
|
+
defuns_of_interest.add(defun);
|
554
|
+
}
|
555
|
+
}
|
560
556
|
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
557
|
+
// linearize all symbols, and locate defs that are read after the defun
|
558
|
+
if (potential_conflicts.length) {
|
559
|
+
// All "symbols of interest", that is, defuns or defs, that we found.
|
560
|
+
// These are placed in order so we can check which is after which.
|
561
|
+
const found_symbols = [];
|
562
|
+
// Indices of `found_symbols` which are writes
|
563
|
+
const found_symbol_writes = new Set();
|
564
|
+
// Defun ranges are recorded because we don't care if a function uses the def internally
|
565
|
+
const defun_ranges = new Map();
|
566
|
+
|
567
|
+
let tw;
|
568
|
+
parent.walk((tw = new TreeWalker((node, descend) => {
|
569
|
+
if (node instanceof AST_Defun && defuns_of_interest.has(node)) {
|
570
|
+
const start = found_symbols.length;
|
571
|
+
descend();
|
572
|
+
const end = found_symbols.length;
|
573
|
+
|
574
|
+
defun_ranges.set(node, { start, end });
|
575
|
+
return true;
|
576
|
+
}
|
577
|
+
// if we found a defun on the list, mark IN_DEFUN=id and descend
|
578
|
+
|
579
|
+
if (node instanceof AST_Symbol && node.thedef) {
|
580
|
+
const id = node.definition().id;
|
581
|
+
if (symbols_of_interest.has(id)) {
|
582
|
+
if (node instanceof AST_SymbolDeclaration || is_lhs(node, tw)) {
|
583
|
+
found_symbol_writes.add(found_symbols.length);
|
584
|
+
}
|
585
|
+
found_symbols.push(id);
|
570
586
|
}
|
571
|
-
}
|
587
|
+
}
|
588
|
+
})));
|
589
|
+
|
590
|
+
for (const { def, defun, fname_def } of potential_conflicts) {
|
591
|
+
const defun_range = defun_ranges.get(defun);
|
592
|
+
|
593
|
+
// find the index in `found_symbols`, with some special rules:
|
594
|
+
const find = (sym_id, starting_at = 0, must_be_write = false) => {
|
595
|
+
let index = starting_at;
|
596
|
+
|
597
|
+
for (;;) {
|
598
|
+
index = found_symbols.indexOf(sym_id, index);
|
599
|
+
|
600
|
+
if (index === -1) {
|
601
|
+
break;
|
602
|
+
} else if (index >= defun_range.start && index < defun_range.end) {
|
603
|
+
index = defun_range.end;
|
604
|
+
continue;
|
605
|
+
} else if (must_be_write && !found_symbol_writes.has(index)) {
|
606
|
+
index++;
|
607
|
+
continue;
|
608
|
+
} else {
|
609
|
+
break;
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
return index;
|
614
|
+
};
|
615
|
+
|
616
|
+
const read_defun_at = find(fname_def.id);
|
617
|
+
const wrote_def_at = find(def.id, read_defun_at + 1, true);
|
618
|
+
|
619
|
+
const wrote_def_after_reading_defun = read_defun_at != -1 && wrote_def_at != -1 && wrote_def_at > read_defun_at;
|
572
620
|
|
573
|
-
if (
|
621
|
+
if (wrote_def_after_reading_defun) {
|
574
622
|
def.fixed = false;
|
575
623
|
}
|
576
624
|
}
|