terser 5.7.0 → 5.7.1
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 +9 -0
- package/dist/bundle.min.js +54 -41
- package/lib/ast.js +0 -4
- package/lib/cli.js +0 -2
- package/lib/compress/index.js +35 -27
- package/lib/equivalent-to.js +5 -0
- package/lib/output.js +5 -1
- package/lib/scope.js +8 -3
- package/lib/utils/index.js +2 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.7.1
|
4
|
+
|
5
|
+
- Avoided collapsing assignments together if it would place a chain assignment on the left hand side, which is invalid syntax (`a?.b = c`)
|
6
|
+
- Removed undefined from object expansions (`{ ...void 0 }` -> `{}`)
|
7
|
+
- Fix crash when checking if something is nullish or undefined (#1009)
|
8
|
+
- Fixed comparison of private class properties (#1015)
|
9
|
+
- Minor performance improvements (#993)
|
10
|
+
- Fixed scope of function defs in strict mode (they are block scoped)
|
11
|
+
|
3
12
|
## v5.7.0
|
4
13
|
|
5
14
|
- Several compile-time evaluation and inlining fixes
|
package/dist/bundle.min.js
CHANGED
@@ -72,10 +72,8 @@ class DefaultsError extends Error {
|
|
72
72
|
function defaults(args, defs, croak) {
|
73
73
|
if (args === true) {
|
74
74
|
args = {};
|
75
|
-
}
|
76
|
-
|
77
|
-
if (args != null && typeof args === "object") {
|
78
|
-
args = Object.assign({}, args);
|
75
|
+
} else if (args != null && typeof args === "object") {
|
76
|
+
args = {...args};
|
79
77
|
}
|
80
78
|
|
81
79
|
const ret = args || {};
|
@@ -3701,8 +3699,6 @@ function walk_body(node, visitor) {
|
|
3701
3699
|
function clone_block_scope(deep) {
|
3702
3700
|
var clone = this._clone(deep);
|
3703
3701
|
if (this.block_scope) {
|
3704
|
-
// TODO this is sometimes undefined during compression.
|
3705
|
-
// But it should always have a value!
|
3706
3702
|
clone.block_scope = this.block_scope.clone();
|
3707
3703
|
}
|
3708
3704
|
return clone;
|
@@ -3886,7 +3882,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
|
3886
3882
|
$documentation: "Base class for all statements introducing a lexical scope",
|
3887
3883
|
$propdoc: {
|
3888
3884
|
variables: "[Map/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
3889
|
-
functions: "[Map/S] like `variables`, but only lists function declarations",
|
3890
3885
|
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
3891
3886
|
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
3892
3887
|
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
@@ -3909,7 +3904,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
|
3909
3904
|
});
|
3910
3905
|
} else {
|
3911
3906
|
if (this.variables) node.variables = new Map(this.variables);
|
3912
|
-
if (this.functions) node.functions = new Map(this.functions);
|
3913
3907
|
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
3914
3908
|
if (this._block_scope) node._block_scope = this._block_scope;
|
3915
3909
|
}
|
@@ -7097,11 +7091,15 @@ function OutputStream(options) {
|
|
7097
7091
|
var do_add_mapping = mappings ? function() {
|
7098
7092
|
mappings.forEach(function(mapping) {
|
7099
7093
|
try {
|
7094
|
+
let name = !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name;
|
7095
|
+
if (name instanceof AST_Symbol) {
|
7096
|
+
name = name.name;
|
7097
|
+
}
|
7100
7098
|
options.source_map.add(
|
7101
7099
|
mapping.token.file,
|
7102
7100
|
mapping.line, mapping.col,
|
7103
7101
|
mapping.token.line, mapping.token.col,
|
7104
|
-
|
7102
|
+
is_basic_identifier_string(name) ? name : undefined
|
7105
7103
|
);
|
7106
7104
|
} catch(ex) {
|
7107
7105
|
// Ignore bad mapping
|
@@ -9196,6 +9194,10 @@ AST_Dot.prototype.shallow_cmp = mkshallow({
|
|
9196
9194
|
property: "eq"
|
9197
9195
|
});
|
9198
9196
|
|
9197
|
+
AST_DotHash.prototype.shallow_cmp = mkshallow({
|
9198
|
+
property: "eq"
|
9199
|
+
});
|
9200
|
+
|
9199
9201
|
AST_Unary.prototype.shallow_cmp = mkshallow({
|
9200
9202
|
operator: "eq"
|
9201
9203
|
});
|
@@ -9501,7 +9503,14 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
9501
9503
|
// scope when we encounter the AST_Defun node (which is
|
9502
9504
|
// instanceof AST_Scope) but we get to the symbol a bit
|
9503
9505
|
// later.
|
9504
|
-
|
9506
|
+
const closest_scope = defun.parent_scope;
|
9507
|
+
|
9508
|
+
// In strict mode, function definitions are block-scoped
|
9509
|
+
node.scope = tw.directives["use strict"]
|
9510
|
+
? closest_scope
|
9511
|
+
: closest_scope.get_defun_scope();
|
9512
|
+
|
9513
|
+
mark_export(node.scope.def_function(node, defun), 1);
|
9505
9514
|
} else if (node instanceof AST_SymbolClass) {
|
9506
9515
|
mark_export(defun.def_variable(node, defun), 1);
|
9507
9516
|
} else if (node instanceof AST_SymbolImport) {
|
@@ -9680,7 +9689,6 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
|
9680
9689
|
|
9681
9690
|
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
9682
9691
|
this.variables = new Map(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
9683
|
-
this.functions = new Map(); // map name to AST_SymbolDefun (functions defined in this scope)
|
9684
9692
|
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
9685
9693
|
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
9686
9694
|
this.parent_scope = parent_scope; // the parent scope
|
@@ -9843,7 +9851,6 @@ AST_Scope.DEFMETHOD("find_variable", function(name) {
|
|
9843
9851
|
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
|
9844
9852
|
var def = this.def_variable(symbol, init);
|
9845
9853
|
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
9846
|
-
this.functions.set(symbol.name, def);
|
9847
9854
|
return def;
|
9848
9855
|
});
|
9849
9856
|
|
@@ -11951,6 +11958,7 @@ function tighten_body(statements, compressor) {
|
|
11951
11958
|
if (stop_after === node) abort = true;
|
11952
11959
|
if (stop_if_hit === node) stop_if_hit = null;
|
11953
11960
|
});
|
11961
|
+
|
11954
11962
|
var multi_replacer = new TreeTransformer(function(node) {
|
11955
11963
|
if (abort) return node;
|
11956
11964
|
// Skip nodes before `candidate` as quickly as possible
|
@@ -11973,6 +11981,7 @@ function tighten_body(statements, compressor) {
|
|
11973
11981
|
// Skip (non-executed) functions and (leading) default case in switch statements
|
11974
11982
|
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
11975
11983
|
});
|
11984
|
+
|
11976
11985
|
while (--stat_index >= 0) {
|
11977
11986
|
// Treat parameters as collapsible in IIFE, i.e.
|
11978
11987
|
// function(a, b){ ... }(x());
|
@@ -12148,7 +12157,10 @@ function tighten_body(statements, compressor) {
|
|
12148
12157
|
function extract_candidates(expr) {
|
12149
12158
|
hit_stack.push(expr);
|
12150
12159
|
if (expr instanceof AST_Assign) {
|
12151
|
-
if (
|
12160
|
+
if (
|
12161
|
+
!expr.left.has_side_effects(compressor)
|
12162
|
+
&& !(expr.right instanceof AST_Chain)
|
12163
|
+
) {
|
12152
12164
|
candidates.push(hit_stack.slice());
|
12153
12165
|
}
|
12154
12166
|
extract_candidates(expr.right);
|
@@ -12211,7 +12223,7 @@ function tighten_body(statements, compressor) {
|
|
12211
12223
|
candidates.push(hit_stack.slice());
|
12212
12224
|
}
|
12213
12225
|
} else if (expr instanceof AST_VarDef) {
|
12214
|
-
if (expr.value) {
|
12226
|
+
if (expr.value && !(expr.value instanceof AST_Chain)) {
|
12215
12227
|
candidates.push(hit_stack.slice());
|
12216
12228
|
extract_candidates(expr.value);
|
12217
12229
|
}
|
@@ -13919,7 +13931,7 @@ const pure_prop_access_globals = new Set([
|
|
13919
13931
|
|| this.expression.has_side_effects(compressor);
|
13920
13932
|
});
|
13921
13933
|
def_has_side_effects(AST_Sub, function(compressor) {
|
13922
|
-
if (this.optional && is_nullish(this.expression)) {
|
13934
|
+
if (this.optional && is_nullish(this.expression, compressor)) {
|
13923
13935
|
return false;
|
13924
13936
|
}
|
13925
13937
|
|
@@ -13989,7 +14001,7 @@ const pure_prop_access_globals = new Set([
|
|
13989
14001
|
return any(this.body, compressor);
|
13990
14002
|
});
|
13991
14003
|
def_may_throw(AST_Call, function(compressor) {
|
13992
|
-
if (this.optional && is_nullish(this.expression)) return false;
|
14004
|
+
if (this.optional && is_nullish(this.expression, compressor)) return false;
|
13993
14005
|
if (any(this.args, compressor)) return true;
|
13994
14006
|
if (this.is_callee_pure(compressor)) return false;
|
13995
14007
|
if (this.expression.may_throw(compressor)) return true;
|
@@ -14052,7 +14064,7 @@ const pure_prop_access_globals = new Set([
|
|
14052
14064
|
|| this.expression.may_throw(compressor);
|
14053
14065
|
});
|
14054
14066
|
def_may_throw(AST_Sub, function(compressor) {
|
14055
|
-
if (this.optional && is_nullish(this.expression)) return false;
|
14067
|
+
if (this.optional && is_nullish(this.expression, compressor)) return false;
|
14056
14068
|
|
14057
14069
|
return !this.optional && this.expression.may_throw_on_access(compressor)
|
14058
14070
|
|| this.expression.may_throw(compressor)
|
@@ -14865,7 +14877,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
14865
14877
|
def_drop_side_effect_free(AST_Constant, return_null);
|
14866
14878
|
def_drop_side_effect_free(AST_This, return_null);
|
14867
14879
|
def_drop_side_effect_free(AST_Call, function(compressor, first_in_statement) {
|
14868
|
-
if (this.optional && is_nullish(this.expression)) {
|
14880
|
+
if (this.optional && is_nullish(this.expression, compressor)) {
|
14869
14881
|
return make_node(AST_Undefined, this);
|
14870
14882
|
}
|
14871
14883
|
|
@@ -15012,7 +15024,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
15012
15024
|
});
|
15013
15025
|
def_drop_side_effect_free(AST_Dot, function(compressor, first_in_statement) {
|
15014
15026
|
if (this.optional) {
|
15015
|
-
return is_nullish(this.expression) ? make_node(AST_Undefined, this) : this;
|
15027
|
+
return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this) : this;
|
15016
15028
|
}
|
15017
15029
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
15018
15030
|
|
@@ -15020,7 +15032,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
15020
15032
|
});
|
15021
15033
|
def_drop_side_effect_free(AST_Sub, function(compressor, first_in_statement) {
|
15022
15034
|
if (this.optional) {
|
15023
|
-
return is_nullish(this.expression) ? make_node(AST_Undefined, this): this;
|
15035
|
+
return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this): this;
|
15024
15036
|
}
|
15025
15037
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
15026
15038
|
|
@@ -15545,11 +15557,11 @@ def_optimize(AST_Definitions, function(self) {
|
|
15545
15557
|
return self;
|
15546
15558
|
});
|
15547
15559
|
|
15548
|
-
def_optimize(AST_VarDef, function(self) {
|
15560
|
+
def_optimize(AST_VarDef, function(self, compressor) {
|
15549
15561
|
if (
|
15550
15562
|
self.name instanceof AST_SymbolLet
|
15551
15563
|
&& self.value != null
|
15552
|
-
&& is_undefined(self.value)
|
15564
|
+
&& is_undefined(self.value, compressor)
|
15553
15565
|
) {
|
15554
15566
|
self.value = null;
|
15555
15567
|
}
|
@@ -15587,7 +15599,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
15587
15599
|
}
|
15588
15600
|
}
|
15589
15601
|
|
15590
|
-
if (self.optional && is_nullish(fn)) {
|
15602
|
+
if (self.optional && is_nullish(fn, compressor)) {
|
15591
15603
|
return make_node(AST_Undefined, self);
|
15592
15604
|
}
|
15593
15605
|
|
@@ -16613,7 +16625,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
16613
16625
|
}
|
16614
16626
|
break;
|
16615
16627
|
case "??":
|
16616
|
-
if (is_nullish(self.left)) {
|
16628
|
+
if (is_nullish(self.left, compressor)) {
|
16617
16629
|
return self.right;
|
16618
16630
|
}
|
16619
16631
|
|
@@ -17221,20 +17233,20 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
|
|
17221
17233
|
return self;
|
17222
17234
|
});
|
17223
17235
|
|
17224
|
-
function is_nullish(node) {
|
17236
|
+
function is_nullish(node, compressor) {
|
17225
17237
|
let fixed;
|
17226
17238
|
return (
|
17227
17239
|
node instanceof AST_Null
|
17228
|
-
|| is_undefined(node)
|
17240
|
+
|| is_undefined(node, compressor)
|
17229
17241
|
|| (
|
17230
17242
|
node instanceof AST_SymbolRef
|
17231
17243
|
&& (fixed = node.definition().fixed) instanceof AST_Node
|
17232
|
-
&& is_nullish(fixed)
|
17244
|
+
&& is_nullish(fixed, compressor)
|
17233
17245
|
)
|
17234
17246
|
// Recurse into those optional chains!
|
17235
|
-
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression)
|
17236
|
-
|| node instanceof AST_Call && node.optional && is_nullish(node.expression)
|
17237
|
-
|| node instanceof AST_Chain && is_nullish(node.expression)
|
17247
|
+
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression, compressor)
|
17248
|
+
|| node instanceof AST_Call && node.optional && is_nullish(node.expression, compressor)
|
17249
|
+
|| node instanceof AST_Chain && is_nullish(node.expression, compressor)
|
17238
17250
|
);
|
17239
17251
|
}
|
17240
17252
|
|
@@ -17249,8 +17261,8 @@ function is_nullish_check(check, check_subject, compressor) {
|
|
17249
17261
|
&& check.operator === "=="
|
17250
17262
|
// which side is nullish?
|
17251
17263
|
&& (
|
17252
|
-
(nullish_side = is_nullish(check.left) && check.left)
|
17253
|
-
|| (nullish_side = is_nullish(check.right) && check.right)
|
17264
|
+
(nullish_side = is_nullish(check.left, compressor) && check.left)
|
17265
|
+
|| (nullish_side = is_nullish(check.right, compressor) && check.right)
|
17254
17266
|
)
|
17255
17267
|
// is the other side the same as the check_subject
|
17256
17268
|
&& (
|
@@ -17288,12 +17300,12 @@ function is_nullish_check(check, check_subject, compressor) {
|
|
17288
17300
|
null_cmp = cmp;
|
17289
17301
|
defined_side = cmp.left;
|
17290
17302
|
}
|
17291
|
-
if (is_undefined(cmp.left)) {
|
17303
|
+
if (is_undefined(cmp.left, compressor)) {
|
17292
17304
|
found++;
|
17293
17305
|
undefined_cmp = cmp;
|
17294
17306
|
defined_side = cmp.right;
|
17295
17307
|
}
|
17296
|
-
if (is_undefined(cmp.right)) {
|
17308
|
+
if (is_undefined(cmp.right, compressor)) {
|
17297
17309
|
found++;
|
17298
17310
|
undefined_cmp = cmp;
|
17299
17311
|
defined_side = cmp.left;
|
@@ -17794,7 +17806,7 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
17794
17806
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
17795
17807
|
return best_of(compressor, ev, self);
|
17796
17808
|
}
|
17797
|
-
if (self.optional && is_nullish(self.expression)) {
|
17809
|
+
if (self.optional && is_nullish(self.expression, compressor)) {
|
17798
17810
|
return make_node(AST_Undefined, self);
|
17799
17811
|
}
|
17800
17812
|
return self;
|
@@ -17868,7 +17880,7 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
17868
17880
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
17869
17881
|
return best_of(compressor, ev, self);
|
17870
17882
|
}
|
17871
|
-
if (self.optional && is_nullish(self.expression)) {
|
17883
|
+
if (self.optional && is_nullish(self.expression, compressor)) {
|
17872
17884
|
return make_node(AST_Undefined, self);
|
17873
17885
|
}
|
17874
17886
|
return self;
|
@@ -17912,7 +17924,7 @@ def_optimize(AST_Array, function(self, compressor) {
|
|
17912
17924
|
return self;
|
17913
17925
|
});
|
17914
17926
|
|
17915
|
-
function inline_object_prop_spread(props) {
|
17927
|
+
function inline_object_prop_spread(props, compressor) {
|
17916
17928
|
for (var i = 0; i < props.length; i++) {
|
17917
17929
|
var prop = props[i];
|
17918
17930
|
if (prop instanceof AST_Expansion) {
|
@@ -17930,6 +17942,9 @@ function inline_object_prop_spread(props) {
|
|
17930
17942
|
// non-iterable value silently does nothing; it is thus safe
|
17931
17943
|
// to remove. AST_String is the only iterable AST_Constant.
|
17932
17944
|
props.splice(i, 1);
|
17945
|
+
} else if (is_nullish(expr, compressor)) {
|
17946
|
+
// Likewise, null and undefined can be silently removed.
|
17947
|
+
props.splice(i, 1);
|
17933
17948
|
}
|
17934
17949
|
}
|
17935
17950
|
}
|
@@ -17940,7 +17955,7 @@ def_optimize(AST_Object, function(self, compressor) {
|
|
17940
17955
|
if (optimized !== self) {
|
17941
17956
|
return optimized;
|
17942
17957
|
}
|
17943
|
-
inline_object_prop_spread(self.properties);
|
17958
|
+
inline_object_prop_spread(self.properties, compressor);
|
17944
17959
|
return self;
|
17945
17960
|
});
|
17946
17961
|
|
@@ -18033,7 +18048,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
18033
18048
|
&& (
|
18034
18049
|
segments[1].is_string(compressor)
|
18035
18050
|
|| segments[1].is_number(compressor)
|
18036
|
-
|| is_nullish(segments[1])
|
18051
|
+
|| is_nullish(segments[1], compressor)
|
18037
18052
|
|| compressor.option("unsafe")
|
18038
18053
|
)
|
18039
18054
|
) {
|
@@ -26902,7 +26917,6 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
26902
26917
|
case "enclosed":
|
26903
26918
|
return value.length ? value.map(symdef) : undefined;
|
26904
26919
|
case "variables":
|
26905
|
-
case "functions":
|
26906
26920
|
case "globals":
|
26907
26921
|
return value.size ? collect_from_map(value, symdef) : undefined;
|
26908
26922
|
}
|
@@ -26915,7 +26929,6 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
26915
26929
|
};
|
26916
26930
|
if (value.block_scope) {
|
26917
26931
|
result.variables = value.block_scope.variables;
|
26918
|
-
result.functions = value.block_scope.functions;
|
26919
26932
|
result.enclosed = value.block_scope.enclosed;
|
26920
26933
|
}
|
26921
26934
|
value.CTOR.PROPS.forEach(function(prop) {
|
package/lib/ast.js
CHANGED
@@ -214,8 +214,6 @@ function walk_body(node, visitor) {
|
|
214
214
|
function clone_block_scope(deep) {
|
215
215
|
var clone = this._clone(deep);
|
216
216
|
if (this.block_scope) {
|
217
|
-
// TODO this is sometimes undefined during compression.
|
218
|
-
// But it should always have a value!
|
219
217
|
clone.block_scope = this.block_scope.clone();
|
220
218
|
}
|
221
219
|
return clone;
|
@@ -399,7 +397,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
|
399
397
|
$documentation: "Base class for all statements introducing a lexical scope",
|
400
398
|
$propdoc: {
|
401
399
|
variables: "[Map/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
402
|
-
functions: "[Map/S] like `variables`, but only lists function declarations",
|
403
400
|
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
404
401
|
uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
|
405
402
|
parent_scope: "[AST_Scope?/S] link to the parent scope",
|
@@ -422,7 +419,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
|
422
419
|
});
|
423
420
|
} else {
|
424
421
|
if (this.variables) node.variables = new Map(this.variables);
|
425
|
-
if (this.functions) node.functions = new Map(this.functions);
|
426
422
|
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
427
423
|
if (this._block_scope) node._block_scope = this._block_scope;
|
428
424
|
}
|
package/lib/cli.js
CHANGED
@@ -264,7 +264,6 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
264
264
|
case "enclosed":
|
265
265
|
return value.length ? value.map(symdef) : undefined;
|
266
266
|
case "variables":
|
267
|
-
case "functions":
|
268
267
|
case "globals":
|
269
268
|
return value.size ? collect_from_map(value, symdef) : undefined;
|
270
269
|
}
|
@@ -277,7 +276,6 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
277
276
|
};
|
278
277
|
if (value.block_scope) {
|
279
278
|
result.variables = value.block_scope.variables;
|
280
|
-
result.functions = value.block_scope.functions;
|
281
279
|
result.enclosed = value.block_scope.enclosed;
|
282
280
|
}
|
283
281
|
value.CTOR.PROPS.forEach(function(prop) {
|
package/lib/compress/index.js
CHANGED
@@ -1508,6 +1508,7 @@ function tighten_body(statements, compressor) {
|
|
1508
1508
|
if (stop_after === node) abort = true;
|
1509
1509
|
if (stop_if_hit === node) stop_if_hit = null;
|
1510
1510
|
});
|
1511
|
+
|
1511
1512
|
var multi_replacer = new TreeTransformer(function(node) {
|
1512
1513
|
if (abort) return node;
|
1513
1514
|
// Skip nodes before `candidate` as quickly as possible
|
@@ -1530,6 +1531,7 @@ function tighten_body(statements, compressor) {
|
|
1530
1531
|
// Skip (non-executed) functions and (leading) default case in switch statements
|
1531
1532
|
if (node instanceof AST_Default || node instanceof AST_Scope) return node;
|
1532
1533
|
});
|
1534
|
+
|
1533
1535
|
while (--stat_index >= 0) {
|
1534
1536
|
// Treat parameters as collapsible in IIFE, i.e.
|
1535
1537
|
// function(a, b){ ... }(x());
|
@@ -1705,7 +1707,10 @@ function tighten_body(statements, compressor) {
|
|
1705
1707
|
function extract_candidates(expr) {
|
1706
1708
|
hit_stack.push(expr);
|
1707
1709
|
if (expr instanceof AST_Assign) {
|
1708
|
-
if (
|
1710
|
+
if (
|
1711
|
+
!expr.left.has_side_effects(compressor)
|
1712
|
+
&& !(expr.right instanceof AST_Chain)
|
1713
|
+
) {
|
1709
1714
|
candidates.push(hit_stack.slice());
|
1710
1715
|
}
|
1711
1716
|
extract_candidates(expr.right);
|
@@ -1768,7 +1773,7 @@ function tighten_body(statements, compressor) {
|
|
1768
1773
|
candidates.push(hit_stack.slice());
|
1769
1774
|
}
|
1770
1775
|
} else if (expr instanceof AST_VarDef) {
|
1771
|
-
if (expr.value) {
|
1776
|
+
if (expr.value && !(expr.value instanceof AST_Chain)) {
|
1772
1777
|
candidates.push(hit_stack.slice());
|
1773
1778
|
extract_candidates(expr.value);
|
1774
1779
|
}
|
@@ -3476,7 +3481,7 @@ const pure_prop_access_globals = new Set([
|
|
3476
3481
|
|| this.expression.has_side_effects(compressor);
|
3477
3482
|
});
|
3478
3483
|
def_has_side_effects(AST_Sub, function(compressor) {
|
3479
|
-
if (this.optional && is_nullish(this.expression)) {
|
3484
|
+
if (this.optional && is_nullish(this.expression, compressor)) {
|
3480
3485
|
return false;
|
3481
3486
|
}
|
3482
3487
|
|
@@ -3546,7 +3551,7 @@ const pure_prop_access_globals = new Set([
|
|
3546
3551
|
return any(this.body, compressor);
|
3547
3552
|
});
|
3548
3553
|
def_may_throw(AST_Call, function(compressor) {
|
3549
|
-
if (this.optional && is_nullish(this.expression)) return false;
|
3554
|
+
if (this.optional && is_nullish(this.expression, compressor)) return false;
|
3550
3555
|
if (any(this.args, compressor)) return true;
|
3551
3556
|
if (this.is_callee_pure(compressor)) return false;
|
3552
3557
|
if (this.expression.may_throw(compressor)) return true;
|
@@ -3609,7 +3614,7 @@ const pure_prop_access_globals = new Set([
|
|
3609
3614
|
|| this.expression.may_throw(compressor);
|
3610
3615
|
});
|
3611
3616
|
def_may_throw(AST_Sub, function(compressor) {
|
3612
|
-
if (this.optional && is_nullish(this.expression)) return false;
|
3617
|
+
if (this.optional && is_nullish(this.expression, compressor)) return false;
|
3613
3618
|
|
3614
3619
|
return !this.optional && this.expression.may_throw_on_access(compressor)
|
3615
3620
|
|| this.expression.may_throw(compressor)
|
@@ -4422,7 +4427,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4422
4427
|
def_drop_side_effect_free(AST_Constant, return_null);
|
4423
4428
|
def_drop_side_effect_free(AST_This, return_null);
|
4424
4429
|
def_drop_side_effect_free(AST_Call, function(compressor, first_in_statement) {
|
4425
|
-
if (this.optional && is_nullish(this.expression)) {
|
4430
|
+
if (this.optional && is_nullish(this.expression, compressor)) {
|
4426
4431
|
return make_node(AST_Undefined, this);
|
4427
4432
|
}
|
4428
4433
|
|
@@ -4569,7 +4574,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4569
4574
|
});
|
4570
4575
|
def_drop_side_effect_free(AST_Dot, function(compressor, first_in_statement) {
|
4571
4576
|
if (this.optional) {
|
4572
|
-
return is_nullish(this.expression) ? make_node(AST_Undefined, this) : this;
|
4577
|
+
return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this) : this;
|
4573
4578
|
}
|
4574
4579
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
4575
4580
|
|
@@ -4577,7 +4582,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
|
|
4577
4582
|
});
|
4578
4583
|
def_drop_side_effect_free(AST_Sub, function(compressor, first_in_statement) {
|
4579
4584
|
if (this.optional) {
|
4580
|
-
return is_nullish(this.expression) ? make_node(AST_Undefined, this): this;
|
4585
|
+
return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this): this;
|
4581
4586
|
}
|
4582
4587
|
if (this.expression.may_throw_on_access(compressor)) return this;
|
4583
4588
|
|
@@ -5102,11 +5107,11 @@ def_optimize(AST_Definitions, function(self) {
|
|
5102
5107
|
return self;
|
5103
5108
|
});
|
5104
5109
|
|
5105
|
-
def_optimize(AST_VarDef, function(self) {
|
5110
|
+
def_optimize(AST_VarDef, function(self, compressor) {
|
5106
5111
|
if (
|
5107
5112
|
self.name instanceof AST_SymbolLet
|
5108
5113
|
&& self.value != null
|
5109
|
-
&& is_undefined(self.value)
|
5114
|
+
&& is_undefined(self.value, compressor)
|
5110
5115
|
) {
|
5111
5116
|
self.value = null;
|
5112
5117
|
}
|
@@ -5144,7 +5149,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
5144
5149
|
}
|
5145
5150
|
}
|
5146
5151
|
|
5147
|
-
if (self.optional && is_nullish(fn)) {
|
5152
|
+
if (self.optional && is_nullish(fn, compressor)) {
|
5148
5153
|
return make_node(AST_Undefined, self);
|
5149
5154
|
}
|
5150
5155
|
|
@@ -6170,7 +6175,7 @@ def_optimize(AST_Binary, function(self, compressor) {
|
|
6170
6175
|
}
|
6171
6176
|
break;
|
6172
6177
|
case "??":
|
6173
|
-
if (is_nullish(self.left)) {
|
6178
|
+
if (is_nullish(self.left, compressor)) {
|
6174
6179
|
return self.right;
|
6175
6180
|
}
|
6176
6181
|
|
@@ -6778,20 +6783,20 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
|
|
6778
6783
|
return self;
|
6779
6784
|
});
|
6780
6785
|
|
6781
|
-
function is_nullish(node) {
|
6786
|
+
function is_nullish(node, compressor) {
|
6782
6787
|
let fixed;
|
6783
6788
|
return (
|
6784
6789
|
node instanceof AST_Null
|
6785
|
-
|| is_undefined(node)
|
6790
|
+
|| is_undefined(node, compressor)
|
6786
6791
|
|| (
|
6787
6792
|
node instanceof AST_SymbolRef
|
6788
6793
|
&& (fixed = node.definition().fixed) instanceof AST_Node
|
6789
|
-
&& is_nullish(fixed)
|
6794
|
+
&& is_nullish(fixed, compressor)
|
6790
6795
|
)
|
6791
6796
|
// Recurse into those optional chains!
|
6792
|
-
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression)
|
6793
|
-
|| node instanceof AST_Call && node.optional && is_nullish(node.expression)
|
6794
|
-
|| node instanceof AST_Chain && is_nullish(node.expression)
|
6797
|
+
|| node instanceof AST_PropAccess && node.optional && is_nullish(node.expression, compressor)
|
6798
|
+
|| node instanceof AST_Call && node.optional && is_nullish(node.expression, compressor)
|
6799
|
+
|| node instanceof AST_Chain && is_nullish(node.expression, compressor)
|
6795
6800
|
);
|
6796
6801
|
}
|
6797
6802
|
|
@@ -6806,8 +6811,8 @@ function is_nullish_check(check, check_subject, compressor) {
|
|
6806
6811
|
&& check.operator === "=="
|
6807
6812
|
// which side is nullish?
|
6808
6813
|
&& (
|
6809
|
-
(nullish_side = is_nullish(check.left) && check.left)
|
6810
|
-
|| (nullish_side = is_nullish(check.right) && check.right)
|
6814
|
+
(nullish_side = is_nullish(check.left, compressor) && check.left)
|
6815
|
+
|| (nullish_side = is_nullish(check.right, compressor) && check.right)
|
6811
6816
|
)
|
6812
6817
|
// is the other side the same as the check_subject
|
6813
6818
|
&& (
|
@@ -6845,12 +6850,12 @@ function is_nullish_check(check, check_subject, compressor) {
|
|
6845
6850
|
null_cmp = cmp;
|
6846
6851
|
defined_side = cmp.left;
|
6847
6852
|
}
|
6848
|
-
if (is_undefined(cmp.left)) {
|
6853
|
+
if (is_undefined(cmp.left, compressor)) {
|
6849
6854
|
found++;
|
6850
6855
|
undefined_cmp = cmp;
|
6851
6856
|
defined_side = cmp.right;
|
6852
6857
|
}
|
6853
|
-
if (is_undefined(cmp.right)) {
|
6858
|
+
if (is_undefined(cmp.right, compressor)) {
|
6854
6859
|
found++;
|
6855
6860
|
undefined_cmp = cmp;
|
6856
6861
|
defined_side = cmp.left;
|
@@ -7351,7 +7356,7 @@ def_optimize(AST_Sub, function(self, compressor) {
|
|
7351
7356
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
7352
7357
|
return best_of(compressor, ev, self);
|
7353
7358
|
}
|
7354
|
-
if (self.optional && is_nullish(self.expression)) {
|
7359
|
+
if (self.optional && is_nullish(self.expression, compressor)) {
|
7355
7360
|
return make_node(AST_Undefined, self);
|
7356
7361
|
}
|
7357
7362
|
return self;
|
@@ -7425,7 +7430,7 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
7425
7430
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
7426
7431
|
return best_of(compressor, ev, self);
|
7427
7432
|
}
|
7428
|
-
if (self.optional && is_nullish(self.expression)) {
|
7433
|
+
if (self.optional && is_nullish(self.expression, compressor)) {
|
7429
7434
|
return make_node(AST_Undefined, self);
|
7430
7435
|
}
|
7431
7436
|
return self;
|
@@ -7469,7 +7474,7 @@ def_optimize(AST_Array, function(self, compressor) {
|
|
7469
7474
|
return self;
|
7470
7475
|
});
|
7471
7476
|
|
7472
|
-
function inline_object_prop_spread(props) {
|
7477
|
+
function inline_object_prop_spread(props, compressor) {
|
7473
7478
|
for (var i = 0; i < props.length; i++) {
|
7474
7479
|
var prop = props[i];
|
7475
7480
|
if (prop instanceof AST_Expansion) {
|
@@ -7487,6 +7492,9 @@ function inline_object_prop_spread(props) {
|
|
7487
7492
|
// non-iterable value silently does nothing; it is thus safe
|
7488
7493
|
// to remove. AST_String is the only iterable AST_Constant.
|
7489
7494
|
props.splice(i, 1);
|
7495
|
+
} else if (is_nullish(expr, compressor)) {
|
7496
|
+
// Likewise, null and undefined can be silently removed.
|
7497
|
+
props.splice(i, 1);
|
7490
7498
|
}
|
7491
7499
|
}
|
7492
7500
|
}
|
@@ -7497,7 +7505,7 @@ def_optimize(AST_Object, function(self, compressor) {
|
|
7497
7505
|
if (optimized !== self) {
|
7498
7506
|
return optimized;
|
7499
7507
|
}
|
7500
|
-
inline_object_prop_spread(self.properties);
|
7508
|
+
inline_object_prop_spread(self.properties, compressor);
|
7501
7509
|
return self;
|
7502
7510
|
});
|
7503
7511
|
|
@@ -7590,7 +7598,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
|
|
7590
7598
|
&& (
|
7591
7599
|
segments[1].is_string(compressor)
|
7592
7600
|
|| segments[1].is_number(compressor)
|
7593
|
-
|| is_nullish(segments[1])
|
7601
|
+
|| is_nullish(segments[1], compressor)
|
7594
7602
|
|| compressor.option("unsafe")
|
7595
7603
|
)
|
7596
7604
|
) {
|
package/lib/equivalent-to.js
CHANGED
@@ -18,6 +18,7 @@ import {
|
|
18
18
|
AST_Directive,
|
19
19
|
AST_Do,
|
20
20
|
AST_Dot,
|
21
|
+
AST_DotHash,
|
21
22
|
AST_EmptyStatement,
|
22
23
|
AST_Expansion,
|
23
24
|
AST_Export,
|
@@ -233,6 +234,10 @@ AST_Dot.prototype.shallow_cmp = mkshallow({
|
|
233
234
|
property: "eq"
|
234
235
|
});
|
235
236
|
|
237
|
+
AST_DotHash.prototype.shallow_cmp = mkshallow({
|
238
|
+
property: "eq"
|
239
|
+
});
|
240
|
+
|
236
241
|
AST_Unary.prototype.shallow_cmp = mkshallow({
|
237
242
|
operator: "eq"
|
238
243
|
});
|
package/lib/output.js
CHANGED
@@ -349,11 +349,15 @@ function OutputStream(options) {
|
|
349
349
|
var do_add_mapping = mappings ? function() {
|
350
350
|
mappings.forEach(function(mapping) {
|
351
351
|
try {
|
352
|
+
let name = !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name;
|
353
|
+
if (name instanceof AST_Symbol) {
|
354
|
+
name = name.name;
|
355
|
+
}
|
352
356
|
options.source_map.add(
|
353
357
|
mapping.token.file,
|
354
358
|
mapping.line, mapping.col,
|
355
359
|
mapping.token.line, mapping.token.col,
|
356
|
-
|
360
|
+
is_basic_identifier_string(name) ? name : undefined
|
357
361
|
);
|
358
362
|
} catch(ex) {
|
359
363
|
// Ignore bad mapping
|
package/lib/scope.js
CHANGED
@@ -299,7 +299,14 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
|
|
299
299
|
// scope when we encounter the AST_Defun node (which is
|
300
300
|
// instanceof AST_Scope) but we get to the symbol a bit
|
301
301
|
// later.
|
302
|
-
|
302
|
+
const closest_scope = defun.parent_scope;
|
303
|
+
|
304
|
+
// In strict mode, function definitions are block-scoped
|
305
|
+
node.scope = tw.directives["use strict"]
|
306
|
+
? closest_scope
|
307
|
+
: closest_scope.get_defun_scope();
|
308
|
+
|
309
|
+
mark_export(node.scope.def_function(node, defun), 1);
|
303
310
|
} else if (node instanceof AST_SymbolClass) {
|
304
311
|
mark_export(defun.def_variable(node, defun), 1);
|
305
312
|
} else if (node instanceof AST_SymbolImport) {
|
@@ -478,7 +485,6 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
|
|
478
485
|
|
479
486
|
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
|
480
487
|
this.variables = new Map(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
|
481
|
-
this.functions = new Map(); // map name to AST_SymbolDefun (functions defined in this scope)
|
482
488
|
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
|
483
489
|
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
|
484
490
|
this.parent_scope = parent_scope; // the parent scope
|
@@ -641,7 +647,6 @@ AST_Scope.DEFMETHOD("find_variable", function(name) {
|
|
641
647
|
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
|
642
648
|
var def = this.def_variable(symbol, init);
|
643
649
|
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
644
|
-
this.functions.set(symbol.name, def);
|
645
650
|
return def;
|
646
651
|
});
|
647
652
|
|
package/lib/utils/index.js
CHANGED
@@ -64,10 +64,8 @@ class DefaultsError extends Error {
|
|
64
64
|
function defaults(args, defs, croak) {
|
65
65
|
if (args === true) {
|
66
66
|
args = {};
|
67
|
-
}
|
68
|
-
|
69
|
-
if (args != null && typeof args === "object") {
|
70
|
-
args = Object.assign({}, args);
|
67
|
+
} else if (args != null && typeof args === "object") {
|
68
|
+
args = {...args};
|
71
69
|
}
|
72
70
|
|
73
71
|
const ret = args || {};
|