terser 5.17.0 → 5.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## v5.17.1
4
+ - Fix evaluating `.length` when the source array might've been mutated
5
+
3
6
  ## v5.17.0
4
7
  - Drop vestigial `= undefined` default argument in IIFE calls (#1366)
5
8
  - Evaluate known arrays' `.length` property when statically determinable
@@ -4515,11 +4515,14 @@ var AST_Destructuring = DEFNODE("Destructuring", "names is_array", function AST_
4515
4515
  },
4516
4516
  all_symbols: function() {
4517
4517
  var out = [];
4518
- this.walk(new TreeWalker(function (node) {
4519
- if (node instanceof AST_Symbol) {
4518
+ walk(this, node => {
4519
+ if (node instanceof AST_SymbolDeclaration) {
4520
4520
  out.push(node);
4521
4521
  }
4522
- }));
4522
+ if (node instanceof AST_Lambda) {
4523
+ return true;
4524
+ }
4525
+ });
4523
4526
  return out;
4524
4527
  }
4525
4528
  });
@@ -5050,6 +5053,13 @@ var AST_VarDef = DEFNODE("VarDef", "name value", function AST_VarDef(props) {
5050
5053
  if (this.value) push(this.value);
5051
5054
  push(this.name);
5052
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
+ }
5053
5063
  });
5054
5064
 
5055
5065
  var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", function AST_NameMapping(props) {
@@ -14496,24 +14506,16 @@ def_eval(AST_PropAccess, function (compressor, depth) {
14496
14506
  return obj.length;
14497
14507
  }
14498
14508
 
14499
- const is_spreadless_array = obj =>
14509
+ const is_spreadless_array =
14500
14510
  obj instanceof AST_Array
14501
14511
  && obj.elements.every(el => !(el instanceof AST_Expansion));
14502
14512
 
14503
14513
  if (
14504
- is_spreadless_array(obj)
14514
+ is_spreadless_array
14505
14515
  && obj.elements.every(el => !el.has_side_effects(compressor))
14506
14516
  ) {
14507
14517
  return obj.elements.length;
14508
14518
  }
14509
-
14510
- let fixed;
14511
- if (
14512
- obj instanceof AST_SymbolRef
14513
- && is_spreadless_array((fixed = obj.definition().fixed_value()))
14514
- ) {
14515
- return fixed.elements.length;
14516
- }
14517
14519
  }
14518
14520
 
14519
14521
  if (compressor.option("unsafe")) {
@@ -16138,12 +16140,31 @@ function is_lhs_read_only(lhs) {
16138
16140
  return false;
16139
16141
  }
16140
16142
 
16141
- // Remove code which we know is unreachable.
16143
+ /** var a = 1 --> var a*/
16144
+ function remove_initializers(var_statement) {
16145
+ var decls = [];
16146
+ var_statement.definitions.forEach(function(def) {
16147
+ if (def.name instanceof AST_SymbolDeclaration) {
16148
+ def.value = null;
16149
+ decls.push(def);
16150
+ } else {
16151
+ def.declarations_as_names().forEach(name => {
16152
+ decls.push(make_node(AST_VarDef, def, {
16153
+ name,
16154
+ value: null
16155
+ }));
16156
+ });
16157
+ }
16158
+ });
16159
+ return decls.length ? make_node(AST_Var, var_statement, { definitions: decls }) : null;
16160
+ }
16161
+
16162
+ /** Called on code which we know is unreachable, to keep elements that affect outside of it. */
16142
16163
  function trim_unreachable_code(compressor, stat, target) {
16143
16164
  walk(stat, node => {
16144
16165
  if (node instanceof AST_Var) {
16145
- node.remove_initializers();
16146
- target.push(node);
16166
+ const no_initializers = remove_initializers(node);
16167
+ if (no_initializers) target.push(no_initializers);
16147
16168
  return true;
16148
16169
  }
16149
16170
  if (
@@ -19373,26 +19394,6 @@ def_optimize(AST_Try, function(self, compressor) {
19373
19394
  return self;
19374
19395
  });
19375
19396
 
19376
- AST_Definitions.DEFMETHOD("remove_initializers", function() {
19377
- var decls = [];
19378
- this.definitions.forEach(function(def) {
19379
- if (def.name instanceof AST_SymbolDeclaration) {
19380
- def.value = null;
19381
- decls.push(def);
19382
- } else {
19383
- walk(def.name, node => {
19384
- if (node instanceof AST_SymbolDeclaration) {
19385
- decls.push(make_node(AST_VarDef, def, {
19386
- name: node,
19387
- value: null
19388
- }));
19389
- }
19390
- });
19391
- }
19392
- });
19393
- this.definitions = decls;
19394
- });
19395
-
19396
19397
  AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
19397
19398
  var reduce_vars = compressor.option("reduce_vars");
19398
19399
  var assignments = [];
package/lib/ast.js CHANGED
@@ -905,11 +905,14 @@ var AST_Destructuring = DEFNODE("Destructuring", "names is_array", function AST_
905
905
  },
906
906
  all_symbols: function() {
907
907
  var out = [];
908
- this.walk(new TreeWalker(function (node) {
909
- if (node instanceof AST_Symbol) {
908
+ walk(this, node => {
909
+ if (node instanceof AST_SymbolDeclaration) {
910
910
  out.push(node);
911
911
  }
912
- }));
912
+ if (node instanceof AST_Lambda) {
913
+ return true;
914
+ }
915
+ });
913
916
  return out;
914
917
  }
915
918
  });
@@ -1440,6 +1443,13 @@ var AST_VarDef = DEFNODE("VarDef", "name value", function AST_VarDef(props) {
1440
1443
  if (this.value) push(this.value);
1441
1444
  push(this.name);
1442
1445
  },
1446
+ declarations_as_names() {
1447
+ if (this.name instanceof AST_SymbolDeclaration) {
1448
+ return [this];
1449
+ } else {
1450
+ return this.name.all_symbols();
1451
+ }
1452
+ }
1443
1453
  });
1444
1454
 
1445
1455
  var AST_NameMapping = DEFNODE("NameMapping", "foreign_name name", function AST_NameMapping(props) {
@@ -359,24 +359,16 @@ def_eval(AST_PropAccess, function (compressor, depth) {
359
359
  return obj.length;
360
360
  }
361
361
 
362
- const is_spreadless_array = obj =>
362
+ const is_spreadless_array =
363
363
  obj instanceof AST_Array
364
364
  && obj.elements.every(el => !(el instanceof AST_Expansion));
365
365
 
366
366
  if (
367
- is_spreadless_array(obj)
367
+ is_spreadless_array
368
368
  && obj.elements.every(el => !el.has_side_effects(compressor))
369
369
  ) {
370
370
  return obj.elements.length;
371
371
  }
372
-
373
- let fixed;
374
- if (
375
- obj instanceof AST_SymbolRef
376
- && is_spreadless_array((fixed = obj.definition().fixed_value()))
377
- ) {
378
- return fixed.elements.length;
379
- }
380
372
  }
381
373
 
382
374
  if (compressor.option("unsafe")) {
@@ -1545,26 +1545,6 @@ def_optimize(AST_Try, function(self, compressor) {
1545
1545
  return self;
1546
1546
  });
1547
1547
 
1548
- AST_Definitions.DEFMETHOD("remove_initializers", function() {
1549
- var decls = [];
1550
- this.definitions.forEach(function(def) {
1551
- if (def.name instanceof AST_SymbolDeclaration) {
1552
- def.value = null;
1553
- decls.push(def);
1554
- } else {
1555
- walk(def.name, node => {
1556
- if (node instanceof AST_SymbolDeclaration) {
1557
- decls.push(make_node(AST_VarDef, def, {
1558
- name: node,
1559
- value: null
1560
- }));
1561
- }
1562
- });
1563
- }
1564
- });
1565
- this.definitions = decls;
1566
- });
1567
-
1568
1548
  AST_Definitions.DEFMETHOD("to_assignments", function(compressor) {
1569
1549
  var reduce_vars = compressor.option("reduce_vars");
1570
1550
  var assignments = [];
@@ -170,12 +170,31 @@ function is_lhs_read_only(lhs) {
170
170
  return false;
171
171
  }
172
172
 
173
- // Remove code which we know is unreachable.
173
+ /** var a = 1 --> var a*/
174
+ function remove_initializers(var_statement) {
175
+ var decls = [];
176
+ var_statement.definitions.forEach(function(def) {
177
+ if (def.name instanceof AST_SymbolDeclaration) {
178
+ def.value = null;
179
+ decls.push(def);
180
+ } else {
181
+ def.declarations_as_names().forEach(name => {
182
+ decls.push(make_node(AST_VarDef, def, {
183
+ name,
184
+ value: null
185
+ }));
186
+ });
187
+ }
188
+ });
189
+ return decls.length ? make_node(AST_Var, var_statement, { definitions: decls }) : null;
190
+ }
191
+
192
+ /** Called on code which we know is unreachable, to keep elements that affect outside of it. */
174
193
  export function trim_unreachable_code(compressor, stat, target) {
175
194
  walk(stat, node => {
176
195
  if (node instanceof AST_Var) {
177
- node.remove_initializers();
178
- target.push(node);
196
+ const no_initializers = remove_initializers(node);
197
+ if (no_initializers) target.push(no_initializers);
179
198
  return true;
180
199
  }
181
200
  if (
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.17.0",
7
+ "version": "5.17.1",
8
8
  "engines": {
9
9
  "node": ">=10"
10
10
  },