terser 5.16.2 → 5.16.4

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/lib/ast.js CHANGED
@@ -111,6 +111,14 @@ class AST_Token {
111
111
  Object.seal(this);
112
112
  }
113
113
 
114
+ // Return a string summary of the token for node.js console.log
115
+ [Symbol.for("nodejs.util.inspect.custom")](_depth, options) {
116
+ const special = str => options.stylize(str, "special");
117
+ const quote = typeof this.value === "string" && this.value.includes("`") ? "'" : "`";
118
+ const value = `${quote}${this.value}${quote}`;
119
+ return `${special("[AST_Token")} ${value} at ${this.line}:${this.col}${special("]")}`;
120
+ }
121
+
114
122
  get nlb() {
115
123
  return has_tok_flag(this, TOK_FLAG_NLB);
116
124
  }
@@ -1257,12 +1265,11 @@ var AST_Case = DEFNODE("Case", "expression", function AST_Case(props) {
1257
1265
 
1258
1266
  /* -----[ EXCEPTIONS ]----- */
1259
1267
 
1260
- var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
1268
+ var AST_Try = DEFNODE("Try", "body bcatch bfinally", function AST_Try(props) {
1261
1269
  if (props) {
1270
+ this.body = props.body;
1262
1271
  this.bcatch = props.bcatch;
1263
1272
  this.bfinally = props.bfinally;
1264
- this.body = props.body;
1265
- this.block_scope = props.block_scope;
1266
1273
  this.start = props.start;
1267
1274
  this.end = props.end;
1268
1275
  }
@@ -1271,12 +1278,13 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
1271
1278
  }, {
1272
1279
  $documentation: "A `try` statement",
1273
1280
  $propdoc: {
1281
+ body: "[AST_TryBlock] the try block",
1274
1282
  bcatch: "[AST_Catch?] the catch block, or null if not present",
1275
1283
  bfinally: "[AST_Finally?] the finally block, or null if not present"
1276
1284
  },
1277
1285
  _walk: function(visitor) {
1278
1286
  return visitor._visit(this, function() {
1279
- walk_body(this, visitor);
1287
+ this.body._walk(visitor);
1280
1288
  if (this.bcatch) this.bcatch._walk(visitor);
1281
1289
  if (this.bfinally) this.bfinally._walk(visitor);
1282
1290
  });
@@ -1284,9 +1292,21 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", function AST_Try(props) {
1284
1292
  _children_backwards(push) {
1285
1293
  if (this.bfinally) push(this.bfinally);
1286
1294
  if (this.bcatch) push(this.bcatch);
1287
- let i = this.body.length;
1288
- while (i--) push(this.body[i]);
1295
+ push(this.body);
1289
1296
  },
1297
+ }, AST_Statement);
1298
+
1299
+ var AST_TryBlock = DEFNODE("TryBlock", null, function AST_TryBlock(props) {
1300
+ if (props) {
1301
+ this.body = props.body;
1302
+ this.block_scope = props.block_scope;
1303
+ this.start = props.start;
1304
+ this.end = props.end;
1305
+ }
1306
+
1307
+ this.flags = 0;
1308
+ }, {
1309
+ $documentation: "The `try` block of a try statement"
1290
1310
  }, AST_Block);
1291
1311
 
1292
1312
  var AST_Catch = DEFNODE("Catch", "argname", function AST_Catch(props) {
@@ -3235,6 +3255,7 @@ export {
3235
3255
  AST_Toplevel,
3236
3256
  AST_True,
3237
3257
  AST_Try,
3258
+ AST_TryBlock,
3238
3259
  AST_Unary,
3239
3260
  AST_UnaryPostfix,
3240
3261
  AST_UnaryPrefix,
@@ -1529,9 +1529,9 @@ def_optimize(AST_Switch, function(self, compressor) {
1529
1529
  });
1530
1530
 
1531
1531
  def_optimize(AST_Try, function(self, compressor) {
1532
- tighten_body(self.body, compressor);
1533
1532
  if (self.bcatch && self.bfinally && self.bfinally.body.every(is_empty)) self.bfinally = null;
1534
- if (compressor.option("dead_code") && self.body.every(is_empty)) {
1533
+
1534
+ if (compressor.option("dead_code") && self.body.body.every(is_empty)) {
1535
1535
  var body = [];
1536
1536
  if (self.bcatch) {
1537
1537
  trim_unreachable_code(compressor, self.bcatch, body);
@@ -2737,16 +2737,21 @@ def_optimize(AST_Assign, function(self, compressor) {
2737
2737
  return self;
2738
2738
 
2739
2739
  function in_try(level, node) {
2740
- var right = self.right;
2741
- self.right = make_node(AST_Null, right);
2742
- var may_throw = node.may_throw(compressor);
2743
- self.right = right;
2744
- var scope = self.left.definition().scope;
2740
+ function may_assignment_throw() {
2741
+ const right = self.right;
2742
+ self.right = make_node(AST_Null, right);
2743
+ const may_throw = node.may_throw(compressor);
2744
+ self.right = right;
2745
+
2746
+ return may_throw;
2747
+ }
2748
+
2749
+ var stop_at = self.left.definition().scope.get_defun_scope();
2745
2750
  var parent;
2746
- while ((parent = compressor.parent(level++)) !== scope) {
2751
+ while ((parent = compressor.parent(level++)) !== stop_at) {
2747
2752
  if (parent instanceof AST_Try) {
2748
2753
  if (parent.bfinally) return true;
2749
- if (may_throw && parent.bcatch) return true;
2754
+ if (parent.bcatch && may_assignment_throw()) return true;
2750
2755
  }
2751
2756
  }
2752
2757
  }
@@ -2759,7 +2764,13 @@ def_optimize(AST_DefaultAssign, function(self, compressor) {
2759
2764
  var evaluateRight = self.right.evaluate(compressor);
2760
2765
 
2761
2766
  // `[x = undefined] = foo` ---> `[x] = foo`
2762
- if (evaluateRight === undefined) {
2767
+ // `(arg = undefined) => ...` ---> `(arg) => ...` (unless `keep_fargs`)
2768
+ if (
2769
+ evaluateRight === undefined &&
2770
+ (compressor.parent() instanceof AST_Lambda
2771
+ ? compressor.option("keep_fargs") === false
2772
+ : true)
2773
+ ) {
2763
2774
  self = self.left;
2764
2775
  } else if (evaluateRight !== self.right) {
2765
2776
  evaluateRight = make_node_from_constant(evaluateRight, self.right);
@@ -300,7 +300,7 @@ export function is_nullish(node, compressor) {
300
300
  || any(this.body, compressor);
301
301
  });
302
302
  def_has_side_effects(AST_Try, function(compressor) {
303
- return any(this.body, compressor)
303
+ return this.body.has_side_effects(compressor)
304
304
  || this.bcatch && this.bcatch.has_side_effects(compressor)
305
305
  || this.bfinally && this.bfinally.has_side_effects(compressor);
306
306
  });
@@ -529,7 +529,7 @@ export function is_nullish(node, compressor) {
529
529
  });
530
530
  def_may_throw(AST_SymbolClassProperty, return_false);
531
531
  def_may_throw(AST_Try, function(compressor) {
532
- return this.bcatch ? this.bcatch.may_throw(compressor) : any(this.body, compressor)
532
+ return this.bcatch ? this.bcatch.may_throw(compressor) : this.body.may_throw(compressor)
533
533
  || this.bfinally && this.bfinally.may_throw(compressor);
534
534
  });
535
535
  def_may_throw(AST_Unary, function(compressor) {
@@ -92,7 +92,6 @@ import "../size.js";
92
92
  import "./evaluate.js";
93
93
  import "./drop-side-effect-free.js";
94
94
  import "./reduce-vars.js";
95
- import { is_lhs } from "./inference.js";
96
95
  import {
97
96
  SQUEEZED,
98
97
  INLINED,
@@ -114,6 +113,13 @@ import {
114
113
  retain_top_func,
115
114
  } from "./common.js";
116
115
 
116
+ /**
117
+ * Module that contains the inlining logic.
118
+ *
119
+ * @module
120
+ *
121
+ * The stars of the show are `inline_into_symbolref` and `inline_into_call`.
122
+ */
117
123
 
118
124
  function within_array_or_object_literal(compressor) {
119
125
  var node, level = 0;
@@ -144,136 +150,135 @@ function scope_encloses_variables_in_this_scope(scope, pulled_scope) {
144
150
 
145
151
  export function inline_into_symbolref(self, compressor) {
146
152
  const parent = compressor.parent();
147
- if (compressor.option("reduce_vars") && is_lhs(self, parent) !== self) {
148
- const def = self.definition();
149
- const nearest_scope = compressor.find_scope();
150
- if (compressor.top_retain && def.global && compressor.top_retain(def)) {
151
- def.fixed = false;
152
- def.single_use = false;
153
- return self;
154
- }
155
153
 
156
- let fixed = self.fixed_value();
157
- let single_use = def.single_use
158
- && !(parent instanceof AST_Call
159
- && (parent.is_callee_pure(compressor))
160
- || has_annotation(parent, _NOINLINE))
161
- && !(parent instanceof AST_Export
162
- && fixed instanceof AST_Lambda
163
- && fixed.name);
164
-
165
- if (single_use && fixed instanceof AST_Node) {
166
- single_use =
167
- !fixed.has_side_effects(compressor)
168
- && !fixed.may_throw(compressor);
169
- }
154
+ const def = self.definition();
155
+ const nearest_scope = compressor.find_scope();
156
+ if (compressor.top_retain && def.global && compressor.top_retain(def)) {
157
+ def.fixed = false;
158
+ def.single_use = false;
159
+ return self;
160
+ }
170
161
 
171
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
172
- if (retain_top_func(fixed, compressor)) {
173
- single_use = false;
174
- } else if (def.scope !== self.scope
175
- && (def.escaped == 1
176
- || has_flag(fixed, INLINED)
177
- || within_array_or_object_literal(compressor)
178
- || !compressor.option("reduce_funcs"))) {
179
- single_use = false;
180
- } else if (is_recursive_ref(compressor, def)) {
181
- single_use = false;
182
- } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
183
- single_use = fixed.is_constant_expression(self.scope);
184
- if (single_use == "f") {
185
- var scope = self.scope;
186
- do {
187
- if (scope instanceof AST_Defun || is_func_expr(scope)) {
188
- set_flag(scope, INLINED);
189
- }
190
- } while (scope = scope.parent_scope);
191
- }
162
+ let fixed = self.fixed_value();
163
+ let single_use = def.single_use
164
+ && !(parent instanceof AST_Call
165
+ && (parent.is_callee_pure(compressor))
166
+ || has_annotation(parent, _NOINLINE))
167
+ && !(parent instanceof AST_Export
168
+ && fixed instanceof AST_Lambda
169
+ && fixed.name);
170
+
171
+ if (single_use && fixed instanceof AST_Node) {
172
+ single_use =
173
+ !fixed.has_side_effects(compressor)
174
+ && !fixed.may_throw(compressor);
175
+ }
176
+
177
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
178
+ if (retain_top_func(fixed, compressor)) {
179
+ single_use = false;
180
+ } else if (def.scope !== self.scope
181
+ && (def.escaped == 1
182
+ || has_flag(fixed, INLINED)
183
+ || within_array_or_object_literal(compressor)
184
+ || !compressor.option("reduce_funcs"))) {
185
+ single_use = false;
186
+ } else if (is_recursive_ref(compressor, def)) {
187
+ single_use = false;
188
+ } else if (def.scope !== self.scope || def.orig[0] instanceof AST_SymbolFunarg) {
189
+ single_use = fixed.is_constant_expression(self.scope);
190
+ if (single_use == "f") {
191
+ var scope = self.scope;
192
+ do {
193
+ if (scope instanceof AST_Defun || is_func_expr(scope)) {
194
+ set_flag(scope, INLINED);
195
+ }
196
+ } while (scope = scope.parent_scope);
192
197
  }
193
198
  }
199
+ }
194
200
 
195
- if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
196
- single_use =
197
- def.scope === self.scope
198
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
199
- || parent instanceof AST_Call
200
- && parent.expression === self
201
- && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
202
- && !(fixed.name && fixed.name.definition().recursive_refs > 0);
203
- }
201
+ if (single_use && (fixed instanceof AST_Lambda || fixed instanceof AST_Class)) {
202
+ single_use =
203
+ def.scope === self.scope
204
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
205
+ || parent instanceof AST_Call
206
+ && parent.expression === self
207
+ && !scope_encloses_variables_in_this_scope(nearest_scope, fixed)
208
+ && !(fixed.name && fixed.name.definition().recursive_refs > 0);
209
+ }
204
210
 
205
- if (single_use && fixed) {
206
- if (fixed instanceof AST_DefClass) {
207
- set_flag(fixed, SQUEEZED);
208
- fixed = make_node(AST_ClassExpression, fixed, fixed);
209
- }
210
- if (fixed instanceof AST_Defun) {
211
- set_flag(fixed, SQUEEZED);
212
- fixed = make_node(AST_Function, fixed, fixed);
211
+ if (single_use && fixed) {
212
+ if (fixed instanceof AST_DefClass) {
213
+ set_flag(fixed, SQUEEZED);
214
+ fixed = make_node(AST_ClassExpression, fixed, fixed);
215
+ }
216
+ if (fixed instanceof AST_Defun) {
217
+ set_flag(fixed, SQUEEZED);
218
+ fixed = make_node(AST_Function, fixed, fixed);
219
+ }
220
+ if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
221
+ const defun_def = fixed.name.definition();
222
+ let lambda_def = fixed.variables.get(fixed.name.name);
223
+ let name = lambda_def && lambda_def.orig[0];
224
+ if (!(name instanceof AST_SymbolLambda)) {
225
+ name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
226
+ name.scope = fixed;
227
+ fixed.name = name;
228
+ lambda_def = fixed.def_function(name);
213
229
  }
214
- if (def.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) {
215
- const defun_def = fixed.name.definition();
216
- let lambda_def = fixed.variables.get(fixed.name.name);
217
- let name = lambda_def && lambda_def.orig[0];
218
- if (!(name instanceof AST_SymbolLambda)) {
219
- name = make_node(AST_SymbolLambda, fixed.name, fixed.name);
220
- name.scope = fixed;
221
- fixed.name = name;
222
- lambda_def = fixed.def_function(name);
230
+ walk(fixed, node => {
231
+ if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
232
+ node.thedef = lambda_def;
233
+ lambda_def.references.push(node);
223
234
  }
224
- walk(fixed, node => {
225
- if (node instanceof AST_SymbolRef && node.definition() === defun_def) {
226
- node.thedef = lambda_def;
227
- lambda_def.references.push(node);
228
- }
229
- });
235
+ });
236
+ }
237
+ if (
238
+ (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
239
+ && fixed.parent_scope !== nearest_scope
240
+ ) {
241
+ fixed = fixed.clone(true, compressor.get_toplevel());
242
+
243
+ nearest_scope.add_child_scope(fixed);
244
+ }
245
+ return fixed.optimize(compressor);
246
+ }
247
+
248
+ // multiple uses
249
+ if (fixed) {
250
+ let replace;
251
+
252
+ if (fixed instanceof AST_This) {
253
+ if (!(def.orig[0] instanceof AST_SymbolFunarg)
254
+ && def.references.every((ref) =>
255
+ def.scope === ref.scope
256
+ )) {
257
+ replace = fixed;
230
258
  }
259
+ } else {
260
+ var ev = fixed.evaluate(compressor);
231
261
  if (
232
- (fixed instanceof AST_Lambda || fixed instanceof AST_Class)
233
- && fixed.parent_scope !== nearest_scope
262
+ ev !== fixed
263
+ && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
234
264
  ) {
235
- fixed = fixed.clone(true, compressor.get_toplevel());
236
-
237
- nearest_scope.add_child_scope(fixed);
265
+ replace = make_node_from_constant(ev, fixed);
238
266
  }
239
- return fixed.optimize(compressor);
240
267
  }
241
268
 
242
- // multiple uses
243
- if (fixed) {
244
- let replace;
269
+ if (replace) {
270
+ const name_length = self.size(compressor);
271
+ const replace_size = replace.size(compressor);
245
272
 
246
- if (fixed instanceof AST_This) {
247
- if (!(def.orig[0] instanceof AST_SymbolFunarg)
248
- && def.references.every((ref) =>
249
- def.scope === ref.scope
250
- )) {
251
- replace = fixed;
252
- }
253
- } else {
254
- var ev = fixed.evaluate(compressor);
255
- if (
256
- ev !== fixed
257
- && (compressor.option("unsafe_regexp") || !(ev instanceof RegExp))
258
- ) {
259
- replace = make_node_from_constant(ev, fixed);
260
- }
273
+ let overhead = 0;
274
+ if (compressor.option("unused") && !compressor.exposed(def)) {
275
+ overhead =
276
+ (name_length + 2 + replace_size) /
277
+ (def.references.length - def.assignments);
261
278
  }
262
279
 
263
- if (replace) {
264
- const name_length = self.size(compressor);
265
- const replace_size = replace.size(compressor);
266
-
267
- let overhead = 0;
268
- if (compressor.option("unused") && !compressor.exposed(def)) {
269
- overhead =
270
- (name_length + 2 + replace_size) /
271
- (def.references.length - def.assignments);
272
- }
273
-
274
- if (replace_size <= name_length + overhead) {
275
- return replace;
276
- }
280
+ if (replace_size <= name_length + overhead) {
281
+ return replace;
277
282
  }
278
283
  }
279
284
  }
@@ -103,15 +103,17 @@ import { lazy_op, is_modified } from "./inference.js";
103
103
  import { INLINED, clear_flag } from "./compressor-flags.js";
104
104
  import { read_property, has_break_or_continue, is_recursive_ref } from "./common.js";
105
105
 
106
- // Define the method AST_Node#reduce_vars, which goes through the AST in
107
- // execution order to perform basic flow analysis
108
-
106
+ /**
107
+ * Define the method AST_Node#reduce_vars, which goes through the AST in
108
+ * execution order to perform basic flow analysis
109
+ */
109
110
  function def_reduce_vars(node, func) {
110
111
  node.DEFMETHOD("reduce_vars", func);
111
112
  }
112
113
 
113
114
  def_reduce_vars(AST_Node, noop);
114
115
 
116
+ /** Clear definition properties */
115
117
  function reset_def(compressor, def) {
116
118
  def.assignments = 0;
117
119
  def.chained = false;
@@ -120,7 +122,10 @@ function reset_def(compressor, def) {
120
122
  def.recursive_refs = 0;
121
123
  def.references = [];
122
124
  def.single_use = undefined;
123
- if (def.scope.pinned()) {
125
+ if (
126
+ def.scope.pinned()
127
+ || (def.orig[0] instanceof AST_SymbolFunarg && def.scope.uses_arguments)
128
+ ) {
124
129
  def.fixed = false;
125
130
  } else if (def.orig[0] instanceof AST_SymbolConst || !compressor.exposed(def)) {
126
131
  def.fixed = def.init;
@@ -442,15 +447,23 @@ def_reduce_vars(AST_Default, function(tw, descend) {
442
447
 
443
448
  function mark_lambda(tw, descend, compressor) {
444
449
  clear_flag(this, INLINED);
445
- push(tw);
446
- reset_variables(tw, compressor, this);
447
- if (this.uses_arguments) {
448
- descend();
449
- pop(tw);
450
- return;
450
+
451
+ // Sometimes we detach the lambda for safety, and instead of push()
452
+ // we go to an entirely fresh lineage of safe_ids.
453
+ let previous_safe_ids;
454
+ if (this instanceof AST_Defun || this.uses_arguments || this.pinned()) {
455
+ previous_safe_ids = tw.safe_ids;
456
+ tw.safe_ids = Object.create(null);
457
+ } else {
458
+ push(tw);
451
459
  }
460
+
461
+ reset_variables(tw, compressor, this);
462
+
452
463
  var iife;
453
464
  if (!this.name
465
+ && !this.uses_arguments
466
+ && !this.pinned()
454
467
  && (iife = tw.parent()) instanceof AST_Call
455
468
  && iife.expression === this
456
469
  && !iife.args.some(arg => arg instanceof AST_Expansion)
@@ -476,7 +489,13 @@ function mark_lambda(tw, descend, compressor) {
476
489
  });
477
490
  }
478
491
  descend();
479
- pop(tw);
492
+
493
+ if (previous_safe_ids) {
494
+ tw.safe_ids = previous_safe_ids;
495
+ } else {
496
+ pop(tw);
497
+ }
498
+
480
499
  return true;
481
500
  }
482
501
 
@@ -605,7 +624,7 @@ def_reduce_vars(AST_Toplevel, function(tw, descend, compressor) {
605
624
  def_reduce_vars(AST_Try, function(tw, descend, compressor) {
606
625
  reset_block_variables(compressor, this);
607
626
  push(tw);
608
- walk_body(this, tw);
627
+ this.body.walk(tw);
609
628
  pop(tw);
610
629
  if (this.bcatch) {
611
630
  push(tw);
@@ -52,7 +52,6 @@ import {
52
52
  AST_Break,
53
53
  AST_Call,
54
54
  AST_Case,
55
- AST_Catch,
56
55
  AST_Chain,
57
56
  AST_Class,
58
57
  AST_Conditional,
@@ -71,7 +70,6 @@ import {
71
70
  AST_Exit,
72
71
  AST_Expansion,
73
72
  AST_Export,
74
- AST_Finally,
75
73
  AST_For,
76
74
  AST_ForIn,
77
75
  AST_If,
@@ -103,6 +101,7 @@ import {
103
101
  AST_SymbolVar,
104
102
  AST_This,
105
103
  AST_Try,
104
+ AST_TryBlock,
106
105
  AST_Unary,
107
106
  AST_UnaryPostfix,
108
107
  AST_UnaryPrefix,
@@ -234,13 +233,11 @@ export function tighten_body(statements, compressor) {
234
233
  function find_loop_scope_try() {
235
234
  var node = compressor.self(), level = 0, in_loop = false, in_try = false;
236
235
  do {
237
- if (node instanceof AST_Catch || node instanceof AST_Finally) {
238
- level++;
239
- } else if (node instanceof AST_IterationStatement) {
236
+ if (node instanceof AST_IterationStatement) {
240
237
  in_loop = true;
241
238
  } else if (node instanceof AST_Scope) {
242
239
  break;
243
- } else if (node instanceof AST_Try) {
240
+ } else if (node instanceof AST_TryBlock) {
244
241
  in_try = true;
245
242
  }
246
243
  } while (node = compressor.parent(level++));
@@ -284,6 +281,9 @@ export function tighten_body(statements, compressor) {
284
281
  && (node.logical || node.operator != "=" && lhs.equivalent_to(node.left))
285
282
  || node instanceof AST_Await
286
283
  || node instanceof AST_Call && lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression)
284
+ ||
285
+ (node instanceof AST_Call || node instanceof AST_PropAccess)
286
+ && node.optional
287
287
  || node instanceof AST_Debugger
288
288
  || node instanceof AST_Destructuring
289
289
  || node instanceof AST_Expansion
@@ -457,7 +457,11 @@ export function tighten_body(statements, compressor) {
457
457
  var hit = funarg;
458
458
  var abort = false, replaced = 0, can_replace = !args || !hit;
459
459
  if (!can_replace) {
460
- for (var j = compressor.self().argnames.lastIndexOf(candidate.name) + 1; !abort && j < args.length; j++) {
460
+ for (
461
+ let j = compressor.self().argnames.lastIndexOf(candidate.name) + 1;
462
+ !abort && j < args.length;
463
+ j++
464
+ ) {
461
465
  args[j].transform(scanner);
462
466
  }
463
467
  can_replace = true;
@@ -172,7 +172,7 @@ AST_Switch.prototype.shallow_cmp = pass_through;
172
172
  AST_SwitchBranch.prototype.shallow_cmp = pass_through;
173
173
 
174
174
  AST_Try.prototype.shallow_cmp = function(other) {
175
- return (this.bcatch == null ? other.bcatch == null : this.bcatch === other.bcatch) && (this.bfinally == null ? other.bfinally == null : this.bfinally === other.bfinally);
175
+ 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);
176
176
  };
177
177
 
178
178
  AST_Catch.prototype.shallow_cmp = function(other) {
@@ -151,6 +151,7 @@ import {
151
151
  AST_Toplevel,
152
152
  AST_True,
153
153
  AST_Try,
154
+ AST_TryBlock,
154
155
  AST_Unary,
155
156
  AST_UnaryPostfix,
156
157
  AST_UnaryPrefix,
@@ -344,7 +345,7 @@ import { is_basic_identifier_string } from "./parse.js";
344
345
  return new AST_Try({
345
346
  start : my_start_token(M),
346
347
  end : my_end_token(M),
347
- body : from_moz(M.block).body,
348
+ body : new AST_TryBlock(from_moz(M.block)),
348
349
  bcatch : from_moz(handlers[0]),
349
350
  bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
350
351
  });
@@ -1315,7 +1316,7 @@ import { is_basic_identifier_string } from "./parse.js";
1315
1316
  def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
1316
1317
  return {
1317
1318
  type: "TryStatement",
1318
- block: to_moz_block(M),
1319
+ block: to_moz_block(M.body),
1319
1320
  handler: to_moz(M.bcatch),
1320
1321
  guardedHandlers: [],
1321
1322
  finalizer: to_moz(M.bfinally)
package/lib/output.js CHANGED
@@ -143,6 +143,7 @@ import {
143
143
  AST_Throw,
144
144
  AST_Toplevel,
145
145
  AST_Try,
146
+ AST_TryBlock,
146
147
  AST_Unary,
147
148
  AST_UnaryPostfix,
148
149
  AST_UnaryPrefix,
@@ -1620,7 +1621,7 @@ function OutputStream(options) {
1620
1621
  DEFPRINT(AST_Try, function(self, output) {
1621
1622
  output.print("try");
1622
1623
  output.space();
1623
- print_braced(self, output);
1624
+ self.body.print(output);
1624
1625
  if (self.bcatch) {
1625
1626
  output.space();
1626
1627
  self.bcatch.print(output);
@@ -1630,6 +1631,9 @@ function OutputStream(options) {
1630
1631
  self.bfinally.print(output);
1631
1632
  }
1632
1633
  });
1634
+ DEFPRINT(AST_TryBlock, function(self, output) {
1635
+ print_braced(self, output);
1636
+ });
1633
1637
  DEFPRINT(AST_Catch, function(self, output) {
1634
1638
  output.print("catch");
1635
1639
  if (self.argname) {