terser 5.6.1 → 5.7.0
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 +10 -0
- package/README.md +25 -19
- package/dist/bundle.min.js +165 -122
- package/lib/ast.js +12 -0
- package/lib/compress/index.js +55 -34
- package/lib/minify.js +26 -9
- package/lib/parse.js +72 -80
- package/lib/utils/index.js +1 -1
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.7.0
|
4
|
+
|
5
|
+
- Several compile-time evaluation and inlining fixes
|
6
|
+
- Allow `reduce_funcs` to be disabled again.
|
7
|
+
- Add `spidermonkey` options to parse and format (#974)
|
8
|
+
- Accept `{get = "default val"}` and `{set = "default val"}` in destructuring arguments.
|
9
|
+
- Change package.json export map to help require.resolve (#971)
|
10
|
+
- Improve docs
|
11
|
+
- Fix `export default` of an anonymous class with `extends`
|
12
|
+
|
3
13
|
## v5.6.1
|
4
14
|
|
5
15
|
- Mark assignments to the `.prototype` of a class as pure
|
package/README.md
CHANGED
@@ -21,8 +21,8 @@ Find the changelog in [CHANGELOG.md](https://github.com/terser/terser/blob/maste
|
|
21
21
|
[npm-url]: https://npmjs.org/package/terser
|
22
22
|
[downloads-image]: https://img.shields.io/npm/dm/terser.svg
|
23
23
|
[downloads-url]: https://npmjs.org/package/terser
|
24
|
-
[travis-image]: https://
|
25
|
-
[travis-url]: https://travis-ci.
|
24
|
+
[travis-image]: https://travis-ci.com/terser/terser.svg?branch=master
|
25
|
+
[travis-url]: https://travis-ci.com/terser/terser
|
26
26
|
[opencollective-contributors]: https://opencollective.com/terser/tiers/badge.svg
|
27
27
|
[opencollective-url]: https://opencollective.com/terser
|
28
28
|
|
@@ -416,7 +416,7 @@ Browser loading is also supported:
|
|
416
416
|
|
417
417
|
There is a single async high level function, **`async minify(code, options)`**,
|
418
418
|
which will perform all minification [phases](#minify-options) in a configurable
|
419
|
-
manner.
|
419
|
+
manner. By default `minify()` will enable [`compress`](#compress-options)
|
420
420
|
and [`mangle`](#mangle-options). Example:
|
421
421
|
```javascript
|
422
422
|
var code = "function add(first, second) { return first + second; }";
|
@@ -608,7 +608,7 @@ try {
|
|
608
608
|
module: false,
|
609
609
|
nameCache: null, // or specify a name cache object
|
610
610
|
safari10: false,
|
611
|
-
toplevel: false
|
611
|
+
toplevel: false
|
612
612
|
}
|
613
613
|
```
|
614
614
|
|
@@ -669,6 +669,8 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
|
|
669
669
|
|
670
670
|
- `shebang` (default `true`) -- support `#!command` as the first line
|
671
671
|
|
672
|
+
- `spidermonkey` (default `false`) -- accept a Spidermonkey (Mozilla) AST
|
673
|
+
|
672
674
|
## Compress options
|
673
675
|
|
674
676
|
- `defaults` (default: `true`) -- Pass `false` to disable most default
|
@@ -795,11 +797,13 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
|
|
795
797
|
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
|
796
798
|
`foo` is certain to not throw, i.e. not `null` or `undefined`.
|
797
799
|
|
798
|
-
- `reduce_funcs` (legacy option, safely ignored for backwards compatibility).
|
799
|
-
|
800
800
|
- `reduce_vars` (default: `true`) -- Improve optimization on variables assigned with and
|
801
801
|
used as constant values.
|
802
802
|
|
803
|
+
- `reduce_funcs` (default: `true`) -- Inline single-use functions when
|
804
|
+
possible. Depends on `reduce_vars` being enabled. Disabling this option
|
805
|
+
sometimes improves performance of the output code.
|
806
|
+
|
803
807
|
- `sequences` (default: `true`) -- join consecutive simple statements using the
|
804
808
|
comma operator. May be set to a positive integer to specify the maximum number
|
805
809
|
of consecutive comma sequences that will be generated. If this option is set to
|
@@ -848,7 +852,7 @@ If you happen to need the source map as a raw object, set `sourceMap.asObject` t
|
|
848
852
|
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
849
853
|
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
850
854
|
|
851
|
-
- `unsafe_symbols` (default: `false`) -- removes keys from native Symbol
|
855
|
+
- `unsafe_symbols` (default: `false`) -- removes keys from native Symbol
|
852
856
|
declarations, e.g `Symbol("kDog")` becomes `Symbol()`.
|
853
857
|
|
854
858
|
- `unsafe_methods` (default: false) -- Converts `{ m: function(){} }` to
|
@@ -929,11 +933,10 @@ await minify(code, { mangle: { toplevel: true } }).code;
|
|
929
933
|
- `debug` (default: `false`) — Mangle names with the original name still present.
|
930
934
|
Pass an empty string `""` to enable, or a non-empty string to set the debug suffix.
|
931
935
|
|
932
|
-
- `keep_quoted` (default: `false`) —
|
933
|
-
- `
|
934
|
-
|
935
|
-
- `
|
936
|
-
explicitly reserved.
|
936
|
+
- `keep_quoted` (default: `false`) — How quoting properties (`{"prop": ...}` and `obj["prop"]`) controls what gets mangled.
|
937
|
+
- `"strict"` (recommended) -- `obj.prop` is mangled.
|
938
|
+
- `false` -- `obj["prop"]` is mangled.
|
939
|
+
- `true` -- `obj.prop` is mangled unless there is `obj["prop"]` elsewhere in the code.
|
937
940
|
|
938
941
|
- `regex` (default: `null`) — Pass a [RegExp literal or pattern string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) to only mangle property matching the regular expression.
|
939
942
|
|
@@ -954,19 +957,17 @@ as "output options".
|
|
954
957
|
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
|
955
958
|
regexps (affects directives with non-ascii characters becoming invalid)
|
956
959
|
|
957
|
-
- `beautify` (default `false`) -- whether to
|
958
|
-
|
959
|
-
when you want to generate minified code, in order to specify additional
|
960
|
-
arguments, so you can use `-b beautify=false` to override it.
|
960
|
+
- `beautify` (default `false`) -- (DEPRECATED) whether to beautify the output.
|
961
|
+
When using the legacy `-b` CLI flag, this is set to true by default.
|
961
962
|
|
962
963
|
- `braces` (default `false`) -- always insert braces in `if`, `for`,
|
963
964
|
`do`, `while` or `with` statements, even if their body is a single
|
964
965
|
statement.
|
965
966
|
|
966
967
|
- `comments` (default `"some"`) -- by default it keeps JSDoc-style comments
|
967
|
-
that contain "@license"
|
968
|
-
comments, `false` to omit comments in the output,
|
969
|
-
(e.g. `/^!/`) or a function.
|
968
|
+
that contain "@license", "@preserve" or start with `!`, pass `true` or
|
969
|
+
`"all"` to preserve all comments, `false` to omit comments in the output,
|
970
|
+
a regular expression string (e.g. `/^!/`) or a function.
|
970
971
|
|
971
972
|
- `ecma` (default `5`) -- set desired EcmaScript standard version for output.
|
972
973
|
Set `ecma` to `2015` or greater to emit shorthand object properties - i.e.:
|
@@ -1019,6 +1020,8 @@ as "output options".
|
|
1019
1020
|
|
1020
1021
|
- `shebang` (default `true`) -- preserve shebang `#!` in preamble (bash scripts)
|
1021
1022
|
|
1023
|
+
- `spidermonkey` (default `false`) -- produce a Spidermonkey (Mozilla) AST
|
1024
|
+
|
1022
1025
|
- `webkit` (default `false`) -- enable workarounds for WebKit bugs.
|
1023
1026
|
PhantomJS users should set this option to `true`.
|
1024
1027
|
|
@@ -1190,6 +1193,9 @@ JavaScript, but JS code described in SpiderMonkey AST in JSON. Therefore we
|
|
1190
1193
|
don't use our own parser in this case, but just transform that AST into our
|
1191
1194
|
internal AST.
|
1192
1195
|
|
1196
|
+
`spidermonkey` is also available in `minify` as `parse` and `format` options to
|
1197
|
+
accept and/or produce a spidermonkey AST.
|
1198
|
+
|
1193
1199
|
### Use Acorn for parsing
|
1194
1200
|
|
1195
1201
|
More for fun, I added the `-p acorn` option which will use Acorn to do all
|
package/dist/bundle.min.js
CHANGED
@@ -204,7 +204,7 @@ function mergeSort(array, cmp) {
|
|
204
204
|
function makePredicate(words) {
|
205
205
|
if (!Array.isArray(words)) words = words.split(" ");
|
206
206
|
|
207
|
-
return new Set(words);
|
207
|
+
return new Set(words.sort());
|
208
208
|
}
|
209
209
|
|
210
210
|
function map_add(map, key, value) {
|
@@ -1459,7 +1459,7 @@ function parse($TEXT, options) {
|
|
1459
1459
|
if (is_if_body) {
|
1460
1460
|
croak("classes are not allowed as the body of an if");
|
1461
1461
|
}
|
1462
|
-
return class_(AST_DefClass);
|
1462
|
+
return class_(AST_DefClass, is_export_default);
|
1463
1463
|
|
1464
1464
|
case "function":
|
1465
1465
|
next();
|
@@ -2654,7 +2654,7 @@ function parse($TEXT, options) {
|
|
2654
2654
|
return new AST_Object({ properties: a });
|
2655
2655
|
});
|
2656
2656
|
|
2657
|
-
function class_(KindOfClass) {
|
2657
|
+
function class_(KindOfClass, is_export_default) {
|
2658
2658
|
var start, method, class_name, extends_, a = [];
|
2659
2659
|
|
2660
2660
|
S.input.push_directives_stack(); // Push directive stack, but not scope stack
|
@@ -2665,7 +2665,11 @@ function parse($TEXT, options) {
|
|
2665
2665
|
}
|
2666
2666
|
|
2667
2667
|
if (KindOfClass === AST_DefClass && !class_name) {
|
2668
|
-
|
2668
|
+
if (is_export_default) {
|
2669
|
+
KindOfClass = AST_ClassExpression;
|
2670
|
+
} else {
|
2671
|
+
unexpected();
|
2672
|
+
}
|
2669
2673
|
}
|
2670
2674
|
|
2671
2675
|
if (S.token.value == "extends") {
|
@@ -2698,9 +2702,9 @@ function parse($TEXT, options) {
|
|
2698
2702
|
}
|
2699
2703
|
|
2700
2704
|
function concise_method_or_getset(name, start, is_class) {
|
2701
|
-
|
2705
|
+
const get_symbol_ast = (name, SymbolClass = AST_SymbolMethod) => {
|
2702
2706
|
if (typeof name === "string" || typeof name === "number") {
|
2703
|
-
return new
|
2707
|
+
return new SymbolClass({
|
2704
2708
|
start,
|
2705
2709
|
name: "" + name,
|
2706
2710
|
end: prev()
|
@@ -2710,47 +2714,71 @@ function parse($TEXT, options) {
|
|
2710
2714
|
}
|
2711
2715
|
return name;
|
2712
2716
|
};
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
2716
|
-
|
2717
|
-
end: property_token,
|
2718
|
-
name: "" + name
|
2719
|
-
});
|
2720
|
-
} else if (name === null) {
|
2721
|
-
unexpected();
|
2722
|
-
}
|
2723
|
-
return name;
|
2724
|
-
};
|
2725
|
-
var privatename = start.type == "privatename";
|
2717
|
+
|
2718
|
+
const is_not_method_start = () =>
|
2719
|
+
!is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("operator", "=");
|
2720
|
+
|
2726
2721
|
var is_async = false;
|
2727
2722
|
var is_static = false;
|
2728
2723
|
var is_generator = false;
|
2729
|
-
var
|
2730
|
-
|
2724
|
+
var is_private = false;
|
2725
|
+
var accessor_type = null;
|
2726
|
+
|
2727
|
+
if (is_class && name === "static" && is_not_method_start()) {
|
2731
2728
|
is_static = true;
|
2732
|
-
property_token = S.token;
|
2733
|
-
privatename = property_token.type == "privatename";
|
2734
2729
|
name = as_property_name();
|
2735
2730
|
}
|
2736
|
-
if (name === "async" &&
|
2731
|
+
if (name === "async" && is_not_method_start()) {
|
2737
2732
|
is_async = true;
|
2738
|
-
property_token = S.token;
|
2739
|
-
privatename = property_token.type == "privatename";
|
2740
2733
|
name = as_property_name();
|
2741
2734
|
}
|
2742
|
-
if (
|
2735
|
+
if (prev().type === "operator" && prev().value === "*") {
|
2743
2736
|
is_generator = true;
|
2744
|
-
property_token = S.token;
|
2745
|
-
privatename = property_token.type == "privatename";
|
2746
2737
|
name = as_property_name();
|
2747
|
-
|
2748
|
-
|
2738
|
+
}
|
2739
|
+
if ((name === "get" || name === "set") && is_not_method_start()) {
|
2740
|
+
accessor_type = name;
|
2741
|
+
name = as_property_name();
|
2742
|
+
}
|
2743
|
+
if (prev().type === "privatename") {
|
2744
|
+
is_private = true;
|
2745
|
+
}
|
2746
|
+
|
2747
|
+
const property_token = prev();
|
2748
|
+
|
2749
|
+
if (accessor_type != null) {
|
2750
|
+
if (!is_private) {
|
2751
|
+
const AccessorClass = accessor_type === "get"
|
2752
|
+
? AST_ObjectGetter
|
2753
|
+
: AST_ObjectSetter;
|
2754
|
+
|
2755
|
+
name = get_symbol_ast(name);
|
2756
|
+
return new AccessorClass({
|
2757
|
+
start,
|
2758
|
+
static: is_static,
|
2759
|
+
key: name,
|
2760
|
+
quote: name instanceof AST_SymbolMethod ? property_token.quote : undefined,
|
2761
|
+
value: create_accessor(),
|
2762
|
+
end: prev()
|
2763
|
+
});
|
2764
|
+
} else {
|
2765
|
+
const AccessorClass = accessor_type === "get"
|
2766
|
+
? AST_PrivateGetter
|
2767
|
+
: AST_PrivateSetter;
|
2768
|
+
|
2769
|
+
return new AccessorClass({
|
2770
|
+
start,
|
2771
|
+
static: is_static,
|
2772
|
+
key: get_symbol_ast(name),
|
2773
|
+
value: create_accessor(),
|
2774
|
+
end: prev(),
|
2775
|
+
});
|
2749
2776
|
}
|
2750
2777
|
}
|
2778
|
+
|
2751
2779
|
if (is("punc", "(")) {
|
2752
|
-
name =
|
2753
|
-
const AST_MethodVariant =
|
2780
|
+
name = get_symbol_ast(name);
|
2781
|
+
const AST_MethodVariant = is_private
|
2754
2782
|
? AST_PrivateMethod
|
2755
2783
|
: AST_ConciseMethod;
|
2756
2784
|
var node = new AST_MethodVariant({
|
@@ -2766,57 +2794,13 @@ function parse($TEXT, options) {
|
|
2766
2794
|
});
|
2767
2795
|
return node;
|
2768
2796
|
}
|
2769
|
-
const setter_token = S.token;
|
2770
|
-
if ((name === "get" || name === "set") && setter_token.type === "privatename") {
|
2771
|
-
next();
|
2772
|
-
|
2773
|
-
const AST_AccessorVariant =
|
2774
|
-
name === "get"
|
2775
|
-
? AST_PrivateGetter
|
2776
|
-
: AST_PrivateSetter;
|
2777
|
-
|
2778
|
-
return new AST_AccessorVariant({
|
2779
|
-
start,
|
2780
|
-
static: is_static,
|
2781
|
-
key: get_method_name_ast(setter_token.value, start),
|
2782
|
-
value: create_accessor(),
|
2783
|
-
end: prev(),
|
2784
|
-
});
|
2785
|
-
}
|
2786
2797
|
|
2787
|
-
if (name == "get") {
|
2788
|
-
if (!is("punc") || is("punc", "[")) {
|
2789
|
-
name = get_method_name_ast(as_property_name(), start);
|
2790
|
-
return new AST_ObjectGetter({
|
2791
|
-
start : start,
|
2792
|
-
static: is_static,
|
2793
|
-
key : name,
|
2794
|
-
quote : name instanceof AST_SymbolMethod ?
|
2795
|
-
setter_token.quote : undefined,
|
2796
|
-
value : create_accessor(),
|
2797
|
-
end : prev()
|
2798
|
-
});
|
2799
|
-
}
|
2800
|
-
} else if (name == "set") {
|
2801
|
-
if (!is("punc") || is("punc", "[")) {
|
2802
|
-
name = get_method_name_ast(as_property_name(), start);
|
2803
|
-
return new AST_ObjectSetter({
|
2804
|
-
start : start,
|
2805
|
-
static: is_static,
|
2806
|
-
key : name,
|
2807
|
-
quote : name instanceof AST_SymbolMethod ?
|
2808
|
-
setter_token.quote : undefined,
|
2809
|
-
value : create_accessor(),
|
2810
|
-
end : prev()
|
2811
|
-
});
|
2812
|
-
}
|
2813
|
-
}
|
2814
2798
|
if (is_class) {
|
2815
|
-
const key =
|
2799
|
+
const key = get_symbol_ast(name, AST_SymbolClassProperty);
|
2816
2800
|
const quote = key instanceof AST_SymbolClassProperty
|
2817
2801
|
? property_token.quote
|
2818
2802
|
: undefined;
|
2819
|
-
const AST_ClassPropertyVariant =
|
2803
|
+
const AST_ClassPropertyVariant = is_private
|
2820
2804
|
? AST_ClassPrivateProperty
|
2821
2805
|
: AST_ClassProperty;
|
2822
2806
|
if (is("operator", "=")) {
|
@@ -3038,8 +3022,17 @@ function parse($TEXT, options) {
|
|
3038
3022
|
semicolon();
|
3039
3023
|
} else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
|
3040
3024
|
unexpected(node.start);
|
3041
|
-
} else if (
|
3025
|
+
} else if (
|
3026
|
+
node instanceof AST_Definitions
|
3027
|
+
|| node instanceof AST_Defun
|
3028
|
+
|| node instanceof AST_DefClass
|
3029
|
+
) {
|
3042
3030
|
exported_definition = node;
|
3031
|
+
} else if (
|
3032
|
+
node instanceof AST_ClassExpression
|
3033
|
+
|| node instanceof AST_Function
|
3034
|
+
) {
|
3035
|
+
exported_value = node;
|
3043
3036
|
} else if (node instanceof AST_SimpleStatement) {
|
3044
3037
|
exported_value = node.body;
|
3045
3038
|
} else {
|
@@ -4018,6 +4011,18 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator as
|
|
4018
4011
|
},
|
4019
4012
|
is_braceless() {
|
4020
4013
|
return this.body[0] instanceof AST_Return && this.body[0].value;
|
4014
|
+
},
|
4015
|
+
// Default args and expansion don't count, so .argnames.length doesn't cut it
|
4016
|
+
length_property() {
|
4017
|
+
let length = 0;
|
4018
|
+
|
4019
|
+
for (const arg of this.argnames) {
|
4020
|
+
if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
|
4021
|
+
length++;
|
4022
|
+
}
|
4023
|
+
}
|
4024
|
+
|
4025
|
+
return length;
|
4021
4026
|
}
|
4022
4027
|
}, AST_Scope);
|
4023
4028
|
|
@@ -10647,11 +10652,8 @@ const TOP = 0b0000010000000000;
|
|
10647
10652
|
|
10648
10653
|
const CLEAR_BETWEEN_PASSES = SQUEEZED | OPTIMIZED | TOP;
|
10649
10654
|
|
10650
|
-
/*@__INLINE__*/
|
10651
10655
|
const has_flag = (node, flag) => node.flags & flag;
|
10652
|
-
/*@__INLINE__*/
|
10653
10656
|
const set_flag = (node, flag) => { node.flags |= flag; };
|
10654
|
-
/*@__INLINE__*/
|
10655
10657
|
const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
10656
10658
|
|
10657
10659
|
class Compressor extends TreeWalker {
|
@@ -10694,7 +10696,7 @@ class Compressor extends TreeWalker {
|
|
10694
10696
|
properties : !false_by_default,
|
10695
10697
|
pure_getters : !false_by_default && "strict",
|
10696
10698
|
pure_funcs : null,
|
10697
|
-
reduce_funcs :
|
10699
|
+
reduce_funcs : !false_by_default,
|
10698
10700
|
reduce_vars : !false_by_default,
|
10699
10701
|
sequences : !false_by_default,
|
10700
10702
|
side_effects : !false_by_default,
|
@@ -10994,7 +10996,7 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
10994
10996
|
&& parent.expression === node
|
10995
10997
|
&& !(value instanceof AST_Arrow)
|
10996
10998
|
&& !(value instanceof AST_Class)
|
10997
|
-
&& !parent.
|
10999
|
+
&& !parent.is_callee_pure(compressor)
|
10998
11000
|
&& (!(value instanceof AST_Function)
|
10999
11001
|
|| !(parent instanceof AST_New) && value.contains_this())) {
|
11000
11002
|
return true;
|
@@ -11299,9 +11301,6 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
11299
11301
|
return true;
|
11300
11302
|
});
|
11301
11303
|
def_reduce_vars(AST_Call, function (tw) {
|
11302
|
-
// TODO this block should just be { return } but
|
11303
|
-
// for some reason the _walk function of AST_Call walks the callee last
|
11304
|
-
|
11305
11304
|
this.expression.walk(tw);
|
11306
11305
|
|
11307
11306
|
if (this.optional) {
|
@@ -13375,9 +13374,7 @@ var static_fns = convert_to_predicate({
|
|
13375
13374
|
if (compressor.option("unsafe")) {
|
13376
13375
|
var fn = function() {};
|
13377
13376
|
fn.node = this;
|
13378
|
-
fn.toString =
|
13379
|
-
return this.node.print_to_string();
|
13380
|
-
};
|
13377
|
+
fn.toString = () => this.print_to_string();
|
13381
13378
|
return fn;
|
13382
13379
|
}
|
13383
13380
|
return this;
|
@@ -13558,6 +13555,14 @@ var static_fns = convert_to_predicate({
|
|
13558
13555
|
"POSITIVE_INFINITY",
|
13559
13556
|
],
|
13560
13557
|
});
|
13558
|
+
const regexp_flags = new Set([
|
13559
|
+
"dotAll",
|
13560
|
+
"global",
|
13561
|
+
"ignoreCase",
|
13562
|
+
"multiline",
|
13563
|
+
"sticky",
|
13564
|
+
"unicode",
|
13565
|
+
]);
|
13561
13566
|
def_eval(AST_PropAccess, function(compressor, depth) {
|
13562
13567
|
if (this.optional) {
|
13563
13568
|
const obj = this.expression._eval(compressor, depth);
|
@@ -13590,12 +13595,19 @@ var static_fns = convert_to_predicate({
|
|
13590
13595
|
val = global_objs[exp.name];
|
13591
13596
|
} else {
|
13592
13597
|
val = exp._eval(compressor, depth + 1);
|
13598
|
+
if (val instanceof RegExp) {
|
13599
|
+
if (key == "source") {
|
13600
|
+
return regexp_source_fix(val.source);
|
13601
|
+
} else if (key == "flags" || regexp_flags.has(key)) {
|
13602
|
+
return val[key];
|
13603
|
+
}
|
13604
|
+
}
|
13593
13605
|
if (!val || val === exp || !HOP(val, key)) return this;
|
13594
13606
|
if (typeof val == "function") switch (key) {
|
13595
13607
|
case "name":
|
13596
13608
|
return val.node.name ? val.node.name.name : "";
|
13597
13609
|
case "length":
|
13598
|
-
return val.node.
|
13610
|
+
return val.node.length_property();
|
13599
13611
|
default:
|
13600
13612
|
return this;
|
13601
13613
|
}
|
@@ -13647,6 +13659,7 @@ var static_fns = convert_to_predicate({
|
|
13647
13659
|
var arg = this.args[i];
|
13648
13660
|
var value = arg._eval(compressor, depth);
|
13649
13661
|
if (arg === value) return this;
|
13662
|
+
if (arg instanceof AST_Lambda) return this;
|
13650
13663
|
args.push(value);
|
13651
13664
|
}
|
13652
13665
|
try {
|
@@ -13746,7 +13759,7 @@ var static_fns = convert_to_predicate({
|
|
13746
13759
|
});
|
13747
13760
|
|
13748
13761
|
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
|
13749
|
-
AST_Call.DEFMETHOD("
|
13762
|
+
AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
|
13750
13763
|
if (compressor.option("unsafe")) {
|
13751
13764
|
var expr = this.expression;
|
13752
13765
|
var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
|
@@ -13816,7 +13829,7 @@ const pure_prop_access_globals = new Set([
|
|
13816
13829
|
});
|
13817
13830
|
def_has_side_effects(AST_Call, function(compressor) {
|
13818
13831
|
if (
|
13819
|
-
!this.
|
13832
|
+
!this.is_callee_pure(compressor)
|
13820
13833
|
&& (!this.expression.is_call_pure(compressor)
|
13821
13834
|
|| this.expression.has_side_effects(compressor))
|
13822
13835
|
) {
|
@@ -13978,7 +13991,7 @@ const pure_prop_access_globals = new Set([
|
|
13978
13991
|
def_may_throw(AST_Call, function(compressor) {
|
13979
13992
|
if (this.optional && is_nullish(this.expression)) return false;
|
13980
13993
|
if (any(this.args, compressor)) return true;
|
13981
|
-
if (this.
|
13994
|
+
if (this.is_callee_pure(compressor)) return false;
|
13982
13995
|
if (this.expression.may_throw(compressor)) return true;
|
13983
13996
|
return !(this.expression instanceof AST_Lambda)
|
13984
13997
|
|| any(this.expression.body, compressor);
|
@@ -14856,7 +14869,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
14856
14869
|
return make_node(AST_Undefined, this);
|
14857
14870
|
}
|
14858
14871
|
|
14859
|
-
if (!this.
|
14872
|
+
if (!this.is_callee_pure(compressor)) {
|
14860
14873
|
if (this.expression.is_call_pure(compressor)) {
|
14861
14874
|
var exprs = this.args.slice();
|
14862
14875
|
exprs.unshift(this.expression.expression);
|
@@ -15876,7 +15889,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
15876
15889
|
|
15877
15890
|
var stat = is_func && fn.body[0];
|
15878
15891
|
var is_regular_func = is_func && !fn.is_generator && !fn.async;
|
15879
|
-
var can_inline = is_regular_func && compressor.option("inline") && !self.
|
15892
|
+
var can_inline = is_regular_func && compressor.option("inline") && !self.is_callee_pure(compressor);
|
15880
15893
|
if (can_inline && stat instanceof AST_Return) {
|
15881
15894
|
let returned = stat.value;
|
15882
15895
|
if (!returned || returned.is_constant_expression()) {
|
@@ -16902,19 +16915,26 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
16902
16915
|
let fixed = self.fixed_value();
|
16903
16916
|
let single_use = def.single_use
|
16904
16917
|
&& !(parent instanceof AST_Call
|
16905
|
-
&& (parent.
|
16918
|
+
&& (parent.is_callee_pure(compressor))
|
16906
16919
|
|| has_annotation(parent, _NOINLINE))
|
16907
16920
|
&& !(parent instanceof AST_Export
|
16908
16921
|
&& fixed instanceof AST_Lambda
|
16909
16922
|
&& fixed.name);
|
16910
16923
|
|
16924
|
+
if (single_use && fixed instanceof AST_Node) {
|
16925
|
+
single_use =
|
16926
|
+
!fixed.has_side_effects(compressor)
|
16927
|
+
&& !fixed.may_throw(compressor);
|
16928
|
+
}
|
16929
|
+
|
16911
16930
|
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
16912
16931
|
if (retain_top_func(fixed, compressor)) {
|
16913
16932
|
single_use = false;
|
16914
16933
|
} else if (def.scope !== self.scope
|
16915
16934
|
&& (def.escaped == 1
|
16916
16935
|
|| has_flag(fixed, INLINED)
|
16917
|
-
|| within_array_or_object_literal(compressor)
|
16936
|
+
|| within_array_or_object_literal(compressor)
|
16937
|
+
|| !compressor.option("reduce_funcs"))) {
|
16918
16938
|
single_use = false;
|
16919
16939
|
} else if (recursive_ref(compressor, def)) {
|
16920
16940
|
single_use = false;
|
@@ -16930,6 +16950,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
16930
16950
|
}
|
16931
16951
|
}
|
16932
16952
|
}
|
16953
|
+
|
16933
16954
|
if (single_use && fixed instanceof AST_Lambda) {
|
16934
16955
|
single_use =
|
16935
16956
|
def.scope === self.scope
|
@@ -16939,15 +16960,6 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
16939
16960
|
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
16940
16961
|
&& !(fixed.name && fixed.name.definition().recursive_refs > 0);
|
16941
16962
|
}
|
16942
|
-
if (single_use && fixed instanceof AST_Class) {
|
16943
|
-
const extends_inert = !fixed.extends
|
16944
|
-
|| !fixed.extends.may_throw(compressor)
|
16945
|
-
&& !fixed.extends.has_side_effects(compressor);
|
16946
|
-
single_use = extends_inert
|
16947
|
-
&& !fixed.properties.some(prop =>
|
16948
|
-
prop.may_throw(compressor) || prop.has_side_effects(compressor)
|
16949
|
-
);
|
16950
|
-
}
|
16951
16963
|
|
16952
16964
|
if (single_use && fixed) {
|
16953
16965
|
if (fixed instanceof AST_DefClass) {
|
@@ -17024,6 +17036,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
17024
17036
|
}
|
17025
17037
|
}
|
17026
17038
|
}
|
17039
|
+
|
17027
17040
|
return self;
|
17028
17041
|
});
|
17029
17042
|
|
@@ -17610,27 +17623,40 @@ function safe_to_flatten(value, compressor) {
|
|
17610
17623
|
|
17611
17624
|
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
17612
17625
|
if (!compressor.option("properties")) return;
|
17626
|
+
if (key === "__proto__") return;
|
17627
|
+
|
17613
17628
|
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
17614
17629
|
var expr = this.expression;
|
17615
17630
|
if (expr instanceof AST_Object) {
|
17616
17631
|
var props = expr.properties;
|
17632
|
+
|
17617
17633
|
for (var i = props.length; --i >= 0;) {
|
17618
17634
|
var prop = props[i];
|
17635
|
+
|
17619
17636
|
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
17620
|
-
|
17621
|
-
|
17622
|
-
|| arrows &&
|
17623
|
-
|
17624
|
-
|
17637
|
+
const all_props_flattenable = props.every((p) =>
|
17638
|
+
(p instanceof AST_ObjectKeyVal
|
17639
|
+
|| arrows && p instanceof AST_ConciseMethod && !p.is_generator
|
17640
|
+
)
|
17641
|
+
&& !p.computed_key()
|
17642
|
+
);
|
17643
|
+
|
17644
|
+
if (!all_props_flattenable) return;
|
17645
|
+
if (!safe_to_flatten(prop.value, compressor)) return;
|
17646
|
+
|
17625
17647
|
return make_node(AST_Sub, this, {
|
17626
17648
|
expression: make_node(AST_Array, expr, {
|
17627
17649
|
elements: props.map(function(prop) {
|
17628
17650
|
var v = prop.value;
|
17629
|
-
if (v instanceof AST_Accessor)
|
17651
|
+
if (v instanceof AST_Accessor) {
|
17652
|
+
v = make_node(AST_Function, v, v);
|
17653
|
+
}
|
17654
|
+
|
17630
17655
|
var k = prop.key;
|
17631
17656
|
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
17632
17657
|
return make_sequence(prop, [ k, v ]);
|
17633
17658
|
}
|
17659
|
+
|
17634
17660
|
return v;
|
17635
17661
|
})
|
17636
17662
|
}),
|
@@ -26430,6 +26456,7 @@ async function minify(files, options) {
|
|
26430
26456
|
rename: undefined,
|
26431
26457
|
safari10: false,
|
26432
26458
|
sourceMap: false,
|
26459
|
+
spidermonkey: false,
|
26433
26460
|
timings: false,
|
26434
26461
|
toplevel: false,
|
26435
26462
|
warnings: false,
|
@@ -26501,20 +26528,32 @@ async function minify(files, options) {
|
|
26501
26528
|
if (files instanceof AST_Toplevel) {
|
26502
26529
|
toplevel = files;
|
26503
26530
|
} else {
|
26504
|
-
if (typeof files == "string") {
|
26531
|
+
if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
|
26505
26532
|
files = [ files ];
|
26506
26533
|
}
|
26507
26534
|
options.parse = options.parse || {};
|
26508
26535
|
options.parse.toplevel = null;
|
26509
|
-
|
26510
|
-
|
26511
|
-
options.parse.toplevel =
|
26512
|
-
|
26513
|
-
|
26514
|
-
|
26515
|
-
|
26536
|
+
|
26537
|
+
if (options.parse.spidermonkey) {
|
26538
|
+
options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
|
26539
|
+
if (!toplevel) return files[name];
|
26540
|
+
toplevel.body = toplevel.body.concat(files[name].body);
|
26541
|
+
return toplevel;
|
26542
|
+
}, null));
|
26543
|
+
} else {
|
26544
|
+
delete options.parse.spidermonkey;
|
26545
|
+
|
26546
|
+
for (var name in files) if (HOP(files, name)) {
|
26547
|
+
options.parse.filename = name;
|
26548
|
+
options.parse.toplevel = parse(files[name], options.parse);
|
26549
|
+
if (options.sourceMap && options.sourceMap.content == "inline") {
|
26550
|
+
if (Object.keys(files).length > 1)
|
26551
|
+
throw new Error("inline source map only works with singular input");
|
26552
|
+
options.sourceMap.content = read_source_map(files[name]);
|
26553
|
+
}
|
26516
26554
|
}
|
26517
26555
|
}
|
26556
|
+
|
26518
26557
|
toplevel = options.parse.toplevel;
|
26519
26558
|
}
|
26520
26559
|
if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
|
@@ -26550,6 +26589,9 @@ async function minify(files, options) {
|
|
26550
26589
|
if (options.format.ast) {
|
26551
26590
|
result.ast = toplevel;
|
26552
26591
|
}
|
26592
|
+
if (options.format.spidermonkey) {
|
26593
|
+
result.ast = toplevel.to_mozilla_ast();
|
26594
|
+
}
|
26553
26595
|
if (!HOP(options.format, "code") || options.format.code) {
|
26554
26596
|
if (options.sourceMap) {
|
26555
26597
|
options.format.source_map = await SourceMap({
|
@@ -26567,6 +26609,7 @@ async function minify(files, options) {
|
|
26567
26609
|
}
|
26568
26610
|
delete options.format.ast;
|
26569
26611
|
delete options.format.code;
|
26612
|
+
delete options.format.spidermonkey;
|
26570
26613
|
var stream = OutputStream(options.format);
|
26571
26614
|
toplevel.print(stream);
|
26572
26615
|
result.code = stream.get();
|
package/lib/ast.js
CHANGED
@@ -524,6 +524,18 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator as
|
|
524
524
|
},
|
525
525
|
is_braceless() {
|
526
526
|
return this.body[0] instanceof AST_Return && this.body[0].value;
|
527
|
+
},
|
528
|
+
// Default args and expansion don't count, so .argnames.length doesn't cut it
|
529
|
+
length_property() {
|
530
|
+
let length = 0;
|
531
|
+
|
532
|
+
for (const arg of this.argnames) {
|
533
|
+
if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
|
534
|
+
length++;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
return length;
|
527
539
|
}
|
528
540
|
}, AST_Scope);
|
529
541
|
|
package/lib/compress/index.js
CHANGED
@@ -209,11 +209,8 @@ const TOP = 0b0000010000000000;
|
|
209
209
|
|
210
210
|
const CLEAR_BETWEEN_PASSES = SQUEEZED | OPTIMIZED | TOP;
|
211
211
|
|
212
|
-
/*@__INLINE__*/
|
213
212
|
const has_flag = (node, flag) => node.flags & flag;
|
214
|
-
/*@__INLINE__*/
|
215
213
|
const set_flag = (node, flag) => { node.flags |= flag; };
|
216
|
-
/*@__INLINE__*/
|
217
214
|
const clear_flag = (node, flag) => { node.flags &= ~flag; };
|
218
215
|
|
219
216
|
class Compressor extends TreeWalker {
|
@@ -256,7 +253,7 @@ class Compressor extends TreeWalker {
|
|
256
253
|
properties : !false_by_default,
|
257
254
|
pure_getters : !false_by_default && "strict",
|
258
255
|
pure_funcs : null,
|
259
|
-
reduce_funcs :
|
256
|
+
reduce_funcs : !false_by_default,
|
260
257
|
reduce_vars : !false_by_default,
|
261
258
|
sequences : !false_by_default,
|
262
259
|
side_effects : !false_by_default,
|
@@ -556,7 +553,7 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
556
553
|
&& parent.expression === node
|
557
554
|
&& !(value instanceof AST_Arrow)
|
558
555
|
&& !(value instanceof AST_Class)
|
559
|
-
&& !parent.
|
556
|
+
&& !parent.is_callee_pure(compressor)
|
560
557
|
&& (!(value instanceof AST_Function)
|
561
558
|
|| !(parent instanceof AST_New) && value.contains_this())) {
|
562
559
|
return true;
|
@@ -861,9 +858,6 @@ function is_modified(compressor, tw, node, value, level, immutable) {
|
|
861
858
|
return true;
|
862
859
|
});
|
863
860
|
def_reduce_vars(AST_Call, function (tw) {
|
864
|
-
// TODO this block should just be { return } but
|
865
|
-
// for some reason the _walk function of AST_Call walks the callee last
|
866
|
-
|
867
861
|
this.expression.walk(tw);
|
868
862
|
|
869
863
|
if (this.optional) {
|
@@ -2937,9 +2931,7 @@ var static_fns = convert_to_predicate({
|
|
2937
2931
|
if (compressor.option("unsafe")) {
|
2938
2932
|
var fn = function() {};
|
2939
2933
|
fn.node = this;
|
2940
|
-
fn.toString =
|
2941
|
-
return this.node.print_to_string();
|
2942
|
-
};
|
2934
|
+
fn.toString = () => this.print_to_string();
|
2943
2935
|
return fn;
|
2944
2936
|
}
|
2945
2937
|
return this;
|
@@ -3120,6 +3112,14 @@ var static_fns = convert_to_predicate({
|
|
3120
3112
|
"POSITIVE_INFINITY",
|
3121
3113
|
],
|
3122
3114
|
});
|
3115
|
+
const regexp_flags = new Set([
|
3116
|
+
"dotAll",
|
3117
|
+
"global",
|
3118
|
+
"ignoreCase",
|
3119
|
+
"multiline",
|
3120
|
+
"sticky",
|
3121
|
+
"unicode",
|
3122
|
+
]);
|
3123
3123
|
def_eval(AST_PropAccess, function(compressor, depth) {
|
3124
3124
|
if (this.optional) {
|
3125
3125
|
const obj = this.expression._eval(compressor, depth);
|
@@ -3152,12 +3152,19 @@ var static_fns = convert_to_predicate({
|
|
3152
3152
|
val = global_objs[exp.name];
|
3153
3153
|
} else {
|
3154
3154
|
val = exp._eval(compressor, depth + 1);
|
3155
|
+
if (val instanceof RegExp) {
|
3156
|
+
if (key == "source") {
|
3157
|
+
return regexp_source_fix(val.source);
|
3158
|
+
} else if (key == "flags" || regexp_flags.has(key)) {
|
3159
|
+
return val[key];
|
3160
|
+
}
|
3161
|
+
}
|
3155
3162
|
if (!val || val === exp || !HOP(val, key)) return this;
|
3156
3163
|
if (typeof val == "function") switch (key) {
|
3157
3164
|
case "name":
|
3158
3165
|
return val.node.name ? val.node.name.name : "";
|
3159
3166
|
case "length":
|
3160
|
-
return val.node.
|
3167
|
+
return val.node.length_property();
|
3161
3168
|
default:
|
3162
3169
|
return this;
|
3163
3170
|
}
|
@@ -3209,6 +3216,7 @@ var static_fns = convert_to_predicate({
|
|
3209
3216
|
var arg = this.args[i];
|
3210
3217
|
var value = arg._eval(compressor, depth);
|
3211
3218
|
if (arg === value) return this;
|
3219
|
+
if (arg instanceof AST_Lambda) return this;
|
3212
3220
|
args.push(value);
|
3213
3221
|
}
|
3214
3222
|
try {
|
@@ -3308,7 +3316,7 @@ var static_fns = convert_to_predicate({
|
|
3308
3316
|
});
|
3309
3317
|
|
3310
3318
|
var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
|
3311
|
-
AST_Call.DEFMETHOD("
|
3319
|
+
AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
|
3312
3320
|
if (compressor.option("unsafe")) {
|
3313
3321
|
var expr = this.expression;
|
3314
3322
|
var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
|
@@ -3378,7 +3386,7 @@ const pure_prop_access_globals = new Set([
|
|
3378
3386
|
});
|
3379
3387
|
def_has_side_effects(AST_Call, function(compressor) {
|
3380
3388
|
if (
|
3381
|
-
!this.
|
3389
|
+
!this.is_callee_pure(compressor)
|
3382
3390
|
&& (!this.expression.is_call_pure(compressor)
|
3383
3391
|
|| this.expression.has_side_effects(compressor))
|
3384
3392
|
) {
|
@@ -3540,7 +3548,7 @@ const pure_prop_access_globals = new Set([
|
|
3540
3548
|
def_may_throw(AST_Call, function(compressor) {
|
3541
3549
|
if (this.optional && is_nullish(this.expression)) return false;
|
3542
3550
|
if (any(this.args, compressor)) return true;
|
3543
|
-
if (this.
|
3551
|
+
if (this.is_callee_pure(compressor)) return false;
|
3544
3552
|
if (this.expression.may_throw(compressor)) return true;
|
3545
3553
|
return !(this.expression instanceof AST_Lambda)
|
3546
3554
|
|| any(this.expression.body, compressor);
|
@@ -4418,7 +4426,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4418
4426
|
return make_node(AST_Undefined, this);
|
4419
4427
|
}
|
4420
4428
|
|
4421
|
-
if (!this.
|
4429
|
+
if (!this.is_callee_pure(compressor)) {
|
4422
4430
|
if (this.expression.is_call_pure(compressor)) {
|
4423
4431
|
var exprs = this.args.slice();
|
4424
4432
|
exprs.unshift(this.expression.expression);
|
@@ -5438,7 +5446,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
5438
5446
|
|
5439
5447
|
var stat = is_func && fn.body[0];
|
5440
5448
|
var is_regular_func = is_func && !fn.is_generator && !fn.async;
|
5441
|
-
var can_inline = is_regular_func && compressor.option("inline") && !self.
|
5449
|
+
var can_inline = is_regular_func && compressor.option("inline") && !self.is_callee_pure(compressor);
|
5442
5450
|
if (can_inline && stat instanceof AST_Return) {
|
5443
5451
|
let returned = stat.value;
|
5444
5452
|
if (!returned || returned.is_constant_expression()) {
|
@@ -6464,19 +6472,26 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6464
6472
|
let fixed = self.fixed_value();
|
6465
6473
|
let single_use = def.single_use
|
6466
6474
|
&& !(parent instanceof AST_Call
|
6467
|
-
&& (parent.
|
6475
|
+
&& (parent.is_callee_pure(compressor))
|
6468
6476
|
|| has_annotation(parent, _NOINLINE))
|
6469
6477
|
&& !(parent instanceof AST_Export
|
6470
6478
|
&& fixed instanceof AST_Lambda
|
6471
6479
|
&& fixed.name);
|
6472
6480
|
|
6481
|
+
if (single_use && fixed instanceof AST_Node) {
|
6482
|
+
single_use =
|
6483
|
+
!fixed.has_side_effects(compressor)
|
6484
|
+
&& !fixed.may_throw(compressor);
|
6485
|
+
}
|
6486
|
+
|
6473
6487
|
if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
|
6474
6488
|
if (retain_top_func(fixed, compressor)) {
|
6475
6489
|
single_use = false;
|
6476
6490
|
} else if (def.scope !== self.scope
|
6477
6491
|
&& (def.escaped == 1
|
6478
6492
|
|| has_flag(fixed, INLINED)
|
6479
|
-
|| within_array_or_object_literal(compressor)
|
6493
|
+
|| within_array_or_object_literal(compressor)
|
6494
|
+
|| !compressor.option("reduce_funcs"))) {
|
6480
6495
|
single_use = false;
|
6481
6496
|
} else if (recursive_ref(compressor, def)) {
|
6482
6497
|
single_use = false;
|
@@ -6492,6 +6507,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6492
6507
|
}
|
6493
6508
|
}
|
6494
6509
|
}
|
6510
|
+
|
6495
6511
|
if (single_use && fixed instanceof AST_Lambda) {
|
6496
6512
|
single_use =
|
6497
6513
|
def.scope === self.scope
|
@@ -6501,15 +6517,6 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6501
6517
|
&& !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
|
6502
6518
|
&& !(fixed.name && fixed.name.definition().recursive_refs > 0);
|
6503
6519
|
}
|
6504
|
-
if (single_use && fixed instanceof AST_Class) {
|
6505
|
-
const extends_inert = !fixed.extends
|
6506
|
-
|| !fixed.extends.may_throw(compressor)
|
6507
|
-
&& !fixed.extends.has_side_effects(compressor);
|
6508
|
-
single_use = extends_inert
|
6509
|
-
&& !fixed.properties.some(prop =>
|
6510
|
-
prop.may_throw(compressor) || prop.has_side_effects(compressor)
|
6511
|
-
);
|
6512
|
-
}
|
6513
6520
|
|
6514
6521
|
if (single_use && fixed) {
|
6515
6522
|
if (fixed instanceof AST_DefClass) {
|
@@ -6586,6 +6593,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
|
|
6586
6593
|
}
|
6587
6594
|
}
|
6588
6595
|
}
|
6596
|
+
|
6589
6597
|
return self;
|
6590
6598
|
});
|
6591
6599
|
|
@@ -7172,27 +7180,40 @@ function safe_to_flatten(value, compressor) {
|
|
7172
7180
|
|
7173
7181
|
AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
|
7174
7182
|
if (!compressor.option("properties")) return;
|
7183
|
+
if (key === "__proto__") return;
|
7184
|
+
|
7175
7185
|
var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
|
7176
7186
|
var expr = this.expression;
|
7177
7187
|
if (expr instanceof AST_Object) {
|
7178
7188
|
var props = expr.properties;
|
7189
|
+
|
7179
7190
|
for (var i = props.length; --i >= 0;) {
|
7180
7191
|
var prop = props[i];
|
7192
|
+
|
7181
7193
|
if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
|
7182
|
-
|
7183
|
-
|
7184
|
-
|| arrows &&
|
7185
|
-
|
7186
|
-
|
7194
|
+
const all_props_flattenable = props.every((p) =>
|
7195
|
+
(p instanceof AST_ObjectKeyVal
|
7196
|
+
|| arrows && p instanceof AST_ConciseMethod && !p.is_generator
|
7197
|
+
)
|
7198
|
+
&& !p.computed_key()
|
7199
|
+
);
|
7200
|
+
|
7201
|
+
if (!all_props_flattenable) return;
|
7202
|
+
if (!safe_to_flatten(prop.value, compressor)) return;
|
7203
|
+
|
7187
7204
|
return make_node(AST_Sub, this, {
|
7188
7205
|
expression: make_node(AST_Array, expr, {
|
7189
7206
|
elements: props.map(function(prop) {
|
7190
7207
|
var v = prop.value;
|
7191
|
-
if (v instanceof AST_Accessor)
|
7208
|
+
if (v instanceof AST_Accessor) {
|
7209
|
+
v = make_node(AST_Function, v, v);
|
7210
|
+
}
|
7211
|
+
|
7192
7212
|
var k = prop.key;
|
7193
7213
|
if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
|
7194
7214
|
return make_sequence(prop, [ k, v ]);
|
7195
7215
|
}
|
7216
|
+
|
7196
7217
|
return v;
|
7197
7218
|
})
|
7198
7219
|
}),
|
package/lib/minify.js
CHANGED
@@ -7,7 +7,7 @@ import {
|
|
7
7
|
map_to_object,
|
8
8
|
HOP,
|
9
9
|
} from "./utils/index.js";
|
10
|
-
import { AST_Toplevel } from "./ast.js";
|
10
|
+
import { AST_Toplevel, AST_Node } from "./ast.js";
|
11
11
|
import { parse } from "./parse.js";
|
12
12
|
import { OutputStream } from "./output.js";
|
13
13
|
import { Compressor } from "./compress/index.js";
|
@@ -77,6 +77,7 @@ async function minify(files, options) {
|
|
77
77
|
rename: undefined,
|
78
78
|
safari10: false,
|
79
79
|
sourceMap: false,
|
80
|
+
spidermonkey: false,
|
80
81
|
timings: false,
|
81
82
|
toplevel: false,
|
82
83
|
warnings: false,
|
@@ -148,20 +149,32 @@ async function minify(files, options) {
|
|
148
149
|
if (files instanceof AST_Toplevel) {
|
149
150
|
toplevel = files;
|
150
151
|
} else {
|
151
|
-
if (typeof files == "string") {
|
152
|
+
if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
|
152
153
|
files = [ files ];
|
153
154
|
}
|
154
155
|
options.parse = options.parse || {};
|
155
156
|
options.parse.toplevel = null;
|
156
|
-
|
157
|
-
|
158
|
-
options.parse.toplevel =
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
157
|
+
|
158
|
+
if (options.parse.spidermonkey) {
|
159
|
+
options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
|
160
|
+
if (!toplevel) return files[name];
|
161
|
+
toplevel.body = toplevel.body.concat(files[name].body);
|
162
|
+
return toplevel;
|
163
|
+
}, null));
|
164
|
+
} else {
|
165
|
+
delete options.parse.spidermonkey;
|
166
|
+
|
167
|
+
for (var name in files) if (HOP(files, name)) {
|
168
|
+
options.parse.filename = name;
|
169
|
+
options.parse.toplevel = parse(files[name], options.parse);
|
170
|
+
if (options.sourceMap && options.sourceMap.content == "inline") {
|
171
|
+
if (Object.keys(files).length > 1)
|
172
|
+
throw new Error("inline source map only works with singular input");
|
173
|
+
options.sourceMap.content = read_source_map(files[name]);
|
174
|
+
}
|
163
175
|
}
|
164
176
|
}
|
177
|
+
|
165
178
|
toplevel = options.parse.toplevel;
|
166
179
|
}
|
167
180
|
if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
|
@@ -203,6 +216,9 @@ async function minify(files, options) {
|
|
203
216
|
if (options.format.ast) {
|
204
217
|
result.ast = toplevel;
|
205
218
|
}
|
219
|
+
if (options.format.spidermonkey) {
|
220
|
+
result.ast = toplevel.to_mozilla_ast();
|
221
|
+
}
|
206
222
|
if (!HOP(options.format, "code") || options.format.code) {
|
207
223
|
if (options.sourceMap) {
|
208
224
|
options.format.source_map = await SourceMap({
|
@@ -220,6 +236,7 @@ async function minify(files, options) {
|
|
220
236
|
}
|
221
237
|
delete options.format.ast;
|
222
238
|
delete options.format.code;
|
239
|
+
delete options.format.spidermonkey;
|
223
240
|
var stream = OutputStream(options.format);
|
224
241
|
toplevel.print(stream);
|
225
242
|
result.code = stream.get();
|
package/lib/parse.js
CHANGED
@@ -102,7 +102,6 @@ import {
|
|
102
102
|
AST_Label,
|
103
103
|
AST_LabeledStatement,
|
104
104
|
AST_LabelRef,
|
105
|
-
AST_Lambda,
|
106
105
|
AST_Let,
|
107
106
|
AST_NameMapping,
|
108
107
|
AST_New,
|
@@ -1293,7 +1292,7 @@ function parse($TEXT, options) {
|
|
1293
1292
|
if (is_if_body) {
|
1294
1293
|
croak("classes are not allowed as the body of an if");
|
1295
1294
|
}
|
1296
|
-
return class_(AST_DefClass);
|
1295
|
+
return class_(AST_DefClass, is_export_default);
|
1297
1296
|
|
1298
1297
|
case "function":
|
1299
1298
|
next();
|
@@ -2488,7 +2487,7 @@ function parse($TEXT, options) {
|
|
2488
2487
|
return new AST_Object({ properties: a });
|
2489
2488
|
});
|
2490
2489
|
|
2491
|
-
function class_(KindOfClass) {
|
2490
|
+
function class_(KindOfClass, is_export_default) {
|
2492
2491
|
var start, method, class_name, extends_, a = [];
|
2493
2492
|
|
2494
2493
|
S.input.push_directives_stack(); // Push directive stack, but not scope stack
|
@@ -2499,7 +2498,11 @@ function parse($TEXT, options) {
|
|
2499
2498
|
}
|
2500
2499
|
|
2501
2500
|
if (KindOfClass === AST_DefClass && !class_name) {
|
2502
|
-
|
2501
|
+
if (is_export_default) {
|
2502
|
+
KindOfClass = AST_ClassExpression;
|
2503
|
+
} else {
|
2504
|
+
unexpected();
|
2505
|
+
}
|
2503
2506
|
}
|
2504
2507
|
|
2505
2508
|
if (S.token.value == "extends") {
|
@@ -2532,9 +2535,9 @@ function parse($TEXT, options) {
|
|
2532
2535
|
}
|
2533
2536
|
|
2534
2537
|
function concise_method_or_getset(name, start, is_class) {
|
2535
|
-
|
2538
|
+
const get_symbol_ast = (name, SymbolClass = AST_SymbolMethod) => {
|
2536
2539
|
if (typeof name === "string" || typeof name === "number") {
|
2537
|
-
return new
|
2540
|
+
return new SymbolClass({
|
2538
2541
|
start,
|
2539
2542
|
name: "" + name,
|
2540
2543
|
end: prev()
|
@@ -2544,47 +2547,71 @@ function parse($TEXT, options) {
|
|
2544
2547
|
}
|
2545
2548
|
return name;
|
2546
2549
|
};
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
end: property_token,
|
2552
|
-
name: "" + name
|
2553
|
-
});
|
2554
|
-
} else if (name === null) {
|
2555
|
-
unexpected();
|
2556
|
-
}
|
2557
|
-
return name;
|
2558
|
-
};
|
2559
|
-
var privatename = start.type == "privatename";
|
2550
|
+
|
2551
|
+
const is_not_method_start = () =>
|
2552
|
+
!is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("operator", "=");
|
2553
|
+
|
2560
2554
|
var is_async = false;
|
2561
2555
|
var is_static = false;
|
2562
2556
|
var is_generator = false;
|
2563
|
-
var
|
2564
|
-
|
2557
|
+
var is_private = false;
|
2558
|
+
var accessor_type = null;
|
2559
|
+
|
2560
|
+
if (is_class && name === "static" && is_not_method_start()) {
|
2565
2561
|
is_static = true;
|
2566
|
-
property_token = S.token;
|
2567
|
-
privatename = property_token.type == "privatename";
|
2568
2562
|
name = as_property_name();
|
2569
2563
|
}
|
2570
|
-
if (name === "async" &&
|
2564
|
+
if (name === "async" && is_not_method_start()) {
|
2571
2565
|
is_async = true;
|
2572
|
-
property_token = S.token;
|
2573
|
-
privatename = property_token.type == "privatename";
|
2574
2566
|
name = as_property_name();
|
2575
2567
|
}
|
2576
|
-
if (
|
2568
|
+
if (prev().type === "operator" && prev().value === "*") {
|
2577
2569
|
is_generator = true;
|
2578
|
-
property_token = S.token;
|
2579
|
-
privatename = property_token.type == "privatename";
|
2580
2570
|
name = as_property_name();
|
2581
|
-
|
2582
|
-
|
2571
|
+
}
|
2572
|
+
if ((name === "get" || name === "set") && is_not_method_start()) {
|
2573
|
+
accessor_type = name;
|
2574
|
+
name = as_property_name();
|
2575
|
+
}
|
2576
|
+
if (prev().type === "privatename") {
|
2577
|
+
is_private = true;
|
2578
|
+
}
|
2579
|
+
|
2580
|
+
const property_token = prev();
|
2581
|
+
|
2582
|
+
if (accessor_type != null) {
|
2583
|
+
if (!is_private) {
|
2584
|
+
const AccessorClass = accessor_type === "get"
|
2585
|
+
? AST_ObjectGetter
|
2586
|
+
: AST_ObjectSetter;
|
2587
|
+
|
2588
|
+
name = get_symbol_ast(name);
|
2589
|
+
return new AccessorClass({
|
2590
|
+
start,
|
2591
|
+
static: is_static,
|
2592
|
+
key: name,
|
2593
|
+
quote: name instanceof AST_SymbolMethod ? property_token.quote : undefined,
|
2594
|
+
value: create_accessor(),
|
2595
|
+
end: prev()
|
2596
|
+
});
|
2597
|
+
} else {
|
2598
|
+
const AccessorClass = accessor_type === "get"
|
2599
|
+
? AST_PrivateGetter
|
2600
|
+
: AST_PrivateSetter;
|
2601
|
+
|
2602
|
+
return new AccessorClass({
|
2603
|
+
start,
|
2604
|
+
static: is_static,
|
2605
|
+
key: get_symbol_ast(name),
|
2606
|
+
value: create_accessor(),
|
2607
|
+
end: prev(),
|
2608
|
+
});
|
2583
2609
|
}
|
2584
2610
|
}
|
2611
|
+
|
2585
2612
|
if (is("punc", "(")) {
|
2586
|
-
name =
|
2587
|
-
const AST_MethodVariant =
|
2613
|
+
name = get_symbol_ast(name);
|
2614
|
+
const AST_MethodVariant = is_private
|
2588
2615
|
? AST_PrivateMethod
|
2589
2616
|
: AST_ConciseMethod;
|
2590
2617
|
var node = new AST_MethodVariant({
|
@@ -2600,57 +2627,13 @@ function parse($TEXT, options) {
|
|
2600
2627
|
});
|
2601
2628
|
return node;
|
2602
2629
|
}
|
2603
|
-
const setter_token = S.token;
|
2604
|
-
if ((name === "get" || name === "set") && setter_token.type === "privatename") {
|
2605
|
-
next();
|
2606
|
-
|
2607
|
-
const AST_AccessorVariant =
|
2608
|
-
name === "get"
|
2609
|
-
? AST_PrivateGetter
|
2610
|
-
: AST_PrivateSetter;
|
2611
|
-
|
2612
|
-
return new AST_AccessorVariant({
|
2613
|
-
start,
|
2614
|
-
static: is_static,
|
2615
|
-
key: get_method_name_ast(setter_token.value, start),
|
2616
|
-
value: create_accessor(),
|
2617
|
-
end: prev(),
|
2618
|
-
});
|
2619
|
-
}
|
2620
2630
|
|
2621
|
-
if (name == "get") {
|
2622
|
-
if (!is("punc") || is("punc", "[")) {
|
2623
|
-
name = get_method_name_ast(as_property_name(), start);
|
2624
|
-
return new AST_ObjectGetter({
|
2625
|
-
start : start,
|
2626
|
-
static: is_static,
|
2627
|
-
key : name,
|
2628
|
-
quote : name instanceof AST_SymbolMethod ?
|
2629
|
-
setter_token.quote : undefined,
|
2630
|
-
value : create_accessor(),
|
2631
|
-
end : prev()
|
2632
|
-
});
|
2633
|
-
}
|
2634
|
-
} else if (name == "set") {
|
2635
|
-
if (!is("punc") || is("punc", "[")) {
|
2636
|
-
name = get_method_name_ast(as_property_name(), start);
|
2637
|
-
return new AST_ObjectSetter({
|
2638
|
-
start : start,
|
2639
|
-
static: is_static,
|
2640
|
-
key : name,
|
2641
|
-
quote : name instanceof AST_SymbolMethod ?
|
2642
|
-
setter_token.quote : undefined,
|
2643
|
-
value : create_accessor(),
|
2644
|
-
end : prev()
|
2645
|
-
});
|
2646
|
-
}
|
2647
|
-
}
|
2648
2631
|
if (is_class) {
|
2649
|
-
const key =
|
2632
|
+
const key = get_symbol_ast(name, AST_SymbolClassProperty);
|
2650
2633
|
const quote = key instanceof AST_SymbolClassProperty
|
2651
2634
|
? property_token.quote
|
2652
2635
|
: undefined;
|
2653
|
-
const AST_ClassPropertyVariant =
|
2636
|
+
const AST_ClassPropertyVariant = is_private
|
2654
2637
|
? AST_ClassPrivateProperty
|
2655
2638
|
: AST_ClassProperty;
|
2656
2639
|
if (is("operator", "=")) {
|
@@ -2872,8 +2855,17 @@ function parse($TEXT, options) {
|
|
2872
2855
|
semicolon();
|
2873
2856
|
} else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
|
2874
2857
|
unexpected(node.start);
|
2875
|
-
} else if (
|
2858
|
+
} else if (
|
2859
|
+
node instanceof AST_Definitions
|
2860
|
+
|| node instanceof AST_Defun
|
2861
|
+
|| node instanceof AST_DefClass
|
2862
|
+
) {
|
2876
2863
|
exported_definition = node;
|
2864
|
+
} else if (
|
2865
|
+
node instanceof AST_ClassExpression
|
2866
|
+
|| node instanceof AST_Function
|
2867
|
+
) {
|
2868
|
+
exported_value = node;
|
2877
2869
|
} else if (node instanceof AST_SimpleStatement) {
|
2878
2870
|
exported_value = node.body;
|
2879
2871
|
} else {
|
package/lib/utils/index.js
CHANGED
package/package.json
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
"homepage": "https://terser.org",
|
5
5
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
6
6
|
"license": "BSD-2-Clause",
|
7
|
-
"version": "5.
|
7
|
+
"version": "5.7.0",
|
8
8
|
"engines": {
|
9
9
|
"node": ">=10"
|
10
10
|
},
|
@@ -24,7 +24,8 @@
|
|
24
24
|
"./dist/bundle.min.js"
|
25
25
|
],
|
26
26
|
"./package": "./package.json",
|
27
|
-
"./package.json": "./package.json"
|
27
|
+
"./package.json": "./package.json",
|
28
|
+
"./bin/terser": "./bin/terser"
|
28
29
|
},
|
29
30
|
"types": "tools/terser.d.ts",
|
30
31
|
"bin": {
|
@@ -124,7 +125,7 @@
|
|
124
125
|
"no-unused-vars": [
|
125
126
|
"error",
|
126
127
|
{
|
127
|
-
"varsIgnorePattern": "^_
|
128
|
+
"varsIgnorePattern": "^_"
|
128
129
|
}
|
129
130
|
],
|
130
131
|
"no-tabs": "error",
|