terser 5.14.0 → 5.15.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 +22 -0
- package/bin/terser.mjs +21 -0
- package/dist/bundle.min.js +171 -35
- package/lib/ast.js +32 -0
- package/lib/cli.js +3 -1
- package/lib/compress/drop-side-effect-free.js +9 -0
- package/lib/compress/evaluate.js +14 -14
- package/lib/compress/index.js +20 -11
- package/lib/compress/inference.js +21 -1
- package/lib/compress/inline.js +1 -0
- package/lib/compress/reduce-vars.js +5 -0
- package/lib/mozilla-ast.js +16 -0
- package/lib/output.js +8 -0
- package/lib/parse.js +33 -8
- package/lib/size.js +6 -0
- package/lib/transform.js +5 -0
- package/lib/utils/index.js +9 -1
- package/package.json +1 -1
- package/tools/domprops.js +3 -0
- package/tools/terser.d.ts +1 -0
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.15.0
|
4
|
+
- Basic support for ES2022 class static initializer blocks.
|
5
|
+
- Add `AudioWorkletNode` constructor options to domprops list (#1230)
|
6
|
+
- Make identity function inliner not inline `id(...expandedArgs)`
|
7
|
+
|
8
|
+
## v5.14.2
|
9
|
+
|
10
|
+
- Security fix for RegExps that should not be evaluated (regexp DDOS)
|
11
|
+
- Source maps improvements (#1211)
|
12
|
+
- Performance improvements in long property access evaluation (#1213)
|
13
|
+
|
14
|
+
## v5.14.1
|
15
|
+
- keep_numbers option added to TypeScript defs (#1208)
|
16
|
+
- Fixed parsing of nested template strings (#1204)
|
17
|
+
|
3
18
|
## v5.14.0
|
4
19
|
- Switched to @jridgewell/source-map for sourcemap generation (#1190, #1181)
|
5
20
|
- Fixed source maps with non-terminated segments (#1106)
|
@@ -202,6 +217,13 @@ Hotfix release, fixes package.json "engines" syntax
|
|
202
217
|
- Module is now distributed as a dual package - You can `import` and `require()` too.
|
203
218
|
- Inline improvements were made
|
204
219
|
|
220
|
+
|
221
|
+
-----
|
222
|
+
|
223
|
+
## v4.8.1 (backport)
|
224
|
+
|
225
|
+
- Security fix for RegExps that should not be evaluated (regexp DDOS)
|
226
|
+
|
205
227
|
## v4.8.0
|
206
228
|
|
207
229
|
- Support for numeric separators (`million = 1_000_000`) was added.
|
package/bin/terser.mjs
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
"use strict";
|
4
|
+
|
5
|
+
import "../tools/exit.cjs";
|
6
|
+
|
7
|
+
import fs from "fs"
|
8
|
+
import path from "path"
|
9
|
+
import program from "commander"
|
10
|
+
|
11
|
+
import { run_cli } from "../lib/cli.js"
|
12
|
+
|
13
|
+
const packageJson = {
|
14
|
+
name: "terser",
|
15
|
+
version: "experimental module CLI"
|
16
|
+
}
|
17
|
+
|
18
|
+
run_cli({ program, packageJson, fs, path }).catch((error) => {
|
19
|
+
console.error(error);
|
20
|
+
process.exitCode = 1;
|
21
|
+
});
|
package/dist/bundle.min.js
CHANGED
@@ -253,7 +253,15 @@ function regexp_source_fix(source) {
|
|
253
253
|
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
|
254
254
|
});
|
255
255
|
}
|
256
|
-
|
256
|
+
|
257
|
+
// Subset of regexps that is not going to cause regexp based DDOS
|
258
|
+
// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
|
259
|
+
const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;
|
260
|
+
|
261
|
+
/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
|
262
|
+
const regexp_is_safe = (source) => re_safe_regexp.test(source);
|
263
|
+
|
264
|
+
const all_flags = "dgimsuy";
|
257
265
|
function sort_regexp_flags(flags) {
|
258
266
|
const existing_flags = new Set(flags.split(""));
|
259
267
|
let out = "";
|
@@ -323,7 +331,7 @@ function set_annotation(node, annotation) {
|
|
323
331
|
***********************************************************************/
|
324
332
|
|
325
333
|
var LATEST_RAW = ""; // Only used for numbers and template strings
|
326
|
-
var
|
334
|
+
var TEMPLATE_RAWS = new Map(); // Raw template strings
|
327
335
|
|
328
336
|
var KEYWORDS = "break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with";
|
329
337
|
var KEYWORDS_ATOM = "false null true";
|
@@ -854,8 +862,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
854
862
|
next(true, true);
|
855
863
|
S.brace_counter++;
|
856
864
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
857
|
-
|
858
|
-
|
865
|
+
TEMPLATE_RAWS.set(tok, raw);
|
866
|
+
tok.template_end = false;
|
859
867
|
return tok;
|
860
868
|
}
|
861
869
|
|
@@ -871,8 +879,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
871
879
|
}
|
872
880
|
S.template_braces.pop();
|
873
881
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
874
|
-
|
875
|
-
|
882
|
+
TEMPLATE_RAWS.set(tok, raw);
|
883
|
+
tok.template_end = true;
|
876
884
|
return tok;
|
877
885
|
});
|
878
886
|
|
@@ -2528,19 +2536,19 @@ function parse($TEXT, options) {
|
|
2528
2536
|
|
2529
2537
|
segments.push(new AST_TemplateSegment({
|
2530
2538
|
start: S.token,
|
2531
|
-
raw:
|
2539
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2532
2540
|
value: S.token.value,
|
2533
2541
|
end: S.token
|
2534
2542
|
}));
|
2535
2543
|
|
2536
|
-
while (!
|
2544
|
+
while (!S.token.template_end) {
|
2537
2545
|
next();
|
2538
2546
|
handle_regexp();
|
2539
2547
|
segments.push(expression(true));
|
2540
2548
|
|
2541
2549
|
segments.push(new AST_TemplateSegment({
|
2542
2550
|
start: S.token,
|
2543
|
-
raw:
|
2551
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2544
2552
|
value: S.token.value,
|
2545
2553
|
end: S.token
|
2546
2554
|
}));
|
@@ -2723,6 +2731,10 @@ function parse($TEXT, options) {
|
|
2723
2731
|
var accessor_type = null;
|
2724
2732
|
|
2725
2733
|
if (is_class && name === "static" && is_not_method_start()) {
|
2734
|
+
const static_block = class_static_block();
|
2735
|
+
if (static_block != null) {
|
2736
|
+
return static_block;
|
2737
|
+
}
|
2726
2738
|
is_static = true;
|
2727
2739
|
name = as_property_name();
|
2728
2740
|
}
|
@@ -2829,6 +2841,25 @@ function parse($TEXT, options) {
|
|
2829
2841
|
}
|
2830
2842
|
}
|
2831
2843
|
|
2844
|
+
function class_static_block() {
|
2845
|
+
if (!is("punc", "{")) {
|
2846
|
+
return null;
|
2847
|
+
}
|
2848
|
+
|
2849
|
+
const start = S.token;
|
2850
|
+
const body = [];
|
2851
|
+
|
2852
|
+
next();
|
2853
|
+
|
2854
|
+
while (!is("punc", "}")) {
|
2855
|
+
body.push(statement());
|
2856
|
+
}
|
2857
|
+
|
2858
|
+
next();
|
2859
|
+
|
2860
|
+
return new AST_ClassStaticBlock({ start, body, end: prev() });
|
2861
|
+
}
|
2862
|
+
|
2832
2863
|
function maybe_import_assertion() {
|
2833
2864
|
if (is("name", "assert") && !has_newline_before(S.token)) {
|
2834
2865
|
next();
|
@@ -3503,6 +3534,7 @@ function parse($TEXT, options) {
|
|
3503
3534
|
} else {
|
3504
3535
|
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
|
3505
3536
|
}
|
3537
|
+
TEMPLATE_RAWS = new Map();
|
3506
3538
|
return toplevel;
|
3507
3539
|
})();
|
3508
3540
|
|
@@ -3596,6 +3628,7 @@ const set_tok_flag = (tok, flag, truth) => {
|
|
3596
3628
|
const TOK_FLAG_NLB = 0b0001;
|
3597
3629
|
const TOK_FLAG_QUOTE_SINGLE = 0b0010;
|
3598
3630
|
const TOK_FLAG_QUOTE_EXISTS = 0b0100;
|
3631
|
+
const TOK_FLAG_TEMPLATE_END = 0b1000;
|
3599
3632
|
|
3600
3633
|
class AST_Token {
|
3601
3634
|
constructor(type, value, line, col, pos, nlb, comments_before, comments_after, file) {
|
@@ -3631,6 +3664,14 @@ class AST_Token {
|
|
3631
3664
|
set_tok_flag(this, TOK_FLAG_QUOTE_SINGLE, quote_type === "'");
|
3632
3665
|
set_tok_flag(this, TOK_FLAG_QUOTE_EXISTS, !!quote_type);
|
3633
3666
|
}
|
3667
|
+
|
3668
|
+
get template_end() {
|
3669
|
+
return has_tok_flag(this, TOK_FLAG_TEMPLATE_END);
|
3670
|
+
}
|
3671
|
+
|
3672
|
+
set template_end(new_template_end) {
|
3673
|
+
set_tok_flag(this, TOK_FLAG_TEMPLATE_END, new_template_end);
|
3674
|
+
}
|
3634
3675
|
}
|
3635
3676
|
|
3636
3677
|
var AST_Node = DEFNODE("Node", "start end", function AST_Node(props) {
|
@@ -5766,6 +5807,28 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
|
|
5766
5807
|
$documentation: "A class definition",
|
5767
5808
|
}, AST_Class);
|
5768
5809
|
|
5810
|
+
var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
|
5811
|
+
this.body = props.body;
|
5812
|
+
this.block_scope = props.block_scope;
|
5813
|
+
this.start = props.start;
|
5814
|
+
this.end = props.end;
|
5815
|
+
}, {
|
5816
|
+
$documentation: "A block containing statements to be executed in the context of the class",
|
5817
|
+
$propdoc: {
|
5818
|
+
body: "[AST_Statement*] an array of statements",
|
5819
|
+
},
|
5820
|
+
_walk: function(visitor) {
|
5821
|
+
return visitor._visit(this, function() {
|
5822
|
+
walk_body(this, visitor);
|
5823
|
+
});
|
5824
|
+
},
|
5825
|
+
_children_backwards(push) {
|
5826
|
+
let i = this.body.length;
|
5827
|
+
while (i--) push(this.body[i]);
|
5828
|
+
},
|
5829
|
+
clone: clone_block_scope,
|
5830
|
+
}, AST_Scope);
|
5831
|
+
|
5769
5832
|
var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
|
5770
5833
|
if (props) {
|
5771
5834
|
this.name = props.name;
|
@@ -6782,6 +6845,10 @@ def_transform(AST_Class, function(self, tw) {
|
|
6782
6845
|
self.properties = do_list(self.properties, tw);
|
6783
6846
|
});
|
6784
6847
|
|
6848
|
+
def_transform(AST_ClassStaticBlock, function(self, tw) {
|
6849
|
+
self.body = do_list(self.body, tw);
|
6850
|
+
});
|
6851
|
+
|
6785
6852
|
def_transform(AST_Expansion, function(self, tw) {
|
6786
6853
|
self.expression = self.expression.transform(tw);
|
6787
6854
|
});
|
@@ -7141,6 +7208,14 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
7141
7208
|
});
|
7142
7209
|
},
|
7143
7210
|
|
7211
|
+
StaticBlock: function(M) {
|
7212
|
+
return new AST_ClassStaticBlock({
|
7213
|
+
start : my_start_token(M),
|
7214
|
+
end : my_end_token(M),
|
7215
|
+
body : M.body.map(from_moz),
|
7216
|
+
});
|
7217
|
+
},
|
7218
|
+
|
7144
7219
|
ArrayExpression: function(M) {
|
7145
7220
|
return new AST_Array({
|
7146
7221
|
start : my_start_token(M),
|
@@ -8280,6 +8355,13 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
|
|
8280
8355
|
};
|
8281
8356
|
});
|
8282
8357
|
|
8358
|
+
def_to_moz(AST_ClassStaticBlock, function To_Moz_StaticBlock(M) {
|
8359
|
+
return {
|
8360
|
+
type: "StaticBlock",
|
8361
|
+
body: M.body.map(to_moz),
|
8362
|
+
};
|
8363
|
+
});
|
8364
|
+
|
8283
8365
|
def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
|
8284
8366
|
return {
|
8285
8367
|
type: "MetaProperty",
|
@@ -9630,12 +9712,14 @@ function OutputStream(options) {
|
|
9630
9712
|
output.with_indent(output.next_indent(), function() {
|
9631
9713
|
output.append_comments(self, true);
|
9632
9714
|
});
|
9715
|
+
output.add_mapping(self.end);
|
9633
9716
|
output.print("}");
|
9634
9717
|
}
|
9635
9718
|
function print_braced(self, output, allow_directives) {
|
9636
9719
|
if (self.body.length > 0) {
|
9637
9720
|
output.with_block(function() {
|
9638
9721
|
display_body(self.body, false, output, allow_directives);
|
9722
|
+
output.add_mapping(self.end);
|
9639
9723
|
});
|
9640
9724
|
} else print_braced_empty(self, output);
|
9641
9725
|
}
|
@@ -10575,6 +10659,11 @@ function OutputStream(options) {
|
|
10575
10659
|
}
|
10576
10660
|
self._print_getter_setter(type, false, output);
|
10577
10661
|
});
|
10662
|
+
DEFPRINT(AST_ClassStaticBlock, function (self, output) {
|
10663
|
+
output.print("static");
|
10664
|
+
output.space();
|
10665
|
+
print_braced(self, output);
|
10666
|
+
});
|
10578
10667
|
AST_Symbol.DEFMETHOD("_do_print", function(output) {
|
10579
10668
|
var def = this.definition();
|
10580
10669
|
output.print_name(def ? def.mangled_name || def.name : this.name);
|
@@ -12248,6 +12337,11 @@ AST_Class.prototype._size = function () {
|
|
12248
12337
|
);
|
12249
12338
|
};
|
12250
12339
|
|
12340
|
+
AST_ClassStaticBlock.prototype._size = function () {
|
12341
|
+
// "class{}" + semicolons
|
12342
|
+
return 7 + list_overhead(this.body);
|
12343
|
+
};
|
12344
|
+
|
12251
12345
|
AST_ClassProperty.prototype._size = function () {
|
12252
12346
|
return (
|
12253
12347
|
static_size(this.static)
|
@@ -13118,6 +13212,9 @@ function is_nullish(node, compressor) {
|
|
13118
13212
|
}
|
13119
13213
|
return any(this.properties, compressor);
|
13120
13214
|
});
|
13215
|
+
def_has_side_effects(AST_ClassStaticBlock, function(compressor) {
|
13216
|
+
return any(this.body, compressor);
|
13217
|
+
});
|
13121
13218
|
def_has_side_effects(AST_Binary, function(compressor) {
|
13122
13219
|
return this.left.has_side_effects(compressor)
|
13123
13220
|
|| this.right.has_side_effects(compressor);
|
@@ -13217,6 +13314,9 @@ function is_nullish(node, compressor) {
|
|
13217
13314
|
if (this.extends && this.extends.may_throw(compressor)) return true;
|
13218
13315
|
return any(this.properties, compressor);
|
13219
13316
|
});
|
13317
|
+
def_may_throw(AST_ClassStaticBlock, function (compressor) {
|
13318
|
+
return any(this.body, compressor);
|
13319
|
+
});
|
13220
13320
|
|
13221
13321
|
def_may_throw(AST_Array, function(compressor) {
|
13222
13322
|
return any(this.elements, compressor);
|
@@ -13385,6 +13485,9 @@ function is_nullish(node, compressor) {
|
|
13385
13485
|
if (prop.static && prop.value && !prop.value.is_constant_expression(scope)) {
|
13386
13486
|
return false;
|
13387
13487
|
}
|
13488
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
13489
|
+
return false;
|
13490
|
+
}
|
13388
13491
|
}
|
13389
13492
|
|
13390
13493
|
return all_refs_local.call(this, scope);
|
@@ -13708,9 +13811,18 @@ const aborts = (thing) => thing && thing.aborts();
|
|
13708
13811
|
}
|
13709
13812
|
return null;
|
13710
13813
|
}
|
13711
|
-
def_aborts(AST_Import,
|
13814
|
+
def_aborts(AST_Import, return_null);
|
13712
13815
|
def_aborts(AST_BlockStatement, block_aborts);
|
13713
13816
|
def_aborts(AST_SwitchBranch, block_aborts);
|
13817
|
+
def_aborts(AST_DefClass, function () {
|
13818
|
+
for (const prop of this.properties) {
|
13819
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
13820
|
+
if (prop.aborts()) return prop;
|
13821
|
+
}
|
13822
|
+
}
|
13823
|
+
return null;
|
13824
|
+
});
|
13825
|
+
def_aborts(AST_ClassStaticBlock, block_aborts);
|
13714
13826
|
def_aborts(AST_If, function() {
|
13715
13827
|
return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
|
13716
13828
|
});
|
@@ -13841,7 +13953,7 @@ def_eval(AST_BigInt, return_this);
|
|
13841
13953
|
|
13842
13954
|
def_eval(AST_RegExp, function (compressor) {
|
13843
13955
|
let evaluated = compressor.evaluated_regexps.get(this.value);
|
13844
|
-
if (evaluated === undefined) {
|
13956
|
+
if (evaluated === undefined && regexp_is_safe(this.value.source)) {
|
13845
13957
|
try {
|
13846
13958
|
const { source, flags } = this.value;
|
13847
13959
|
evaluated = new RegExp(source, flags);
|
@@ -14054,7 +14166,7 @@ const regexp_flags = new Set([
|
|
14054
14166
|
]);
|
14055
14167
|
|
14056
14168
|
def_eval(AST_PropAccess, function (compressor, depth) {
|
14057
|
-
|
14169
|
+
let obj = this.expression._eval(compressor, depth + 1);
|
14058
14170
|
if (obj === nullish || (this.optional && obj == null)) return nullish;
|
14059
14171
|
if (compressor.option("unsafe")) {
|
14060
14172
|
var key = this.property;
|
@@ -14064,7 +14176,6 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
14064
14176
|
return this;
|
14065
14177
|
}
|
14066
14178
|
var exp = this.expression;
|
14067
|
-
var val;
|
14068
14179
|
if (is_undeclared_ref(exp)) {
|
14069
14180
|
|
14070
14181
|
var aa;
|
@@ -14081,29 +14192,29 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
14081
14192
|
}
|
14082
14193
|
if (!is_pure_native_value(exp.name, key))
|
14083
14194
|
return this;
|
14084
|
-
|
14195
|
+
obj = global_objs[exp.name];
|
14085
14196
|
} else {
|
14086
|
-
|
14087
|
-
if (val instanceof RegExp) {
|
14197
|
+
if (obj instanceof RegExp) {
|
14088
14198
|
if (key == "source") {
|
14089
|
-
return regexp_source_fix(
|
14199
|
+
return regexp_source_fix(obj.source);
|
14090
14200
|
} else if (key == "flags" || regexp_flags.has(key)) {
|
14091
|
-
return
|
14201
|
+
return obj[key];
|
14092
14202
|
}
|
14093
14203
|
}
|
14094
|
-
if (!
|
14204
|
+
if (!obj || obj === exp || !HOP(obj, key))
|
14095
14205
|
return this;
|
14096
|
-
|
14206
|
+
|
14207
|
+
if (typeof obj == "function")
|
14097
14208
|
switch (key) {
|
14098
14209
|
case "name":
|
14099
|
-
return
|
14210
|
+
return obj.node.name ? obj.node.name.name : "";
|
14100
14211
|
case "length":
|
14101
|
-
return
|
14212
|
+
return obj.node.length_property();
|
14102
14213
|
default:
|
14103
14214
|
return this;
|
14104
14215
|
}
|
14105
14216
|
}
|
14106
|
-
return
|
14217
|
+
return obj[key];
|
14107
14218
|
}
|
14108
14219
|
return this;
|
14109
14220
|
});
|
@@ -14290,6 +14401,14 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
|
|
14290
14401
|
if (trimmed_extends)
|
14291
14402
|
with_effects.push(trimmed_extends);
|
14292
14403
|
for (const prop of this.properties) {
|
14404
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
14405
|
+
if (prop.body.some(stat => stat.has_side_effects(compressor))) {
|
14406
|
+
return this;
|
14407
|
+
} else {
|
14408
|
+
continue;
|
14409
|
+
}
|
14410
|
+
}
|
14411
|
+
|
14293
14412
|
const trimmed_prop = prop.drop_side_effect_free(compressor);
|
14294
14413
|
if (trimmed_prop)
|
14295
14414
|
with_effects.push(trimmed_prop);
|
@@ -14801,6 +14920,10 @@ def_reduce_vars(AST_Class, function(tw, descend) {
|
|
14801
14920
|
return true;
|
14802
14921
|
});
|
14803
14922
|
|
14923
|
+
def_reduce_vars(AST_ClassStaticBlock, function(tw, descend, compressor) {
|
14924
|
+
reset_block_variables(compressor, this);
|
14925
|
+
});
|
14926
|
+
|
14804
14927
|
def_reduce_vars(AST_Conditional, function(tw) {
|
14805
14928
|
this.condition.walk(tw);
|
14806
14929
|
push(tw);
|
@@ -16715,6 +16838,7 @@ function inline_into_call(self, fn, compressor) {
|
|
16715
16838
|
fn.argnames.length === 1
|
16716
16839
|
&& (fn.argnames[0] instanceof AST_SymbolFunarg)
|
16717
16840
|
&& self.args.length < 2
|
16841
|
+
&& !(self.args[0] instanceof AST_Expansion)
|
16718
16842
|
&& returned instanceof AST_SymbolRef
|
16719
16843
|
&& returned.name === fn.argnames[0].name
|
16720
16844
|
) {
|
@@ -17674,18 +17798,13 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
17674
17798
|
}
|
17675
17799
|
if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
|
17676
17800
|
const def = node.name.definition();
|
17677
|
-
|
17678
|
-
|
17801
|
+
const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
|
17802
|
+
// Class "extends" and static blocks may have side effects
|
17803
|
+
const has_side_effects = !keep
|
17804
|
+
&& node instanceof AST_Class
|
17805
|
+
&& node.has_side_effects(compressor);
|
17806
|
+
if (!keep && !has_side_effects) {
|
17679
17807
|
def.eliminated++;
|
17680
|
-
if (node instanceof AST_DefClass) {
|
17681
|
-
// Classes might have extends with side effects
|
17682
|
-
const side_effects = node.drop_side_effect_free(compressor);
|
17683
|
-
if (side_effects) {
|
17684
|
-
return make_node(AST_SimpleStatement, node, {
|
17685
|
-
body: side_effects
|
17686
|
-
});
|
17687
|
-
}
|
17688
|
-
}
|
17689
17808
|
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
17690
17809
|
}
|
17691
17810
|
}
|
@@ -18982,6 +19101,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
18982
19101
|
params.push(value);
|
18983
19102
|
return arg !== value;
|
18984
19103
|
})
|
19104
|
+
&& regexp_is_safe(params[0])
|
18985
19105
|
) {
|
18986
19106
|
let [ source, flags ] = params;
|
18987
19107
|
source = regexp_source_fix(new RegExp(source).source);
|
@@ -20641,6 +20761,12 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
20641
20761
|
const sub = self.flatten_object(self.property, compressor);
|
20642
20762
|
if (sub) return sub.optimize(compressor);
|
20643
20763
|
}
|
20764
|
+
|
20765
|
+
if (self.expression instanceof AST_PropAccess
|
20766
|
+
&& parent instanceof AST_PropAccess) {
|
20767
|
+
return self;
|
20768
|
+
}
|
20769
|
+
|
20644
20770
|
let ev = self.evaluate(compressor);
|
20645
20771
|
if (ev !== self) {
|
20646
20772
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
@@ -20757,6 +20883,11 @@ def_optimize(AST_Class, function(self) {
|
|
20757
20883
|
return self;
|
20758
20884
|
});
|
20759
20885
|
|
20886
|
+
def_optimize(AST_ClassStaticBlock, function(self, compressor) {
|
20887
|
+
tighten_body(self.body, compressor);
|
20888
|
+
return self;
|
20889
|
+
});
|
20890
|
+
|
20760
20891
|
def_optimize(AST_Yield, function(self, compressor) {
|
20761
20892
|
if (self.expression && !self.is_star && is_undefined(self.expression, compressor)) {
|
20762
20893
|
self.expression = null;
|
@@ -27144,6 +27275,7 @@ var domprops = [
|
|
27144
27275
|
"outlineStyle",
|
27145
27276
|
"outlineWidth",
|
27146
27277
|
"outputBuffer",
|
27278
|
+
"outputChannelCount",
|
27147
27279
|
"outputLatency",
|
27148
27280
|
"outputs",
|
27149
27281
|
"overflow",
|
@@ -27231,6 +27363,7 @@ var domprops = [
|
|
27231
27363
|
"palette",
|
27232
27364
|
"pan",
|
27233
27365
|
"panningModel",
|
27366
|
+
"parameterData",
|
27234
27367
|
"parameters",
|
27235
27368
|
"parent",
|
27236
27369
|
"parentElement",
|
@@ -27406,6 +27539,7 @@ var domprops = [
|
|
27406
27539
|
"processIceMessage",
|
27407
27540
|
"processingEnd",
|
27408
27541
|
"processingStart",
|
27542
|
+
"processorOptions",
|
27409
27543
|
"product",
|
27410
27544
|
"productId",
|
27411
27545
|
"productName",
|
@@ -29846,7 +29980,9 @@ async function run_cli({ program, packageJson, fs, path }) {
|
|
29846
29980
|
result.enclosed = value.block_scope.enclosed;
|
29847
29981
|
}
|
29848
29982
|
value.CTOR.PROPS.forEach(function(prop) {
|
29849
|
-
|
29983
|
+
if (prop !== "block_scope") {
|
29984
|
+
result[prop] = value[prop];
|
29985
|
+
}
|
29850
29986
|
});
|
29851
29987
|
return result;
|
29852
29988
|
}
|
package/lib/ast.js
CHANGED
@@ -93,6 +93,7 @@ const set_tok_flag = (tok, flag, truth) => {
|
|
93
93
|
const TOK_FLAG_NLB = 0b0001;
|
94
94
|
const TOK_FLAG_QUOTE_SINGLE = 0b0010;
|
95
95
|
const TOK_FLAG_QUOTE_EXISTS = 0b0100;
|
96
|
+
const TOK_FLAG_TEMPLATE_END = 0b1000;
|
96
97
|
|
97
98
|
class AST_Token {
|
98
99
|
constructor(type, value, line, col, pos, nlb, comments_before, comments_after, file) {
|
@@ -128,6 +129,14 @@ class AST_Token {
|
|
128
129
|
set_tok_flag(this, TOK_FLAG_QUOTE_SINGLE, quote_type === "'");
|
129
130
|
set_tok_flag(this, TOK_FLAG_QUOTE_EXISTS, !!quote_type);
|
130
131
|
}
|
132
|
+
|
133
|
+
get template_end() {
|
134
|
+
return has_tok_flag(this, TOK_FLAG_TEMPLATE_END);
|
135
|
+
}
|
136
|
+
|
137
|
+
set template_end(new_template_end) {
|
138
|
+
set_tok_flag(this, TOK_FLAG_TEMPLATE_END, new_template_end);
|
139
|
+
}
|
131
140
|
}
|
132
141
|
|
133
142
|
var AST_Node = DEFNODE("Node", "start end", function AST_Node(props) {
|
@@ -2263,6 +2272,28 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
|
|
2263
2272
|
$documentation: "A class definition",
|
2264
2273
|
}, AST_Class);
|
2265
2274
|
|
2275
|
+
var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", function AST_ClassStaticBlock (props) {
|
2276
|
+
this.body = props.body;
|
2277
|
+
this.block_scope = props.block_scope;
|
2278
|
+
this.start = props.start;
|
2279
|
+
this.end = props.end;
|
2280
|
+
}, {
|
2281
|
+
$documentation: "A block containing statements to be executed in the context of the class",
|
2282
|
+
$propdoc: {
|
2283
|
+
body: "[AST_Statement*] an array of statements",
|
2284
|
+
},
|
2285
|
+
_walk: function(visitor) {
|
2286
|
+
return visitor._visit(this, function() {
|
2287
|
+
walk_body(this, visitor);
|
2288
|
+
});
|
2289
|
+
},
|
2290
|
+
_children_backwards(push) {
|
2291
|
+
let i = this.body.length;
|
2292
|
+
while (i--) push(this.body[i]);
|
2293
|
+
},
|
2294
|
+
clone: clone_block_scope,
|
2295
|
+
}, AST_Scope);
|
2296
|
+
|
2266
2297
|
var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
|
2267
2298
|
if (props) {
|
2268
2299
|
this.name = props.name;
|
@@ -3063,6 +3094,7 @@ export {
|
|
3063
3094
|
AST_ClassExpression,
|
3064
3095
|
AST_ClassPrivateProperty,
|
3065
3096
|
AST_ClassProperty,
|
3097
|
+
AST_ClassStaticBlock,
|
3066
3098
|
AST_ConciseMethod,
|
3067
3099
|
AST_Conditional,
|
3068
3100
|
AST_Const,
|
package/lib/cli.js
CHANGED
@@ -279,7 +279,9 @@ export async function run_cli({ program, packageJson, fs, path }) {
|
|
279
279
|
result.enclosed = value.block_scope.enclosed;
|
280
280
|
}
|
281
281
|
value.CTOR.PROPS.forEach(function(prop) {
|
282
|
-
|
282
|
+
if (prop !== "block_scope") {
|
283
|
+
result[prop] = value[prop];
|
284
|
+
}
|
283
285
|
});
|
284
286
|
return result;
|
285
287
|
}
|
@@ -50,6 +50,7 @@ import {
|
|
50
50
|
AST_Call,
|
51
51
|
AST_Chain,
|
52
52
|
AST_Class,
|
53
|
+
AST_ClassStaticBlock,
|
53
54
|
AST_ClassProperty,
|
54
55
|
AST_ConciseMethod,
|
55
56
|
AST_Conditional,
|
@@ -156,6 +157,14 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
|
|
156
157
|
if (trimmed_extends)
|
157
158
|
with_effects.push(trimmed_extends);
|
158
159
|
for (const prop of this.properties) {
|
160
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
161
|
+
if (prop.body.some(stat => stat.has_side_effects(compressor))) {
|
162
|
+
return this;
|
163
|
+
} else {
|
164
|
+
continue;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
159
168
|
const trimmed_prop = prop.drop_side_effect_free(compressor);
|
160
169
|
if (trimmed_prop)
|
161
170
|
with_effects.push(trimmed_prop);
|
package/lib/compress/evaluate.js
CHANGED
@@ -46,7 +46,8 @@ import {
|
|
46
46
|
makePredicate,
|
47
47
|
return_this,
|
48
48
|
string_template,
|
49
|
-
regexp_source_fix
|
49
|
+
regexp_source_fix,
|
50
|
+
regexp_is_safe,
|
50
51
|
} from "../utils/index.js";
|
51
52
|
import {
|
52
53
|
AST_Array,
|
@@ -129,7 +130,7 @@ def_eval(AST_BigInt, return_this);
|
|
129
130
|
|
130
131
|
def_eval(AST_RegExp, function (compressor) {
|
131
132
|
let evaluated = compressor.evaluated_regexps.get(this.value);
|
132
|
-
if (evaluated === undefined) {
|
133
|
+
if (evaluated === undefined && regexp_is_safe(this.value.source)) {
|
133
134
|
try {
|
134
135
|
const { source, flags } = this.value;
|
135
136
|
evaluated = new RegExp(source, flags);
|
@@ -342,7 +343,7 @@ const regexp_flags = new Set([
|
|
342
343
|
]);
|
343
344
|
|
344
345
|
def_eval(AST_PropAccess, function (compressor, depth) {
|
345
|
-
|
346
|
+
let obj = this.expression._eval(compressor, depth + 1);
|
346
347
|
if (obj === nullish || (this.optional && obj == null)) return nullish;
|
347
348
|
if (compressor.option("unsafe")) {
|
348
349
|
var key = this.property;
|
@@ -352,7 +353,6 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
352
353
|
return this;
|
353
354
|
}
|
354
355
|
var exp = this.expression;
|
355
|
-
var val;
|
356
356
|
if (is_undeclared_ref(exp)) {
|
357
357
|
|
358
358
|
var aa;
|
@@ -369,29 +369,29 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
369
369
|
}
|
370
370
|
if (!is_pure_native_value(exp.name, key))
|
371
371
|
return this;
|
372
|
-
|
372
|
+
obj = global_objs[exp.name];
|
373
373
|
} else {
|
374
|
-
|
375
|
-
if (val instanceof RegExp) {
|
374
|
+
if (obj instanceof RegExp) {
|
376
375
|
if (key == "source") {
|
377
|
-
return regexp_source_fix(
|
376
|
+
return regexp_source_fix(obj.source);
|
378
377
|
} else if (key == "flags" || regexp_flags.has(key)) {
|
379
|
-
return
|
378
|
+
return obj[key];
|
380
379
|
}
|
381
380
|
}
|
382
|
-
if (!
|
381
|
+
if (!obj || obj === exp || !HOP(obj, key))
|
383
382
|
return this;
|
384
|
-
|
383
|
+
|
384
|
+
if (typeof obj == "function")
|
385
385
|
switch (key) {
|
386
386
|
case "name":
|
387
|
-
return
|
387
|
+
return obj.node.name ? obj.node.name.name : "";
|
388
388
|
case "length":
|
389
|
-
return
|
389
|
+
return obj.node.length_property();
|
390
390
|
default:
|
391
391
|
return this;
|
392
392
|
}
|
393
393
|
}
|
394
|
-
return
|
394
|
+
return obj[key];
|
395
395
|
}
|
396
396
|
return this;
|
397
397
|
});
|
package/lib/compress/index.js
CHANGED
@@ -58,6 +58,7 @@ import {
|
|
58
58
|
AST_Class,
|
59
59
|
AST_ClassExpression,
|
60
60
|
AST_ClassProperty,
|
61
|
+
AST_ClassStaticBlock,
|
61
62
|
AST_ConciseMethod,
|
62
63
|
AST_Conditional,
|
63
64
|
AST_Const,
|
@@ -158,6 +159,7 @@ import {
|
|
158
159
|
return_true,
|
159
160
|
regexp_source_fix,
|
160
161
|
has_annotation,
|
162
|
+
regexp_is_safe,
|
161
163
|
} from "../utils/index.js";
|
162
164
|
import { first_in_statement } from "../utils/first_in_statement.js";
|
163
165
|
import { equivalent_to } from "../equivalent-to.js";
|
@@ -832,18 +834,13 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
|
|
832
834
|
}
|
833
835
|
if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
|
834
836
|
const def = node.name.definition();
|
835
|
-
|
836
|
-
|
837
|
+
const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
|
838
|
+
// Class "extends" and static blocks may have side effects
|
839
|
+
const has_side_effects = !keep
|
840
|
+
&& node instanceof AST_Class
|
841
|
+
&& node.has_side_effects(compressor);
|
842
|
+
if (!keep && !has_side_effects) {
|
837
843
|
def.eliminated++;
|
838
|
-
if (node instanceof AST_DefClass) {
|
839
|
-
// Classes might have extends with side effects
|
840
|
-
const side_effects = node.drop_side_effect_free(compressor);
|
841
|
-
if (side_effects) {
|
842
|
-
return make_node(AST_SimpleStatement, node, {
|
843
|
-
body: side_effects
|
844
|
-
});
|
845
|
-
}
|
846
|
-
}
|
847
844
|
return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
|
848
845
|
}
|
849
846
|
}
|
@@ -2140,6 +2137,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
2140
2137
|
params.push(value);
|
2141
2138
|
return arg !== value;
|
2142
2139
|
})
|
2140
|
+
&& regexp_is_safe(params[0])
|
2143
2141
|
) {
|
2144
2142
|
let [ source, flags ] = params;
|
2145
2143
|
source = regexp_source_fix(new RegExp(source).source);
|
@@ -3799,6 +3797,12 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
3799
3797
|
const sub = self.flatten_object(self.property, compressor);
|
3800
3798
|
if (sub) return sub.optimize(compressor);
|
3801
3799
|
}
|
3800
|
+
|
3801
|
+
if (self.expression instanceof AST_PropAccess
|
3802
|
+
&& parent instanceof AST_PropAccess) {
|
3803
|
+
return self;
|
3804
|
+
}
|
3805
|
+
|
3802
3806
|
let ev = self.evaluate(compressor);
|
3803
3807
|
if (ev !== self) {
|
3804
3808
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
@@ -3915,6 +3919,11 @@ def_optimize(AST_Class, function(self) {
|
|
3915
3919
|
return self;
|
3916
3920
|
});
|
3917
3921
|
|
3922
|
+
def_optimize(AST_ClassStaticBlock, function(self, compressor) {
|
3923
|
+
tighten_body(self.body, compressor);
|
3924
|
+
return self;
|
3925
|
+
});
|
3926
|
+
|
3918
3927
|
def_optimize(AST_Yield, function(self, compressor) {
|
3919
3928
|
if (self.expression && !self.is_star && is_undefined(self.expression, compressor)) {
|
3920
3929
|
self.expression = null;
|
@@ -52,6 +52,8 @@ import {
|
|
52
52
|
AST_Case,
|
53
53
|
AST_Chain,
|
54
54
|
AST_Class,
|
55
|
+
AST_DefClass,
|
56
|
+
AST_ClassStaticBlock,
|
55
57
|
AST_ClassProperty,
|
56
58
|
AST_ConciseMethod,
|
57
59
|
AST_Conditional,
|
@@ -320,6 +322,9 @@ export function is_nullish(node, compressor) {
|
|
320
322
|
}
|
321
323
|
return any(this.properties, compressor);
|
322
324
|
});
|
325
|
+
def_has_side_effects(AST_ClassStaticBlock, function(compressor) {
|
326
|
+
return any(this.body, compressor);
|
327
|
+
});
|
323
328
|
def_has_side_effects(AST_Binary, function(compressor) {
|
324
329
|
return this.left.has_side_effects(compressor)
|
325
330
|
|| this.right.has_side_effects(compressor);
|
@@ -419,6 +424,9 @@ export function is_nullish(node, compressor) {
|
|
419
424
|
if (this.extends && this.extends.may_throw(compressor)) return true;
|
420
425
|
return any(this.properties, compressor);
|
421
426
|
});
|
427
|
+
def_may_throw(AST_ClassStaticBlock, function (compressor) {
|
428
|
+
return any(this.body, compressor);
|
429
|
+
});
|
422
430
|
|
423
431
|
def_may_throw(AST_Array, function(compressor) {
|
424
432
|
return any(this.elements, compressor);
|
@@ -587,6 +595,9 @@ export function is_nullish(node, compressor) {
|
|
587
595
|
if (prop.static && prop.value && !prop.value.is_constant_expression(scope)) {
|
588
596
|
return false;
|
589
597
|
}
|
598
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
599
|
+
return false;
|
600
|
+
}
|
590
601
|
}
|
591
602
|
|
592
603
|
return all_refs_local.call(this, scope);
|
@@ -910,9 +921,18 @@ export const aborts = (thing) => thing && thing.aborts();
|
|
910
921
|
}
|
911
922
|
return null;
|
912
923
|
}
|
913
|
-
def_aborts(AST_Import,
|
924
|
+
def_aborts(AST_Import, return_null);
|
914
925
|
def_aborts(AST_BlockStatement, block_aborts);
|
915
926
|
def_aborts(AST_SwitchBranch, block_aborts);
|
927
|
+
def_aborts(AST_DefClass, function () {
|
928
|
+
for (const prop of this.properties) {
|
929
|
+
if (prop instanceof AST_ClassStaticBlock) {
|
930
|
+
if (prop.aborts()) return prop;
|
931
|
+
}
|
932
|
+
}
|
933
|
+
return null;
|
934
|
+
});
|
935
|
+
def_aborts(AST_ClassStaticBlock, block_aborts);
|
916
936
|
def_aborts(AST_If, function() {
|
917
937
|
return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
|
918
938
|
});
|
package/lib/compress/inline.js
CHANGED
@@ -335,6 +335,7 @@ export function inline_into_call(self, fn, compressor) {
|
|
335
335
|
fn.argnames.length === 1
|
336
336
|
&& (fn.argnames[0] instanceof AST_SymbolFunarg)
|
337
337
|
&& self.args.length < 2
|
338
|
+
&& !(self.args[0] instanceof AST_Expansion)
|
338
339
|
&& returned instanceof AST_SymbolRef
|
339
340
|
&& returned.name === fn.argnames[0].name
|
340
341
|
) {
|
@@ -52,6 +52,7 @@ import {
|
|
52
52
|
AST_Case,
|
53
53
|
AST_Chain,
|
54
54
|
AST_Class,
|
55
|
+
AST_ClassStaticBlock,
|
55
56
|
AST_ClassExpression,
|
56
57
|
AST_Conditional,
|
57
58
|
AST_Default,
|
@@ -377,6 +378,10 @@ def_reduce_vars(AST_Class, function(tw, descend) {
|
|
377
378
|
return true;
|
378
379
|
});
|
379
380
|
|
381
|
+
def_reduce_vars(AST_ClassStaticBlock, function(tw, descend, compressor) {
|
382
|
+
reset_block_variables(compressor, this);
|
383
|
+
});
|
384
|
+
|
380
385
|
def_reduce_vars(AST_Conditional, function(tw) {
|
381
386
|
this.condition.walk(tw);
|
382
387
|
push(tw);
|
package/lib/mozilla-ast.js
CHANGED
@@ -60,6 +60,7 @@ import {
|
|
60
60
|
AST_Catch,
|
61
61
|
AST_Chain,
|
62
62
|
AST_Class,
|
63
|
+
AST_ClassStaticBlock,
|
63
64
|
AST_ClassExpression,
|
64
65
|
AST_ClassProperty,
|
65
66
|
AST_ClassPrivateProperty,
|
@@ -444,6 +445,14 @@ import { is_basic_identifier_string } from "./parse.js";
|
|
444
445
|
});
|
445
446
|
},
|
446
447
|
|
448
|
+
StaticBlock: function(M) {
|
449
|
+
return new AST_ClassStaticBlock({
|
450
|
+
start : my_start_token(M),
|
451
|
+
end : my_end_token(M),
|
452
|
+
body : M.body.map(from_moz),
|
453
|
+
});
|
454
|
+
},
|
455
|
+
|
447
456
|
ArrayExpression: function(M) {
|
448
457
|
return new AST_Array({
|
449
458
|
start : my_start_token(M),
|
@@ -1583,6 +1592,13 @@ import { is_basic_identifier_string } from "./parse.js";
|
|
1583
1592
|
};
|
1584
1593
|
});
|
1585
1594
|
|
1595
|
+
def_to_moz(AST_ClassStaticBlock, function To_Moz_StaticBlock(M) {
|
1596
|
+
return {
|
1597
|
+
type: "StaticBlock",
|
1598
|
+
body: M.body.map(to_moz),
|
1599
|
+
};
|
1600
|
+
});
|
1601
|
+
|
1586
1602
|
def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {
|
1587
1603
|
return {
|
1588
1604
|
type: "MetaProperty",
|
package/lib/output.js
CHANGED
@@ -70,6 +70,7 @@ import {
|
|
70
70
|
AST_ClassExpression,
|
71
71
|
AST_ClassPrivateProperty,
|
72
72
|
AST_ClassProperty,
|
73
|
+
AST_ClassStaticBlock,
|
73
74
|
AST_ConciseMethod,
|
74
75
|
AST_PrivateGetter,
|
75
76
|
AST_PrivateMethod,
|
@@ -1247,12 +1248,14 @@ function OutputStream(options) {
|
|
1247
1248
|
output.with_indent(output.next_indent(), function() {
|
1248
1249
|
output.append_comments(self, true);
|
1249
1250
|
});
|
1251
|
+
output.add_mapping(self.end);
|
1250
1252
|
output.print("}");
|
1251
1253
|
}
|
1252
1254
|
function print_braced(self, output, allow_directives) {
|
1253
1255
|
if (self.body.length > 0) {
|
1254
1256
|
output.with_block(function() {
|
1255
1257
|
display_body(self.body, false, output, allow_directives);
|
1258
|
+
output.add_mapping(self.end);
|
1256
1259
|
});
|
1257
1260
|
} else print_braced_empty(self, output);
|
1258
1261
|
}
|
@@ -2192,6 +2195,11 @@ function OutputStream(options) {
|
|
2192
2195
|
}
|
2193
2196
|
self._print_getter_setter(type, false, output);
|
2194
2197
|
});
|
2198
|
+
DEFPRINT(AST_ClassStaticBlock, function (self, output) {
|
2199
|
+
output.print("static");
|
2200
|
+
output.space();
|
2201
|
+
print_braced(self, output);
|
2202
|
+
});
|
2195
2203
|
AST_Symbol.DEFMETHOD("_do_print", function(output) {
|
2196
2204
|
var def = this.definition();
|
2197
2205
|
output.print_name(def ? def.mangled_name || def.name : this.name);
|
package/lib/parse.js
CHANGED
@@ -67,6 +67,7 @@ import {
|
|
67
67
|
AST_ClassExpression,
|
68
68
|
AST_ClassPrivateProperty,
|
69
69
|
AST_ClassProperty,
|
70
|
+
AST_ClassStaticBlock,
|
70
71
|
AST_ConciseMethod,
|
71
72
|
AST_PrivateGetter,
|
72
73
|
AST_PrivateMethod,
|
@@ -162,7 +163,7 @@ import {
|
|
162
163
|
} from "./ast.js";
|
163
164
|
|
164
165
|
var LATEST_RAW = ""; // Only used for numbers and template strings
|
165
|
-
var
|
166
|
+
var TEMPLATE_RAWS = new Map(); // Raw template strings
|
166
167
|
|
167
168
|
var KEYWORDS = "break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with";
|
168
169
|
var KEYWORDS_ATOM = "false null true";
|
@@ -693,8 +694,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
693
694
|
next(true, true);
|
694
695
|
S.brace_counter++;
|
695
696
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
696
|
-
|
697
|
-
|
697
|
+
TEMPLATE_RAWS.set(tok, raw);
|
698
|
+
tok.template_end = false;
|
698
699
|
return tok;
|
699
700
|
}
|
700
701
|
|
@@ -710,8 +711,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
710
711
|
}
|
711
712
|
S.template_braces.pop();
|
712
713
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
713
|
-
|
714
|
-
|
714
|
+
TEMPLATE_RAWS.set(tok, raw);
|
715
|
+
tok.template_end = true;
|
715
716
|
return tok;
|
716
717
|
});
|
717
718
|
|
@@ -2367,19 +2368,19 @@ function parse($TEXT, options) {
|
|
2367
2368
|
|
2368
2369
|
segments.push(new AST_TemplateSegment({
|
2369
2370
|
start: S.token,
|
2370
|
-
raw:
|
2371
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2371
2372
|
value: S.token.value,
|
2372
2373
|
end: S.token
|
2373
2374
|
}));
|
2374
2375
|
|
2375
|
-
while (!
|
2376
|
+
while (!S.token.template_end) {
|
2376
2377
|
next();
|
2377
2378
|
handle_regexp();
|
2378
2379
|
segments.push(expression(true));
|
2379
2380
|
|
2380
2381
|
segments.push(new AST_TemplateSegment({
|
2381
2382
|
start: S.token,
|
2382
|
-
raw:
|
2383
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2383
2384
|
value: S.token.value,
|
2384
2385
|
end: S.token
|
2385
2386
|
}));
|
@@ -2562,6 +2563,10 @@ function parse($TEXT, options) {
|
|
2562
2563
|
var accessor_type = null;
|
2563
2564
|
|
2564
2565
|
if (is_class && name === "static" && is_not_method_start()) {
|
2566
|
+
const static_block = class_static_block();
|
2567
|
+
if (static_block != null) {
|
2568
|
+
return static_block;
|
2569
|
+
}
|
2565
2570
|
is_static = true;
|
2566
2571
|
name = as_property_name();
|
2567
2572
|
}
|
@@ -2668,6 +2673,25 @@ function parse($TEXT, options) {
|
|
2668
2673
|
}
|
2669
2674
|
}
|
2670
2675
|
|
2676
|
+
function class_static_block() {
|
2677
|
+
if (!is("punc", "{")) {
|
2678
|
+
return null;
|
2679
|
+
}
|
2680
|
+
|
2681
|
+
const start = S.token;
|
2682
|
+
const body = [];
|
2683
|
+
|
2684
|
+
next();
|
2685
|
+
|
2686
|
+
while (!is("punc", "}")) {
|
2687
|
+
body.push(statement());
|
2688
|
+
}
|
2689
|
+
|
2690
|
+
next();
|
2691
|
+
|
2692
|
+
return new AST_ClassStaticBlock({ start, body, end: prev() });
|
2693
|
+
}
|
2694
|
+
|
2671
2695
|
function maybe_import_assertion() {
|
2672
2696
|
if (is("name", "assert") && !has_newline_before(S.token)) {
|
2673
2697
|
next();
|
@@ -3342,6 +3366,7 @@ function parse($TEXT, options) {
|
|
3342
3366
|
} else {
|
3343
3367
|
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
|
3344
3368
|
}
|
3369
|
+
TEMPLATE_RAWS = new Map();
|
3345
3370
|
return toplevel;
|
3346
3371
|
})();
|
3347
3372
|
|
package/lib/size.js
CHANGED
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
AST_Call,
|
11
11
|
AST_Case,
|
12
12
|
AST_Class,
|
13
|
+
AST_ClassStaticBlock,
|
13
14
|
AST_ClassPrivateProperty,
|
14
15
|
AST_ClassProperty,
|
15
16
|
AST_ConciseMethod,
|
@@ -401,6 +402,11 @@ AST_Class.prototype._size = function () {
|
|
401
402
|
);
|
402
403
|
};
|
403
404
|
|
405
|
+
AST_ClassStaticBlock.prototype._size = function () {
|
406
|
+
// "class{}" + semicolons
|
407
|
+
return 7 + list_overhead(this.body);
|
408
|
+
};
|
409
|
+
|
404
410
|
AST_ClassProperty.prototype._size = function () {
|
405
411
|
return (
|
406
412
|
static_size(this.static)
|
package/lib/transform.js
CHANGED
@@ -53,6 +53,7 @@ import {
|
|
53
53
|
AST_Catch,
|
54
54
|
AST_Chain,
|
55
55
|
AST_Class,
|
56
|
+
AST_ClassStaticBlock,
|
56
57
|
AST_Conditional,
|
57
58
|
AST_Definitions,
|
58
59
|
AST_Destructuring,
|
@@ -285,6 +286,10 @@ def_transform(AST_Class, function(self, tw) {
|
|
285
286
|
self.properties = do_list(self.properties, tw);
|
286
287
|
});
|
287
288
|
|
289
|
+
def_transform(AST_ClassStaticBlock, function(self, tw) {
|
290
|
+
self.body = do_list(self.body, tw);
|
291
|
+
});
|
292
|
+
|
288
293
|
def_transform(AST_Expansion, function(self, tw) {
|
289
294
|
self.expression = self.expression.transform(tw);
|
290
295
|
});
|
package/lib/utils/index.js
CHANGED
@@ -249,7 +249,15 @@ function regexp_source_fix(source) {
|
|
249
249
|
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
|
250
250
|
});
|
251
251
|
}
|
252
|
-
|
252
|
+
|
253
|
+
// Subset of regexps that is not going to cause regexp based DDOS
|
254
|
+
// https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
|
255
|
+
const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;
|
256
|
+
|
257
|
+
/** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
|
258
|
+
export const regexp_is_safe = (source) => re_safe_regexp.test(source);
|
259
|
+
|
260
|
+
const all_flags = "dgimsuy";
|
253
261
|
function sort_regexp_flags(flags) {
|
254
262
|
const existing_flags = new Set(flags.split(""));
|
255
263
|
let out = "";
|
package/package.json
CHANGED
package/tools/domprops.js
CHANGED
@@ -6021,6 +6021,7 @@ export var domprops = [
|
|
6021
6021
|
"outlineStyle",
|
6022
6022
|
"outlineWidth",
|
6023
6023
|
"outputBuffer",
|
6024
|
+
"outputChannelCount",
|
6024
6025
|
"outputLatency",
|
6025
6026
|
"outputs",
|
6026
6027
|
"overflow",
|
@@ -6108,6 +6109,7 @@ export var domprops = [
|
|
6108
6109
|
"palette",
|
6109
6110
|
"pan",
|
6110
6111
|
"panningModel",
|
6112
|
+
"parameterData",
|
6111
6113
|
"parameters",
|
6112
6114
|
"parent",
|
6113
6115
|
"parentElement",
|
@@ -6283,6 +6285,7 @@ export var domprops = [
|
|
6283
6285
|
"processIceMessage",
|
6284
6286
|
"processingEnd",
|
6285
6287
|
"processingStart",
|
6288
|
+
"processorOptions",
|
6286
6289
|
"product",
|
6287
6290
|
"productId",
|
6288
6291
|
"productName",
|