terser 5.6.0-beta → 5.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -72,10 +72,8 @@ class DefaultsError extends Error {
72
72
  function defaults(args, defs, croak) {
73
73
  if (args === true) {
74
74
  args = {};
75
- }
76
-
77
- if (args != null && typeof args === "object") {
78
- args = Object.assign({}, args);
75
+ } else if (args != null && typeof args === "object") {
76
+ args = {...args};
79
77
  }
80
78
 
81
79
  const ret = args || {};
@@ -204,7 +202,7 @@ function mergeSort(array, cmp) {
204
202
  function makePredicate(words) {
205
203
  if (!Array.isArray(words)) words = words.split(" ");
206
204
 
207
- return new Set(words);
205
+ return new Set(words.sort());
208
206
  }
209
207
 
210
208
  function map_add(map, key, value) {
@@ -243,6 +241,7 @@ function keep_name(keep_setting, name) {
243
241
  }
244
242
 
245
243
  var lineTerminatorEscape = {
244
+ "\0": "0",
246
245
  "\n": "n",
247
246
  "\r": "r",
248
247
  "\u2028": "u2028",
@@ -250,7 +249,8 @@ var lineTerminatorEscape = {
250
249
  };
251
250
  function regexp_source_fix(source) {
252
251
  // V8 does not escape line terminators in regexp patterns in node 12
253
- return source.replace(/[\n\r\u2028\u2029]/g, function (match, offset) {
252
+ // We'll also remove literal \0
253
+ return source.replace(/[\0\n\r\u2028\u2029]/g, function (match, offset) {
254
254
  var escaped = source[offset - 1] == "\\"
255
255
  && (source[offset - 2] != "\\"
256
256
  || /(?:^|[^\\])(?:\\{2})*$/.test(source.slice(0, offset - 1)));
@@ -1457,7 +1457,7 @@ function parse($TEXT, options) {
1457
1457
  if (is_if_body) {
1458
1458
  croak("classes are not allowed as the body of an if");
1459
1459
  }
1460
- return class_(AST_DefClass);
1460
+ return class_(AST_DefClass, is_export_default);
1461
1461
 
1462
1462
  case "function":
1463
1463
  next();
@@ -2652,7 +2652,7 @@ function parse($TEXT, options) {
2652
2652
  return new AST_Object({ properties: a });
2653
2653
  });
2654
2654
 
2655
- function class_(KindOfClass) {
2655
+ function class_(KindOfClass, is_export_default) {
2656
2656
  var start, method, class_name, extends_, a = [];
2657
2657
 
2658
2658
  S.input.push_directives_stack(); // Push directive stack, but not scope stack
@@ -2663,7 +2663,11 @@ function parse($TEXT, options) {
2663
2663
  }
2664
2664
 
2665
2665
  if (KindOfClass === AST_DefClass && !class_name) {
2666
- unexpected();
2666
+ if (is_export_default) {
2667
+ KindOfClass = AST_ClassExpression;
2668
+ } else {
2669
+ unexpected();
2670
+ }
2667
2671
  }
2668
2672
 
2669
2673
  if (S.token.value == "extends") {
@@ -2696,9 +2700,9 @@ function parse($TEXT, options) {
2696
2700
  }
2697
2701
 
2698
2702
  function concise_method_or_getset(name, start, is_class) {
2699
- var get_method_name_ast = function(name, start) {
2703
+ const get_symbol_ast = (name, SymbolClass = AST_SymbolMethod) => {
2700
2704
  if (typeof name === "string" || typeof name === "number") {
2701
- return new AST_SymbolMethod({
2705
+ return new SymbolClass({
2702
2706
  start,
2703
2707
  name: "" + name,
2704
2708
  end: prev()
@@ -2708,47 +2712,71 @@ function parse($TEXT, options) {
2708
2712
  }
2709
2713
  return name;
2710
2714
  };
2711
- const get_class_property_key_ast = (name) => {
2712
- if (typeof name === "string" || typeof name === "number") {
2713
- return new AST_SymbolClassProperty({
2714
- start: property_token,
2715
- end: property_token,
2716
- name: "" + name
2717
- });
2718
- } else if (name === null) {
2719
- unexpected();
2720
- }
2721
- return name;
2722
- };
2723
- var privatename = start.type == "privatename";
2715
+
2716
+ const is_not_method_start = () =>
2717
+ !is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("operator", "=");
2718
+
2724
2719
  var is_async = false;
2725
2720
  var is_static = false;
2726
2721
  var is_generator = false;
2727
- var property_token = start;
2728
- if (is_class && name === "static" && !is("punc", "(")) {
2722
+ var is_private = false;
2723
+ var accessor_type = null;
2724
+
2725
+ if (is_class && name === "static" && is_not_method_start()) {
2729
2726
  is_static = true;
2730
- property_token = S.token;
2731
- privatename = property_token.type == "privatename";
2732
2727
  name = as_property_name();
2733
2728
  }
2734
- if (name === "async" && !is("punc", "(") && !is("punc", ",") && !is("punc", "}") && !is("operator", "=")) {
2729
+ if (name === "async" && is_not_method_start()) {
2735
2730
  is_async = true;
2736
- property_token = S.token;
2737
- privatename = property_token.type == "privatename";
2738
2731
  name = as_property_name();
2739
2732
  }
2740
- if (name === null) {
2733
+ if (prev().type === "operator" && prev().value === "*") {
2741
2734
  is_generator = true;
2742
- property_token = S.token;
2743
- privatename = property_token.type == "privatename";
2744
2735
  name = as_property_name();
2745
- if (name === null) {
2746
- unexpected();
2736
+ }
2737
+ if ((name === "get" || name === "set") && is_not_method_start()) {
2738
+ accessor_type = name;
2739
+ name = as_property_name();
2740
+ }
2741
+ if (prev().type === "privatename") {
2742
+ is_private = true;
2743
+ }
2744
+
2745
+ const property_token = prev();
2746
+
2747
+ if (accessor_type != null) {
2748
+ if (!is_private) {
2749
+ const AccessorClass = accessor_type === "get"
2750
+ ? AST_ObjectGetter
2751
+ : AST_ObjectSetter;
2752
+
2753
+ name = get_symbol_ast(name);
2754
+ return new AccessorClass({
2755
+ start,
2756
+ static: is_static,
2757
+ key: name,
2758
+ quote: name instanceof AST_SymbolMethod ? property_token.quote : undefined,
2759
+ value: create_accessor(),
2760
+ end: prev()
2761
+ });
2762
+ } else {
2763
+ const AccessorClass = accessor_type === "get"
2764
+ ? AST_PrivateGetter
2765
+ : AST_PrivateSetter;
2766
+
2767
+ return new AccessorClass({
2768
+ start,
2769
+ static: is_static,
2770
+ key: get_symbol_ast(name),
2771
+ value: create_accessor(),
2772
+ end: prev(),
2773
+ });
2747
2774
  }
2748
2775
  }
2776
+
2749
2777
  if (is("punc", "(")) {
2750
- name = get_method_name_ast(name, start);
2751
- const AST_MethodVariant = privatename
2778
+ name = get_symbol_ast(name);
2779
+ const AST_MethodVariant = is_private
2752
2780
  ? AST_PrivateMethod
2753
2781
  : AST_ConciseMethod;
2754
2782
  var node = new AST_MethodVariant({
@@ -2764,57 +2792,13 @@ function parse($TEXT, options) {
2764
2792
  });
2765
2793
  return node;
2766
2794
  }
2767
- const setter_token = S.token;
2768
- if ((name === "get" || name === "set") && setter_token.type === "privatename") {
2769
- next();
2770
-
2771
- const AST_AccessorVariant =
2772
- name === "get"
2773
- ? AST_PrivateGetter
2774
- : AST_PrivateSetter;
2775
-
2776
- return new AST_AccessorVariant({
2777
- start,
2778
- static: is_static,
2779
- key: get_method_name_ast(setter_token.value, start),
2780
- value: create_accessor(),
2781
- end: prev(),
2782
- });
2783
- }
2784
2795
 
2785
- if (name == "get") {
2786
- if (!is("punc") || is("punc", "[")) {
2787
- name = get_method_name_ast(as_property_name(), start);
2788
- return new AST_ObjectGetter({
2789
- start : start,
2790
- static: is_static,
2791
- key : name,
2792
- quote : name instanceof AST_SymbolMethod ?
2793
- setter_token.quote : undefined,
2794
- value : create_accessor(),
2795
- end : prev()
2796
- });
2797
- }
2798
- } else if (name == "set") {
2799
- if (!is("punc") || is("punc", "[")) {
2800
- name = get_method_name_ast(as_property_name(), start);
2801
- return new AST_ObjectSetter({
2802
- start : start,
2803
- static: is_static,
2804
- key : name,
2805
- quote : name instanceof AST_SymbolMethod ?
2806
- setter_token.quote : undefined,
2807
- value : create_accessor(),
2808
- end : prev()
2809
- });
2810
- }
2811
- }
2812
2796
  if (is_class) {
2813
- const key = get_class_property_key_ast(name);
2797
+ const key = get_symbol_ast(name, AST_SymbolClassProperty);
2814
2798
  const quote = key instanceof AST_SymbolClassProperty
2815
2799
  ? property_token.quote
2816
2800
  : undefined;
2817
- const AST_ClassPropertyVariant = privatename
2801
+ const AST_ClassPropertyVariant = is_private
2818
2802
  ? AST_ClassPrivateProperty
2819
2803
  : AST_ClassProperty;
2820
2804
  if (is("operator", "=")) {
@@ -3036,8 +3020,17 @@ function parse($TEXT, options) {
3036
3020
  semicolon();
3037
3021
  } else if ((node = statement(is_default)) instanceof AST_Definitions && is_default) {
3038
3022
  unexpected(node.start);
3039
- } else if (node instanceof AST_Definitions || node instanceof AST_Lambda || node instanceof AST_DefClass) {
3023
+ } else if (
3024
+ node instanceof AST_Definitions
3025
+ || node instanceof AST_Defun
3026
+ || node instanceof AST_DefClass
3027
+ ) {
3040
3028
  exported_definition = node;
3029
+ } else if (
3030
+ node instanceof AST_ClassExpression
3031
+ || node instanceof AST_Function
3032
+ ) {
3033
+ exported_value = node;
3041
3034
  } else if (node instanceof AST_SimpleStatement) {
3042
3035
  exported_value = node.body;
3043
3036
  } else {
@@ -3706,8 +3699,6 @@ function walk_body(node, visitor) {
3706
3699
  function clone_block_scope(deep) {
3707
3700
  var clone = this._clone(deep);
3708
3701
  if (this.block_scope) {
3709
- // TODO this is sometimes undefined during compression.
3710
- // But it should always have a value!
3711
3702
  clone.block_scope = this.block_scope.clone();
3712
3703
  }
3713
3704
  return clone;
@@ -3891,7 +3882,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
3891
3882
  $documentation: "Base class for all statements introducing a lexical scope",
3892
3883
  $propdoc: {
3893
3884
  variables: "[Map/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
3894
- functions: "[Map/S] like `variables`, but only lists function declarations",
3895
3885
  uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
3896
3886
  uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
3897
3887
  parent_scope: "[AST_Scope?/S] link to the parent scope",
@@ -3914,7 +3904,6 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
3914
3904
  });
3915
3905
  } else {
3916
3906
  if (this.variables) node.variables = new Map(this.variables);
3917
- if (this.functions) node.functions = new Map(this.functions);
3918
3907
  if (this.enclosed) node.enclosed = this.enclosed.slice();
3919
3908
  if (this._block_scope) node._block_scope = this._block_scope;
3920
3909
  }
@@ -4014,6 +4003,21 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator as
4014
4003
 
4015
4004
  if (this.name) push(this.name);
4016
4005
  },
4006
+ is_braceless() {
4007
+ return this.body[0] instanceof AST_Return && this.body[0].value;
4008
+ },
4009
+ // Default args and expansion don't count, so .argnames.length doesn't cut it
4010
+ length_property() {
4011
+ let length = 0;
4012
+
4013
+ for (const arg of this.argnames) {
4014
+ if (arg instanceof AST_SymbolFunarg || arg instanceof AST_Destructuring) {
4015
+ length++;
4016
+ }
4017
+ }
4018
+
4019
+ return length;
4020
+ }
4017
4021
  }, AST_Scope);
4018
4022
 
4019
4023
  var AST_Accessor = DEFNODE("Accessor", null, {
@@ -7087,11 +7091,15 @@ function OutputStream(options) {
7087
7091
  var do_add_mapping = mappings ? function() {
7088
7092
  mappings.forEach(function(mapping) {
7089
7093
  try {
7094
+ let name = !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name;
7095
+ if (name instanceof AST_Symbol) {
7096
+ name = name.name;
7097
+ }
7090
7098
  options.source_map.add(
7091
7099
  mapping.token.file,
7092
7100
  mapping.line, mapping.col,
7093
7101
  mapping.token.line, mapping.token.col,
7094
- !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
7102
+ is_basic_identifier_string(name) ? name : undefined
7095
7103
  );
7096
7104
  } catch(ex) {
7097
7105
  // Ignore bad mapping
@@ -7671,6 +7679,7 @@ function OutputStream(options) {
7671
7679
  var p = output.parent();
7672
7680
  return p instanceof AST_PropAccess && p.expression === this
7673
7681
  || p instanceof AST_Call && p.expression === this
7682
+ || p instanceof AST_Binary && p.operator === "**" && p.left === this
7674
7683
  || output.option("safari10") && p instanceof AST_UnaryPrefix;
7675
7684
  });
7676
7685
 
@@ -8888,7 +8897,9 @@ function OutputStream(options) {
8888
8897
  source = regexp_source_fix(source);
8889
8898
  flags = flags ? sort_regexp_flags(flags) : "";
8890
8899
  source = source.replace(r_slash_script, slash_script_replace);
8900
+
8891
8901
  output.print(output.to_utf8(`/${source}/${flags}`));
8902
+
8892
8903
  const parent = output.parent();
8893
8904
  if (
8894
8905
  parent instanceof AST_Binary
@@ -9183,6 +9194,10 @@ AST_Dot.prototype.shallow_cmp = mkshallow({
9183
9194
  property: "eq"
9184
9195
  });
9185
9196
 
9197
+ AST_DotHash.prototype.shallow_cmp = mkshallow({
9198
+ property: "eq"
9199
+ });
9200
+
9186
9201
  AST_Unary.prototype.shallow_cmp = mkshallow({
9187
9202
  operator: "eq"
9188
9203
  });
@@ -9488,7 +9503,14 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
9488
9503
  // scope when we encounter the AST_Defun node (which is
9489
9504
  // instanceof AST_Scope) but we get to the symbol a bit
9490
9505
  // later.
9491
- mark_export((node.scope = defun.parent_scope.get_defun_scope()).def_function(node, defun), 1);
9506
+ const closest_scope = defun.parent_scope;
9507
+
9508
+ // In strict mode, function definitions are block-scoped
9509
+ node.scope = tw.directives["use strict"]
9510
+ ? closest_scope
9511
+ : closest_scope.get_defun_scope();
9512
+
9513
+ mark_export(node.scope.def_function(node, defun), 1);
9492
9514
  } else if (node instanceof AST_SymbolClass) {
9493
9515
  mark_export(defun.def_variable(node, defun), 1);
9494
9516
  } else if (node instanceof AST_SymbolImport) {
@@ -9667,7 +9689,6 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
9667
9689
 
9668
9690
  AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
9669
9691
  this.variables = new Map(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
9670
- this.functions = new Map(); // map name to AST_SymbolDefun (functions defined in this scope)
9671
9692
  this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
9672
9693
  this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
9673
9694
  this.parent_scope = parent_scope; // the parent scope
@@ -9830,7 +9851,6 @@ AST_Scope.DEFMETHOD("find_variable", function(name) {
9830
9851
  AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
9831
9852
  var def = this.def_variable(symbol, init);
9832
9853
  if (!def.init || def.init instanceof AST_Defun) def.init = init;
9833
- this.functions.set(symbol.name, def);
9834
9854
  return def;
9835
9855
  });
9836
9856
 
@@ -10184,6 +10204,12 @@ AST_Node.prototype.size = function (compressor, stack) {
10184
10204
  let size = 0;
10185
10205
  walk_parent(this, (node, info) => {
10186
10206
  size += node._size(info);
10207
+
10208
+ // Braceless arrow functions have fake "return" statements
10209
+ if (node instanceof AST_Arrow && node.is_braceless()) {
10210
+ size += node.body[0].value._size(info);
10211
+ return true;
10212
+ }
10187
10213
  }, stack || (compressor && compressor.stack));
10188
10214
 
10189
10215
  // just to save a bit of memory
@@ -10228,7 +10254,6 @@ AST_With.prototype._size = () => 6;
10228
10254
 
10229
10255
  AST_Expansion.prototype._size = () => 3;
10230
10256
 
10231
- /*#__INLINE__*/
10232
10257
  const lambda_modifiers = func =>
10233
10258
  (func.is_generator ? 1 : 0) + (func.async ? 6 : 0);
10234
10259
 
@@ -10257,7 +10282,9 @@ AST_Arrow.prototype._size = function () {
10257
10282
  args_and_arrow += 2;
10258
10283
  }
10259
10284
 
10260
- return lambda_modifiers(this) + args_and_arrow + (Array.isArray(this.body) ? list_overhead(this.body) : this.body._size());
10285
+ const body_overhead = this.is_braceless() ? 0 : list_overhead(this.body) + 2;
10286
+
10287
+ return lambda_modifiers(this) + args_and_arrow + body_overhead;
10261
10288
  };
10262
10289
 
10263
10290
  AST_Destructuring.prototype._size = () => 2;
@@ -10632,11 +10659,8 @@ const TOP = 0b0000010000000000;
10632
10659
 
10633
10660
  const CLEAR_BETWEEN_PASSES = SQUEEZED | OPTIMIZED | TOP;
10634
10661
 
10635
- /*@__INLINE__*/
10636
10662
  const has_flag = (node, flag) => node.flags & flag;
10637
- /*@__INLINE__*/
10638
10663
  const set_flag = (node, flag) => { node.flags |= flag; };
10639
- /*@__INLINE__*/
10640
10664
  const clear_flag = (node, flag) => { node.flags &= ~flag; };
10641
10665
 
10642
10666
  class Compressor extends TreeWalker {
@@ -10679,7 +10703,7 @@ class Compressor extends TreeWalker {
10679
10703
  properties : !false_by_default,
10680
10704
  pure_getters : !false_by_default && "strict",
10681
10705
  pure_funcs : null,
10682
- reduce_funcs : null, // legacy
10706
+ reduce_funcs : !false_by_default,
10683
10707
  reduce_vars : !false_by_default,
10684
10708
  sequences : !false_by_default,
10685
10709
  side_effects : !false_by_default,
@@ -10979,7 +11003,7 @@ function is_modified(compressor, tw, node, value, level, immutable) {
10979
11003
  && parent.expression === node
10980
11004
  && !(value instanceof AST_Arrow)
10981
11005
  && !(value instanceof AST_Class)
10982
- && !parent.is_expr_pure(compressor)
11006
+ && !parent.is_callee_pure(compressor)
10983
11007
  && (!(value instanceof AST_Function)
10984
11008
  || !(parent instanceof AST_New) && value.contains_this())) {
10985
11009
  return true;
@@ -11284,9 +11308,6 @@ function is_modified(compressor, tw, node, value, level, immutable) {
11284
11308
  return true;
11285
11309
  });
11286
11310
  def_reduce_vars(AST_Call, function (tw) {
11287
- // TODO this block should just be { return } but
11288
- // for some reason the _walk function of AST_Call walks the callee last
11289
-
11290
11311
  this.expression.walk(tw);
11291
11312
 
11292
11313
  if (this.optional) {
@@ -11839,8 +11860,11 @@ function tighten_body(statements, compressor) {
11839
11860
  || node instanceof AST_Debugger
11840
11861
  || node instanceof AST_Destructuring
11841
11862
  || node instanceof AST_Expansion
11842
- && node.expression instanceof AST_Symbol
11843
- && node.expression.definition().references.length > 1
11863
+ && node.expression instanceof AST_Symbol
11864
+ && (
11865
+ node.expression instanceof AST_This
11866
+ || node.expression.definition().references.length > 1
11867
+ )
11844
11868
  || node instanceof AST_IterationStatement && !(node instanceof AST_For)
11845
11869
  || node instanceof AST_LoopControl
11846
11870
  || node instanceof AST_Try
@@ -11934,6 +11958,7 @@ function tighten_body(statements, compressor) {
11934
11958
  if (stop_after === node) abort = true;
11935
11959
  if (stop_if_hit === node) stop_if_hit = null;
11936
11960
  });
11961
+
11937
11962
  var multi_replacer = new TreeTransformer(function(node) {
11938
11963
  if (abort) return node;
11939
11964
  // Skip nodes before `candidate` as quickly as possible
@@ -11956,6 +11981,7 @@ function tighten_body(statements, compressor) {
11956
11981
  // Skip (non-executed) functions and (leading) default case in switch statements
11957
11982
  if (node instanceof AST_Default || node instanceof AST_Scope) return node;
11958
11983
  });
11984
+
11959
11985
  while (--stat_index >= 0) {
11960
11986
  // Treat parameters as collapsible in IIFE, i.e.
11961
11987
  // function(a, b){ ... }(x());
@@ -12131,7 +12157,10 @@ function tighten_body(statements, compressor) {
12131
12157
  function extract_candidates(expr) {
12132
12158
  hit_stack.push(expr);
12133
12159
  if (expr instanceof AST_Assign) {
12134
- if (!expr.left.has_side_effects(compressor)) {
12160
+ if (
12161
+ !expr.left.has_side_effects(compressor)
12162
+ && !(expr.right instanceof AST_Chain)
12163
+ ) {
12135
12164
  candidates.push(hit_stack.slice());
12136
12165
  }
12137
12166
  extract_candidates(expr.right);
@@ -12194,7 +12223,7 @@ function tighten_body(statements, compressor) {
12194
12223
  candidates.push(hit_stack.slice());
12195
12224
  }
12196
12225
  } else if (expr instanceof AST_VarDef) {
12197
- if (expr.value) {
12226
+ if (expr.value && !(expr.value instanceof AST_Chain)) {
12198
12227
  candidates.push(hit_stack.slice());
12199
12228
  extract_candidates(expr.value);
12200
12229
  }
@@ -13009,7 +13038,13 @@ function is_undefined(node, compressor) {
13009
13038
  });
13010
13039
  def_may_throw_on_access(AST_Dot, function(compressor) {
13011
13040
  if (!is_strict(compressor)) return false;
13012
- if (this.expression instanceof AST_Function && this.property == "prototype") return false;
13041
+
13042
+ if (this.property == "prototype") {
13043
+ return !(
13044
+ this.expression instanceof AST_Function
13045
+ || this.expression instanceof AST_Class
13046
+ );
13047
+ }
13013
13048
  return true;
13014
13049
  });
13015
13050
  def_may_throw_on_access(AST_Chain, function(compressor) {
@@ -13351,9 +13386,7 @@ var static_fns = convert_to_predicate({
13351
13386
  if (compressor.option("unsafe")) {
13352
13387
  var fn = function() {};
13353
13388
  fn.node = this;
13354
- fn.toString = function() {
13355
- return this.node.print_to_string();
13356
- };
13389
+ fn.toString = () => this.print_to_string();
13357
13390
  return fn;
13358
13391
  }
13359
13392
  return this;
@@ -13534,6 +13567,14 @@ var static_fns = convert_to_predicate({
13534
13567
  "POSITIVE_INFINITY",
13535
13568
  ],
13536
13569
  });
13570
+ const regexp_flags = new Set([
13571
+ "dotAll",
13572
+ "global",
13573
+ "ignoreCase",
13574
+ "multiline",
13575
+ "sticky",
13576
+ "unicode",
13577
+ ]);
13537
13578
  def_eval(AST_PropAccess, function(compressor, depth) {
13538
13579
  if (this.optional) {
13539
13580
  const obj = this.expression._eval(compressor, depth);
@@ -13566,12 +13607,19 @@ var static_fns = convert_to_predicate({
13566
13607
  val = global_objs[exp.name];
13567
13608
  } else {
13568
13609
  val = exp._eval(compressor, depth + 1);
13610
+ if (val instanceof RegExp) {
13611
+ if (key == "source") {
13612
+ return regexp_source_fix(val.source);
13613
+ } else if (key == "flags" || regexp_flags.has(key)) {
13614
+ return val[key];
13615
+ }
13616
+ }
13569
13617
  if (!val || val === exp || !HOP(val, key)) return this;
13570
13618
  if (typeof val == "function") switch (key) {
13571
13619
  case "name":
13572
13620
  return val.node.name ? val.node.name.name : "";
13573
13621
  case "length":
13574
- return val.node.argnames.length;
13622
+ return val.node.length_property();
13575
13623
  default:
13576
13624
  return this;
13577
13625
  }
@@ -13623,6 +13671,7 @@ var static_fns = convert_to_predicate({
13623
13671
  var arg = this.args[i];
13624
13672
  var value = arg._eval(compressor, depth);
13625
13673
  if (arg === value) return this;
13674
+ if (arg instanceof AST_Lambda) return this;
13626
13675
  args.push(value);
13627
13676
  }
13628
13677
  try {
@@ -13722,7 +13771,7 @@ var static_fns = convert_to_predicate({
13722
13771
  });
13723
13772
 
13724
13773
  var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError");
13725
- AST_Call.DEFMETHOD("is_expr_pure", function(compressor) {
13774
+ AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
13726
13775
  if (compressor.option("unsafe")) {
13727
13776
  var expr = this.expression;
13728
13777
  var first_arg = (this.args && this.args[0] && this.args[0].evaluate(compressor));
@@ -13792,7 +13841,7 @@ const pure_prop_access_globals = new Set([
13792
13841
  });
13793
13842
  def_has_side_effects(AST_Call, function(compressor) {
13794
13843
  if (
13795
- !this.is_expr_pure(compressor)
13844
+ !this.is_callee_pure(compressor)
13796
13845
  && (!this.expression.is_call_pure(compressor)
13797
13846
  || this.expression.has_side_effects(compressor))
13798
13847
  ) {
@@ -13882,7 +13931,7 @@ const pure_prop_access_globals = new Set([
13882
13931
  || this.expression.has_side_effects(compressor);
13883
13932
  });
13884
13933
  def_has_side_effects(AST_Sub, function(compressor) {
13885
- if (this.optional && is_nullish(this.expression)) {
13934
+ if (this.optional && is_nullish(this.expression, compressor)) {
13886
13935
  return false;
13887
13936
  }
13888
13937
 
@@ -13952,9 +14001,9 @@ const pure_prop_access_globals = new Set([
13952
14001
  return any(this.body, compressor);
13953
14002
  });
13954
14003
  def_may_throw(AST_Call, function(compressor) {
13955
- if (this.optional && is_nullish(this.expression)) return false;
14004
+ if (this.optional && is_nullish(this.expression, compressor)) return false;
13956
14005
  if (any(this.args, compressor)) return true;
13957
- if (this.is_expr_pure(compressor)) return false;
14006
+ if (this.is_callee_pure(compressor)) return false;
13958
14007
  if (this.expression.may_throw(compressor)) return true;
13959
14008
  return !(this.expression instanceof AST_Lambda)
13960
14009
  || any(this.expression.body, compressor);
@@ -14015,7 +14064,7 @@ const pure_prop_access_globals = new Set([
14015
14064
  || this.expression.may_throw(compressor);
14016
14065
  });
14017
14066
  def_may_throw(AST_Sub, function(compressor) {
14018
- if (this.optional && is_nullish(this.expression)) return false;
14067
+ if (this.optional && is_nullish(this.expression, compressor)) return false;
14019
14068
 
14020
14069
  return !this.optional && this.expression.may_throw_on_access(compressor)
14021
14070
  || this.expression.may_throw(compressor)
@@ -14828,11 +14877,11 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
14828
14877
  def_drop_side_effect_free(AST_Constant, return_null);
14829
14878
  def_drop_side_effect_free(AST_This, return_null);
14830
14879
  def_drop_side_effect_free(AST_Call, function(compressor, first_in_statement) {
14831
- if (this.optional && is_nullish(this.expression)) {
14880
+ if (this.optional && is_nullish(this.expression, compressor)) {
14832
14881
  return make_node(AST_Undefined, this);
14833
14882
  }
14834
14883
 
14835
- if (!this.is_expr_pure(compressor)) {
14884
+ if (!this.is_callee_pure(compressor)) {
14836
14885
  if (this.expression.is_call_pure(compressor)) {
14837
14886
  var exprs = this.args.slice();
14838
14887
  exprs.unshift(this.expression.expression);
@@ -14975,7 +15024,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
14975
15024
  });
14976
15025
  def_drop_side_effect_free(AST_Dot, function(compressor, first_in_statement) {
14977
15026
  if (this.optional) {
14978
- return is_nullish(this.expression) ? make_node(AST_Undefined, this) : this;
15027
+ return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this) : this;
14979
15028
  }
14980
15029
  if (this.expression.may_throw_on_access(compressor)) return this;
14981
15030
 
@@ -14983,7 +15032,7 @@ AST_Scope.DEFMETHOD("hoist_properties", function(compressor) {
14983
15032
  });
14984
15033
  def_drop_side_effect_free(AST_Sub, function(compressor, first_in_statement) {
14985
15034
  if (this.optional) {
14986
- return is_nullish(this.expression) ? make_node(AST_Undefined, this): this;
15035
+ return is_nullish(this.expression, compressor) ? make_node(AST_Undefined, this): this;
14987
15036
  }
14988
15037
  if (this.expression.may_throw_on_access(compressor)) return this;
14989
15038
 
@@ -15508,11 +15557,11 @@ def_optimize(AST_Definitions, function(self) {
15508
15557
  return self;
15509
15558
  });
15510
15559
 
15511
- def_optimize(AST_VarDef, function(self) {
15560
+ def_optimize(AST_VarDef, function(self, compressor) {
15512
15561
  if (
15513
15562
  self.name instanceof AST_SymbolLet
15514
15563
  && self.value != null
15515
- && is_undefined(self.value)
15564
+ && is_undefined(self.value, compressor)
15516
15565
  ) {
15517
15566
  self.value = null;
15518
15567
  }
@@ -15550,7 +15599,7 @@ def_optimize(AST_Call, function(self, compressor) {
15550
15599
  }
15551
15600
  }
15552
15601
 
15553
- if (self.optional && is_nullish(fn)) {
15602
+ if (self.optional && is_nullish(fn, compressor)) {
15554
15603
  return make_node(AST_Undefined, self);
15555
15604
  }
15556
15605
 
@@ -15852,7 +15901,7 @@ def_optimize(AST_Call, function(self, compressor) {
15852
15901
 
15853
15902
  var stat = is_func && fn.body[0];
15854
15903
  var is_regular_func = is_func && !fn.is_generator && !fn.async;
15855
- var can_inline = is_regular_func && compressor.option("inline") && !self.is_expr_pure(compressor);
15904
+ var can_inline = is_regular_func && compressor.option("inline") && !self.is_callee_pure(compressor);
15856
15905
  if (can_inline && stat instanceof AST_Return) {
15857
15906
  let returned = stat.value;
15858
15907
  if (!returned || returned.is_constant_expression()) {
@@ -16576,7 +16625,7 @@ def_optimize(AST_Binary, function(self, compressor) {
16576
16625
  }
16577
16626
  break;
16578
16627
  case "??":
16579
- if (is_nullish(self.left)) {
16628
+ if (is_nullish(self.left, compressor)) {
16580
16629
  return self.right;
16581
16630
  }
16582
16631
 
@@ -16878,19 +16927,26 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
16878
16927
  let fixed = self.fixed_value();
16879
16928
  let single_use = def.single_use
16880
16929
  && !(parent instanceof AST_Call
16881
- && (parent.is_expr_pure(compressor))
16930
+ && (parent.is_callee_pure(compressor))
16882
16931
  || has_annotation(parent, _NOINLINE))
16883
16932
  && !(parent instanceof AST_Export
16884
16933
  && fixed instanceof AST_Lambda
16885
16934
  && fixed.name);
16886
16935
 
16936
+ if (single_use && fixed instanceof AST_Node) {
16937
+ single_use =
16938
+ !fixed.has_side_effects(compressor)
16939
+ && !fixed.may_throw(compressor);
16940
+ }
16941
+
16887
16942
  if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
16888
16943
  if (retain_top_func(fixed, compressor)) {
16889
16944
  single_use = false;
16890
16945
  } else if (def.scope !== self.scope
16891
16946
  && (def.escaped == 1
16892
16947
  || has_flag(fixed, INLINED)
16893
- || within_array_or_object_literal(compressor))) {
16948
+ || within_array_or_object_literal(compressor)
16949
+ || !compressor.option("reduce_funcs"))) {
16894
16950
  single_use = false;
16895
16951
  } else if (recursive_ref(compressor, def)) {
16896
16952
  single_use = false;
@@ -16906,6 +16962,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
16906
16962
  }
16907
16963
  }
16908
16964
  }
16965
+
16909
16966
  if (single_use && fixed instanceof AST_Lambda) {
16910
16967
  single_use =
16911
16968
  def.scope === self.scope
@@ -16915,15 +16972,6 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
16915
16972
  && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
16916
16973
  && !(fixed.name && fixed.name.definition().recursive_refs > 0);
16917
16974
  }
16918
- if (single_use && fixed instanceof AST_Class) {
16919
- const extends_inert = !fixed.extends
16920
- || !fixed.extends.may_throw(compressor)
16921
- && !fixed.extends.has_side_effects(compressor);
16922
- single_use = extends_inert
16923
- && !fixed.properties.some(prop =>
16924
- prop.may_throw(compressor) || prop.has_side_effects(compressor)
16925
- );
16926
- }
16927
16975
 
16928
16976
  if (single_use && fixed) {
16929
16977
  if (fixed instanceof AST_DefClass) {
@@ -17000,6 +17048,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
17000
17048
  }
17001
17049
  }
17002
17050
  }
17051
+
17003
17052
  return self;
17004
17053
  });
17005
17054
 
@@ -17184,20 +17233,20 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
17184
17233
  return self;
17185
17234
  });
17186
17235
 
17187
- function is_nullish(node) {
17236
+ function is_nullish(node, compressor) {
17188
17237
  let fixed;
17189
17238
  return (
17190
17239
  node instanceof AST_Null
17191
- || is_undefined(node)
17240
+ || is_undefined(node, compressor)
17192
17241
  || (
17193
17242
  node instanceof AST_SymbolRef
17194
17243
  && (fixed = node.definition().fixed) instanceof AST_Node
17195
- && is_nullish(fixed)
17244
+ && is_nullish(fixed, compressor)
17196
17245
  )
17197
17246
  // Recurse into those optional chains!
17198
- || node instanceof AST_PropAccess && node.optional && is_nullish(node.expression)
17199
- || node instanceof AST_Call && node.optional && is_nullish(node.expression)
17200
- || node instanceof AST_Chain && is_nullish(node.expression)
17247
+ || node instanceof AST_PropAccess && node.optional && is_nullish(node.expression, compressor)
17248
+ || node instanceof AST_Call && node.optional && is_nullish(node.expression, compressor)
17249
+ || node instanceof AST_Chain && is_nullish(node.expression, compressor)
17201
17250
  );
17202
17251
  }
17203
17252
 
@@ -17212,8 +17261,8 @@ function is_nullish_check(check, check_subject, compressor) {
17212
17261
  && check.operator === "=="
17213
17262
  // which side is nullish?
17214
17263
  && (
17215
- (nullish_side = is_nullish(check.left) && check.left)
17216
- || (nullish_side = is_nullish(check.right) && check.right)
17264
+ (nullish_side = is_nullish(check.left, compressor) && check.left)
17265
+ || (nullish_side = is_nullish(check.right, compressor) && check.right)
17217
17266
  )
17218
17267
  // is the other side the same as the check_subject
17219
17268
  && (
@@ -17251,12 +17300,12 @@ function is_nullish_check(check, check_subject, compressor) {
17251
17300
  null_cmp = cmp;
17252
17301
  defined_side = cmp.left;
17253
17302
  }
17254
- if (is_undefined(cmp.left)) {
17303
+ if (is_undefined(cmp.left, compressor)) {
17255
17304
  found++;
17256
17305
  undefined_cmp = cmp;
17257
17306
  defined_side = cmp.right;
17258
17307
  }
17259
- if (is_undefined(cmp.right)) {
17308
+ if (is_undefined(cmp.right, compressor)) {
17260
17309
  found++;
17261
17310
  undefined_cmp = cmp;
17262
17311
  defined_side = cmp.left;
@@ -17586,27 +17635,40 @@ function safe_to_flatten(value, compressor) {
17586
17635
 
17587
17636
  AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) {
17588
17637
  if (!compressor.option("properties")) return;
17638
+ if (key === "__proto__") return;
17639
+
17589
17640
  var arrows = compressor.option("unsafe_arrows") && compressor.option("ecma") >= 2015;
17590
17641
  var expr = this.expression;
17591
17642
  if (expr instanceof AST_Object) {
17592
17643
  var props = expr.properties;
17644
+
17593
17645
  for (var i = props.length; --i >= 0;) {
17594
17646
  var prop = props[i];
17647
+
17595
17648
  if ("" + (prop instanceof AST_ConciseMethod ? prop.key.name : prop.key) == key) {
17596
- if (!props.every((prop) => {
17597
- return prop instanceof AST_ObjectKeyVal
17598
- || arrows && prop instanceof AST_ConciseMethod && !prop.is_generator;
17599
- })) break;
17600
- if (!safe_to_flatten(prop.value, compressor)) break;
17649
+ const all_props_flattenable = props.every((p) =>
17650
+ (p instanceof AST_ObjectKeyVal
17651
+ || arrows && p instanceof AST_ConciseMethod && !p.is_generator
17652
+ )
17653
+ && !p.computed_key()
17654
+ );
17655
+
17656
+ if (!all_props_flattenable) return;
17657
+ if (!safe_to_flatten(prop.value, compressor)) return;
17658
+
17601
17659
  return make_node(AST_Sub, this, {
17602
17660
  expression: make_node(AST_Array, expr, {
17603
17661
  elements: props.map(function(prop) {
17604
17662
  var v = prop.value;
17605
- if (v instanceof AST_Accessor) v = make_node(AST_Function, v, v);
17663
+ if (v instanceof AST_Accessor) {
17664
+ v = make_node(AST_Function, v, v);
17665
+ }
17666
+
17606
17667
  var k = prop.key;
17607
17668
  if (k instanceof AST_Node && !(k instanceof AST_SymbolMethod)) {
17608
17669
  return make_sequence(prop, [ k, v ]);
17609
17670
  }
17671
+
17610
17672
  return v;
17611
17673
  })
17612
17674
  }),
@@ -17744,7 +17806,7 @@ def_optimize(AST_Sub, function(self, compressor) {
17744
17806
  ev = make_node_from_constant(ev, self).optimize(compressor);
17745
17807
  return best_of(compressor, ev, self);
17746
17808
  }
17747
- if (self.optional && is_nullish(self.expression)) {
17809
+ if (self.optional && is_nullish(self.expression, compressor)) {
17748
17810
  return make_node(AST_Undefined, self);
17749
17811
  }
17750
17812
  return self;
@@ -17818,7 +17880,7 @@ def_optimize(AST_Dot, function(self, compressor) {
17818
17880
  ev = make_node_from_constant(ev, self).optimize(compressor);
17819
17881
  return best_of(compressor, ev, self);
17820
17882
  }
17821
- if (self.optional && is_nullish(self.expression)) {
17883
+ if (self.optional && is_nullish(self.expression, compressor)) {
17822
17884
  return make_node(AST_Undefined, self);
17823
17885
  }
17824
17886
  return self;
@@ -17862,7 +17924,7 @@ def_optimize(AST_Array, function(self, compressor) {
17862
17924
  return self;
17863
17925
  });
17864
17926
 
17865
- function inline_object_prop_spread(props) {
17927
+ function inline_object_prop_spread(props, compressor) {
17866
17928
  for (var i = 0; i < props.length; i++) {
17867
17929
  var prop = props[i];
17868
17930
  if (prop instanceof AST_Expansion) {
@@ -17880,6 +17942,9 @@ function inline_object_prop_spread(props) {
17880
17942
  // non-iterable value silently does nothing; it is thus safe
17881
17943
  // to remove. AST_String is the only iterable AST_Constant.
17882
17944
  props.splice(i, 1);
17945
+ } else if (is_nullish(expr, compressor)) {
17946
+ // Likewise, null and undefined can be silently removed.
17947
+ props.splice(i, 1);
17883
17948
  }
17884
17949
  }
17885
17950
  }
@@ -17890,7 +17955,7 @@ def_optimize(AST_Object, function(self, compressor) {
17890
17955
  if (optimized !== self) {
17891
17956
  return optimized;
17892
17957
  }
17893
- inline_object_prop_spread(self.properties);
17958
+ inline_object_prop_spread(self.properties, compressor);
17894
17959
  return self;
17895
17960
  });
17896
17961
 
@@ -17983,7 +18048,7 @@ def_optimize(AST_TemplateString, function(self, compressor) {
17983
18048
  && (
17984
18049
  segments[1].is_string(compressor)
17985
18050
  || segments[1].is_number(compressor)
17986
- || is_nullish(segments[1])
18051
+ || is_nullish(segments[1], compressor)
17987
18052
  || compressor.option("unsafe")
17988
18053
  )
17989
18054
  ) {
@@ -22374,6 +22439,7 @@ var domprops = [
22374
22439
  "exponent",
22375
22440
  "exponentialRampToValueAtTime",
22376
22441
  "exportKey",
22442
+ "exports",
22377
22443
  "extend",
22378
22444
  "extensions",
22379
22445
  "extentNode",
@@ -26405,6 +26471,7 @@ async function minify(files, options) {
26405
26471
  rename: undefined,
26406
26472
  safari10: false,
26407
26473
  sourceMap: false,
26474
+ spidermonkey: false,
26408
26475
  timings: false,
26409
26476
  toplevel: false,
26410
26477
  warnings: false,
@@ -26476,20 +26543,32 @@ async function minify(files, options) {
26476
26543
  if (files instanceof AST_Toplevel) {
26477
26544
  toplevel = files;
26478
26545
  } else {
26479
- if (typeof files == "string") {
26546
+ if (typeof files == "string" || (options.parse.spidermonkey && !Array.isArray(files))) {
26480
26547
  files = [ files ];
26481
26548
  }
26482
26549
  options.parse = options.parse || {};
26483
26550
  options.parse.toplevel = null;
26484
- for (var name in files) if (HOP(files, name)) {
26485
- options.parse.filename = name;
26486
- options.parse.toplevel = parse(files[name], options.parse);
26487
- if (options.sourceMap && options.sourceMap.content == "inline") {
26488
- if (Object.keys(files).length > 1)
26489
- throw new Error("inline source map only works with singular input");
26490
- options.sourceMap.content = read_source_map(files[name]);
26551
+
26552
+ if (options.parse.spidermonkey) {
26553
+ options.parse.toplevel = AST_Node.from_mozilla_ast(Object.keys(files).reduce(function(toplevel, name) {
26554
+ if (!toplevel) return files[name];
26555
+ toplevel.body = toplevel.body.concat(files[name].body);
26556
+ return toplevel;
26557
+ }, null));
26558
+ } else {
26559
+ delete options.parse.spidermonkey;
26560
+
26561
+ for (var name in files) if (HOP(files, name)) {
26562
+ options.parse.filename = name;
26563
+ options.parse.toplevel = parse(files[name], options.parse);
26564
+ if (options.sourceMap && options.sourceMap.content == "inline") {
26565
+ if (Object.keys(files).length > 1)
26566
+ throw new Error("inline source map only works with singular input");
26567
+ options.sourceMap.content = read_source_map(files[name]);
26568
+ }
26491
26569
  }
26492
26570
  }
26571
+
26493
26572
  toplevel = options.parse.toplevel;
26494
26573
  }
26495
26574
  if (quoted_props && options.mangle.properties.keep_quoted !== "strict") {
@@ -26525,6 +26604,9 @@ async function minify(files, options) {
26525
26604
  if (options.format.ast) {
26526
26605
  result.ast = toplevel;
26527
26606
  }
26607
+ if (options.format.spidermonkey) {
26608
+ result.ast = toplevel.to_mozilla_ast();
26609
+ }
26528
26610
  if (!HOP(options.format, "code") || options.format.code) {
26529
26611
  if (options.sourceMap) {
26530
26612
  options.format.source_map = await SourceMap({
@@ -26542,6 +26624,7 @@ async function minify(files, options) {
26542
26624
  }
26543
26625
  delete options.format.ast;
26544
26626
  delete options.format.code;
26627
+ delete options.format.spidermonkey;
26545
26628
  var stream = OutputStream(options.format);
26546
26629
  toplevel.print(stream);
26547
26630
  result.code = stream.get();
@@ -26834,7 +26917,6 @@ async function run_cli({ program, packageJson, fs, path }) {
26834
26917
  case "enclosed":
26835
26918
  return value.length ? value.map(symdef) : undefined;
26836
26919
  case "variables":
26837
- case "functions":
26838
26920
  case "globals":
26839
26921
  return value.size ? collect_from_map(value, symdef) : undefined;
26840
26922
  }
@@ -26847,7 +26929,6 @@ async function run_cli({ program, packageJson, fs, path }) {
26847
26929
  };
26848
26930
  if (value.block_scope) {
26849
26931
  result.variables = value.block_scope.variables;
26850
- result.functions = value.block_scope.functions;
26851
26932
  result.enclosed = value.block_scope.enclosed;
26852
26933
  }
26853
26934
  value.CTOR.PROPS.forEach(function(prop) {