terser 5.16.1 → 5.17.7

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.
@@ -2,7 +2,7 @@
2
2
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@jridgewell/source-map')) :
3
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, sourceMap) { 'use strict';
5
+ })(this, (function (exports, sourceMap) { 'use strict';
6
6
 
7
7
  /***********************************************************************
8
8
 
@@ -100,48 +100,26 @@ function return_this() { return this; }
100
100
  function return_null() { return null; }
101
101
 
102
102
  var MAP = (function() {
103
- function MAP(a, f, backwards) {
104
- var ret = [], top = [], i;
105
- function doit() {
106
- var val = f(a[i], i);
107
- var is_last = val instanceof Last;
108
- if (is_last) val = val.v;
109
- if (val instanceof AtTop) {
110
- val = val.v;
111
- if (val instanceof Splice) {
112
- top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
113
- } else {
114
- top.push(val);
115
- }
116
- } else if (val !== skip) {
117
- if (val instanceof Splice) {
118
- ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
119
- } else {
120
- ret.push(val);
121
- }
122
- }
123
- return is_last;
124
- }
125
- if (Array.isArray(a)) {
126
- if (backwards) {
127
- for (i = a.length; --i >= 0;) if (doit()) break;
128
- ret.reverse();
129
- top.reverse();
130
- } else {
131
- for (i = 0; i < a.length; ++i) if (doit()) break;
103
+ function MAP(a, tw, allow_splicing = true) {
104
+ const new_a = [];
105
+
106
+ for (let i = 0; i < a.length; ++i) {
107
+ let item = a[i];
108
+ let ret = item.transform(tw, allow_splicing);
109
+
110
+ if (ret instanceof AST_Node) {
111
+ new_a.push(ret);
112
+ } else if (ret instanceof Splice) {
113
+ new_a.push(...ret.v);
132
114
  }
133
- } else {
134
- for (i in a) if (HOP(a, i)) if (doit()) break;
135
115
  }
136
- return top.concat(ret);
116
+
117
+ return new_a;
137
118
  }
138
- MAP.at_top = function(val) { return new AtTop(val); };
119
+
139
120
  MAP.splice = function(val) { return new Splice(val); };
140
- MAP.last = function(val) { return new Last(val); };
141
- var skip = MAP.skip = {};
142
- function AtTop(val) { this.v = val; }
121
+ MAP.skip = {};
143
122
  function Splice(val) { this.v = val; }
144
- function Last(val) { this.v = val; }
145
123
  return MAP;
146
124
  })();
147
125
 
@@ -261,7 +239,7 @@ const re_safe_regexp = /^[\\/|\0\s\w^$.[\]()]*$/;
261
239
  /** Check if the regexp is safe for Terser to create without risking a RegExp DOS */
262
240
  const regexp_is_safe = (source) => re_safe_regexp.test(source);
263
241
 
264
- const all_flags = "dgimsuy";
242
+ const all_flags = "dgimsuyv";
265
243
  function sort_regexp_flags(flags) {
266
244
  const existing_flags = new Set(flags.split(""));
267
245
  let out = "";
@@ -286,6 +264,10 @@ function set_annotation(node, annotation) {
286
264
  node._annotations |= annotation;
287
265
  }
288
266
 
267
+ function clear_annotation(node, annotation) {
268
+ node._annotations &= ~annotation;
269
+ }
270
+
289
271
  /***********************************************************************
290
272
 
291
273
  A JavaScript tokenizer / parser / beautifier / compressor.
@@ -426,6 +408,19 @@ var UNICODE = {
426
408
  ID_Continue: /(?:[$0-9A-Z_a-z\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF])+/,
427
409
  };
428
410
 
411
+ try {
412
+ UNICODE = {
413
+ // https://262.ecma-international.org/13.0/#prod-IdentifierStartChar
414
+ // $, _, ID_Start
415
+ ID_Start: new RegExp("[_$\\p{ID_Start}]", "u"),
416
+ // https://262.ecma-international.org/13.0/#prod-IdentifierPartChar
417
+ // $, zero-width-joiner, zero-width-non-joiner, ID_Continue
418
+ ID_Continue: new RegExp("[$\\u200C\\u200D\\p{ID_Continue}]+", "u"),
419
+ };
420
+ } catch(e) {
421
+ // Could not use modern JS \p{...}. UNICODE is already defined above so let's continue
422
+ }
423
+
429
424
  function get_full_char(str, pos) {
430
425
  if (is_surrogate_pair_head(str.charCodeAt(pos))) {
431
426
  if (is_surrogate_pair_tail(str.charCodeAt(pos + 1))) {
@@ -2219,7 +2214,12 @@ function parse($TEXT, options) {
2219
2214
  }
2220
2215
 
2221
2216
  function try_() {
2222
- var body = block_(), bcatch = null, bfinally = null;
2217
+ var body, bcatch = null, bfinally = null;
2218
+ body = new AST_TryBlock({
2219
+ start : S.token,
2220
+ body : block_(),
2221
+ end : prev(),
2222
+ });
2223
2223
  if (is("keyword", "catch")) {
2224
2224
  var start = S.token;
2225
2225
  next();
@@ -2255,14 +2255,20 @@ function parse($TEXT, options) {
2255
2255
  });
2256
2256
  }
2257
2257
 
2258
+ /**
2259
+ * var
2260
+ * vardef1 = 2,
2261
+ * vardef2 = 3;
2262
+ */
2258
2263
  function vardefs(no_in, kind) {
2259
- var a = [];
2264
+ var var_defs = [];
2260
2265
  var def;
2261
2266
  for (;;) {
2262
2267
  var sym_type =
2263
2268
  kind === "var" ? AST_SymbolVar :
2264
2269
  kind === "const" ? AST_SymbolConst :
2265
2270
  kind === "let" ? AST_SymbolLet : null;
2271
+ // var { a } = b
2266
2272
  if (is("punc", "{") || is("punc", "[")) {
2267
2273
  def = new AST_VarDef({
2268
2274
  start: S.token,
@@ -2282,12 +2288,12 @@ function parse($TEXT, options) {
2282
2288
  });
2283
2289
  if (def.name.name == "import") croak("Unexpected token: import");
2284
2290
  }
2285
- a.push(def);
2291
+ var_defs.push(def);
2286
2292
  if (!is("punc", ","))
2287
2293
  break;
2288
2294
  next();
2289
2295
  }
2290
- return a;
2296
+ return var_defs;
2291
2297
  }
2292
2298
 
2293
2299
  var var_ = function(no_in) {
@@ -2366,6 +2372,7 @@ function parse($TEXT, options) {
2366
2372
  value : tok.value,
2367
2373
  quote : tok.quote
2368
2374
  });
2375
+ annotate(ret);
2369
2376
  break;
2370
2377
  case "regexp":
2371
2378
  const [_, source, flags] = tok.value.match(/^\/(.*)\/(\w*)$/);
@@ -2448,8 +2455,8 @@ function parse($TEXT, options) {
2448
2455
  if (is("operator", "new")) {
2449
2456
  return new_(allow_calls);
2450
2457
  }
2451
- if (is("operator", "import")) {
2452
- return import_meta();
2458
+ if (is("name", "import") && is_token(peek(), "punc", ".")) {
2459
+ return import_meta(allow_calls);
2453
2460
  }
2454
2461
  var start = S.token;
2455
2462
  var peeked;
@@ -2942,21 +2949,22 @@ function parse($TEXT, options) {
2942
2949
  });
2943
2950
  }
2944
2951
 
2945
- function import_meta() {
2952
+ function import_meta(allow_calls) {
2946
2953
  var start = S.token;
2947
- expect_token("operator", "import");
2954
+ expect_token("name", "import");
2948
2955
  expect_token("punc", ".");
2949
2956
  expect_token("name", "meta");
2950
2957
  return subscripts(new AST_ImportMeta({
2951
2958
  start: start,
2952
2959
  end: prev()
2953
- }), false);
2960
+ }), allow_calls);
2954
2961
  }
2955
2962
 
2956
2963
  function map_name(is_import) {
2957
- function make_symbol(type) {
2964
+ function make_symbol(type, quote) {
2958
2965
  return new type({
2959
2966
  name: as_property_name(),
2967
+ quote: quote || undefined,
2960
2968
  start: prev(),
2961
2969
  end: prev()
2962
2970
  });
@@ -2969,16 +2977,16 @@ function parse($TEXT, options) {
2969
2977
  var name;
2970
2978
 
2971
2979
  if (is_import) {
2972
- foreign_name = make_symbol(foreign_type);
2980
+ foreign_name = make_symbol(foreign_type, start.quote);
2973
2981
  } else {
2974
- name = make_symbol(type);
2982
+ name = make_symbol(type, start.quote);
2975
2983
  }
2976
2984
  if (is("name", "as")) {
2977
2985
  next(); // The "as" word
2978
2986
  if (is_import) {
2979
2987
  name = make_symbol(type);
2980
2988
  } else {
2981
- foreign_name = make_symbol(foreign_type);
2989
+ foreign_name = make_symbol(foreign_type, S.token.quote);
2982
2990
  }
2983
2991
  } else if (is_import) {
2984
2992
  name = new type(foreign_name);
@@ -2994,20 +3002,26 @@ function parse($TEXT, options) {
2994
3002
  });
2995
3003
  }
2996
3004
 
2997
- function map_nameAsterisk(is_import, name) {
3005
+ function map_nameAsterisk(is_import, import_or_export_foreign_name) {
2998
3006
  var foreign_type = is_import ? AST_SymbolImportForeign : AST_SymbolExportForeign;
2999
3007
  var type = is_import ? AST_SymbolImport : AST_SymbolExport;
3000
3008
  var start = S.token;
3001
- var foreign_name;
3009
+ var name, foreign_name;
3002
3010
  var end = prev();
3003
3011
 
3012
+ if (is_import) {
3013
+ name = import_or_export_foreign_name;
3014
+ } else {
3015
+ foreign_name = import_or_export_foreign_name;
3016
+ }
3017
+
3004
3018
  name = name || new type({
3005
3019
  start: start,
3006
3020
  name: "*",
3007
3021
  end: end,
3008
3022
  });
3009
3023
 
3010
- foreign_name = new foreign_type({
3024
+ foreign_name = foreign_name || new foreign_type({
3011
3025
  start: start,
3012
3026
  name: "*",
3013
3027
  end: end,
@@ -3036,9 +3050,9 @@ function parse($TEXT, options) {
3036
3050
  } else if (is("operator", "*")) {
3037
3051
  var name;
3038
3052
  next();
3039
- if (is_import && is("name", "as")) {
3053
+ if (is("name", "as")) {
3040
3054
  next(); // The "as" word
3041
- name = as_symbol(is_import ? AST_SymbolImport : AST_SymbolExportForeign);
3055
+ name = is_import ? as_symbol(AST_SymbolImport) : as_symbol_or_string(AST_SymbolExportForeign);
3042
3056
  }
3043
3057
  names = [map_nameAsterisk(is_import, name)];
3044
3058
  }
@@ -3203,6 +3217,27 @@ function parse($TEXT, options) {
3203
3217
  return sym;
3204
3218
  }
3205
3219
 
3220
+ function as_symbol_or_string(type) {
3221
+ if (!is("name")) {
3222
+ if (!is("string")) {
3223
+ croak("Name or string expected");
3224
+ }
3225
+ var tok = S.token;
3226
+ var ret = new type({
3227
+ start : tok,
3228
+ end : tok,
3229
+ name : tok.value,
3230
+ quote : tok.quote
3231
+ });
3232
+ next();
3233
+ return ret;
3234
+ }
3235
+ var sym = _make_symbol(type);
3236
+ _verify_symbol(sym);
3237
+ next();
3238
+ return sym;
3239
+ }
3240
+
3206
3241
  // Annotate AST_Call, AST_Lambda or AST_New with the special comments
3207
3242
  function annotate(node) {
3208
3243
  var start = node.start;
@@ -3224,6 +3259,10 @@ function parse($TEXT, options) {
3224
3259
  set_annotation(node, _NOINLINE);
3225
3260
  break;
3226
3261
  }
3262
+ if (/[@#]__KEY__/.test(comment.value)) {
3263
+ set_annotation(node, _KEY);
3264
+ break;
3265
+ }
3227
3266
  }
3228
3267
  }
3229
3268
  }
@@ -3682,6 +3721,14 @@ class AST_Token {
3682
3721
  Object.seal(this);
3683
3722
  }
3684
3723
 
3724
+ // Return a string summary of the token for node.js console.log
3725
+ [Symbol.for("nodejs.util.inspect.custom")](_depth, options) {
3726
+ const special = str => options.stylize(str, "special");
3727
+ const quote = typeof this.value === "string" && this.value.includes("`") ? "'" : "`";
3728
+ const value = `${quote}${this.value}${quote}`;
3729
+ return `${special("[AST_Token")} ${value} at ${this.line}:${this.col}${special("]")}`;
3730
+ }
3731
+
3685
3732
  get nlb() {
3686
3733
  return has_tok_flag(this, TOK_FLAG_NLB);
3687
3734
  }
@@ -4468,11 +4515,14 @@ var AST_Destructuring = DEFNODE("Destructuring", "names is_array", function AST_
4468
4515
  },
4469
4516
  all_symbols: function() {
4470
4517
  var out = [];
4471
- this.walk(new TreeWalker(function (node) {
4472
- if (node instanceof AST_Symbol) {
4518
+ walk(this, node => {
4519
+ if (node instanceof AST_SymbolDeclaration) {
4473
4520
  out.push(node);
4474
4521
  }
4475
- }));
4522
+ if (node instanceof AST_Lambda) {
4523
+ return true;
4524
+ }
4525
+ });
4476
4526
  return out;
4477
4527
  }
4478
4528
  });
@@ -4565,6 +4615,7 @@ var AST_Jump = DEFNODE("Jump", null, function AST_Jump(props) {
4565
4615
  $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
4566
4616
  }, AST_Statement);
4567
4617
 
4618
+ /** Base class for “exits” (`return` and `throw`) */
4568
4619
  var AST_Exit = DEFNODE("Exit", "value", function AST_Exit(props) {
4569
4620
  if (props) {
4570
4621
  this.value = props.value;
@@ -4827,12 +4878,11 @@ var AST_Case = DEFNODE("Case", "expression", function AST_Case(props) {
4827
4878
 
4828
4879
  /* -----[ EXCEPTIONS ]----- */
4829
4880
 
4830
- var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
4881
+ var AST_Try = DEFNODE("Try", "body bcatch bfinally", function AST_Try(props) {
4831
4882
  if (props) {
4883
+ this.body = props.body;
4832
4884
  this.bcatch = props.bcatch;
4833
4885
  this.bfinally = props.bfinally;
4834
- this.body = props.body;
4835
- this.block_scope = props.block_scope;
4836
4886
  this.start = props.start;
4837
4887
  this.end = props.end;
4838
4888
  }
@@ -4841,12 +4891,13 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
4841
4891
  }, {
4842
4892
  $documentation: "A `try` statement",
4843
4893
  $propdoc: {
4894
+ body: "[AST_TryBlock] the try block",
4844
4895
  bcatch: "[AST_Catch?] the catch block, or null if not present",
4845
4896
  bfinally: "[AST_Finally?] the finally block, or null if not present"
4846
4897
  },
4847
4898
  _walk: function(visitor) {
4848
4899
  return visitor._visit(this, function() {
4849
- walk_body(this, visitor);
4900
+ this.body._walk(visitor);
4850
4901
  if (this.bcatch) this.bcatch._walk(visitor);
4851
4902
  if (this.bfinally) this.bfinally._walk(visitor);
4852
4903
  });
@@ -4854,9 +4905,21 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
4854
4905
  _children_backwards(push) {
4855
4906
  if (this.bfinally) push(this.bfinally);
4856
4907
  if (this.bcatch) push(this.bcatch);
4857
- let i = this.body.length;
4858
- while (i--) push(this.body[i]);
4908
+ push(this.body);
4859
4909
  },
4910
+ }, AST_Statement);
4911
+
4912
+ var AST_TryBlock = DEFNODE("TryBlock", null, function AST_TryBlock(props) {
4913
+ if (props) {
4914
+ this.body = props.body;
4915
+ this.block_scope = props.block_scope;
4916
+ this.start = props.start;
4917
+ this.end = props.end;
4918
+ }
4919
+
4920
+ this.flags = 0;
4921
+ }, {
4922
+ $documentation: "The `try` block of a try statement"
4860
4923
  }, AST_Block);
4861
4924
 
4862
4925
  var AST_Catch = DEFNODE("Catch", "argname", function AST_Catch(props) {
@@ -4990,6 +5053,13 @@ var AST_VarDef = DEFNODE("VarDef", "name value", function AST_VarDef(props) {
4990
5053
  if (this.value) push(this.value);
4991
5054
  push(this.name);
4992
5055
  },
5056
+ declarations_as_names() {
5057
+ if (this.name instanceof AST_SymbolDeclaration) {
5058
+ return [this];
5059
+ } else {
5060
+ return this.name.all_symbols();
5061
+ }
5062
+ }
4993
5063
  });
4994
5064
 
4995
5065
  var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", function AST_NameMapping(props) {
@@ -5770,6 +5840,40 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
5770
5840
  if (this.extends) push(this.extends);
5771
5841
  if (this.name) push(this.name);
5772
5842
  },
5843
+ /** go through the bits that are executed instantly, not when the class is `new`'d. Doesn't walk the name. */
5844
+ visit_nondeferred_class_parts(visitor) {
5845
+ if (this.extends) {
5846
+ this.extends._walk(visitor);
5847
+ }
5848
+ this.properties.forEach((prop) => {
5849
+ if (prop instanceof AST_ClassStaticBlock) {
5850
+ prop._walk(visitor);
5851
+ return;
5852
+ }
5853
+ if (prop.computed_key()) {
5854
+ visitor.push(prop);
5855
+ prop.key._walk(visitor);
5856
+ visitor.pop();
5857
+ }
5858
+ if ((prop instanceof AST_ClassPrivateProperty || prop instanceof AST_ClassProperty) && prop.static && prop.value) {
5859
+ visitor.push(prop);
5860
+ prop.value._walk(visitor);
5861
+ visitor.pop();
5862
+ }
5863
+ });
5864
+ },
5865
+ /** go through the bits that are executed later, when the class is `new`'d or a static method is called */
5866
+ visit_deferred_class_parts(visitor) {
5867
+ this.properties.forEach((prop) => {
5868
+ if (prop instanceof AST_ConciseMethod) {
5869
+ prop.walk(visitor);
5870
+ } else if (prop instanceof AST_ClassProperty && !prop.static && prop.value) {
5871
+ visitor.push(prop);
5872
+ prop.value._walk(visitor);
5873
+ visitor.pop();
5874
+ }
5875
+ });
5876
+ },
5773
5877
  }, AST_Scope /* TODO a class might have a scope but it's not a scope */);
5774
5878
 
5775
5879
  var AST_ClassProperty = DEFNODE("ClassProperty", "static quote", function AST_ClassProperty(props) {
@@ -5886,6 +5990,7 @@ var AST_ClassStaticBlock = DEFNODE("ClassStaticBlock", "body block_scope", funct
5886
5990
  while (i--) push(this.body[i]);
5887
5991
  },
5888
5992
  clone: clone_block_scope,
5993
+ computed_key: () => false
5889
5994
  }, AST_Scope);
5890
5995
 
5891
5996
  var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExpression(props) {
@@ -6159,6 +6264,7 @@ var AST_SymbolImportForeign = DEFNODE("SymbolImportForeign", null, function AST_
6159
6264
  this.scope = props.scope;
6160
6265
  this.name = props.name;
6161
6266
  this.thedef = props.thedef;
6267
+ this.quote = props.quote;
6162
6268
  this.start = props.start;
6163
6269
  this.end = props.end;
6164
6270
  }
@@ -6210,6 +6316,7 @@ var AST_SymbolExport = DEFNODE("SymbolExport", null, function AST_SymbolExport(p
6210
6316
  this.scope = props.scope;
6211
6317
  this.name = props.name;
6212
6318
  this.thedef = props.thedef;
6319
+ this.quote = props.quote;
6213
6320
  this.start = props.start;
6214
6321
  this.end = props.end;
6215
6322
  }
@@ -6224,6 +6331,7 @@ var AST_SymbolExportForeign = DEFNODE("SymbolExportForeign", null, function AST_
6224
6331
  this.scope = props.scope;
6225
6332
  this.name = props.name;
6226
6333
  this.thedef = props.thedef;
6334
+ this.quote = props.quote;
6227
6335
  this.start = props.start;
6228
6336
  this.end = props.end;
6229
6337
  }
@@ -6309,6 +6417,7 @@ var AST_String = DEFNODE("String", "value quote", function AST_String(props) {
6309
6417
  this.quote = props.quote;
6310
6418
  this.start = props.start;
6311
6419
  this.end = props.end;
6420
+ this._annotations = props._annotations;
6312
6421
  }
6313
6422
 
6314
6423
  this.flags = 0;
@@ -6681,6 +6790,7 @@ class TreeTransformer extends TreeWalker {
6681
6790
  const _PURE = 0b00000001;
6682
6791
  const _INLINE = 0b00000010;
6683
6792
  const _NOINLINE = 0b00000100;
6793
+ const _KEY = 0b00001000;
6684
6794
 
6685
6795
  /***********************************************************************
6686
6796
 
@@ -6743,12 +6853,6 @@ function def_transform(node, descend) {
6743
6853
  });
6744
6854
  }
6745
6855
 
6746
- function do_list(list, tw) {
6747
- return MAP(list, function(node) {
6748
- return node.transform(tw, true);
6749
- });
6750
- }
6751
-
6752
6856
  def_transform(AST_Node, noop);
6753
6857
 
6754
6858
  def_transform(AST_LabeledStatement, function(self, tw) {
@@ -6761,7 +6865,7 @@ def_transform(AST_SimpleStatement, function(self, tw) {
6761
6865
  });
6762
6866
 
6763
6867
  def_transform(AST_Block, function(self, tw) {
6764
- self.body = do_list(self.body, tw);
6868
+ self.body = MAP(self.body, tw);
6765
6869
  });
6766
6870
 
6767
6871
  def_transform(AST_Do, function(self, tw) {
@@ -6808,27 +6912,27 @@ def_transform(AST_If, function(self, tw) {
6808
6912
 
6809
6913
  def_transform(AST_Switch, function(self, tw) {
6810
6914
  self.expression = self.expression.transform(tw);
6811
- self.body = do_list(self.body, tw);
6915
+ self.body = MAP(self.body, tw);
6812
6916
  });
6813
6917
 
6814
6918
  def_transform(AST_Case, function(self, tw) {
6815
6919
  self.expression = self.expression.transform(tw);
6816
- self.body = do_list(self.body, tw);
6920
+ self.body = MAP(self.body, tw);
6817
6921
  });
6818
6922
 
6819
6923
  def_transform(AST_Try, function(self, tw) {
6820
- self.body = do_list(self.body, tw);
6924
+ self.body = self.body.transform(tw);
6821
6925
  if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
6822
6926
  if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
6823
6927
  });
6824
6928
 
6825
6929
  def_transform(AST_Catch, function(self, tw) {
6826
6930
  if (self.argname) self.argname = self.argname.transform(tw);
6827
- self.body = do_list(self.body, tw);
6931
+ self.body = MAP(self.body, tw);
6828
6932
  });
6829
6933
 
6830
6934
  def_transform(AST_Definitions, function(self, tw) {
6831
- self.definitions = do_list(self.definitions, tw);
6935
+ self.definitions = MAP(self.definitions, tw);
6832
6936
  });
6833
6937
 
6834
6938
  def_transform(AST_VarDef, function(self, tw) {
@@ -6837,26 +6941,26 @@ def_transform(AST_VarDef, function(self, tw) {
6837
6941
  });
6838
6942
 
6839
6943
  def_transform(AST_Destructuring, function(self, tw) {
6840
- self.names = do_list(self.names, tw);
6944
+ self.names = MAP(self.names, tw);
6841
6945
  });
6842
6946
 
6843
6947
  def_transform(AST_Lambda, function(self, tw) {
6844
6948
  if (self.name) self.name = self.name.transform(tw);
6845
- self.argnames = do_list(self.argnames, tw);
6949
+ self.argnames = MAP(self.argnames, tw, /* allow_splicing */ false);
6846
6950
  if (self.body instanceof AST_Node) {
6847
6951
  self.body = self.body.transform(tw);
6848
6952
  } else {
6849
- self.body = do_list(self.body, tw);
6953
+ self.body = MAP(self.body, tw);
6850
6954
  }
6851
6955
  });
6852
6956
 
6853
6957
  def_transform(AST_Call, function(self, tw) {
6854
6958
  self.expression = self.expression.transform(tw);
6855
- self.args = do_list(self.args, tw);
6959
+ self.args = MAP(self.args, tw, /* allow_splicing */ false);
6856
6960
  });
6857
6961
 
6858
6962
  def_transform(AST_Sequence, function(self, tw) {
6859
- const result = do_list(self.expressions, tw);
6963
+ const result = MAP(self.expressions, tw);
6860
6964
  self.expressions = result.length
6861
6965
  ? result
6862
6966
  : [new AST_Number({ value: 0 })];
@@ -6904,11 +7008,11 @@ def_transform(AST_Conditional, function(self, tw) {
6904
7008
  });
6905
7009
 
6906
7010
  def_transform(AST_Array, function(self, tw) {
6907
- self.elements = do_list(self.elements, tw);
7011
+ self.elements = MAP(self.elements, tw);
6908
7012
  });
6909
7013
 
6910
7014
  def_transform(AST_Object, function(self, tw) {
6911
- self.properties = do_list(self.properties, tw);
7015
+ self.properties = MAP(self.properties, tw);
6912
7016
  });
6913
7017
 
6914
7018
  def_transform(AST_ObjectProperty, function(self, tw) {
@@ -6921,11 +7025,11 @@ def_transform(AST_ObjectProperty, function(self, tw) {
6921
7025
  def_transform(AST_Class, function(self, tw) {
6922
7026
  if (self.name) self.name = self.name.transform(tw);
6923
7027
  if (self.extends) self.extends = self.extends.transform(tw);
6924
- self.properties = do_list(self.properties, tw);
7028
+ self.properties = MAP(self.properties, tw);
6925
7029
  });
6926
7030
 
6927
7031
  def_transform(AST_ClassStaticBlock, function(self, tw) {
6928
- self.body = do_list(self.body, tw);
7032
+ self.body = MAP(self.body, tw);
6929
7033
  });
6930
7034
 
6931
7035
  def_transform(AST_Expansion, function(self, tw) {
@@ -6939,19 +7043,19 @@ def_transform(AST_NameMapping, function(self, tw) {
6939
7043
 
6940
7044
  def_transform(AST_Import, function(self, tw) {
6941
7045
  if (self.imported_name) self.imported_name = self.imported_name.transform(tw);
6942
- if (self.imported_names) do_list(self.imported_names, tw);
7046
+ if (self.imported_names) MAP(self.imported_names, tw);
6943
7047
  self.module_name = self.module_name.transform(tw);
6944
7048
  });
6945
7049
 
6946
7050
  def_transform(AST_Export, function(self, tw) {
6947
7051
  if (self.exported_definition) self.exported_definition = self.exported_definition.transform(tw);
6948
7052
  if (self.exported_value) self.exported_value = self.exported_value.transform(tw);
6949
- if (self.exported_names) do_list(self.exported_names, tw);
7053
+ if (self.exported_names) MAP(self.exported_names, tw);
6950
7054
  if (self.module_name) self.module_name = self.module_name.transform(tw);
6951
7055
  });
6952
7056
 
6953
7057
  def_transform(AST_TemplateString, function(self, tw) {
6954
- self.segments = do_list(self.segments, tw);
7058
+ self.segments = MAP(self.segments, tw);
6955
7059
  });
6956
7060
 
6957
7061
  def_transform(AST_PrefixedTemplateString, function(self, tw) {
@@ -7184,7 +7288,7 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7184
7288
  return new AST_Try({
7185
7289
  start : my_start_token(M),
7186
7290
  end : my_end_token(M),
7187
- body : from_moz(M.block).body,
7291
+ body : new AST_TryBlock(from_moz(M.block)),
7188
7292
  bcatch : from_moz(handlers[0]),
7189
7293
  bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
7190
7294
  });
@@ -7234,22 +7338,25 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7234
7338
  },
7235
7339
 
7236
7340
  MethodDefinition: function(M) {
7341
+ const is_private = M.key.type === "PrivateIdentifier";
7342
+ const key = M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value });
7343
+
7237
7344
  var args = {
7238
7345
  start : my_start_token(M),
7239
7346
  end : my_end_token(M),
7240
- key : M.computed ? from_moz(M.key) : new AST_SymbolMethod({ name: M.key.name || M.key.value }),
7347
+ key,
7241
7348
  value : from_moz(M.value),
7242
7349
  static : M.static,
7243
7350
  };
7244
7351
  if (M.kind == "get") {
7245
- return new AST_ObjectGetter(args);
7352
+ return new (is_private ? AST_PrivateGetter : AST_ObjectGetter)(args);
7246
7353
  }
7247
7354
  if (M.kind == "set") {
7248
- return new AST_ObjectSetter(args);
7355
+ return new (is_private ? AST_PrivateSetter : AST_ObjectSetter)(args);
7249
7356
  }
7250
7357
  args.is_generator = M.value.generator;
7251
7358
  args.async = M.value.async;
7252
- return new AST_ConciseMethod(args);
7359
+ return new (is_private ? AST_PrivateMethod : AST_ConciseMethod)(args);
7253
7360
  },
7254
7361
 
7255
7362
  FieldDefinition: function(M) {
@@ -7273,8 +7380,16 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7273
7380
  let key;
7274
7381
  if (M.computed) {
7275
7382
  key = from_moz(M.key);
7383
+ } else if (M.key.type === "PrivateIdentifier") {
7384
+ return new AST_ClassPrivateProperty({
7385
+ start : my_start_token(M),
7386
+ end : my_end_token(M),
7387
+ key : from_moz(M.key),
7388
+ value : from_moz(M.value),
7389
+ static : M.static,
7390
+ });
7276
7391
  } else {
7277
- if (M.key.type !== "Identifier" && M.key.type !== "PrivateIdentifier") {
7392
+ if (M.key.type !== "Identifier") {
7278
7393
  throw new Error("Non-Identifier key in PropertyDefinition");
7279
7394
  }
7280
7395
  key = from_moz(M.key);
@@ -7289,6 +7404,14 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7289
7404
  });
7290
7405
  },
7291
7406
 
7407
+ PrivateIdentifier: function (M) {
7408
+ return new AST_SymbolPrivateProperty({
7409
+ start: my_start_token(M),
7410
+ end: my_end_token(M),
7411
+ name: M.name
7412
+ });
7413
+ },
7414
+
7292
7415
  StaticBlock: function(M) {
7293
7416
  return new AST_ClassStaticBlock({
7294
7417
  start : my_start_token(M),
@@ -7330,6 +7453,15 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7330
7453
  },
7331
7454
 
7332
7455
  MemberExpression: function(M) {
7456
+ if (M.property.type === "PrivateIdentifier") {
7457
+ return new AST_DotHash({
7458
+ start : my_start_token(M),
7459
+ end : my_end_token(M),
7460
+ property : M.property.name,
7461
+ expression : from_moz(M.object),
7462
+ optional : M.optional || false
7463
+ });
7464
+ }
7333
7465
  return new (M.computed ? AST_Sub : AST_Dot)({
7334
7466
  start : my_start_token(M),
7335
7467
  end : my_end_token(M),
@@ -7369,24 +7501,11 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7369
7501
  var imported_name = null;
7370
7502
  var imported_names = null;
7371
7503
  M.specifiers.forEach(function (specifier) {
7372
- if (specifier.type === "ImportSpecifier") {
7504
+ if (specifier.type === "ImportSpecifier" || specifier.type === "ImportNamespaceSpecifier") {
7373
7505
  if (!imported_names) { imported_names = []; }
7374
- imported_names.push(new AST_NameMapping({
7375
- start: my_start_token(specifier),
7376
- end: my_end_token(specifier),
7377
- foreign_name: from_moz(specifier.imported),
7378
- name: from_moz(specifier.local)
7379
- }));
7506
+ imported_names.push(from_moz(specifier));
7380
7507
  } else if (specifier.type === "ImportDefaultSpecifier") {
7381
- imported_name = from_moz(specifier.local);
7382
- } else if (specifier.type === "ImportNamespaceSpecifier") {
7383
- if (!imported_names) { imported_names = []; }
7384
- imported_names.push(new AST_NameMapping({
7385
- start: my_start_token(specifier),
7386
- end: my_end_token(specifier),
7387
- foreign_name: new AST_SymbolImportForeign({ name: "*" }),
7388
- name: from_moz(specifier.local)
7389
- }));
7508
+ imported_name = from_moz(specifier);
7390
7509
  }
7391
7510
  });
7392
7511
  return new AST_Import({
@@ -7399,14 +7518,39 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7399
7518
  });
7400
7519
  },
7401
7520
 
7521
+ ImportSpecifier: function(M) {
7522
+ return new AST_NameMapping({
7523
+ start: my_start_token(M),
7524
+ end: my_end_token(M),
7525
+ foreign_name: from_moz(M.imported),
7526
+ name: from_moz(M.local)
7527
+ });
7528
+ },
7529
+
7530
+ ImportDefaultSpecifier: function(M) {
7531
+ return from_moz(M.local);
7532
+ },
7533
+
7534
+ ImportNamespaceSpecifier: function(M) {
7535
+ return new AST_NameMapping({
7536
+ start: my_start_token(M),
7537
+ end: my_end_token(M),
7538
+ foreign_name: new AST_SymbolImportForeign({ name: "*" }),
7539
+ name: from_moz(M.local)
7540
+ });
7541
+ },
7542
+
7402
7543
  ExportAllDeclaration: function(M) {
7544
+ var foreign_name = M.exported == null ?
7545
+ new AST_SymbolExportForeign({ name: "*" }) :
7546
+ from_moz(M.exported);
7403
7547
  return new AST_Export({
7404
7548
  start: my_start_token(M),
7405
7549
  end: my_end_token(M),
7406
7550
  exported_names: [
7407
7551
  new AST_NameMapping({
7408
7552
  name: new AST_SymbolExportForeign({ name: "*" }),
7409
- foreign_name: new AST_SymbolExportForeign({ name: "*" })
7553
+ foreign_name: foreign_name
7410
7554
  })
7411
7555
  ],
7412
7556
  module_name: from_moz(M.source),
@@ -7420,10 +7564,7 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7420
7564
  end: my_end_token(M),
7421
7565
  exported_definition: from_moz(M.declaration),
7422
7566
  exported_names: M.specifiers && M.specifiers.length ? M.specifiers.map(function (specifier) {
7423
- return new AST_NameMapping({
7424
- foreign_name: from_moz(specifier.exported),
7425
- name: from_moz(specifier.local)
7426
- });
7567
+ return from_moz(specifier);
7427
7568
  }) : null,
7428
7569
  module_name: from_moz(M.source),
7429
7570
  assert_clause: assert_clause_from_moz(M.assertions)
@@ -7439,6 +7580,13 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7439
7580
  });
7440
7581
  },
7441
7582
 
7583
+ ExportSpecifier: function(M) {
7584
+ return new AST_NameMapping({
7585
+ foreign_name: from_moz(M.exported),
7586
+ name: from_moz(M.local)
7587
+ });
7588
+ },
7589
+
7442
7590
  Literal: function(M) {
7443
7591
  var val = M.value, args = {
7444
7592
  start : my_start_token(M),
@@ -7464,6 +7612,22 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
7464
7612
  if (val === null) return new AST_Null(args);
7465
7613
  switch (typeof val) {
7466
7614
  case "string":
7615
+ args.quote = "\"";
7616
+ var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
7617
+ if (p.type == "ImportSpecifier") {
7618
+ args.name = val;
7619
+ return new AST_SymbolImportForeign(args);
7620
+ } else if (p.type == "ExportSpecifier") {
7621
+ args.name = val;
7622
+ if (M == p.exported) {
7623
+ return new AST_SymbolExportForeign(args);
7624
+ } else {
7625
+ return new AST_SymbolExport(args);
7626
+ }
7627
+ } else if (p.type == "ExportAllDeclaration" && M == p.exported) {
7628
+ args.name = val;
7629
+ return new AST_SymbolExportForeign(args);
7630
+ }
7467
7631
  args.value = val;
7468
7632
  return new AST_String(args);
7469
7633
  case "number":
@@ -8123,7 +8287,7 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8123
8287
  def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
8124
8288
  return {
8125
8289
  type: "TryStatement",
8126
- block: to_moz_block(M),
8290
+ block: to_moz_block(M.body),
8127
8291
  handler: to_moz(M.bcatch),
8128
8292
  guardedHandlers: [],
8129
8293
  finalizer: to_moz(M.bfinally)
@@ -8168,10 +8332,17 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8168
8332
 
8169
8333
  def_to_moz(AST_Export, function To_Moz_ExportDeclaration(M) {
8170
8334
  if (M.exported_names) {
8171
- if (M.exported_names[0].name.name === "*") {
8335
+ var first_exported = M.exported_names[0];
8336
+ var first_exported_name = first_exported.name;
8337
+ if (first_exported_name.name === "*" && !first_exported_name.quote) {
8338
+ var foreign_name = first_exported.foreign_name;
8339
+ var exported = foreign_name.name === "*" && !foreign_name.quote
8340
+ ? null
8341
+ : to_moz(foreign_name);
8172
8342
  return {
8173
8343
  type: "ExportAllDeclaration",
8174
8344
  source: to_moz(M.module_name),
8345
+ exported: exported,
8175
8346
  assertions: assert_clause_to_moz(M.assert_clause)
8176
8347
  };
8177
8348
  }
@@ -8203,19 +8374,22 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8203
8374
  local: to_moz(M.imported_name)
8204
8375
  });
8205
8376
  }
8206
- if (M.imported_names && M.imported_names[0].foreign_name.name === "*") {
8207
- specifiers.push({
8208
- type: "ImportNamespaceSpecifier",
8209
- local: to_moz(M.imported_names[0].name)
8210
- });
8211
- } else if (M.imported_names) {
8212
- M.imported_names.forEach(function(name_mapping) {
8377
+ if (M.imported_names) {
8378
+ var first_imported_foreign_name = M.imported_names[0].foreign_name;
8379
+ if (first_imported_foreign_name.name === "*" && !first_imported_foreign_name.quote) {
8213
8380
  specifiers.push({
8214
- type: "ImportSpecifier",
8215
- local: to_moz(name_mapping.name),
8216
- imported: to_moz(name_mapping.foreign_name)
8381
+ type: "ImportNamespaceSpecifier",
8382
+ local: to_moz(M.imported_names[0].name)
8217
8383
  });
8218
- });
8384
+ } else {
8385
+ M.imported_names.forEach(function(name_mapping) {
8386
+ specifiers.push({
8387
+ type: "ImportSpecifier",
8388
+ local: to_moz(name_mapping.name),
8389
+ imported: to_moz(name_mapping.foreign_name)
8390
+ });
8391
+ });
8392
+ }
8219
8393
  }
8220
8394
  return {
8221
8395
  type: "ImportDeclaration",
@@ -8479,7 +8653,14 @@ def_transform(AST_PrefixedTemplateString, function(self, tw) {
8479
8653
  });
8480
8654
 
8481
8655
  def_to_moz(AST_Symbol, function To_Moz_Identifier(M, parent) {
8482
- if (M instanceof AST_SymbolMethod && parent.quote) {
8656
+ if (
8657
+ (M instanceof AST_SymbolMethod && parent.quote) ||
8658
+ ((
8659
+ M instanceof AST_SymbolImportForeign ||
8660
+ M instanceof AST_SymbolExportForeign ||
8661
+ M instanceof AST_SymbolExport
8662
+ ) && M.quote)
8663
+ ) {
8483
8664
  return {
8484
8665
  type: "Literal",
8485
8666
  value: M.name
@@ -9227,14 +9408,17 @@ function OutputStream(options) {
9227
9408
  if (!start) return;
9228
9409
  var printed_comments = self.printed_comments;
9229
9410
 
9230
- // There cannot be a newline between return and its value.
9231
- const return_with_value = node instanceof AST_Exit && node.value;
9411
+ // There cannot be a newline between return/yield and its value.
9412
+ const keyword_with_value =
9413
+ node instanceof AST_Exit && node.value
9414
+ || (node instanceof AST_Await || node instanceof AST_Yield)
9415
+ && node.expression;
9232
9416
 
9233
9417
  if (
9234
9418
  start.comments_before
9235
9419
  && printed_comments.has(start.comments_before)
9236
9420
  ) {
9237
- if (return_with_value) {
9421
+ if (keyword_with_value) {
9238
9422
  start.comments_before = [];
9239
9423
  } else {
9240
9424
  return;
@@ -9247,10 +9431,12 @@ function OutputStream(options) {
9247
9431
  }
9248
9432
  printed_comments.add(comments);
9249
9433
 
9250
- if (return_with_value) {
9434
+ if (keyword_with_value) {
9251
9435
  var tw = new TreeWalker(function(node) {
9252
9436
  var parent = tw.parent();
9253
9437
  if (parent instanceof AST_Exit
9438
+ || parent instanceof AST_Await
9439
+ || parent instanceof AST_Yield
9254
9440
  || parent instanceof AST_Binary && parent.left === node
9255
9441
  || parent.TYPE == "Call" && parent.expression === node
9256
9442
  || parent instanceof AST_Conditional && parent.condition === node
@@ -9269,7 +9455,7 @@ function OutputStream(options) {
9269
9455
  }
9270
9456
  });
9271
9457
  tw.push(node);
9272
- node.value.walk(tw);
9458
+ keyword_with_value.walk(tw);
9273
9459
  }
9274
9460
 
9275
9461
  if (current_pos == 0) {
@@ -9645,6 +9831,12 @@ function OutputStream(options) {
9645
9831
  return true;
9646
9832
  });
9647
9833
 
9834
+ PARENS(AST_Chain, function(output) {
9835
+ var p = output.parent();
9836
+ if (!(p instanceof AST_Call || p instanceof AST_PropAccess)) return false;
9837
+ return p.expression === this;
9838
+ });
9839
+
9648
9840
  PARENS(AST_PropAccess, function(output) {
9649
9841
  var p = output.parent();
9650
9842
  if (p instanceof AST_New && p.expression === this) {
@@ -9791,7 +9983,7 @@ function OutputStream(options) {
9791
9983
  }
9792
9984
 
9793
9985
  AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
9794
- force_statement(this.body, output);
9986
+ print_maybe_braced_body(this.body, output);
9795
9987
  });
9796
9988
 
9797
9989
  DEFPRINT(AST_Statement, function(self, output) {
@@ -10120,7 +10312,7 @@ function OutputStream(options) {
10120
10312
  b = b.body;
10121
10313
  } else break;
10122
10314
  }
10123
- force_statement(self.body, output);
10315
+ print_maybe_braced_body(self.body, output);
10124
10316
  }
10125
10317
  DEFPRINT(AST_If, function(self, output) {
10126
10318
  output.print("if");
@@ -10137,7 +10329,7 @@ function OutputStream(options) {
10137
10329
  if (self.alternative instanceof AST_If)
10138
10330
  self.alternative.print(output);
10139
10331
  else
10140
- force_statement(self.alternative, output);
10332
+ print_maybe_braced_body(self.alternative, output);
10141
10333
  } else {
10142
10334
  self._do_print_body(output);
10143
10335
  }
@@ -10186,7 +10378,7 @@ function OutputStream(options) {
10186
10378
  DEFPRINT(AST_Try, function(self, output) {
10187
10379
  output.print("try");
10188
10380
  output.space();
10189
- print_braced(self, output);
10381
+ self.body.print(output);
10190
10382
  if (self.bcatch) {
10191
10383
  output.space();
10192
10384
  self.bcatch.print(output);
@@ -10196,6 +10388,9 @@ function OutputStream(options) {
10196
10388
  self.bfinally.print(output);
10197
10389
  }
10198
10390
  });
10391
+ DEFPRINT(AST_TryBlock, function(self, output) {
10392
+ print_braced(self, output);
10393
+ });
10199
10394
  DEFPRINT(AST_Catch, function(self, output) {
10200
10395
  output.print("catch");
10201
10396
  if (self.argname) {
@@ -10247,7 +10442,9 @@ function OutputStream(options) {
10247
10442
  output.space();
10248
10443
  }
10249
10444
  if (self.imported_names) {
10250
- if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
10445
+ if (self.imported_names.length === 1 &&
10446
+ self.imported_names[0].foreign_name.name === "*" &&
10447
+ !self.imported_names[0].foreign_name.quote) {
10251
10448
  self.imported_names[0].print(output);
10252
10449
  } else {
10253
10450
  output.print("{");
@@ -10281,14 +10478,31 @@ function OutputStream(options) {
10281
10478
  DEFPRINT(AST_NameMapping, function(self, output) {
10282
10479
  var is_import = output.parent() instanceof AST_Import;
10283
10480
  var definition = self.name.definition();
10481
+ var foreign_name = self.foreign_name;
10284
10482
  var names_are_different =
10285
10483
  (definition && definition.mangled_name || self.name.name) !==
10286
- self.foreign_name.name;
10484
+ foreign_name.name;
10485
+ if (!names_are_different &&
10486
+ foreign_name.name === "*" &&
10487
+ foreign_name.quote != self.name.quote) {
10488
+ // export * as "*"
10489
+ names_are_different = true;
10490
+ }
10491
+ var foreign_name_is_name = foreign_name.quote == null;
10287
10492
  if (names_are_different) {
10288
10493
  if (is_import) {
10289
- output.print(self.foreign_name.name);
10494
+ if (foreign_name_is_name) {
10495
+ output.print(foreign_name.name);
10496
+ } else {
10497
+ output.print_string(foreign_name.name, foreign_name.quote);
10498
+ }
10290
10499
  } else {
10291
- self.name.print(output);
10500
+ if (self.name.quote == null) {
10501
+ self.name.print(output);
10502
+ } else {
10503
+ output.print_string(self.name.name, self.name.quote);
10504
+ }
10505
+
10292
10506
  }
10293
10507
  output.space();
10294
10508
  output.print("as");
@@ -10296,10 +10510,18 @@ function OutputStream(options) {
10296
10510
  if (is_import) {
10297
10511
  self.name.print(output);
10298
10512
  } else {
10299
- output.print(self.foreign_name.name);
10513
+ if (foreign_name_is_name) {
10514
+ output.print(foreign_name.name);
10515
+ } else {
10516
+ output.print_string(foreign_name.name, foreign_name.quote);
10517
+ }
10300
10518
  }
10301
10519
  } else {
10302
- self.name.print(output);
10520
+ if (self.name.quote == null) {
10521
+ self.name.print(output);
10522
+ } else {
10523
+ output.print_string(self.name.name, self.name.quote);
10524
+ }
10303
10525
  }
10304
10526
  });
10305
10527
 
@@ -10311,8 +10533,10 @@ function OutputStream(options) {
10311
10533
  output.space();
10312
10534
  }
10313
10535
  if (self.exported_names) {
10314
- if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
10315
- self.exported_names[0].print(output);
10536
+ if (self.exported_names.length === 1 &&
10537
+ self.exported_names[0].name.name === "*" &&
10538
+ !self.exported_names[0].name.quote) {
10539
+ self.exported_names[0].print(output);
10316
10540
  } else {
10317
10541
  output.print("{");
10318
10542
  self.exported_names.forEach(function(name_export, i) {
@@ -10439,7 +10663,7 @@ function OutputStream(options) {
10439
10663
  ? output.option("ie8")
10440
10664
  : !is_identifier_string(
10441
10665
  prop,
10442
- output.option("ecma") >= 2015 || output.option("safari10")
10666
+ output.option("ecma") >= 2015 && !output.option("safari10")
10443
10667
  );
10444
10668
 
10445
10669
  if (self.optional) output.print("?.");
@@ -10607,15 +10831,19 @@ function OutputStream(options) {
10607
10831
  output.print("new.target");
10608
10832
  });
10609
10833
 
10834
+ /** Prints a prop name. Returns whether it can be used as a shorthand. */
10610
10835
  function print_property_name(key, quote, output) {
10611
10836
  if (output.option("quote_keys")) {
10612
- return output.print_string(key);
10837
+ output.print_string(key);
10838
+ return false;
10613
10839
  }
10614
10840
  if ("" + +key == key && key >= 0) {
10615
10841
  if (output.option("keep_numbers")) {
10616
- return output.print(key);
10842
+ output.print(key);
10843
+ return false;
10617
10844
  }
10618
- return output.print(make_num(key));
10845
+ output.print(make_num(key));
10846
+ return false;
10619
10847
  }
10620
10848
  var print_string = ALL_RESERVED_WORDS.has(key)
10621
10849
  ? output.option("ie8")
@@ -10625,9 +10853,11 @@ function OutputStream(options) {
10625
10853
  : !is_identifier_string(key, true)
10626
10854
  );
10627
10855
  if (print_string || (quote && output.option("keep_quoted_props"))) {
10628
- return output.print_string(key, quote);
10856
+ output.print_string(key, quote);
10857
+ return false;
10629
10858
  }
10630
- return output.print_name(key);
10859
+ output.print_name(key);
10860
+ return true;
10631
10861
  }
10632
10862
 
10633
10863
  DEFPRINT(AST_ObjectKeyVal, function(self, output) {
@@ -10636,28 +10866,29 @@ function OutputStream(options) {
10636
10866
  return def ? def.mangled_name || def.name : self.name;
10637
10867
  }
10638
10868
 
10639
- var allowShortHand = output.option("shorthand");
10640
- if (allowShortHand &&
10641
- self.value instanceof AST_Symbol &&
10642
- is_identifier_string(
10643
- self.key,
10644
- output.option("ecma") >= 2015 || output.option("safari10")
10645
- ) &&
10646
- get_name(self.value) === self.key &&
10647
- !ALL_RESERVED_WORDS.has(self.key)
10869
+ const try_shorthand = output.option("shorthand") && !(self.key instanceof AST_Node);
10870
+ if (
10871
+ try_shorthand
10872
+ && self.value instanceof AST_Symbol
10873
+ && get_name(self.value) === self.key
10874
+ && !ALL_RESERVED_WORDS.has(self.key)
10648
10875
  ) {
10649
- print_property_name(self.key, self.quote, output);
10650
-
10651
- } else if (allowShortHand &&
10652
- self.value instanceof AST_DefaultAssign &&
10653
- self.value.left instanceof AST_Symbol &&
10654
- is_identifier_string(
10655
- self.key,
10656
- output.option("ecma") >= 2015 || output.option("safari10")
10657
- ) &&
10658
- get_name(self.value.left) === self.key
10876
+ const was_shorthand = print_property_name(self.key, self.quote, output);
10877
+ if (!was_shorthand) {
10878
+ output.colon();
10879
+ self.value.print(output);
10880
+ }
10881
+ } else if (
10882
+ try_shorthand
10883
+ && self.value instanceof AST_DefaultAssign
10884
+ && self.value.left instanceof AST_Symbol
10885
+ && get_name(self.value.left) === self.key
10659
10886
  ) {
10660
- print_property_name(self.key, self.quote, output);
10887
+ const was_shorthand = print_property_name(self.key, self.quote, output);
10888
+ if (!was_shorthand) {
10889
+ output.colon();
10890
+ self.value.left.print(output);
10891
+ }
10661
10892
  output.space();
10662
10893
  output.print("=");
10663
10894
  output.space();
@@ -10832,12 +11063,15 @@ function OutputStream(options) {
10832
11063
  }
10833
11064
  });
10834
11065
 
10835
- function force_statement(stat, output) {
11066
+ /** if, for, while, may or may not have braces surrounding its body */
11067
+ function print_maybe_braced_body(stat, output) {
10836
11068
  if (output.option("braces")) {
10837
11069
  make_block(stat, output);
10838
11070
  } else {
10839
11071
  if (!stat || stat instanceof AST_EmptyStatement)
10840
11072
  output.force_semicolon();
11073
+ else if (stat instanceof AST_Let || stat instanceof AST_Const || stat instanceof AST_Class)
11074
+ make_block(stat, output);
10841
11075
  else
10842
11076
  stat.print(output);
10843
11077
  }
@@ -11056,7 +11290,7 @@ AST_Switch.prototype.shallow_cmp = pass_through;
11056
11290
  AST_SwitchBranch.prototype.shallow_cmp = pass_through;
11057
11291
 
11058
11292
  AST_Try.prototype.shallow_cmp = function(other) {
11059
- return (this.bcatch == null ? other.bcatch == null : this.bcatch === other.bcatch) && (this.bfinally == null ? other.bfinally == null : this.bfinally === other.bfinally);
11293
+ return (this.body === other.body) && (this.bcatch == null ? other.bcatch == null : this.bcatch === other.bcatch) && (this.bfinally == null ? other.bfinally == null : this.bfinally === other.bfinally);
11060
11294
  };
11061
11295
 
11062
11296
  AST_Catch.prototype.shallow_cmp = function(other) {
@@ -11323,16 +11557,12 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
11323
11557
  const save_scope = scope;
11324
11558
  node.block_scope = scope = new AST_Scope(node);
11325
11559
  scope._block_scope = true;
11326
- // AST_Try in the AST sadly *is* (not has) a body itself,
11327
- // and its catch and finally branches are children of the AST_Try itself
11328
- const parent_scope = node instanceof AST_Catch
11329
- ? save_scope.parent_scope
11330
- : save_scope;
11331
- scope.init_scope_vars(parent_scope);
11560
+ scope.init_scope_vars(save_scope);
11332
11561
  scope.uses_with = save_scope.uses_with;
11333
11562
  scope.uses_eval = save_scope.uses_eval;
11563
+
11334
11564
  if (options.safari10) {
11335
- if (node instanceof AST_For || node instanceof AST_ForIn) {
11565
+ if (node instanceof AST_For || node instanceof AST_ForIn || node instanceof AST_ForOf) {
11336
11566
  for_scopes.push(scope);
11337
11567
  }
11338
11568
  }
@@ -11342,7 +11572,7 @@ AST_Scope.DEFMETHOD("figure_out_scope", function(options, { parent_scope = null,
11342
11572
  // AST_Switch has a scope within the body, but it itself "is a block scope"
11343
11573
  // This means the switched expression has to belong to the outer scope
11344
11574
  // while the body inside belongs to the switch itself.
11345
- // This is pretty nasty and warrants an AST change similar to AST_Try (read above)
11575
+ // This is pretty nasty and warrants an AST change
11346
11576
  const the_block_scope = scope;
11347
11577
  scope = save_scope;
11348
11578
  node.expression.walk(tw);
@@ -12288,9 +12518,7 @@ AST_Default.prototype._size = function () {
12288
12518
  return 8 + list_overhead(this.body);
12289
12519
  };
12290
12520
 
12291
- AST_Try.prototype._size = function () {
12292
- return 3 + list_overhead(this.body);
12293
- };
12521
+ AST_Try.prototype._size = () => 3;
12294
12522
 
12295
12523
  AST_Catch.prototype._size = function () {
12296
12524
  let size = 7 + list_overhead(this.body);
@@ -12813,7 +13041,8 @@ function maintain_this_binding(parent, orig, val) {
12813
13041
  parent instanceof AST_UnaryPrefix && parent.operator == "delete"
12814
13042
  || parent instanceof AST_Call && parent.expression === orig
12815
13043
  && (
12816
- val instanceof AST_PropAccess
13044
+ val instanceof AST_Chain
13045
+ || val instanceof AST_PropAccess
12817
13046
  || val instanceof AST_SymbolRef && val.name == "eval"
12818
13047
  )
12819
13048
  ) {
@@ -12828,9 +13057,10 @@ function is_func_expr(node) {
12828
13057
  return node instanceof AST_Arrow || node instanceof AST_Function;
12829
13058
  }
12830
13059
 
13060
+ /**
13061
+ * Used to determine whether the node can benefit from negation.
13062
+ * Not the case with arrow functions (you need an extra set of parens). */
12831
13063
  function is_iife_call(node) {
12832
- // Used to determine whether the node can benefit from negation.
12833
- // Not the case with arrow functions (you need an extra set of parens).
12834
13064
  if (node.TYPE != "Call") return false;
12835
13065
  return node.expression instanceof AST_Function || is_iife_call(node.expression);
12836
13066
  }
@@ -13010,6 +13240,9 @@ const object_methods = [
13010
13240
 
13011
13241
  const is_pure_native_method = make_nested_lookup({
13012
13242
  Array: [
13243
+ "at",
13244
+ "flat",
13245
+ "includes",
13013
13246
  "indexOf",
13014
13247
  "join",
13015
13248
  "lastIndexOf",
@@ -13030,22 +13263,41 @@ const is_pure_native_method = make_nested_lookup({
13030
13263
  ...object_methods,
13031
13264
  ],
13032
13265
  String: [
13266
+ "at",
13033
13267
  "charAt",
13034
13268
  "charCodeAt",
13269
+ "charPointAt",
13035
13270
  "concat",
13271
+ "endsWith",
13272
+ "fromCharCode",
13273
+ "fromCodePoint",
13274
+ "includes",
13036
13275
  "indexOf",
13037
13276
  "italics",
13038
13277
  "lastIndexOf",
13278
+ "localeCompare",
13039
13279
  "match",
13280
+ "matchAll",
13281
+ "normalize",
13282
+ "padStart",
13283
+ "padEnd",
13284
+ "repeat",
13040
13285
  "replace",
13286
+ "replaceAll",
13041
13287
  "search",
13042
13288
  "slice",
13043
13289
  "split",
13290
+ "startsWith",
13044
13291
  "substr",
13045
13292
  "substring",
13293
+ "repeat",
13294
+ "toLocaleLowerCase",
13295
+ "toLocaleUpperCase",
13046
13296
  "toLowerCase",
13047
13297
  "toUpperCase",
13048
13298
  "trim",
13299
+ "trimEnd",
13300
+ "trimStart",
13049
13301
  ...object_methods,
13050
13302
  ],
13051
13303
  });
@@ -13202,7 +13454,7 @@ const unary_side_effects = makePredicate("delete ++ --");
13202
13454
  def_is_number(AST_Number, return_true);
13203
13455
  const unary = makePredicate("+ - ~ ++ --");
13204
13456
  def_is_number(AST_Unary, function() {
13205
- return unary.has(this.operator);
13457
+ return unary.has(this.operator) && !(this.expression instanceof AST_BigInt);
13206
13458
  });
13207
13459
  const numeric_ops = makePredicate("- * / % & | ^ << >> >>>");
13208
13460
  def_is_number(AST_Binary, function(compressor) {
@@ -13331,7 +13583,7 @@ function is_nullish(node, compressor) {
13331
13583
  || any(this.body, compressor);
13332
13584
  });
13333
13585
  def_has_side_effects(AST_Try, function(compressor) {
13334
- return any(this.body, compressor)
13586
+ return this.body.has_side_effects(compressor)
13335
13587
  || this.bcatch && this.bcatch.has_side_effects(compressor)
13336
13588
  || this.bfinally && this.bfinally.has_side_effects(compressor);
13337
13589
  });
@@ -13340,6 +13592,7 @@ function is_nullish(node, compressor) {
13340
13592
  || this.body && this.body.has_side_effects(compressor)
13341
13593
  || this.alternative && this.alternative.has_side_effects(compressor);
13342
13594
  });
13595
+ def_has_side_effects(AST_ImportMeta, return_false);
13343
13596
  def_has_side_effects(AST_LabeledStatement, function(compressor) {
13344
13597
  return this.body.has_side_effects(compressor);
13345
13598
  });
@@ -13443,6 +13696,7 @@ function is_nullish(node, compressor) {
13443
13696
  def_may_throw(AST_Lambda, return_false);
13444
13697
  def_may_throw(AST_SymbolDeclaration, return_false);
13445
13698
  def_may_throw(AST_This, return_false);
13699
+ def_may_throw(AST_ImportMeta, return_false);
13446
13700
 
13447
13701
  function any(list, compressor) {
13448
13702
  for (var i = list.length; --i >= 0;)
@@ -13560,7 +13814,7 @@ function is_nullish(node, compressor) {
13560
13814
  });
13561
13815
  def_may_throw(AST_SymbolClassProperty, return_false);
13562
13816
  def_may_throw(AST_Try, function(compressor) {
13563
- return this.bcatch ? this.bcatch.may_throw(compressor) : any(this.body, compressor)
13817
+ return this.bcatch ? this.bcatch.may_throw(compressor) : this.body.may_throw(compressor)
13564
13818
  || this.bfinally && this.bfinally.may_throw(compressor);
13565
13819
  });
13566
13820
  def_may_throw(AST_Unary, function(compressor) {
@@ -13739,6 +13993,7 @@ function is_nullish(node, compressor) {
13739
13993
  function is_lhs(node, parent) {
13740
13994
  if (parent instanceof AST_Unary && unary_side_effects.has(parent.operator)) return parent.expression;
13741
13995
  if (parent instanceof AST_Assign && parent.left === node) return node;
13996
+ if (parent instanceof AST_ForIn && parent.init === node) return node;
13742
13997
  }
13743
13998
 
13744
13999
  (function(def_find_defs) {
@@ -13806,6 +14061,11 @@ function is_lhs(node, parent) {
13806
14061
  var name = this.name + suffix;
13807
14062
  if (HOP(defines, name)) return to_node(defines[name], this);
13808
14063
  });
14064
+ def_find_defs(AST_ImportMeta, function(compressor, suffix) {
14065
+ var defines = compressor.option("global_defs");
14066
+ var name = "import.meta" + suffix;
14067
+ if (HOP(defines, name)) return to_node(defines[name], this);
14068
+ });
13809
14069
  })(function(node, func) {
13810
14070
  node.DEFMETHOD("_find_defs", func);
13811
14071
  });
@@ -13837,6 +14097,9 @@ function is_lhs(node, parent) {
13837
14097
  def_negate(AST_Function, function() {
13838
14098
  return basic_negation(this);
13839
14099
  });
14100
+ def_negate(AST_Class, function() {
14101
+ return basic_negation(this);
14102
+ });
13840
14103
  def_negate(AST_Arrow, function() {
13841
14104
  return basic_negation(this);
13842
14105
  });
@@ -13970,6 +14233,19 @@ const aborts = (thing) => thing && thing.aborts();
13970
14233
  node.DEFMETHOD("aborts", func);
13971
14234
  });
13972
14235
 
14236
+ AST_Node.DEFMETHOD("contains_this", function() {
14237
+ return walk(this, node => {
14238
+ if (node instanceof AST_This) return walk_abort;
14239
+ if (
14240
+ node !== this
14241
+ && node instanceof AST_Scope
14242
+ && !(node instanceof AST_Arrow)
14243
+ ) {
14244
+ return true;
14245
+ }
14246
+ });
14247
+ });
14248
+
13973
14249
  function is_modified(compressor, tw, node, value, level, immutable) {
13974
14250
  var parent = tw.parent(level);
13975
14251
  var lhs = is_lhs(node, parent);
@@ -14315,6 +14591,25 @@ const regexp_flags = new Set([
14315
14591
  def_eval(AST_PropAccess, function (compressor, depth) {
14316
14592
  let obj = this.expression._eval(compressor, depth + 1);
14317
14593
  if (obj === nullish || (this.optional && obj == null)) return nullish;
14594
+
14595
+ // `.length` of strings and arrays is always safe
14596
+ if (this.property === "length") {
14597
+ if (typeof obj === "string") {
14598
+ return obj.length;
14599
+ }
14600
+
14601
+ const is_spreadless_array =
14602
+ obj instanceof AST_Array
14603
+ && obj.elements.every(el => !(el instanceof AST_Expansion));
14604
+
14605
+ if (
14606
+ is_spreadless_array
14607
+ && obj.elements.every(el => !el.has_side_effects(compressor))
14608
+ ) {
14609
+ return obj.elements.length;
14610
+ }
14611
+ }
14612
+
14318
14613
  if (compressor.option("unsafe")) {
14319
14614
  var key = this.property;
14320
14615
  if (key instanceof AST_Node) {
@@ -14322,9 +14617,9 @@ def_eval(AST_PropAccess, function (compressor, depth) {
14322
14617
  if (key === this.property)
14323
14618
  return this;
14324
14619
  }
14620
+
14325
14621
  var exp = this.expression;
14326
14622
  if (is_undeclared_ref(exp)) {
14327
-
14328
14623
  var aa;
14329
14624
  var first_arg = exp.name === "hasOwnProperty"
14330
14625
  && key === "call"
@@ -14547,22 +14842,43 @@ def_drop_side_effect_free(AST_Class, function (compressor) {
14547
14842
  const trimmed_extends = this.extends && this.extends.drop_side_effect_free(compressor);
14548
14843
  if (trimmed_extends)
14549
14844
  with_effects.push(trimmed_extends);
14845
+
14550
14846
  for (const prop of this.properties) {
14551
14847
  if (prop instanceof AST_ClassStaticBlock) {
14552
- if (prop.body.some(stat => stat.has_side_effects(compressor))) {
14553
- return this;
14554
- } else {
14555
- continue;
14848
+ if (prop.has_side_effects(compressor)) {
14849
+ return this; // Be cautious about these
14556
14850
  }
14557
- }
14851
+ } else {
14852
+ const trimmed_prop = prop.drop_side_effect_free(compressor);
14853
+ if (trimmed_prop) {
14854
+ if (trimmed_prop.contains_this()) return this;
14558
14855
 
14559
- const trimmed_prop = prop.drop_side_effect_free(compressor);
14560
- if (trimmed_prop)
14561
- with_effects.push(trimmed_prop);
14856
+ with_effects.push(trimmed_prop);
14857
+ }
14858
+ }
14562
14859
  }
14860
+
14563
14861
  if (!with_effects.length)
14564
14862
  return null;
14565
- return make_sequence(this, with_effects);
14863
+
14864
+ const exprs = make_sequence(this, with_effects);
14865
+ if (this instanceof AST_DefClass) {
14866
+ // We want a statement
14867
+ return make_node(AST_SimpleStatement, this, { body: exprs });
14868
+ } else {
14869
+ return exprs;
14870
+ }
14871
+ });
14872
+
14873
+ def_drop_side_effect_free(AST_ClassProperty, function (compressor) {
14874
+ const key = this.computed_key() && this.key.drop_side_effect_free(compressor);
14875
+
14876
+ const value = this.static && this.value
14877
+ && this.value.drop_side_effect_free(compressor);
14878
+
14879
+ if (key && value)
14880
+ return make_sequence(this, [key, value]);
14881
+ return key || value || null;
14566
14882
  });
14567
14883
 
14568
14884
  def_drop_side_effect_free(AST_Binary, function (compressor, first_in_statement) {
@@ -14668,17 +14984,6 @@ def_drop_side_effect_free(AST_ObjectProperty, function (compressor, first_in_sta
14668
14984
  return key || value;
14669
14985
  });
14670
14986
 
14671
- def_drop_side_effect_free(AST_ClassProperty, function (compressor) {
14672
- const key = this.computed_key() && this.key.drop_side_effect_free(compressor);
14673
-
14674
- const value = this.static && this.value
14675
- && this.value.drop_side_effect_free(compressor);
14676
-
14677
- if (key && value)
14678
- return make_sequence(this, [key, value]);
14679
- return key || value || null;
14680
- });
14681
-
14682
14987
  def_drop_side_effect_free(AST_ConciseMethod, function () {
14683
14988
  return this.computed_key() ? this.key : null;
14684
14989
  });
@@ -14838,6 +15143,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
14838
15143
  });
14839
15144
  }
14840
15145
  if (node === self) return;
15146
+ if (node instanceof AST_Class) {
15147
+ if (node.has_side_effects(compressor)) {
15148
+ node.visit_nondeferred_class_parts(tw);
15149
+ }
15150
+ }
14841
15151
  if (node instanceof AST_Defun || node instanceof AST_DefClass) {
14842
15152
  var node_def = node.name.definition();
14843
15153
  const in_export = tw.parent() instanceof AST_Export;
@@ -14846,23 +15156,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
14846
15156
  in_use_ids.set(node_def.id, node_def);
14847
15157
  }
14848
15158
  }
14849
- if (node instanceof AST_DefClass) {
14850
- if (
14851
- node.extends
14852
- && (node.extends.has_side_effects(compressor)
14853
- || node.extends.may_throw(compressor))
14854
- ) {
14855
- node.extends.walk(tw);
14856
- }
14857
- for (const prop of node.properties) {
14858
- if (
14859
- prop.has_side_effects(compressor) ||
14860
- prop.may_throw(compressor)
14861
- ) {
14862
- prop.walk(tw);
14863
- }
14864
- }
14865
- }
15159
+
14866
15160
  map_add(initializations, node_def.id, node);
14867
15161
  return true; // don't go in nested scopes
14868
15162
  }
@@ -14927,9 +15221,9 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
14927
15221
  if (!in_use || fixed_ids.has(def.id) && fixed_ids.get(def.id) !== node) {
14928
15222
  return maintain_this_binding(parent, node, node.right.transform(tt));
14929
15223
  }
14930
- } else if (!in_use) return in_list ? MAP.skip : make_node(AST_Number, node, {
14931
- value: 0
14932
- });
15224
+ } else if (!in_use) {
15225
+ return in_list ? MAP.skip : make_node(AST_Number, node, { value: 0 });
15226
+ }
14933
15227
  }
14934
15228
  }
14935
15229
  if (scope !== self) return;
@@ -14972,11 +15266,18 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
14972
15266
  if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
14973
15267
  const def = node.name.definition();
14974
15268
  const keep = def.global && !drop_funcs || in_use_ids.has(def.id);
14975
- // Class "extends" and static blocks may have side effects
14976
- const has_side_effects = !keep
14977
- && node instanceof AST_Class
14978
- && node.has_side_effects(compressor);
14979
- if (!keep && !has_side_effects) {
15269
+ if (!keep) {
15270
+ // Class "extends" and static blocks may have side effects
15271
+ if (node instanceof AST_Class) {
15272
+ const kept = node.drop_side_effect_free(compressor);
15273
+ if (kept !== node) {
15274
+ def.eliminated++;
15275
+ if (kept) return kept;
15276
+ return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
15277
+ } else {
15278
+ return kept;
15279
+ }
15280
+ }
14980
15281
  def.eliminated++;
14981
15282
  return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
14982
15283
  }
@@ -15072,9 +15373,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15072
15373
  case 1:
15073
15374
  return body[0];
15074
15375
  default:
15075
- return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
15076
- body: body
15077
- });
15376
+ return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { body });
15078
15377
  }
15079
15378
  }
15080
15379
  // certain combination of unused name + side effect leads to:
@@ -15117,7 +15416,7 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15117
15416
  }
15118
15417
  return node;
15119
15418
  }
15120
- if (node instanceof AST_Scope) {
15419
+ if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) {
15121
15420
  const save_scope = scope;
15122
15421
  scope = node;
15123
15422
  descend(node, this);
@@ -15156,7 +15455,11 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15156
15455
  }
15157
15456
  return true;
15158
15457
  }
15159
- if (node instanceof AST_Scope) {
15458
+ if (node instanceof AST_Class) {
15459
+ descend();
15460
+ return true;
15461
+ }
15462
+ if (node instanceof AST_Scope && !(node instanceof AST_ClassStaticBlock)) {
15160
15463
  var save_scope = scope;
15161
15464
  scope = node;
15162
15465
  descend();
@@ -15209,15 +15512,17 @@ AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
15209
15512
 
15210
15513
  ***********************************************************************/
15211
15514
 
15212
- // Define the method AST_Node#reduce_vars, which goes through the AST in
15213
- // execution order to perform basic flow analysis
15214
-
15515
+ /**
15516
+ * Define the method AST_Node#reduce_vars, which goes through the AST in
15517
+ * execution order to perform basic flow analysis
15518
+ */
15215
15519
  function def_reduce_vars(node, func) {
15216
15520
  node.DEFMETHOD("reduce_vars", func);
15217
15521
  }
15218
15522
 
15219
15523
  def_reduce_vars(AST_Node, noop);
15220
15524
 
15525
+ /** Clear definition properties */
15221
15526
  function reset_def(compressor, def) {
15222
15527
  def.assignments = 0;
15223
15528
  def.chained = false;
@@ -15226,7 +15531,10 @@ function reset_def(compressor, def) {
15226
15531
  def.recursive_refs = 0;
15227
15532
  def.references = [];
15228
15533
  def.single_use = undefined;
15229
- if (def.scope.pinned()) {
15534
+ if (
15535
+ def.scope.pinned()
15536
+ || (def.orig[0] instanceof AST_SymbolFunarg && def.scope.uses_arguments)
15537
+ ) {
15230
15538
  def.fixed = false;
15231
15539
  } else if (def.orig[0] instanceof AST_SymbolConst || !compressor.exposed(def)) {
15232
15540
  def.fixed = def.init;
@@ -15550,13 +15858,11 @@ function mark_lambda(tw, descend, compressor) {
15550
15858
  clear_flag(this, INLINED);
15551
15859
  push(tw);
15552
15860
  reset_variables(tw, compressor, this);
15553
- if (this.uses_arguments) {
15554
- descend();
15555
- pop(tw);
15556
- return;
15557
- }
15861
+
15558
15862
  var iife;
15559
15863
  if (!this.name
15864
+ && !this.uses_arguments
15865
+ && !this.pinned()
15560
15866
  && (iife = tw.parent()) instanceof AST_Call
15561
15867
  && iife.expression === this
15562
15868
  && !iife.args.some(arg => arg instanceof AST_Expansion)
@@ -15581,11 +15887,101 @@ function mark_lambda(tw, descend, compressor) {
15581
15887
  }
15582
15888
  });
15583
15889
  }
15890
+
15584
15891
  descend();
15585
15892
  pop(tw);
15893
+
15894
+ handle_defined_after_hoist(this);
15895
+
15586
15896
  return true;
15587
15897
  }
15588
15898
 
15899
+ /**
15900
+ * It's possible for a hoisted function to use something that's not defined yet. Example:
15901
+ *
15902
+ * hoisted();
15903
+ * var defined_after = true;
15904
+ * function hoisted() {
15905
+ * // use defined_after
15906
+ * }
15907
+ *
15908
+ * This function is called on the parent to handle this issue.
15909
+ */
15910
+ function handle_defined_after_hoist(parent) {
15911
+ const defuns = [];
15912
+ walk(parent, node => {
15913
+ if (node === parent) return;
15914
+ if (node instanceof AST_Defun) defuns.push(node);
15915
+ if (
15916
+ node instanceof AST_Scope
15917
+ || node instanceof AST_SimpleStatement
15918
+ ) return true;
15919
+ });
15920
+
15921
+ for (const defun of defuns) {
15922
+ const fname_def = defun.name.definition();
15923
+ const found_self_ref_in_other_defuns = defuns.some(
15924
+ d => d !== defun && d.enclosed.indexOf(fname_def) !== -1
15925
+ );
15926
+
15927
+ for (const def of defun.enclosed) {
15928
+ if (
15929
+ def.fixed === false
15930
+ || def === fname_def
15931
+ || def.scope.get_defun_scope() !== parent
15932
+ ) {
15933
+ continue;
15934
+ }
15935
+
15936
+ // defun is hoisted, so always safe
15937
+ if (
15938
+ def.assignments === 0
15939
+ && def.orig.length === 1
15940
+ && def.orig[0] instanceof AST_SymbolDefun
15941
+ ) {
15942
+ continue;
15943
+ }
15944
+
15945
+ if (found_self_ref_in_other_defuns) {
15946
+ def.fixed = false;
15947
+ continue;
15948
+ }
15949
+
15950
+ // Detect `call_defun(); var used_in_defun = X`
15951
+ // Because `used_in_defun` is not certainly X when it's defined after.
15952
+ let found_defun_ref = false;
15953
+ let found_def_after_defun = false;
15954
+ walk_parent(parent, (node, info) => {
15955
+ if (node === defun) return true;
15956
+
15957
+ // Step 1: find `call_defun()` or other refs to the defun
15958
+ if (
15959
+ !found_defun_ref
15960
+ && node.thedef === fname_def
15961
+ && node instanceof AST_Symbol
15962
+ ) {
15963
+ found_defun_ref = true;
15964
+ }
15965
+
15966
+ // Step 2: if Step 1 occurred, find a var the defun uses
15967
+ if (
15968
+ found_defun_ref
15969
+ && node.thedef === def
15970
+ && (node instanceof AST_SymbolDeclaration
15971
+ || is_lhs(node, info))
15972
+ ) {
15973
+ found_def_after_defun = true;
15974
+ return walk_abort;
15975
+ }
15976
+ });
15977
+
15978
+ if (found_def_after_defun) {
15979
+ def.fixed = false;
15980
+ }
15981
+ }
15982
+ }
15983
+ }
15984
+
15589
15985
  def_reduce_vars(AST_Lambda, mark_lambda);
15590
15986
 
15591
15987
  def_reduce_vars(AST_Do, function(tw, descend, compressor) {
@@ -15706,12 +16102,15 @@ def_reduce_vars(AST_Toplevel, function(tw, descend, compressor) {
15706
16102
  reset_def(compressor, def);
15707
16103
  });
15708
16104
  reset_variables(tw, compressor, this);
16105
+ descend();
16106
+ handle_defined_after_hoist(this);
16107
+ return true;
15709
16108
  });
15710
16109
 
15711
16110
  def_reduce_vars(AST_Try, function(tw, descend, compressor) {
15712
16111
  reset_block_variables(compressor, this);
15713
16112
  push(tw);
15714
- walk_body(this, tw);
16113
+ this.body.walk(tw);
15715
16114
  pop(tw);
15716
16115
  if (this.bcatch) {
15717
16116
  push(tw);
@@ -15852,12 +16251,31 @@ function is_lhs_read_only(lhs) {
15852
16251
  return false;
15853
16252
  }
15854
16253
 
15855
- // Remove code which we know is unreachable.
16254
+ /** var a = 1 --> var a*/
16255
+ function remove_initializers(var_statement) {
16256
+ var decls = [];
16257
+ var_statement.definitions.forEach(function(def) {
16258
+ if (def.name instanceof AST_SymbolDeclaration) {
16259
+ def.value = null;
16260
+ decls.push(def);
16261
+ } else {
16262
+ def.declarations_as_names().forEach(name => {
16263
+ decls.push(make_node(AST_VarDef, def, {
16264
+ name,
16265
+ value: null
16266
+ }));
16267
+ });
16268
+ }
16269
+ });
16270
+ return decls.length ? make_node(AST_Var, var_statement, { definitions: decls }) : null;
16271
+ }
16272
+
16273
+ /** Called on code which we know is unreachable, to keep elements that affect outside of it. */
15856
16274
  function trim_unreachable_code(compressor, stat, target) {
15857
16275
  walk(stat, node => {
15858
16276
  if (node instanceof AST_Var) {
15859
- node.remove_initializers();
15860
- target.push(node);
16277
+ const no_initializers = remove_initializers(node);
16278
+ if (no_initializers) target.push(no_initializers);
15861
16279
  return true;
15862
16280
  }
15863
16281
  if (
@@ -15915,13 +16333,11 @@ function tighten_body(statements, compressor) {
15915
16333
  function find_loop_scope_try() {
15916
16334
  var node = compressor.self(), level = 0, in_loop = false, in_try = false;
15917
16335
  do {
15918
- if (node instanceof AST_Catch || node instanceof AST_Finally) {
15919
- level++;
15920
- } else if (node instanceof AST_IterationStatement) {
16336
+ if (node instanceof AST_IterationStatement) {
15921
16337
  in_loop = true;
15922
16338
  } else if (node instanceof AST_Scope) {
15923
16339
  break;
15924
- } else if (node instanceof AST_Try) {
16340
+ } else if (node instanceof AST_TryBlock) {
15925
16341
  in_try = true;
15926
16342
  }
15927
16343
  } while (node = compressor.parent(level++));
@@ -15965,6 +16381,9 @@ function tighten_body(statements, compressor) {
15965
16381
  && (node.logical || node.operator != "=" && lhs.equivalent_to(node.left))
15966
16382
  || node instanceof AST_Await
15967
16383
  || node instanceof AST_Call && lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression)
16384
+ ||
16385
+ (node instanceof AST_Call || node instanceof AST_PropAccess)
16386
+ && node.optional
15968
16387
  || node instanceof AST_Debugger
15969
16388
  || node instanceof AST_Destructuring
15970
16389
  || node instanceof AST_Expansion
@@ -16138,7 +16557,11 @@ function tighten_body(statements, compressor) {
16138
16557
  var hit = funarg;
16139
16558
  var abort = false, replaced = 0, can_replace = !args || !hit;
16140
16559
  if (!can_replace) {
16141
- for (var j = compressor.self().argnames.lastIndexOf(candidate.name) + 1; !abort && j < args.length; j++) {
16560
+ for (
16561
+ let j = compressor.self().argnames.lastIndexOf(candidate.name) + 1;
16562
+ !abort && j < args.length;
16563
+ j++
16564
+ ) {
16142
16565
  args[j].transform(scanner);
16143
16566
  }
16144
16567
  can_replace = true;
@@ -16660,27 +17083,34 @@ function tighten_body(statements, compressor) {
16660
17083
  }
16661
17084
 
16662
17085
  if (stat instanceof AST_If) {
16663
- var ab = aborts(stat.body);
16664
- if (can_merge_flow(ab)) {
17086
+ let ab, new_else;
17087
+
17088
+ ab = aborts(stat.body);
17089
+ if (
17090
+ can_merge_flow(ab)
17091
+ && (new_else = as_statement_array_with_return(stat.body, ab))
17092
+ ) {
16665
17093
  if (ab.label) {
16666
17094
  remove(ab.label.thedef.references, ab);
16667
17095
  }
16668
17096
  CHANGED = true;
16669
17097
  stat = stat.clone();
16670
17098
  stat.condition = stat.condition.negate(compressor);
16671
- var body = as_statement_array_with_return(stat.body, ab);
16672
17099
  stat.body = make_node(AST_BlockStatement, stat, {
16673
17100
  body: as_statement_array(stat.alternative).concat(extract_functions())
16674
17101
  });
16675
17102
  stat.alternative = make_node(AST_BlockStatement, stat, {
16676
- body: body
17103
+ body: new_else
16677
17104
  });
16678
17105
  statements[i] = stat.transform(compressor);
16679
17106
  continue;
16680
17107
  }
16681
17108
 
16682
- var ab = aborts(stat.alternative);
16683
- if (can_merge_flow(ab)) {
17109
+ ab = aborts(stat.alternative);
17110
+ if (
17111
+ can_merge_flow(ab)
17112
+ && (new_else = as_statement_array_with_return(stat.alternative, ab))
17113
+ ) {
16684
17114
  if (ab.label) {
16685
17115
  remove(ab.label.thedef.references, ab);
16686
17116
  }
@@ -16689,9 +17119,8 @@ function tighten_body(statements, compressor) {
16689
17119
  stat.body = make_node(AST_BlockStatement, stat.body, {
16690
17120
  body: as_statement_array(stat.body).concat(extract_functions())
16691
17121
  });
16692
- var body = as_statement_array_with_return(stat.alternative, ab);
16693
17122
  stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
16694
- body: body
17123
+ body: new_else
16695
17124
  });
16696
17125
  statements[i] = stat.transform(compressor);
16697
17126
  continue;
@@ -16806,7 +17235,11 @@ function tighten_body(statements, compressor) {
16806
17235
  }
16807
17236
 
16808
17237
  function as_statement_array_with_return(node, ab) {
16809
- var body = as_statement_array(node).slice(0, -1);
17238
+ var body = as_statement_array(node);
17239
+ if (ab !== body[body.length - 1]) {
17240
+ return undefined;
17241
+ }
17242
+ body = body.slice(0, -1);
16810
17243
  if (ab.value) {
16811
17244
  body.push(make_node(AST_SimpleStatement, ab.value, {
16812
17245
  body: ab.value.expression
@@ -17085,14 +17518,21 @@ function tighten_body(statements, compressor) {
17085
17518
  CHANGED = true;
17086
17519
  stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
17087
17520
  statements[++j] = stat;
17088
- } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
17521
+ } else if (
17522
+ prev instanceof AST_Var
17523
+ && (!stat.init || stat.init.TYPE == prev.TYPE)
17524
+ ) {
17089
17525
  if (stat.init) {
17090
17526
  prev.definitions = prev.definitions.concat(stat.init.definitions);
17091
17527
  }
17092
17528
  stat.init = prev;
17093
17529
  statements[j] = stat;
17094
17530
  CHANGED = true;
17095
- } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) {
17531
+ } else if (
17532
+ defs instanceof AST_Var
17533
+ && stat.init instanceof AST_Var
17534
+ && declarations_only(stat.init)
17535
+ ) {
17096
17536
  defs.definitions = defs.definitions.concat(stat.init.definitions);
17097
17537
  stat.init = null;
17098
17538
  statements[++j] = stat;
@@ -17184,6 +17624,13 @@ function tighten_body(statements, compressor) {
17184
17624
 
17185
17625
  ***********************************************************************/
17186
17626
 
17627
+ /**
17628
+ * Module that contains the inlining logic.
17629
+ *
17630
+ * @module
17631
+ *
17632
+ * The stars of the show are `inline_into_symbolref` and `inline_into_call`.
17633
+ */
17187
17634
 
17188
17635
  function within_array_or_object_literal(compressor) {
17189
17636
  var node, level = 0;
@@ -17214,136 +17661,135 @@ function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
17214
17661
 
17215
17662
  function inline_into_symbolref(self, compressor) {
17216
17663
  const parent = compressor.parent();
17217
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
17218
- const def = self.definition();
17219
- const nearest_scope = compressor.find_scope();
17220
- if (compressor.top_retain && def.global && compressor.top_retain(def)) {
17221
- def.fixed = false;
17222
- def.single_use = false;
17223
- return self;
17664
+
17665
+ const def = self.definition();
17666
+ const nearest_scope = compressor.find_scope();
17667
+ if (compressor.top_retain && def.global && compressor.top_retain(def)) {
17668
+ def.fixed = false;
17669
+ def.single_use = false;
17670
+ return self;
17671
+ }
17672
+
17673
+ let fixed = self.fixed_value();
17674
+ let single_use = def.single_use
17675
+ && !(parent instanceof AST_Call
17676
+ && (parent.is_callee_pure(compressor))
17677
+ || has_annotation(parent, _NOINLINE))
17678
+ && !(parent instanceof AST_Export
17679
+ && fixed instanceof AST_Lambda
17680
+ && fixed.name);
17681
+
17682
+ if (single_use && fixed instanceof AST_Node) {
17683
+ single_use =
17684
+ !fixed.has_side_effects(compressor)
17685
+ && !fixed.may_throw(compressor);
17686
+ }
17687
+
17688
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
17689
+ if (retain_top_func(fixed, compressor)) {
17690
+ single_use = false;
17691
+ } else if (def.scope !== self.scope
17692
+ && (def.escaped == 1
17693
+ || has_flag(fixed, INLINED)
17694
+ || within_array_or_object_literal(compressor)
17695
+ || !compressor.option("reduce_funcs"))) {
17696
+ single_use = false;
17697
+ } else if (is_recursive_ref(compressor, def)) {
17698
+ single_use = false;
17699
+ } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
17700
+ single_use = fixed.is_constant_expression(self.scope);
17701
+ if (single_use == "f") {
17702
+ var scope = self.scope;
17703
+ do {
17704
+ if (scope instanceof AST_Defun || is_func_expr(scope)) {
17705
+ set_flag(scope, INLINED);
17706
+ }
17707
+ } while (scope = scope.parent_scope);
17708
+ }
17224
17709
  }
17710
+ }
17225
17711
 
17226
- let fixed = self.fixed_value();
17227
- let single_use = def.single_use
17228
- && !(parent instanceof AST_Call
17229
- && (parent.is_callee_pure(compressor))
17230
- || has_annotation(parent, _NOINLINE))
17231
- && !(parent instanceof AST_Export
17232
- && fixed instanceof AST_Lambda
17233
- && fixed.name);
17234
-
17235
- if (single_use && fixed instanceof AST_Node) {
17236
- single_use =
17237
- !fixed.has_side_effects(compressor)
17238
- && !fixed.may_throw(compressor);
17239
- }
17240
-
17241
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
17242
- if (retain_top_func(fixed, compressor)) {
17243
- single_use = false;
17244
- } else if (def.scope !== self.scope
17245
- && (def.escaped == 1
17246
- || has_flag(fixed, INLINED)
17247
- || within_array_or_object_literal(compressor)
17248
- || !compressor.option("reduce_funcs"))) {
17249
- single_use = false;
17250
- } else if (is_recursive_ref(compressor, def)) {
17251
- single_use = false;
17252
- } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
17253
- single_use = fixed.is_constant_expression(self.scope);
17254
- if (single_use == "f") {
17255
- var scope = self.scope;
17256
- do {
17257
- if (scope instanceof AST_Defun || is_func_expr(scope)) {
17258
- set_flag(scope, INLINED);
17259
- }
17260
- } while (scope = scope.parent_scope);
17712
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
17713
+ single_use =
17714
+ def.scope === self.scope
17715
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
17716
+ || parent instanceof AST_Call
17717
+ && parent.expression === self
17718
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
17719
+ && !(fixed.name && fixed.name.definition().recursive_refs > 0);
17720
+ }
17721
+
17722
+ if (single_use && fixed) {
17723
+ if (fixed instanceof AST_DefClass) {
17724
+ set_flag(fixed, SQUEEZED);
17725
+ fixed = make_node(AST_ClassExpression, fixed, fixed);
17726
+ }
17727
+ if (fixed instanceof AST_Defun) {
17728
+ set_flag(fixed, SQUEEZED);
17729
+ fixed = make_node(AST_Function, fixed, fixed);
17730
+ }
17731
+ if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
17732
+ const defun_def = fixed.name.definition();
17733
+ let lambda_def = fixed.variables.get(fixed.name.name);
17734
+ let name = lambda_def && lambda_def.orig[0];
17735
+ if (!(name instanceof AST_SymbolLambda)) {
17736
+ name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
17737
+ name.scope = fixed;
17738
+ fixed.name = name;
17739
+ lambda_def = fixed.def_function(name);
17740
+ }
17741
+ walk(fixed, node => {
17742
+ if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
17743
+ node.thedef = lambda_def;
17744
+ lambda_def.references.push(node);
17261
17745
  }
17262
- }
17746
+ });
17263
17747
  }
17748
+ if (
17749
+ (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
17750
+ && fixed.parent_scope !== nearest_scope
17751
+ ) {
17752
+ fixed = fixed.clone(true, compressor.get_toplevel());
17264
17753
 
17265
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
17266
- single_use =
17267
- def.scope === self.scope
17268
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
17269
- || parent instanceof AST_Call
17270
- && parent.expression === self
17271
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
17272
- && !(fixed.name && fixed.name.definition().recursive_refs > 0);
17754
+ nearest_scope.add_child_scope(fixed);
17273
17755
  }
17756
+ return fixed.optimize(compressor);
17757
+ }
17274
17758
 
17275
- if (single_use && fixed) {
17276
- if (fixed instanceof AST_DefClass) {
17277
- set_flag(fixed, SQUEEZED);
17278
- fixed = make_node(AST_ClassExpression, fixed, fixed);
17279
- }
17280
- if (fixed instanceof AST_Defun) {
17281
- set_flag(fixed, SQUEEZED);
17282
- fixed = make_node(AST_Function, fixed, fixed);
17283
- }
17284
- if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
17285
- const defun_def = fixed.name.definition();
17286
- let lambda_def = fixed.variables.get(fixed.name.name);
17287
- let name = lambda_def && lambda_def.orig[0];
17288
- if (!(name instanceof AST_SymbolLambda)) {
17289
- name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
17290
- name.scope = fixed;
17291
- fixed.name = name;
17292
- lambda_def = fixed.def_function(name);
17293
- }
17294
- walk(fixed, node => {
17295
- if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
17296
- node.thedef = lambda_def;
17297
- lambda_def.references.push(node);
17298
- }
17299
- });
17759
+ // multiple uses
17760
+ if (fixed) {
17761
+ let replace;
17762
+
17763
+ if (fixed instanceof AST_This) {
17764
+ if (!(def.orig[0] instanceof AST_SymbolFunarg)
17765
+ && def.references.every((ref) =>
17766
+ def.scope === ref.scope
17767
+ )) {
17768
+ replace = fixed;
17300
17769
  }
17770
+ } else {
17771
+ var ev = fixed.evaluate(compressor);
17301
17772
  if (
17302
- (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
17303
- && fixed.parent_scope !== nearest_scope
17773
+ ev !== fixed
17774
+ && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
17304
17775
  ) {
17305
- fixed = fixed.clone(true, compressor.get_toplevel());
17306
-
17307
- nearest_scope.add_child_scope(fixed);
17776
+ replace = make_node_from_constant(ev, fixed);
17308
17777
  }
17309
- return fixed.optimize(compressor);
17310
17778
  }
17311
17779
 
17312
- // multiple uses
17313
- if (fixed) {
17314
- let replace;
17780
+ if (replace) {
17781
+ const name_length = self.size(compressor);
17782
+ const replace_size = replace.size(compressor);
17315
17783
 
17316
- if (fixed instanceof AST_This) {
17317
- if (!(def.orig[0] instanceof AST_SymbolFunarg)
17318
- && def.references.every((ref) =>
17319
- def.scope === ref.scope
17320
- )) {
17321
- replace = fixed;
17322
- }
17323
- } else {
17324
- var ev = fixed.evaluate(compressor);
17325
- if (
17326
- ev !== fixed
17327
- && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
17328
- ) {
17329
- replace = make_node_from_constant(ev, fixed);
17330
- }
17784
+ let overhead = 0;
17785
+ if (compressor.option("unused") && !compressor.exposed(def)) {
17786
+ overhead =
17787
+ (name_length + 2 + replace_size) /
17788
+ (def.references.length - def.assignments);
17331
17789
  }
17332
17790
 
17333
- if (replace) {
17334
- const name_length = self.size(compressor);
17335
- const replace_size = replace.size(compressor);
17336
-
17337
- let overhead = 0;
17338
- if (compressor.option("unused") && !compressor.exposed(def)) {
17339
- overhead =
17340
- (name_length + 2 + replace_size) /
17341
- (def.references.length - def.assignments);
17342
- }
17343
-
17344
- if (replace_size <= name_length + overhead) {
17345
- return replace;
17346
- }
17791
+ if (replace_size <= name_length + overhead) {
17792
+ return replace;
17347
17793
  }
17348
17794
  }
17349
17795
  }
@@ -17769,6 +18215,7 @@ class Compressor extends TreeWalker {
17769
18215
  keep_fargs : true,
17770
18216
  keep_fnames : false,
17771
18217
  keep_infinity : false,
18218
+ lhs_constants : !false_by_default,
17772
18219
  loops : !false_by_default,
17773
18220
  module : false,
17774
18221
  negate_iife : !false_by_default,
@@ -17965,6 +18412,13 @@ class Compressor extends TreeWalker {
17965
18412
  if (opt === node) set_flag(opt, SQUEEZED);
17966
18413
  return opt;
17967
18414
  }
18415
+
18416
+ /** Alternative to plain is_lhs() which doesn't work within .optimize() */
18417
+ is_lhs() {
18418
+ const self = this.stack[this.stack.length - 1];
18419
+ const parent = this.stack[this.stack.length - 2];
18420
+ return is_lhs(self, parent);
18421
+ }
17968
18422
  }
17969
18423
 
17970
18424
  function def_optimize(node, optimizer) {
@@ -18171,8 +18625,6 @@ def_optimize(AST_Lambda, opt_AST_Lambda);
18171
18625
  AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
18172
18626
  var self = this;
18173
18627
  if (compressor.has_directive("use asm")) return self;
18174
- // Hoisting makes no sense in an arrow func
18175
- if (!Array.isArray(self.body)) return self;
18176
18628
 
18177
18629
  var hoist_funs = compressor.option("hoist_funs");
18178
18630
  var hoist_vars = compressor.option("hoist_vars");
@@ -19053,9 +19505,9 @@ def_optimize(AST_Switch, function(self, compressor) {
19053
19505
  });
19054
19506
 
19055
19507
  def_optimize(AST_Try, function(self, compressor) {
19056
- tighten_body(self.body, compressor);
19057
19508
  if (self.bcatch && self.bfinally && self.bfinally.body.every(is_empty)) self.bfinally = null;
19058
- if (compressor.option("dead_code") && self.body.every(is_empty)) {
19509
+
19510
+ if (compressor.option("dead_code") && self.body.body.every(is_empty)) {
19059
19511
  var body = [];
19060
19512
  if (self.bcatch) {
19061
19513
  trim_unreachable_code(compressor, self.bcatch, body);
@@ -19068,26 +19520,6 @@ def_optimize(AST_Try, function(self, compressor) {
19068
19520
  return self;
19069
19521
  });
19070
19522
 
19071
- AST_Definitions.DEFMETHOD("remove_initializers", function() {
19072
- var decls = [];
19073
- this.definitions.forEach(function(def) {
19074
- if (def.name instanceof AST_SymbolDeclaration) {
19075
- def.value = null;
19076
- decls.push(def);
19077
- } else {
19078
- walk(def.name, node => {
19079
- if (node instanceof AST_SymbolDeclaration) {
19080
- decls.push(make_node(AST_VarDef, def, {
19081
- name: node,
19082
- value: null
19083
- }));
19084
- }
19085
- });
19086
- }
19087
- });
19088
- this.definitions = decls;
19089
- });
19090
-
19091
19523
  AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
19092
19524
  var reduce_vars = compressor.option("reduce_vars");
19093
19525
  var assignments = [];
@@ -19655,7 +20087,7 @@ def_optimize(AST_Binary, function(self, compressor) {
19655
20087
  self.right = tmp;
19656
20088
  }
19657
20089
  }
19658
- if (commutativeOperators.has(self.operator)) {
20090
+ if (compressor.option("lhs_constants") && commutativeOperators.has(self.operator)) {
19659
20091
  if (self.right.is_constant()
19660
20092
  && !self.left.is_constant()) {
19661
20093
  // if right is a constant, whatever side effects the
@@ -19685,6 +20117,9 @@ def_optimize(AST_Binary, function(self, compressor) {
19685
20117
  // void 0 == x => null == x
19686
20118
  if (!is_strict_comparison && is_undefined(self.left, compressor)) {
19687
20119
  self.left = make_node(AST_Null, self.left);
20120
+ // x == void 0 => x == null
20121
+ } else if (!is_strict_comparison && is_undefined(self.right, compressor)) {
20122
+ self.right = make_node(AST_Null, self.right);
19688
20123
  } else if (compressor.option("typeofs")
19689
20124
  // "undefined" == typeof x => undefined === x
19690
20125
  && self.left instanceof AST_String
@@ -19698,6 +20133,19 @@ def_optimize(AST_Binary, function(self, compressor) {
19698
20133
  self.left = make_node(AST_Undefined, self.left).optimize(compressor);
19699
20134
  if (self.operator.length == 2) self.operator += "=";
19700
20135
  }
20136
+ } else if (compressor.option("typeofs")
20137
+ // typeof x === "undefined" => x === undefined
20138
+ && self.left instanceof AST_UnaryPrefix
20139
+ && self.left.operator == "typeof"
20140
+ && self.right instanceof AST_String
20141
+ && self.right.value == "undefined") {
20142
+ var expr = self.left.expression;
20143
+ if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
20144
+ : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
20145
+ self.left = expr;
20146
+ self.right = make_node(AST_Undefined, self.right).optimize(compressor);
20147
+ if (self.operator.length == 2) self.operator += "=";
20148
+ }
19701
20149
  } else if (self.left instanceof AST_SymbolRef
19702
20150
  // obj !== obj => false
19703
20151
  && self.right instanceof AST_SymbolRef
@@ -20126,8 +20574,7 @@ def_optimize(AST_SymbolRef, function(self, compressor) {
20126
20574
  }
20127
20575
  }
20128
20576
 
20129
- const parent = compressor.parent();
20130
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
20577
+ if (compressor.option("reduce_vars") && !compressor.is_lhs()) {
20131
20578
  return inline_into_symbolref(self, compressor);
20132
20579
  } else {
20133
20580
  return self;
@@ -20151,7 +20598,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
20151
20598
  return ref;
20152
20599
  }
20153
20600
  }
20154
- var lhs = is_lhs(compressor.self(), compressor.parent());
20601
+ var lhs = compressor.is_lhs();
20155
20602
  if (lhs && is_atomic(lhs, self)) return self;
20156
20603
  return make_node(AST_UnaryPrefix, self, {
20157
20604
  operator: "void",
@@ -20162,7 +20609,7 @@ def_optimize(AST_Undefined, function(self, compressor) {
20162
20609
  });
20163
20610
 
20164
20611
  def_optimize(AST_Infinity, function(self, compressor) {
20165
- var lhs = is_lhs(compressor.self(), compressor.parent());
20612
+ var lhs = compressor.is_lhs();
20166
20613
  if (lhs && is_atomic(lhs, self)) return self;
20167
20614
  if (
20168
20615
  compressor.option("keep_infinity")
@@ -20183,7 +20630,7 @@ def_optimize(AST_Infinity, function(self, compressor) {
20183
20630
  });
20184
20631
 
20185
20632
  def_optimize(AST_NaN, function(self, compressor) {
20186
- var lhs = is_lhs(compressor.self(), compressor.parent());
20633
+ var lhs = compressor.is_lhs();
20187
20634
  if (lhs && !is_atomic(lhs, self)
20188
20635
  || find_variable(compressor, "NaN")) {
20189
20636
  return make_node(AST_Binary, self, {
@@ -20261,16 +20708,21 @@ def_optimize(AST_Assign, function(self, compressor) {
20261
20708
  return self;
20262
20709
 
20263
20710
  function in_try(level, node) {
20264
- var right = self.right;
20265
- self.right = make_node(AST_Null, right);
20266
- var may_throw = node.may_throw(compressor);
20267
- self.right = right;
20268
- var scope = self.left.definition().scope;
20711
+ function may_assignment_throw() {
20712
+ const right = self.right;
20713
+ self.right = make_node(AST_Null, right);
20714
+ const may_throw = node.may_throw(compressor);
20715
+ self.right = right;
20716
+
20717
+ return may_throw;
20718
+ }
20719
+
20720
+ var stop_at = self.left.definition().scope.get_defun_scope();
20269
20721
  var parent;
20270
- while ((parent = compressor.parent(level++)) !== scope) {
20722
+ while ((parent = compressor.parent(level++)) !== stop_at) {
20271
20723
  if (parent instanceof AST_Try) {
20272
20724
  if (parent.bfinally) return true;
20273
- if (may_throw && parent.bcatch) return true;
20725
+ if (parent.bcatch && may_assignment_throw()) return true;
20274
20726
  }
20275
20727
  }
20276
20728
  }
@@ -20283,8 +20735,21 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
20283
20735
  var evaluateRight = self.right.evaluate(compressor);
20284
20736
 
20285
20737
  // `[x = undefined] = foo` ---> `[x] = foo`
20738
+ // `(arg = undefined) => ...` ---> `(arg) => ...` (unless `keep_fargs`)
20739
+ // `((arg = undefined) => ...)()` ---> `((arg) => ...)()`
20740
+ let lambda, iife;
20286
20741
  if (evaluateRight === undefined) {
20287
- self = self.left;
20742
+ if (
20743
+ (lambda = compressor.parent()) instanceof AST_Lambda
20744
+ ? (
20745
+ compressor.option("keep_fargs") === false
20746
+ || (iife = compressor.parent(1)).TYPE === "Call"
20747
+ && iife.expression === lambda
20748
+ )
20749
+ : true
20750
+ ) {
20751
+ self = self.left;
20752
+ }
20288
20753
  } else if (evaluateRight !== self.right) {
20289
20754
  evaluateRight = make_node_from_constant(evaluateRight, self.right);
20290
20755
  self.right = best_of_expression(evaluateRight, self.right);
@@ -20741,7 +21206,10 @@ def_optimize(AST_Sub, function(self, compressor) {
20741
21206
  }
20742
21207
  }
20743
21208
  }
20744
- prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));
21209
+ prop = self.property = best_of_expression(
21210
+ prop,
21211
+ make_node_from_constant(key, prop).transform(compressor)
21212
+ );
20745
21213
  var property = "" + key;
20746
21214
  if (is_basic_identifier_string(property)
20747
21215
  && property.length <= prop.size() + 1) {
@@ -20799,7 +21267,7 @@ def_optimize(AST_Sub, function(self, compressor) {
20799
21267
  return sym;
20800
21268
  }
20801
21269
  }
20802
- if (is_lhs(self, compressor.parent())) return self;
21270
+ if (compressor.is_lhs()) return self;
20803
21271
  if (key !== prop) {
20804
21272
  var sub = self.flatten_object(property, compressor);
20805
21273
  if (sub) {
@@ -20867,22 +21335,9 @@ def_optimize(AST_Chain, function (self, compressor) {
20867
21335
  return self;
20868
21336
  });
20869
21337
 
20870
- AST_Lambda.DEFMETHOD("contains_this", function() {
20871
- return walk(this, node => {
20872
- if (node instanceof AST_This) return walk_abort;
20873
- if (
20874
- node !== this
20875
- && node instanceof AST_Scope
20876
- && !(node instanceof AST_Arrow)
20877
- ) {
20878
- return true;
20879
- }
20880
- });
20881
- });
20882
-
20883
21338
  def_optimize(AST_Dot, function(self, compressor) {
20884
21339
  const parent = compressor.parent();
20885
- if (is_lhs(self, parent)) return self;
21340
+ if (compressor.is_lhs()) return self;
20886
21341
  if (compressor.option("unsafe_proto")
20887
21342
  && self.expression instanceof AST_Dot
20888
21343
  && self.expression.property == "prototype") {
@@ -24993,6 +25448,7 @@ var domprops = [
24993
25448
  "coneInnerAngle",
24994
25449
  "coneOuterAngle",
24995
25450
  "coneOuterGain",
25451
+ "configurable",
24996
25452
  "configuration",
24997
25453
  "configurationName",
24998
25454
  "configurationValue",
@@ -25502,6 +25958,7 @@ var domprops = [
25502
25958
  "entities",
25503
25959
  "entries",
25504
25960
  "entryType",
25961
+ "enumerable",
25505
25962
  "enumerate",
25506
25963
  "enumerateDevices",
25507
25964
  "enumerateEditable",
@@ -26184,6 +26641,7 @@ var domprops = [
26184
26641
  "indexOf",
26185
26642
  "indexedDB",
26186
26643
  "indicate",
26644
+ "inert",
26187
26645
  "inertiaDestinationX",
26188
26646
  "inertiaDestinationY",
26189
26647
  "info",
@@ -29437,6 +29895,8 @@ function mangle_properties(ast, options) {
29437
29895
  addStrings(node.args[1], add);
29438
29896
  } else if (node instanceof AST_Binary && node.operator === "in") {
29439
29897
  addStrings(node.left, add);
29898
+ } else if (node instanceof AST_String && has_annotation(node, _KEY)) {
29899
+ add(node.value);
29440
29900
  }
29441
29901
  }));
29442
29902
 
@@ -29468,6 +29928,10 @@ function mangle_properties(ast, options) {
29468
29928
  node.args[1] = mangleStrings(node.args[1]);
29469
29929
  } else if (node instanceof AST_Binary && node.operator === "in") {
29470
29930
  node.left = mangleStrings(node.left);
29931
+ } else if (node instanceof AST_String && has_annotation(node, _KEY)) {
29932
+ // Clear _KEY annotation to prevent double mangling
29933
+ clear_annotation(node, _KEY);
29934
+ node.value = mangle(node.value);
29471
29935
  }
29472
29936
  }));
29473
29937
 
@@ -29533,6 +29997,8 @@ function mangle_properties(ast, options) {
29533
29997
  var last = node.expressions.length - 1;
29534
29998
  node.expressions[last] = mangleStrings(node.expressions[last]);
29535
29999
  } else if (node instanceof AST_String) {
30000
+ // Clear _KEY annotation to prevent double mangling
30001
+ clear_annotation(node, _KEY);
29536
30002
  node.value = mangle(node.value);
29537
30003
  } else if (node instanceof AST_Conditional) {
29538
30004
  node.consequent = mangleStrings(node.consequent);
@@ -29543,12 +30009,15 @@ function mangle_properties(ast, options) {
29543
30009
  }
29544
30010
  }
29545
30011
 
29546
- var to_ascii = typeof atob == "undefined" ? function(b64) {
29547
- return Buffer.from(b64, "base64").toString();
29548
- } : atob;
29549
- var to_base64 = typeof btoa == "undefined" ? function(str) {
29550
- return Buffer.from(str).toString("base64");
29551
- } : btoa;
30012
+ // to/from base64 functions
30013
+ // Prefer built-in Buffer, if available, then use hack
30014
+ // https://developer.mozilla.org/en-US/docs/Glossary/Base64#The_Unicode_Problem
30015
+ var to_ascii = typeof Buffer !== "undefined"
30016
+ ? (b64) => Buffer.from(b64, "base64").toString()
30017
+ : (b64) => decodeURIComponent(escape(atob(b64)));
30018
+ var to_base64 = typeof Buffer !== "undefined"
30019
+ ? (str) => Buffer.from(str).toString("base64")
30020
+ : (str) => btoa(unescape(encodeURIComponent(str)));
29552
30021
 
29553
30022
  function read_source_map(code) {
29554
30023
  var match = /(?:^|[^.])\/\/# sourceMappingURL=data:application\/json(;[\w=-]*)?;base64,([+/0-9A-Za-z]*=*)\s*$/.exec(code);
@@ -29795,10 +30264,13 @@ async function minify(files, options, _fs_module) {
29795
30264
  if (options.format.spidermonkey) {
29796
30265
  result.ast = toplevel.to_mozilla_ast();
29797
30266
  }
30267
+ let format_options;
29798
30268
  if (!HOP(options.format, "code") || options.format.code) {
29799
- if (!options.format.ast) {
30269
+ // Make a shallow copy so that we can modify without mutating the user's input.
30270
+ format_options = {...options.format};
30271
+ if (!format_options.ast) {
29800
30272
  // Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
29801
- options.format._destroy_ast = true;
30273
+ format_options._destroy_ast = true;
29802
30274
 
29803
30275
  walk(toplevel, node => {
29804
30276
  if (node instanceof AST_Scope) {
@@ -29818,17 +30290,17 @@ async function minify(files, options, _fs_module) {
29818
30290
  if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
29819
30291
  throw new Error("original source content unavailable");
29820
30292
  }
29821
- options.format.source_map = await SourceMap({
30293
+ format_options.source_map = await SourceMap({
29822
30294
  file: options.sourceMap.filename,
29823
30295
  orig: options.sourceMap.content,
29824
30296
  root: options.sourceMap.root,
29825
30297
  files: options.sourceMap.includeSources ? files : null,
29826
30298
  });
29827
30299
  }
29828
- delete options.format.ast;
29829
- delete options.format.code;
29830
- delete options.format.spidermonkey;
29831
- var stream = OutputStream(options.format);
30300
+ delete format_options.ast;
30301
+ delete format_options.code;
30302
+ delete format_options.spidermonkey;
30303
+ var stream = OutputStream(format_options);
29832
30304
  toplevel.print(stream);
29833
30305
  result.code = stream.get();
29834
30306
  if (options.sourceMap) {
@@ -29836,7 +30308,7 @@ async function minify(files, options, _fs_module) {
29836
30308
  configurable: true,
29837
30309
  enumerable: true,
29838
30310
  get() {
29839
- const map = options.format.source_map.getEncoded();
30311
+ const map = format_options.source_map.getEncoded();
29840
30312
  return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
29841
30313
  },
29842
30314
  set(value) {
@@ -29846,7 +30318,7 @@ async function minify(files, options, _fs_module) {
29846
30318
  });
29847
30319
  }
29848
30320
  });
29849
- result.decoded_map = options.format.source_map.getDecoded();
30321
+ result.decoded_map = format_options.source_map.getDecoded();
29850
30322
  if (options.sourceMap.url == "inline") {
29851
30323
  var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
29852
30324
  result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
@@ -29861,8 +30333,8 @@ async function minify(files, options, _fs_module) {
29861
30333
  options.nameCache.props = cache_to_json(options.mangle.properties.cache);
29862
30334
  }
29863
30335
  }
29864
- if (options.format && options.format.source_map) {
29865
- options.format.source_map.destroy();
30336
+ if (format_options && format_options.source_map) {
30337
+ format_options.source_map.destroy();
29866
30338
  }
29867
30339
  if (timings) {
29868
30340
  timings.end = Date.now();
@@ -30371,4 +30843,4 @@ exports._default_options = _default_options;
30371
30843
  exports._run_cli = run_cli;
30372
30844
  exports.minify = minify;
30373
30845
 
30374
- })));
30846
+ }));