terser 5.29.1 → 5.30.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 +7 -0
- package/dist/bundle.min.js +41 -25
- package/lib/ast.js +18 -0
- package/lib/compress/drop-side-effect-free.js +7 -7
- package/lib/compress/drop-unused.js +8 -13
- package/lib/compress/index.js +7 -5
- package/lib/compress/inline.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.20.0
|
4
|
+
- Improve removal of classes referring to themselves
|
5
|
+
|
6
|
+
## v5.29.2
|
7
|
+
- Make sure 'computed_props' creates string keys
|
8
|
+
- Take into account the evaluated size when inlining
|
9
|
+
|
3
10
|
## v5.29.1
|
4
11
|
- fix optimisation of all-bits mask check
|
5
12
|
|
package/dist/bundle.min.js
CHANGED
@@ -5894,6 +5894,24 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
|
|
5894
5894
|
}
|
5895
5895
|
});
|
5896
5896
|
},
|
5897
|
+
is_self_referential: function() {
|
5898
|
+
const this_id = this.name && this.name.definition().id;
|
5899
|
+
let found = false;
|
5900
|
+
let class_this = true;
|
5901
|
+
this.visit_nondeferred_class_parts(new TreeWalker((node, descend) => {
|
5902
|
+
if (found) return true;
|
5903
|
+
if (node instanceof AST_This) return (found = class_this);
|
5904
|
+
if (node instanceof AST_SymbolRef) return (found = node.definition().id === this_id);
|
5905
|
+
if (node instanceof AST_Lambda && !(node instanceof AST_Arrow)) {
|
5906
|
+
const class_this_save = class_this;
|
5907
|
+
class_this = false;
|
5908
|
+
descend();
|
5909
|
+
class_this = class_this_save;
|
5910
|
+
return true;
|
5911
|
+
}
|
5912
|
+
}));
|
5913
|
+
return found;
|
5914
|
+
},
|
5897
5915
|
}, AST_Scope /* TODO a class might have a scope but it's not a scope */);
|
5898
5916
|
|
5899
5917
|
var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", function AST_ClassProperty(props) {
|
@@ -14919,9 +14937,13 @@ def_drop_side_effect_free(AST_Arrow, return_null);
|
|
14919
14937
|
|
14920
14938
|
def_drop_side_effect_free(AST_Class, function (compressor) {
|
14921
14939
|
const with_effects = [];
|
14940
|
+
|
14941
|
+
if (this.is_self_referential() && this.has_side_effects(compressor)) {
|
14942
|
+
return this;
|
14943
|
+
}
|
14944
|
+
|
14922
14945
|
const trimmed_extends = this.extends && this.extends.drop_side_effect_free(compressor);
|
14923
|
-
if (trimmed_extends)
|
14924
|
-
with_effects.push(trimmed_extends);
|
14946
|
+
if (trimmed_extends) with_effects.push(trimmed_extends);
|
14925
14947
|
|
14926
14948
|
for (const prop of this.properties) {
|
14927
14949
|
if (prop instanceof AST_ClassStaticBlock) {
|
@@ -14930,11 +14952,7 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
|
|
14930
14952
|
}
|
14931
14953
|
} else {
|
14932
14954
|
const trimmed_prop = prop.drop_side_effect_free(compressor);
|
14933
|
-
if (trimmed_prop)
|
14934
|
-
if (trimmed_prop.contains_this()) return this;
|
14935
|
-
|
14936
|
-
with_effects.push(trimmed_prop);
|
14937
|
-
}
|
14955
|
+
if (trimmed_prop) with_effects.push(trimmed_prop);
|
14938
14956
|
}
|
14939
14957
|
}
|
14940
14958
|
|
@@ -15204,7 +15222,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15204
15222
|
return node.expression;
|
15205
15223
|
}
|
15206
15224
|
};
|
15207
|
-
var this_def = null;
|
15208
15225
|
var in_use_ids = new Map();
|
15209
15226
|
var fixed_ids = new Map();
|
15210
15227
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
@@ -15216,6 +15233,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15216
15233
|
}
|
15217
15234
|
var var_defs_by_id = new Map();
|
15218
15235
|
var initializations = new Map();
|
15236
|
+
var self_referential_classes = new Set();
|
15219
15237
|
|
15220
15238
|
// pass 1: find out which symbols are directly used in
|
15221
15239
|
// this scope (not in nested scopes).
|
@@ -15229,6 +15247,10 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15229
15247
|
});
|
15230
15248
|
}
|
15231
15249
|
if (node === self) return;
|
15250
|
+
if (node instanceof AST_Class && node.has_side_effects(compressor)) {
|
15251
|
+
if (node.is_self_referential()) self_referential_classes.add(node);
|
15252
|
+
node.visit_nondeferred_class_parts(tw);
|
15253
|
+
}
|
15232
15254
|
if (node instanceof AST_Defun || node instanceof AST_DefClass) {
|
15233
15255
|
var node_def = node.name.definition();
|
15234
15256
|
const in_export = tw.parent() instanceof AST_Export;
|
@@ -15238,22 +15260,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15238
15260
|
}
|
15239
15261
|
}
|
15240
15262
|
|
15241
|
-
if (node instanceof AST_DefClass && node.has_side_effects(compressor)) {
|
15242
|
-
const save_this_def = this_def;
|
15243
|
-
this_def = node_def;
|
15244
|
-
node.visit_nondeferred_class_parts(tw);
|
15245
|
-
this_def = save_this_def;
|
15246
|
-
}
|
15247
|
-
|
15248
15263
|
map_add(initializations, node_def.id, node);
|
15249
15264
|
return true; // don't go in nested scopes
|
15250
15265
|
}
|
15251
15266
|
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
15252
15267
|
const in_root_scope = scope === self;
|
15253
|
-
if (node instanceof AST_This && this_def && in_root_scope) {
|
15254
|
-
in_use_ids.set(this_def.id, this_def);
|
15255
|
-
return true;
|
15256
|
-
}
|
15257
15268
|
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
15258
15269
|
map_add(var_defs_by_id, node.definition().id, node);
|
15259
15270
|
}
|
@@ -15302,6 +15313,9 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
15302
15313
|
init.walk(tw);
|
15303
15314
|
});
|
15304
15315
|
});
|
15316
|
+
self_referential_classes.forEach(function (cls) {
|
15317
|
+
cls.walk(tw);
|
15318
|
+
});
|
15305
15319
|
// pass 3: we should drop declarations not in_use
|
15306
15320
|
var tt = new TreeTransformer(
|
15307
15321
|
function before(node, descend, in_list) {
|
@@ -17971,7 +17985,7 @@ function inline_into_symbolref(self, compressor) {
|
|
17971
17985
|
let overhead = 0;
|
17972
17986
|
if (compressor.option("unused") && !compressor.exposed(def)) {
|
17973
17987
|
overhead =
|
17974
|
-
(name_length + 2 +
|
17988
|
+
(name_length + 2 + fixed.size(compressor)) /
|
17975
17989
|
(def.references.length - def.assignments);
|
17976
17990
|
}
|
17977
17991
|
|
@@ -22163,21 +22177,23 @@ function lift_key(self, compressor) {
|
|
22163
22177
|
if (!(self.key instanceof AST_Constant)) return self;
|
22164
22178
|
// allow certain acceptable props as not all AST_Constants are true constants
|
22165
22179
|
if (self.key instanceof AST_String || self.key instanceof AST_Number) {
|
22166
|
-
|
22167
|
-
|
22180
|
+
const key = self.key.value.toString();
|
22181
|
+
|
22182
|
+
if (key === "__proto__") return self;
|
22183
|
+
if (key == "constructor"
|
22168
22184
|
&& compressor.parent() instanceof AST_Class) return self;
|
22169
22185
|
if (self instanceof AST_ObjectKeyVal) {
|
22170
22186
|
self.quote = self.key.quote;
|
22171
|
-
self.key =
|
22187
|
+
self.key = key;
|
22172
22188
|
} else if (self instanceof AST_ClassProperty) {
|
22173
22189
|
self.quote = self.key.quote;
|
22174
22190
|
self.key = make_node(AST_SymbolClassProperty, self.key, {
|
22175
|
-
name:
|
22191
|
+
name: key,
|
22176
22192
|
});
|
22177
22193
|
} else {
|
22178
22194
|
self.quote = self.key.quote;
|
22179
22195
|
self.key = make_node(AST_SymbolMethod, self.key, {
|
22180
|
-
name:
|
22196
|
+
name: key,
|
22181
22197
|
});
|
22182
22198
|
}
|
22183
22199
|
}
|
package/lib/ast.js
CHANGED
@@ -2271,6 +2271,24 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
|
|
2271
2271
|
}
|
2272
2272
|
});
|
2273
2273
|
},
|
2274
|
+
is_self_referential: function() {
|
2275
|
+
const this_id = this.name && this.name.definition().id;
|
2276
|
+
let found = false;
|
2277
|
+
let class_this = true;
|
2278
|
+
this.visit_nondeferred_class_parts(new TreeWalker((node, descend) => {
|
2279
|
+
if (found) return true;
|
2280
|
+
if (node instanceof AST_This) return (found = class_this);
|
2281
|
+
if (node instanceof AST_SymbolRef) return (found = node.definition().id === this_id);
|
2282
|
+
if (node instanceof AST_Lambda && !(node instanceof AST_Arrow)) {
|
2283
|
+
const class_this_save = class_this;
|
2284
|
+
class_this = false;
|
2285
|
+
descend();
|
2286
|
+
class_this = class_this_save;
|
2287
|
+
return true;
|
2288
|
+
}
|
2289
|
+
}));
|
2290
|
+
return found;
|
2291
|
+
},
|
2274
2292
|
}, AST_Scope /* TODO a class might have a scope but it's not a scope */);
|
2275
2293
|
|
2276
2294
|
var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", function AST_ClassProperty(props) {
|
@@ -155,9 +155,13 @@ def_drop_side_effect_free(AST_Arrow, return_null);
|
|
155
155
|
|
156
156
|
def_drop_side_effect_free(AST_Class, function (compressor) {
|
157
157
|
const with_effects = [];
|
158
|
+
|
159
|
+
if (this.is_self_referential() && this.has_side_effects(compressor)) {
|
160
|
+
return this;
|
161
|
+
}
|
162
|
+
|
158
163
|
const trimmed_extends = this.extends && this.extends.drop_side_effect_free(compressor);
|
159
|
-
if (trimmed_extends)
|
160
|
-
with_effects.push(trimmed_extends);
|
164
|
+
if (trimmed_extends) with_effects.push(trimmed_extends);
|
161
165
|
|
162
166
|
for (const prop of this.properties) {
|
163
167
|
if (prop instanceof AST_ClassStaticBlock) {
|
@@ -166,11 +170,7 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
|
|
166
170
|
}
|
167
171
|
} else {
|
168
172
|
const trimmed_prop = prop.drop_side_effect_free(compressor);
|
169
|
-
if (trimmed_prop)
|
170
|
-
if (trimmed_prop.contains_this()) return this;
|
171
|
-
|
172
|
-
with_effects.push(trimmed_prop);
|
173
|
-
}
|
173
|
+
if (trimmed_prop) with_effects.push(trimmed_prop);
|
174
174
|
}
|
175
175
|
}
|
176
176
|
|
@@ -70,7 +70,6 @@ import {
|
|
70
70
|
AST_SymbolFunarg,
|
71
71
|
AST_SymbolRef,
|
72
72
|
AST_SymbolVar,
|
73
|
-
AST_This,
|
74
73
|
AST_Toplevel,
|
75
74
|
AST_Unary,
|
76
75
|
AST_Var,
|
@@ -127,7 +126,6 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
127
126
|
return node.expression;
|
128
127
|
}
|
129
128
|
};
|
130
|
-
var this_def = null;
|
131
129
|
var in_use_ids = new Map();
|
132
130
|
var fixed_ids = new Map();
|
133
131
|
if (self instanceof AST_Toplevel && compressor.top_retain) {
|
@@ -139,6 +137,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
139
137
|
}
|
140
138
|
var var_defs_by_id = new Map();
|
141
139
|
var initializations = new Map();
|
140
|
+
var self_referential_classes = new Set();
|
142
141
|
|
143
142
|
// pass 1: find out which symbols are directly used in
|
144
143
|
// this scope (not in nested scopes).
|
@@ -152,6 +151,10 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
152
151
|
});
|
153
152
|
}
|
154
153
|
if (node === self) return;
|
154
|
+
if (node instanceof AST_Class && node.has_side_effects(compressor)) {
|
155
|
+
if (node.is_self_referential()) self_referential_classes.add(node);
|
156
|
+
node.visit_nondeferred_class_parts(tw);
|
157
|
+
}
|
155
158
|
if (node instanceof AST_Defun || node instanceof AST_DefClass) {
|
156
159
|
var node_def = node.name.definition();
|
157
160
|
const in_export = tw.parent() instanceof AST_Export;
|
@@ -161,22 +164,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
161
164
|
}
|
162
165
|
}
|
163
166
|
|
164
|
-
if (node instanceof AST_DefClass && node.has_side_effects(compressor)) {
|
165
|
-
const save_this_def = this_def;
|
166
|
-
this_def = node_def;
|
167
|
-
node.visit_nondeferred_class_parts(tw);
|
168
|
-
this_def = save_this_def;
|
169
|
-
}
|
170
|
-
|
171
167
|
map_add(initializations, node_def.id, node);
|
172
168
|
return true; // don't go in nested scopes
|
173
169
|
}
|
174
170
|
// In the root scope, we drop things. In inner scopes, we just check for uses.
|
175
171
|
const in_root_scope = scope === self;
|
176
|
-
if (node instanceof AST_This && this_def && in_root_scope) {
|
177
|
-
in_use_ids.set(this_def.id, this_def);
|
178
|
-
return true;
|
179
|
-
}
|
180
172
|
if (node instanceof AST_SymbolFunarg && in_root_scope) {
|
181
173
|
map_add(var_defs_by_id, node.definition().id, node);
|
182
174
|
}
|
@@ -225,6 +217,9 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
225
217
|
init.walk(tw);
|
226
218
|
});
|
227
219
|
});
|
220
|
+
self_referential_classes.forEach(function (cls) {
|
221
|
+
cls.walk(tw);
|
222
|
+
});
|
228
223
|
// pass 3: we should drop declarations not in_use
|
229
224
|
var tt = new TreeTransformer(
|
230
225
|
function before(node, descend, in_list) {
|
package/lib/compress/index.js
CHANGED
@@ -3924,21 +3924,23 @@ function lift_key(self, compressor) {
|
|
3924
3924
|
if (!(self.key instanceof AST_Constant)) return self;
|
3925
3925
|
// allow certain acceptable props as not all AST_Constants are true constants
|
3926
3926
|
if (self.key instanceof AST_String || self.key instanceof AST_Number) {
|
3927
|
-
|
3928
|
-
|
3927
|
+
const key = self.key.value.toString();
|
3928
|
+
|
3929
|
+
if (key === "__proto__") return self;
|
3930
|
+
if (key == "constructor"
|
3929
3931
|
&& compressor.parent() instanceof AST_Class) return self;
|
3930
3932
|
if (self instanceof AST_ObjectKeyVal) {
|
3931
3933
|
self.quote = self.key.quote;
|
3932
|
-
self.key =
|
3934
|
+
self.key = key;
|
3933
3935
|
} else if (self instanceof AST_ClassProperty) {
|
3934
3936
|
self.quote = self.key.quote;
|
3935
3937
|
self.key = make_node(AST_SymbolClassProperty, self.key, {
|
3936
|
-
name:
|
3938
|
+
name: key,
|
3937
3939
|
});
|
3938
3940
|
} else {
|
3939
3941
|
self.quote = self.key.quote;
|
3940
3942
|
self.key = make_node(AST_SymbolMethod, self.key, {
|
3941
|
-
name:
|
3943
|
+
name: key,
|
3942
3944
|
});
|
3943
3945
|
}
|
3944
3946
|
}
|
package/lib/compress/inline.js
CHANGED
@@ -302,7 +302,7 @@ export function inline_into_symbolref(self, compressor) {
|
|
302
302
|
let overhead = 0;
|
303
303
|
if (compressor.option("unused") && !compressor.exposed(def)) {
|
304
304
|
overhead =
|
305
|
-
(name_length + 2 +
|
305
|
+
(name_length + 2 + fixed.size(compressor)) /
|
306
306
|
(def.references.length - def.assignments);
|
307
307
|
}
|
308
308
|
|