github.com/evanw/esbuild@v0.21.4/internal/js_printer/js_printer_test.go (about)

     1  package js_printer
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/evanw/esbuild/internal/ast"
     8  	"github.com/evanw/esbuild/internal/compat"
     9  	"github.com/evanw/esbuild/internal/config"
    10  	"github.com/evanw/esbuild/internal/js_parser"
    11  	"github.com/evanw/esbuild/internal/logger"
    12  	"github.com/evanw/esbuild/internal/renamer"
    13  	"github.com/evanw/esbuild/internal/test"
    14  )
    15  
    16  func expectPrintedCommon(t *testing.T, name string, contents string, expected string, options config.Options) {
    17  	t.Helper()
    18  	t.Run(name, func(t *testing.T) {
    19  		t.Helper()
    20  		log := logger.NewDeferLog(logger.DeferLogNoVerboseOrDebug, nil)
    21  		tree, ok := js_parser.Parse(log, test.SourceForTest(contents), js_parser.OptionsFromConfig(&options))
    22  		msgs := log.Done()
    23  		text := ""
    24  		for _, msg := range msgs {
    25  			text += msg.String(logger.OutputOptions{}, logger.TerminalInfo{})
    26  		}
    27  		test.AssertEqualWithDiff(t, text, "")
    28  		if !ok {
    29  			t.Fatal("Parse error")
    30  		}
    31  		symbols := ast.NewSymbolMap(1)
    32  		symbols.SymbolsForSource[0] = tree.Symbols
    33  		r := renamer.NewNoOpRenamer(symbols)
    34  		js := Print(tree, symbols, r, Options{
    35  			ASCIIOnly:           options.ASCIIOnly,
    36  			MinifySyntax:        options.MinifySyntax,
    37  			MinifyWhitespace:    options.MinifyWhitespace,
    38  			UnsupportedFeatures: options.UnsupportedJSFeatures,
    39  		}).JS
    40  		test.AssertEqualWithDiff(t, string(js), expected)
    41  	})
    42  }
    43  
    44  func expectPrinted(t *testing.T, contents string, expected string) {
    45  	t.Helper()
    46  	expectPrintedCommon(t, contents, contents, expected, config.Options{})
    47  }
    48  
    49  func expectPrintedMinify(t *testing.T, contents string, expected string) {
    50  	t.Helper()
    51  	expectPrintedCommon(t, contents+" [minified]", contents, expected, config.Options{
    52  		MinifyWhitespace: true,
    53  	})
    54  }
    55  
    56  func expectPrintedMangle(t *testing.T, contents string, expected string) {
    57  	t.Helper()
    58  	expectPrintedCommon(t, contents+" [mangled]", contents, expected, config.Options{
    59  		MinifySyntax: true,
    60  	})
    61  }
    62  
    63  func expectPrintedMangleMinify(t *testing.T, contents string, expected string) {
    64  	t.Helper()
    65  	expectPrintedCommon(t, contents+" [mangled, minified]", contents, expected, config.Options{
    66  		MinifySyntax:     true,
    67  		MinifyWhitespace: true,
    68  	})
    69  }
    70  
    71  func expectPrintedASCII(t *testing.T, contents string, expected string) {
    72  	t.Helper()
    73  	expectPrintedCommon(t, contents+" [ascii]", contents, expected, config.Options{
    74  		ASCIIOnly: true,
    75  	})
    76  }
    77  
    78  func expectPrintedMinifyASCII(t *testing.T, contents string, expected string) {
    79  	t.Helper()
    80  	expectPrintedCommon(t, contents+" [ascii]", contents, expected, config.Options{
    81  		MinifyWhitespace: true,
    82  		ASCIIOnly:        true,
    83  	})
    84  }
    85  
    86  func expectPrintedTarget(t *testing.T, esVersion int, contents string, expected string) {
    87  	t.Helper()
    88  	expectPrintedCommon(t, contents, contents, expected, config.Options{
    89  		UnsupportedJSFeatures: compat.UnsupportedJSFeatures(map[compat.Engine]compat.Semver{
    90  			compat.ES: {Parts: []int{esVersion}},
    91  		}),
    92  	})
    93  }
    94  
    95  func expectPrintedTargetMinify(t *testing.T, esVersion int, contents string, expected string) {
    96  	t.Helper()
    97  	expectPrintedCommon(t, contents+" [minified]", contents, expected, config.Options{
    98  		UnsupportedJSFeatures: compat.UnsupportedJSFeatures(map[compat.Engine]compat.Semver{
    99  			compat.ES: {Parts: []int{esVersion}},
   100  		}),
   101  		MinifyWhitespace: true,
   102  	})
   103  }
   104  
   105  func expectPrintedTargetMangle(t *testing.T, esVersion int, contents string, expected string) {
   106  	t.Helper()
   107  	expectPrintedCommon(t, contents+" [mangled]", contents, expected, config.Options{
   108  		UnsupportedJSFeatures: compat.UnsupportedJSFeatures(map[compat.Engine]compat.Semver{
   109  			compat.ES: {Parts: []int{esVersion}},
   110  		}),
   111  		MinifySyntax: true,
   112  	})
   113  }
   114  
   115  func expectPrintedTargetASCII(t *testing.T, esVersion int, contents string, expected string) {
   116  	t.Helper()
   117  	expectPrintedCommon(t, contents+" [ascii]", contents, expected, config.Options{
   118  		UnsupportedJSFeatures: compat.UnsupportedJSFeatures(map[compat.Engine]compat.Semver{
   119  			compat.ES: {Parts: []int{esVersion}},
   120  		}),
   121  		ASCIIOnly: true,
   122  	})
   123  }
   124  
   125  func expectPrintedJSX(t *testing.T, contents string, expected string) {
   126  	t.Helper()
   127  	expectPrintedCommon(t, contents, contents, expected, config.Options{
   128  		JSX: config.JSXOptions{
   129  			Parse:    true,
   130  			Preserve: true,
   131  		},
   132  	})
   133  }
   134  
   135  func expectPrintedJSXASCII(t *testing.T, contents string, expected string) {
   136  	t.Helper()
   137  	expectPrintedCommon(t, contents, contents, expected, config.Options{
   138  		JSX: config.JSXOptions{
   139  			Parse:    true,
   140  			Preserve: true,
   141  		},
   142  		ASCIIOnly: true,
   143  	})
   144  }
   145  
   146  func expectPrintedJSXMinify(t *testing.T, contents string, expected string) {
   147  	t.Helper()
   148  	expectPrintedCommon(t, contents+" [minified]", contents, expected, config.Options{
   149  		JSX: config.JSXOptions{
   150  			Parse:    true,
   151  			Preserve: true,
   152  		},
   153  		MinifyWhitespace: true,
   154  	})
   155  }
   156  
   157  func TestNumber(t *testing.T) {
   158  	// Check "1eN"
   159  	expectPrinted(t, "x = 1e-100", "x = 1e-100;\n")
   160  	expectPrinted(t, "x = 1e-4", "x = 1e-4;\n")
   161  	expectPrinted(t, "x = 1e-3", "x = 1e-3;\n")
   162  	expectPrinted(t, "x = 1e-2", "x = 0.01;\n")
   163  	expectPrinted(t, "x = 1e-1", "x = 0.1;\n")
   164  	expectPrinted(t, "x = 1e0", "x = 1;\n")
   165  	expectPrinted(t, "x = 1e1", "x = 10;\n")
   166  	expectPrinted(t, "x = 1e2", "x = 100;\n")
   167  	expectPrinted(t, "x = 1e3", "x = 1e3;\n")
   168  	expectPrinted(t, "x = 1e4", "x = 1e4;\n")
   169  	expectPrinted(t, "x = 1e100", "x = 1e100;\n")
   170  	expectPrintedMinify(t, "x = 1e-100", "x=1e-100;")
   171  	expectPrintedMinify(t, "x = 1e-5", "x=1e-5;")
   172  	expectPrintedMinify(t, "x = 1e-4", "x=1e-4;")
   173  	expectPrintedMinify(t, "x = 1e-3", "x=.001;")
   174  	expectPrintedMinify(t, "x = 1e-2", "x=.01;")
   175  	expectPrintedMinify(t, "x = 1e-1", "x=.1;")
   176  	expectPrintedMinify(t, "x = 1e0", "x=1;")
   177  	expectPrintedMinify(t, "x = 1e1", "x=10;")
   178  	expectPrintedMinify(t, "x = 1e2", "x=100;")
   179  	expectPrintedMinify(t, "x = 1e3", "x=1e3;")
   180  	expectPrintedMinify(t, "x = 1e4", "x=1e4;")
   181  	expectPrintedMinify(t, "x = 1e100", "x=1e100;")
   182  
   183  	// Check "12eN"
   184  	expectPrinted(t, "x = 12e-100", "x = 12e-100;\n")
   185  	expectPrinted(t, "x = 12e-5", "x = 12e-5;\n")
   186  	expectPrinted(t, "x = 12e-4", "x = 12e-4;\n")
   187  	expectPrinted(t, "x = 12e-3", "x = 0.012;\n")
   188  	expectPrinted(t, "x = 12e-2", "x = 0.12;\n")
   189  	expectPrinted(t, "x = 12e-1", "x = 1.2;\n")
   190  	expectPrinted(t, "x = 12e0", "x = 12;\n")
   191  	expectPrinted(t, "x = 12e1", "x = 120;\n")
   192  	expectPrinted(t, "x = 12e2", "x = 1200;\n")
   193  	expectPrinted(t, "x = 12e3", "x = 12e3;\n")
   194  	expectPrinted(t, "x = 12e4", "x = 12e4;\n")
   195  	expectPrinted(t, "x = 12e100", "x = 12e100;\n")
   196  	expectPrintedMinify(t, "x = 12e-100", "x=12e-100;")
   197  	expectPrintedMinify(t, "x = 12e-6", "x=12e-6;")
   198  	expectPrintedMinify(t, "x = 12e-5", "x=12e-5;")
   199  	expectPrintedMinify(t, "x = 12e-4", "x=.0012;")
   200  	expectPrintedMinify(t, "x = 12e-3", "x=.012;")
   201  	expectPrintedMinify(t, "x = 12e-2", "x=.12;")
   202  	expectPrintedMinify(t, "x = 12e-1", "x=1.2;")
   203  	expectPrintedMinify(t, "x = 12e0", "x=12;")
   204  	expectPrintedMinify(t, "x = 12e1", "x=120;")
   205  	expectPrintedMinify(t, "x = 12e2", "x=1200;")
   206  	expectPrintedMinify(t, "x = 12e3", "x=12e3;")
   207  	expectPrintedMinify(t, "x = 12e4", "x=12e4;")
   208  	expectPrintedMinify(t, "x = 12e100", "x=12e100;")
   209  
   210  	// Check cases for "A.BeX" => "ABeY" simplification
   211  	expectPrinted(t, "x = 123456789", "x = 123456789;\n")
   212  	expectPrinted(t, "x = 1123456789", "x = 1123456789;\n")
   213  	expectPrinted(t, "x = 10123456789", "x = 10123456789;\n")
   214  	expectPrinted(t, "x = 100123456789", "x = 100123456789;\n")
   215  	expectPrinted(t, "x = 1000123456789", "x = 1000123456789;\n")
   216  	expectPrinted(t, "x = 10000123456789", "x = 10000123456789;\n")
   217  	expectPrinted(t, "x = 100000123456789", "x = 100000123456789;\n")
   218  	expectPrinted(t, "x = 1000000123456789", "x = 1000000123456789;\n")
   219  	expectPrinted(t, "x = 10000000123456789", "x = 10000000123456788;\n")
   220  	expectPrinted(t, "x = 100000000123456789", "x = 100000000123456780;\n")
   221  	expectPrinted(t, "x = 1000000000123456789", "x = 1000000000123456800;\n")
   222  	expectPrinted(t, "x = 10000000000123456789", "x = 10000000000123458e3;\n")
   223  	expectPrinted(t, "x = 100000000000123456789", "x = 10000000000012345e4;\n")
   224  
   225  	// Check numbers around the ends of various integer ranges. These were
   226  	// crashing in the WebAssembly build due to a bug in the Go runtime.
   227  
   228  	// int32
   229  	expectPrinted(t, "x = 0x7fff_ffff", "x = 2147483647;\n")
   230  	expectPrinted(t, "x = 0x8000_0000", "x = 2147483648;\n")
   231  	expectPrinted(t, "x = 0x8000_0001", "x = 2147483649;\n")
   232  	expectPrinted(t, "x = -0x7fff_ffff", "x = -2147483647;\n")
   233  	expectPrinted(t, "x = -0x8000_0000", "x = -2147483648;\n")
   234  	expectPrinted(t, "x = -0x8000_0001", "x = -2147483649;\n")
   235  
   236  	// uint32
   237  	expectPrinted(t, "x = 0xffff_ffff", "x = 4294967295;\n")
   238  	expectPrinted(t, "x = 0x1_0000_0000", "x = 4294967296;\n")
   239  	expectPrinted(t, "x = 0x1_0000_0001", "x = 4294967297;\n")
   240  	expectPrinted(t, "x = -0xffff_ffff", "x = -4294967295;\n")
   241  	expectPrinted(t, "x = -0x1_0000_0000", "x = -4294967296;\n")
   242  	expectPrinted(t, "x = -0x1_0000_0001", "x = -4294967297;\n")
   243  
   244  	// int64
   245  	expectPrinted(t, "x = 0x7fff_ffff_ffff_fdff", "x = 9223372036854775e3;\n")
   246  	expectPrinted(t, "x = 0x8000_0000_0000_0000", "x = 9223372036854776e3;\n")
   247  	expectPrinted(t, "x = 0x8000_0000_0000_3000", "x = 9223372036854788e3;\n")
   248  	expectPrinted(t, "x = -0x7fff_ffff_ffff_fdff", "x = -9223372036854775e3;\n")
   249  	expectPrinted(t, "x = -0x8000_0000_0000_0000", "x = -9223372036854776e3;\n")
   250  	expectPrinted(t, "x = -0x8000_0000_0000_3000", "x = -9223372036854788e3;\n")
   251  
   252  	// uint64
   253  	expectPrinted(t, "x = 0xffff_ffff_ffff_fbff", "x = 1844674407370955e4;\n")
   254  	expectPrinted(t, "x = 0x1_0000_0000_0000_0000", "x = 18446744073709552e3;\n")
   255  	expectPrinted(t, "x = 0x1_0000_0000_0000_1000", "x = 18446744073709556e3;\n")
   256  	expectPrinted(t, "x = -0xffff_ffff_ffff_fbff", "x = -1844674407370955e4;\n")
   257  	expectPrinted(t, "x = -0x1_0000_0000_0000_0000", "x = -18446744073709552e3;\n")
   258  	expectPrinted(t, "x = -0x1_0000_0000_0000_1000", "x = -18446744073709556e3;\n")
   259  
   260  	// Check the hex vs. decimal decision boundary when minifying
   261  	expectPrinted(t, "x = 999999999999", "x = 999999999999;\n")
   262  	expectPrinted(t, "x = 1000000000001", "x = 1000000000001;\n")
   263  	expectPrinted(t, "x = 0x0FFF_FFFF_FFFF_FF80", "x = 1152921504606846800;\n")
   264  	expectPrinted(t, "x = 0x1000_0000_0000_0000", "x = 1152921504606847e3;\n")
   265  	expectPrinted(t, "x = 0xFFFF_FFFF_FFFF_F000", "x = 18446744073709548e3;\n")
   266  	expectPrinted(t, "x = 0xFFFF_FFFF_FFFF_F800", "x = 1844674407370955e4;\n")
   267  	expectPrinted(t, "x = 0xFFFF_FFFF_FFFF_FFFF", "x = 18446744073709552e3;\n")
   268  	expectPrintedMinify(t, "x = 999999999999", "x=999999999999;")
   269  	expectPrintedMinify(t, "x = 1000000000001", "x=0xe8d4a51001;")
   270  	expectPrintedMinify(t, "x = 0x0FFF_FFFF_FFFF_FF80", "x=0xfffffffffffff80;")
   271  	expectPrintedMinify(t, "x = 0x1000_0000_0000_0000", "x=1152921504606847e3;")
   272  	expectPrintedMinify(t, "x = 0xFFFF_FFFF_FFFF_F000", "x=0xfffffffffffff000;")
   273  	expectPrintedMinify(t, "x = 0xFFFF_FFFF_FFFF_F800", "x=1844674407370955e4;")
   274  	expectPrintedMinify(t, "x = 0xFFFF_FFFF_FFFF_FFFF", "x=18446744073709552e3;")
   275  
   276  	// Check printing a space in between a number and a subsequent "."
   277  	expectPrintedMinify(t, "x = 0.0001 .y", "x=1e-4.y;")
   278  	expectPrintedMinify(t, "x = 0.001 .y", "x=.001.y;")
   279  	expectPrintedMinify(t, "x = 0.01 .y", "x=.01.y;")
   280  	expectPrintedMinify(t, "x = 0.1 .y", "x=.1.y;")
   281  	expectPrintedMinify(t, "x = 0 .y", "x=0 .y;")
   282  	expectPrintedMinify(t, "x = 10 .y", "x=10 .y;")
   283  	expectPrintedMinify(t, "x = 100 .y", "x=100 .y;")
   284  	expectPrintedMinify(t, "x = 1000 .y", "x=1e3.y;")
   285  	expectPrintedMinify(t, "x = 12345 .y", "x=12345 .y;")
   286  	expectPrintedMinify(t, "x = 0xFFFF_0000_FFFF_0000 .y", "x=0xffff0000ffff0000.y;")
   287  }
   288  
   289  func TestArray(t *testing.T) {
   290  	expectPrinted(t, "[]", "[];\n")
   291  	expectPrinted(t, "[,]", "[,];\n")
   292  	expectPrinted(t, "[,,]", "[, ,];\n")
   293  }
   294  
   295  func TestSplat(t *testing.T) {
   296  	expectPrinted(t, "[...(a, b)]", "[...(a, b)];\n")
   297  	expectPrinted(t, "x(...(a, b))", "x(...(a, b));\n")
   298  	expectPrinted(t, "({...(a, b)})", "({ ...(a, b) });\n")
   299  }
   300  
   301  func TestNew(t *testing.T) {
   302  	expectPrinted(t, "new x", "new x();\n")
   303  	expectPrinted(t, "new x()", "new x();\n")
   304  	expectPrinted(t, "new (x)", "new x();\n")
   305  	expectPrinted(t, "new (x())", "new (x())();\n")
   306  	expectPrinted(t, "new (new x())", "new new x()();\n")
   307  	expectPrinted(t, "new (x + x)", "new (x + x)();\n")
   308  	expectPrinted(t, "(new x)()", "new x()();\n")
   309  
   310  	expectPrinted(t, "new foo().bar", "new foo().bar;\n")
   311  	expectPrinted(t, "new (foo().bar)", "new (foo()).bar();\n")
   312  	expectPrinted(t, "new (foo()).bar", "new (foo()).bar();\n")
   313  	expectPrinted(t, "new foo()[bar]", "new foo()[bar];\n")
   314  	expectPrinted(t, "new (foo()[bar])", "new (foo())[bar]();\n")
   315  	expectPrinted(t, "new (foo())[bar]", "new (foo())[bar]();\n")
   316  
   317  	expectPrinted(t, "new (import('foo').bar)", "new (import(\"foo\")).bar();\n")
   318  	expectPrinted(t, "new (import('foo')).bar", "new (import(\"foo\")).bar();\n")
   319  	expectPrinted(t, "new (import('foo')[bar])", "new (import(\"foo\"))[bar]();\n")
   320  	expectPrinted(t, "new (import('foo'))[bar]", "new (import(\"foo\"))[bar]();\n")
   321  
   322  	expectPrintedMinify(t, "new x", "new x;")
   323  	expectPrintedMinify(t, "new x.y", "new x.y;")
   324  	expectPrintedMinify(t, "(new x).y", "new x().y;")
   325  	expectPrintedMinify(t, "new x().y", "new x().y;")
   326  	expectPrintedMinify(t, "new x() + y", "new x+y;")
   327  	expectPrintedMinify(t, "new x() ** 2", "new x**2;")
   328  
   329  	// Test preservation of Webpack-specific comments
   330  	expectPrinted(t, "new Worker(// webpackFoo: 1\n // webpackBar: 2\n 'path');", "new Worker(\n  // webpackFoo: 1\n  // webpackBar: 2\n  \"path\"\n);\n")
   331  	expectPrinted(t, "new Worker(/* webpackFoo: 1 */ /* webpackBar: 2 */ 'path');", "new Worker(\n  /* webpackFoo: 1 */\n  /* webpackBar: 2 */\n  \"path\"\n);\n")
   332  	expectPrinted(t, "new Worker(\n    /* multi\n     * line\n     * webpackBar: */ 'path');", "new Worker(\n  /* multi\n   * line\n   * webpackBar: */\n  \"path\"\n);\n")
   333  	expectPrinted(t, "new Worker(/* webpackFoo: 1 */ 'path' /* webpackBar:2 */);", "new Worker(\n  /* webpackFoo: 1 */\n  \"path\"\n  /* webpackBar:2 */\n);\n")
   334  	expectPrinted(t, "new Worker(/* webpackFoo: 1 */ 'path' /* webpackBar:2 */ ,);", "new Worker(\n  /* webpackFoo: 1 */\n  \"path\"\n);\n") // Not currently handled
   335  	expectPrinted(t, "new Worker(/* webpackFoo: 1 */ 'path', /* webpackBar:2 */ );", "new Worker(\n  /* webpackFoo: 1 */\n  \"path\"\n  /* webpackBar:2 */\n);\n")
   336  	expectPrinted(t, "new Worker(new URL('path', /* webpackFoo: these can go anywhere */ import.meta.url))",
   337  		"new Worker(new URL(\n  \"path\",\n  /* webpackFoo: these can go anywhere */\n  import.meta.url\n));\n")
   338  }
   339  
   340  func TestCall(t *testing.T) {
   341  	expectPrinted(t, "x()()()", "x()()();\n")
   342  	expectPrinted(t, "x().y()[z]()", "x().y()[z]();\n")
   343  	expectPrinted(t, "(--x)();", "(--x)();\n")
   344  	expectPrinted(t, "(x--)();", "(x--)();\n")
   345  
   346  	expectPrinted(t, "eval(x)", "eval(x);\n")
   347  	expectPrinted(t, "eval?.(x)", "eval?.(x);\n")
   348  	expectPrinted(t, "(eval)(x)", "eval(x);\n")
   349  	expectPrinted(t, "(eval)?.(x)", "eval?.(x);\n")
   350  
   351  	expectPrinted(t, "eval(x, y)", "eval(x, y);\n")
   352  	expectPrinted(t, "eval?.(x, y)", "eval?.(x, y);\n")
   353  	expectPrinted(t, "(1, eval)(x)", "(1, eval)(x);\n")
   354  	expectPrinted(t, "(1, eval)?.(x)", "(1, eval)?.(x);\n")
   355  	expectPrintedMangle(t, "(1 ? eval : 2)(x)", "(0, eval)(x);\n")
   356  	expectPrintedMangle(t, "(1 ? eval : 2)?.(x)", "eval?.(x);\n")
   357  
   358  	expectPrintedMinify(t, "eval?.(x)", "eval?.(x);")
   359  	expectPrintedMinify(t, "eval(x,y)", "eval(x,y);")
   360  	expectPrintedMinify(t, "eval?.(x,y)", "eval?.(x,y);")
   361  	expectPrintedMinify(t, "(1, eval)(x)", "(1,eval)(x);")
   362  	expectPrintedMinify(t, "(1, eval)?.(x)", "(1,eval)?.(x);")
   363  	expectPrintedMangleMinify(t, "(1 ? eval : 2)(x)", "(0,eval)(x);")
   364  	expectPrintedMangleMinify(t, "(1 ? eval : 2)?.(x)", "eval?.(x);")
   365  }
   366  
   367  func TestMember(t *testing.T) {
   368  	expectPrinted(t, "x.y[z]", "x.y[z];\n")
   369  	expectPrinted(t, "((x+1).y+1)[z]", "((x + 1).y + 1)[z];\n")
   370  }
   371  
   372  func TestComma(t *testing.T) {
   373  	expectPrinted(t, "1, 2, 3", "1, 2, 3;\n")
   374  	expectPrinted(t, "(1, 2), 3", "1, 2, 3;\n")
   375  	expectPrinted(t, "1, (2, 3)", "1, 2, 3;\n")
   376  	expectPrinted(t, "a ? (b, c) : (d, e)", "a ? (b, c) : (d, e);\n")
   377  	expectPrinted(t, "let x = (a, b)", "let x = (a, b);\n")
   378  	expectPrinted(t, "(x = a), b", "x = a, b;\n")
   379  	expectPrinted(t, "x = (a, b)", "x = (a, b);\n")
   380  	expectPrinted(t, "x((1, 2))", "x((1, 2));\n")
   381  }
   382  
   383  func TestUnary(t *testing.T) {
   384  	expectPrinted(t, "+(x--)", "+x--;\n")
   385  	expectPrinted(t, "-(x++)", "-x++;\n")
   386  }
   387  
   388  func TestNullish(t *testing.T) {
   389  	// "??" can't directly contain "||" or "&&"
   390  	expectPrinted(t, "(a && b) ?? c", "(a && b) ?? c;\n")
   391  	expectPrinted(t, "(a || b) ?? c", "(a || b) ?? c;\n")
   392  	expectPrinted(t, "a ?? (b && c)", "a ?? (b && c);\n")
   393  	expectPrinted(t, "a ?? (b || c)", "a ?? (b || c);\n")
   394  
   395  	// "||" and "&&" can't directly contain "??"
   396  	expectPrinted(t, "a && (b ?? c)", "a && (b ?? c);\n")
   397  	expectPrinted(t, "a || (b ?? c)", "a || (b ?? c);\n")
   398  	expectPrinted(t, "(a ?? b) && c", "(a ?? b) && c;\n")
   399  	expectPrinted(t, "(a ?? b) || c", "(a ?? b) || c;\n")
   400  }
   401  
   402  func TestString(t *testing.T) {
   403  	expectPrinted(t, "let x = ''", "let x = \"\";\n")
   404  	expectPrinted(t, "let x = '\b'", "let x = \"\\b\";\n")
   405  	expectPrinted(t, "let x = '\f'", "let x = \"\\f\";\n")
   406  	expectPrinted(t, "let x = '\t'", "let x = \"\t\";\n")
   407  	expectPrinted(t, "let x = '\v'", "let x = \"\\v\";\n")
   408  	expectPrinted(t, "let x = '\\n'", "let x = \"\\n\";\n")
   409  	expectPrinted(t, "let x = '\\''", "let x = \"'\";\n")
   410  	expectPrinted(t, "let x = '\\\"'", "let x = '\"';\n")
   411  	expectPrinted(t, "let x = '\\'\"'", "let x = `'\"`;\n")
   412  	expectPrinted(t, "let x = '\\\\'", "let x = \"\\\\\";\n")
   413  	expectPrinted(t, "let x = '\x00'", "let x = \"\\0\";\n")
   414  	expectPrinted(t, "let x = '\x00!'", "let x = \"\\0!\";\n")
   415  	expectPrinted(t, "let x = '\x001'", "let x = \"\\x001\";\n")
   416  	expectPrinted(t, "let x = '\\0'", "let x = \"\\0\";\n")
   417  	expectPrinted(t, "let x = '\\0!'", "let x = \"\\0!\";\n")
   418  	expectPrinted(t, "let x = '\x07'", "let x = \"\\x07\";\n")
   419  	expectPrinted(t, "let x = '\x07!'", "let x = \"\\x07!\";\n")
   420  	expectPrinted(t, "let x = '\x071'", "let x = \"\\x071\";\n")
   421  	expectPrinted(t, "let x = '\\7'", "let x = \"\\x07\";\n")
   422  	expectPrinted(t, "let x = '\\7!'", "let x = \"\\x07!\";\n")
   423  	expectPrinted(t, "let x = '\\01'", "let x = \"\x01\";\n")
   424  	expectPrinted(t, "let x = '\x10'", "let x = \"\x10\";\n")
   425  	expectPrinted(t, "let x = '\\x10'", "let x = \"\x10\";\n")
   426  	expectPrinted(t, "let x = '\x1B'", "let x = \"\\x1B\";\n")
   427  	expectPrinted(t, "let x = '\\x1B'", "let x = \"\\x1B\";\n")
   428  	expectPrinted(t, "let x = '\uABCD'", "let x = \"\uABCD\";\n")
   429  	expectPrinted(t, "let x = '\\uABCD'", "let x = \"\uABCD\";\n")
   430  	expectPrinted(t, "let x = '\U000123AB'", "let x = \"\U000123AB\";\n")
   431  	expectPrinted(t, "let x = '\\u{123AB}'", "let x = \"\U000123AB\";\n")
   432  	expectPrinted(t, "let x = '\\uD808\\uDFAB'", "let x = \"\U000123AB\";\n")
   433  	expectPrinted(t, "let x = '\\uD808'", "let x = \"\\uD808\";\n")
   434  	expectPrinted(t, "let x = '\\uD808X'", "let x = \"\\uD808X\";\n")
   435  	expectPrinted(t, "let x = '\\uDFAB'", "let x = \"\\uDFAB\";\n")
   436  	expectPrinted(t, "let x = '\\uDFABX'", "let x = \"\\uDFABX\";\n")
   437  
   438  	expectPrinted(t, "let x = '\\x80'", "let x = \"\U00000080\";\n")
   439  	expectPrinted(t, "let x = '\\xFF'", "let x = \"\U000000FF\";\n")
   440  	expectPrinted(t, "let x = '\\xF0\\x9F\\x8D\\x95'", "let x = \"\U000000F0\U0000009F\U0000008D\U00000095\";\n")
   441  	expectPrinted(t, "let x = '\\uD801\\uDC02\\uDC03\\uD804'", "let x = \"\U00010402\\uDC03\\uD804\";\n")
   442  }
   443  
   444  func TestTemplate(t *testing.T) {
   445  	expectPrinted(t, "let x = `\\0`", "let x = `\\0`;\n")
   446  	expectPrinted(t, "let x = `\\x01`", "let x = `\x01`;\n")
   447  	expectPrinted(t, "let x = `\\0${0}`", "let x = `\\0${0}`;\n")
   448  	expectPrinted(t, "let x = `\\x01${0}`", "let x = `\x01${0}`;\n")
   449  	expectPrinted(t, "let x = `${0}\\0`", "let x = `${0}\\0`;\n")
   450  	expectPrinted(t, "let x = `${0}\\x01`", "let x = `${0}\x01`;\n")
   451  	expectPrinted(t, "let x = `${0}\\0${1}`", "let x = `${0}\\0${1}`;\n")
   452  	expectPrinted(t, "let x = `${0}\\x01${1}`", "let x = `${0}\x01${1}`;\n")
   453  
   454  	expectPrinted(t, "let x = String.raw`\\1`", "let x = String.raw`\\1`;\n")
   455  	expectPrinted(t, "let x = String.raw`\\x01`", "let x = String.raw`\\x01`;\n")
   456  	expectPrinted(t, "let x = String.raw`\\1${0}`", "let x = String.raw`\\1${0}`;\n")
   457  	expectPrinted(t, "let x = String.raw`\\x01${0}`", "let x = String.raw`\\x01${0}`;\n")
   458  	expectPrinted(t, "let x = String.raw`${0}\\1`", "let x = String.raw`${0}\\1`;\n")
   459  	expectPrinted(t, "let x = String.raw`${0}\\x01`", "let x = String.raw`${0}\\x01`;\n")
   460  	expectPrinted(t, "let x = String.raw`${0}\\1${1}`", "let x = String.raw`${0}\\1${1}`;\n")
   461  	expectPrinted(t, "let x = String.raw`${0}\\x01${1}`", "let x = String.raw`${0}\\x01${1}`;\n")
   462  
   463  	expectPrinted(t, "let x = `${y}`", "let x = `${y}`;\n")
   464  	expectPrinted(t, "let x = `$(y)`", "let x = `$(y)`;\n")
   465  	expectPrinted(t, "let x = `{y}$`", "let x = `{y}$`;\n")
   466  	expectPrinted(t, "let x = `$}y{`", "let x = `$}y{`;\n")
   467  	expectPrinted(t, "let x = `\\${y}`", "let x = `\\${y}`;\n")
   468  	expectPrinted(t, "let x = `$\\{y}`", "let x = `\\${y}`;\n")
   469  
   470  	expectPrinted(t, "await tag`x`", "await tag`x`;\n")
   471  	expectPrinted(t, "await (tag`x`)", "await tag`x`;\n")
   472  	expectPrinted(t, "(await tag)`x`", "(await tag)`x`;\n")
   473  
   474  	expectPrinted(t, "await tag`${x}`", "await tag`${x}`;\n")
   475  	expectPrinted(t, "await (tag`${x}`)", "await tag`${x}`;\n")
   476  	expectPrinted(t, "(await tag)`${x}`", "(await tag)`${x}`;\n")
   477  
   478  	expectPrinted(t, "new tag`x`", "new tag`x`();\n")
   479  	expectPrinted(t, "new (tag`x`)", "new tag`x`();\n")
   480  	expectPrinted(t, "new tag()`x`", "new tag()`x`;\n")
   481  	expectPrinted(t, "(new tag)`x`", "new tag()`x`;\n")
   482  	expectPrintedMinify(t, "new tag`x`", "new tag`x`;")
   483  	expectPrintedMinify(t, "new (tag`x`)", "new tag`x`;")
   484  	expectPrintedMinify(t, "new tag()`x`", "new tag()`x`;")
   485  	expectPrintedMinify(t, "(new tag)`x`", "new tag()`x`;")
   486  
   487  	expectPrinted(t, "new tag`${x}`", "new tag`${x}`();\n")
   488  	expectPrinted(t, "new (tag`${x}`)", "new tag`${x}`();\n")
   489  	expectPrinted(t, "new tag()`${x}`", "new tag()`${x}`;\n")
   490  	expectPrinted(t, "(new tag)`${x}`", "new tag()`${x}`;\n")
   491  	expectPrintedMinify(t, "new tag`${x}`", "new tag`${x}`;")
   492  	expectPrintedMinify(t, "new (tag`${x}`)", "new tag`${x}`;")
   493  	expectPrintedMinify(t, "new tag()`${x}`", "new tag()`${x}`;")
   494  	expectPrintedMinify(t, "(new tag)`${x}`", "new tag()`${x}`;")
   495  }
   496  
   497  func TestObject(t *testing.T) {
   498  	expectPrinted(t, "let x = {'(':')'}", "let x = { \"(\": \")\" };\n")
   499  	expectPrinted(t, "({})", "({});\n")
   500  	expectPrinted(t, "({}.x)", "({}).x;\n")
   501  	expectPrinted(t, "({} = {})", "({} = {});\n")
   502  	expectPrinted(t, "(x, {} = {})", "x, {} = {};\n")
   503  	expectPrinted(t, "let x = () => ({})", "let x = () => ({});\n")
   504  	expectPrinted(t, "let x = () => ({}.x)", "let x = () => ({}).x;\n")
   505  	expectPrinted(t, "let x = () => ({} = {})", "let x = () => ({} = {});\n")
   506  	expectPrinted(t, "let x = () => (x, {} = {})", "let x = () => (x, {} = {});\n")
   507  
   508  	// "{ __proto__: __proto__ }" must not become "{ __proto__ }"
   509  	expectPrinted(t, "function foo(__proto__) { return { __proto__: __proto__ } }", "function foo(__proto__) {\n  return { __proto__: __proto__ };\n}\n")
   510  	expectPrinted(t, "function foo(__proto__) { return { '__proto__': __proto__ } }", "function foo(__proto__) {\n  return { \"__proto__\": __proto__ };\n}\n")
   511  	expectPrinted(t, "function foo(__proto__) { return { ['__proto__']: __proto__ } }", "function foo(__proto__) {\n  return { [\"__proto__\"]: __proto__ };\n}\n")
   512  	expectPrinted(t, "import { __proto__ } from 'foo'; let foo = () => ({ __proto__: __proto__ })", "import { __proto__ } from \"foo\";\nlet foo = () => ({ __proto__: __proto__ });\n")
   513  	expectPrinted(t, "import { __proto__ } from 'foo'; let foo = () => ({ '__proto__': __proto__ })", "import { __proto__ } from \"foo\";\nlet foo = () => ({ \"__proto__\": __proto__ });\n")
   514  	expectPrinted(t, "import { __proto__ } from 'foo'; let foo = () => ({ ['__proto__']: __proto__ })", "import { __proto__ } from \"foo\";\nlet foo = () => ({ [\"__proto__\"]: __proto__ });\n")
   515  
   516  	// Don't use ES6+ features (such as a shorthand or computed property name) in ES5
   517  	expectPrintedTarget(t, 5, "function foo(__proto__) { return { __proto__ } }", "function foo(__proto__) {\n  return { __proto__: __proto__ };\n}\n")
   518  }
   519  
   520  func TestFor(t *testing.T) {
   521  	// Make sure "in" expressions are forbidden in the right places
   522  	expectPrinted(t, "for ((a in b);;);", "for ((a in b); ; ) ;\n")
   523  	expectPrinted(t, "for (a ? b : (c in d);;);", "for (a ? b : (c in d); ; ) ;\n")
   524  	expectPrinted(t, "for ((a ? b : c in d).foo;;);", "for ((a ? b : c in d).foo; ; ) ;\n")
   525  	expectPrinted(t, "for (var x = (a in b);;);", "for (var x = (a in b); ; ) ;\n")
   526  	expectPrinted(t, "for (x = (a in b);;);", "for (x = (a in b); ; ) ;\n")
   527  	expectPrinted(t, "for (x == (a in b);;);", "for (x == (a in b); ; ) ;\n")
   528  	expectPrinted(t, "for (1 * (x == a in b);;);", "for (1 * (x == a in b); ; ) ;\n")
   529  	expectPrinted(t, "for (a ? b : x = (c in d);;);", "for (a ? b : x = (c in d); ; ) ;\n")
   530  	expectPrinted(t, "for (var x = y = (a in b);;);", "for (var x = y = (a in b); ; ) ;\n")
   531  	expectPrinted(t, "for ([a in b];;);", "for ([a in b]; ; ) ;\n")
   532  	expectPrinted(t, "for (x(a in b);;);", "for (x(a in b); ; ) ;\n")
   533  	expectPrinted(t, "for (x[a in b];;);", "for (x[a in b]; ; ) ;\n")
   534  	expectPrinted(t, "for (x?.[a in b];;);", "for (x?.[a in b]; ; ) ;\n")
   535  	expectPrinted(t, "for ((x => a in b);;);", "for ((x) => (a in b); ; ) ;\n")
   536  
   537  	// Make sure for-of loops with commas are wrapped in parentheses
   538  	expectPrinted(t, "for (let a in b, c);", "for (let a in b, c) ;\n")
   539  	expectPrinted(t, "for (let a of (b, c));", "for (let a of (b, c)) ;\n")
   540  }
   541  
   542  func TestFunction(t *testing.T) {
   543  	expectPrinted(t,
   544  		"function foo(a = (b, c), ...d) {}",
   545  		"function foo(a = (b, c), ...d) {\n}\n")
   546  	expectPrinted(t,
   547  		"function foo({[1 + 2]: a = 3} = {[1 + 2]: 3}) {}",
   548  		"function foo({ [1 + 2]: a = 3 } = { [1 + 2]: 3 }) {\n}\n")
   549  	expectPrinted(t,
   550  		"function foo([a = (1, 2), ...[b, ...c]] = [1, [2, 3]]) {}",
   551  		"function foo([a = (1, 2), ...[b, ...c]] = [1, [2, 3]]) {\n}\n")
   552  	expectPrinted(t,
   553  		"function foo([] = []) {}",
   554  		"function foo([] = []) {\n}\n")
   555  	expectPrinted(t,
   556  		"function foo([,] = [,]) {}",
   557  		"function foo([,] = [,]) {\n}\n")
   558  	expectPrinted(t,
   559  		"function foo([,,] = [,,]) {}",
   560  		"function foo([, ,] = [, ,]) {\n}\n")
   561  }
   562  
   563  func TestCommentsAndParentheses(t *testing.T) {
   564  	expectPrinted(t, "(/* foo */ { x() { foo() } }.x());", "/* foo */\n({ x() {\n  foo();\n} }).x();\n")
   565  	expectPrinted(t, "(/* foo */ function f() { foo(f) }());", "/* foo */\n(function f() {\n  foo(f);\n})();\n")
   566  	expectPrinted(t, "(/* foo */ class x { static y() { foo(x) } }.y());", "/* foo */\n(class x {\n  static y() {\n    foo(x);\n  }\n}).y();\n")
   567  	expectPrinted(t, "(/* @__PURE__ */ (() => foo())());", "/* @__PURE__ */ (() => foo())();\n")
   568  	expectPrinted(t, "export default (/* foo */ function f() {});", "export default (\n  /* foo */\n  function f() {\n  }\n);\n")
   569  	expectPrinted(t, "export default (/* foo */ class x {});", "export default (\n  /* foo */\n  class x {\n  }\n);\n")
   570  	expectPrinted(t, "x = () => (/* foo */ {});", "x = () => (\n  /* foo */\n  {}\n);\n")
   571  	expectPrinted(t, "for ((/* foo */ let).x of y) ;", "for (\n  /* foo */\n  (let).x of y\n) ;\n")
   572  	expectPrinted(t, "for (/* foo */ (let).x of y) ;", "for (\n  /* foo */\n  (let).x of y\n) ;\n")
   573  	expectPrinted(t, "function *x() { yield (/* foo */ y) }", "function* x() {\n  yield (\n    /* foo */\n    y\n  );\n}\n")
   574  }
   575  
   576  func TestPureComment(t *testing.T) {
   577  	expectPrinted(t,
   578  		"(function() { foo() })",
   579  		"(function() {\n  foo();\n});\n")
   580  	expectPrinted(t,
   581  		"(function() { foo() })()",
   582  		"(function() {\n  foo();\n})();\n")
   583  	expectPrinted(t,
   584  		"/*@__PURE__*/(function() { foo() })()",
   585  		"/* @__PURE__ */ (function() {\n  foo();\n})();\n")
   586  
   587  	expectPrinted(t,
   588  		"new (function() {})",
   589  		"new function() {\n}();\n")
   590  	expectPrinted(t,
   591  		"new (function() {})()",
   592  		"new function() {\n}();\n")
   593  	expectPrinted(t,
   594  		"/*@__PURE__*/new (function() {})()",
   595  		"/* @__PURE__ */ new function() {\n}();\n")
   596  
   597  	expectPrinted(t,
   598  		"export default (function() { foo() })",
   599  		"export default (function() {\n  foo();\n});\n")
   600  	expectPrinted(t,
   601  		"export default (function() { foo() })()",
   602  		"export default (function() {\n  foo();\n})();\n")
   603  	expectPrinted(t,
   604  		"export default /*@__PURE__*/(function() { foo() })()",
   605  		"export default /* @__PURE__ */ (function() {\n  foo();\n})();\n")
   606  }
   607  
   608  func TestGenerator(t *testing.T) {
   609  	expectPrinted(t,
   610  		"function* foo() {}",
   611  		"function* foo() {\n}\n")
   612  	expectPrinted(t,
   613  		"(function* () {})",
   614  		"(function* () {\n});\n")
   615  	expectPrinted(t,
   616  		"(function* foo() {})",
   617  		"(function* foo() {\n});\n")
   618  
   619  	expectPrinted(t,
   620  		"class Foo { *foo() {} }",
   621  		"class Foo {\n  *foo() {\n  }\n}\n")
   622  	expectPrinted(t,
   623  		"class Foo { static *foo() {} }",
   624  		"class Foo {\n  static *foo() {\n  }\n}\n")
   625  	expectPrinted(t,
   626  		"class Foo { *[foo]() {} }",
   627  		"class Foo {\n  *[foo]() {\n  }\n}\n")
   628  	expectPrinted(t,
   629  		"class Foo { static *[foo]() {} }",
   630  		"class Foo {\n  static *[foo]() {\n  }\n}\n")
   631  
   632  	expectPrinted(t,
   633  		"(class { *foo() {} })",
   634  		"(class {\n  *foo() {\n  }\n});\n")
   635  	expectPrinted(t,
   636  		"(class { static *foo() {} })",
   637  		"(class {\n  static *foo() {\n  }\n});\n")
   638  	expectPrinted(t,
   639  		"(class { *[foo]() {} })",
   640  		"(class {\n  *[foo]() {\n  }\n});\n")
   641  	expectPrinted(t,
   642  		"(class { static *[foo]() {} })",
   643  		"(class {\n  static *[foo]() {\n  }\n});\n")
   644  }
   645  
   646  func TestArrow(t *testing.T) {
   647  	expectPrinted(t, "() => {}", "() => {\n};\n")
   648  	expectPrinted(t, "x => (x, 0)", "(x) => (x, 0);\n")
   649  	expectPrinted(t, "x => {y}", "(x) => {\n  y;\n};\n")
   650  	expectPrinted(t,
   651  		"(a = (b, c), ...d) => {}",
   652  		"(a = (b, c), ...d) => {\n};\n")
   653  	expectPrinted(t,
   654  		"({[1 + 2]: a = 3} = {[1 + 2]: 3}) => {}",
   655  		"({ [1 + 2]: a = 3 } = { [1 + 2]: 3 }) => {\n};\n")
   656  	expectPrinted(t,
   657  		"([a = (1, 2), ...[b, ...c]] = [1, [2, 3]]) => {}",
   658  		"([a = (1, 2), ...[b, ...c]] = [1, [2, 3]]) => {\n};\n")
   659  	expectPrinted(t,
   660  		"([] = []) => {}",
   661  		"([] = []) => {\n};\n")
   662  	expectPrinted(t,
   663  		"([,] = [,]) => {}",
   664  		"([,] = [,]) => {\n};\n")
   665  	expectPrinted(t,
   666  		"([,,] = [,,]) => {}",
   667  		"([, ,] = [, ,]) => {\n};\n")
   668  	expectPrinted(t,
   669  		"a = () => {}",
   670  		"a = () => {\n};\n")
   671  	expectPrinted(t,
   672  		"a || (() => {})",
   673  		"a || (() => {\n});\n")
   674  	expectPrinted(t,
   675  		"({a = b, c = d}) => {}",
   676  		"({ a = b, c = d }) => {\n};\n")
   677  	expectPrinted(t,
   678  		"([{a = b, c = d} = {}] = []) => {}",
   679  		"([{ a = b, c = d } = {}] = []) => {\n};\n")
   680  	expectPrinted(t,
   681  		"({a: [b = c] = []} = {}) => {}",
   682  		"({ a: [b = c] = [] } = {}) => {\n};\n")
   683  
   684  	// These are not arrow functions but initially look like one
   685  	expectPrinted(t, "(a = b, c)", "a = b, c;\n")
   686  	expectPrinted(t, "([...a = b])", "[...a = b];\n")
   687  	expectPrinted(t, "([...a, ...b])", "[...a, ...b];\n")
   688  	expectPrinted(t, "({a: b, c() {}})", "({ a: b, c() {\n} });\n")
   689  	expectPrinted(t, "({a: b, get c() {}})", "({ a: b, get c() {\n} });\n")
   690  	expectPrinted(t, "({a: b, set c(x) {}})", "({ a: b, set c(x) {\n} });\n")
   691  }
   692  
   693  func TestClass(t *testing.T) {
   694  	expectPrinted(t, "class Foo extends (a, b) {}", "class Foo extends (a, b) {\n}\n")
   695  	expectPrinted(t, "class Foo { get foo() {} }", "class Foo {\n  get foo() {\n  }\n}\n")
   696  	expectPrinted(t, "class Foo { set foo(x) {} }", "class Foo {\n  set foo(x) {\n  }\n}\n")
   697  	expectPrinted(t, "class Foo { static foo() {} }", "class Foo {\n  static foo() {\n  }\n}\n")
   698  	expectPrinted(t, "class Foo { static get foo() {} }", "class Foo {\n  static get foo() {\n  }\n}\n")
   699  	expectPrinted(t, "class Foo { static set foo(x) {} }", "class Foo {\n  static set foo(x) {\n  }\n}\n")
   700  }
   701  
   702  func TestAutoAccessors(t *testing.T) {
   703  	expectPrinted(t, "class Foo { accessor x; static accessor y }", "class Foo {\n  accessor x;\n  static accessor y;\n}\n")
   704  	expectPrinted(t, "class Foo { accessor [x]; static accessor [y] }", "class Foo {\n  accessor [x];\n  static accessor [y];\n}\n")
   705  	expectPrintedMinify(t, "class Foo { accessor x; static accessor y }", "class Foo{accessor x;static accessor y}")
   706  	expectPrintedMinify(t, "class Foo { accessor [x]; static accessor [y] }", "class Foo{accessor[x];static accessor[y]}")
   707  }
   708  
   709  func TestPrivateIdentifiers(t *testing.T) {
   710  	expectPrinted(t, "class Foo { #foo; foo() { return #foo in this } }", "class Foo {\n  #foo;\n  foo() {\n    return #foo in this;\n  }\n}\n")
   711  	expectPrintedMinify(t, "class Foo { #foo; foo() { return #foo in this } }", "class Foo{#foo;foo(){return#foo in this}}")
   712  }
   713  
   714  func TestDecorators(t *testing.T) {
   715  	example := "class Foo {\n@w\nw; @x x; @a1\n@b1@b2\n@c1@c2@c3\ny = @y1 @y2 class {}; @a1\n@b1@b2\n@c1@c2@c3 z =\n@z1\n@z2\nclass {}}"
   716  	expectPrinted(t, example, "class Foo {\n  @w\n  w;\n  @x x;\n  @a1\n  @b1 @b2\n  @c1 @c2 @c3\n  "+
   717  		"y = @y1 @y2 class {\n  };\n  @a1\n  @b1 @b2\n  @c1 @c2 @c3 z = @z1 @z2 class {\n  };\n}\n")
   718  	expectPrintedMinify(t, example, "class Foo{@w w;@x x;@a1@b1@b2@c1@c2@c3 y=@y1@y2 class{};@a1@b1@b2@c1@c2@c3 z=@z1@z2 class{}}")
   719  }
   720  
   721  func TestImport(t *testing.T) {
   722  	expectPrinted(t, "import('path');", "import(\"path\");\n") // The semicolon must not be a separate statement
   723  
   724  	// Test preservation of Webpack-specific comments
   725  	expectPrinted(t, "import(// webpackFoo: 1\n // webpackBar: 2\n 'path');", "import(\n  // webpackFoo: 1\n  // webpackBar: 2\n  \"path\"\n);\n")
   726  	expectPrinted(t, "import(// webpackFoo: 1\n // webpackBar: 2\n 'path', {type: 'module'});", "import(\n  // webpackFoo: 1\n  // webpackBar: 2\n  \"path\",\n  { type: \"module\" }\n);\n")
   727  	expectPrinted(t, "import(/* webpackFoo: 1 */ /* webpackBar: 2 */ 'path');", "import(\n  /* webpackFoo: 1 */\n  /* webpackBar: 2 */\n  \"path\"\n);\n")
   728  	expectPrinted(t, "import(/* webpackFoo: 1 */ /* webpackBar: 2 */ 'path', {type: 'module'});", "import(\n  /* webpackFoo: 1 */\n  /* webpackBar: 2 */\n  \"path\",\n  { type: \"module\" }\n);\n")
   729  	expectPrinted(t, "import(\n    /* multi\n     * line\n     * webpackBar: */ 'path');", "import(\n  /* multi\n   * line\n   * webpackBar: */\n  \"path\"\n);\n")
   730  	expectPrinted(t, "import(/* webpackFoo: 1 */ 'path' /* webpackBar:2 */);", "import(\n  /* webpackFoo: 1 */\n  \"path\"\n  /* webpackBar:2 */\n);\n")
   731  	expectPrinted(t, "import(/* webpackFoo: 1 */ 'path' /* webpackBar:2 */ ,);", "import(\n  /* webpackFoo: 1 */\n  \"path\"\n);\n") // Not currently handled
   732  	expectPrinted(t, "import(/* webpackFoo: 1 */ 'path', /* webpackBar:2 */ );", "import(\n  /* webpackFoo: 1 */\n  \"path\"\n  /* webpackBar:2 */\n);\n")
   733  	expectPrinted(t, "import(/* webpackFoo: 1 */ 'path', { type: 'module' } /* webpackBar:2 */ );", "import(\n  /* webpackFoo: 1 */\n  \"path\",\n  { type: \"module\" }\n  /* webpackBar:2 */\n);\n")
   734  	expectPrinted(t, "import(new URL('path', /* webpackFoo: these can go anywhere */ import.meta.url))",
   735  		"import(new URL(\n  \"path\",\n  /* webpackFoo: these can go anywhere */\n  import.meta.url\n));\n")
   736  }
   737  
   738  func TestExportDefault(t *testing.T) {
   739  	expectPrinted(t, "export default function() {}", "export default function() {\n}\n")
   740  	expectPrinted(t, "export default function foo() {}", "export default function foo() {\n}\n")
   741  	expectPrinted(t, "export default async function() {}", "export default async function() {\n}\n")
   742  	expectPrinted(t, "export default async function foo() {}", "export default async function foo() {\n}\n")
   743  	expectPrinted(t, "export default class {}", "export default class {\n}\n")
   744  	expectPrinted(t, "export default class foo {}", "export default class foo {\n}\n")
   745  
   746  	expectPrinted(t, "export default (function() {})", "export default (function() {\n});\n")
   747  	expectPrinted(t, "export default (function foo() {})", "export default (function foo() {\n});\n")
   748  	expectPrinted(t, "export default (async function() {})", "export default (async function() {\n});\n")
   749  	expectPrinted(t, "export default (async function foo() {})", "export default (async function foo() {\n});\n")
   750  	expectPrinted(t, "export default (class {})", "export default (class {\n});\n")
   751  	expectPrinted(t, "export default (class foo {})", "export default (class foo {\n});\n")
   752  
   753  	expectPrinted(t, "export default (function() {}.toString())", "export default (function() {\n}).toString();\n")
   754  	expectPrinted(t, "export default (function foo() {}.toString())", "export default (function foo() {\n}).toString();\n")
   755  	expectPrinted(t, "export default (async function() {}.toString())", "export default (async function() {\n}).toString();\n")
   756  	expectPrinted(t, "export default (async function foo() {}.toString())", "export default (async function foo() {\n}).toString();\n")
   757  	expectPrinted(t, "export default (class {}.toString())", "export default (class {\n}).toString();\n")
   758  	expectPrinted(t, "export default (class foo {}.toString())", "export default (class foo {\n}).toString();\n")
   759  
   760  	expectPrintedMinify(t, "export default function() {}", "export default function(){}")
   761  	expectPrintedMinify(t, "export default function foo() {}", "export default function foo(){}")
   762  	expectPrintedMinify(t, "export default async function() {}", "export default async function(){}")
   763  	expectPrintedMinify(t, "export default async function foo() {}", "export default async function foo(){}")
   764  	expectPrintedMinify(t, "export default class {}", "export default class{}")
   765  	expectPrintedMinify(t, "export default class foo {}", "export default class foo{}")
   766  }
   767  
   768  func TestWhitespace(t *testing.T) {
   769  	expectPrinted(t, "- -x", "- -x;\n")
   770  	expectPrinted(t, "+ -x", "+-x;\n")
   771  	expectPrinted(t, "- +x", "-+x;\n")
   772  	expectPrinted(t, "+ +x", "+ +x;\n")
   773  	expectPrinted(t, "- --x", "- --x;\n")
   774  	expectPrinted(t, "+ --x", "+--x;\n")
   775  	expectPrinted(t, "- ++x", "-++x;\n")
   776  	expectPrinted(t, "+ ++x", "+ ++x;\n")
   777  
   778  	expectPrintedMinify(t, "- -x", "- -x;")
   779  	expectPrintedMinify(t, "+ -x", "+-x;")
   780  	expectPrintedMinify(t, "- +x", "-+x;")
   781  	expectPrintedMinify(t, "+ +x", "+ +x;")
   782  	expectPrintedMinify(t, "- --x", "- --x;")
   783  	expectPrintedMinify(t, "+ --x", "+--x;")
   784  	expectPrintedMinify(t, "- ++x", "-++x;")
   785  	expectPrintedMinify(t, "+ ++x", "+ ++x;")
   786  
   787  	expectPrintedMinify(t, "x - --y", "x- --y;")
   788  	expectPrintedMinify(t, "x + --y", "x+--y;")
   789  	expectPrintedMinify(t, "x - ++y", "x-++y;")
   790  	expectPrintedMinify(t, "x + ++y", "x+ ++y;")
   791  
   792  	expectPrintedMinify(t, "x-- > y", "x-- >y;")
   793  	expectPrintedMinify(t, "x < !--y", "x<! --y;")
   794  	expectPrintedMinify(t, "x > !--y", "x>!--y;")
   795  	expectPrintedMinify(t, "!--y", "!--y;")
   796  
   797  	expectPrintedMinify(t, "1 + -0", "1+-0;")
   798  	expectPrintedMinify(t, "1 - -0", "1- -0;")
   799  	expectPrintedMinify(t, "1 + -Infinity", "1+-Infinity;")
   800  	expectPrintedMinify(t, "1 - -Infinity", "1- -Infinity;")
   801  
   802  	expectPrintedMinify(t, "/x/ / /y/", "/x// /y/;")
   803  	expectPrintedMinify(t, "/x/ + Foo", "/x/+Foo;")
   804  	expectPrintedMinify(t, "/x/ instanceof Foo", "/x/ instanceof Foo;")
   805  	expectPrintedMinify(t, "[x] instanceof Foo", "[x]instanceof Foo;")
   806  
   807  	expectPrintedMinify(t, "throw x", "throw x;")
   808  	expectPrintedMinify(t, "throw typeof x", "throw typeof x;")
   809  	expectPrintedMinify(t, "throw delete x", "throw delete x;")
   810  	expectPrintedMinify(t, "throw function(){}", "throw function(){};")
   811  
   812  	expectPrintedMinify(t, "x in function(){}", "x in function(){};")
   813  	expectPrintedMinify(t, "x instanceof function(){}", "x instanceof function(){};")
   814  	expectPrintedMinify(t, "π in function(){}", "π in function(){};")
   815  	expectPrintedMinify(t, "π instanceof function(){}", "π instanceof function(){};")
   816  
   817  	expectPrintedMinify(t, "()=>({})", "()=>({});")
   818  	expectPrintedMinify(t, "()=>({}[1])", "()=>({})[1];")
   819  	expectPrintedMinify(t, "()=>({}+0)", "()=>\"[object Object]0\";")
   820  	expectPrintedMinify(t, "()=>function(){}", "()=>function(){};")
   821  
   822  	expectPrintedMinify(t, "(function(){})", "(function(){});")
   823  	expectPrintedMinify(t, "(class{})", "(class{});")
   824  	expectPrintedMinify(t, "({})", "({});")
   825  }
   826  
   827  func TestMangle(t *testing.T) {
   828  	expectPrintedMangle(t, "let x = '\\n'", "let x = `\n`;\n")
   829  	expectPrintedMangle(t, "let x = `\n`", "let x = `\n`;\n")
   830  	expectPrintedMangle(t, "let x = '\\n${}'", "let x = \"\\n${}\";\n")
   831  	expectPrintedMangle(t, "let x = `\n\\${}`", "let x = \"\\n${}\";\n")
   832  	expectPrintedMangle(t, "let x = `\n\\${}${y}\\${}`", "let x = `\n\\${}${y}\\${}`;\n")
   833  }
   834  
   835  func TestMinify(t *testing.T) {
   836  	expectPrintedMinify(t, "0.1", ".1;")
   837  	expectPrintedMinify(t, "1.2", "1.2;")
   838  
   839  	expectPrintedMinify(t, "() => {}", "()=>{};")
   840  	expectPrintedMinify(t, "(a) => {}", "a=>{};")
   841  	expectPrintedMinify(t, "(...a) => {}", "(...a)=>{};")
   842  	expectPrintedMinify(t, "(a = 0) => {}", "(a=0)=>{};")
   843  	expectPrintedMinify(t, "(a, b) => {}", "(a,b)=>{};")
   844  
   845  	expectPrinted(t, "true ** 2", "true ** 2;\n")
   846  	expectPrinted(t, "false ** 2", "false ** 2;\n")
   847  	expectPrintedMinify(t, "true ** 2", "true**2;")
   848  	expectPrintedMinify(t, "false ** 2", "false**2;")
   849  	expectPrintedMangle(t, "true ** 2", "(!0) ** 2;\n")
   850  	expectPrintedMangle(t, "false ** 2", "(!1) ** 2;\n")
   851  
   852  	expectPrintedMinify(t, "import a from 'path'", "import a from\"path\";")
   853  	expectPrintedMinify(t, "import * as ns from 'path'", "import*as ns from\"path\";")
   854  	expectPrintedMinify(t, "import {a, b as c} from 'path'", "import{a,b as c}from\"path\";")
   855  	expectPrintedMinify(t, "import {a, ' ' as c} from 'path'", "import{a,\" \"as c}from\"path\";")
   856  
   857  	expectPrintedMinify(t, "export * as ns from 'path'", "export*as ns from\"path\";")
   858  	expectPrintedMinify(t, "export * as ' ' from 'path'", "export*as\" \"from\"path\";")
   859  	expectPrintedMinify(t, "export {a, b as c} from 'path'", "export{a,b as c}from\"path\";")
   860  	expectPrintedMinify(t, "export {' ', '-' as ';'} from 'path'", "export{\" \",\"-\"as\";\"}from\"path\";")
   861  	expectPrintedMinify(t, "let a, b; export {a, b as c}", "let a,b;export{a,b as c};")
   862  	expectPrintedMinify(t, "let a, b; export {a, b as ' '}", "let a,b;export{a,b as\" \"};")
   863  
   864  	// Print some strings using template literals when minifying
   865  	expectPrinted(t, "x = '\\n'", "x = \"\\n\";\n")
   866  	expectPrintedMangle(t, "x = '\\n'", "x = `\n`;\n")
   867  	expectPrintedMangle(t, "x = {'\\n': 0}", "x = { \"\\n\": 0 };\n")
   868  	expectPrintedMangle(t, "x = class{'\\n' = 0}", "x = class {\n  \"\\n\" = 0;\n};\n")
   869  	expectPrintedMangle(t, "class Foo{'\\n' = 0}", "class Foo {\n  \"\\n\" = 0;\n}\n")
   870  
   871  	// Special identifiers must not be minified
   872  	expectPrintedMinify(t, "exports", "exports;")
   873  	expectPrintedMinify(t, "require", "require;")
   874  	expectPrintedMinify(t, "module", "module;")
   875  
   876  	// Comment statements must not affect their surroundings when minified
   877  	expectPrintedMinify(t, "//!single\nthrow 1 + 2", "//!single\nthrow 1+2;")
   878  	expectPrintedMinify(t, "/*!multi-\nline*/\nthrow 1 + 2", "/*!multi-\nline*/throw 1+2;")
   879  }
   880  
   881  func TestES5(t *testing.T) {
   882  	expectPrintedTargetMangle(t, 5, "foo('a\\n\\n\\nb')", "foo(\"a\\n\\n\\nb\");\n")
   883  	expectPrintedTargetMangle(t, 2015, "foo('a\\n\\n\\nb')", "foo(`a\n\n\nb`);\n")
   884  
   885  	expectPrintedTarget(t, 5, "foo({a, b})", "foo({ a: a, b: b });\n")
   886  	expectPrintedTarget(t, 2015, "foo({a, b})", "foo({ a, b });\n")
   887  
   888  	expectPrintedTarget(t, 5, "x => x", "(function(x) {\n  return x;\n});\n")
   889  	expectPrintedTarget(t, 2015, "x => x", "(x) => x;\n")
   890  
   891  	expectPrintedTarget(t, 5, "() => {}", "(function() {\n});\n")
   892  	expectPrintedTarget(t, 2015, "() => {}", "() => {\n};\n")
   893  
   894  	expectPrintedTargetMinify(t, 5, "x => x", "(function(x){return x});")
   895  	expectPrintedTargetMinify(t, 2015, "x => x", "x=>x;")
   896  
   897  	expectPrintedTargetMinify(t, 5, "() => {}", "(function(){});")
   898  	expectPrintedTargetMinify(t, 2015, "() => {}", "()=>{};")
   899  }
   900  
   901  func TestASCIIOnly(t *testing.T) {
   902  	expectPrinted(t, "let π = 'π'", "let π = \"π\";\n")
   903  	expectPrinted(t, "let π_ = 'π'", "let π_ = \"π\";\n")
   904  	expectPrinted(t, "let _π = 'π'", "let _π = \"π\";\n")
   905  	expectPrintedASCII(t, "let π = 'π'", "let \\u03C0 = \"\\u03C0\";\n")
   906  	expectPrintedASCII(t, "let π_ = 'π'", "let \\u03C0_ = \"\\u03C0\";\n")
   907  	expectPrintedASCII(t, "let _π = 'π'", "let _\\u03C0 = \"\\u03C0\";\n")
   908  
   909  	expectPrinted(t, "let 貓 = '🐈'", "let 貓 = \"🐈\";\n")
   910  	expectPrinted(t, "let 貓abc = '🐈'", "let 貓abc = \"🐈\";\n")
   911  	expectPrinted(t, "let abc貓 = '🐈'", "let abc貓 = \"🐈\";\n")
   912  	expectPrintedASCII(t, "let 貓 = '🐈'", "let \\u8C93 = \"\\u{1F408}\";\n")
   913  	expectPrintedASCII(t, "let 貓abc = '🐈'", "let \\u8C93abc = \"\\u{1F408}\";\n")
   914  	expectPrintedASCII(t, "let abc貓 = '🐈'", "let abc\\u8C93 = \"\\u{1F408}\";\n")
   915  
   916  	// Test a character outside the BMP
   917  	expectPrinted(t, "var 𐀀", "var 𐀀;\n")
   918  	expectPrinted(t, "var \\u{10000}", "var 𐀀;\n")
   919  	expectPrintedASCII(t, "var 𐀀", "var \\u{10000};\n")
   920  	expectPrintedASCII(t, "var \\u{10000}", "var \\u{10000};\n")
   921  	expectPrintedTargetASCII(t, 2015, "'𐀀'", "\"\\u{10000}\";\n")
   922  	expectPrintedTargetASCII(t, 5, "'𐀀'", "\"\\uD800\\uDC00\";\n")
   923  	expectPrintedTargetASCII(t, 2015, "x.𐀀", "x[\"\\u{10000}\"];\n")
   924  	expectPrintedTargetASCII(t, 5, "x.𐀀", "x[\"\\uD800\\uDC00\"];\n")
   925  
   926  	// Escapes should use consistent case
   927  	expectPrintedASCII(t, "var \\u{100a} = {\\u100A: '\\u100A'}", "var \\u100A = { \\u100A: \"\\u100A\" };\n")
   928  	expectPrintedASCII(t, "var \\u{1000a} = {\\u{1000A}: '\\u{1000A}'}", "var \\u{1000A} = { \"\\u{1000A}\": \"\\u{1000A}\" };\n")
   929  
   930  	// These characters should always be escaped
   931  	expectPrinted(t, "let x = '\u2028'", "let x = \"\\u2028\";\n")
   932  	expectPrinted(t, "let x = '\u2029'", "let x = \"\\u2029\";\n")
   933  	expectPrinted(t, "let x = '\uFEFF'", "let x = \"\\uFEFF\";\n")
   934  
   935  	// There should still be a space before "extends"
   936  	expectPrintedASCII(t, "class 𐀀 extends π {}", "class \\u{10000} extends \\u03C0 {\n}\n")
   937  	expectPrintedASCII(t, "(class 𐀀 extends π {})", "(class \\u{10000} extends \\u03C0 {\n});\n")
   938  	expectPrintedMinifyASCII(t, "class 𐀀 extends π {}", "class \\u{10000} extends \\u03C0{}")
   939  	expectPrintedMinifyASCII(t, "(class 𐀀 extends π {})", "(class \\u{10000} extends \\u03C0{});")
   940  }
   941  
   942  func TestJSX(t *testing.T) {
   943  	expectPrintedJSX(t, "<a/>", "<a />;\n")
   944  	expectPrintedJSX(t, "<A/>", "<A />;\n")
   945  	expectPrintedJSX(t, "<a.b/>", "<a.b />;\n")
   946  	expectPrintedJSX(t, "<A.B/>", "<A.B />;\n")
   947  	expectPrintedJSX(t, "<a-b/>", "<a-b />;\n")
   948  	expectPrintedJSX(t, "<a:b/>", "<a:b />;\n")
   949  	expectPrintedJSX(t, "<a></a>", "<a />;\n")
   950  	expectPrintedJSX(t, "<a b></a>", "<a b />;\n")
   951  
   952  	expectPrintedJSX(t, "<a b={true}></a>", "<a b={true} />;\n")
   953  	expectPrintedJSX(t, "<a b='x'></a>", "<a b='x' />;\n")
   954  	expectPrintedJSX(t, "<a b=\"x\"></a>", "<a b=\"x\" />;\n")
   955  	expectPrintedJSX(t, "<a b={'x'}></a>", "<a b={\"x\"} />;\n")
   956  	expectPrintedJSX(t, "<a b={`'`}></a>", "<a b={`'`} />;\n")
   957  	expectPrintedJSX(t, "<a b={`\"`}></a>", "<a b={`\"`} />;\n")
   958  	expectPrintedJSX(t, "<a b={`'\"`}></a>", "<a b={`'\"`} />;\n")
   959  	expectPrintedJSX(t, "<a b=\"&quot;\"></a>", "<a b=\"&quot;\" />;\n")
   960  	expectPrintedJSX(t, "<a b=\"&amp;\"></a>", "<a b=\"&amp;\" />;\n")
   961  
   962  	expectPrintedJSX(t, "<a>x</a>", "<a>x</a>;\n")
   963  	expectPrintedJSX(t, "<a>x\ny</a>", "<a>x\ny</a>;\n")
   964  	expectPrintedJSX(t, "<a>{'x'}{'y'}</a>", "<a>{\"x\"}{\"y\"}</a>;\n")
   965  	expectPrintedJSX(t, "<a> x</a>", "<a> x</a>;\n")
   966  	expectPrintedJSX(t, "<a>x </a>", "<a>x </a>;\n")
   967  	expectPrintedJSX(t, "<a>&#10;</a>", "<a>&#10;</a>;\n")
   968  	expectPrintedJSX(t, "<a>&amp;</a>", "<a>&amp;</a>;\n")
   969  	expectPrintedJSX(t, "<a>&lt;</a>", "<a>&lt;</a>;\n")
   970  	expectPrintedJSX(t, "<a>&gt;</a>", "<a>&gt;</a>;\n")
   971  	expectPrintedJSX(t, "<a>&#123;</a>", "<a>&#123;</a>;\n")
   972  	expectPrintedJSX(t, "<a>&#125;</a>", "<a>&#125;</a>;\n")
   973  
   974  	expectPrintedJSX(t, "<a><x/></a>", "<a><x /></a>;\n")
   975  	expectPrintedJSX(t, "<a><x/><y/></a>", "<a><x /><y /></a>;\n")
   976  	expectPrintedJSX(t, "<a>b<c/>d</a>", "<a>b<c />d</a>;\n")
   977  
   978  	expectPrintedJSX(t, "<></>", "<></>;\n")
   979  	expectPrintedJSX(t, "<>x<y/>z</>", "<>x<y />z</>;\n")
   980  
   981  	// JSX elements as JSX attribute values
   982  	expectPrintedJSX(t, "<a b=<c/>/>", "<a b=<c /> />;\n")
   983  	expectPrintedJSX(t, "<a b=<>c</>/>", "<a b=<>c</> />;\n")
   984  	expectPrintedJSX(t, "<a b=<>{c}</>/>", "<a b=<>{c}</> />;\n")
   985  	expectPrintedJSX(t, "<a b={<c/>}/>", "<a b={<c />} />;\n")
   986  	expectPrintedJSX(t, "<a b={<>c</>}/>", "<a b={<>c</>} />;\n")
   987  	expectPrintedJSX(t, "<a b={<>{c}</>}/>", "<a b={<>{c}</>} />;\n")
   988  
   989  	// These can't be escaped because JSX lacks a syntax for escapes
   990  	expectPrintedJSXASCII(t, "<π/>", "<π />;\n")
   991  	expectPrintedJSXASCII(t, "<π.𐀀/>", "<π.𐀀 />;\n")
   992  	expectPrintedJSXASCII(t, "<𐀀.π/>", "<𐀀.π />;\n")
   993  	expectPrintedJSXASCII(t, "<π>x</π>", "<π>x</π>;\n")
   994  	expectPrintedJSXASCII(t, "<𐀀>x</𐀀>", "<𐀀>x</𐀀>;\n")
   995  	expectPrintedJSXASCII(t, "<a π/>", "<a π />;\n")
   996  	expectPrintedJSXASCII(t, "<a 𐀀/>", "<a 𐀀 />;\n")
   997  
   998  	// JSX text is deliberately not printed as ASCII when JSX preservation is
   999  	// enabled. This is because:
  1000  	//
  1001  	// a) The JSX specification doesn't say how JSX text is supposed to be interpreted
  1002  	// b) Enabling JSX preservation means that JSX will be transformed again anyway
  1003  	// c) People do very weird/custom things with JSX that "preserve" shouldn't break
  1004  	//
  1005  	// See also: https://github.com/evanw/esbuild/issues/3605
  1006  	expectPrintedJSXASCII(t, "<a b='π'/>", "<a b='π' />;\n")
  1007  	expectPrintedJSXASCII(t, "<a b='𐀀'/>", "<a b='𐀀' />;\n")
  1008  	expectPrintedJSXASCII(t, "<a>π</a>", "<a>π</a>;\n")
  1009  	expectPrintedJSXASCII(t, "<a>𐀀</a>", "<a>𐀀</a>;\n")
  1010  
  1011  	expectPrintedJSXMinify(t, "<a b c={x,y} d='true'/>", "<a b c={(x,y)}d='true'/>;")
  1012  	expectPrintedJSXMinify(t, "<a><b/><c/></a>", "<a><b/><c/></a>;")
  1013  	expectPrintedJSXMinify(t, "<a> x <b/> y </a>", "<a> x <b/> y </a>;")
  1014  	expectPrintedJSXMinify(t, "<a>{' x '}{'<b/>'}{' y '}</a>", "<a>{\" x \"}{\"<b/>\"}{\" y \"}</a>;")
  1015  }
  1016  
  1017  func TestJSXSingleLine(t *testing.T) {
  1018  	expectPrintedJSX(t, "<x/>", "<x />;\n")
  1019  	expectPrintedJSX(t, "<x y/>", "<x y />;\n")
  1020  	expectPrintedJSX(t, "<x\n/>", "<x />;\n")
  1021  	expectPrintedJSX(t, "<x\ny/>", "<x\n  y\n/>;\n")
  1022  	expectPrintedJSX(t, "<x y\n/>", "<x\n  y\n/>;\n")
  1023  	expectPrintedJSX(t, "<x\n{...y}/>", "<x\n  {...y}\n/>;\n")
  1024  
  1025  	expectPrintedJSXMinify(t, "<x/>", "<x/>;")
  1026  	expectPrintedJSXMinify(t, "<x y/>", "<x y/>;")
  1027  	expectPrintedJSXMinify(t, "<x\n/>", "<x/>;")
  1028  	expectPrintedJSXMinify(t, "<x\ny/>", "<x y/>;")
  1029  	expectPrintedJSXMinify(t, "<x y\n/>", "<x y/>;")
  1030  	expectPrintedJSXMinify(t, "<x\n{...y}/>", "<x{...y}/>;")
  1031  }
  1032  
  1033  func TestAvoidSlashScript(t *testing.T) {
  1034  	// Positive cases
  1035  	expectPrinted(t, "x = '</script'", "x = \"<\\/script\";\n")
  1036  	expectPrinted(t, "x = `</script`", "x = `<\\/script`;\n")
  1037  	expectPrinted(t, "x = `</SCRIPT`", "x = `<\\/SCRIPT`;\n")
  1038  	expectPrinted(t, "x = `</ScRiPt`", "x = `<\\/ScRiPt`;\n")
  1039  	expectPrinted(t, "x = `</script${y}`", "x = `<\\/script${y}`;\n")
  1040  	expectPrinted(t, "x = `${y}</script`", "x = `${y}<\\/script`;\n")
  1041  	expectPrintedMinify(t, "x = 1 < /script/.exec(y).length", "x=1< /script/.exec(y).length;")
  1042  	expectPrintedMinify(t, "x = 1 < /SCRIPT/.exec(y).length", "x=1< /SCRIPT/.exec(y).length;")
  1043  	expectPrintedMinify(t, "x = 1 < /ScRiPt/.exec(y).length", "x=1< /ScRiPt/.exec(y).length;")
  1044  	expectPrintedMinify(t, "x = 1 << /script/.exec(y).length", "x=1<< /script/.exec(y).length;")
  1045  	expectPrinted(t, "//! </script\n//! >/script\n//! /script", "//! <\\/script\n//! >/script\n//! /script\n")
  1046  	expectPrinted(t, "//! </SCRIPT\n//! >/SCRIPT\n//! /SCRIPT", "//! <\\/SCRIPT\n//! >/SCRIPT\n//! /SCRIPT\n")
  1047  	expectPrinted(t, "//! </ScRiPt\n//! >/ScRiPt\n//! /ScRiPt", "//! <\\/ScRiPt\n//! >/ScRiPt\n//! /ScRiPt\n")
  1048  	expectPrinted(t, "/*! </script \n </script */", "/*! <\\/script \n <\\/script */\n")
  1049  	expectPrinted(t, "/*! </SCRIPT \n </SCRIPT */", "/*! <\\/SCRIPT \n <\\/SCRIPT */\n")
  1050  	expectPrinted(t, "/*! </ScRiPt \n </ScRiPt */", "/*! <\\/ScRiPt \n <\\/ScRiPt */\n")
  1051  	expectPrinted(t, "String.raw`</script`",
  1052  		"import { __template } from \"<runtime>\";\nvar _a;\nString.raw(_a || (_a = __template([\"<\\/script\"])));\n")
  1053  	expectPrinted(t, "String.raw`</script${a}`",
  1054  		"import { __template } from \"<runtime>\";\nvar _a;\nString.raw(_a || (_a = __template([\"<\\/script\", \"\"])), a);\n")
  1055  	expectPrinted(t, "String.raw`${a}</script`",
  1056  		"import { __template } from \"<runtime>\";\nvar _a;\nString.raw(_a || (_a = __template([\"\", \"<\\/script\"])), a);\n")
  1057  	expectPrinted(t, "String.raw`</SCRIPT`",
  1058  		"import { __template } from \"<runtime>\";\nvar _a;\nString.raw(_a || (_a = __template([\"<\\/SCRIPT\"])));\n")
  1059  	expectPrinted(t, "String.raw`</ScRiPt`",
  1060  		"import { __template } from \"<runtime>\";\nvar _a;\nString.raw(_a || (_a = __template([\"<\\/ScRiPt\"])));\n")
  1061  
  1062  	// Negative cases
  1063  	expectPrinted(t, "x = '</'", "x = \"</\";\n")
  1064  	expectPrinted(t, "x = '</ script'", "x = \"</ script\";\n")
  1065  	expectPrinted(t, "x = '< /script'", "x = \"< /script\";\n")
  1066  	expectPrinted(t, "x = '/script>'", "x = \"/script>\";\n")
  1067  	expectPrinted(t, "x = '<script>'", "x = \"<script>\";\n")
  1068  	expectPrintedMinify(t, "x = 1 < / script/.exec(y).length", "x=1</ script/.exec(y).length;")
  1069  	expectPrintedMinify(t, "x = 1 << / script/.exec(y).length", "x=1<</ script/.exec(y).length;")
  1070  }
  1071  
  1072  func TestInfinity(t *testing.T) {
  1073  	expectPrinted(t, "x = Infinity", "x = Infinity;\n")
  1074  	expectPrinted(t, "x = -Infinity", "x = -Infinity;\n")
  1075  	expectPrinted(t, "x = (Infinity).toString", "x = Infinity.toString;\n")
  1076  	expectPrinted(t, "x = (-Infinity).toString", "x = (-Infinity).toString;\n")
  1077  	expectPrinted(t, "x = (Infinity) ** 2", "x = Infinity ** 2;\n")
  1078  	expectPrinted(t, "x = (-Infinity) ** 2", "x = (-Infinity) ** 2;\n")
  1079  	expectPrinted(t, "x = ~Infinity", "x = ~Infinity;\n")
  1080  	expectPrinted(t, "x = ~-Infinity", "x = ~-Infinity;\n")
  1081  	expectPrinted(t, "x = Infinity * y", "x = Infinity * y;\n")
  1082  	expectPrinted(t, "x = Infinity / y", "x = Infinity / y;\n")
  1083  	expectPrinted(t, "x = y * Infinity", "x = y * Infinity;\n")
  1084  	expectPrinted(t, "x = y / Infinity", "x = y / Infinity;\n")
  1085  	expectPrinted(t, "throw Infinity", "throw Infinity;\n")
  1086  
  1087  	expectPrintedMinify(t, "x = Infinity", "x=Infinity;")
  1088  	expectPrintedMinify(t, "x = -Infinity", "x=-Infinity;")
  1089  	expectPrintedMinify(t, "x = (Infinity).toString", "x=Infinity.toString;")
  1090  	expectPrintedMinify(t, "x = (-Infinity).toString", "x=(-Infinity).toString;")
  1091  	expectPrintedMinify(t, "x = (Infinity) ** 2", "x=Infinity**2;")
  1092  	expectPrintedMinify(t, "x = (-Infinity) ** 2", "x=(-Infinity)**2;")
  1093  	expectPrintedMinify(t, "x = ~Infinity", "x=~Infinity;")
  1094  	expectPrintedMinify(t, "x = ~-Infinity", "x=~-Infinity;")
  1095  	expectPrintedMinify(t, "x = Infinity * y", "x=Infinity*y;")
  1096  	expectPrintedMinify(t, "x = Infinity / y", "x=Infinity/y;")
  1097  	expectPrintedMinify(t, "x = y * Infinity", "x=y*Infinity;")
  1098  	expectPrintedMinify(t, "x = y / Infinity", "x=y/Infinity;")
  1099  	expectPrintedMinify(t, "throw Infinity", "throw Infinity;")
  1100  
  1101  	expectPrintedMangle(t, "x = Infinity", "x = 1 / 0;\n")
  1102  	expectPrintedMangle(t, "x = -Infinity", "x = -1 / 0;\n")
  1103  	expectPrintedMangle(t, "x = (Infinity).toString", "x = (1 / 0).toString;\n")
  1104  	expectPrintedMangle(t, "x = (-Infinity).toString", "x = (-1 / 0).toString;\n")
  1105  	expectPrintedMangle(t, "x = Infinity ** 2", "x = (1 / 0) ** 2;\n")
  1106  	expectPrintedMangle(t, "x = (-Infinity) ** 2", "x = (-1 / 0) ** 2;\n")
  1107  	expectPrintedMangle(t, "x = Infinity * y", "x = 1 / 0 * y;\n")
  1108  	expectPrintedMangle(t, "x = Infinity / y", "x = 1 / 0 / y;\n")
  1109  	expectPrintedMangle(t, "x = y * Infinity", "x = y * (1 / 0);\n")
  1110  	expectPrintedMangle(t, "x = y / Infinity", "x = y / (1 / 0);\n")
  1111  	expectPrintedMangle(t, "throw Infinity", "throw 1 / 0;\n")
  1112  
  1113  	expectPrintedMangleMinify(t, "x = Infinity", "x=1/0;")
  1114  	expectPrintedMangleMinify(t, "x = -Infinity", "x=-1/0;")
  1115  	expectPrintedMangleMinify(t, "x = (Infinity).toString", "x=(1/0).toString;")
  1116  	expectPrintedMangleMinify(t, "x = (-Infinity).toString", "x=(-1/0).toString;")
  1117  	expectPrintedMangleMinify(t, "x = Infinity ** 2", "x=(1/0)**2;")
  1118  	expectPrintedMangleMinify(t, "x = (-Infinity) ** 2", "x=(-1/0)**2;")
  1119  	expectPrintedMangleMinify(t, "x = Infinity * y", "x=1/0*y;")
  1120  	expectPrintedMangleMinify(t, "x = Infinity / y", "x=1/0/y;")
  1121  	expectPrintedMangleMinify(t, "x = y * Infinity", "x=y*(1/0);")
  1122  	expectPrintedMangleMinify(t, "x = y / Infinity", "x=y/(1/0);")
  1123  	expectPrintedMangleMinify(t, "throw Infinity", "throw 1/0;")
  1124  }
  1125  
  1126  func TestBinaryOperatorVisitor(t *testing.T) {
  1127  	// Make sure the inner "/*b*/" comment doesn't disappear due to weird binary visitor stuff
  1128  	expectPrintedMangle(t, "x = (0, /*a*/ (0, /*b*/ (0, /*c*/ 1 == 2) + 3) * 4)", "x = /*a*/\n/*b*/\n(/*c*/\n!1 + 3) * 4;\n")
  1129  
  1130  	// Make sure deeply-nested ASTs don't cause a stack overflow
  1131  	x := "x = f()" + strings.Repeat(" || f()", 10_000) + ";\n"
  1132  	expectPrinted(t, x, x)
  1133  }
  1134  
  1135  // See: https://github.com/tc39/proposal-explicit-resource-management
  1136  func TestUsing(t *testing.T) {
  1137  	expectPrinted(t, "using x = y", "using x = y;\n")
  1138  	expectPrinted(t, "using x = y, z = _", "using x = y, z = _;\n")
  1139  	expectPrintedMinify(t, "using x = y", "using x=y;")
  1140  	expectPrintedMinify(t, "using x = y, z = _", "using x=y,z=_;")
  1141  
  1142  	expectPrinted(t, "await using x = y", "await using x = y;\n")
  1143  	expectPrinted(t, "await using x = y, z = _", "await using x = y, z = _;\n")
  1144  	expectPrintedMinify(t, "await using x = y", "await using x=y;")
  1145  	expectPrintedMinify(t, "await using x = y, z = _", "await using x=y,z=_;")
  1146  }