terser 5.13.1 → 5.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/bundle.min.js +174 -75
- package/lib/ast.js +10 -11
- package/lib/compress/evaluate.js +14 -14
- package/lib/compress/index.js +8 -0
- package/lib/minify.js +47 -14
- package/lib/output.js +19 -0
- package/lib/parse.js +9 -8
- package/lib/sourcemap.js +60 -26
- package/lib/utils/index.js +9 -1
- package/package.json +5 -3
- package/tools/domprops.js +1 -0
- package/tools/terser.d.ts +6 -3
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## v5.14.2
|
4
|
+
|
5
|
+
- Security fix for RegExps that should not be evaluated (regexp DDOS)
|
6
|
+
- Source maps improvements (#1211)
|
7
|
+
- Performance improvements in long property access evaluation (#1213)
|
8
|
+
|
9
|
+
## v5.14.1
|
10
|
+
- keep_numbers option added to TypeScript defs (#1208)
|
11
|
+
- Fixed parsing of nested template strings (#1204)
|
12
|
+
|
13
|
+
## v5.14.0
|
14
|
+
- Switched to @jridgewell/source-map for sourcemap generation (#1190, #1181)
|
15
|
+
- Fixed source maps with non-terminated segments (#1106)
|
16
|
+
- Enabled typescript types to be imported from the package (#1194)
|
17
|
+
- Extra DOM props have been added (#1191)
|
18
|
+
- Delete the AST while generating code, as a means to save RAM
|
19
|
+
|
3
20
|
## v5.13.1
|
4
21
|
- Removed self-assignments (`varname=varname`) (closes #1081)
|
5
22
|
- Separated inlining code (for inlining things into references, or removing IIFEs)
|
@@ -195,6 +212,13 @@ Hotfix release, fixes package.json "engines" syntax
|
|
195
212
|
- Module is now distributed as a dual package - You can `import` and `require()` too.
|
196
213
|
- Inline improvements were made
|
197
214
|
|
215
|
+
|
216
|
+
-----
|
217
|
+
|
218
|
+
## v4.8.1 (backport)
|
219
|
+
|
220
|
+
- Security fix for RegExps that should not be evaluated (regexp DDOS)
|
221
|
+
|
198
222
|
## v4.8.0
|
199
223
|
|
200
224
|
- Support for numeric separators (`million = 1_000_000`) was added.
|
package/dist/bundle.min.js
CHANGED
@@ -1,12 +1,8 @@
|
|
1
1
|
(function (global, factory) {
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('source-map')) :
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'source-map'], factory) :
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@jridgewell/source-map')) :
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@jridgewell/source-map'], factory) :
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Terser = {}, global.sourceMap));
|
5
|
-
}(this, (function (exports,
|
6
|
-
|
7
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
8
|
-
|
9
|
-
var MOZ_SourceMap__default = /*#__PURE__*/_interopDefaultLegacy(MOZ_SourceMap);
|
5
|
+
}(this, (function (exports, sourceMap) { 'use strict';
|
10
6
|
|
11
7
|
/***********************************************************************
|
12
8
|
|
@@ -257,7 +253,15 @@ function regexp_source_fix(source) {
|
|
257
253
|
return (escaped ? "" : "\\") + lineTerminatorEscape[match];
|
258
254
|
});
|
259
255
|
}
|
260
|
-
|
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";
|
261
265
|
function sort_regexp_flags(flags) {
|
262
266
|
const existing_flags = new Set(flags.split(""));
|
263
267
|
let out = "";
|
@@ -327,7 +331,7 @@ function set_annotation(node, annotation) {
|
|
327
331
|
***********************************************************************/
|
328
332
|
|
329
333
|
var LATEST_RAW = ""; // Only used for numbers and template strings
|
330
|
-
var
|
334
|
+
var TEMPLATE_RAWS = new Map(); // Raw template strings
|
331
335
|
|
332
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";
|
333
337
|
var KEYWORDS_ATOM = "false null true";
|
@@ -858,8 +862,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
858
862
|
next(true, true);
|
859
863
|
S.brace_counter++;
|
860
864
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
861
|
-
|
862
|
-
|
865
|
+
TEMPLATE_RAWS.set(tok, raw);
|
866
|
+
tok.template_end = false;
|
863
867
|
return tok;
|
864
868
|
}
|
865
869
|
|
@@ -875,8 +879,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
875
879
|
}
|
876
880
|
S.template_braces.pop();
|
877
881
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
878
|
-
|
879
|
-
|
882
|
+
TEMPLATE_RAWS.set(tok, raw);
|
883
|
+
tok.template_end = true;
|
880
884
|
return tok;
|
881
885
|
});
|
882
886
|
|
@@ -2532,19 +2536,19 @@ function parse($TEXT, options) {
|
|
2532
2536
|
|
2533
2537
|
segments.push(new AST_TemplateSegment({
|
2534
2538
|
start: S.token,
|
2535
|
-
raw:
|
2539
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2536
2540
|
value: S.token.value,
|
2537
2541
|
end: S.token
|
2538
2542
|
}));
|
2539
2543
|
|
2540
|
-
while (!
|
2544
|
+
while (!S.token.template_end) {
|
2541
2545
|
next();
|
2542
2546
|
handle_regexp();
|
2543
2547
|
segments.push(expression(true));
|
2544
2548
|
|
2545
2549
|
segments.push(new AST_TemplateSegment({
|
2546
2550
|
start: S.token,
|
2547
|
-
raw:
|
2551
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2548
2552
|
value: S.token.value,
|
2549
2553
|
end: S.token
|
2550
2554
|
}));
|
@@ -3507,6 +3511,7 @@ function parse($TEXT, options) {
|
|
3507
3511
|
} else {
|
3508
3512
|
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
|
3509
3513
|
}
|
3514
|
+
TEMPLATE_RAWS = new Map();
|
3510
3515
|
return toplevel;
|
3511
3516
|
})();
|
3512
3517
|
|
@@ -3600,6 +3605,7 @@ const set_tok_flag = (tok, flag, truth) => {
|
|
3600
3605
|
const TOK_FLAG_NLB = 0b0001;
|
3601
3606
|
const TOK_FLAG_QUOTE_SINGLE = 0b0010;
|
3602
3607
|
const TOK_FLAG_QUOTE_EXISTS = 0b0100;
|
3608
|
+
const TOK_FLAG_TEMPLATE_END = 0b1000;
|
3603
3609
|
|
3604
3610
|
class AST_Token {
|
3605
3611
|
constructor(type, value, line, col, pos, nlb, comments_before, comments_after, file) {
|
@@ -3635,6 +3641,14 @@ class AST_Token {
|
|
3635
3641
|
set_tok_flag(this, TOK_FLAG_QUOTE_SINGLE, quote_type === "'");
|
3636
3642
|
set_tok_flag(this, TOK_FLAG_QUOTE_EXISTS, !!quote_type);
|
3637
3643
|
}
|
3644
|
+
|
3645
|
+
get template_end() {
|
3646
|
+
return has_tok_flag(this, TOK_FLAG_TEMPLATE_END);
|
3647
|
+
}
|
3648
|
+
|
3649
|
+
set template_end(new_template_end) {
|
3650
|
+
set_tok_flag(this, TOK_FLAG_TEMPLATE_END, new_template_end);
|
3651
|
+
}
|
3638
3652
|
}
|
3639
3653
|
|
3640
3654
|
var AST_Node = DEFNODE("Node", "start end", function AST_Node(props) {
|
@@ -4059,11 +4073,10 @@ var AST_With = DEFNODE("With", "expression", function AST_With(props) {
|
|
4059
4073
|
|
4060
4074
|
var AST_Scope = DEFNODE(
|
4061
4075
|
"Scope",
|
4062
|
-
"variables
|
4076
|
+
"variables uses_with uses_eval parent_scope enclosed cname",
|
4063
4077
|
function AST_Scope(props) {
|
4064
4078
|
if (props) {
|
4065
4079
|
this.variables = props.variables;
|
4066
|
-
this.functions = props.functions;
|
4067
4080
|
this.uses_with = props.uses_with;
|
4068
4081
|
this.uses_eval = props.uses_eval;
|
4069
4082
|
this.parent_scope = props.parent_scope;
|
@@ -4119,7 +4132,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
|
|
4119
4132
|
if (props) {
|
4120
4133
|
this.globals = props.globals;
|
4121
4134
|
this.variables = props.variables;
|
4122
|
-
this.functions = props.functions;
|
4123
4135
|
this.uses_with = props.uses_with;
|
4124
4136
|
this.uses_eval = props.uses_eval;
|
4125
4137
|
this.parent_scope = props.parent_scope;
|
@@ -4201,7 +4213,6 @@ var AST_Lambda = DEFNODE(
|
|
4201
4213
|
this.is_generator = props.is_generator;
|
4202
4214
|
this.async = props.async;
|
4203
4215
|
this.variables = props.variables;
|
4204
|
-
this.functions = props.functions;
|
4205
4216
|
this.uses_with = props.uses_with;
|
4206
4217
|
this.uses_eval = props.uses_eval;
|
4207
4218
|
this.parent_scope = props.parent_scope;
|
@@ -4281,7 +4292,6 @@ var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
|
|
4281
4292
|
this.is_generator = props.is_generator;
|
4282
4293
|
this.async = props.async;
|
4283
4294
|
this.variables = props.variables;
|
4284
|
-
this.functions = props.functions;
|
4285
4295
|
this.uses_with = props.uses_with;
|
4286
4296
|
this.uses_eval = props.uses_eval;
|
4287
4297
|
this.parent_scope = props.parent_scope;
|
@@ -4306,7 +4316,6 @@ var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
|
|
4306
4316
|
this.is_generator = props.is_generator;
|
4307
4317
|
this.async = props.async;
|
4308
4318
|
this.variables = props.variables;
|
4309
|
-
this.functions = props.functions;
|
4310
4319
|
this.uses_with = props.uses_with;
|
4311
4320
|
this.uses_eval = props.uses_eval;
|
4312
4321
|
this.parent_scope = props.parent_scope;
|
@@ -4331,7 +4340,6 @@ var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
|
|
4331
4340
|
this.is_generator = props.is_generator;
|
4332
4341
|
this.async = props.async;
|
4333
4342
|
this.variables = props.variables;
|
4334
|
-
this.functions = props.functions;
|
4335
4343
|
this.uses_with = props.uses_with;
|
4336
4344
|
this.uses_eval = props.uses_eval;
|
4337
4345
|
this.parent_scope = props.parent_scope;
|
@@ -4356,7 +4364,6 @@ var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
|
|
4356
4364
|
this.is_generator = props.is_generator;
|
4357
4365
|
this.async = props.async;
|
4358
4366
|
this.variables = props.variables;
|
4359
|
-
this.functions = props.functions;
|
4360
4367
|
this.uses_with = props.uses_with;
|
4361
4368
|
this.uses_eval = props.uses_eval;
|
4362
4369
|
this.parent_scope = props.parent_scope;
|
@@ -5668,7 +5675,6 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
|
|
5668
5675
|
this.extends = props.extends;
|
5669
5676
|
this.properties = props.properties;
|
5670
5677
|
this.variables = props.variables;
|
5671
|
-
this.functions = props.functions;
|
5672
5678
|
this.uses_with = props.uses_with;
|
5673
5679
|
this.uses_eval = props.uses_eval;
|
5674
5680
|
this.parent_scope = props.parent_scope;
|
@@ -5762,7 +5768,6 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
|
|
5762
5768
|
this.extends = props.extends;
|
5763
5769
|
this.properties = props.properties;
|
5764
5770
|
this.variables = props.variables;
|
5765
|
-
this.functions = props.functions;
|
5766
5771
|
this.uses_with = props.uses_with;
|
5767
5772
|
this.uses_eval = props.uses_eval;
|
5768
5773
|
this.parent_scope = props.parent_scope;
|
@@ -5785,7 +5790,6 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExp
|
|
5785
5790
|
this.extends = props.extends;
|
5786
5791
|
this.properties = props.properties;
|
5787
5792
|
this.variables = props.variables;
|
5788
|
-
this.functions = props.functions;
|
5789
5793
|
this.uses_with = props.uses_with;
|
5790
5794
|
this.uses_eval = props.uses_eval;
|
5791
5795
|
this.parent_scope = props.parent_scope;
|
@@ -8644,6 +8648,8 @@ function OutputStream(options) {
|
|
8644
8648
|
width : 80,
|
8645
8649
|
wrap_iife : false,
|
8646
8650
|
wrap_func_args : true,
|
8651
|
+
|
8652
|
+
_destroy_ast : false
|
8647
8653
|
}, true);
|
8648
8654
|
|
8649
8655
|
if (options.shorthand === undefined)
|
@@ -9193,6 +9199,18 @@ function OutputStream(options) {
|
|
9193
9199
|
if (OUTPUT.length() > insert) newline_insert = insert;
|
9194
9200
|
}
|
9195
9201
|
|
9202
|
+
/**
|
9203
|
+
* When output.option("_destroy_ast") is enabled, destroy the function.
|
9204
|
+
* Call this after printing it.
|
9205
|
+
*/
|
9206
|
+
const gc_scope =
|
9207
|
+
options["_destroy_ast"]
|
9208
|
+
? function gc_scope(scope) {
|
9209
|
+
scope.body.length = 0;
|
9210
|
+
scope.argnames.length = 0;
|
9211
|
+
}
|
9212
|
+
: noop;
|
9213
|
+
|
9196
9214
|
var stack = [];
|
9197
9215
|
return {
|
9198
9216
|
get : get,
|
@@ -9239,6 +9257,7 @@ function OutputStream(options) {
|
|
9239
9257
|
with_square : with_square,
|
9240
9258
|
add_mapping : add_mapping,
|
9241
9259
|
option : function(opt) { return options[opt]; },
|
9260
|
+
gc_scope,
|
9242
9261
|
printed_comments: printed_comments,
|
9243
9262
|
prepend_comments: readonly ? noop : prepend_comments,
|
9244
9263
|
append_comments : readonly || comment_filter === return_false ? noop : append_comments,
|
@@ -9629,12 +9648,14 @@ function OutputStream(options) {
|
|
9629
9648
|
output.with_indent(output.next_indent(), function() {
|
9630
9649
|
output.append_comments(self, true);
|
9631
9650
|
});
|
9651
|
+
output.add_mapping(self.end);
|
9632
9652
|
output.print("}");
|
9633
9653
|
}
|
9634
9654
|
function print_braced(self, output, allow_directives) {
|
9635
9655
|
if (self.body.length > 0) {
|
9636
9656
|
output.with_block(function() {
|
9637
9657
|
display_body(self.body, false, output, allow_directives);
|
9658
|
+
output.add_mapping(self.end);
|
9638
9659
|
});
|
9639
9660
|
} else print_braced_empty(self, output);
|
9640
9661
|
}
|
@@ -9755,6 +9776,7 @@ function OutputStream(options) {
|
|
9755
9776
|
});
|
9756
9777
|
DEFPRINT(AST_Lambda, function(self, output) {
|
9757
9778
|
self._do_print(output);
|
9779
|
+
output.gc_scope(self);
|
9758
9780
|
});
|
9759
9781
|
|
9760
9782
|
DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
|
@@ -9834,6 +9856,7 @@ function OutputStream(options) {
|
|
9834
9856
|
print_braced(self, output);
|
9835
9857
|
}
|
9836
9858
|
if (needs_parens) { output.print(")"); }
|
9859
|
+
output.gc_scope(self);
|
9837
9860
|
});
|
9838
9861
|
|
9839
9862
|
/* -----[ exits ]----- */
|
@@ -13838,7 +13861,7 @@ def_eval(AST_BigInt, return_this);
|
|
13838
13861
|
|
13839
13862
|
def_eval(AST_RegExp, function (compressor) {
|
13840
13863
|
let evaluated = compressor.evaluated_regexps.get(this.value);
|
13841
|
-
if (evaluated === undefined) {
|
13864
|
+
if (evaluated === undefined && regexp_is_safe(this.value.source)) {
|
13842
13865
|
try {
|
13843
13866
|
const { source, flags } = this.value;
|
13844
13867
|
evaluated = new RegExp(source, flags);
|
@@ -14051,7 +14074,7 @@ const regexp_flags = new Set([
|
|
14051
14074
|
]);
|
14052
14075
|
|
14053
14076
|
def_eval(AST_PropAccess, function (compressor, depth) {
|
14054
|
-
|
14077
|
+
let obj = this.expression._eval(compressor, depth + 1);
|
14055
14078
|
if (obj === nullish || (this.optional && obj == null)) return nullish;
|
14056
14079
|
if (compressor.option("unsafe")) {
|
14057
14080
|
var key = this.property;
|
@@ -14061,7 +14084,6 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
14061
14084
|
return this;
|
14062
14085
|
}
|
14063
14086
|
var exp = this.expression;
|
14064
|
-
var val;
|
14065
14087
|
if (is_undeclared_ref(exp)) {
|
14066
14088
|
|
14067
14089
|
var aa;
|
@@ -14078,29 +14100,29 @@ def_eval(AST_PropAccess, function (compressor, depth) {
|
|
14078
14100
|
}
|
14079
14101
|
if (!is_pure_native_value(exp.name, key))
|
14080
14102
|
return this;
|
14081
|
-
|
14103
|
+
obj = global_objs[exp.name];
|
14082
14104
|
} else {
|
14083
|
-
|
14084
|
-
if (val instanceof RegExp) {
|
14105
|
+
if (obj instanceof RegExp) {
|
14085
14106
|
if (key == "source") {
|
14086
|
-
return regexp_source_fix(
|
14107
|
+
return regexp_source_fix(obj.source);
|
14087
14108
|
} else if (key == "flags" || regexp_flags.has(key)) {
|
14088
|
-
return
|
14109
|
+
return obj[key];
|
14089
14110
|
}
|
14090
14111
|
}
|
14091
|
-
if (!
|
14112
|
+
if (!obj || obj === exp || !HOP(obj, key))
|
14092
14113
|
return this;
|
14093
|
-
|
14114
|
+
|
14115
|
+
if (typeof obj == "function")
|
14094
14116
|
switch (key) {
|
14095
14117
|
case "name":
|
14096
|
-
return
|
14118
|
+
return obj.node.name ? obj.node.name.name : "";
|
14097
14119
|
case "length":
|
14098
|
-
return
|
14120
|
+
return obj.node.length_property();
|
14099
14121
|
default:
|
14100
14122
|
return this;
|
14101
14123
|
}
|
14102
14124
|
}
|
14103
|
-
return
|
14125
|
+
return obj[key];
|
14104
14126
|
}
|
14105
14127
|
return this;
|
14106
14128
|
});
|
@@ -18979,6 +19001,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
18979
19001
|
params.push(value);
|
18980
19002
|
return arg !== value;
|
18981
19003
|
})
|
19004
|
+
&& regexp_is_safe(params[0])
|
18982
19005
|
) {
|
18983
19006
|
let [ source, flags ] = params;
|
18984
19007
|
source = regexp_source_fix(new RegExp(source).source);
|
@@ -20638,6 +20661,12 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
20638
20661
|
const sub = self.flatten_object(self.property, compressor);
|
20639
20662
|
if (sub) return sub.optimize(compressor);
|
20640
20663
|
}
|
20664
|
+
|
20665
|
+
if (self.expression instanceof AST_PropAccess
|
20666
|
+
&& parent instanceof AST_PropAccess) {
|
20667
|
+
return self;
|
20668
|
+
}
|
20669
|
+
|
20641
20670
|
let ev = self.evaluate(compressor);
|
20642
20671
|
if (ev !== self) {
|
20643
20672
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
@@ -21021,40 +21050,56 @@ def_optimize(AST_Destructuring, function(self, compressor) {
|
|
21021
21050
|
|
21022
21051
|
***********************************************************************/
|
21023
21052
|
|
21024
|
-
// a small wrapper around
|
21053
|
+
// a small wrapper around source-map and @jridgewell/source-map
|
21025
21054
|
async function SourceMap(options) {
|
21026
21055
|
options = defaults(options, {
|
21027
21056
|
file : null,
|
21028
21057
|
root : null,
|
21029
21058
|
orig : null,
|
21030
|
-
|
21031
|
-
orig_line_diff : 0,
|
21032
|
-
dest_line_diff : 0,
|
21059
|
+
files: {},
|
21033
21060
|
});
|
21034
21061
|
|
21035
21062
|
var orig_map;
|
21036
|
-
var generator = new
|
21063
|
+
var generator = new sourceMap.SourceMapGenerator({
|
21037
21064
|
file : options.file,
|
21038
21065
|
sourceRoot : options.root
|
21039
21066
|
});
|
21040
21067
|
|
21068
|
+
let sourcesContent = {__proto__: null};
|
21069
|
+
let files = options.files;
|
21070
|
+
for (var name in files) if (HOP(files, name)) {
|
21071
|
+
sourcesContent[name] = files[name];
|
21072
|
+
}
|
21041
21073
|
if (options.orig) {
|
21042
|
-
|
21043
|
-
|
21044
|
-
|
21045
|
-
|
21046
|
-
|
21047
|
-
|
21048
|
-
|
21074
|
+
// We support both @jridgewell/source-map (which has a sync
|
21075
|
+
// SourceMapConsumer) and source-map (which has an async
|
21076
|
+
// SourceMapConsumer).
|
21077
|
+
orig_map = await new sourceMap.SourceMapConsumer(options.orig);
|
21078
|
+
if (orig_map.sourcesContent) {
|
21079
|
+
orig_map.sources.forEach(function(source, i) {
|
21080
|
+
var content = orig_map.sourcesContent[i];
|
21081
|
+
if (content) {
|
21082
|
+
sourcesContent[source] = content;
|
21083
|
+
}
|
21084
|
+
});
|
21085
|
+
}
|
21049
21086
|
}
|
21050
21087
|
|
21051
21088
|
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
21089
|
+
let generatedPos = { line: gen_line, column: gen_col };
|
21090
|
+
|
21052
21091
|
if (orig_map) {
|
21053
21092
|
var info = orig_map.originalPositionFor({
|
21054
21093
|
line: orig_line,
|
21055
21094
|
column: orig_col
|
21056
21095
|
});
|
21057
21096
|
if (info.source === null) {
|
21097
|
+
generator.addMapping({
|
21098
|
+
generated: generatedPos,
|
21099
|
+
original: null,
|
21100
|
+
source: null,
|
21101
|
+
name: null
|
21102
|
+
});
|
21058
21103
|
return;
|
21059
21104
|
}
|
21060
21105
|
source = info.source;
|
@@ -21063,22 +21108,42 @@ async function SourceMap(options) {
|
|
21063
21108
|
name = info.name || name;
|
21064
21109
|
}
|
21065
21110
|
generator.addMapping({
|
21066
|
-
generated :
|
21067
|
-
original : { line: orig_line
|
21111
|
+
generated : generatedPos,
|
21112
|
+
original : { line: orig_line, column: orig_col },
|
21068
21113
|
source : source,
|
21069
21114
|
name : name
|
21070
21115
|
});
|
21116
|
+
generator.setSourceContent(source, sourcesContent[source]);
|
21117
|
+
}
|
21118
|
+
|
21119
|
+
function clean(map) {
|
21120
|
+
const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null);
|
21121
|
+
if (allNull) delete map.sourcesContent;
|
21122
|
+
if (map.file === undefined) delete map.file;
|
21123
|
+
if (map.sourceRoot === undefined) delete map.sourceRoot;
|
21124
|
+
return map;
|
21125
|
+
}
|
21126
|
+
|
21127
|
+
function getDecoded() {
|
21128
|
+
if (!generator.toDecodedMap) return null;
|
21129
|
+
return clean(generator.toDecodedMap());
|
21130
|
+
}
|
21131
|
+
|
21132
|
+
function getEncoded() {
|
21133
|
+
return clean(generator.toJSON());
|
21134
|
+
}
|
21135
|
+
|
21136
|
+
function destroy() {
|
21137
|
+
// @jridgewell/source-map's SourceMapConsumer does not need to be
|
21138
|
+
// manually freed.
|
21139
|
+
if (orig_map && orig_map.destroy) orig_map.destroy();
|
21071
21140
|
}
|
21072
21141
|
|
21073
21142
|
return {
|
21074
|
-
add
|
21075
|
-
|
21076
|
-
|
21077
|
-
destroy
|
21078
|
-
if (orig_map && orig_map.destroy) {
|
21079
|
-
orig_map.destroy();
|
21080
|
-
}
|
21081
|
-
}
|
21143
|
+
add,
|
21144
|
+
getDecoded,
|
21145
|
+
getEncoded,
|
21146
|
+
destroy,
|
21082
21147
|
};
|
21083
21148
|
}
|
21084
21149
|
|
@@ -21404,6 +21469,7 @@ var domprops = [
|
|
21404
21469
|
"COMMENT_NODE",
|
21405
21470
|
"COMPARE_REF_TO_TEXTURE",
|
21406
21471
|
"COMPILE_STATUS",
|
21472
|
+
"COMPLETION_STATUS_KHR",
|
21407
21473
|
"COMPRESSED_RGBA_S3TC_DXT1_EXT",
|
21408
21474
|
"COMPRESSED_RGBA_S3TC_DXT3_EXT",
|
21409
21475
|
"COMPRESSED_RGBA_S3TC_DXT5_EXT",
|
@@ -29379,6 +29445,8 @@ async function minify(files, options, _fs_module) {
|
|
29379
29445
|
url: null,
|
29380
29446
|
}, true);
|
29381
29447
|
}
|
29448
|
+
|
29449
|
+
// -- Parse phase --
|
29382
29450
|
if (timings) timings.parse = Date.now();
|
29383
29451
|
var toplevel;
|
29384
29452
|
if (files instanceof AST_Toplevel) {
|
@@ -29422,12 +29490,16 @@ async function minify(files, options, _fs_module) {
|
|
29422
29490
|
toplevel = toplevel.wrap_enclose(options.enclose);
|
29423
29491
|
}
|
29424
29492
|
if (timings) timings.rename = Date.now();
|
29493
|
+
|
29494
|
+
// -- Compress phase --
|
29425
29495
|
if (timings) timings.compress = Date.now();
|
29426
29496
|
if (options.compress) {
|
29427
29497
|
toplevel = new Compressor(options.compress, {
|
29428
29498
|
mangle_options: options.mangle
|
29429
29499
|
}).compress(toplevel);
|
29430
29500
|
}
|
29501
|
+
|
29502
|
+
// -- Mangle phase --
|
29431
29503
|
if (timings) timings.scope = Date.now();
|
29432
29504
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
29433
29505
|
if (timings) timings.mangle = Date.now();
|
@@ -29440,6 +29512,8 @@ async function minify(files, options, _fs_module) {
|
|
29440
29512
|
if (options.mangle && options.mangle.properties) {
|
29441
29513
|
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
29442
29514
|
}
|
29515
|
+
|
29516
|
+
// Format phase
|
29443
29517
|
if (timings) timings.format = Date.now();
|
29444
29518
|
var result = {};
|
29445
29519
|
if (options.format.ast) {
|
@@ -29449,19 +29523,34 @@ async function minify(files, options, _fs_module) {
|
|
29449
29523
|
result.ast = toplevel.to_mozilla_ast();
|
29450
29524
|
}
|
29451
29525
|
if (!HOP(options.format, "code") || options.format.code) {
|
29526
|
+
if (!options.format.ast) {
|
29527
|
+
// Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
|
29528
|
+
options.format._destroy_ast = true;
|
29529
|
+
|
29530
|
+
walk(toplevel, node => {
|
29531
|
+
if (node instanceof AST_Scope) {
|
29532
|
+
node.variables = undefined;
|
29533
|
+
node.enclosed = undefined;
|
29534
|
+
node.parent_scope = undefined;
|
29535
|
+
}
|
29536
|
+
if (node.block_scope) {
|
29537
|
+
node.block_scope.variables = undefined;
|
29538
|
+
node.block_scope.enclosed = undefined;
|
29539
|
+
node.parent_scope = undefined;
|
29540
|
+
}
|
29541
|
+
});
|
29542
|
+
}
|
29543
|
+
|
29452
29544
|
if (options.sourceMap) {
|
29545
|
+
if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
|
29546
|
+
throw new Error("original source content unavailable");
|
29547
|
+
}
|
29453
29548
|
options.format.source_map = await SourceMap({
|
29454
29549
|
file: options.sourceMap.filename,
|
29455
29550
|
orig: options.sourceMap.content,
|
29456
|
-
root: options.sourceMap.root
|
29551
|
+
root: options.sourceMap.root,
|
29552
|
+
files: options.sourceMap.includeSources ? files : null,
|
29457
29553
|
});
|
29458
|
-
if (options.sourceMap.includeSources) {
|
29459
|
-
if (files instanceof AST_Toplevel) {
|
29460
|
-
throw new Error("original source content unavailable");
|
29461
|
-
} else for (var name in files) if (HOP(files, name)) {
|
29462
|
-
options.format.source_map.get().setSourceContent(name, files[name]);
|
29463
|
-
}
|
29464
|
-
}
|
29465
29554
|
}
|
29466
29555
|
delete options.format.ast;
|
29467
29556
|
delete options.format.code;
|
@@ -29470,11 +29559,21 @@ async function minify(files, options, _fs_module) {
|
|
29470
29559
|
toplevel.print(stream);
|
29471
29560
|
result.code = stream.get();
|
29472
29561
|
if (options.sourceMap) {
|
29473
|
-
|
29474
|
-
|
29475
|
-
|
29476
|
-
|
29477
|
-
|
29562
|
+
Object.defineProperty(result, "map", {
|
29563
|
+
configurable: true,
|
29564
|
+
enumerable: true,
|
29565
|
+
get() {
|
29566
|
+
const map = options.format.source_map.getEncoded();
|
29567
|
+
return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
|
29568
|
+
},
|
29569
|
+
set(value) {
|
29570
|
+
Object.defineProperty(result, "map", {
|
29571
|
+
value,
|
29572
|
+
writable: true,
|
29573
|
+
});
|
29574
|
+
}
|
29575
|
+
});
|
29576
|
+
result.decoded_map = options.format.source_map.getDecoded();
|
29478
29577
|
if (options.sourceMap.url == "inline") {
|
29479
29578
|
var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
|
29480
29579
|
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
|
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) {
|
@@ -552,11 +561,10 @@ var AST_With = DEFNODE("With", "expression", function AST_With(props) {
|
|
552
561
|
|
553
562
|
var AST_Scope = DEFNODE(
|
554
563
|
"Scope",
|
555
|
-
"variables
|
564
|
+
"variables uses_with uses_eval parent_scope enclosed cname",
|
556
565
|
function AST_Scope(props) {
|
557
566
|
if (props) {
|
558
567
|
this.variables = props.variables;
|
559
|
-
this.functions = props.functions;
|
560
568
|
this.uses_with = props.uses_with;
|
561
569
|
this.uses_eval = props.uses_eval;
|
562
570
|
this.parent_scope = props.parent_scope;
|
@@ -612,7 +620,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
|
|
612
620
|
if (props) {
|
613
621
|
this.globals = props.globals;
|
614
622
|
this.variables = props.variables;
|
615
|
-
this.functions = props.functions;
|
616
623
|
this.uses_with = props.uses_with;
|
617
624
|
this.uses_eval = props.uses_eval;
|
618
625
|
this.parent_scope = props.parent_scope;
|
@@ -694,7 +701,6 @@ var AST_Lambda = DEFNODE(
|
|
694
701
|
this.is_generator = props.is_generator;
|
695
702
|
this.async = props.async;
|
696
703
|
this.variables = props.variables;
|
697
|
-
this.functions = props.functions;
|
698
704
|
this.uses_with = props.uses_with;
|
699
705
|
this.uses_eval = props.uses_eval;
|
700
706
|
this.parent_scope = props.parent_scope;
|
@@ -774,7 +780,6 @@ var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
|
|
774
780
|
this.is_generator = props.is_generator;
|
775
781
|
this.async = props.async;
|
776
782
|
this.variables = props.variables;
|
777
|
-
this.functions = props.functions;
|
778
783
|
this.uses_with = props.uses_with;
|
779
784
|
this.uses_eval = props.uses_eval;
|
780
785
|
this.parent_scope = props.parent_scope;
|
@@ -799,7 +804,6 @@ var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
|
|
799
804
|
this.is_generator = props.is_generator;
|
800
805
|
this.async = props.async;
|
801
806
|
this.variables = props.variables;
|
802
|
-
this.functions = props.functions;
|
803
807
|
this.uses_with = props.uses_with;
|
804
808
|
this.uses_eval = props.uses_eval;
|
805
809
|
this.parent_scope = props.parent_scope;
|
@@ -824,7 +828,6 @@ var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
|
|
824
828
|
this.is_generator = props.is_generator;
|
825
829
|
this.async = props.async;
|
826
830
|
this.variables = props.variables;
|
827
|
-
this.functions = props.functions;
|
828
831
|
this.uses_with = props.uses_with;
|
829
832
|
this.uses_eval = props.uses_eval;
|
830
833
|
this.parent_scope = props.parent_scope;
|
@@ -849,7 +852,6 @@ var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
|
|
849
852
|
this.is_generator = props.is_generator;
|
850
853
|
this.async = props.async;
|
851
854
|
this.variables = props.variables;
|
852
|
-
this.functions = props.functions;
|
853
855
|
this.uses_with = props.uses_with;
|
854
856
|
this.uses_eval = props.uses_eval;
|
855
857
|
this.parent_scope = props.parent_scope;
|
@@ -2161,7 +2163,6 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
|
|
2161
2163
|
this.extends = props.extends;
|
2162
2164
|
this.properties = props.properties;
|
2163
2165
|
this.variables = props.variables;
|
2164
|
-
this.functions = props.functions;
|
2165
2166
|
this.uses_with = props.uses_with;
|
2166
2167
|
this.uses_eval = props.uses_eval;
|
2167
2168
|
this.parent_scope = props.parent_scope;
|
@@ -2255,7 +2256,6 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
|
|
2255
2256
|
this.extends = props.extends;
|
2256
2257
|
this.properties = props.properties;
|
2257
2258
|
this.variables = props.variables;
|
2258
|
-
this.functions = props.functions;
|
2259
2259
|
this.uses_with = props.uses_with;
|
2260
2260
|
this.uses_eval = props.uses_eval;
|
2261
2261
|
this.parent_scope = props.parent_scope;
|
@@ -2278,7 +2278,6 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExp
|
|
2278
2278
|
this.extends = props.extends;
|
2279
2279
|
this.properties = props.properties;
|
2280
2280
|
this.variables = props.variables;
|
2281
|
-
this.functions = props.functions;
|
2282
2281
|
this.uses_with = props.uses_with;
|
2283
2282
|
this.uses_eval = props.uses_eval;
|
2284
2283
|
this.parent_scope = props.parent_scope;
|
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
@@ -158,6 +158,7 @@ import {
|
|
158
158
|
return_true,
|
159
159
|
regexp_source_fix,
|
160
160
|
has_annotation,
|
161
|
+
regexp_is_safe,
|
161
162
|
} from "../utils/index.js";
|
162
163
|
import { first_in_statement } from "../utils/first_in_statement.js";
|
163
164
|
import { equivalent_to } from "../equivalent-to.js";
|
@@ -2140,6 +2141,7 @@ def_optimize(AST_Call, function(self, compressor) {
|
|
2140
2141
|
params.push(value);
|
2141
2142
|
return arg !== value;
|
2142
2143
|
})
|
2144
|
+
&& regexp_is_safe(params[0])
|
2143
2145
|
) {
|
2144
2146
|
let [ source, flags ] = params;
|
2145
2147
|
source = regexp_source_fix(new RegExp(source).source);
|
@@ -3799,6 +3801,12 @@ def_optimize(AST_Dot, function(self, compressor) {
|
|
3799
3801
|
const sub = self.flatten_object(self.property, compressor);
|
3800
3802
|
if (sub) return sub.optimize(compressor);
|
3801
3803
|
}
|
3804
|
+
|
3805
|
+
if (self.expression instanceof AST_PropAccess
|
3806
|
+
&& parent instanceof AST_PropAccess) {
|
3807
|
+
return self;
|
3808
|
+
}
|
3809
|
+
|
3802
3810
|
let ev = self.evaluate(compressor);
|
3803
3811
|
if (ev !== self) {
|
3804
3812
|
ev = make_node_from_constant(ev, self).optimize(compressor);
|
package/lib/minify.js
CHANGED
@@ -7,7 +7,7 @@ import {
|
|
7
7
|
map_to_object,
|
8
8
|
HOP,
|
9
9
|
} from "./utils/index.js";
|
10
|
-
import { AST_Toplevel, AST_Node } from "./ast.js";
|
10
|
+
import { AST_Toplevel, AST_Node, walk, AST_Scope } from "./ast.js";
|
11
11
|
import { parse } from "./parse.js";
|
12
12
|
import { OutputStream } from "./output.js";
|
13
13
|
import { Compressor } from "./compress/index.js";
|
@@ -194,6 +194,8 @@ async function minify(files, options, _fs_module) {
|
|
194
194
|
url: null,
|
195
195
|
}, true);
|
196
196
|
}
|
197
|
+
|
198
|
+
// -- Parse phase --
|
197
199
|
if (timings) timings.parse = Date.now();
|
198
200
|
var toplevel;
|
199
201
|
if (files instanceof AST_Toplevel) {
|
@@ -243,12 +245,16 @@ async function minify(files, options, _fs_module) {
|
|
243
245
|
toplevel.figure_out_scope(options.mangle);
|
244
246
|
toplevel.expand_names(options.mangle);
|
245
247
|
}
|
248
|
+
|
249
|
+
// -- Compress phase --
|
246
250
|
if (timings) timings.compress = Date.now();
|
247
251
|
if (options.compress) {
|
248
252
|
toplevel = new Compressor(options.compress, {
|
249
253
|
mangle_options: options.mangle
|
250
254
|
}).compress(toplevel);
|
251
255
|
}
|
256
|
+
|
257
|
+
// -- Mangle phase --
|
252
258
|
if (timings) timings.scope = Date.now();
|
253
259
|
if (options.mangle) toplevel.figure_out_scope(options.mangle);
|
254
260
|
if (timings) timings.mangle = Date.now();
|
@@ -261,6 +267,8 @@ async function minify(files, options, _fs_module) {
|
|
261
267
|
if (options.mangle && options.mangle.properties) {
|
262
268
|
toplevel = mangle_properties(toplevel, options.mangle.properties);
|
263
269
|
}
|
270
|
+
|
271
|
+
// Format phase
|
264
272
|
if (timings) timings.format = Date.now();
|
265
273
|
var result = {};
|
266
274
|
if (options.format.ast) {
|
@@ -270,19 +278,34 @@ async function minify(files, options, _fs_module) {
|
|
270
278
|
result.ast = toplevel.to_mozilla_ast();
|
271
279
|
}
|
272
280
|
if (!HOP(options.format, "code") || options.format.code) {
|
281
|
+
if (!options.format.ast) {
|
282
|
+
// Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
|
283
|
+
options.format._destroy_ast = true;
|
284
|
+
|
285
|
+
walk(toplevel, node => {
|
286
|
+
if (node instanceof AST_Scope) {
|
287
|
+
node.variables = undefined;
|
288
|
+
node.enclosed = undefined;
|
289
|
+
node.parent_scope = undefined;
|
290
|
+
}
|
291
|
+
if (node.block_scope) {
|
292
|
+
node.block_scope.variables = undefined;
|
293
|
+
node.block_scope.enclosed = undefined;
|
294
|
+
node.parent_scope = undefined;
|
295
|
+
}
|
296
|
+
});
|
297
|
+
}
|
298
|
+
|
273
299
|
if (options.sourceMap) {
|
300
|
+
if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
|
301
|
+
throw new Error("original source content unavailable");
|
302
|
+
}
|
274
303
|
options.format.source_map = await SourceMap({
|
275
304
|
file: options.sourceMap.filename,
|
276
305
|
orig: options.sourceMap.content,
|
277
|
-
root: options.sourceMap.root
|
306
|
+
root: options.sourceMap.root,
|
307
|
+
files: options.sourceMap.includeSources ? files : null,
|
278
308
|
});
|
279
|
-
if (options.sourceMap.includeSources) {
|
280
|
-
if (files instanceof AST_Toplevel) {
|
281
|
-
throw new Error("original source content unavailable");
|
282
|
-
} else for (var name in files) if (HOP(files, name)) {
|
283
|
-
options.format.source_map.get().setSourceContent(name, files[name]);
|
284
|
-
}
|
285
|
-
}
|
286
309
|
}
|
287
310
|
delete options.format.ast;
|
288
311
|
delete options.format.code;
|
@@ -291,11 +314,21 @@ async function minify(files, options, _fs_module) {
|
|
291
314
|
toplevel.print(stream);
|
292
315
|
result.code = stream.get();
|
293
316
|
if (options.sourceMap) {
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
317
|
+
Object.defineProperty(result, "map", {
|
318
|
+
configurable: true,
|
319
|
+
enumerable: true,
|
320
|
+
get() {
|
321
|
+
const map = options.format.source_map.getEncoded();
|
322
|
+
return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
|
323
|
+
},
|
324
|
+
set(value) {
|
325
|
+
Object.defineProperty(result, "map", {
|
326
|
+
value,
|
327
|
+
writable: true,
|
328
|
+
});
|
329
|
+
}
|
330
|
+
});
|
331
|
+
result.decoded_map = options.format.source_map.getDecoded();
|
299
332
|
if (options.sourceMap.url == "inline") {
|
300
333
|
var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
|
301
334
|
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
|
package/lib/output.js
CHANGED
@@ -247,6 +247,8 @@ function OutputStream(options) {
|
|
247
247
|
width : 80,
|
248
248
|
wrap_iife : false,
|
249
249
|
wrap_func_args : true,
|
250
|
+
|
251
|
+
_destroy_ast : false
|
250
252
|
}, true);
|
251
253
|
|
252
254
|
if (options.shorthand === undefined)
|
@@ -796,6 +798,18 @@ function OutputStream(options) {
|
|
796
798
|
if (OUTPUT.length() > insert) newline_insert = insert;
|
797
799
|
}
|
798
800
|
|
801
|
+
/**
|
802
|
+
* When output.option("_destroy_ast") is enabled, destroy the function.
|
803
|
+
* Call this after printing it.
|
804
|
+
*/
|
805
|
+
const gc_scope =
|
806
|
+
options["_destroy_ast"]
|
807
|
+
? function gc_scope(scope) {
|
808
|
+
scope.body.length = 0;
|
809
|
+
scope.argnames.length = 0;
|
810
|
+
}
|
811
|
+
: noop;
|
812
|
+
|
799
813
|
var stack = [];
|
800
814
|
return {
|
801
815
|
get : get,
|
@@ -842,6 +856,7 @@ function OutputStream(options) {
|
|
842
856
|
with_square : with_square,
|
843
857
|
add_mapping : add_mapping,
|
844
858
|
option : function(opt) { return options[opt]; },
|
859
|
+
gc_scope,
|
845
860
|
printed_comments: printed_comments,
|
846
861
|
prepend_comments: readonly ? noop : prepend_comments,
|
847
862
|
append_comments : readonly || comment_filter === return_false ? noop : append_comments,
|
@@ -1232,12 +1247,14 @@ function OutputStream(options) {
|
|
1232
1247
|
output.with_indent(output.next_indent(), function() {
|
1233
1248
|
output.append_comments(self, true);
|
1234
1249
|
});
|
1250
|
+
output.add_mapping(self.end);
|
1235
1251
|
output.print("}");
|
1236
1252
|
}
|
1237
1253
|
function print_braced(self, output, allow_directives) {
|
1238
1254
|
if (self.body.length > 0) {
|
1239
1255
|
output.with_block(function() {
|
1240
1256
|
display_body(self.body, false, output, allow_directives);
|
1257
|
+
output.add_mapping(self.end);
|
1241
1258
|
});
|
1242
1259
|
} else print_braced_empty(self, output);
|
1243
1260
|
}
|
@@ -1358,6 +1375,7 @@ function OutputStream(options) {
|
|
1358
1375
|
});
|
1359
1376
|
DEFPRINT(AST_Lambda, function(self, output) {
|
1360
1377
|
self._do_print(output);
|
1378
|
+
output.gc_scope(self);
|
1361
1379
|
});
|
1362
1380
|
|
1363
1381
|
DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
|
@@ -1437,6 +1455,7 @@ function OutputStream(options) {
|
|
1437
1455
|
print_braced(self, output);
|
1438
1456
|
}
|
1439
1457
|
if (needs_parens) { output.print(")"); }
|
1458
|
+
output.gc_scope(self);
|
1440
1459
|
});
|
1441
1460
|
|
1442
1461
|
/* -----[ exits ]----- */
|
package/lib/parse.js
CHANGED
@@ -162,7 +162,7 @@ import {
|
|
162
162
|
} from "./ast.js";
|
163
163
|
|
164
164
|
var LATEST_RAW = ""; // Only used for numbers and template strings
|
165
|
-
var
|
165
|
+
var TEMPLATE_RAWS = new Map(); // Raw template strings
|
166
166
|
|
167
167
|
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
168
|
var KEYWORDS_ATOM = "false null true";
|
@@ -693,8 +693,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
693
693
|
next(true, true);
|
694
694
|
S.brace_counter++;
|
695
695
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
696
|
-
|
697
|
-
|
696
|
+
TEMPLATE_RAWS.set(tok, raw);
|
697
|
+
tok.template_end = false;
|
698
698
|
return tok;
|
699
699
|
}
|
700
700
|
|
@@ -710,8 +710,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
|
|
710
710
|
}
|
711
711
|
S.template_braces.pop();
|
712
712
|
tok = token(begin ? "template_head" : "template_substitution", content);
|
713
|
-
|
714
|
-
|
713
|
+
TEMPLATE_RAWS.set(tok, raw);
|
714
|
+
tok.template_end = true;
|
715
715
|
return tok;
|
716
716
|
});
|
717
717
|
|
@@ -2367,19 +2367,19 @@ function parse($TEXT, options) {
|
|
2367
2367
|
|
2368
2368
|
segments.push(new AST_TemplateSegment({
|
2369
2369
|
start: S.token,
|
2370
|
-
raw:
|
2370
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2371
2371
|
value: S.token.value,
|
2372
2372
|
end: S.token
|
2373
2373
|
}));
|
2374
2374
|
|
2375
|
-
while (!
|
2375
|
+
while (!S.token.template_end) {
|
2376
2376
|
next();
|
2377
2377
|
handle_regexp();
|
2378
2378
|
segments.push(expression(true));
|
2379
2379
|
|
2380
2380
|
segments.push(new AST_TemplateSegment({
|
2381
2381
|
start: S.token,
|
2382
|
-
raw:
|
2382
|
+
raw: TEMPLATE_RAWS.get(S.token),
|
2383
2383
|
value: S.token.value,
|
2384
2384
|
end: S.token
|
2385
2385
|
}));
|
@@ -3342,6 +3342,7 @@ function parse($TEXT, options) {
|
|
3342
3342
|
} else {
|
3343
3343
|
toplevel = new AST_Toplevel({ start: start, body: body, end: end });
|
3344
3344
|
}
|
3345
|
+
TEMPLATE_RAWS = new Map();
|
3345
3346
|
return toplevel;
|
3346
3347
|
})();
|
3347
3348
|
|
package/lib/sourcemap.js
CHANGED
@@ -43,45 +43,59 @@
|
|
43
43
|
|
44
44
|
"use strict";
|
45
45
|
|
46
|
-
import
|
47
|
-
import {
|
48
|
-
defaults,
|
49
|
-
} from "./utils/index.js";
|
46
|
+
import {SourceMapConsumer, SourceMapGenerator} from "@jridgewell/source-map";
|
47
|
+
import {defaults, HOP} from "./utils/index.js";
|
50
48
|
|
51
|
-
// a small wrapper around
|
49
|
+
// a small wrapper around source-map and @jridgewell/source-map
|
52
50
|
async function SourceMap(options) {
|
53
51
|
options = defaults(options, {
|
54
52
|
file : null,
|
55
53
|
root : null,
|
56
54
|
orig : null,
|
57
|
-
|
58
|
-
orig_line_diff : 0,
|
59
|
-
dest_line_diff : 0,
|
55
|
+
files: {},
|
60
56
|
});
|
61
57
|
|
62
58
|
var orig_map;
|
63
|
-
var generator = new
|
59
|
+
var generator = new SourceMapGenerator({
|
64
60
|
file : options.file,
|
65
61
|
sourceRoot : options.root
|
66
62
|
});
|
67
63
|
|
64
|
+
let sourcesContent = {__proto__: null};
|
65
|
+
let files = options.files;
|
66
|
+
for (var name in files) if (HOP(files, name)) {
|
67
|
+
sourcesContent[name] = files[name];
|
68
|
+
}
|
68
69
|
if (options.orig) {
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
70
|
+
// We support both @jridgewell/source-map (which has a sync
|
71
|
+
// SourceMapConsumer) and source-map (which has an async
|
72
|
+
// SourceMapConsumer).
|
73
|
+
orig_map = await new SourceMapConsumer(options.orig);
|
74
|
+
if (orig_map.sourcesContent) {
|
75
|
+
orig_map.sources.forEach(function(source, i) {
|
76
|
+
var content = orig_map.sourcesContent[i];
|
77
|
+
if (content) {
|
78
|
+
sourcesContent[source] = content;
|
79
|
+
}
|
80
|
+
});
|
81
|
+
}
|
76
82
|
}
|
77
83
|
|
78
84
|
function add(source, gen_line, gen_col, orig_line, orig_col, name) {
|
85
|
+
let generatedPos = { line: gen_line, column: gen_col };
|
86
|
+
|
79
87
|
if (orig_map) {
|
80
88
|
var info = orig_map.originalPositionFor({
|
81
89
|
line: orig_line,
|
82
90
|
column: orig_col
|
83
91
|
});
|
84
92
|
if (info.source === null) {
|
93
|
+
generator.addMapping({
|
94
|
+
generated: generatedPos,
|
95
|
+
original: null,
|
96
|
+
source: null,
|
97
|
+
name: null
|
98
|
+
});
|
85
99
|
return;
|
86
100
|
}
|
87
101
|
source = info.source;
|
@@ -90,22 +104,42 @@ async function SourceMap(options) {
|
|
90
104
|
name = info.name || name;
|
91
105
|
}
|
92
106
|
generator.addMapping({
|
93
|
-
generated :
|
94
|
-
original : { line: orig_line
|
107
|
+
generated : generatedPos,
|
108
|
+
original : { line: orig_line, column: orig_col },
|
95
109
|
source : source,
|
96
110
|
name : name
|
97
111
|
});
|
112
|
+
generator.setSourceContent(source, sourcesContent[source]);
|
113
|
+
}
|
114
|
+
|
115
|
+
function clean(map) {
|
116
|
+
const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null);
|
117
|
+
if (allNull) delete map.sourcesContent;
|
118
|
+
if (map.file === undefined) delete map.file;
|
119
|
+
if (map.sourceRoot === undefined) delete map.sourceRoot;
|
120
|
+
return map;
|
121
|
+
}
|
122
|
+
|
123
|
+
function getDecoded() {
|
124
|
+
if (!generator.toDecodedMap) return null;
|
125
|
+
return clean(generator.toDecodedMap());
|
126
|
+
}
|
127
|
+
|
128
|
+
function getEncoded() {
|
129
|
+
return clean(generator.toJSON());
|
130
|
+
}
|
131
|
+
|
132
|
+
function destroy() {
|
133
|
+
// @jridgewell/source-map's SourceMapConsumer does not need to be
|
134
|
+
// manually freed.
|
135
|
+
if (orig_map && orig_map.destroy) orig_map.destroy();
|
98
136
|
}
|
99
137
|
|
100
138
|
return {
|
101
|
-
add
|
102
|
-
|
103
|
-
|
104
|
-
destroy
|
105
|
-
if (orig_map && orig_map.destroy) {
|
106
|
-
orig_map.destroy();
|
107
|
-
}
|
108
|
-
}
|
139
|
+
add,
|
140
|
+
getDecoded,
|
141
|
+
getEncoded,
|
142
|
+
destroy,
|
109
143
|
};
|
110
144
|
}
|
111
145
|
|
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
@@ -4,7 +4,7 @@
|
|
4
4
|
"homepage": "https://terser.org",
|
5
5
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
6
6
|
"license": "BSD-2-Clause",
|
7
|
-
"version": "5.
|
7
|
+
"version": "5.14.2",
|
8
8
|
"engines": {
|
9
9
|
"node": ">=10"
|
10
10
|
},
|
@@ -18,6 +18,7 @@
|
|
18
18
|
"exports": {
|
19
19
|
".": [
|
20
20
|
{
|
21
|
+
"types": "./tools/terser.d.ts",
|
21
22
|
"import": "./main.js",
|
22
23
|
"require": "./dist/bundle.min.js"
|
23
24
|
},
|
@@ -43,9 +44,9 @@
|
|
43
44
|
"main.js"
|
44
45
|
],
|
45
46
|
"dependencies": {
|
47
|
+
"@jridgewell/source-map": "^0.3.2",
|
46
48
|
"acorn": "^8.5.0",
|
47
49
|
"commander": "^2.20.0",
|
48
|
-
"source-map": "~0.8.0-beta.0",
|
49
50
|
"source-map-support": "~0.5.20"
|
50
51
|
},
|
51
52
|
"devDependencies": {
|
@@ -58,7 +59,8 @@
|
|
58
59
|
"pre-commit": "^1.2.2",
|
59
60
|
"rimraf": "^3.0.2",
|
60
61
|
"rollup": "2.56.3",
|
61
|
-
"semver": "^7.3.4"
|
62
|
+
"semver": "^7.3.4",
|
63
|
+
"source-map": "~0.8.0-beta.0"
|
62
64
|
},
|
63
65
|
"scripts": {
|
64
66
|
"test": "node test/compress.js && mocha test/mocha",
|
package/tools/domprops.js
CHANGED
package/tools/terser.d.ts
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
/// <reference lib="es2015" />
|
2
2
|
|
3
|
-
import {
|
3
|
+
import { SectionedSourceMapInput, EncodedSourceMap, DecodedSourceMap } from '@jridgewell/source-map';
|
4
4
|
|
5
5
|
export type ECMA = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020;
|
6
6
|
|
7
7
|
export interface ParseOptions {
|
8
8
|
bare_returns?: boolean;
|
9
|
+
/** @deprecated legacy option. Currently, all supported EcmaScript is valid to parse. */
|
9
10
|
ecma?: ECMA;
|
10
11
|
html5_comments?: boolean;
|
11
12
|
shebang?: boolean;
|
@@ -144,6 +145,7 @@ export interface FormatOptions {
|
|
144
145
|
}) => boolean );
|
145
146
|
ecma?: ECMA;
|
146
147
|
ie8?: boolean;
|
148
|
+
keep_numbers?: boolean;
|
147
149
|
indent_level?: number;
|
148
150
|
indent_start?: number;
|
149
151
|
inline_script?: boolean;
|
@@ -192,12 +194,13 @@ export interface MinifyOptions {
|
|
192
194
|
|
193
195
|
export interface MinifyOutput {
|
194
196
|
code?: string;
|
195
|
-
map?:
|
197
|
+
map?: EncodedSourceMap | string;
|
198
|
+
decoded_map?: DecodedSourceMap | null;
|
196
199
|
}
|
197
200
|
|
198
201
|
export interface SourceMapOptions {
|
199
202
|
/** Source map object, 'inline' or source map file content */
|
200
|
-
content?:
|
203
|
+
content?: SectionedSourceMapInput | string;
|
201
204
|
includeSources?: boolean;
|
202
205
|
filename?: string;
|
203
206
|
root?: string;
|