terser 5.13.1 → 5.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.14.0
4
+ - Switched to @jridgewell/source-map for sourcemap generation (#1190, #1181)
5
+ - Fixed source maps with non-terminated segments (#1106)
6
+ - Enabled typescript types to be imported from the package (#1194)
7
+ - Extra DOM props have been added (#1191)
8
+ - Delete the AST while generating code, as a means to save RAM
9
+
3
10
  ## v5.13.1
4
11
  - Removed self-assignments (`varname=varname`) (closes #1081)
5
12
  - Separated inlining code (for inlining things into references, or removing IIFEs)
@@ -1,12 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('source-map')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'source-map'], factory) :
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@jridgewell/source-map')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@jridgewell/source-map'], factory) :
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Terser = {}, global.sourceMap));
5
- }(this, (function (exports, MOZ_SourceMap) { 'use strict';
6
-
7
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
-
9
- var MOZ_SourceMap__default = /*#__PURE__*/_interopDefaultLegacy(MOZ_SourceMap);
5
+ }(this, (function (exports, sourceMap) { 'use strict';
10
6
 
11
7
  /***********************************************************************
12
8
 
@@ -4059,11 +4055,10 @@ var AST_With = DEFNODE("With", "expression", function AST_With(props) {
4059
4055
 
4060
4056
  var AST_Scope = DEFNODE(
4061
4057
  "Scope",
4062
- "variables functions uses_with uses_eval parent_scope enclosed cname",
4058
+ "variables uses_with uses_eval parent_scope enclosed cname",
4063
4059
  function AST_Scope(props) {
4064
4060
  if (props) {
4065
4061
  this.variables = props.variables;
4066
- this.functions = props.functions;
4067
4062
  this.uses_with = props.uses_with;
4068
4063
  this.uses_eval = props.uses_eval;
4069
4064
  this.parent_scope = props.parent_scope;
@@ -4119,7 +4114,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
4119
4114
  if (props) {
4120
4115
  this.globals = props.globals;
4121
4116
  this.variables = props.variables;
4122
- this.functions = props.functions;
4123
4117
  this.uses_with = props.uses_with;
4124
4118
  this.uses_eval = props.uses_eval;
4125
4119
  this.parent_scope = props.parent_scope;
@@ -4201,7 +4195,6 @@ var AST_Lambda = DEFNODE(
4201
4195
  this.is_generator = props.is_generator;
4202
4196
  this.async = props.async;
4203
4197
  this.variables = props.variables;
4204
- this.functions = props.functions;
4205
4198
  this.uses_with = props.uses_with;
4206
4199
  this.uses_eval = props.uses_eval;
4207
4200
  this.parent_scope = props.parent_scope;
@@ -4281,7 +4274,6 @@ var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
4281
4274
  this.is_generator = props.is_generator;
4282
4275
  this.async = props.async;
4283
4276
  this.variables = props.variables;
4284
- this.functions = props.functions;
4285
4277
  this.uses_with = props.uses_with;
4286
4278
  this.uses_eval = props.uses_eval;
4287
4279
  this.parent_scope = props.parent_scope;
@@ -4306,7 +4298,6 @@ var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
4306
4298
  this.is_generator = props.is_generator;
4307
4299
  this.async = props.async;
4308
4300
  this.variables = props.variables;
4309
- this.functions = props.functions;
4310
4301
  this.uses_with = props.uses_with;
4311
4302
  this.uses_eval = props.uses_eval;
4312
4303
  this.parent_scope = props.parent_scope;
@@ -4331,7 +4322,6 @@ var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
4331
4322
  this.is_generator = props.is_generator;
4332
4323
  this.async = props.async;
4333
4324
  this.variables = props.variables;
4334
- this.functions = props.functions;
4335
4325
  this.uses_with = props.uses_with;
4336
4326
  this.uses_eval = props.uses_eval;
4337
4327
  this.parent_scope = props.parent_scope;
@@ -4356,7 +4346,6 @@ var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
4356
4346
  this.is_generator = props.is_generator;
4357
4347
  this.async = props.async;
4358
4348
  this.variables = props.variables;
4359
- this.functions = props.functions;
4360
4349
  this.uses_with = props.uses_with;
4361
4350
  this.uses_eval = props.uses_eval;
4362
4351
  this.parent_scope = props.parent_scope;
@@ -5668,7 +5657,6 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
5668
5657
  this.extends = props.extends;
5669
5658
  this.properties = props.properties;
5670
5659
  this.variables = props.variables;
5671
- this.functions = props.functions;
5672
5660
  this.uses_with = props.uses_with;
5673
5661
  this.uses_eval = props.uses_eval;
5674
5662
  this.parent_scope = props.parent_scope;
@@ -5762,7 +5750,6 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
5762
5750
  this.extends = props.extends;
5763
5751
  this.properties = props.properties;
5764
5752
  this.variables = props.variables;
5765
- this.functions = props.functions;
5766
5753
  this.uses_with = props.uses_with;
5767
5754
  this.uses_eval = props.uses_eval;
5768
5755
  this.parent_scope = props.parent_scope;
@@ -5785,7 +5772,6 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExp
5785
5772
  this.extends = props.extends;
5786
5773
  this.properties = props.properties;
5787
5774
  this.variables = props.variables;
5788
- this.functions = props.functions;
5789
5775
  this.uses_with = props.uses_with;
5790
5776
  this.uses_eval = props.uses_eval;
5791
5777
  this.parent_scope = props.parent_scope;
@@ -8644,6 +8630,8 @@ function OutputStream(options) {
8644
8630
  width : 80,
8645
8631
  wrap_iife : false,
8646
8632
  wrap_func_args : true,
8633
+
8634
+ _destroy_ast : false
8647
8635
  }, true);
8648
8636
 
8649
8637
  if (options.shorthand === undefined)
@@ -9193,6 +9181,18 @@ function OutputStream(options) {
9193
9181
  if (OUTPUT.length() > insert) newline_insert = insert;
9194
9182
  }
9195
9183
 
9184
+ /**
9185
+ * When output.option("_destroy_ast") is enabled, destroy the function.
9186
+ * Call this after printing it.
9187
+ */
9188
+ const gc_scope =
9189
+ options["_destroy_ast"]
9190
+ ? function gc_scope(scope) {
9191
+ scope.body.length = 0;
9192
+ scope.argnames.length = 0;
9193
+ }
9194
+ : noop;
9195
+
9196
9196
  var stack = [];
9197
9197
  return {
9198
9198
  get : get,
@@ -9239,6 +9239,7 @@ function OutputStream(options) {
9239
9239
  with_square : with_square,
9240
9240
  add_mapping : add_mapping,
9241
9241
  option : function(opt) { return options[opt]; },
9242
+ gc_scope,
9242
9243
  printed_comments: printed_comments,
9243
9244
  prepend_comments: readonly ? noop : prepend_comments,
9244
9245
  append_comments : readonly || comment_filter === return_false ? noop : append_comments,
@@ -9755,6 +9756,7 @@ function OutputStream(options) {
9755
9756
  });
9756
9757
  DEFPRINT(AST_Lambda, function(self, output) {
9757
9758
  self._do_print(output);
9759
+ output.gc_scope(self);
9758
9760
  });
9759
9761
 
9760
9762
  DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
@@ -9834,6 +9836,7 @@ function OutputStream(options) {
9834
9836
  print_braced(self, output);
9835
9837
  }
9836
9838
  if (needs_parens) { output.print(")"); }
9839
+ output.gc_scope(self);
9837
9840
  });
9838
9841
 
9839
9842
  /* -----[ exits ]----- */
@@ -21021,40 +21024,56 @@ def_optimize(AST_Destructuring, function(self, compressor) {
21021
21024
 
21022
21025
  ***********************************************************************/
21023
21026
 
21024
- // a small wrapper around fitzgen's source-map library
21027
+ // a small wrapper around source-map and @jridgewell/source-map
21025
21028
  async function SourceMap(options) {
21026
21029
  options = defaults(options, {
21027
21030
  file : null,
21028
21031
  root : null,
21029
21032
  orig : null,
21030
-
21031
- orig_line_diff : 0,
21032
- dest_line_diff : 0,
21033
+ files: {},
21033
21034
  });
21034
21035
 
21035
21036
  var orig_map;
21036
- var generator = new MOZ_SourceMap__default['default'].SourceMapGenerator({
21037
+ var generator = new sourceMap.SourceMapGenerator({
21037
21038
  file : options.file,
21038
21039
  sourceRoot : options.root
21039
21040
  });
21040
21041
 
21042
+ let sourcesContent = {__proto__: null};
21043
+ let files = options.files;
21044
+ for (var name in files) if (HOP(files, name)) {
21045
+ sourcesContent[name] = files[name];
21046
+ }
21041
21047
  if (options.orig) {
21042
- orig_map = await new MOZ_SourceMap__default['default'].SourceMapConsumer(options.orig);
21043
- orig_map.sources.forEach(function(source) {
21044
- var sourceContent = orig_map.sourceContentFor(source, true);
21045
- if (sourceContent) {
21046
- generator.setSourceContent(source, sourceContent);
21047
- }
21048
- });
21048
+ // We support both @jridgewell/source-map (which has a sync
21049
+ // SourceMapConsumer) and source-map (which has an async
21050
+ // SourceMapConsumer).
21051
+ orig_map = await new sourceMap.SourceMapConsumer(options.orig);
21052
+ if (orig_map.sourcesContent) {
21053
+ orig_map.sources.forEach(function(source, i) {
21054
+ var content = orig_map.sourcesContent[i];
21055
+ if (content) {
21056
+ sourcesContent[source] = content;
21057
+ }
21058
+ });
21059
+ }
21049
21060
  }
21050
21061
 
21051
21062
  function add(source, gen_line, gen_col, orig_line, orig_col, name) {
21063
+ let generatedPos = { line: gen_line, column: gen_col };
21064
+
21052
21065
  if (orig_map) {
21053
21066
  var info = orig_map.originalPositionFor({
21054
21067
  line: orig_line,
21055
21068
  column: orig_col
21056
21069
  });
21057
21070
  if (info.source === null) {
21071
+ generator.addMapping({
21072
+ generated: generatedPos,
21073
+ original: null,
21074
+ source: null,
21075
+ name: null
21076
+ });
21058
21077
  return;
21059
21078
  }
21060
21079
  source = info.source;
@@ -21063,22 +21082,42 @@ async function SourceMap(options) {
21063
21082
  name = info.name || name;
21064
21083
  }
21065
21084
  generator.addMapping({
21066
- generated : { line: gen_line + options.dest_line_diff, column: gen_col },
21067
- original : { line: orig_line + options.orig_line_diff, column: orig_col },
21085
+ generated : generatedPos,
21086
+ original : { line: orig_line, column: orig_col },
21068
21087
  source : source,
21069
21088
  name : name
21070
21089
  });
21090
+ generator.setSourceContent(source, sourcesContent[source]);
21091
+ }
21092
+
21093
+ function clean(map) {
21094
+ const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null);
21095
+ if (allNull) delete map.sourcesContent;
21096
+ if (map.file === undefined) delete map.file;
21097
+ if (map.sourceRoot === undefined) delete map.sourceRoot;
21098
+ return map;
21099
+ }
21100
+
21101
+ function getDecoded() {
21102
+ if (!generator.toDecodedMap) return null;
21103
+ return clean(generator.toDecodedMap());
21104
+ }
21105
+
21106
+ function getEncoded() {
21107
+ return clean(generator.toJSON());
21108
+ }
21109
+
21110
+ function destroy() {
21111
+ // @jridgewell/source-map's SourceMapConsumer does not need to be
21112
+ // manually freed.
21113
+ if (orig_map && orig_map.destroy) orig_map.destroy();
21071
21114
  }
21072
21115
 
21073
21116
  return {
21074
- add : add,
21075
- get : function() { return generator; },
21076
- toString : function() { return generator.toString(); },
21077
- destroy : function () {
21078
- if (orig_map && orig_map.destroy) {
21079
- orig_map.destroy();
21080
- }
21081
- }
21117
+ add,
21118
+ getDecoded,
21119
+ getEncoded,
21120
+ destroy,
21082
21121
  };
21083
21122
  }
21084
21123
 
@@ -21404,6 +21443,7 @@ var domprops = [
21404
21443
  "COMMENT_NODE",
21405
21444
  "COMPARE_REF_TO_TEXTURE",
21406
21445
  "COMPILE_STATUS",
21446
+ "COMPLETION_STATUS_KHR",
21407
21447
  "COMPRESSED_RGBA_S3TC_DXT1_EXT",
21408
21448
  "COMPRESSED_RGBA_S3TC_DXT3_EXT",
21409
21449
  "COMPRESSED_RGBA_S3TC_DXT5_EXT",
@@ -29379,6 +29419,8 @@ async function minify(files, options, _fs_module) {
29379
29419
  url: null,
29380
29420
  }, true);
29381
29421
  }
29422
+
29423
+ // -- Parse phase --
29382
29424
  if (timings) timings.parse = Date.now();
29383
29425
  var toplevel;
29384
29426
  if (files instanceof AST_Toplevel) {
@@ -29422,12 +29464,16 @@ async function minify(files, options, _fs_module) {
29422
29464
  toplevel = toplevel.wrap_enclose(options.enclose);
29423
29465
  }
29424
29466
  if (timings) timings.rename = Date.now();
29467
+
29468
+ // -- Compress phase --
29425
29469
  if (timings) timings.compress = Date.now();
29426
29470
  if (options.compress) {
29427
29471
  toplevel = new Compressor(options.compress, {
29428
29472
  mangle_options: options.mangle
29429
29473
  }).compress(toplevel);
29430
29474
  }
29475
+
29476
+ // -- Mangle phase --
29431
29477
  if (timings) timings.scope = Date.now();
29432
29478
  if (options.mangle) toplevel.figure_out_scope(options.mangle);
29433
29479
  if (timings) timings.mangle = Date.now();
@@ -29440,6 +29486,8 @@ async function minify(files, options, _fs_module) {
29440
29486
  if (options.mangle && options.mangle.properties) {
29441
29487
  toplevel = mangle_properties(toplevel, options.mangle.properties);
29442
29488
  }
29489
+
29490
+ // Format phase
29443
29491
  if (timings) timings.format = Date.now();
29444
29492
  var result = {};
29445
29493
  if (options.format.ast) {
@@ -29449,19 +29497,34 @@ async function minify(files, options, _fs_module) {
29449
29497
  result.ast = toplevel.to_mozilla_ast();
29450
29498
  }
29451
29499
  if (!HOP(options.format, "code") || options.format.code) {
29500
+ if (!options.format.ast) {
29501
+ // Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
29502
+ options.format._destroy_ast = true;
29503
+
29504
+ walk(toplevel, node => {
29505
+ if (node instanceof AST_Scope) {
29506
+ node.variables = undefined;
29507
+ node.enclosed = undefined;
29508
+ node.parent_scope = undefined;
29509
+ }
29510
+ if (node.block_scope) {
29511
+ node.block_scope.variables = undefined;
29512
+ node.block_scope.enclosed = undefined;
29513
+ node.parent_scope = undefined;
29514
+ }
29515
+ });
29516
+ }
29517
+
29452
29518
  if (options.sourceMap) {
29519
+ if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
29520
+ throw new Error("original source content unavailable");
29521
+ }
29453
29522
  options.format.source_map = await SourceMap({
29454
29523
  file: options.sourceMap.filename,
29455
29524
  orig: options.sourceMap.content,
29456
- root: options.sourceMap.root
29525
+ root: options.sourceMap.root,
29526
+ files: options.sourceMap.includeSources ? files : null,
29457
29527
  });
29458
- if (options.sourceMap.includeSources) {
29459
- if (files instanceof AST_Toplevel) {
29460
- throw new Error("original source content unavailable");
29461
- } else for (var name in files) if (HOP(files, name)) {
29462
- options.format.source_map.get().setSourceContent(name, files[name]);
29463
- }
29464
- }
29465
29528
  }
29466
29529
  delete options.format.ast;
29467
29530
  delete options.format.code;
@@ -29470,11 +29533,21 @@ async function minify(files, options, _fs_module) {
29470
29533
  toplevel.print(stream);
29471
29534
  result.code = stream.get();
29472
29535
  if (options.sourceMap) {
29473
- if(options.sourceMap.asObject) {
29474
- result.map = options.format.source_map.get().toJSON();
29475
- } else {
29476
- result.map = options.format.source_map.toString();
29477
- }
29536
+ Object.defineProperty(result, "map", {
29537
+ configurable: true,
29538
+ enumerable: true,
29539
+ get() {
29540
+ const map = options.format.source_map.getEncoded();
29541
+ return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
29542
+ },
29543
+ set(value) {
29544
+ Object.defineProperty(result, "map", {
29545
+ value,
29546
+ writable: true,
29547
+ });
29548
+ }
29549
+ });
29550
+ result.decoded_map = options.format.source_map.getDecoded();
29478
29551
  if (options.sourceMap.url == "inline") {
29479
29552
  var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
29480
29553
  result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
package/lib/ast.js CHANGED
@@ -552,11 +552,10 @@ var AST_With = DEFNODE("With", "expression", function AST_With(props) {
552
552
 
553
553
  var AST_Scope = DEFNODE(
554
554
  "Scope",
555
- "variables functions uses_with uses_eval parent_scope enclosed cname",
555
+ "variables uses_with uses_eval parent_scope enclosed cname",
556
556
  function AST_Scope(props) {
557
557
  if (props) {
558
558
  this.variables = props.variables;
559
- this.functions = props.functions;
560
559
  this.uses_with = props.uses_with;
561
560
  this.uses_eval = props.uses_eval;
562
561
  this.parent_scope = props.parent_scope;
@@ -612,7 +611,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", function AST_Toplevel(props) {
612
611
  if (props) {
613
612
  this.globals = props.globals;
614
613
  this.variables = props.variables;
615
- this.functions = props.functions;
616
614
  this.uses_with = props.uses_with;
617
615
  this.uses_eval = props.uses_eval;
618
616
  this.parent_scope = props.parent_scope;
@@ -694,7 +692,6 @@ var AST_Lambda = DEFNODE(
694
692
  this.is_generator = props.is_generator;
695
693
  this.async = props.async;
696
694
  this.variables = props.variables;
697
- this.functions = props.functions;
698
695
  this.uses_with = props.uses_with;
699
696
  this.uses_eval = props.uses_eval;
700
697
  this.parent_scope = props.parent_scope;
@@ -774,7 +771,6 @@ var AST_Accessor = DEFNODE("Accessor", null, function AST_Accessor(props) {
774
771
  this.is_generator = props.is_generator;
775
772
  this.async = props.async;
776
773
  this.variables = props.variables;
777
- this.functions = props.functions;
778
774
  this.uses_with = props.uses_with;
779
775
  this.uses_eval = props.uses_eval;
780
776
  this.parent_scope = props.parent_scope;
@@ -799,7 +795,6 @@ var AST_Function = DEFNODE("Function", null, function AST_Function(props) {
799
795
  this.is_generator = props.is_generator;
800
796
  this.async = props.async;
801
797
  this.variables = props.variables;
802
- this.functions = props.functions;
803
798
  this.uses_with = props.uses_with;
804
799
  this.uses_eval = props.uses_eval;
805
800
  this.parent_scope = props.parent_scope;
@@ -824,7 +819,6 @@ var AST_Arrow = DEFNODE("Arrow", null, function AST_Arrow(props) {
824
819
  this.is_generator = props.is_generator;
825
820
  this.async = props.async;
826
821
  this.variables = props.variables;
827
- this.functions = props.functions;
828
822
  this.uses_with = props.uses_with;
829
823
  this.uses_eval = props.uses_eval;
830
824
  this.parent_scope = props.parent_scope;
@@ -849,7 +843,6 @@ var AST_Defun = DEFNODE("Defun", null, function AST_Defun(props) {
849
843
  this.is_generator = props.is_generator;
850
844
  this.async = props.async;
851
845
  this.variables = props.variables;
852
- this.functions = props.functions;
853
846
  this.uses_with = props.uses_with;
854
847
  this.uses_eval = props.uses_eval;
855
848
  this.parent_scope = props.parent_scope;
@@ -2161,7 +2154,6 @@ var AST_Class = DEFNODE("Class", "name extends properties", function AST_Class(p
2161
2154
  this.extends = props.extends;
2162
2155
  this.properties = props.properties;
2163
2156
  this.variables = props.variables;
2164
- this.functions = props.functions;
2165
2157
  this.uses_with = props.uses_with;
2166
2158
  this.uses_eval = props.uses_eval;
2167
2159
  this.parent_scope = props.parent_scope;
@@ -2255,7 +2247,6 @@ var AST_DefClass = DEFNODE("DefClass", null, function AST_DefClass(props) {
2255
2247
  this.extends = props.extends;
2256
2248
  this.properties = props.properties;
2257
2249
  this.variables = props.variables;
2258
- this.functions = props.functions;
2259
2250
  this.uses_with = props.uses_with;
2260
2251
  this.uses_eval = props.uses_eval;
2261
2252
  this.parent_scope = props.parent_scope;
@@ -2278,7 +2269,6 @@ var AST_ClassExpression = DEFNODE("ClassExpression", null, function AST_ClassExp
2278
2269
  this.extends = props.extends;
2279
2270
  this.properties = props.properties;
2280
2271
  this.variables = props.variables;
2281
- this.functions = props.functions;
2282
2272
  this.uses_with = props.uses_with;
2283
2273
  this.uses_eval = props.uses_eval;
2284
2274
  this.parent_scope = props.parent_scope;
package/lib/minify.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  map_to_object,
8
8
  HOP,
9
9
  } from "./utils/index.js";
10
- import { AST_Toplevel, AST_Node } from "./ast.js";
10
+ import { AST_Toplevel, AST_Node, walk, AST_Scope } from "./ast.js";
11
11
  import { parse } from "./parse.js";
12
12
  import { OutputStream } from "./output.js";
13
13
  import { Compressor } from "./compress/index.js";
@@ -194,6 +194,8 @@ async function minify(files, options, _fs_module) {
194
194
  url: null,
195
195
  }, true);
196
196
  }
197
+
198
+ // -- Parse phase --
197
199
  if (timings) timings.parse = Date.now();
198
200
  var toplevel;
199
201
  if (files instanceof AST_Toplevel) {
@@ -243,12 +245,16 @@ async function minify(files, options, _fs_module) {
243
245
  toplevel.figure_out_scope(options.mangle);
244
246
  toplevel.expand_names(options.mangle);
245
247
  }
248
+
249
+ // -- Compress phase --
246
250
  if (timings) timings.compress = Date.now();
247
251
  if (options.compress) {
248
252
  toplevel = new Compressor(options.compress, {
249
253
  mangle_options: options.mangle
250
254
  }).compress(toplevel);
251
255
  }
256
+
257
+ // -- Mangle phase --
252
258
  if (timings) timings.scope = Date.now();
253
259
  if (options.mangle) toplevel.figure_out_scope(options.mangle);
254
260
  if (timings) timings.mangle = Date.now();
@@ -261,6 +267,8 @@ async function minify(files, options, _fs_module) {
261
267
  if (options.mangle && options.mangle.properties) {
262
268
  toplevel = mangle_properties(toplevel, options.mangle.properties);
263
269
  }
270
+
271
+ // Format phase
264
272
  if (timings) timings.format = Date.now();
265
273
  var result = {};
266
274
  if (options.format.ast) {
@@ -270,19 +278,34 @@ async function minify(files, options, _fs_module) {
270
278
  result.ast = toplevel.to_mozilla_ast();
271
279
  }
272
280
  if (!HOP(options.format, "code") || options.format.code) {
281
+ if (!options.format.ast) {
282
+ // Destroy stuff to save RAM. (unless the deprecated `ast` option is on)
283
+ options.format._destroy_ast = true;
284
+
285
+ walk(toplevel, node => {
286
+ if (node instanceof AST_Scope) {
287
+ node.variables = undefined;
288
+ node.enclosed = undefined;
289
+ node.parent_scope = undefined;
290
+ }
291
+ if (node.block_scope) {
292
+ node.block_scope.variables = undefined;
293
+ node.block_scope.enclosed = undefined;
294
+ node.parent_scope = undefined;
295
+ }
296
+ });
297
+ }
298
+
273
299
  if (options.sourceMap) {
300
+ if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
301
+ throw new Error("original source content unavailable");
302
+ }
274
303
  options.format.source_map = await SourceMap({
275
304
  file: options.sourceMap.filename,
276
305
  orig: options.sourceMap.content,
277
- root: options.sourceMap.root
306
+ root: options.sourceMap.root,
307
+ files: options.sourceMap.includeSources ? files : null,
278
308
  });
279
- if (options.sourceMap.includeSources) {
280
- if (files instanceof AST_Toplevel) {
281
- throw new Error("original source content unavailable");
282
- } else for (var name in files) if (HOP(files, name)) {
283
- options.format.source_map.get().setSourceContent(name, files[name]);
284
- }
285
- }
286
309
  }
287
310
  delete options.format.ast;
288
311
  delete options.format.code;
@@ -291,11 +314,21 @@ async function minify(files, options, _fs_module) {
291
314
  toplevel.print(stream);
292
315
  result.code = stream.get();
293
316
  if (options.sourceMap) {
294
- if(options.sourceMap.asObject) {
295
- result.map = options.format.source_map.get().toJSON();
296
- } else {
297
- result.map = options.format.source_map.toString();
298
- }
317
+ Object.defineProperty(result, "map", {
318
+ configurable: true,
319
+ enumerable: true,
320
+ get() {
321
+ const map = options.format.source_map.getEncoded();
322
+ return (result.map = options.sourceMap.asObject ? map : JSON.stringify(map));
323
+ },
324
+ set(value) {
325
+ Object.defineProperty(result, "map", {
326
+ value,
327
+ writable: true,
328
+ });
329
+ }
330
+ });
331
+ result.decoded_map = options.format.source_map.getDecoded();
299
332
  if (options.sourceMap.url == "inline") {
300
333
  var sourceMap = typeof result.map === "object" ? JSON.stringify(result.map) : result.map;
301
334
  result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(sourceMap);
package/lib/output.js CHANGED
@@ -247,6 +247,8 @@ function OutputStream(options) {
247
247
  width : 80,
248
248
  wrap_iife : false,
249
249
  wrap_func_args : true,
250
+
251
+ _destroy_ast : false
250
252
  }, true);
251
253
 
252
254
  if (options.shorthand === undefined)
@@ -796,6 +798,18 @@ function OutputStream(options) {
796
798
  if (OUTPUT.length() > insert) newline_insert = insert;
797
799
  }
798
800
 
801
+ /**
802
+ * When output.option("_destroy_ast") is enabled, destroy the function.
803
+ * Call this after printing it.
804
+ */
805
+ const gc_scope =
806
+ options["_destroy_ast"]
807
+ ? function gc_scope(scope) {
808
+ scope.body.length = 0;
809
+ scope.argnames.length = 0;
810
+ }
811
+ : noop;
812
+
799
813
  var stack = [];
800
814
  return {
801
815
  get : get,
@@ -842,6 +856,7 @@ function OutputStream(options) {
842
856
  with_square : with_square,
843
857
  add_mapping : add_mapping,
844
858
  option : function(opt) { return options[opt]; },
859
+ gc_scope,
845
860
  printed_comments: printed_comments,
846
861
  prepend_comments: readonly ? noop : prepend_comments,
847
862
  append_comments : readonly || comment_filter === return_false ? noop : append_comments,
@@ -1358,6 +1373,7 @@ function OutputStream(options) {
1358
1373
  });
1359
1374
  DEFPRINT(AST_Lambda, function(self, output) {
1360
1375
  self._do_print(output);
1376
+ output.gc_scope(self);
1361
1377
  });
1362
1378
 
1363
1379
  DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
@@ -1437,6 +1453,7 @@ function OutputStream(options) {
1437
1453
  print_braced(self, output);
1438
1454
  }
1439
1455
  if (needs_parens) { output.print(")"); }
1456
+ output.gc_scope(self);
1440
1457
  });
1441
1458
 
1442
1459
  /* -----[ exits ]----- */
package/lib/sourcemap.js CHANGED
@@ -43,45 +43,59 @@
43
43
 
44
44
  "use strict";
45
45
 
46
- import MOZ_SourceMap from "source-map";
47
- import {
48
- defaults,
49
- } from "./utils/index.js";
46
+ import {SourceMapConsumer, SourceMapGenerator} from "@jridgewell/source-map";
47
+ import {defaults, HOP} from "./utils/index.js";
50
48
 
51
- // a small wrapper around fitzgen's source-map library
49
+ // a small wrapper around source-map and @jridgewell/source-map
52
50
  async function SourceMap(options) {
53
51
  options = defaults(options, {
54
52
  file : null,
55
53
  root : null,
56
54
  orig : null,
57
-
58
- orig_line_diff : 0,
59
- dest_line_diff : 0,
55
+ files: {},
60
56
  });
61
57
 
62
58
  var orig_map;
63
- var generator = new MOZ_SourceMap.SourceMapGenerator({
59
+ var generator = new SourceMapGenerator({
64
60
  file : options.file,
65
61
  sourceRoot : options.root
66
62
  });
67
63
 
64
+ let sourcesContent = {__proto__: null};
65
+ let files = options.files;
66
+ for (var name in files) if (HOP(files, name)) {
67
+ sourcesContent[name] = files[name];
68
+ }
68
69
  if (options.orig) {
69
- orig_map = await new MOZ_SourceMap.SourceMapConsumer(options.orig);
70
- orig_map.sources.forEach(function(source) {
71
- var sourceContent = orig_map.sourceContentFor(source, true);
72
- if (sourceContent) {
73
- generator.setSourceContent(source, sourceContent);
74
- }
75
- });
70
+ // We support both @jridgewell/source-map (which has a sync
71
+ // SourceMapConsumer) and source-map (which has an async
72
+ // SourceMapConsumer).
73
+ orig_map = await new SourceMapConsumer(options.orig);
74
+ if (orig_map.sourcesContent) {
75
+ orig_map.sources.forEach(function(source, i) {
76
+ var content = orig_map.sourcesContent[i];
77
+ if (content) {
78
+ sourcesContent[source] = content;
79
+ }
80
+ });
81
+ }
76
82
  }
77
83
 
78
84
  function add(source, gen_line, gen_col, orig_line, orig_col, name) {
85
+ let generatedPos = { line: gen_line, column: gen_col };
86
+
79
87
  if (orig_map) {
80
88
  var info = orig_map.originalPositionFor({
81
89
  line: orig_line,
82
90
  column: orig_col
83
91
  });
84
92
  if (info.source === null) {
93
+ generator.addMapping({
94
+ generated: generatedPos,
95
+ original: null,
96
+ source: null,
97
+ name: null
98
+ });
85
99
  return;
86
100
  }
87
101
  source = info.source;
@@ -90,22 +104,42 @@ async function SourceMap(options) {
90
104
  name = info.name || name;
91
105
  }
92
106
  generator.addMapping({
93
- generated : { line: gen_line + options.dest_line_diff, column: gen_col },
94
- original : { line: orig_line + options.orig_line_diff, column: orig_col },
107
+ generated : generatedPos,
108
+ original : { line: orig_line, column: orig_col },
95
109
  source : source,
96
110
  name : name
97
111
  });
112
+ generator.setSourceContent(source, sourcesContent[source]);
113
+ }
114
+
115
+ function clean(map) {
116
+ const allNull = map.sourcesContent && map.sourcesContent.every(c => c == null);
117
+ if (allNull) delete map.sourcesContent;
118
+ if (map.file === undefined) delete map.file;
119
+ if (map.sourceRoot === undefined) delete map.sourceRoot;
120
+ return map;
121
+ }
122
+
123
+ function getDecoded() {
124
+ if (!generator.toDecodedMap) return null;
125
+ return clean(generator.toDecodedMap());
126
+ }
127
+
128
+ function getEncoded() {
129
+ return clean(generator.toJSON());
130
+ }
131
+
132
+ function destroy() {
133
+ // @jridgewell/source-map's SourceMapConsumer does not need to be
134
+ // manually freed.
135
+ if (orig_map && orig_map.destroy) orig_map.destroy();
98
136
  }
99
137
 
100
138
  return {
101
- add : add,
102
- get : function() { return generator; },
103
- toString : function() { return generator.toString(); },
104
- destroy : function () {
105
- if (orig_map && orig_map.destroy) {
106
- orig_map.destroy();
107
- }
108
- }
139
+ add,
140
+ getDecoded,
141
+ getEncoded,
142
+ destroy,
109
143
  };
110
144
  }
111
145
 
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "homepage": "https://terser.org",
5
5
  "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
6
6
  "license": "BSD-2-Clause",
7
- "version": "5.13.1",
7
+ "version": "5.14.0",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
@@ -18,6 +18,7 @@
18
18
  "exports": {
19
19
  ".": [
20
20
  {
21
+ "types": "./tools/terser.d.ts",
21
22
  "import": "./main.js",
22
23
  "require": "./dist/bundle.min.js"
23
24
  },
@@ -43,9 +44,9 @@
43
44
  "main.js"
44
45
  ],
45
46
  "dependencies": {
47
+ "@jridgewell/source-map": "^0.3.2",
46
48
  "acorn": "^8.5.0",
47
49
  "commander": "^2.20.0",
48
- "source-map": "~0.8.0-beta.0",
49
50
  "source-map-support": "~0.5.20"
50
51
  },
51
52
  "devDependencies": {
@@ -58,7 +59,8 @@
58
59
  "pre-commit": "^1.2.2",
59
60
  "rimraf": "^3.0.2",
60
61
  "rollup": "2.56.3",
61
- "semver": "^7.3.4"
62
+ "semver": "^7.3.4",
63
+ "source-map": "~0.8.0-beta.0"
62
64
  },
63
65
  "scripts": {
64
66
  "test": "node test/compress.js && mocha test/mocha",
package/tools/domprops.js CHANGED
@@ -320,6 +320,7 @@ export var domprops = [
320
320
  "COMMENT_NODE",
321
321
  "COMPARE_REF_TO_TEXTURE",
322
322
  "COMPILE_STATUS",
323
+ "COMPLETION_STATUS_KHR",
323
324
  "COMPRESSED_RGBA_S3TC_DXT1_EXT",
324
325
  "COMPRESSED_RGBA_S3TC_DXT3_EXT",
325
326
  "COMPRESSED_RGBA_S3TC_DXT5_EXT",
package/tools/terser.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  /// <reference lib="es2015" />
2
2
 
3
- import { RawSourceMap } from 'source-map';
3
+ import { SectionedSourceMapInput, EncodedSourceMap, DecodedSourceMap } from '@jridgewell/source-map';
4
4
 
5
5
  export type ECMA = 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020;
6
6
 
7
7
  export interface ParseOptions {
8
8
  bare_returns?: boolean;
9
+ /** @deprecated legacy option. Currently, all supported EcmaScript is valid to parse. */
9
10
  ecma?: ECMA;
10
11
  html5_comments?: boolean;
11
12
  shebang?: boolean;
@@ -192,12 +193,13 @@ export interface MinifyOptions {
192
193
 
193
194
  export interface MinifyOutput {
194
195
  code?: string;
195
- map?: RawSourceMap | string;
196
+ map?: EncodedSourceMap | string;
197
+ decoded_map?: DecodedSourceMap | null;
196
198
  }
197
199
 
198
200
  export interface SourceMapOptions {
199
201
  /** Source map object, 'inline' or source map file content */
200
- content?: RawSourceMap | string;
202
+ content?: SectionedSourceMapInput | string;
201
203
  includeSources?: boolean;
202
204
  filename?: string;
203
205
  root?: string;