terser 3.14.0 → 3.17.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.

Potentially problematic release.


This version of terser might be problematic. Click here for more details.

package/lib/output.js DELETED
@@ -1,1939 +0,0 @@
1
- /***********************************************************************
2
-
3
- A JavaScript tokenizer / parser / beautifier / compressor.
4
- https://github.com/mishoo/UglifyJS2
5
-
6
- -------------------------------- (C) ---------------------------------
7
-
8
- Author: Mihai Bazon
9
- <mihai.bazon@gmail.com>
10
- http://mihai.bazon.net/blog
11
-
12
- Distributed under the BSD license:
13
-
14
- Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
15
-
16
- Redistribution and use in source and binary forms, with or without
17
- modification, are permitted provided that the following conditions
18
- are met:
19
-
20
- * Redistributions of source code must retain the above
21
- copyright notice, this list of conditions and the following
22
- disclaimer.
23
-
24
- * Redistributions in binary form must reproduce the above
25
- copyright notice, this list of conditions and the following
26
- disclaimer in the documentation and/or other materials
27
- provided with the distribution.
28
-
29
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39
- THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
- SUCH DAMAGE.
41
-
42
- ***********************************************************************/
43
-
44
- "use strict";
45
-
46
- var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
47
-
48
- function is_some_comments(comment) {
49
- // multiline comment
50
- return comment.type == "comment2" && /@preserve|@license|@cc_on/i.test(comment.value);
51
- }
52
-
53
- function OutputStream(options) {
54
-
55
- var readonly = !options;
56
- options = defaults(options, {
57
- ascii_only : false,
58
- beautify : false,
59
- braces : false,
60
- comments : false,
61
- ecma : 5,
62
- ie8 : false,
63
- indent_level : 4,
64
- indent_start : 0,
65
- inline_script : true,
66
- keep_quoted_props: false,
67
- max_line_len : false,
68
- preamble : null,
69
- quote_keys : false,
70
- quote_style : 0,
71
- safari10 : false,
72
- semicolons : true,
73
- shebang : true,
74
- shorthand : undefined,
75
- source_map : null,
76
- webkit : false,
77
- width : 80,
78
- wrap_iife : false,
79
- }, true);
80
-
81
- if (options.shorthand === undefined)
82
- options.shorthand = options.ecma > 5;
83
-
84
- // Convert comment option to RegExp if neccessary and set up comments filter
85
- var comment_filter = return_false; // Default case, throw all comments away
86
- if (options.comments) {
87
- var comments = options.comments;
88
- if (typeof options.comments === "string" && /^\/.*\/[a-zA-Z]*$/.test(options.comments)) {
89
- var regex_pos = options.comments.lastIndexOf("/");
90
- comments = new RegExp(
91
- options.comments.substr(1, regex_pos - 1),
92
- options.comments.substr(regex_pos + 1)
93
- );
94
- }
95
- if (comments instanceof RegExp) {
96
- comment_filter = function(comment) {
97
- return comment.type != "comment5" && comments.test(comment.value);
98
- };
99
- } else if (typeof comments === "function") {
100
- comment_filter = function(comment) {
101
- return comment.type != "comment5" && comments(this, comment);
102
- };
103
- } else if (comments === "some") {
104
- comment_filter = is_some_comments;
105
- } else { // NOTE includes "all" option
106
- comment_filter = return_true;
107
- }
108
- }
109
-
110
- var indentation = 0;
111
- var current_col = 0;
112
- var current_line = 1;
113
- var current_pos = 0;
114
- var OUTPUT = "";
115
-
116
- var to_utf8 = options.ascii_only ? function(str, identifier) {
117
- if (options.ecma >= 6) {
118
- str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) {
119
- var code = get_full_char_code(ch, 0).toString(16);
120
- return "\\u{" + code + "}";
121
- });
122
- }
123
- return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) {
124
- var code = ch.charCodeAt(0).toString(16);
125
- if (code.length <= 2 && !identifier) {
126
- while (code.length < 2) code = "0" + code;
127
- return "\\x" + code;
128
- } else {
129
- while (code.length < 4) code = "0" + code;
130
- return "\\u" + code;
131
- }
132
- });
133
- } : function(str) {
134
- var s = "";
135
- for (var i = 0, len = str.length; i < len; i++) {
136
- if (is_surrogate_pair_head(str[i]) && !is_surrogate_pair_tail(str[i + 1])
137
- || is_surrogate_pair_tail(str[i]) && !is_surrogate_pair_head(str[i - 1])) {
138
- s += "\\u" + str.charCodeAt(i).toString(16);
139
- } else {
140
- s += str[i];
141
- }
142
- }
143
- return s;
144
- };
145
-
146
- function make_string(str, quote) {
147
- var dq = 0, sq = 0;
148
- str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
149
- function(s, i) {
150
- switch (s) {
151
- case '"': ++dq; return '"';
152
- case "'": ++sq; return "'";
153
- case "\\": return "\\\\";
154
- case "\n": return "\\n";
155
- case "\r": return "\\r";
156
- case "\t": return "\\t";
157
- case "\b": return "\\b";
158
- case "\f": return "\\f";
159
- case "\x0B": return options.ie8 ? "\\x0B" : "\\v";
160
- case "\u2028": return "\\u2028";
161
- case "\u2029": return "\\u2029";
162
- case "\ufeff": return "\\ufeff";
163
- case "\0":
164
- return /[0-9]/.test(get_full_char(str, i+1)) ? "\\x00" : "\\0";
165
- }
166
- return s;
167
- });
168
- function quote_single() {
169
- return "'" + str.replace(/\x27/g, "\\'") + "'";
170
- }
171
- function quote_double() {
172
- return '"' + str.replace(/\x22/g, '\\"') + '"';
173
- }
174
- function quote_template() {
175
- return "`" + str.replace(/`/g, "\\`") + "`";
176
- }
177
- str = to_utf8(str);
178
- if (quote === "`") return quote_template();
179
- switch (options.quote_style) {
180
- case 1:
181
- return quote_single();
182
- case 2:
183
- return quote_double();
184
- case 3:
185
- return quote == "'" ? quote_single() : quote_double();
186
- default:
187
- return dq > sq ? quote_single() : quote_double();
188
- }
189
- }
190
-
191
- function encode_string(str, quote) {
192
- var ret = make_string(str, quote);
193
- if (options.inline_script) {
194
- ret = ret.replace(/<\x2f(script)([>\/\t\n\f\r ])/gi, "<\\/$1$2");
195
- ret = ret.replace(/\x3c!--/g, "\\x3c!--");
196
- ret = ret.replace(/--\x3e/g, "--\\x3e");
197
- }
198
- return ret;
199
- }
200
-
201
- function make_name(name) {
202
- name = name.toString();
203
- name = to_utf8(name, true);
204
- return name;
205
- }
206
-
207
- function make_indent(back) {
208
- return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
209
- }
210
-
211
- /* -----[ beautification/minification ]----- */
212
-
213
- var has_parens = false;
214
- var might_need_space = false;
215
- var might_need_semicolon = false;
216
- var might_add_newline = 0;
217
- var need_newline_indented = false;
218
- var need_space = false;
219
- var newline_insert = -1;
220
- var last = "";
221
- var mapping_token, mapping_name, mappings = options.source_map && [];
222
-
223
- var do_add_mapping = mappings ? function() {
224
- mappings.forEach(function(mapping) {
225
- try {
226
- options.source_map.add(
227
- mapping.token.file,
228
- mapping.line, mapping.col,
229
- mapping.token.line, mapping.token.col,
230
- !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
231
- );
232
- } catch(ex) {
233
- mapping.token.file != null && AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
234
- file: mapping.token.file,
235
- line: mapping.token.line,
236
- col: mapping.token.col,
237
- cline: mapping.line,
238
- ccol: mapping.col,
239
- name: mapping.name || ""
240
- });
241
- }
242
- });
243
- mappings = [];
244
- } : noop;
245
-
246
- var ensure_line_len = options.max_line_len ? function() {
247
- if (current_col > options.max_line_len) {
248
- if (might_add_newline) {
249
- var left = OUTPUT.slice(0, might_add_newline);
250
- var right = OUTPUT.slice(might_add_newline);
251
- if (mappings) {
252
- var delta = right.length - current_col;
253
- mappings.forEach(function(mapping) {
254
- mapping.line++;
255
- mapping.col += delta;
256
- });
257
- }
258
- OUTPUT = left + "\n" + right;
259
- current_line++;
260
- current_pos++;
261
- current_col = right.length;
262
- }
263
- if (current_col > options.max_line_len) {
264
- AST_Node.warn("Output exceeds {max_line_len} characters", options);
265
- }
266
- }
267
- if (might_add_newline) {
268
- might_add_newline = 0;
269
- do_add_mapping();
270
- }
271
- } : noop;
272
-
273
- var requireSemicolonChars = makePredicate("( [ + * / - , . `");
274
-
275
- function print(str) {
276
- str = String(str);
277
- var ch = get_full_char(str, 0);
278
- var prev = get_full_char(last, last.length - 1);
279
- if (need_newline_indented && ch) {
280
- need_newline_indented = false;
281
- if (ch != "\n") {
282
- print("\n");
283
- indent();
284
- }
285
- }
286
- if (need_space && ch) {
287
- need_space = false;
288
- if (!/[\s;})]/.test(ch)) {
289
- space();
290
- }
291
- }
292
- newline_insert = -1;
293
- var prev = last.charAt(last.length - 1);
294
- if (might_need_semicolon) {
295
- might_need_semicolon = false;
296
-
297
- if (prev == ":" && ch == "}" || (!ch || ";}".indexOf(ch) < 0) && prev != ";") {
298
- if (options.semicolons || requireSemicolonChars(ch)) {
299
- OUTPUT += ";";
300
- current_col++;
301
- current_pos++;
302
- } else {
303
- ensure_line_len();
304
- OUTPUT += "\n";
305
- current_pos++;
306
- current_line++;
307
- current_col = 0;
308
-
309
- if (/^\s+$/.test(str)) {
310
- // reset the semicolon flag, since we didn't print one
311
- // now and might still have to later
312
- might_need_semicolon = true;
313
- }
314
- }
315
-
316
- if (!options.beautify)
317
- might_need_space = false;
318
- }
319
- }
320
-
321
- if (might_need_space) {
322
- if ((is_identifier_char(prev)
323
- && (is_identifier_char(ch) || ch == "\\"))
324
- || (ch == "/" && ch == prev)
325
- || ((ch == "+" || ch == "-") && ch == last)
326
- ) {
327
- OUTPUT += " ";
328
- current_col++;
329
- current_pos++;
330
- }
331
- might_need_space = false;
332
- }
333
-
334
- if (mapping_token) {
335
- mappings.push({
336
- token: mapping_token,
337
- name: mapping_name,
338
- line: current_line,
339
- col: current_col
340
- });
341
- mapping_token = false;
342
- if (!might_add_newline) do_add_mapping();
343
- }
344
-
345
- OUTPUT += str;
346
- has_parens = str[str.length - 1] == "(";
347
- current_pos += str.length;
348
- var a = str.split(/\r?\n/), n = a.length - 1;
349
- current_line += n;
350
- current_col += a[0].length;
351
- if (n > 0) {
352
- ensure_line_len();
353
- current_col = a[n].length;
354
- }
355
- last = str;
356
- }
357
-
358
- var star = function() {
359
- print("*");
360
- };
361
-
362
- var space = options.beautify ? function() {
363
- print(" ");
364
- } : function() {
365
- might_need_space = true;
366
- };
367
-
368
- var indent = options.beautify ? function(half) {
369
- if (options.beautify) {
370
- print(make_indent(half ? 0.5 : 0));
371
- }
372
- } : noop;
373
-
374
- var with_indent = options.beautify ? function(col, cont) {
375
- if (col === true) col = next_indent();
376
- var save_indentation = indentation;
377
- indentation = col;
378
- var ret = cont();
379
- indentation = save_indentation;
380
- return ret;
381
- } : function(col, cont) { return cont(); };
382
-
383
- var newline = options.beautify ? function() {
384
- if (newline_insert < 0) return print("\n");
385
- if (OUTPUT[newline_insert] != "\n") {
386
- OUTPUT = OUTPUT.slice(0, newline_insert) + "\n" + OUTPUT.slice(newline_insert);
387
- current_pos++;
388
- current_line++;
389
- }
390
- newline_insert++;
391
- } : options.max_line_len ? function() {
392
- ensure_line_len();
393
- might_add_newline = OUTPUT.length;
394
- } : noop;
395
-
396
- var semicolon = options.beautify ? function() {
397
- print(";");
398
- } : function() {
399
- might_need_semicolon = true;
400
- };
401
-
402
- function force_semicolon() {
403
- might_need_semicolon = false;
404
- print(";");
405
- }
406
-
407
- function next_indent() {
408
- return indentation + options.indent_level;
409
- }
410
-
411
- function with_block(cont) {
412
- var ret;
413
- print("{");
414
- newline();
415
- with_indent(next_indent(), function() {
416
- ret = cont();
417
- });
418
- indent();
419
- print("}");
420
- return ret;
421
- }
422
-
423
- function with_parens(cont) {
424
- print("(");
425
- //XXX: still nice to have that for argument lists
426
- //var ret = with_indent(current_col, cont);
427
- var ret = cont();
428
- print(")");
429
- return ret;
430
- }
431
-
432
- function with_square(cont) {
433
- print("[");
434
- //var ret = with_indent(current_col, cont);
435
- var ret = cont();
436
- print("]");
437
- return ret;
438
- }
439
-
440
- function comma() {
441
- print(",");
442
- space();
443
- }
444
-
445
- function colon() {
446
- print(":");
447
- space();
448
- }
449
-
450
- var add_mapping = mappings ? function(token, name) {
451
- mapping_token = token;
452
- mapping_name = name;
453
- } : noop;
454
-
455
- function get() {
456
- if (might_add_newline) {
457
- ensure_line_len();
458
- }
459
- return OUTPUT;
460
- }
461
-
462
- function has_nlb() {
463
- var index = OUTPUT.lastIndexOf("\n");
464
- return /^ *$/.test(OUTPUT.slice(index + 1));
465
- }
466
-
467
- function prepend_comments(node) {
468
- var self = this;
469
- var start = node.start;
470
- if (!start) return;
471
- if (start.comments_before && start.comments_before._dumped === self) return;
472
- var comments = start.comments_before;
473
- if (!comments) {
474
- comments = start.comments_before = [];
475
- }
476
- comments._dumped = self;
477
-
478
- if (node instanceof AST_Exit && node.value) {
479
- var tw = new TreeWalker(function(node) {
480
- var parent = tw.parent();
481
- if (parent instanceof AST_Exit
482
- || parent instanceof AST_Binary && parent.left === node
483
- || parent.TYPE == "Call" && parent.expression === node
484
- || parent instanceof AST_Conditional && parent.condition === node
485
- || parent instanceof AST_Dot && parent.expression === node
486
- || parent instanceof AST_Sequence && parent.expressions[0] === node
487
- || parent instanceof AST_Sub && parent.expression === node
488
- || parent instanceof AST_UnaryPostfix) {
489
- if (!node.start) return;
490
- var text = node.start.comments_before;
491
- if (text && text._dumped !== self) {
492
- text._dumped = self;
493
- comments = comments.concat(text);
494
- }
495
- } else {
496
- return true;
497
- }
498
- });
499
- tw.push(node);
500
- node.value.walk(tw);
501
- }
502
-
503
- if (current_pos == 0) {
504
- if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
505
- print("#!" + comments.shift().value + "\n");
506
- indent();
507
- }
508
- var preamble = options.preamble;
509
- if (preamble) {
510
- print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
511
- }
512
- }
513
-
514
- comments = comments.filter(comment_filter, node);
515
- if (comments.length == 0) return;
516
- var last_nlb = has_nlb();
517
- comments.forEach(function(c, i) {
518
- if (!last_nlb) {
519
- if (c.nlb) {
520
- print("\n");
521
- indent();
522
- last_nlb = true;
523
- } else if (i > 0) {
524
- space();
525
- }
526
- }
527
- if (/comment[134]/.test(c.type)) {
528
- print("//" + c.value.replace(/[@#]__PURE__/g, " ") + "\n");
529
- indent();
530
- last_nlb = true;
531
- } else if (c.type == "comment2") {
532
- print("/*" + c.value.replace(/[@#]__PURE__/g, " ") + "*/");
533
- last_nlb = false;
534
- }
535
- });
536
- if (!last_nlb) {
537
- if (start.nlb) {
538
- print("\n");
539
- indent();
540
- } else {
541
- space();
542
- }
543
- }
544
- }
545
-
546
- function append_comments(node, tail) {
547
- var self = this;
548
- var token = node.end;
549
- if (!token) return;
550
- var comments = token[tail ? "comments_before" : "comments_after"];
551
- if (!comments || comments._dumped === self) return;
552
- if (!(node instanceof AST_Statement || all(comments, function(c) {
553
- return !/comment[134]/.test(c.type);
554
- }))) return;
555
- comments._dumped = self;
556
- var insert = OUTPUT.length;
557
- comments.filter(comment_filter, node).forEach(function(c, i) {
558
- need_space = false;
559
- if (need_newline_indented) {
560
- print("\n");
561
- indent();
562
- need_newline_indented = false;
563
- } else if (c.nlb && (i > 0 || !has_nlb())) {
564
- print("\n");
565
- indent();
566
- } else if (i > 0 || !tail) {
567
- space();
568
- }
569
- if (/comment[134]/.test(c.type)) {
570
- print("//" + c.value.replace(/[@#]__PURE__/g, " "));
571
- need_newline_indented = true;
572
- } else if (c.type == "comment2") {
573
- print("/*" + c.value.replace(/[@#]__PURE__/g, " ") + "*/");
574
- need_space = true;
575
- }
576
- });
577
- if (OUTPUT.length > insert) newline_insert = insert;
578
- }
579
-
580
- var stack = [];
581
- return {
582
- get : get,
583
- toString : get,
584
- indent : indent,
585
- indentation : function() { return indentation; },
586
- current_width : function() { return current_col - indentation; },
587
- should_break : function() { return options.width && this.current_width() >= options.width; },
588
- has_parens : function() { return has_parens; },
589
- newline : newline,
590
- print : print,
591
- star : star,
592
- space : space,
593
- comma : comma,
594
- colon : colon,
595
- last : function() { return last; },
596
- semicolon : semicolon,
597
- force_semicolon : force_semicolon,
598
- to_utf8 : to_utf8,
599
- print_name : function(name) { print(make_name(name)); },
600
- print_string : function(str, quote, escape_directive) {
601
- var encoded = encode_string(str, quote);
602
- if (escape_directive === true && encoded.indexOf("\\") === -1) {
603
- // Insert semicolons to break directive prologue
604
- if (!EXPECT_DIRECTIVE.test(OUTPUT)) {
605
- force_semicolon();
606
- }
607
- force_semicolon();
608
- }
609
- print(encoded);
610
- },
611
- print_template_string_chars: function(str) {
612
- var encoded = encode_string(str, "`").replace(/\${/g, "\\${");
613
- return print(encoded.substr(1, encoded.length - 2));
614
- },
615
- encode_string : encode_string,
616
- next_indent : next_indent,
617
- with_indent : with_indent,
618
- with_block : with_block,
619
- with_parens : with_parens,
620
- with_square : with_square,
621
- add_mapping : add_mapping,
622
- option : function(opt) { return options[opt]; },
623
- prepend_comments: readonly ? noop : prepend_comments,
624
- append_comments : readonly || comment_filter === return_false ? noop : append_comments,
625
- line : function() { return current_line; },
626
- col : function() { return current_col; },
627
- pos : function() { return current_pos; },
628
- push_node : function(node) { stack.push(node); },
629
- pop_node : function() { return stack.pop(); },
630
- parent : function(n) {
631
- return stack[stack.length - 2 - (n || 0)];
632
- }
633
- };
634
-
635
- }
636
-
637
- /* -----[ code generators ]----- */
638
-
639
- (function() {
640
-
641
- /* -----[ utils ]----- */
642
-
643
- function DEFPRINT(nodetype, generator) {
644
- nodetype.DEFMETHOD("_codegen", generator);
645
- }
646
-
647
- var in_directive = false;
648
- var active_scope = null;
649
- var use_asm = null;
650
-
651
- AST_Node.DEFMETHOD("print", function(stream, force_parens) {
652
- var self = this, generator = self._codegen;
653
- if (self instanceof AST_Scope) {
654
- active_scope = self;
655
- } else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
656
- use_asm = active_scope;
657
- }
658
- function doit() {
659
- stream.prepend_comments(self);
660
- self.add_source_map(stream);
661
- generator(self, stream);
662
- stream.append_comments(self);
663
- }
664
- stream.push_node(self);
665
- if (force_parens || self.needs_parens(stream)) {
666
- stream.with_parens(doit);
667
- } else {
668
- doit();
669
- }
670
- stream.pop_node();
671
- if (self === use_asm) {
672
- use_asm = null;
673
- }
674
- });
675
- AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
676
-
677
- AST_Node.DEFMETHOD("print_to_string", function(options) {
678
- var s = OutputStream(options);
679
- this.print(s);
680
- return s.get();
681
- });
682
-
683
- /* -----[ PARENTHESES ]----- */
684
-
685
- function PARENS(nodetype, func) {
686
- if (Array.isArray(nodetype)) {
687
- nodetype.forEach(function(nodetype) {
688
- PARENS(nodetype, func);
689
- });
690
- } else {
691
- nodetype.DEFMETHOD("needs_parens", func);
692
- }
693
- }
694
-
695
- PARENS(AST_Node, return_false);
696
-
697
- // a function expression needs parens around it when it's provably
698
- // the first token to appear in a statement.
699
- PARENS(AST_Function, function(output) {
700
- if (!output.has_parens() && first_in_statement(output)) {
701
- return true;
702
- }
703
-
704
- if (output.option("webkit")) {
705
- var p = output.parent();
706
- if (p instanceof AST_PropAccess && p.expression === this) {
707
- return true;
708
- }
709
- }
710
-
711
- if (output.option("wrap_iife")) {
712
- var p = output.parent();
713
- return p instanceof AST_Call && p.expression === this;
714
- }
715
-
716
- return false;
717
- });
718
-
719
- PARENS(AST_Arrow, function(output) {
720
- var p = output.parent();
721
- return p instanceof AST_PropAccess && p.expression === this;
722
- });
723
-
724
- // same goes for an object literal, because otherwise it would be
725
- // interpreted as a block of code.
726
- PARENS(AST_Object, function(output) {
727
- return !output.has_parens() && first_in_statement(output);
728
- });
729
-
730
- PARENS(AST_ClassExpression, first_in_statement);
731
-
732
- PARENS(AST_Unary, function(output) {
733
- var p = output.parent();
734
- return p instanceof AST_PropAccess && p.expression === this
735
- || p instanceof AST_Call && p.expression === this
736
- || p instanceof AST_Binary
737
- && p.operator === "**"
738
- && this instanceof AST_UnaryPrefix
739
- && p.left === this
740
- && this.operator !== "++"
741
- && this.operator !== "--";
742
- });
743
-
744
- PARENS(AST_Await, function(output) {
745
- var p = output.parent();
746
- return p instanceof AST_PropAccess && p.expression === this
747
- || p instanceof AST_Call && p.expression === this
748
- || output.option("safari10") && p instanceof AST_UnaryPrefix;
749
- });
750
-
751
- PARENS(AST_Sequence, function(output) {
752
- var p = output.parent();
753
- return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)
754
- || p instanceof AST_Unary // !(foo, bar, baz)
755
- || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8
756
- || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4
757
- || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
758
- || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
759
- || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2
760
- || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
761
- * ==> 20 (side effect, set a := 10 and b := 20) */
762
- || p instanceof AST_Arrow // x => (x, x)
763
- || p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
764
- || p instanceof AST_Expansion // [...(a, b)]
765
- || p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
766
- || p instanceof AST_Yield // yield (foo, bar)
767
- || p instanceof AST_Export // export default (foo, bar)
768
- ;
769
- });
770
-
771
- PARENS(AST_Binary, function(output) {
772
- var p = output.parent();
773
- // (foo && bar)()
774
- if (p instanceof AST_Call && p.expression === this)
775
- return true;
776
- // typeof (foo && bar)
777
- if (p instanceof AST_Unary)
778
- return true;
779
- // (foo && bar)["prop"], (foo && bar).prop
780
- if (p instanceof AST_PropAccess && p.expression === this)
781
- return true;
782
- // this deals with precedence: 3 * (2 + 1)
783
- if (p instanceof AST_Binary) {
784
- var po = p.operator, pp = PRECEDENCE[po];
785
- var so = this.operator, sp = PRECEDENCE[so];
786
- if (pp > sp
787
- || (pp == sp
788
- && (this === p.right || po == "**"))) {
789
- return true;
790
- }
791
- }
792
- });
793
-
794
- PARENS(AST_Yield, function(output) {
795
- var p = output.parent();
796
- // (yield 1) + (yield 2)
797
- // a = yield 3
798
- if (p instanceof AST_Binary && p.operator !== "=")
799
- return true;
800
- // (yield 1)()
801
- // new (yield 1)()
802
- if (p instanceof AST_Call && p.expression === this)
803
- return true;
804
- // (yield 1) ? yield 2 : yield 3
805
- if (p instanceof AST_Conditional && p.condition === this)
806
- return true;
807
- // -(yield 4)
808
- if (p instanceof AST_Unary)
809
- return true;
810
- // (yield x).foo
811
- // (yield x)['foo']
812
- if (p instanceof AST_PropAccess && p.expression === this)
813
- return true;
814
- });
815
-
816
- PARENS(AST_PropAccess, function(output) {
817
- var p = output.parent();
818
- if (p instanceof AST_New && p.expression === this) {
819
- // i.e. new (foo.bar().baz)
820
- //
821
- // if there's one call into this subtree, then we need
822
- // parens around it too, otherwise the call will be
823
- // interpreted as passing the arguments to the upper New
824
- // expression.
825
- var parens = false;
826
- this.walk(new TreeWalker(function(node) {
827
- if (parens || node instanceof AST_Scope) return true;
828
- if (node instanceof AST_Call) {
829
- parens = true;
830
- return true;
831
- }
832
- }));
833
- return parens;
834
- }
835
- });
836
-
837
- PARENS(AST_Call, function(output) {
838
- var p = output.parent(), p1;
839
- if (p instanceof AST_New && p.expression === this
840
- || p instanceof AST_Export && p.is_default && this.expression instanceof AST_Function)
841
- return true;
842
-
843
- // workaround for Safari bug.
844
- // https://bugs.webkit.org/show_bug.cgi?id=123506
845
- return this.expression instanceof AST_Function
846
- && p instanceof AST_PropAccess
847
- && p.expression === this
848
- && (p1 = output.parent(1)) instanceof AST_Assign
849
- && p1.left === p;
850
- });
851
-
852
- PARENS(AST_New, function(output) {
853
- var p = output.parent();
854
- if (!need_constructor_parens(this, output)
855
- && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()
856
- || p instanceof AST_Call && p.expression === this)) // (new foo)(bar)
857
- return true;
858
- });
859
-
860
- PARENS(AST_Number, function(output) {
861
- var p = output.parent();
862
- if (p instanceof AST_PropAccess && p.expression === this) {
863
- var value = this.getValue();
864
- if (value < 0 || /^0/.test(make_num(value))) {
865
- return true;
866
- }
867
- }
868
- });
869
-
870
- PARENS([ AST_Assign, AST_Conditional ], function(output) {
871
- var p = output.parent();
872
- // !(a = false) → true
873
- if (p instanceof AST_Unary)
874
- return true;
875
- // 1 + (a = 2) + 3 → 6, side effect setting a = 2
876
- if (p instanceof AST_Binary && !(p instanceof AST_Assign))
877
- return true;
878
- // (a = func)() —or— new (a = Object)()
879
- if (p instanceof AST_Call && p.expression === this)
880
- return true;
881
- // (a = foo) ? bar : baz
882
- if (p instanceof AST_Conditional && p.condition === this)
883
- return true;
884
- // (a = foo)["prop"] —or— (a = foo).prop
885
- if (p instanceof AST_PropAccess && p.expression === this)
886
- return true;
887
- // ({a, b} = {a: 1, b: 2}), a destructuring assignment
888
- if (this instanceof AST_Assign && this.left instanceof AST_Destructuring && this.left.is_array === false)
889
- return true;
890
- });
891
-
892
- /* -----[ PRINTERS ]----- */
893
-
894
- DEFPRINT(AST_Directive, function(self, output) {
895
- output.print_string(self.value, self.quote);
896
- output.semicolon();
897
- });
898
-
899
- DEFPRINT(AST_Expansion, function (self, output) {
900
- output.print("...");
901
- self.expression.print(output);
902
- });
903
-
904
- DEFPRINT(AST_Destructuring, function (self, output) {
905
- output.print(self.is_array ? "[" : "{");
906
- var len = self.names.length;
907
- self.names.forEach(function (name, i) {
908
- if (i > 0) output.comma();
909
- name.print(output);
910
- // If the final element is a hole, we need to make sure it
911
- // doesn't look like a trailing comma, by inserting an actual
912
- // trailing comma.
913
- if (i == len - 1 && name instanceof AST_Hole) output.comma();
914
- });
915
- output.print(self.is_array ? "]" : "}");
916
- });
917
-
918
- DEFPRINT(AST_Debugger, function(self, output) {
919
- output.print("debugger");
920
- output.semicolon();
921
- });
922
-
923
- /* -----[ statements ]----- */
924
-
925
- function display_body(body, is_toplevel, output, allow_directives) {
926
- var last = body.length - 1;
927
- in_directive = allow_directives;
928
- body.forEach(function(stmt, i) {
929
- if (in_directive === true && !(stmt instanceof AST_Directive ||
930
- stmt instanceof AST_EmptyStatement ||
931
- (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String)
932
- )) {
933
- in_directive = false;
934
- }
935
- if (!(stmt instanceof AST_EmptyStatement)) {
936
- output.indent();
937
- stmt.print(output);
938
- if (!(i == last && is_toplevel)) {
939
- output.newline();
940
- if (is_toplevel) output.newline();
941
- }
942
- }
943
- if (in_directive === true &&
944
- stmt instanceof AST_SimpleStatement &&
945
- stmt.body instanceof AST_String
946
- ) {
947
- in_directive = false;
948
- }
949
- });
950
- in_directive = false;
951
- }
952
-
953
- AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
954
- force_statement(this.body, output);
955
- });
956
-
957
- DEFPRINT(AST_Statement, function(self, output) {
958
- self.body.print(output);
959
- output.semicolon();
960
- });
961
- DEFPRINT(AST_Toplevel, function(self, output) {
962
- display_body(self.body, true, output, true);
963
- output.print("");
964
- });
965
- DEFPRINT(AST_LabeledStatement, function(self, output) {
966
- self.label.print(output);
967
- output.colon();
968
- self.body.print(output);
969
- });
970
- DEFPRINT(AST_SimpleStatement, function(self, output) {
971
- self.body.print(output);
972
- output.semicolon();
973
- });
974
- function print_braced_empty(self, output) {
975
- output.print("{");
976
- output.with_indent(output.next_indent(), function() {
977
- output.append_comments(self, true);
978
- });
979
- output.print("}");
980
- }
981
- function print_braced(self, output, allow_directives) {
982
- if (self.body.length > 0) {
983
- output.with_block(function() {
984
- display_body(self.body, false, output, allow_directives);
985
- });
986
- } else print_braced_empty(self, output);
987
- }
988
- DEFPRINT(AST_BlockStatement, function(self, output) {
989
- print_braced(self, output);
990
- });
991
- DEFPRINT(AST_EmptyStatement, function(self, output) {
992
- output.semicolon();
993
- });
994
- DEFPRINT(AST_Do, function(self, output) {
995
- output.print("do");
996
- output.space();
997
- make_block(self.body, output);
998
- output.space();
999
- output.print("while");
1000
- output.space();
1001
- output.with_parens(function() {
1002
- self.condition.print(output);
1003
- });
1004
- output.semicolon();
1005
- });
1006
- DEFPRINT(AST_While, function(self, output) {
1007
- output.print("while");
1008
- output.space();
1009
- output.with_parens(function() {
1010
- self.condition.print(output);
1011
- });
1012
- output.space();
1013
- self._do_print_body(output);
1014
- });
1015
- DEFPRINT(AST_For, function(self, output) {
1016
- output.print("for");
1017
- output.space();
1018
- output.with_parens(function() {
1019
- if (self.init) {
1020
- if (self.init instanceof AST_Definitions) {
1021
- self.init.print(output);
1022
- } else {
1023
- parenthesize_for_noin(self.init, output, true);
1024
- }
1025
- output.print(";");
1026
- output.space();
1027
- } else {
1028
- output.print(";");
1029
- }
1030
- if (self.condition) {
1031
- self.condition.print(output);
1032
- output.print(";");
1033
- output.space();
1034
- } else {
1035
- output.print(";");
1036
- }
1037
- if (self.step) {
1038
- self.step.print(output);
1039
- }
1040
- });
1041
- output.space();
1042
- self._do_print_body(output);
1043
- });
1044
- DEFPRINT(AST_ForIn, function(self, output) {
1045
- output.print("for");
1046
- if (self.await) {
1047
- output.space();
1048
- output.print("await");
1049
- }
1050
- output.space();
1051
- output.with_parens(function() {
1052
- self.init.print(output);
1053
- output.space();
1054
- output.print(self instanceof AST_ForOf ? "of" : "in");
1055
- output.space();
1056
- self.object.print(output);
1057
- });
1058
- output.space();
1059
- self._do_print_body(output);
1060
- });
1061
- DEFPRINT(AST_With, function(self, output) {
1062
- output.print("with");
1063
- output.space();
1064
- output.with_parens(function() {
1065
- self.expression.print(output);
1066
- });
1067
- output.space();
1068
- self._do_print_body(output);
1069
- });
1070
-
1071
- /* -----[ functions ]----- */
1072
- AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
1073
- var self = this;
1074
- if (!nokeyword) {
1075
- if (self.async) {
1076
- output.print("async");
1077
- output.space();
1078
- }
1079
- output.print("function");
1080
- if (self.is_generator) {
1081
- output.star();
1082
- }
1083
- if (self.name) {
1084
- output.space();
1085
- }
1086
- }
1087
- if (self.name instanceof AST_Symbol) {
1088
- self.name.print(output);
1089
- } else if (nokeyword && self.name instanceof AST_Node) {
1090
- output.with_square(function() {
1091
- self.name.print(output); // Computed method name
1092
- });
1093
- }
1094
- output.with_parens(function() {
1095
- self.argnames.forEach(function(arg, i) {
1096
- if (i) output.comma();
1097
- arg.print(output);
1098
- });
1099
- });
1100
- output.space();
1101
- print_braced(self, output, true);
1102
- });
1103
- DEFPRINT(AST_Lambda, function(self, output) {
1104
- self._do_print(output);
1105
- });
1106
-
1107
- DEFPRINT(AST_PrefixedTemplateString, function(self, output) {
1108
- var tag = self.prefix;
1109
- var parenthesize_tag = tag instanceof AST_Arrow
1110
- || tag instanceof AST_Binary
1111
- || tag instanceof AST_Conditional
1112
- || tag instanceof AST_Sequence
1113
- || tag instanceof AST_Unary;
1114
- if (parenthesize_tag) output.print("(");
1115
- self.prefix.print(output);
1116
- if (parenthesize_tag) output.print(")");
1117
- self.template_string.print(output);
1118
- });
1119
- DEFPRINT(AST_TemplateString, function(self, output) {
1120
- var is_tagged = output.parent() instanceof AST_PrefixedTemplateString;
1121
-
1122
- output.print("`");
1123
- for (var i = 0; i < self.segments.length; i++) {
1124
- if (!(self.segments[i] instanceof AST_TemplateSegment)) {
1125
- output.print("${");
1126
- self.segments[i].print(output);
1127
- output.print("}");
1128
- } else if (is_tagged) {
1129
- output.print(self.segments[i].raw);
1130
- } else {
1131
- output.print_template_string_chars(self.segments[i].value);
1132
- }
1133
- }
1134
- output.print("`");
1135
- });
1136
-
1137
- AST_Arrow.DEFMETHOD("_do_print", function(output) {
1138
- var self = this;
1139
- var parent = output.parent();
1140
- var needs_parens = parent instanceof AST_Binary ||
1141
- parent instanceof AST_Unary ||
1142
- (parent instanceof AST_Call && self === parent.expression);
1143
- if (needs_parens) { output.print("("); }
1144
- if (self.async) {
1145
- output.print("async");
1146
- output.space();
1147
- }
1148
- if (self.argnames.length === 1 && self.argnames[0] instanceof AST_Symbol) {
1149
- self.argnames[0].print(output);
1150
- } else {
1151
- output.with_parens(function() {
1152
- self.argnames.forEach(function(arg, i) {
1153
- if (i) output.comma();
1154
- arg.print(output);
1155
- });
1156
- });
1157
- }
1158
- output.space();
1159
- output.print("=>");
1160
- output.space();
1161
- if (self.body instanceof AST_Node) {
1162
- self.body.print(output);
1163
- } else {
1164
- print_braced(self, output);
1165
- }
1166
- if (needs_parens) { output.print(")"); }
1167
- });
1168
-
1169
- /* -----[ exits ]----- */
1170
- AST_Exit.DEFMETHOD("_do_print", function(output, kind) {
1171
- output.print(kind);
1172
- if (this.value) {
1173
- output.space();
1174
- this.value.print(output);
1175
- }
1176
- output.semicolon();
1177
- });
1178
- DEFPRINT(AST_Return, function(self, output) {
1179
- self._do_print(output, "return");
1180
- });
1181
- DEFPRINT(AST_Throw, function(self, output) {
1182
- self._do_print(output, "throw");
1183
- });
1184
-
1185
- /* -----[ yield ]----- */
1186
-
1187
- DEFPRINT(AST_Yield, function(self, output) {
1188
- var star = self.is_star ? "*" : "";
1189
- output.print("yield" + star);
1190
- if (self.expression) {
1191
- output.space();
1192
- self.expression.print(output);
1193
- }
1194
- });
1195
-
1196
- DEFPRINT(AST_Await, function(self, output) {
1197
- output.print("await");
1198
- output.space();
1199
- var e = self.expression;
1200
- var parens = !(
1201
- e instanceof AST_Call
1202
- || e instanceof AST_SymbolRef
1203
- || e instanceof AST_PropAccess
1204
- || e instanceof AST_Unary
1205
- || e instanceof AST_Constant
1206
- );
1207
- if (parens) output.print("(");
1208
- self.expression.print(output);
1209
- if (parens) output.print(")");
1210
- });
1211
-
1212
- /* -----[ loop control ]----- */
1213
- AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) {
1214
- output.print(kind);
1215
- if (this.label) {
1216
- output.space();
1217
- this.label.print(output);
1218
- }
1219
- output.semicolon();
1220
- });
1221
- DEFPRINT(AST_Break, function(self, output) {
1222
- self._do_print(output, "break");
1223
- });
1224
- DEFPRINT(AST_Continue, function(self, output) {
1225
- self._do_print(output, "continue");
1226
- });
1227
-
1228
- /* -----[ if ]----- */
1229
- function make_then(self, output) {
1230
- var b = self.body;
1231
- if (output.option("braces")
1232
- || output.option("ie8") && b instanceof AST_Do)
1233
- return make_block(b, output);
1234
- // The squeezer replaces "block"-s that contain only a single
1235
- // statement with the statement itself; technically, the AST
1236
- // is correct, but this can create problems when we output an
1237
- // IF having an ELSE clause where the THEN clause ends in an
1238
- // IF *without* an ELSE block (then the outer ELSE would refer
1239
- // to the inner IF). This function checks for this case and
1240
- // adds the block braces if needed.
1241
- if (!b) return output.force_semicolon();
1242
- while (true) {
1243
- if (b instanceof AST_If) {
1244
- if (!b.alternative) {
1245
- make_block(self.body, output);
1246
- return;
1247
- }
1248
- b = b.alternative;
1249
- } else if (b instanceof AST_StatementWithBody) {
1250
- b = b.body;
1251
- } else break;
1252
- }
1253
- force_statement(self.body, output);
1254
- }
1255
- DEFPRINT(AST_If, function(self, output) {
1256
- output.print("if");
1257
- output.space();
1258
- output.with_parens(function() {
1259
- self.condition.print(output);
1260
- });
1261
- output.space();
1262
- if (self.alternative) {
1263
- make_then(self, output);
1264
- output.space();
1265
- output.print("else");
1266
- output.space();
1267
- if (self.alternative instanceof AST_If)
1268
- self.alternative.print(output);
1269
- else
1270
- force_statement(self.alternative, output);
1271
- } else {
1272
- self._do_print_body(output);
1273
- }
1274
- });
1275
-
1276
- /* -----[ switch ]----- */
1277
- DEFPRINT(AST_Switch, function(self, output) {
1278
- output.print("switch");
1279
- output.space();
1280
- output.with_parens(function() {
1281
- self.expression.print(output);
1282
- });
1283
- output.space();
1284
- var last = self.body.length - 1;
1285
- if (last < 0) print_braced_empty(self, output);
1286
- else output.with_block(function() {
1287
- self.body.forEach(function(branch, i) {
1288
- output.indent(true);
1289
- branch.print(output);
1290
- if (i < last && branch.body.length > 0)
1291
- output.newline();
1292
- });
1293
- });
1294
- });
1295
- AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
1296
- output.newline();
1297
- this.body.forEach(function(stmt) {
1298
- output.indent();
1299
- stmt.print(output);
1300
- output.newline();
1301
- });
1302
- });
1303
- DEFPRINT(AST_Default, function(self, output) {
1304
- output.print("default:");
1305
- self._do_print_body(output);
1306
- });
1307
- DEFPRINT(AST_Case, function(self, output) {
1308
- output.print("case");
1309
- output.space();
1310
- self.expression.print(output);
1311
- output.print(":");
1312
- self._do_print_body(output);
1313
- });
1314
-
1315
- /* -----[ exceptions ]----- */
1316
- DEFPRINT(AST_Try, function(self, output) {
1317
- output.print("try");
1318
- output.space();
1319
- print_braced(self, output);
1320
- if (self.bcatch) {
1321
- output.space();
1322
- self.bcatch.print(output);
1323
- }
1324
- if (self.bfinally) {
1325
- output.space();
1326
- self.bfinally.print(output);
1327
- }
1328
- });
1329
- DEFPRINT(AST_Catch, function(self, output) {
1330
- output.print("catch");
1331
- if (self.argname) {
1332
- output.space();
1333
- output.with_parens(function() {
1334
- self.argname.print(output);
1335
- });
1336
- }
1337
- output.space();
1338
- print_braced(self, output);
1339
- });
1340
- DEFPRINT(AST_Finally, function(self, output) {
1341
- output.print("finally");
1342
- output.space();
1343
- print_braced(self, output);
1344
- });
1345
-
1346
- /* -----[ var/const ]----- */
1347
- AST_Definitions.DEFMETHOD("_do_print", function(output, kind) {
1348
- output.print(kind);
1349
- output.space();
1350
- this.definitions.forEach(function(def, i) {
1351
- if (i) output.comma();
1352
- def.print(output);
1353
- });
1354
- var p = output.parent();
1355
- var in_for = p instanceof AST_For || p instanceof AST_ForIn;
1356
- var output_semicolon = !in_for || p && p.init !== this;
1357
- if (output_semicolon)
1358
- output.semicolon();
1359
- });
1360
- DEFPRINT(AST_Let, function(self, output) {
1361
- self._do_print(output, "let");
1362
- });
1363
- DEFPRINT(AST_Var, function(self, output) {
1364
- self._do_print(output, "var");
1365
- });
1366
- DEFPRINT(AST_Const, function(self, output) {
1367
- self._do_print(output, "const");
1368
- });
1369
- DEFPRINT(AST_Import, function(self, output) {
1370
- output.print("import");
1371
- output.space();
1372
- if (self.imported_name) {
1373
- self.imported_name.print(output);
1374
- }
1375
- if (self.imported_name && self.imported_names) {
1376
- output.print(",");
1377
- output.space();
1378
- }
1379
- if (self.imported_names) {
1380
- if (self.imported_names.length === 1 && self.imported_names[0].foreign_name.name === "*") {
1381
- self.imported_names[0].print(output);
1382
- } else {
1383
- output.print("{");
1384
- self.imported_names.forEach(function (name_import, i) {
1385
- output.space();
1386
- name_import.print(output);
1387
- if (i < self.imported_names.length - 1) {
1388
- output.print(",");
1389
- }
1390
- });
1391
- output.space();
1392
- output.print("}");
1393
- }
1394
- }
1395
- if (self.imported_name || self.imported_names) {
1396
- output.space();
1397
- output.print("from");
1398
- output.space();
1399
- }
1400
- self.module_name.print(output);
1401
- output.semicolon();
1402
- });
1403
-
1404
- DEFPRINT(AST_NameMapping, function(self, output) {
1405
- var is_import = output.parent() instanceof AST_Import;
1406
- var definition = self.name.definition();
1407
- var names_are_different =
1408
- (definition && definition.mangled_name || self.name.name) !==
1409
- self.foreign_name.name;
1410
- if (names_are_different) {
1411
- if (is_import) {
1412
- output.print(self.foreign_name.name);
1413
- } else {
1414
- self.name.print(output);
1415
- }
1416
- output.space();
1417
- output.print("as");
1418
- output.space();
1419
- if (is_import) {
1420
- self.name.print(output);
1421
- } else {
1422
- output.print(self.foreign_name.name);
1423
- }
1424
- } else {
1425
- self.name.print(output);
1426
- }
1427
- });
1428
-
1429
- DEFPRINT(AST_Export, function(self, output) {
1430
- output.print("export");
1431
- output.space();
1432
- if (self.is_default) {
1433
- output.print("default");
1434
- output.space();
1435
- }
1436
- if (self.exported_names) {
1437
- if (self.exported_names.length === 1 && self.exported_names[0].name.name === "*") {
1438
- self.exported_names[0].print(output);
1439
- } else {
1440
- output.print("{");
1441
- self.exported_names.forEach(function(name_export, i) {
1442
- output.space();
1443
- name_export.print(output);
1444
- if (i < self.exported_names.length - 1) {
1445
- output.print(",");
1446
- }
1447
- });
1448
- output.space();
1449
- output.print("}");
1450
- }
1451
- } else if (self.exported_value) {
1452
- self.exported_value.print(output);
1453
- } else if (self.exported_definition) {
1454
- self.exported_definition.print(output);
1455
- if (self.exported_definition instanceof AST_Definitions) return;
1456
- }
1457
- if (self.module_name) {
1458
- output.space();
1459
- output.print("from");
1460
- output.space();
1461
- self.module_name.print(output);
1462
- }
1463
- if (self.exported_value
1464
- && !(self.exported_value instanceof AST_Defun ||
1465
- self.exported_value instanceof AST_Function ||
1466
- self.exported_value instanceof AST_Class)
1467
- || self.module_name
1468
- || self.exported_names
1469
- ) {
1470
- output.semicolon();
1471
- }
1472
- });
1473
-
1474
- function parenthesize_for_noin(node, output, noin) {
1475
- var parens = false;
1476
- // need to take some precautions here:
1477
- // https://github.com/mishoo/UglifyJS2/issues/60
1478
- if (noin) node.walk(new TreeWalker(function(node) {
1479
- if (parens || node instanceof AST_Scope) return true;
1480
- if (node instanceof AST_Binary && node.operator == "in") {
1481
- parens = true;
1482
- return true;
1483
- }
1484
- }));
1485
- node.print(output, parens);
1486
- }
1487
-
1488
- DEFPRINT(AST_VarDef, function(self, output) {
1489
- self.name.print(output);
1490
- if (self.value) {
1491
- output.space();
1492
- output.print("=");
1493
- output.space();
1494
- var p = output.parent(1);
1495
- var noin = p instanceof AST_For || p instanceof AST_ForIn;
1496
- parenthesize_for_noin(self.value, output, noin);
1497
- }
1498
- });
1499
-
1500
- /* -----[ other expressions ]----- */
1501
- DEFPRINT(AST_Call, function(self, output) {
1502
- self.expression.print(output);
1503
- if (self instanceof AST_New && !need_constructor_parens(self, output))
1504
- return;
1505
- if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) {
1506
- output.add_mapping(self.start);
1507
- }
1508
- output.with_parens(function() {
1509
- self.args.forEach(function(expr, i) {
1510
- if (i) output.comma();
1511
- expr.print(output);
1512
- });
1513
- });
1514
- });
1515
- DEFPRINT(AST_New, function(self, output) {
1516
- output.print("new");
1517
- output.space();
1518
- AST_Call.prototype._codegen(self, output);
1519
- });
1520
-
1521
- AST_Sequence.DEFMETHOD("_do_print", function(output) {
1522
- this.expressions.forEach(function(node, index) {
1523
- if (index > 0) {
1524
- output.comma();
1525
- if (output.should_break()) {
1526
- output.newline();
1527
- output.indent();
1528
- }
1529
- }
1530
- node.print(output);
1531
- });
1532
- });
1533
- DEFPRINT(AST_Sequence, function(self, output) {
1534
- self._do_print(output);
1535
- // var p = output.parent();
1536
- // if (p instanceof AST_Statement) {
1537
- // output.with_indent(output.next_indent(), function(){
1538
- // self._do_print(output);
1539
- // });
1540
- // } else {
1541
- // self._do_print(output);
1542
- // }
1543
- });
1544
- DEFPRINT(AST_Dot, function(self, output) {
1545
- var expr = self.expression;
1546
- expr.print(output);
1547
- var prop = self.property;
1548
- if (output.option("ie8") && RESERVED_WORDS(prop)) {
1549
- output.print("[");
1550
- output.add_mapping(self.end);
1551
- output.print_string(prop);
1552
- output.print("]");
1553
- } else {
1554
- if (expr instanceof AST_Number && expr.getValue() >= 0) {
1555
- if (!/[xa-f.)]/i.test(output.last())) {
1556
- output.print(".");
1557
- }
1558
- }
1559
- output.print(".");
1560
- // the name after dot would be mapped about here.
1561
- output.add_mapping(self.end);
1562
- output.print_name(prop);
1563
- }
1564
- });
1565
- DEFPRINT(AST_Sub, function(self, output) {
1566
- self.expression.print(output);
1567
- output.print("[");
1568
- self.property.print(output);
1569
- output.print("]");
1570
- });
1571
- DEFPRINT(AST_UnaryPrefix, function(self, output) {
1572
- var op = self.operator;
1573
- output.print(op);
1574
- if (/^[a-z]/i.test(op)
1575
- || (/[+-]$/.test(op)
1576
- && self.expression instanceof AST_UnaryPrefix
1577
- && /^[+-]/.test(self.expression.operator))) {
1578
- output.space();
1579
- }
1580
- self.expression.print(output);
1581
- });
1582
- DEFPRINT(AST_UnaryPostfix, function(self, output) {
1583
- self.expression.print(output);
1584
- output.print(self.operator);
1585
- });
1586
- DEFPRINT(AST_Binary, function(self, output) {
1587
- var op = self.operator;
1588
- self.left.print(output);
1589
- if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
1590
- && self.left instanceof AST_UnaryPostfix
1591
- && self.left.operator == "--") {
1592
- // space is mandatory to avoid outputting -->
1593
- output.print(" ");
1594
- } else {
1595
- // the space is optional depending on "beautify"
1596
- output.space();
1597
- }
1598
- output.print(op);
1599
- if ((op == "<" || op == "<<")
1600
- && self.right instanceof AST_UnaryPrefix
1601
- && self.right.operator == "!"
1602
- && self.right.expression instanceof AST_UnaryPrefix
1603
- && self.right.expression.operator == "--") {
1604
- // space is mandatory to avoid outputting <!--
1605
- output.print(" ");
1606
- } else {
1607
- // the space is optional depending on "beautify"
1608
- output.space();
1609
- }
1610
- self.right.print(output);
1611
- });
1612
- DEFPRINT(AST_Conditional, function(self, output) {
1613
- self.condition.print(output);
1614
- output.space();
1615
- output.print("?");
1616
- output.space();
1617
- self.consequent.print(output);
1618
- output.space();
1619
- output.colon();
1620
- self.alternative.print(output);
1621
- });
1622
-
1623
- /* -----[ literals ]----- */
1624
- DEFPRINT(AST_Array, function(self, output) {
1625
- output.with_square(function() {
1626
- var a = self.elements, len = a.length;
1627
- if (len > 0) output.space();
1628
- a.forEach(function(exp, i) {
1629
- if (i) output.comma();
1630
- exp.print(output);
1631
- // If the final element is a hole, we need to make sure it
1632
- // doesn't look like a trailing comma, by inserting an actual
1633
- // trailing comma.
1634
- if (i === len - 1 && exp instanceof AST_Hole)
1635
- output.comma();
1636
- });
1637
- if (len > 0) output.space();
1638
- });
1639
- });
1640
- DEFPRINT(AST_Object, function(self, output) {
1641
- if (self.properties.length > 0) output.with_block(function() {
1642
- self.properties.forEach(function(prop, i) {
1643
- if (i) {
1644
- output.print(",");
1645
- output.newline();
1646
- }
1647
- output.indent();
1648
- prop.print(output);
1649
- });
1650
- output.newline();
1651
- });
1652
- else print_braced_empty(self, output);
1653
- });
1654
- DEFPRINT(AST_Class, function(self, output) {
1655
- output.print("class");
1656
- output.space();
1657
- if (self.name) {
1658
- self.name.print(output);
1659
- output.space();
1660
- }
1661
- if (self.extends) {
1662
- var parens = (
1663
- !(self.extends instanceof AST_SymbolRef)
1664
- && !(self.extends instanceof AST_PropAccess)
1665
- && !(self.extends instanceof AST_ClassExpression)
1666
- && !(self.extends instanceof AST_Function)
1667
- );
1668
- output.print("extends");
1669
- if (parens) {
1670
- output.print("(");
1671
- } else {
1672
- output.space();
1673
- }
1674
- self.extends.print(output);
1675
- if (parens) {
1676
- output.print(")");
1677
- } else {
1678
- output.space();
1679
- }
1680
- }
1681
- if (self.properties.length > 0) output.with_block(function() {
1682
- self.properties.forEach(function(prop, i) {
1683
- if (i) {
1684
- output.newline();
1685
- }
1686
- output.indent();
1687
- prop.print(output);
1688
- });
1689
- output.newline();
1690
- });
1691
- else output.print("{}");
1692
- });
1693
- DEFPRINT(AST_NewTarget, function(self, output) {
1694
- output.print("new.target");
1695
- });
1696
-
1697
- function print_property_name(key, quote, output) {
1698
- if (output.option("quote_keys")) {
1699
- output.print_string(key);
1700
- } else if ("" + +key == key && key >= 0) {
1701
- output.print(make_num(key));
1702
- } else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
1703
- if (quote && output.option("keep_quoted_props")) {
1704
- output.print_string(key, quote);
1705
- } else {
1706
- output.print_name(key);
1707
- }
1708
- } else {
1709
- output.print_string(key, quote);
1710
- }
1711
- }
1712
-
1713
- DEFPRINT(AST_ObjectKeyVal, function(self, output) {
1714
- function get_name(self) {
1715
- var def = self.definition();
1716
- return def ? def.mangled_name || def.name : self.name;
1717
- }
1718
-
1719
- var allowShortHand = output.option("shorthand");
1720
- if (allowShortHand &&
1721
- self.value instanceof AST_Symbol &&
1722
- is_identifier_string(self.key) &&
1723
- get_name(self.value) === self.key &&
1724
- is_identifier(self.key)
1725
- ) {
1726
- print_property_name(self.key, self.quote, output);
1727
-
1728
- } else if (allowShortHand &&
1729
- self.value instanceof AST_DefaultAssign &&
1730
- self.value.left instanceof AST_Symbol &&
1731
- is_identifier_string(self.key) &&
1732
- get_name(self.value.left) === self.key
1733
- ) {
1734
- print_property_name(self.key, self.quote, output);
1735
- output.space();
1736
- output.print("=");
1737
- output.space();
1738
- self.value.right.print(output);
1739
- } else {
1740
- if (!(self.key instanceof AST_Node)) {
1741
- print_property_name(self.key, self.quote, output);
1742
- } else {
1743
- output.with_square(function() {
1744
- self.key.print(output);
1745
- });
1746
- }
1747
- output.colon();
1748
- self.value.print(output);
1749
- }
1750
- });
1751
- AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
1752
- var self = this;
1753
- if (self.static) {
1754
- output.print("static");
1755
- output.space();
1756
- }
1757
- if (type) {
1758
- output.print(type);
1759
- output.space();
1760
- }
1761
- if (self.key instanceof AST_SymbolMethod) {
1762
- print_property_name(self.key.name, self.quote, output);
1763
- } else {
1764
- output.with_square(function() {
1765
- self.key.print(output);
1766
- });
1767
- }
1768
- self.value._do_print(output, true);
1769
- });
1770
- DEFPRINT(AST_ObjectSetter, function(self, output) {
1771
- self._print_getter_setter("set", output);
1772
- });
1773
- DEFPRINT(AST_ObjectGetter, function(self, output) {
1774
- self._print_getter_setter("get", output);
1775
- });
1776
- DEFPRINT(AST_ConciseMethod, function(self, output) {
1777
- var type;
1778
- if (self.is_generator && self.async) {
1779
- type = "async*";
1780
- } else if (self.is_generator) {
1781
- type = "*";
1782
- } else if (self.async) {
1783
- type = "async";
1784
- }
1785
- self._print_getter_setter(type, output);
1786
- });
1787
- AST_Symbol.DEFMETHOD("_do_print", function(output) {
1788
- var def = this.definition();
1789
- output.print_name(def ? def.mangled_name || def.name : this.name);
1790
- });
1791
- DEFPRINT(AST_Symbol, function (self, output) {
1792
- self._do_print(output);
1793
- });
1794
- DEFPRINT(AST_Hole, noop);
1795
- DEFPRINT(AST_This, function(self, output) {
1796
- output.print("this");
1797
- });
1798
- DEFPRINT(AST_Super, function(self, output) {
1799
- output.print("super");
1800
- });
1801
- DEFPRINT(AST_Constant, function(self, output) {
1802
- output.print(self.getValue());
1803
- });
1804
- DEFPRINT(AST_String, function(self, output) {
1805
- output.print_string(self.getValue(), self.quote, in_directive);
1806
- });
1807
- DEFPRINT(AST_Number, function(self, output) {
1808
- if (use_asm && self.start && self.start.raw != null) {
1809
- output.print(self.start.raw);
1810
- } else {
1811
- output.print(make_num(self.getValue()));
1812
- }
1813
- });
1814
-
1815
- DEFPRINT(AST_RegExp, function(self, output) {
1816
- var regexp = self.getValue();
1817
- var str = regexp.toString();
1818
- str = output.to_utf8(str);
1819
- output.print(str);
1820
- var p = output.parent();
1821
- if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)
1822
- output.print(" ");
1823
- });
1824
-
1825
- function force_statement(stat, output) {
1826
- if (output.option("braces")) {
1827
- make_block(stat, output);
1828
- } else {
1829
- if (!stat || stat instanceof AST_EmptyStatement)
1830
- output.force_semicolon();
1831
- else
1832
- stat.print(output);
1833
- }
1834
- }
1835
-
1836
- // self should be AST_New. decide if we want to show parens or not.
1837
- function need_constructor_parens(self, output) {
1838
- // Always print parentheses with arguments
1839
- if (self.args.length > 0) return true;
1840
-
1841
- return output.option("beautify");
1842
- }
1843
-
1844
- function best_of(a) {
1845
- var best = a[0], len = best.length;
1846
- for (var i = 1; i < a.length; ++i) {
1847
- if (a[i].length < len) {
1848
- best = a[i];
1849
- len = best.length;
1850
- }
1851
- }
1852
- return best;
1853
- }
1854
-
1855
- function make_num(num) {
1856
- var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace("e+", "e") ], m;
1857
- if (Math.floor(num) === num) {
1858
- if (num >= 0) {
1859
- a.push("0x" + num.toString(16).toLowerCase(), // probably pointless
1860
- "0" + num.toString(8)); // same.
1861
- } else {
1862
- a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless
1863
- "-0" + (-num).toString(8)); // same.
1864
- }
1865
- if ((m = /^(.*?)(0+)$/.exec(num))) {
1866
- a.push(m[1] + "e" + m[2].length);
1867
- }
1868
- } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {
1869
- a.push(m[2] + "e-" + (m[1].length + m[2].length),
1870
- str.substr(str.indexOf(".")));
1871
- }
1872
- return best_of(a);
1873
- }
1874
-
1875
- function make_block(stmt, output) {
1876
- if (!stmt || stmt instanceof AST_EmptyStatement)
1877
- output.print("{}");
1878
- else if (stmt instanceof AST_BlockStatement)
1879
- stmt.print(output);
1880
- else output.with_block(function() {
1881
- output.indent();
1882
- stmt.print(output);
1883
- output.newline();
1884
- });
1885
- }
1886
-
1887
- /* -----[ source map generators ]----- */
1888
-
1889
- function DEFMAP(nodetype, generator) {
1890
- nodetype.forEach(function(nodetype) {
1891
- nodetype.DEFMETHOD("add_source_map", generator);
1892
- });
1893
- }
1894
-
1895
- DEFMAP([
1896
- // We could easily add info for ALL nodes, but it seems to me that
1897
- // would be quite wasteful, hence this noop in the base class.
1898
- AST_Node,
1899
- // since the label symbol will mark it
1900
- AST_LabeledStatement,
1901
- AST_Toplevel,
1902
- ], noop);
1903
-
1904
- // XXX: I'm not exactly sure if we need it for all of these nodes,
1905
- // or if we should add even more.
1906
- DEFMAP([
1907
- AST_Array,
1908
- AST_BlockStatement,
1909
- AST_Catch,
1910
- AST_Class,
1911
- AST_Constant,
1912
- AST_Debugger,
1913
- AST_Definitions,
1914
- AST_Directive,
1915
- AST_Finally,
1916
- AST_Jump,
1917
- AST_Lambda,
1918
- AST_New,
1919
- AST_Object,
1920
- AST_StatementWithBody,
1921
- AST_Symbol,
1922
- AST_Switch,
1923
- AST_SwitchBranch,
1924
- AST_Try,
1925
- ], function(output) {
1926
- output.add_mapping(this.start);
1927
- });
1928
-
1929
- DEFMAP([
1930
- AST_ObjectGetter,
1931
- AST_ObjectSetter,
1932
- ], function(output) {
1933
- output.add_mapping(this.start, this.key.name);
1934
- });
1935
-
1936
- DEFMAP([ AST_ObjectProperty ], function(output) {
1937
- output.add_mapping(this.start, this.key);
1938
- });
1939
- })();