github.com/evanw/esbuild@v0.21.4/internal/bundler_tests/bundler_lower_test.go (about)

     1  package bundler_tests
     2  
     3  // This file contains tests for "lowering" syntax, which means converting it to
     4  // older JavaScript. For example, "a ** b" becomes a call to "Math.pow(a, b)"
     5  // when lowered. Which syntax is lowered is determined by the language target.
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/evanw/esbuild/internal/compat"
    11  	"github.com/evanw/esbuild/internal/config"
    12  )
    13  
    14  var lower_suite = suite{
    15  	name: "lower",
    16  }
    17  
    18  func TestLowerOptionalCatchNameCollisionNoBundle(t *testing.T) {
    19  	lower_suite.expectBundled(t, bundled{
    20  		files: map[string]string{
    21  			"/entry.js": `
    22  				try {}
    23  				catch { var e, e2 }
    24  				var e3
    25  			`,
    26  		},
    27  		entryPaths: []string{"/entry.js"},
    28  		options: config.Options{
    29  			UnsupportedJSFeatures: es(2018),
    30  			AbsOutputFile:         "/out.js",
    31  		},
    32  	})
    33  }
    34  
    35  func TestLowerObjectSpreadNoBundle(t *testing.T) {
    36  	lower_suite.expectBundled(t, bundled{
    37  		files: map[string]string{
    38  			"/entry.jsx": `
    39  				let tests = [
    40  					{...a, ...b},
    41  					{a, b, ...c},
    42  					{...a, b, c},
    43  					{a, ...b, c},
    44  					{a, b, ...c, ...d, e, f, ...g, ...h, i, j},
    45  				]
    46  				let jsx = [
    47  					<div {...a} {...b}/>,
    48  					<div a b {...c}/>,
    49  					<div {...a} b c/>,
    50  					<div a {...b} c/>,
    51  					<div a b {...c} {...d} e f {...g} {...h} i j/>,
    52  				]
    53  			`,
    54  		},
    55  		entryPaths: []string{"/entry.jsx"},
    56  		options: config.Options{
    57  			UnsupportedJSFeatures: es(2017),
    58  			AbsOutputFile:         "/out.js",
    59  		},
    60  	})
    61  }
    62  
    63  func TestLowerExponentiationOperatorNoBundle(t *testing.T) {
    64  	lower_suite.expectBundled(t, bundled{
    65  		files: map[string]string{
    66  			"/entry.js": `
    67  				let tests = {
    68  					// Exponentiation operator
    69  					0: a ** b ** c,
    70  					1: (a ** b) ** c,
    71  
    72  					// Exponentiation assignment operator
    73  					2: a **= b,
    74  					3: a.b **= c,
    75  					4: a[b] **= c,
    76  					5: a().b **= c,
    77  					6: a()[b] **= c,
    78  					7: a[b()] **= c,
    79  					8: a()[b()] **= c,
    80  
    81  					// These all should not need capturing (no object identity)
    82  					9: a[0] **= b,
    83  					10: a[false] **= b,
    84  					11: a[null] **= b,
    85  					12: a[void 0] **= b,
    86  					13: a[123n] **= b,
    87  					14: a[this] **= b,
    88  
    89  					// These should need capturing (have object identitiy)
    90  					15: a[/x/] **= b,
    91  					16: a[{}] **= b,
    92  					17: a[[]] **= b,
    93  					18: a[() => {}] **= b,
    94  					19: a[function() {}] **= b,
    95  				}
    96  			`,
    97  		},
    98  		entryPaths: []string{"/entry.js"},
    99  		options: config.Options{
   100  			UnsupportedJSFeatures: es(2015),
   101  			AbsOutputFile:         "/out.js",
   102  		},
   103  		expectedScanLog: `entry.js: ERROR: Big integer literals are not available in the configured target environment
   104  `,
   105  	})
   106  }
   107  
   108  func TestLowerPrivateFieldAssignments2015NoBundle(t *testing.T) {
   109  	lower_suite.expectBundled(t, bundled{
   110  		files: map[string]string{
   111  			"/entry.js": `
   112  				class Foo {
   113  					#x
   114  					unary() {
   115  						this.#x++
   116  						this.#x--
   117  						++this.#x
   118  						--this.#x
   119  					}
   120  					binary() {
   121  						this.#x = 1
   122  						this.#x += 1
   123  						this.#x -= 1
   124  						this.#x *= 1
   125  						this.#x /= 1
   126  						this.#x %= 1
   127  						this.#x **= 1
   128  						this.#x <<= 1
   129  						this.#x >>= 1
   130  						this.#x >>>= 1
   131  						this.#x &= 1
   132  						this.#x |= 1
   133  						this.#x ^= 1
   134  						this.#x &&= 1
   135  						this.#x ||= 1
   136  						this.#x ??= 1
   137  					}
   138  				}
   139  			`,
   140  		},
   141  		entryPaths: []string{"/entry.js"},
   142  		options: config.Options{
   143  			UnsupportedJSFeatures: es(2015),
   144  			AbsOutputFile:         "/out.js",
   145  		},
   146  	})
   147  }
   148  
   149  func TestLowerPrivateFieldAssignments2019NoBundle(t *testing.T) {
   150  	lower_suite.expectBundled(t, bundled{
   151  		files: map[string]string{
   152  			"/entry.js": `
   153  				class Foo {
   154  					#x
   155  					unary() {
   156  						this.#x++
   157  						this.#x--
   158  						++this.#x
   159  						--this.#x
   160  					}
   161  					binary() {
   162  						this.#x = 1
   163  						this.#x += 1
   164  						this.#x -= 1
   165  						this.#x *= 1
   166  						this.#x /= 1
   167  						this.#x %= 1
   168  						this.#x **= 1
   169  						this.#x <<= 1
   170  						this.#x >>= 1
   171  						this.#x >>>= 1
   172  						this.#x &= 1
   173  						this.#x |= 1
   174  						this.#x ^= 1
   175  						this.#x &&= 1
   176  						this.#x ||= 1
   177  						this.#x ??= 1
   178  					}
   179  				}
   180  			`,
   181  		},
   182  		entryPaths: []string{"/entry.js"},
   183  		options: config.Options{
   184  			UnsupportedJSFeatures: es(2019),
   185  			AbsOutputFile:         "/out.js",
   186  		},
   187  	})
   188  }
   189  
   190  func TestLowerPrivateFieldAssignments2020NoBundle(t *testing.T) {
   191  	lower_suite.expectBundled(t, bundled{
   192  		files: map[string]string{
   193  			"/entry.js": `
   194  				class Foo {
   195  					#x
   196  					unary() {
   197  						this.#x++
   198  						this.#x--
   199  						++this.#x
   200  						--this.#x
   201  					}
   202  					binary() {
   203  						this.#x = 1
   204  						this.#x += 1
   205  						this.#x -= 1
   206  						this.#x *= 1
   207  						this.#x /= 1
   208  						this.#x %= 1
   209  						this.#x **= 1
   210  						this.#x <<= 1
   211  						this.#x >>= 1
   212  						this.#x >>>= 1
   213  						this.#x &= 1
   214  						this.#x |= 1
   215  						this.#x ^= 1
   216  						this.#x &&= 1
   217  						this.#x ||= 1
   218  						this.#x ??= 1
   219  					}
   220  				}
   221  			`,
   222  		},
   223  		entryPaths: []string{"/entry.js"},
   224  		options: config.Options{
   225  			UnsupportedJSFeatures: es(2020),
   226  			AbsOutputFile:         "/out.js",
   227  		},
   228  	})
   229  }
   230  
   231  func TestLowerPrivateFieldAssignmentsNextNoBundle(t *testing.T) {
   232  	lower_suite.expectBundled(t, bundled{
   233  		files: map[string]string{
   234  			"/entry.js": `
   235  				class Foo {
   236  					#x
   237  					unary() {
   238  						this.#x++
   239  						this.#x--
   240  						++this.#x
   241  						--this.#x
   242  					}
   243  					binary() {
   244  						this.#x = 1
   245  						this.#x += 1
   246  						this.#x -= 1
   247  						this.#x *= 1
   248  						this.#x /= 1
   249  						this.#x %= 1
   250  						this.#x **= 1
   251  						this.#x <<= 1
   252  						this.#x >>= 1
   253  						this.#x >>>= 1
   254  						this.#x &= 1
   255  						this.#x |= 1
   256  						this.#x ^= 1
   257  						this.#x &&= 1
   258  						this.#x ||= 1
   259  						this.#x ??= 1
   260  					}
   261  				}
   262  			`,
   263  		},
   264  		entryPaths: []string{"/entry.js"},
   265  		options: config.Options{
   266  			AbsOutputFile: "/out.js",
   267  		},
   268  	})
   269  }
   270  
   271  func TestLowerPrivateFieldOptionalChain2019NoBundle(t *testing.T) {
   272  	lower_suite.expectBundled(t, bundled{
   273  		files: map[string]string{
   274  			"/entry.js": `
   275  				class Foo {
   276  					#x
   277  					foo() {
   278  						this?.#x.y
   279  						this?.y.#x
   280  						this.#x?.y
   281  					}
   282  				}
   283  			`,
   284  		},
   285  		entryPaths: []string{"/entry.js"},
   286  		options: config.Options{
   287  			UnsupportedJSFeatures: es(2019),
   288  			AbsOutputFile:         "/out.js",
   289  		},
   290  	})
   291  }
   292  
   293  func TestLowerPrivateFieldOptionalChain2020NoBundle(t *testing.T) {
   294  	lower_suite.expectBundled(t, bundled{
   295  		files: map[string]string{
   296  			"/entry.js": `
   297  				class Foo {
   298  					#x
   299  					foo() {
   300  						this?.#x.y
   301  						this?.y.#x
   302  						this.#x?.y
   303  					}
   304  				}
   305  			`,
   306  		},
   307  		entryPaths: []string{"/entry.js"},
   308  		options: config.Options{
   309  			UnsupportedJSFeatures: es(2020),
   310  			AbsOutputFile:         "/out.js",
   311  		},
   312  	})
   313  }
   314  
   315  func TestLowerPrivateFieldOptionalChainNextNoBundle(t *testing.T) {
   316  	lower_suite.expectBundled(t, bundled{
   317  		files: map[string]string{
   318  			"/entry.js": `
   319  				class Foo {
   320  					#x
   321  					foo() {
   322  						this?.#x.y
   323  						this?.y.#x
   324  						this.#x?.y
   325  					}
   326  				}
   327  			`,
   328  		},
   329  		entryPaths: []string{"/entry.js"},
   330  		options: config.Options{
   331  			AbsOutputFile: "/out.js",
   332  		},
   333  	})
   334  }
   335  
   336  func TestTSLowerPrivateFieldOptionalChain2015NoBundle(t *testing.T) {
   337  	lower_suite.expectBundled(t, bundled{
   338  		files: map[string]string{
   339  			"/entry.ts": `
   340  				class Foo {
   341  					#x
   342  					foo() {
   343  						this?.#x.y
   344  						this?.y.#x
   345  						this.#x?.y
   346  					}
   347  				}
   348  			`,
   349  		},
   350  		entryPaths: []string{"/entry.ts"},
   351  		options: config.Options{
   352  			UnsupportedJSFeatures: es(2015),
   353  			AbsOutputFile:         "/out.js",
   354  		},
   355  	})
   356  }
   357  
   358  func TestTSLowerPrivateStaticMembers2015NoBundle(t *testing.T) {
   359  	lower_suite.expectBundled(t, bundled{
   360  		files: map[string]string{
   361  			"/entry.ts": `
   362  				class Foo {
   363  					static #x
   364  					static get #y() {}
   365  					static set #y(x) {}
   366  					static #z() {}
   367  					foo() {
   368  						Foo.#x += 1
   369  						Foo.#y += 1
   370  						Foo.#z()
   371  					}
   372  				}
   373  			`,
   374  		},
   375  		entryPaths: []string{"/entry.ts"},
   376  		options: config.Options{
   377  			UnsupportedJSFeatures: es(2015),
   378  			AbsOutputFile:         "/out.js",
   379  		},
   380  	})
   381  }
   382  
   383  func TestTSLowerPrivateFieldAndMethodAvoidNameCollision2015(t *testing.T) {
   384  	lower_suite.expectBundled(t, bundled{
   385  		files: map[string]string{
   386  			"/entry.ts": `
   387  				export class WeakMap {
   388  					#x
   389  				}
   390  				export class WeakSet {
   391  					#y() {}
   392  				}
   393  			`,
   394  		},
   395  		entryPaths: []string{"/entry.ts"},
   396  		options: config.Options{
   397  			Mode:                  config.ModeBundle,
   398  			UnsupportedJSFeatures: es(2015),
   399  			AbsOutputFile:         "/out.js",
   400  		},
   401  	})
   402  }
   403  
   404  func TestLowerPrivateGetterSetter2015(t *testing.T) {
   405  	lower_suite.expectBundled(t, bundled{
   406  		files: map[string]string{
   407  			"/entry.js": `
   408  				export class Foo {
   409  					get #foo() { return this.foo }
   410  					set #bar(val) { this.bar = val }
   411  					get #prop() { return this.prop }
   412  					set #prop(val) { this.prop = val }
   413  					foo(fn) {
   414  						fn().#foo
   415  						fn().#bar = 1
   416  						fn().#prop
   417  						fn().#prop = 2
   418  					}
   419  					unary(fn) {
   420  						fn().#prop++;
   421  						fn().#prop--;
   422  						++fn().#prop;
   423  						--fn().#prop;
   424  					}
   425  					binary(fn) {
   426  						fn().#prop = 1;
   427  						fn().#prop += 1;
   428  						fn().#prop -= 1;
   429  						fn().#prop *= 1;
   430  						fn().#prop /= 1;
   431  						fn().#prop %= 1;
   432  						fn().#prop **= 1;
   433  						fn().#prop <<= 1;
   434  						fn().#prop >>= 1;
   435  						fn().#prop >>>= 1;
   436  						fn().#prop &= 1;
   437  						fn().#prop |= 1;
   438  						fn().#prop ^= 1;
   439  						fn().#prop &&= 1;
   440  						fn().#prop ||= 1;
   441  						fn().#prop ??= 1;
   442  					}
   443  				}
   444  			`,
   445  		},
   446  		entryPaths: []string{"/entry.js"},
   447  		options: config.Options{
   448  			Mode:                  config.ModeBundle,
   449  			UnsupportedJSFeatures: es(2015),
   450  			AbsOutputFile:         "/out.js",
   451  		},
   452  	})
   453  }
   454  
   455  func TestLowerPrivateGetterSetter2019(t *testing.T) {
   456  	lower_suite.expectBundled(t, bundled{
   457  		files: map[string]string{
   458  			"/entry.js": `
   459  				export class Foo {
   460  					get #foo() { return this.foo }
   461  					set #bar(val) { this.bar = val }
   462  					get #prop() { return this.prop }
   463  					set #prop(val) { this.prop = val }
   464  					foo(fn) {
   465  						fn().#foo
   466  						fn().#bar = 1
   467  						fn().#prop
   468  						fn().#prop = 2
   469  					}
   470  					unary(fn) {
   471  						fn().#prop++;
   472  						fn().#prop--;
   473  						++fn().#prop;
   474  						--fn().#prop;
   475  					}
   476  					binary(fn) {
   477  						fn().#prop = 1;
   478  						fn().#prop += 1;
   479  						fn().#prop -= 1;
   480  						fn().#prop *= 1;
   481  						fn().#prop /= 1;
   482  						fn().#prop %= 1;
   483  						fn().#prop **= 1;
   484  						fn().#prop <<= 1;
   485  						fn().#prop >>= 1;
   486  						fn().#prop >>>= 1;
   487  						fn().#prop &= 1;
   488  						fn().#prop |= 1;
   489  						fn().#prop ^= 1;
   490  						fn().#prop &&= 1;
   491  						fn().#prop ||= 1;
   492  						fn().#prop ??= 1;
   493  					}
   494  				}
   495  			`,
   496  		},
   497  		entryPaths: []string{"/entry.js"},
   498  		options: config.Options{
   499  			Mode:                  config.ModeBundle,
   500  			UnsupportedJSFeatures: es(2019),
   501  			AbsOutputFile:         "/out.js",
   502  		},
   503  	})
   504  }
   505  
   506  func TestLowerPrivateGetterSetter2020(t *testing.T) {
   507  	lower_suite.expectBundled(t, bundled{
   508  		files: map[string]string{
   509  			"/entry.js": `
   510  				export class Foo {
   511  					get #foo() { return this.foo }
   512  					set #bar(val) { this.bar = val }
   513  					get #prop() { return this.prop }
   514  					set #prop(val) { this.prop = val }
   515  					foo(fn) {
   516  						fn().#foo
   517  						fn().#bar = 1
   518  						fn().#prop
   519  						fn().#prop = 2
   520  					}
   521  					unary(fn) {
   522  						fn().#prop++;
   523  						fn().#prop--;
   524  						++fn().#prop;
   525  						--fn().#prop;
   526  					}
   527  					binary(fn) {
   528  						fn().#prop = 1;
   529  						fn().#prop += 1;
   530  						fn().#prop -= 1;
   531  						fn().#prop *= 1;
   532  						fn().#prop /= 1;
   533  						fn().#prop %= 1;
   534  						fn().#prop **= 1;
   535  						fn().#prop <<= 1;
   536  						fn().#prop >>= 1;
   537  						fn().#prop >>>= 1;
   538  						fn().#prop &= 1;
   539  						fn().#prop |= 1;
   540  						fn().#prop ^= 1;
   541  						fn().#prop &&= 1;
   542  						fn().#prop ||= 1;
   543  						fn().#prop ??= 1;
   544  					}
   545  				}
   546  			`,
   547  		},
   548  		entryPaths: []string{"/entry.js"},
   549  		options: config.Options{
   550  			Mode:                  config.ModeBundle,
   551  			UnsupportedJSFeatures: es(2020),
   552  			AbsOutputFile:         "/out.js",
   553  		},
   554  	})
   555  }
   556  
   557  func TestLowerPrivateGetterSetterNext(t *testing.T) {
   558  	lower_suite.expectBundled(t, bundled{
   559  		files: map[string]string{
   560  			"/entry.js": `
   561  				export class Foo {
   562  					get #foo() { return this.foo }
   563  					set #bar(val) { this.bar = val }
   564  					get #prop() { return this.prop }
   565  					set #prop(val) { this.prop = val }
   566  					foo(fn) {
   567  						fn().#foo
   568  						fn().#bar = 1
   569  						fn().#prop
   570  						fn().#prop = 2
   571  					}
   572  					unary(fn) {
   573  						fn().#prop++;
   574  						fn().#prop--;
   575  						++fn().#prop;
   576  						--fn().#prop;
   577  					}
   578  					binary(fn) {
   579  						fn().#prop = 1;
   580  						fn().#prop += 1;
   581  						fn().#prop -= 1;
   582  						fn().#prop *= 1;
   583  						fn().#prop /= 1;
   584  						fn().#prop %= 1;
   585  						fn().#prop **= 1;
   586  						fn().#prop <<= 1;
   587  						fn().#prop >>= 1;
   588  						fn().#prop >>>= 1;
   589  						fn().#prop &= 1;
   590  						fn().#prop |= 1;
   591  						fn().#prop ^= 1;
   592  						fn().#prop &&= 1;
   593  						fn().#prop ||= 1;
   594  						fn().#prop ??= 1;
   595  					}
   596  				}
   597  			`,
   598  		},
   599  		entryPaths: []string{"/entry.js"},
   600  		options: config.Options{
   601  			Mode:          config.ModeBundle,
   602  			AbsOutputFile: "/out.js",
   603  		},
   604  	})
   605  }
   606  
   607  func TestLowerPrivateMethod2019(t *testing.T) {
   608  	lower_suite.expectBundled(t, bundled{
   609  		files: map[string]string{
   610  			"/entry.js": `
   611  				export class Foo {
   612  					#field
   613  					#method() {}
   614  					baseline() {
   615  						a().foo
   616  						b().foo(x)
   617  						c()?.foo(x)
   618  						d().foo?.(x)
   619  						e()?.foo?.(x)
   620  					}
   621  					privateField() {
   622  						a().#field
   623  						b().#field(x)
   624  						c()?.#field(x)
   625  						d().#field?.(x)
   626  						e()?.#field?.(x)
   627  						f()?.foo.#field(x).bar()
   628  					}
   629  					privateMethod() {
   630  						a().#method
   631  						b().#method(x)
   632  						c()?.#method(x)
   633  						d().#method?.(x)
   634  						e()?.#method?.(x)
   635  						f()?.foo.#method(x).bar()
   636  					}
   637  				}
   638  			`,
   639  		},
   640  		entryPaths: []string{"/entry.js"},
   641  		options: config.Options{
   642  			Mode:                  config.ModeBundle,
   643  			UnsupportedJSFeatures: es(2019),
   644  			AbsOutputFile:         "/out.js",
   645  		},
   646  	})
   647  }
   648  
   649  func TestLowerPrivateMethod2020(t *testing.T) {
   650  	lower_suite.expectBundled(t, bundled{
   651  		files: map[string]string{
   652  			"/entry.js": `
   653  				export class Foo {
   654  					#field
   655  					#method() {}
   656  					baseline() {
   657  						a().foo
   658  						b().foo(x)
   659  						c()?.foo(x)
   660  						d().foo?.(x)
   661  						e()?.foo?.(x)
   662  					}
   663  					privateField() {
   664  						a().#field
   665  						b().#field(x)
   666  						c()?.#field(x)
   667  						d().#field?.(x)
   668  						e()?.#field?.(x)
   669  						f()?.foo.#field(x).bar()
   670  					}
   671  					privateMethod() {
   672  						a().#method
   673  						b().#method(x)
   674  						c()?.#method(x)
   675  						d().#method?.(x)
   676  						e()?.#method?.(x)
   677  						f()?.foo.#method(x).bar()
   678  					}
   679  				}
   680  			`,
   681  		},
   682  		entryPaths: []string{"/entry.js"},
   683  		options: config.Options{
   684  			Mode:                  config.ModeBundle,
   685  			UnsupportedJSFeatures: es(2020),
   686  			AbsOutputFile:         "/out.js",
   687  		},
   688  	})
   689  }
   690  
   691  func TestLowerPrivateMethodNext(t *testing.T) {
   692  	lower_suite.expectBundled(t, bundled{
   693  		files: map[string]string{
   694  			"/entry.js": `
   695  				export class Foo {
   696  					#field
   697  					#method() {}
   698  					baseline() {
   699  						a().foo
   700  						b().foo(x)
   701  						c()?.foo(x)
   702  						d().foo?.(x)
   703  						e()?.foo?.(x)
   704  					}
   705  					privateField() {
   706  						a().#field
   707  						b().#field(x)
   708  						c()?.#field(x)
   709  						d().#field?.(x)
   710  						e()?.#field?.(x)
   711  						f()?.foo.#field(x).bar()
   712  					}
   713  					privateMethod() {
   714  						a().#method
   715  						b().#method(x)
   716  						c()?.#method(x)
   717  						d().#method?.(x)
   718  						e()?.#method?.(x)
   719  						f()?.foo.#method(x).bar()
   720  					}
   721  				}
   722  			`,
   723  		},
   724  		entryPaths: []string{"/entry.js"},
   725  		options: config.Options{
   726  			Mode:          config.ModeBundle,
   727  			AbsOutputFile: "/out.js",
   728  		},
   729  	})
   730  }
   731  
   732  func TestLowerPrivateClassExpr2020NoBundle(t *testing.T) {
   733  	lower_suite.expectBundled(t, bundled{
   734  		files: map[string]string{
   735  			"/entry.js": `
   736  				export let Foo = class {
   737  					#field
   738  					#method() {}
   739  					static #staticField
   740  					static #staticMethod() {}
   741  					foo() {
   742  						this.#field = this.#method()
   743  						Foo.#staticField = Foo.#staticMethod()
   744  					}
   745  				}
   746  			`,
   747  		},
   748  		entryPaths: []string{"/entry.js"},
   749  		options: config.Options{
   750  			UnsupportedJSFeatures: es(2020),
   751  			AbsOutputFile:         "/out.js",
   752  		},
   753  	})
   754  }
   755  
   756  func TestLowerPrivateMethodWithModifiers2020(t *testing.T) {
   757  	lower_suite.expectBundled(t, bundled{
   758  		files: map[string]string{
   759  			"/entry.js": `
   760  				export class Foo {
   761  					*#g() {}
   762  					async #a() {}
   763  					async *#ag() {}
   764  
   765  					static *#sg() {}
   766  					static async #sa() {}
   767  					static async *#sag() {}
   768  				}
   769  			`,
   770  		},
   771  		entryPaths: []string{"/entry.js"},
   772  		options: config.Options{
   773  			Mode:                  config.ModeBundle,
   774  			UnsupportedJSFeatures: es(2020),
   775  			AbsOutputFile:         "/out.js",
   776  		},
   777  	})
   778  }
   779  
   780  func TestLowerAsync2016NoBundle(t *testing.T) {
   781  	lower_suite.expectBundled(t, bundled{
   782  		files: map[string]string{
   783  			"/entry.js": `
   784  				async function foo(bar) {
   785  					await bar
   786  					return [this, arguments]
   787  				}
   788  				class Foo {async foo() {}}
   789  				export default [
   790  					foo,
   791  					Foo,
   792  					async function() {},
   793  					async () => {},
   794  					{async foo() {}},
   795  					class {async foo() {}},
   796  					function() {
   797  						return async (bar) => {
   798  							await bar
   799  							return [this, arguments]
   800  						}
   801  					},
   802  				]
   803  			`,
   804  		},
   805  		entryPaths: []string{"/entry.js"},
   806  		options: config.Options{
   807  			UnsupportedJSFeatures: es(2016),
   808  			AbsOutputFile:         "/out.js",
   809  		},
   810  	})
   811  }
   812  
   813  func TestLowerAsync2017NoBundle(t *testing.T) {
   814  	lower_suite.expectBundled(t, bundled{
   815  		files: map[string]string{
   816  			"/entry.js": `
   817  				async function foo(bar) {
   818  					await bar
   819  					return arguments
   820  				}
   821  				class Foo {async foo() {}}
   822  				export default [
   823  					foo,
   824  					Foo,
   825  					async function() {},
   826  					async () => {},
   827  					{async foo() {}},
   828  					class {async foo() {}},
   829  					function() {
   830  						return async (bar) => {
   831  							await bar
   832  							return [this, arguments]
   833  						}
   834  					},
   835  				]
   836  			`,
   837  		},
   838  		entryPaths: []string{"/entry.js"},
   839  		options: config.Options{
   840  			UnsupportedJSFeatures: es(2017),
   841  			AbsOutputFile:         "/out.js",
   842  		},
   843  	})
   844  }
   845  
   846  func TestLowerAsyncThis2016CommonJS(t *testing.T) {
   847  	lower_suite.expectBundled(t, bundled{
   848  		files: map[string]string{
   849  			"/entry.js": `
   850  				exports.foo = async () => this
   851  			`,
   852  		},
   853  		entryPaths: []string{"/entry.js"},
   854  		options: config.Options{
   855  			Mode:                  config.ModeBundle,
   856  			UnsupportedJSFeatures: es(2016),
   857  			AbsOutputFile:         "/out.js",
   858  		},
   859  	})
   860  }
   861  
   862  func TestLowerAsyncThis2016ES6(t *testing.T) {
   863  	lower_suite.expectBundled(t, bundled{
   864  		files: map[string]string{
   865  			"/entry.js": `
   866  				export {bar} from "./other"
   867  				export let foo = async () => this
   868  			`,
   869  			"/other.js": `
   870  				export let bar = async () => {}
   871  			`,
   872  		},
   873  		entryPaths: []string{"/entry.js"},
   874  		options: config.Options{
   875  			Mode:                  config.ModeBundle,
   876  			UnsupportedJSFeatures: es(2016),
   877  			AbsOutputFile:         "/out.js",
   878  		},
   879  		debugLogs: true,
   880  		expectedScanLog: `entry.js: DEBUG: Top-level "this" will be replaced with undefined since this file is an ECMAScript module
   881  entry.js: NOTE: This file is considered to be an ECMAScript module because of the "export" keyword here:
   882  `,
   883  	})
   884  }
   885  
   886  func TestLowerAsyncES5(t *testing.T) {
   887  	lower_suite.expectBundled(t, bundled{
   888  		files: map[string]string{
   889  			"/entry.js": `
   890  				import './fn-stmt'
   891  				import './fn-expr'
   892  				import './arrow-1'
   893  				import './arrow-2'
   894  				import './export-def-1'
   895  				import './export-def-2'
   896  				import './obj-method'
   897  			`,
   898  			"/fn-stmt.js":      `async function foo() {}`,
   899  			"/fn-expr.js":      `(async function() {})`,
   900  			"/arrow-1.js":      `(async () => {})`,
   901  			"/arrow-2.js":      `(async x => {})`,
   902  			"/export-def-1.js": `export default async function foo() {}`,
   903  			"/export-def-2.js": `export default async function() {}`,
   904  			"/obj-method.js":   `({async foo() {}})`,
   905  		},
   906  		entryPaths: []string{"/entry.js"},
   907  		options: config.Options{
   908  			Mode:                  config.ModeBundle,
   909  			UnsupportedJSFeatures: es(5),
   910  			AbsOutputFile:         "/out.js",
   911  		},
   912  		expectedScanLog: `arrow-1.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   913  arrow-2.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   914  export-def-1.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   915  export-def-2.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   916  fn-expr.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   917  fn-stmt.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   918  obj-method.js: ERROR: Transforming async functions to the configured target environment is not supported yet
   919  `,
   920  	})
   921  }
   922  
   923  func TestLowerAsyncSuperES2017NoBundle(t *testing.T) {
   924  	lower_suite.expectBundled(t, bundled{
   925  		files: map[string]string{
   926  			"/entry.js": `
   927  				class Derived extends Base {
   928  					async test(key) {
   929  						return [
   930  							await super.foo,
   931  							await super[key],
   932  							await ([super.foo] = [0]),
   933  							await ([super[key]] = [0]),
   934  
   935  							await (super.foo = 1),
   936  							await (super[key] = 1),
   937  							await (super.foo += 2),
   938  							await (super[key] += 2),
   939  
   940  							await ++super.foo,
   941  							await ++super[key],
   942  							await super.foo++,
   943  							await super[key]++,
   944  
   945  							await super.foo.name,
   946  							await super[key].name,
   947  							await super.foo?.name,
   948  							await super[key]?.name,
   949  
   950  							await super.foo(1, 2),
   951  							await super[key](1, 2),
   952  							await super.foo?.(1, 2),
   953  							await super[key]?.(1, 2),
   954  
   955  							await (() => super.foo)(),
   956  							await (() => super[key])(),
   957  							await (() => super.foo())(),
   958  							await (() => super[key]())(),
   959  
   960  							await super.foo` + "``" + `,
   961  							await super[key]` + "``" + `,
   962  						]
   963  					}
   964  				}
   965  
   966  				// This covers a bug that caused a compiler crash
   967  				let fn = async () => class extends Base {
   968  					a = super.a
   969  					b = () => super.b
   970  					c() { return super.c }
   971  					d() { return () => super.d }
   972  				}
   973  
   974  				// This covers a bug that generated bad code
   975  				class Derived2 extends Base {
   976  					async a() { return class { [super.foo] = 123 } }
   977  					b = async () => class { [super.foo] = 123 }
   978  				}
   979  
   980  				// This covers putting the generated temporary variable inside the loop
   981  				for (let i = 0; i < 3; i++) {
   982  					objs.push({
   983  						__proto__: {
   984  							foo() { return i },
   985  						},
   986  						async bar() { return super.foo() },
   987  					})
   988  				}
   989  			`,
   990  		},
   991  		entryPaths: []string{"/entry.js"},
   992  		options: config.Options{
   993  			UnsupportedJSFeatures: es(2017),
   994  			AbsOutputFile:         "/out.js",
   995  		},
   996  	})
   997  }
   998  
   999  func TestLowerAsyncSuperES2016NoBundle(t *testing.T) {
  1000  	lower_suite.expectBundled(t, bundled{
  1001  		files: map[string]string{
  1002  			"/entry.js": `
  1003  				class Derived extends Base {
  1004  					async test(key) {
  1005  						return [
  1006  							await super.foo,
  1007  							await super[key],
  1008  							await ([super.foo] = [0]),
  1009  							await ([super[key]] = [0]),
  1010  
  1011  							await (super.foo = 1),
  1012  							await (super[key] = 1),
  1013  							await (super.foo += 2),
  1014  							await (super[key] += 2),
  1015  
  1016  							await ++super.foo,
  1017  							await ++super[key],
  1018  							await super.foo++,
  1019  							await super[key]++,
  1020  
  1021  							await super.foo.name,
  1022  							await super[key].name,
  1023  							await super.foo?.name,
  1024  							await super[key]?.name,
  1025  
  1026  							await super.foo(1, 2),
  1027  							await super[key](1, 2),
  1028  							await super.foo?.(1, 2),
  1029  							await super[key]?.(1, 2),
  1030  
  1031  							await (() => super.foo)(),
  1032  							await (() => super[key])(),
  1033  							await (() => super.foo())(),
  1034  							await (() => super[key]())(),
  1035  
  1036  							await super.foo` + "``" + `,
  1037  							await super[key]` + "``" + `,
  1038  						]
  1039  					}
  1040  				}
  1041  
  1042  				// This covers a bug that caused a compiler crash
  1043  				let fn = async () => class extends Base {
  1044  					a = super.a
  1045  					b = () => super.b
  1046  					c() { return super.c }
  1047  					d() { return () => super.d }
  1048  				}
  1049  
  1050  				// This covers a bug that generated bad code
  1051  				class Derived2 extends Base {
  1052  					async a() { return class { [super.foo] = 123 } }
  1053  					b = async () => class { [super.foo] = 123 }
  1054  				}
  1055  
  1056  				// This covers putting the generated temporary variable inside the loop
  1057  				for (let i = 0; i < 3; i++) {
  1058  					objs.push({
  1059  						__proto__: {
  1060  							foo() { return i },
  1061  						},
  1062  						async bar() { return super.foo() },
  1063  					})
  1064  				}
  1065  			`,
  1066  		},
  1067  		entryPaths: []string{"/entry.js"},
  1068  		options: config.Options{
  1069  			UnsupportedJSFeatures: es(2016),
  1070  			AbsOutputFile:         "/out.js",
  1071  		},
  1072  	})
  1073  }
  1074  
  1075  func TestLowerStaticAsyncSuperES2021NoBundle(t *testing.T) {
  1076  	lower_suite.expectBundled(t, bundled{
  1077  		files: map[string]string{
  1078  			"/entry.js": `
  1079  				class Derived extends Base {
  1080  					static test = async (key) => {
  1081  						return [
  1082  							await super.foo,
  1083  							await super[key],
  1084  							await ([super.foo] = [0]),
  1085  							await ([super[key]] = [0]),
  1086  
  1087  							await (super.foo = 1),
  1088  							await (super[key] = 1),
  1089  							await (super.foo += 2),
  1090  							await (super[key] += 2),
  1091  
  1092  							await ++super.foo,
  1093  							await ++super[key],
  1094  							await super.foo++,
  1095  							await super[key]++,
  1096  
  1097  							await super.foo.name,
  1098  							await super[key].name,
  1099  							await super.foo?.name,
  1100  							await super[key]?.name,
  1101  
  1102  							await super.foo(1, 2),
  1103  							await super[key](1, 2),
  1104  							await super.foo?.(1, 2),
  1105  							await super[key]?.(1, 2),
  1106  
  1107  							await (() => super.foo)(),
  1108  							await (() => super[key])(),
  1109  							await (() => super.foo())(),
  1110  							await (() => super[key]())(),
  1111  
  1112  							await super.foo` + "``" + `,
  1113  							await super[key]` + "``" + `,
  1114  						]
  1115  					}
  1116  				}
  1117  
  1118  				// This covers a bug that caused a compiler crash
  1119  				let fn = async () => class extends Base {
  1120  					static a = super.a
  1121  					static b = () => super.b
  1122  					static c() { return super.c }
  1123  					static d() { return () => super.d }
  1124  				}
  1125  
  1126  				// This covers a bug that generated bad code
  1127  				class Derived2 extends Base {
  1128  					static async a() { return class { [super.foo] = 123 } }
  1129  					static b = async () => class { [super.foo] = 123 }
  1130  				}
  1131  			`,
  1132  		},
  1133  		entryPaths: []string{"/entry.js"},
  1134  		options: config.Options{
  1135  			UnsupportedJSFeatures: es(2021),
  1136  			AbsOutputFile:         "/out.js",
  1137  		},
  1138  	})
  1139  }
  1140  
  1141  func TestLowerStaticAsyncSuperES2016NoBundle(t *testing.T) {
  1142  	lower_suite.expectBundled(t, bundled{
  1143  		files: map[string]string{
  1144  			"/entry.js": `
  1145  				class Derived extends Base {
  1146  					static test = async (key) => {
  1147  						return [
  1148  							await super.foo,
  1149  							await super[key],
  1150  							await ([super.foo] = [0]),
  1151  							await ([super[key]] = [0]),
  1152  
  1153  							await (super.foo = 1),
  1154  							await (super[key] = 1),
  1155  							await (super.foo += 2),
  1156  							await (super[key] += 2),
  1157  
  1158  							await ++super.foo,
  1159  							await ++super[key],
  1160  							await super.foo++,
  1161  							await super[key]++,
  1162  
  1163  							await super.foo.name,
  1164  							await super[key].name,
  1165  							await super.foo?.name,
  1166  							await super[key]?.name,
  1167  
  1168  							await super.foo(1, 2),
  1169  							await super[key](1, 2),
  1170  							await super.foo?.(1, 2),
  1171  							await super[key]?.(1, 2),
  1172  
  1173  							await (() => super.foo)(),
  1174  							await (() => super[key])(),
  1175  							await (() => super.foo())(),
  1176  							await (() => super[key]())(),
  1177  
  1178  							await super.foo` + "``" + `,
  1179  							await super[key]` + "``" + `,
  1180  						]
  1181  					}
  1182  				}
  1183  
  1184  				// This covers a bug that caused a compiler crash
  1185  				let fn = async () => class extends Base {
  1186  					static a = super.a
  1187  					static b = () => super.b
  1188  					static c() { return super.c }
  1189  					static d() { return () => super.d }
  1190  				}
  1191  
  1192  				// This covers a bug that generated bad code
  1193  				class Derived2 extends Base {
  1194  					static async a() { return class { [super.foo] = 123 } }
  1195  					static b = async () => class { [super.foo] = 123 }
  1196  				}
  1197  			`,
  1198  		},
  1199  		entryPaths: []string{"/entry.js"},
  1200  		options: config.Options{
  1201  			UnsupportedJSFeatures: es(2016),
  1202  			AbsOutputFile:         "/out.js",
  1203  		},
  1204  	})
  1205  }
  1206  
  1207  func TestLowerStaticSuperES2021NoBundle(t *testing.T) {
  1208  	lower_suite.expectBundled(t, bundled{
  1209  		files: map[string]string{
  1210  			"/entry.js": `
  1211  				class Derived extends Base {
  1212  					static test = key => {
  1213  						return [
  1214  							super.foo,
  1215  							super[key],
  1216  							([super.foo] = [0]),
  1217  							([super[key]] = [0]),
  1218  
  1219  							(super.foo = 1),
  1220  							(super[key] = 1),
  1221  							(super.foo += 2),
  1222  							(super[key] += 2),
  1223  
  1224  							++super.foo,
  1225  							++super[key],
  1226  							super.foo++,
  1227  							super[key]++,
  1228  
  1229  							super.foo.name,
  1230  							super[key].name,
  1231  							super.foo?.name,
  1232  							super[key]?.name,
  1233  
  1234  							super.foo(1, 2),
  1235  							super[key](1, 2),
  1236  							super.foo?.(1, 2),
  1237  							super[key]?.(1, 2),
  1238  
  1239  							(() => super.foo)(),
  1240  							(() => super[key])(),
  1241  							(() => super.foo())(),
  1242  							(() => super[key]())(),
  1243  
  1244  							super.foo` + "``" + `,
  1245  							super[key]` + "``" + `,
  1246  						]
  1247  					}
  1248  				}
  1249  			`,
  1250  		},
  1251  		entryPaths: []string{"/entry.js"},
  1252  		options: config.Options{
  1253  			UnsupportedJSFeatures: es(2021),
  1254  			AbsOutputFile:         "/out.js",
  1255  		},
  1256  	})
  1257  }
  1258  
  1259  func TestLowerStaticSuperES2016NoBundle(t *testing.T) {
  1260  	lower_suite.expectBundled(t, bundled{
  1261  		files: map[string]string{
  1262  			"/entry.js": `
  1263  				class Derived extends Base {
  1264  					static test = key => {
  1265  						return [
  1266  							super.foo,
  1267  							super[key],
  1268  							([super.foo] = [0]),
  1269  							([super[key]] = [0]),
  1270  
  1271  							(super.foo = 1),
  1272  							(super[key] = 1),
  1273  							(super.foo += 2),
  1274  							(super[key] += 2),
  1275  
  1276  							++super.foo,
  1277  							++super[key],
  1278  							super.foo++,
  1279  							super[key]++,
  1280  
  1281  							super.foo.name,
  1282  							super[key].name,
  1283  							super.foo?.name,
  1284  							super[key]?.name,
  1285  
  1286  							super.foo(1, 2),
  1287  							super[key](1, 2),
  1288  							super.foo?.(1, 2),
  1289  							super[key]?.(1, 2),
  1290  
  1291  							(() => super.foo)(),
  1292  							(() => super[key])(),
  1293  							(() => super.foo())(),
  1294  							(() => super[key]())(),
  1295  
  1296  							super.foo` + "``" + `,
  1297  							super[key]` + "``" + `,
  1298  						]
  1299  					}
  1300  				}
  1301  			`,
  1302  		},
  1303  		entryPaths: []string{"/entry.js"},
  1304  		options: config.Options{
  1305  			UnsupportedJSFeatures: es(2016),
  1306  			AbsOutputFile:         "/out.js",
  1307  		},
  1308  	})
  1309  }
  1310  
  1311  func TestLowerAsyncArrowSuperES2016(t *testing.T) {
  1312  	lower_suite.expectBundled(t, bundled{
  1313  		files: map[string]string{
  1314  			"/entry.js": `
  1315  				export { default as foo1 } from "./foo1"
  1316  				export { default as foo2 } from "./foo2"
  1317  				export { default as foo3 } from "./foo3"
  1318  				export { default as foo4 } from "./foo4"
  1319  				export { default as bar1 } from "./bar1"
  1320  				export { default as bar2 } from "./bar2"
  1321  				export { default as bar3 } from "./bar3"
  1322  				export { default as bar4 } from "./bar4"
  1323  				export { default as baz1 } from "./baz1"
  1324  				export { default as baz2 } from "./baz2"
  1325  				import "./outer"
  1326  			`,
  1327  			"/foo1.js": `export default class extends x { foo1() { return async () => super.foo('foo1') } }`,
  1328  			"/foo2.js": `export default class extends x { foo2() { return async () => () => super.foo('foo2') } }`,
  1329  			"/foo3.js": `export default class extends x { foo3() { return () => async () => super.foo('foo3') } }`,
  1330  			"/foo4.js": `export default class extends x { foo4() { return async () => async () => super.foo('foo4') } }`,
  1331  			"/bar1.js": `export default class extends x { bar1 = async () => super.foo('bar1') }`,
  1332  			"/bar2.js": `export default class extends x { bar2 = async () => () => super.foo('bar2') }`,
  1333  			"/bar3.js": `export default class extends x { bar3 = () => async () => super.foo('bar3') }`,
  1334  			"/bar4.js": `export default class extends x { bar4 = async () => async () => super.foo('bar4') }`,
  1335  			"/baz1.js": `export default class extends x { async baz1() { return () => super.foo('baz1') } }`,
  1336  			"/baz2.js": `export default class extends x { async baz2() { return () => () => super.foo('baz2') } }`,
  1337  			"/outer.js": `
  1338  				// Helper functions for "super" shouldn't be inserted into this outer function
  1339  				export default (async function () {
  1340  					class y extends z {
  1341  						foo = async () => super.foo()
  1342  					}
  1343  					await new y().foo()()
  1344  				})()
  1345  			`,
  1346  		},
  1347  		entryPaths: []string{"/entry.js"},
  1348  		options: config.Options{
  1349  			Mode:                  config.ModeBundle,
  1350  			UnsupportedJSFeatures: es(2016),
  1351  			AbsOutputFile:         "/out.js",
  1352  		},
  1353  	})
  1354  }
  1355  
  1356  func TestLowerAsyncArrowSuperSetterES2016(t *testing.T) {
  1357  	lower_suite.expectBundled(t, bundled{
  1358  		files: map[string]string{
  1359  			"/entry.js": `
  1360  				export { default as foo1 } from "./foo1"
  1361  				export { default as foo2 } from "./foo2"
  1362  				export { default as foo3 } from "./foo3"
  1363  				export { default as foo4 } from "./foo4"
  1364  				export { default as bar1 } from "./bar1"
  1365  				export { default as bar2 } from "./bar2"
  1366  				export { default as bar3 } from "./bar3"
  1367  				export { default as bar4 } from "./bar4"
  1368  				export { default as baz1 } from "./baz1"
  1369  				export { default as baz2 } from "./baz2"
  1370  				import "./outer"
  1371  			`,
  1372  			"/foo1.js": `export default class extends x { foo1() { return async () => super.foo = 'foo1' } }`,
  1373  			"/foo2.js": `export default class extends x { foo2() { return async () => () => super.foo = 'foo2' } }`,
  1374  			"/foo3.js": `export default class extends x { foo3() { return () => async () => super.foo = 'foo3' } }`,
  1375  			"/foo4.js": `export default class extends x { foo4() { return async () => async () => super.foo = 'foo4' } }`,
  1376  			"/bar1.js": `export default class extends x { bar1 = async () => super.foo = 'bar1' }`,
  1377  			"/bar2.js": `export default class extends x { bar2 = async () => () => super.foo = 'bar2' }`,
  1378  			"/bar3.js": `export default class extends x { bar3 = () => async () => super.foo = 'bar3' }`,
  1379  			"/bar4.js": `export default class extends x { bar4 = async () => async () => super.foo = 'bar4' }`,
  1380  			"/baz1.js": `export default class extends x { async baz1() { return () => super.foo = 'baz1' } }`,
  1381  			"/baz2.js": `export default class extends x { async baz2() { return () => () => super.foo = 'baz2' } }`,
  1382  			"/outer.js": `
  1383  				// Helper functions for "super" shouldn't be inserted into this outer function
  1384  				export default (async function () {
  1385  					class y extends z {
  1386  						foo = async () => super.foo = 'foo'
  1387  					}
  1388  					await new y().foo()()
  1389  				})()
  1390  			`,
  1391  		},
  1392  		entryPaths: []string{"/entry.js"},
  1393  		options: config.Options{
  1394  			Mode:                  config.ModeBundle,
  1395  			UnsupportedJSFeatures: es(2016),
  1396  			AbsOutputFile:         "/out.js",
  1397  		},
  1398  	})
  1399  }
  1400  
  1401  func TestLowerStaticAsyncArrowSuperES2016(t *testing.T) {
  1402  	lower_suite.expectBundled(t, bundled{
  1403  		files: map[string]string{
  1404  			"/entry.js": `
  1405  				export { default as foo1 } from "./foo1"
  1406  				export { default as foo2 } from "./foo2"
  1407  				export { default as foo3 } from "./foo3"
  1408  				export { default as foo4 } from "./foo4"
  1409  				export { default as bar1 } from "./bar1"
  1410  				export { default as bar2 } from "./bar2"
  1411  				export { default as bar3 } from "./bar3"
  1412  				export { default as bar4 } from "./bar4"
  1413  				export { default as baz1 } from "./baz1"
  1414  				export { default as baz2 } from "./baz2"
  1415  				import "./outer"
  1416  			`,
  1417  			"/foo1.js": `export default class extends x { static foo1() { return async () => super.foo('foo1') } }`,
  1418  			"/foo2.js": `export default class extends x { static foo2() { return async () => () => super.foo('foo2') } }`,
  1419  			"/foo3.js": `export default class extends x { static foo3() { return () => async () => super.foo('foo3') } }`,
  1420  			"/foo4.js": `export default class extends x { static foo4() { return async () => async () => super.foo('foo4') } }`,
  1421  			"/bar1.js": `export default class extends x { static bar1 = async () => super.foo('bar1') }`,
  1422  			"/bar2.js": `export default class extends x { static bar2 = async () => () => super.foo('bar2') }`,
  1423  			"/bar3.js": `export default class extends x { static bar3 = () => async () => super.foo('bar3') }`,
  1424  			"/bar4.js": `export default class extends x { static bar4 = async () => async () => super.foo('bar4') }`,
  1425  			"/baz1.js": `export default class extends x { static async baz1() { return () => super.foo('baz1') } }`,
  1426  			"/baz2.js": `export default class extends x { static async baz2() { return () => () => super.foo('baz2') } }`,
  1427  			"/outer.js": `
  1428  				// Helper functions for "super" shouldn't be inserted into this outer function
  1429  				export default (async function () {
  1430  					class y extends z {
  1431  						static foo = async () => super.foo()
  1432  					}
  1433  					await y.foo()()
  1434  				})()
  1435  			`,
  1436  		},
  1437  		entryPaths: []string{"/entry.js"},
  1438  		options: config.Options{
  1439  			Mode:                  config.ModeBundle,
  1440  			UnsupportedJSFeatures: es(2016),
  1441  			AbsOutputFile:         "/out.js",
  1442  		},
  1443  	})
  1444  }
  1445  
  1446  func TestLowerStaticAsyncArrowSuperSetterES2016(t *testing.T) {
  1447  	lower_suite.expectBundled(t, bundled{
  1448  		files: map[string]string{
  1449  			"/entry.js": `
  1450  				export { default as foo1 } from "./foo1"
  1451  				export { default as foo2 } from "./foo2"
  1452  				export { default as foo3 } from "./foo3"
  1453  				export { default as foo4 } from "./foo4"
  1454  				export { default as bar1 } from "./bar1"
  1455  				export { default as bar2 } from "./bar2"
  1456  				export { default as bar3 } from "./bar3"
  1457  				export { default as bar4 } from "./bar4"
  1458  				export { default as baz1 } from "./baz1"
  1459  				export { default as baz2 } from "./baz2"
  1460  				import "./outer"
  1461  			`,
  1462  			"/foo1.js": `export default class extends x { static foo1() { return async () => super.foo = 'foo1' } }`,
  1463  			"/foo2.js": `export default class extends x { static foo2() { return async () => () => super.foo = 'foo2' } }`,
  1464  			"/foo3.js": `export default class extends x { static foo3() { return () => async () => super.foo = 'foo3' } }`,
  1465  			"/foo4.js": `export default class extends x { static foo4() { return async () => async () => super.foo = 'foo4' } }`,
  1466  			"/bar1.js": `export default class extends x { static bar1 = async () => super.foo = 'bar1' }`,
  1467  			"/bar2.js": `export default class extends x { static bar2 = async () => () => super.foo = 'bar2' }`,
  1468  			"/bar3.js": `export default class extends x { static bar3 = () => async () => super.foo = 'bar3' }`,
  1469  			"/bar4.js": `export default class extends x { static bar4 = async () => async () => super.foo = 'bar4' }`,
  1470  			"/baz1.js": `export default class extends x { static async baz1() { return () => super.foo = 'baz1' } }`,
  1471  			"/baz2.js": `export default class extends x { static async baz2() { return () => () => super.foo = 'baz2' } }`,
  1472  			"/outer.js": `
  1473  				// Helper functions for "super" shouldn't be inserted into this outer function
  1474  				export default (async function () {
  1475  					class y extends z {
  1476  						static foo = async () => super.foo = 'foo'
  1477  					}
  1478  					await y.foo()()
  1479  				})()
  1480  			`,
  1481  		},
  1482  		entryPaths: []string{"/entry.js"},
  1483  		options: config.Options{
  1484  			Mode:                  config.ModeBundle,
  1485  			UnsupportedJSFeatures: es(2016),
  1486  			AbsOutputFile:         "/out.js",
  1487  		},
  1488  	})
  1489  }
  1490  
  1491  func TestLowerPrivateSuperES2022(t *testing.T) {
  1492  	lower_suite.expectBundled(t, bundled{
  1493  		files: map[string]string{
  1494  			"/entry.js": `
  1495  				export { default as foo1 } from "./foo1"
  1496  				export { default as foo2 } from "./foo2"
  1497  				export { default as foo3 } from "./foo3"
  1498  				export { default as foo4 } from "./foo4"
  1499  				export { default as foo5 } from "./foo5"
  1500  				export { default as foo6 } from "./foo6"
  1501  				export { default as foo7 } from "./foo7"
  1502  				export { default as foo8 } from "./foo8"
  1503  			`,
  1504  			"/foo1.js": `export default class extends x { #foo() { super.foo() } }`,
  1505  			"/foo2.js": `export default class extends x { #foo() { super.foo++ } }`,
  1506  			"/foo3.js": `export default class extends x { static #foo() { super.foo() } }`,
  1507  			"/foo4.js": `export default class extends x { static #foo() { super.foo++ } }`,
  1508  			"/foo5.js": `export default class extends x { #foo = () => { super.foo() } }`,
  1509  			"/foo6.js": `export default class extends x { #foo = () => { super.foo++ } }`,
  1510  			"/foo7.js": `export default class extends x { static #foo = () => { super.foo() } }`,
  1511  			"/foo8.js": `export default class extends x { static #foo = () => { super.foo++ } }`,
  1512  		},
  1513  		entryPaths: []string{"/entry.js"},
  1514  		options: config.Options{
  1515  			Mode:                  config.ModeBundle,
  1516  			UnsupportedJSFeatures: es(2022),
  1517  			AbsOutputFile:         "/out.js",
  1518  		},
  1519  	})
  1520  }
  1521  
  1522  func TestLowerPrivateSuperES2021(t *testing.T) {
  1523  	lower_suite.expectBundled(t, bundled{
  1524  		files: map[string]string{
  1525  			"/entry.js": `
  1526  				export { default as foo1 } from "./foo1"
  1527  				export { default as foo2 } from "./foo2"
  1528  				export { default as foo3 } from "./foo3"
  1529  				export { default as foo4 } from "./foo4"
  1530  				export { default as foo5 } from "./foo5"
  1531  				export { default as foo6 } from "./foo6"
  1532  				export { default as foo7 } from "./foo7"
  1533  				export { default as foo8 } from "./foo8"
  1534  			`,
  1535  			"/foo1.js": `export default class extends x { #foo() { super.foo() } }`,
  1536  			"/foo2.js": `export default class extends x { #foo() { super.foo++ } }`,
  1537  			"/foo3.js": `export default class extends x { static #foo() { super.foo() } }`,
  1538  			"/foo4.js": `export default class extends x { static #foo() { super.foo++ } }`,
  1539  			"/foo5.js": `export default class extends x { #foo = () => { super.foo() } }`,
  1540  			"/foo6.js": `export default class extends x { #foo = () => { super.foo++ } }`,
  1541  			"/foo7.js": `export default class extends x { static #foo = () => { super.foo() } }`,
  1542  			"/foo8.js": `export default class extends x { static #foo = () => { super.foo++ } }`,
  1543  		},
  1544  		entryPaths: []string{"/entry.js"},
  1545  		options: config.Options{
  1546  			Mode:                  config.ModeBundle,
  1547  			UnsupportedJSFeatures: es(2021),
  1548  			AbsOutputFile:         "/out.js",
  1549  		},
  1550  	})
  1551  }
  1552  
  1553  // https://github.com/evanw/esbuild/issues/2158
  1554  func TestLowerPrivateSuperStaticBundleIssue2158(t *testing.T) {
  1555  	lower_suite.expectBundled(t, bundled{
  1556  		files: map[string]string{
  1557  			"/entry.js": `
  1558  				export class Foo extends Object {
  1559  					static FOO;
  1560  					constructor() {
  1561  						super();
  1562  					}
  1563  					#foo;
  1564  				}
  1565  			`,
  1566  		},
  1567  		entryPaths: []string{"/entry.js"},
  1568  		options: config.Options{
  1569  			Mode:          config.ModeBundle,
  1570  			AbsOutputFile: "/out.js",
  1571  		},
  1572  	})
  1573  }
  1574  
  1575  func TestLowerClassField2020NoBundle(t *testing.T) {
  1576  	lower_suite.expectBundled(t, bundled{
  1577  		files: map[string]string{
  1578  			"/entry.js": `
  1579  				class Foo {
  1580  					#foo = 123
  1581  					#bar
  1582  					foo = 123
  1583  					bar
  1584  					static #s_foo = 123
  1585  					static #s_bar
  1586  					static s_foo = 123
  1587  					static s_bar
  1588  				}
  1589  			`,
  1590  		},
  1591  		entryPaths: []string{"/entry.js"},
  1592  		options: config.Options{
  1593  			UnsupportedJSFeatures: es(2020),
  1594  			AbsOutputFile:         "/out.js",
  1595  		},
  1596  	})
  1597  }
  1598  
  1599  func TestLowerClassFieldNextNoBundle(t *testing.T) {
  1600  	lower_suite.expectBundled(t, bundled{
  1601  		files: map[string]string{
  1602  			"/entry.js": `
  1603  				class Foo {
  1604  					#foo = 123
  1605  					#bar
  1606  					foo = 123
  1607  					bar
  1608  					static #s_foo = 123
  1609  					static #s_bar
  1610  					static s_foo = 123
  1611  					static s_bar
  1612  				}
  1613  			`,
  1614  		},
  1615  		entryPaths: []string{"/entry.js"},
  1616  		options: config.Options{
  1617  			AbsOutputFile: "/out.js",
  1618  		},
  1619  	})
  1620  }
  1621  
  1622  func TestTSLowerClassField2020NoBundle(t *testing.T) {
  1623  	lower_suite.expectBundled(t, bundled{
  1624  		files: map[string]string{
  1625  			"/entry.ts": `
  1626  				class Foo {
  1627  					#foo = 123
  1628  					#bar
  1629  					foo = 123
  1630  					bar
  1631  					static #s_foo = 123
  1632  					static #s_bar
  1633  					static s_foo = 123
  1634  					static s_bar
  1635  				}
  1636  			`,
  1637  			"/tsconfig.json": `{
  1638  				"compilerOptions": {
  1639  					"useDefineForClassFields": false
  1640  				}
  1641  			}`,
  1642  		},
  1643  		entryPaths: []string{"/entry.ts"},
  1644  		options: config.Options{
  1645  			UnsupportedJSFeatures: es(2020),
  1646  			AbsOutputFile:         "/out.js",
  1647  		},
  1648  	})
  1649  }
  1650  
  1651  func TestTSLowerClassPrivateFieldNextNoBundle(t *testing.T) {
  1652  	lower_suite.expectBundled(t, bundled{
  1653  		files: map[string]string{
  1654  			"/entry.ts": `
  1655  				class Foo {
  1656  					#foo = 123
  1657  					#bar
  1658  					foo = 123
  1659  					bar
  1660  					static #s_foo = 123
  1661  					static #s_bar
  1662  					static s_foo = 123
  1663  					static s_bar
  1664  				}
  1665  			`,
  1666  			"/tsconfig.json": `{
  1667  				"compilerOptions": {
  1668  					"useDefineForClassFields": false
  1669  				}
  1670  			}`,
  1671  		},
  1672  		entryPaths: []string{"/entry.ts"},
  1673  		options: config.Options{
  1674  			AbsOutputFile: "/out.js",
  1675  		},
  1676  	})
  1677  }
  1678  
  1679  func TestLowerClassFieldStrictTsconfigJson2020(t *testing.T) {
  1680  	lower_suite.expectBundled(t, bundled{
  1681  		files: map[string]string{
  1682  			"/entry.js": `
  1683  				import loose from './loose'
  1684  				import strict from './strict'
  1685  				console.log(loose, strict)
  1686  			`,
  1687  			"/loose/index.js": `
  1688  				export default class {
  1689  					foo
  1690  				}
  1691  			`,
  1692  			"/loose/tsconfig.json": `
  1693  				{
  1694  					"compilerOptions": {
  1695  						"useDefineForClassFields": false
  1696  					}
  1697  				}
  1698  			`,
  1699  			"/strict/index.js": `
  1700  				export default class {
  1701  					foo
  1702  				}
  1703  			`,
  1704  			"/strict/tsconfig.json": `
  1705  				{
  1706  					"compilerOptions": {
  1707  						"useDefineForClassFields": true
  1708  					}
  1709  				}
  1710  			`,
  1711  		},
  1712  		entryPaths: []string{"/entry.js"},
  1713  		options: config.Options{
  1714  			Mode:                  config.ModeBundle,
  1715  			UnsupportedJSFeatures: es(2020),
  1716  			AbsOutputFile:         "/out.js",
  1717  		},
  1718  	})
  1719  }
  1720  
  1721  func TestTSLowerClassFieldStrictTsconfigJson2020(t *testing.T) {
  1722  	lower_suite.expectBundled(t, bundled{
  1723  		files: map[string]string{
  1724  			"/entry.js": `
  1725  				import loose from './loose'
  1726  				import strict from './strict'
  1727  				console.log(loose, strict)
  1728  			`,
  1729  			"/loose/index.ts": `
  1730  				export default class {
  1731  					foo
  1732  				}
  1733  			`,
  1734  			"/loose/tsconfig.json": `
  1735  				{
  1736  					"compilerOptions": {
  1737  						"useDefineForClassFields": false
  1738  					}
  1739  				}
  1740  			`,
  1741  			"/strict/index.ts": `
  1742  				export default class {
  1743  					foo
  1744  				}
  1745  			`,
  1746  			"/strict/tsconfig.json": `
  1747  				{
  1748  					"compilerOptions": {
  1749  						"useDefineForClassFields": true
  1750  					}
  1751  				}
  1752  			`,
  1753  		},
  1754  		entryPaths: []string{"/entry.js"},
  1755  		options: config.Options{
  1756  			Mode:                  config.ModeBundle,
  1757  			UnsupportedJSFeatures: es(2020),
  1758  			AbsOutputFile:         "/out.js",
  1759  		},
  1760  	})
  1761  }
  1762  
  1763  func TestTSLowerObjectRest2017NoBundle(t *testing.T) {
  1764  	lower_suite.expectBundled(t, bundled{
  1765  		files: map[string]string{
  1766  			"/entry.ts": `
  1767  				const { ...local_const } = {};
  1768  				let { ...local_let } = {};
  1769  				var { ...local_var } = {};
  1770  				let arrow_fn = ({ ...x }) => { };
  1771  				let fn_expr = function ({ ...x } = default_value) {};
  1772  				let class_expr = class { method(x, ...[y, { ...z }]) {} };
  1773  
  1774  				function fn_stmt({ a = b(), ...x }, { c = d(), ...y }) {}
  1775  				class class_stmt { method({ ...x }) {} }
  1776  				namespace ns { export let { ...x } = {} }
  1777  				try { } catch ({ ...catch_clause }) {}
  1778  
  1779  				for (const { ...for_in_const } in { abc }) {}
  1780  				for (let { ...for_in_let } in { abc }) {}
  1781  				for (var { ...for_in_var } in { abc }) ;
  1782  				for (const { ...for_of_const } of [{}]) ;
  1783  				for (let { ...for_of_let } of [{}]) x()
  1784  				for (var { ...for_of_var } of [{}]) x()
  1785  				for (const { ...for_const } = {}; x; x = null) {}
  1786  				for (let { ...for_let } = {}; x; x = null) {}
  1787  				for (var { ...for_var } = {}; x; x = null) {}
  1788  				for ({ ...x } in { abc }) {}
  1789  				for ({ ...x } of [{}]) {}
  1790  				for ({ ...x } = {}; x; x = null) {}
  1791  
  1792  				({ ...assign } = {});
  1793  				({ obj_method({ ...x }) {} });
  1794  
  1795  				// Check for used return values
  1796  				({ ...x } = x);
  1797  				for ({ ...x } = x; 0; ) ;
  1798  				console.log({ ...x } = x);
  1799  				console.log({ x, ...xx } = { x });
  1800  				console.log({ x: { ...xx } } = { x });
  1801  			`,
  1802  		},
  1803  		entryPaths: []string{"/entry.ts"},
  1804  		options: config.Options{
  1805  			UnsupportedJSFeatures: es(2017),
  1806  			AbsOutputFile:         "/out.js",
  1807  		},
  1808  	})
  1809  }
  1810  
  1811  func TestTSLowerObjectRest2018NoBundle(t *testing.T) {
  1812  	lower_suite.expectBundled(t, bundled{
  1813  		files: map[string]string{
  1814  			"/entry.ts": `
  1815  				const { ...local_const } = {};
  1816  				let { ...local_let } = {};
  1817  				var { ...local_var } = {};
  1818  				let arrow_fn = ({ ...x }) => { };
  1819  				let fn_expr = function ({ ...x } = default_value) {};
  1820  				let class_expr = class { method(x, ...[y, { ...z }]) {} };
  1821  
  1822  				function fn_stmt({ a = b(), ...x }, { c = d(), ...y }) {}
  1823  				class class_stmt { method({ ...x }) {} }
  1824  				namespace ns { export let { ...x } = {} }
  1825  				try { } catch ({ ...catch_clause }) {}
  1826  
  1827  				for (const { ...for_in_const } in { abc }) {}
  1828  				for (let { ...for_in_let } in { abc }) {}
  1829  				for (var { ...for_in_var } in { abc }) ;
  1830  				for (const { ...for_of_const } of [{}]) ;
  1831  				for (let { ...for_of_let } of [{}]) x()
  1832  				for (var { ...for_of_var } of [{}]) x()
  1833  				for (const { ...for_const } = {}; x; x = null) {}
  1834  				for (let { ...for_let } = {}; x; x = null) {}
  1835  				for (var { ...for_var } = {}; x; x = null) {}
  1836  				for ({ ...x } in { abc }) {}
  1837  				for ({ ...x } of [{}]) {}
  1838  				for ({ ...x } = {}; x; x = null) {}
  1839  
  1840  				({ ...assign } = {});
  1841  				({ obj_method({ ...x }) {} });
  1842  
  1843  				// Check for used return values
  1844  				({ ...x } = x);
  1845  				for ({ ...x } = x; 0; ) ;
  1846  				console.log({ ...x } = x);
  1847  				console.log({ x, ...xx } = { x });
  1848  				console.log({ x: { ...xx } } = { x });
  1849  			`,
  1850  		},
  1851  		entryPaths: []string{"/entry.ts"},
  1852  		options: config.Options{
  1853  			UnsupportedJSFeatures: es(2018),
  1854  			AbsOutputFile:         "/out.js",
  1855  		},
  1856  	})
  1857  }
  1858  
  1859  func TestClassSuperThisIssue242NoBundle(t *testing.T) {
  1860  	lower_suite.expectBundled(t, bundled{
  1861  		files: map[string]string{
  1862  			"/entry.ts": `
  1863  				export class A {}
  1864  
  1865  				export class B extends A {
  1866  					#e: string
  1867  					constructor(c: { d: any }) {
  1868  						super()
  1869  						this.#e = c.d ?? 'test'
  1870  					}
  1871  					f() {
  1872  						return this.#e
  1873  					}
  1874  				}
  1875  			`,
  1876  		},
  1877  		entryPaths: []string{"/entry.ts"},
  1878  		options: config.Options{
  1879  			UnsupportedJSFeatures: es(2019),
  1880  			AbsOutputFile:         "/out.js",
  1881  		},
  1882  	})
  1883  }
  1884  
  1885  func TestLowerExportStarAsNameCollisionNoBundle(t *testing.T) {
  1886  	lower_suite.expectBundled(t, bundled{
  1887  		files: map[string]string{
  1888  			"/entry.js": `
  1889  				export * as ns from 'path'
  1890  				let ns = 123
  1891  				export {ns as sn}
  1892  			`,
  1893  		},
  1894  		entryPaths: []string{"/entry.js"},
  1895  		options: config.Options{
  1896  			UnsupportedJSFeatures: es(2019),
  1897  			AbsOutputFile:         "/out.js",
  1898  		},
  1899  	})
  1900  }
  1901  
  1902  func TestLowerExportStarAsNameCollision(t *testing.T) {
  1903  	lower_suite.expectBundled(t, bundled{
  1904  		files: map[string]string{
  1905  			"/entry.js": `
  1906  				import * as test from './nested'
  1907  				console.log(test.foo, test.oof)
  1908  				export * as ns from 'path1'
  1909  				let ns = 123
  1910  				export {ns as sn}
  1911  			`,
  1912  			"/nested.js": `
  1913  				export * as foo from 'path2'
  1914  				let foo = 123
  1915  				export {foo as oof}
  1916  			`,
  1917  		},
  1918  		entryPaths: []string{"/entry.js"},
  1919  		options: config.Options{
  1920  			Mode:                  config.ModeBundle,
  1921  			UnsupportedJSFeatures: es(2019),
  1922  			AbsOutputFile:         "/out.js",
  1923  			ExternalSettings: config.ExternalSettings{
  1924  				PreResolve: config.ExternalMatchers{Exact: map[string]bool{
  1925  					"path1": true,
  1926  					"path2": true,
  1927  				}},
  1928  			},
  1929  		},
  1930  	})
  1931  }
  1932  
  1933  func TestLowerStrictModeSyntax(t *testing.T) {
  1934  	lower_suite.expectBundled(t, bundled{
  1935  		files: map[string]string{
  1936  			"/entry.js": `
  1937  				import './for-in'
  1938  			`,
  1939  			"/for-in.js": `
  1940  				if (test)
  1941  					for (var a = b in {}) ;
  1942  				for (var x = y in {}) ;
  1943  			`,
  1944  		},
  1945  		entryPaths: []string{"/entry.js"},
  1946  		options: config.Options{
  1947  			Mode:          config.ModeBundle,
  1948  			OutputFormat:  config.FormatESModule,
  1949  			AbsOutputFile: "/out.js",
  1950  		},
  1951  	})
  1952  }
  1953  
  1954  func TestLowerForbidStrictModeSyntax(t *testing.T) {
  1955  	lower_suite.expectBundled(t, bundled{
  1956  		files: map[string]string{
  1957  			"/entry.js": `
  1958  				import './with'
  1959  				import './delete-1'
  1960  				import './delete-2'
  1961  				import './delete-3'
  1962  			`,
  1963  			"/with.js": `
  1964  				with (x) y
  1965  			`,
  1966  			"/delete-1.js": `
  1967  				delete x
  1968  			`,
  1969  			"/delete-2.js": `
  1970  				delete (y)
  1971  			`,
  1972  			"/delete-3.js": `
  1973  				delete (1 ? z : z)
  1974  			`,
  1975  		},
  1976  		entryPaths: []string{"/entry.js"},
  1977  		options: config.Options{
  1978  			Mode:          config.ModeBundle,
  1979  			OutputFormat:  config.FormatESModule,
  1980  			AbsOutputFile: "/out.js",
  1981  		},
  1982  		expectedScanLog: `delete-1.js: ERROR: Delete of a bare identifier cannot be used with the "esm" output format due to strict mode
  1983  delete-2.js: ERROR: Delete of a bare identifier cannot be used with the "esm" output format due to strict mode
  1984  with.js: ERROR: With statements cannot be used with the "esm" output format due to strict mode
  1985  `,
  1986  	})
  1987  }
  1988  
  1989  func TestLowerPrivateClassFieldOrder(t *testing.T) {
  1990  	lower_suite.expectBundled(t, bundled{
  1991  		files: map[string]string{
  1992  			"/entry.js": `
  1993  				class Foo {
  1994  					#foo = 123 // This must be set before "bar" is initialized
  1995  					bar = this.#foo
  1996  				}
  1997  				console.log(new Foo().bar === 123)
  1998  			`,
  1999  		},
  2000  		entryPaths: []string{"/entry.js"},
  2001  		options: config.Options{
  2002  			Mode:                  config.ModePassThrough,
  2003  			AbsOutputFile:         "/out.js",
  2004  			UnsupportedJSFeatures: compat.ClassPrivateField,
  2005  		},
  2006  	})
  2007  }
  2008  
  2009  func TestLowerPrivateClassMethodOrder(t *testing.T) {
  2010  	lower_suite.expectBundled(t, bundled{
  2011  		files: map[string]string{
  2012  			"/entry.js": `
  2013  				class Foo {
  2014  					bar = this.#foo()
  2015  					#foo() { return 123 } // This must be set before "bar" is initialized
  2016  				}
  2017  				console.log(new Foo().bar === 123)
  2018  			`,
  2019  		},
  2020  		entryPaths: []string{"/entry.js"},
  2021  		options: config.Options{
  2022  			Mode:                  config.ModePassThrough,
  2023  			AbsOutputFile:         "/out.js",
  2024  			UnsupportedJSFeatures: compat.ClassPrivateMethod,
  2025  		},
  2026  	})
  2027  }
  2028  
  2029  func TestLowerPrivateClassAccessorOrder(t *testing.T) {
  2030  	lower_suite.expectBundled(t, bundled{
  2031  		files: map[string]string{
  2032  			"/entry.js": `
  2033  				class Foo {
  2034  					bar = this.#foo
  2035  					get #foo() { return 123 } // This must be set before "bar" is initialized
  2036  				}
  2037  				console.log(new Foo().bar === 123)
  2038  			`,
  2039  		},
  2040  		entryPaths: []string{"/entry.js"},
  2041  		options: config.Options{
  2042  			Mode:                  config.ModePassThrough,
  2043  			AbsOutputFile:         "/out.js",
  2044  			UnsupportedJSFeatures: compat.ClassPrivateAccessor,
  2045  		},
  2046  	})
  2047  }
  2048  
  2049  func TestLowerPrivateClassStaticFieldOrder(t *testing.T) {
  2050  	lower_suite.expectBundled(t, bundled{
  2051  		files: map[string]string{
  2052  			"/entry.js": `
  2053  				class Foo {
  2054  					static #foo = 123 // This must be set before "bar" is initialized
  2055  					static bar = Foo.#foo
  2056  				}
  2057  				console.log(Foo.bar === 123)
  2058  
  2059  				class FooThis {
  2060  					static #foo = 123 // This must be set before "bar" is initialized
  2061  					static bar = this.#foo
  2062  				}
  2063  				console.log(FooThis.bar === 123)
  2064  			`,
  2065  		},
  2066  		entryPaths: []string{"/entry.js"},
  2067  		options: config.Options{
  2068  			Mode:                  config.ModePassThrough,
  2069  			AbsOutputFile:         "/out.js",
  2070  			UnsupportedJSFeatures: compat.ClassPrivateStaticField,
  2071  		},
  2072  	})
  2073  }
  2074  
  2075  func TestLowerPrivateClassStaticMethodOrder(t *testing.T) {
  2076  	lower_suite.expectBundled(t, bundled{
  2077  		files: map[string]string{
  2078  			"/entry.js": `
  2079  				class Foo {
  2080  					static bar = Foo.#foo()
  2081  					static #foo() { return 123 } // This must be set before "bar" is initialized
  2082  				}
  2083  				console.log(Foo.bar === 123)
  2084  
  2085  				class FooThis {
  2086  					static bar = this.#foo()
  2087  					static #foo() { return 123 } // This must be set before "bar" is initialized
  2088  				}
  2089  				console.log(FooThis.bar === 123)
  2090  			`,
  2091  		},
  2092  		entryPaths: []string{"/entry.js"},
  2093  		options: config.Options{
  2094  			Mode:                  config.ModePassThrough,
  2095  			AbsOutputFile:         "/out.js",
  2096  			UnsupportedJSFeatures: compat.ClassPrivateStaticMethod,
  2097  		},
  2098  	})
  2099  }
  2100  
  2101  func TestLowerPrivateClassStaticAccessorOrder(t *testing.T) {
  2102  	lower_suite.expectBundled(t, bundled{
  2103  		files: map[string]string{
  2104  			"/entry.js": `
  2105  				class Foo {
  2106  					static bar = Foo.#foo
  2107  					static get #foo() { return 123 } // This must be set before "bar" is initialized
  2108  				}
  2109  				console.log(Foo.bar === 123)
  2110  
  2111  				class FooThis {
  2112  					static bar = this.#foo
  2113  					static get #foo() { return 123 } // This must be set before "bar" is initialized
  2114  				}
  2115  				console.log(FooThis.bar === 123)
  2116  			`,
  2117  		},
  2118  		entryPaths: []string{"/entry.js"},
  2119  		options: config.Options{
  2120  			Mode:                  config.ModePassThrough,
  2121  			AbsOutputFile:         "/out.js",
  2122  			UnsupportedJSFeatures: compat.ClassPrivateStaticAccessor,
  2123  		},
  2124  	})
  2125  }
  2126  
  2127  func TestLowerPrivateClassBrandCheckUnsupported(t *testing.T) {
  2128  	lower_suite.expectBundled(t, bundled{
  2129  		files: map[string]string{
  2130  			"/entry.js": `
  2131  				class Foo {
  2132  					#foo
  2133  					#bar
  2134  					baz() {
  2135  						return [
  2136  							this.#foo,
  2137  							this.#bar,
  2138  							#foo in this,
  2139  						]
  2140  					}
  2141  				}
  2142  			`,
  2143  		},
  2144  		entryPaths: []string{"/entry.js"},
  2145  		options: config.Options{
  2146  			Mode:                  config.ModePassThrough,
  2147  			AbsOutputFile:         "/out.js",
  2148  			UnsupportedJSFeatures: compat.ClassPrivateBrandCheck,
  2149  		},
  2150  	})
  2151  }
  2152  
  2153  func TestLowerPrivateClassBrandCheckSupported(t *testing.T) {
  2154  	lower_suite.expectBundled(t, bundled{
  2155  		files: map[string]string{
  2156  			"/entry.js": `
  2157  				class Foo {
  2158  					#foo
  2159  					#bar
  2160  					baz() {
  2161  						return [
  2162  							this.#foo,
  2163  							this.#bar,
  2164  							#foo in this,
  2165  						]
  2166  					}
  2167  				}
  2168  			`,
  2169  		},
  2170  		entryPaths: []string{"/entry.js"},
  2171  		options: config.Options{
  2172  			Mode:          config.ModePassThrough,
  2173  			AbsOutputFile: "/out.js",
  2174  		},
  2175  	})
  2176  }
  2177  
  2178  func TestLowerTemplateObject(t *testing.T) {
  2179  	lower_suite.expectBundled(t, bundled{
  2180  		files: map[string]string{
  2181  			"/entry.js": `
  2182  				x = () => [
  2183  					tag` + "`x`" + `,
  2184  					tag` + "`\\xFF`" + `,
  2185  					tag` + "`\\x`" + `,
  2186  					tag` + "`\\u`" + `,
  2187  				]
  2188  				y = () => [
  2189  					tag` + "`x${y}z`" + `,
  2190  					tag` + "`\\xFF${y}z`" + `,
  2191  					tag` + "`x${y}\\z`" + `,
  2192  					tag` + "`x${y}\\u`" + `,
  2193  				]
  2194  			`,
  2195  		},
  2196  		entryPaths: []string{"/entry.js"},
  2197  		options: config.Options{
  2198  			Mode:                  config.ModePassThrough,
  2199  			AbsOutputFile:         "/out.js",
  2200  			UnsupportedJSFeatures: compat.TemplateLiteral,
  2201  		},
  2202  	})
  2203  }
  2204  
  2205  // See https://github.com/evanw/esbuild/issues/1424 for more information
  2206  func TestLowerPrivateClassFieldStaticIssue1424(t *testing.T) {
  2207  	lower_suite.expectBundled(t, bundled{
  2208  		files: map[string]string{
  2209  			"/entry.js": `
  2210  				class T {
  2211  					#a() { return 'a'; }
  2212  					#b() { return 'b'; }
  2213  					static c;
  2214  					d() { console.log(this.#a()); }
  2215  				}
  2216  				new T().d();
  2217  			`,
  2218  		},
  2219  		entryPaths: []string{"/entry.js"},
  2220  		options: config.Options{
  2221  			Mode:                  config.ModeBundle,
  2222  			AbsOutputFile:         "/out.js",
  2223  			UnsupportedJSFeatures: compat.ClassPrivateMethod,
  2224  		},
  2225  	})
  2226  }
  2227  
  2228  // See https://github.com/evanw/esbuild/issues/1493 for more information
  2229  func TestLowerNullishCoalescingAssignmentIssue1493(t *testing.T) {
  2230  	lower_suite.expectBundled(t, bundled{
  2231  		files: map[string]string{
  2232  			"/entry.js": `
  2233  				export class A {
  2234  					#a;
  2235  					f() {
  2236  						this.#a ??= 1;
  2237  					}
  2238  				}
  2239  			`,
  2240  		},
  2241  		entryPaths: []string{"/entry.js"},
  2242  		options: config.Options{
  2243  			Mode:                  config.ModeBundle,
  2244  			AbsOutputFile:         "/out.js",
  2245  			UnsupportedJSFeatures: compat.LogicalAssignment,
  2246  		},
  2247  	})
  2248  }
  2249  
  2250  func TestStaticClassBlockESNext(t *testing.T) {
  2251  	lower_suite.expectBundled(t, bundled{
  2252  		files: map[string]string{
  2253  			"/entry.js": `
  2254  				class A {
  2255  					static {}
  2256  					static {
  2257  						this.thisField++
  2258  						A.classField++
  2259  						super.superField = super.superField + 1
  2260  						super.superField++
  2261  					}
  2262  				}
  2263  				let B = class {
  2264  					static {}
  2265  					static {
  2266  						this.thisField++
  2267  						super.superField = super.superField + 1
  2268  						super.superField++
  2269  					}
  2270  				}
  2271  			`,
  2272  		},
  2273  		entryPaths: []string{"/entry.js"},
  2274  		options: config.Options{
  2275  			Mode:          config.ModeBundle,
  2276  			AbsOutputFile: "/out.js",
  2277  		},
  2278  	})
  2279  }
  2280  
  2281  func TestStaticClassBlockES2021(t *testing.T) {
  2282  	lower_suite.expectBundled(t, bundled{
  2283  		files: map[string]string{
  2284  			"/entry.js": `
  2285  				class A {
  2286  					static {}
  2287  					static {
  2288  						this.thisField++
  2289  						A.classField++
  2290  						super.superField = super.superField + 1
  2291  						super.superField++
  2292  					}
  2293  				}
  2294  				let B = class {
  2295  					static {}
  2296  					static {
  2297  						this.thisField++
  2298  						super.superField = super.superField + 1
  2299  						super.superField++
  2300  					}
  2301  				}
  2302  			`,
  2303  		},
  2304  		entryPaths: []string{"/entry.js"},
  2305  		options: config.Options{
  2306  			Mode:                  config.ModeBundle,
  2307  			AbsOutputFile:         "/out.js",
  2308  			UnsupportedJSFeatures: es(2021),
  2309  		},
  2310  	})
  2311  }
  2312  
  2313  func TestLowerRegExpNameCollision(t *testing.T) {
  2314  	lower_suite.expectBundled(t, bundled{
  2315  		files: map[string]string{
  2316  			"/entry.js": `
  2317  				export function foo(RegExp) {
  2318  					return new RegExp(/./d, 'd')
  2319  				}
  2320  			`,
  2321  		},
  2322  		entryPaths: []string{"/entry.js"},
  2323  		options: config.Options{
  2324  			Mode:                  config.ModeBundle,
  2325  			AbsOutputFile:         "/out.js",
  2326  			UnsupportedJSFeatures: es(2021),
  2327  		},
  2328  	})
  2329  }
  2330  
  2331  func TestLowerForAwait2017(t *testing.T) {
  2332  	lower_suite.expectBundled(t, bundled{
  2333  		files: map[string]string{
  2334  			"/entry.js": `
  2335  				export default [
  2336  					async () => { for await (x of y) z(x) },
  2337  					async () => { for await (x.y of y) z(x) },
  2338  					async () => { for await (let x of y) z(x) },
  2339  					async () => { for await (const x of y) z(x) },
  2340  					async () => { label: for await (const x of y) break label },
  2341  					async () => { label: for await (const x of y) continue label },
  2342  				]
  2343  			`,
  2344  		},
  2345  		entryPaths: []string{"/entry.js"},
  2346  		options: config.Options{
  2347  			Mode:                  config.ModePassThrough,
  2348  			AbsOutputFile:         "/out.js",
  2349  			UnsupportedJSFeatures: es(2017),
  2350  		},
  2351  	})
  2352  }
  2353  
  2354  func TestLowerForAwait2015(t *testing.T) {
  2355  	lower_suite.expectBundled(t, bundled{
  2356  		files: map[string]string{
  2357  			"/entry.js": `
  2358  				export default [
  2359  					async () => { for await (x of y) z(x) },
  2360  					async () => { for await (x.y of y) z(x) },
  2361  					async () => { for await (let x of y) z(x) },
  2362  					async () => { for await (const x of y) z(x) },
  2363  					async () => { label: for await (const x of y) break label },
  2364  					async () => { label: for await (const x of y) continue label },
  2365  				]
  2366  			`,
  2367  		},
  2368  		entryPaths: []string{"/entry.js"},
  2369  		options: config.Options{
  2370  			Mode:                  config.ModePassThrough,
  2371  			AbsOutputFile:         "/out.js",
  2372  			UnsupportedJSFeatures: es(2015),
  2373  		},
  2374  	})
  2375  }
  2376  
  2377  func TestLowerNestedFunctionDirectEval(t *testing.T) {
  2378  	lower_suite.expectBundled(t, bundled{
  2379  		files: map[string]string{
  2380  			"/1.js": "if (foo) { function x() {} }",
  2381  			"/2.js": "if (foo) { function x() {} eval('') }",
  2382  			"/3.js": "if (foo) { function x() {} if (bar) { eval('') } }",
  2383  			"/4.js": "if (foo) { eval(''); function x() {} }",
  2384  			"/5.js": "'use strict'; if (foo) { function x() {} }",
  2385  			"/6.js": "'use strict'; if (foo) { function x() {} eval('') }",
  2386  			"/7.js": "'use strict'; if (foo) { function x() {} if (bar) { eval('') } }",
  2387  			"/8.js": "'use strict'; if (foo) { eval(''); function x() {} }",
  2388  		},
  2389  		entryPaths: []string{
  2390  			"/1.js",
  2391  			"/2.js",
  2392  			"/3.js",
  2393  			"/4.js",
  2394  			"/5.js",
  2395  			"/6.js",
  2396  			"/7.js",
  2397  			"/8.js",
  2398  		},
  2399  		options: config.Options{
  2400  			Mode:         config.ModePassThrough,
  2401  			AbsOutputDir: "/out",
  2402  		},
  2403  	})
  2404  }
  2405  
  2406  func TestJavaScriptDecoratorsESNext(t *testing.T) {
  2407  	lower_suite.expectBundled(t, bundled{
  2408  		files: map[string]string{
  2409  			"/entry.js": `
  2410  				@x.y()
  2411  				@(new y.x)
  2412  				export default class Foo {
  2413  					@x @y mUndef
  2414  					@x @y mDef = 1
  2415  					@x @y method() { return new Foo }
  2416  					@x @y static sUndef
  2417  					@x @y static sDef = new Foo
  2418  					@x @y static sMethod() { return new Foo }
  2419  				}
  2420  			`,
  2421  		},
  2422  		entryPaths: []string{"/entry.js"},
  2423  		options: config.Options{
  2424  			Mode:          config.ModePassThrough,
  2425  			AbsOutputFile: "/out.js",
  2426  		},
  2427  	})
  2428  }
  2429  
  2430  func TestJavaScriptAutoAccessorESNext(t *testing.T) {
  2431  	lower_suite.expectBundled(t, bundled{
  2432  		files: map[string]string{
  2433  			"/js-define.js": `
  2434  				class Foo {
  2435  					accessor one = 1
  2436  					accessor #two = 2
  2437  					accessor [three()] = 3
  2438  
  2439  					static accessor four = 4
  2440  					static accessor #five = 5
  2441  					static accessor [six()] = 6
  2442  				}
  2443  			`,
  2444  			"/ts-define/ts-define.ts": `
  2445  				class Foo {
  2446  					accessor one = 1
  2447  					accessor #two = 2
  2448  					accessor [three()] = 3
  2449  
  2450  					static accessor four = 4
  2451  					static accessor #five = 5
  2452  					static accessor [six()] = 6
  2453  				}
  2454  				class Normal { accessor a = b; c = d }
  2455  				class Private { accessor #a = b; c = d }
  2456  				class StaticNormal { static accessor a = b; static c = d }
  2457  				class StaticPrivate { static accessor #a = b; static c = d }
  2458  			`,
  2459  			"/ts-define/tsconfig.json": `{
  2460  				"compilerOptions": {
  2461  					"useDefineForClassFields": true,
  2462  				},
  2463  			}`,
  2464  			"/ts-assign/ts-assign.ts": `
  2465  				class Foo {
  2466  					accessor one = 1
  2467  					accessor #two = 2
  2468  					accessor [three()] = 3
  2469  
  2470  					static accessor four = 4
  2471  					static accessor #five = 5
  2472  					static accessor [six()] = 6
  2473  				}
  2474  				class Normal { accessor a = b; c = d }
  2475  				class Private { accessor #a = b; c = d }
  2476  				class StaticNormal { static accessor a = b; static c = d }
  2477  				class StaticPrivate { static accessor #a = b; static c = d }
  2478  			`,
  2479  			"/ts-assign/tsconfig.json": `{
  2480  				"compilerOptions": {
  2481  					"useDefineForClassFields": false,
  2482  				},
  2483  			}`,
  2484  		},
  2485  		entryPaths: []string{
  2486  			"/js-define.js",
  2487  			"/ts-define/ts-define.ts",
  2488  			"/ts-assign/ts-assign.ts",
  2489  		},
  2490  		options: config.Options{
  2491  			Mode:         config.ModePassThrough,
  2492  			AbsOutputDir: "/out",
  2493  		},
  2494  	})
  2495  }
  2496  
  2497  func TestJavaScriptAutoAccessorES2022(t *testing.T) {
  2498  	lower_suite.expectBundled(t, bundled{
  2499  		files: map[string]string{
  2500  			"/js-define.js": `
  2501  				class Foo {
  2502  					accessor one = 1
  2503  					accessor #two = 2
  2504  					accessor [three()] = 3
  2505  
  2506  					static accessor four = 4
  2507  					static accessor #five = 5
  2508  					static accessor [six()] = 6
  2509  				}
  2510  			`,
  2511  			"/ts-define/ts-define.ts": `
  2512  				class Foo {
  2513  					accessor one = 1
  2514  					accessor #two = 2
  2515  					accessor [three()] = 3
  2516  
  2517  					static accessor four = 4
  2518  					static accessor #five = 5
  2519  					static accessor [six()] = 6
  2520  				}
  2521  				class Normal { accessor a = b; c = d }
  2522  				class Private { accessor #a = b; c = d }
  2523  				class StaticNormal { static accessor a = b; static c = d }
  2524  				class StaticPrivate { static accessor #a = b; static c = d }
  2525  			`,
  2526  			"/ts-define/tsconfig.json": `{
  2527  				"compilerOptions": {
  2528  					"useDefineForClassFields": true,
  2529  				},
  2530  			}`,
  2531  			"/ts-assign/ts-assign.ts": `
  2532  				class Foo {
  2533  					accessor one = 1
  2534  					accessor #two = 2
  2535  					accessor [three()] = 3
  2536  
  2537  					static accessor four = 4
  2538  					static accessor #five = 5
  2539  					static accessor [six()] = 6
  2540  				}
  2541  				class Normal { accessor a = b; c = d }
  2542  				class Private { accessor #a = b; c = d }
  2543  				class StaticNormal { static accessor a = b; static c = d }
  2544  				class StaticPrivate { static accessor #a = b; static c = d }
  2545  			`,
  2546  			"/ts-assign/tsconfig.json": `{
  2547  				"compilerOptions": {
  2548  					"useDefineForClassFields": false,
  2549  				},
  2550  			}`,
  2551  		},
  2552  		entryPaths: []string{
  2553  			"/js-define.js",
  2554  			"/ts-define/ts-define.ts",
  2555  			"/ts-assign/ts-assign.ts",
  2556  		},
  2557  		options: config.Options{
  2558  			Mode:                  config.ModePassThrough,
  2559  			AbsOutputDir:          "/out",
  2560  			UnsupportedJSFeatures: es(2022),
  2561  		},
  2562  	})
  2563  }
  2564  
  2565  func TestJavaScriptAutoAccessorES2021(t *testing.T) {
  2566  	lower_suite.expectBundled(t, bundled{
  2567  		files: map[string]string{
  2568  			"/js-define.js": `
  2569  				class Foo {
  2570  					accessor one = 1
  2571  					accessor #two = 2
  2572  					accessor [three()] = 3
  2573  
  2574  					static accessor four = 4
  2575  					static accessor #five = 5
  2576  					static accessor [six()] = 6
  2577  				}
  2578  			`,
  2579  			"/ts-define/ts-define.ts": `
  2580  				class Foo {
  2581  					accessor one = 1
  2582  					accessor #two = 2
  2583  					accessor [three()] = 3
  2584  
  2585  					static accessor four = 4
  2586  					static accessor #five = 5
  2587  					static accessor [six()] = 6
  2588  				}
  2589  				class Normal { accessor a = b; c = d }
  2590  				class Private { accessor #a = b; c = d }
  2591  				class StaticNormal { static accessor a = b; static c = d }
  2592  				class StaticPrivate { static accessor #a = b; static c = d }
  2593  			`,
  2594  			"/ts-define/tsconfig.json": `{
  2595  				"compilerOptions": {
  2596  					"useDefineForClassFields": true,
  2597  				},
  2598  			}`,
  2599  			"/ts-assign/ts-assign.ts": `
  2600  				class Foo {
  2601  					accessor one = 1
  2602  					accessor #two = 2
  2603  					accessor [three()] = 3
  2604  
  2605  					static accessor four = 4
  2606  					static accessor #five = 5
  2607  					static accessor [six()] = 6
  2608  				}
  2609  				class Normal { accessor a = b; c = d }
  2610  				class Private { accessor #a = b; c = d }
  2611  				class StaticNormal { static accessor a = b; static c = d }
  2612  				class StaticPrivate { static accessor #a = b; static c = d }
  2613  			`,
  2614  			"/ts-assign/tsconfig.json": `{
  2615  				"compilerOptions": {
  2616  					"useDefineForClassFields": false,
  2617  				},
  2618  			}`,
  2619  		},
  2620  		entryPaths: []string{
  2621  			"/js-define.js",
  2622  			"/ts-define/ts-define.ts",
  2623  			"/ts-assign/ts-assign.ts",
  2624  		},
  2625  		options: config.Options{
  2626  			Mode:                  config.ModePassThrough,
  2627  			AbsOutputDir:          "/out",
  2628  			UnsupportedJSFeatures: es(2021),
  2629  		},
  2630  	})
  2631  }
  2632  
  2633  func TestLowerUsing(t *testing.T) {
  2634  	lower_suite.expectBundled(t, bundled{
  2635  		files: map[string]string{
  2636  			"/entry.js": `
  2637  				using a = b
  2638  				await using c = d
  2639  				if (nested) {
  2640  					using x = 1
  2641  					await using y = 2
  2642  				}
  2643  
  2644  				function foo() {
  2645  					using a = b
  2646  					if (nested) {
  2647  						using x = 1
  2648  					}
  2649  				}
  2650  
  2651  				async function bar() {
  2652  					using a = b
  2653  					await using c = d
  2654  					if (nested) {
  2655  						using x = 1
  2656  						await using y = 2
  2657  					}
  2658  				}
  2659  			`,
  2660  			"/loops.js": `
  2661  				for (using a of b) c(() => a)
  2662  				for (await using d of e) f(() => d)
  2663  				for await (using g of h) i(() => g)
  2664  				for await (await using j of k) l(() => j)
  2665  
  2666  				if (nested) {
  2667  					for (using a of b) c(() => a)
  2668  					for (await using d of e) f(() => d)
  2669  					for await (using g of h) i(() => g)
  2670  					for await (await using j of k) l(() => j)
  2671  				}
  2672  
  2673  				function foo() {
  2674  					for (using a of b) c(() => a)
  2675  				}
  2676  
  2677  				async function bar() {
  2678  					for (using a of b) c(() => a)
  2679  					for (await using d of e) f(() => d)
  2680  					for await (using g of h) i(() => g)
  2681  					for await (await using j of k) l(() => j)
  2682  				}
  2683  			`,
  2684  			"/switch.js": `
  2685  				using x = y
  2686  				switch (foo) {
  2687  					case 0: using c = d
  2688  					default: using e = f
  2689  				}
  2690  				switch (foo) {
  2691  					case 0: await using c = d
  2692  					default: using e = f
  2693  				}
  2694  
  2695  				async function foo() {
  2696  					using x = y
  2697  					switch (foo) {
  2698  						case 0: using c = d
  2699  						default: using e = f
  2700  					}
  2701  					switch (foo) {
  2702  						case 0: await using c = d
  2703  						default: using e = f
  2704  					}
  2705  				}
  2706  			`,
  2707  		},
  2708  		entryPaths: []string{
  2709  			"/entry.js",
  2710  			"/loops.js",
  2711  			"/switch.js",
  2712  		},
  2713  		options: config.Options{
  2714  			Mode:                  config.ModePassThrough,
  2715  			AbsOutputDir:          "/out",
  2716  			UnsupportedJSFeatures: compat.Using,
  2717  		},
  2718  	})
  2719  }
  2720  
  2721  func TestLowerUsingUnsupportedAsync(t *testing.T) {
  2722  	lower_suite.expectBundled(t, bundled{
  2723  		files: map[string]string{
  2724  			"/entry.js": `
  2725  				function foo() {
  2726  					using a = b
  2727  					if (nested) {
  2728  						using x = 1
  2729  					}
  2730  				}
  2731  
  2732  				async function bar() {
  2733  					using a = b
  2734  					await using c = d
  2735  					if (nested) {
  2736  						using x = 1
  2737  						await using y = 2
  2738  					}
  2739  				}
  2740  			`,
  2741  			"/loops.js": `
  2742  				for (using a of b) c(() => a)
  2743  
  2744  				if (nested) {
  2745  					for (using a of b) c(() => a)
  2746  				}
  2747  
  2748  				function foo() {
  2749  					for (using a of b) c(() => a)
  2750  				}
  2751  
  2752  				async function bar() {
  2753  					for (using a of b) c(() => a)
  2754  					for (await using d of e) f(() => d)
  2755  				}
  2756  			`,
  2757  			"/switch.js": `
  2758  				using x = y
  2759  				switch (foo) {
  2760  					case 0: using c = d
  2761  					default: using e = f
  2762  				}
  2763  
  2764  				async function foo() {
  2765  					using x = y
  2766  					switch (foo) {
  2767  						case 0: using c = d
  2768  						default: using e = f
  2769  					}
  2770  					switch (foo) {
  2771  						case 0: await using c = d
  2772  						default: using e = f
  2773  					}
  2774  				}
  2775  			`,
  2776  		},
  2777  		entryPaths: []string{
  2778  			"/entry.js",
  2779  			"/loops.js",
  2780  			"/switch.js",
  2781  		},
  2782  		options: config.Options{
  2783  			Mode:                  config.ModePassThrough,
  2784  			AbsOutputDir:          "/out",
  2785  			UnsupportedJSFeatures: compat.AsyncAwait | compat.TopLevelAwait,
  2786  		},
  2787  	})
  2788  }
  2789  
  2790  func TestLowerUsingUnsupportedUsingAndAsync(t *testing.T) {
  2791  	lower_suite.expectBundled(t, bundled{
  2792  		files: map[string]string{
  2793  			"/entry.js": `
  2794  				function foo() {
  2795  					using a = b
  2796  					if (nested) {
  2797  						using x = 1
  2798  					}
  2799  				}
  2800  
  2801  				async function bar() {
  2802  					using a = b
  2803  					await using c = d
  2804  					if (nested) {
  2805  						using x = 1
  2806  						await using y = 2
  2807  					}
  2808  				}
  2809  			`,
  2810  			"/loops.js": `
  2811  				for (using a of b) c(() => a)
  2812  
  2813  				if (nested) {
  2814  					for (using a of b) c(() => a)
  2815  				}
  2816  
  2817  				function foo() {
  2818  					for (using a of b) c(() => a)
  2819  				}
  2820  
  2821  				async function bar() {
  2822  					for (using a of b) c(() => a)
  2823  					for (await using d of e) f(() => d)
  2824  				}
  2825  			`,
  2826  			"/switch.js": `
  2827  				using x = y
  2828  				switch (foo) {
  2829  					case 0: using c = d
  2830  					default: using e = f
  2831  				}
  2832  
  2833  				async function foo() {
  2834  					using x = y
  2835  					switch (foo) {
  2836  						case 0: using c = d
  2837  						default: using e = f
  2838  					}
  2839  					switch (foo) {
  2840  						case 0: await using c = d
  2841  						default: using e = f
  2842  					}
  2843  				}
  2844  			`,
  2845  		},
  2846  		entryPaths: []string{
  2847  			"/entry.js",
  2848  			"/loops.js",
  2849  			"/switch.js",
  2850  		},
  2851  		options: config.Options{
  2852  			Mode:                  config.ModePassThrough,
  2853  			AbsOutputDir:          "/out",
  2854  			UnsupportedJSFeatures: compat.Using | compat.AsyncAwait | compat.TopLevelAwait,
  2855  		},
  2856  	})
  2857  }
  2858  
  2859  func TestLowerUsingHoisting(t *testing.T) {
  2860  	lower_suite.expectBundled(t, bundled{
  2861  		files: map[string]string{
  2862  			"/hoist-use-strict.js": `
  2863  				"use strict"
  2864  				using a = b
  2865  				function foo() {
  2866  					"use strict"
  2867  					using a = b
  2868  				}
  2869  			`,
  2870  			"/hoist-directive.js": `
  2871  				"use wtf"
  2872  				using a = b
  2873  				function foo() {
  2874  					"use wtf"
  2875  					using a = b
  2876  				}
  2877  			`,
  2878  			"/hoist-import.js": `
  2879  				using a = b
  2880  				import "./foo"
  2881  				using c = d
  2882  			`,
  2883  			"/hoist-export-star.js": `
  2884  				using a = b
  2885  				export * from './foo'
  2886  				using c = d
  2887  			`,
  2888  			"/hoist-export-from.js": `
  2889  				using a = b
  2890  				export {x, y} from './foo'
  2891  				using c = d
  2892  			`,
  2893  			"/hoist-export-clause.js": `
  2894  				using a = b
  2895  				export {a, c as 'c!'}
  2896  				using c = d
  2897  			`,
  2898  			"/hoist-export-local-direct.js": `
  2899  				using a = b
  2900  				export var ac1 = [a, c], { x: [x1] } = foo
  2901  				export let a1 = a, { y: [y1] } = foo
  2902  				export const c1 = c, { z: [z1] } = foo
  2903  				var ac2 = [a, c], { x: [x2] } = foo
  2904  				let a2 = a, { y: [y2] } = foo
  2905  				const c2 = c, { z: [z2] } = foo
  2906  				using c = d
  2907  			`,
  2908  			"/hoist-export-local-indirect.js": `
  2909  				using a = b
  2910  				var ac1 = [a, c], { x: [x1] } = foo
  2911  				let a1 = a, { y: [y1] } = foo
  2912  				const c1 = c, { z: [z1] } = foo
  2913  				var ac2 = [a, c], { x: [x2] } = foo
  2914  				let a2 = a, { y: [y2] } = foo
  2915  				const c2 = c, { z: [z2] } = foo
  2916  				using c = d
  2917  				export {x1, y1, z1}
  2918  			`,
  2919  			"/hoist-export-class-direct.js": `
  2920  				using a = b
  2921  				export class Foo1 { ac = [a, c] }
  2922  				export class Bar1 { ac = [a, c, Bar1] }
  2923  				class Foo2 { ac = [a, c] }
  2924  				class Bar2 { ac = [a, c, Bar2] }
  2925  				using c = d
  2926  			`,
  2927  			"/hoist-export-class-indirect.js": `
  2928  				using a = b
  2929  				class Foo1 { ac = [a, c] }
  2930  				class Bar1 { ac = [a, c, Bar1] }
  2931  				class Foo2 { ac = [a, c] }
  2932  				class Bar2 { ac = [a, c, Bar2] }
  2933  				using c = d
  2934  				export {Foo1, Bar1}
  2935  			`,
  2936  			"/hoist-export-function-direct.js": `
  2937  				using a = b
  2938  				export function foo1() { return [a, c] }
  2939  				export function bar1() { return [a, c, bar1] }
  2940  				function foo2() { return [a, c] }
  2941  				function bar2() { return [a, c, bar2] }
  2942  				using c = d
  2943  			`,
  2944  			"/hoist-export-function-indirect.js": `
  2945  				using a = b
  2946  				function foo1() { return [a, c] }
  2947  				function bar1() { return [a, c, bar1] }
  2948  				function foo2() { return [a, c] }
  2949  				function bar2() { return [a, c, bar2] }
  2950  				using c = d
  2951  				export {foo1, bar1}
  2952  			`,
  2953  			"/hoist-export-default-class-name-unused.js": `
  2954  				using a = b
  2955  				export default class Foo {
  2956  					ac = [a, c]
  2957  				}
  2958  				using c = d
  2959  			`,
  2960  			"/hoist-export-default-class-name-used.js": `
  2961  				using a = b
  2962  				export default class Foo {
  2963  					ac = [a, c, Foo]
  2964  				}
  2965  				using c = d
  2966  			`,
  2967  			"/hoist-export-default-class-anonymous.js": `
  2968  				using a = b
  2969  				export default class {
  2970  					ac = [a, c]
  2971  				}
  2972  				using c = d
  2973  			`,
  2974  			"/hoist-export-default-function-name-unused.js": `
  2975  				using a = b
  2976  				export default function foo() {
  2977  					return [a, c]
  2978  				}
  2979  				using c = d
  2980  			`,
  2981  			"/hoist-export-default-function-name-used.js": `
  2982  				using a = b
  2983  				export default function foo() {
  2984  					return [a, c, foo]
  2985  				}
  2986  				using c = d
  2987  			`,
  2988  			"/hoist-export-default-function-anonymous.js": `
  2989  				using a = b
  2990  				export default function() {
  2991  					return [a, c]
  2992  				}
  2993  				using c = d
  2994  			`,
  2995  			"/hoist-export-default-expr.js": `
  2996  				using a = b
  2997  				export default [a, c]
  2998  				using c = d
  2999  			`,
  3000  		},
  3001  		entryPaths: []string{
  3002  			"/hoist-use-strict.js",
  3003  			"/hoist-directive.js",
  3004  			"/hoist-import.js",
  3005  			"/hoist-export-star.js",
  3006  			"/hoist-export-from.js",
  3007  			"/hoist-export-clause.js",
  3008  			"/hoist-export-local-direct.js",
  3009  			"/hoist-export-local-indirect.js",
  3010  			"/hoist-export-class-direct.js",
  3011  			"/hoist-export-class-indirect.js",
  3012  			"/hoist-export-function-direct.js",
  3013  			"/hoist-export-function-indirect.js",
  3014  			"/hoist-export-default-class-name-unused.js",
  3015  			"/hoist-export-default-class-name-used.js",
  3016  			"/hoist-export-default-class-anonymous.js",
  3017  			"/hoist-export-default-function-name-unused.js",
  3018  			"/hoist-export-default-function-name-used.js",
  3019  			"/hoist-export-default-function-anonymous.js",
  3020  			"/hoist-export-default-expr.js",
  3021  		},
  3022  		options: config.Options{
  3023  			Mode:                  config.ModePassThrough,
  3024  			AbsOutputDir:          "/out",
  3025  			UnsupportedJSFeatures: compat.Using,
  3026  		},
  3027  	})
  3028  }
  3029  
  3030  func TestLowerUsingInsideTSNamespace(t *testing.T) {
  3031  	lower_suite.expectBundled(t, bundled{
  3032  		files: map[string]string{
  3033  			"/entry.ts": `
  3034  				namespace ns {
  3035  					export let a = b
  3036  					using c = d
  3037  					export let e = f
  3038  				}
  3039  			`,
  3040  		},
  3041  		entryPaths: []string{"/entry.ts"},
  3042  		options: config.Options{
  3043  			Mode:                  config.ModePassThrough,
  3044  			AbsOutputDir:          "/out",
  3045  			UnsupportedJSFeatures: compat.Using,
  3046  		},
  3047  	})
  3048  }
  3049  
  3050  func TestLowerAsyncGenerator(t *testing.T) {
  3051  	lower_suite.expectBundled(t, bundled{
  3052  		files: map[string]string{
  3053  			"/entry.ts": `
  3054  				async function* foo() {
  3055  					yield
  3056  					yield x
  3057  					yield *x
  3058  					await using x = await y
  3059  					for await (let x of y) {}
  3060  					for await (await using x of y) {}
  3061  				}
  3062  				foo = async function* () {
  3063  					yield
  3064  					yield x
  3065  					yield *x
  3066  					await using x = await y
  3067  					for await (let x of y) {}
  3068  					for await (await using x of y) {}
  3069  				}
  3070  				foo = { async *bar () {
  3071  					yield
  3072  					yield x
  3073  					yield *x
  3074  					await using x = await y
  3075  					for await (let x of y) {}
  3076  					for await (await using x of y) {}
  3077  				} }
  3078  				class Foo { async *bar () {
  3079  					yield
  3080  					yield x
  3081  					yield *x
  3082  					await using x = await y
  3083  					for await (let x of y) {}
  3084  					for await (await using x of y) {}
  3085  				} }
  3086  				Foo = class { async *bar () {
  3087  					yield
  3088  					yield x
  3089  					yield *x
  3090  					await using x = await y
  3091  					for await (let x of y) {}
  3092  					for await (await using x of y) {}
  3093  				} }
  3094  				async function bar() {
  3095  					await using x = await y
  3096  					for await (let x of y) {}
  3097  					for await (await using x of y) {}
  3098  				}
  3099  			`,
  3100  		},
  3101  		entryPaths: []string{"/entry.ts"},
  3102  		options: config.Options{
  3103  			Mode:                  config.ModePassThrough,
  3104  			AbsOutputDir:          "/out",
  3105  			UnsupportedJSFeatures: compat.AsyncGenerator,
  3106  		},
  3107  	})
  3108  }
  3109  
  3110  func TestLowerAsyncGeneratorNoAwait(t *testing.T) {
  3111  	lower_suite.expectBundled(t, bundled{
  3112  		files: map[string]string{
  3113  			"/entry.ts": `
  3114  				async function* foo() {
  3115  					yield
  3116  					yield x
  3117  					yield *x
  3118  					await using x = await y
  3119  					for await (let x of y) {}
  3120  					for await (await using x of y) {}
  3121  				}
  3122  				foo = async function* () {
  3123  					yield
  3124  					yield x
  3125  					yield *x
  3126  					await using x = await y
  3127  					for await (let x of y) {}
  3128  					for await (await using x of y) {}
  3129  				}
  3130  				foo = { async *bar () {
  3131  					yield
  3132  					yield x
  3133  					yield *x
  3134  					await using x = await y
  3135  					for await (let x of y) {}
  3136  					for await (await using x of y) {}
  3137  				} }
  3138  				class Foo { async *bar () {
  3139  					yield
  3140  					yield x
  3141  					yield *x
  3142  					await using x = await y
  3143  					for await (let x of y) {}
  3144  					for await (await using x of y) {}
  3145  				} }
  3146  				Foo = class { async *bar () {
  3147  					yield
  3148  					yield x
  3149  					yield *x
  3150  					await using x = await y
  3151  					for await (let x of y) {}
  3152  					for await (await using x of y) {}
  3153  				} }
  3154  				async function bar() {
  3155  					await using x = await y
  3156  					for await (let x of y) {}
  3157  					for await (await using x of y) {}
  3158  				}
  3159  			`,
  3160  		},
  3161  		entryPaths: []string{"/entry.ts"},
  3162  		options: config.Options{
  3163  			Mode:                  config.ModePassThrough,
  3164  			AbsOutputDir:          "/out",
  3165  			UnsupportedJSFeatures: compat.AsyncGenerator | compat.AsyncAwait,
  3166  		},
  3167  	})
  3168  }
  3169  
  3170  func TestJavaScriptDecoratorsBundleIssue3768(t *testing.T) {
  3171  	lower_suite.expectBundled(t, bundled{
  3172  		files: map[string]string{
  3173  			"/base-instance-method.js":   `class Foo { @dec foo() { return Foo } }`,
  3174  			"/base-instance-field.js":    `class Foo { @dec foo = Foo }`,
  3175  			"/base-instance-accessor.js": `class Foo { @dec accessor foo = Foo }`,
  3176  
  3177  			"/base-static-method.js":   `class Foo { @dec static foo() { return Foo } }`,
  3178  			"/base-static-field.js":    `class Foo { @dec static foo = Foo }`,
  3179  			"/base-static-accessor.js": `class Foo { @dec static accessor foo = Foo }`,
  3180  
  3181  			"/derived-instance-method.js":   `class Foo extends Bar { @dec foo() { return Foo } }`,
  3182  			"/derived-instance-field.js":    `class Foo extends Bar { @dec foo = Foo }`,
  3183  			"/derived-instance-accessor.js": `class Foo extends Bar { @dec accessor foo = Foo }`,
  3184  
  3185  			"/derived-static-method.js":   `class Foo extends Bar { @dec static foo() { return Foo } }`,
  3186  			"/derived-static-field.js":    `class Foo extends Bar { @dec static foo = Foo }`,
  3187  			"/derived-static-accessor.js": `class Foo extends Bar { @dec static accessor foo = Foo }`,
  3188  		},
  3189  		entryPaths: []string{"/*"},
  3190  		options: config.Options{
  3191  			Mode:                  config.ModeBundle,
  3192  			AbsOutputDir:          "/out",
  3193  			UnsupportedJSFeatures: compat.Decorators,
  3194  		},
  3195  	})
  3196  }