terser 5.25.0 → 5.27.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,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.27.0
4
+ - Created `minify_sync()` alternative to `minify()` since there's no async code left.
5
+
6
+ ## v5.26.0
7
+ - Do not take the `/*#__PURE__*/` annotation into account when the `side_effects` compress option is off.
8
+ - The `preserve_annotations` option now automatically opts annotation comments in, instead of requiring the `comments` option to be configured for this.
9
+ - Refuse to parse empty parenthesized expressions (`()`)
10
+
3
11
  ## v5.25.0
4
12
  - Regex properties added to reserved property mangler (#1471)
5
13
  - `pure_new` option added to drop unused `new` expressions.
package/README.md CHANGED
@@ -424,7 +424,7 @@ Browser loading is also supported. It exposes a global variable `Terser` contain
424
424
  <script src="https://cdn.jsdelivr.net/npm/terser/dist/bundle.min.js"></script>
425
425
  ```
426
426
 
427
- There is a single async high level function, **`async minify(code, options)`**,
427
+ There is an async high level function, **`async minify(code, options)`**,
428
428
  which will perform all minification [phases](#minify-options) in a configurable
429
429
  manner. By default `minify()` will enable [`compress`](#compress-options)
430
430
  and [`mangle`](#mangle-options). Example:
@@ -435,6 +435,8 @@ console.log(result.code); // minified output: function add(n,d){return n+d}
435
435
  console.log(result.map); // source map
436
436
  ```
437
437
 
438
+ There is also a `minify_sync()` alternative version of it, which returns instantly.
439
+
438
440
  You can `minify` more than one JavaScript file at a time by using an object
439
441
  for the first argument where the keys are file names and the values are source
440
442
  code:
@@ -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
 
@@ -2475,9 +2475,7 @@ function parse($TEXT, options) {
2475
2475
  var ex = async ? new AST_Call({
2476
2476
  expression: async,
2477
2477
  args: exprs
2478
- }) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
2479
- expressions: exprs
2480
- });
2478
+ }) : to_expr_or_sequence(start, exprs);
2481
2479
  if (ex.start) {
2482
2480
  const outer_comments_before = start.comments_before.length;
2483
2481
  outer_comments_before_counts.set(start, outer_comments_before);
@@ -3574,6 +3572,16 @@ function parse($TEXT, options) {
3574
3572
  return left;
3575
3573
  };
3576
3574
 
3575
+ var to_expr_or_sequence = function(start, exprs) {
3576
+ if (exprs.length === 1) {
3577
+ return exprs[0];
3578
+ } else if (exprs.length > 1) {
3579
+ return new AST_Sequence({ start, expressions: exprs, end: peek() });
3580
+ } else {
3581
+ croak("Invalid parenthesized expression");
3582
+ }
3583
+ };
3584
+
3577
3585
  var expression = function(commas, no_in) {
3578
3586
  var start = S.token;
3579
3587
  var exprs = [];
@@ -3583,11 +3591,7 @@ function parse($TEXT, options) {
3583
3591
  next();
3584
3592
  commas = true;
3585
3593
  }
3586
- return exprs.length == 1 ? exprs[0] : new AST_Sequence({
3587
- start : start,
3588
- expressions : exprs,
3589
- end : peek()
3590
- });
3594
+ return to_expr_or_sequence(start, exprs);
3591
3595
  };
3592
3596
 
3593
3597
  function in_loop(cont) {
@@ -8931,7 +8935,7 @@ function left_is_object(node) {
8931
8935
  const CODE_LINE_BREAK = 10;
8932
8936
  const CODE_SPACE = 32;
8933
8937
 
8934
- const r_annotation = /[@#]__(PURE|INLINE|NOINLINE)__/g;
8938
+ const r_annotation = /[@#]__(PURE|INLINE|NOINLINE)__/;
8935
8939
 
8936
8940
  function is_some_comments(comment) {
8937
8941
  // multiline comment
@@ -9083,6 +9087,13 @@ function OutputStream(options) {
9083
9087
  }
9084
9088
  }
9085
9089
 
9090
+ if (options.preserve_annotations) {
9091
+ let prev_comment_filter = comment_filter;
9092
+ comment_filter = function (comment) {
9093
+ return r_annotation.test(comment.value) || prev_comment_filter.apply(this, arguments);
9094
+ };
9095
+ }
9096
+
9086
9097
  var indentation = 0;
9087
9098
  var current_col = 0;
9088
9099
  var current_line = 1;
@@ -14173,7 +14184,10 @@ AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
14173
14184
  if ((this instanceof AST_New) && compressor.option("pure_new")) {
14174
14185
  return true;
14175
14186
  }
14176
- return !!has_annotation(this, _PURE) || !compressor.pure_funcs(this);
14187
+ if (compressor.option("side_effects") && has_annotation(this, _PURE)) {
14188
+ return true;
14189
+ }
14190
+ return !compressor.pure_funcs(this);
14177
14191
  });
14178
14192
 
14179
14193
  // If I call this, is it a pure function?
@@ -21976,7 +21990,7 @@ def_optimize(AST_Destructuring, function(self, compressor) {
21976
21990
  ***********************************************************************/
21977
21991
 
21978
21992
  // a small wrapper around source-map and @jridgewell/source-map
21979
- async function SourceMap(options) {
21993
+ function* SourceMap(options) {
21980
21994
  options = defaults(options, {
21981
21995
  file : null,
21982
21996
  root : null,
@@ -21999,7 +22013,7 @@ async function SourceMap(options) {
21999
22013
  // We support both @jridgewell/source-map (which has a sync
22000
22014
  // SourceMapConsumer) and source-map (which has an async
22001
22015
  // SourceMapConsumer).
22002
- orig_map = await new sourceMap.SourceMapConsumer(options.orig);
22016
+ orig_map = yield new sourceMap.SourceMapConsumer(options.orig);
22003
22017
  if (orig_map.sourcesContent) {
22004
22018
  orig_map.sources.forEach(function(source, i) {
22005
22019
  var content = orig_map.sourcesContent[i];
@@ -30563,7 +30577,7 @@ function log_input(files, options, fs, debug_folder) {
30563
30577
  fs.writeFileSync(log_path, "Options: \n" + options_str + "\n\nInput files:\n\n" + files_str(files) + "\n");
30564
30578
  }
30565
30579
 
30566
- async function minify(files, options, _fs_module) {
30580
+ function* minify_sync_or_async(files, options, _fs_module) {
30567
30581
  if (
30568
30582
  _fs_module
30569
30583
  && typeof process === "object"
@@ -30768,7 +30782,7 @@ async function minify(files, options, _fs_module) {
30768
30782
  if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
30769
30783
  throw new Error("original source content unavailable");
30770
30784
  }
30771
- format_options.source_map = await SourceMap({
30785
+ format_options.source_map = yield* SourceMap({
30772
30786
  file: options.sourceMap.filename,
30773
30787
  orig: options.sourceMap.content,
30774
30788
  root: options.sourceMap.root,
@@ -30830,6 +30844,35 @@ async function minify(files, options, _fs_module) {
30830
30844
  return result;
30831
30845
  }
30832
30846
 
30847
+ async function minify(files, options, _fs_module) {
30848
+ const gen = minify_sync_or_async(files, options, _fs_module);
30849
+
30850
+ let yielded;
30851
+ let val;
30852
+ do {
30853
+ val = gen.next(await yielded);
30854
+ yielded = val.value;
30855
+ } while (!val.done);
30856
+
30857
+ return val.value;
30858
+ }
30859
+
30860
+ function minify_sync(files, options, _fs_module) {
30861
+ const gen = minify_sync_or_async(files, options, _fs_module);
30862
+
30863
+ let yielded;
30864
+ let val;
30865
+ do {
30866
+ if (yielded && typeof yielded.then === "function") {
30867
+ throw new Error("minify_sync cannot be used with the legacy source-map module");
30868
+ }
30869
+ val = gen.next(yielded);
30870
+ yielded = val.value;
30871
+ } while (!val.done);
30872
+
30873
+ return val.value;
30874
+ }
30875
+
30833
30876
  async function run_cli({ program, packageJson, fs, path }) {
30834
30877
  const skip_keys = new Set([ "cname", "parent_scope", "scope", "uses_eval", "uses_with" ]);
30835
30878
  var files = {};
@@ -31320,5 +31363,6 @@ async function infer_options(options) {
31320
31363
  exports._default_options = _default_options;
31321
31364
  exports._run_cli = run_cli;
31322
31365
  exports.minify = minify;
31366
+ exports.minify_sync = minify_sync;
31323
31367
 
31324
- })));
31368
+ }));
@@ -831,7 +831,10 @@ AST_Call.DEFMETHOD("is_callee_pure", function(compressor) {
831
831
  if ((this instanceof AST_New) && compressor.option("pure_new")) {
832
832
  return true;
833
833
  }
834
- return !!has_annotation(this, _PURE) || !compressor.pure_funcs(this);
834
+ if (compressor.option("side_effects") && has_annotation(this, _PURE)) {
835
+ return true;
836
+ }
837
+ return !compressor.pure_funcs(this);
835
838
  });
836
839
 
837
840
  // If I call this, is it a pure function?
package/lib/minify.js CHANGED
@@ -103,7 +103,7 @@ function log_input(files, options, fs, debug_folder) {
103
103
  fs.writeFileSync(log_path, "Options: \n" + options_str + "\n\nInput files:\n\n" + files_str(files) + "\n");
104
104
  }
105
105
 
106
- async function minify(files, options, _fs_module) {
106
+ function* minify_sync_or_async(files, options, _fs_module) {
107
107
  if (
108
108
  _fs_module
109
109
  && typeof process === "object"
@@ -314,7 +314,7 @@ async function minify(files, options, _fs_module) {
314
314
  if (options.sourceMap.includeSources && files instanceof AST_Toplevel) {
315
315
  throw new Error("original source content unavailable");
316
316
  }
317
- format_options.source_map = await SourceMap({
317
+ format_options.source_map = yield* SourceMap({
318
318
  file: options.sourceMap.filename,
319
319
  orig: options.sourceMap.content,
320
320
  root: options.sourceMap.root,
@@ -376,7 +376,37 @@ async function minify(files, options, _fs_module) {
376
376
  return result;
377
377
  }
378
378
 
379
+ async function minify(files, options, _fs_module) {
380
+ const gen = minify_sync_or_async(files, options, _fs_module);
381
+
382
+ let yielded;
383
+ let val;
384
+ do {
385
+ val = gen.next(await yielded);
386
+ yielded = val.value;
387
+ } while (!val.done);
388
+
389
+ return val.value;
390
+ }
391
+
392
+ function minify_sync(files, options, _fs_module) {
393
+ const gen = minify_sync_or_async(files, options, _fs_module);
394
+
395
+ let yielded;
396
+ let val;
397
+ do {
398
+ if (yielded && typeof yielded.then === "function") {
399
+ throw new Error("minify_sync cannot be used with the legacy source-map module");
400
+ }
401
+ val = gen.next(yielded);
402
+ yielded = val.value;
403
+ } while (!val.done);
404
+
405
+ return val.value;
406
+ }
407
+
379
408
  export {
380
409
  minify,
410
+ minify_sync,
381
411
  to_ascii,
382
412
  };
package/lib/output.js CHANGED
@@ -169,7 +169,7 @@ import {
169
169
  const CODE_LINE_BREAK = 10;
170
170
  const CODE_SPACE = 32;
171
171
 
172
- const r_annotation = /[@#]__(PURE|INLINE|NOINLINE)__/g;
172
+ const r_annotation = /[@#]__(PURE|INLINE|NOINLINE)__/;
173
173
 
174
174
  function is_some_comments(comment) {
175
175
  // multiline comment
@@ -321,6 +321,13 @@ function OutputStream(options) {
321
321
  }
322
322
  }
323
323
 
324
+ if (options.preserve_annotations) {
325
+ let prev_comment_filter = comment_filter;
326
+ comment_filter = function (comment) {
327
+ return r_annotation.test(comment.value) || prev_comment_filter.apply(this, arguments);
328
+ };
329
+ }
330
+
324
331
  var indentation = 0;
325
332
  var current_col = 0;
326
333
  var current_line = 1;
package/lib/parse.js CHANGED
@@ -2330,9 +2330,7 @@ function parse($TEXT, options) {
2330
2330
  var ex = async ? new AST_Call({
2331
2331
  expression: async,
2332
2332
  args: exprs
2333
- }) : exprs.length == 1 ? exprs[0] : new AST_Sequence({
2334
- expressions: exprs
2335
- });
2333
+ }) : to_expr_or_sequence(start, exprs);
2336
2334
  if (ex.start) {
2337
2335
  const outer_comments_before = start.comments_before.length;
2338
2336
  outer_comments_before_counts.set(start, outer_comments_before);
@@ -3429,6 +3427,16 @@ function parse($TEXT, options) {
3429
3427
  return left;
3430
3428
  };
3431
3429
 
3430
+ var to_expr_or_sequence = function(start, exprs) {
3431
+ if (exprs.length === 1) {
3432
+ return exprs[0];
3433
+ } else if (exprs.length > 1) {
3434
+ return new AST_Sequence({ start, expressions: exprs, end: peek() });
3435
+ } else {
3436
+ croak("Invalid parenthesized expression");
3437
+ }
3438
+ };
3439
+
3432
3440
  var expression = function(commas, no_in) {
3433
3441
  var start = S.token;
3434
3442
  var exprs = [];
@@ -3438,11 +3446,7 @@ function parse($TEXT, options) {
3438
3446
  next();
3439
3447
  commas = true;
3440
3448
  }
3441
- return exprs.length == 1 ? exprs[0] : new AST_Sequence({
3442
- start : start,
3443
- expressions : exprs,
3444
- end : peek()
3445
- });
3449
+ return to_expr_or_sequence(start, exprs);
3446
3450
  };
3447
3451
 
3448
3452
  function in_loop(cont) {
package/lib/sourcemap.js CHANGED
@@ -47,7 +47,7 @@ import {SourceMapConsumer, SourceMapGenerator} from "@jridgewell/source-map";
47
47
  import {defaults, HOP} from "./utils/index.js";
48
48
 
49
49
  // a small wrapper around source-map and @jridgewell/source-map
50
- async function SourceMap(options) {
50
+ function* SourceMap(options) {
51
51
  options = defaults(options, {
52
52
  file : null,
53
53
  root : null,
@@ -70,7 +70,7 @@ async function SourceMap(options) {
70
70
  // We support both @jridgewell/source-map (which has a sync
71
71
  // SourceMapConsumer) and source-map (which has an async
72
72
  // SourceMapConsumer).
73
- orig_map = await new SourceMapConsumer(options.orig);
73
+ orig_map = yield new SourceMapConsumer(options.orig);
74
74
  if (orig_map.sourcesContent) {
75
75
  orig_map.sources.forEach(function(source, i) {
76
76
  var content = orig_map.sourcesContent[i];
package/main.js CHANGED
@@ -2,7 +2,7 @@ import "./lib/transform.js";
2
2
  import "./lib/mozilla-ast.js";
3
3
  import { minify } from "./lib/minify.js";
4
4
 
5
- export { minify } from "./lib/minify.js";
5
+ export { minify, minify_sync } from "./lib/minify.js";
6
6
  export { run_cli as _run_cli } from "./lib/cli.js";
7
7
 
8
8
  export async function _default_options() {
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.25.0",
7
+ "version": "5.27.0",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },
package/tools/terser.d.ts CHANGED
@@ -213,3 +213,4 @@ export interface SourceMapOptions {
213
213
  }
214
214
 
215
215
  export function minify(files: string | string[] | { [file: string]: string }, options?: MinifyOptions): Promise<MinifyOutput>;
216
+ export function minify_sync(files: string | string[] | { [file: string]: string }, options?: MinifyOptions): MinifyOutput;