github.com/evanw/esbuild@v0.21.4/internal/bundler_tests/bundler_tsconfig_test.go (about) 1 package bundler_tests 2 3 import ( 4 "testing" 5 6 "github.com/evanw/esbuild/internal/config" 7 ) 8 9 var tsconfig_suite = suite{ 10 name: "tsconfig", 11 } 12 13 func TestTsconfigPaths(t *testing.T) { 14 tsconfig_suite.expectBundled(t, bundled{ 15 files: map[string]string{ 16 "/Users/user/project/entry.ts": ` 17 import baseurl_dot from './baseurl_dot' 18 import baseurl_nested from './baseurl_nested' 19 console.log(baseurl_dot, baseurl_nested) 20 `, 21 22 // Tests with "baseUrl": "." 23 "/Users/user/project/baseurl_dot/index.ts": ` 24 import test0 from 'test0' 25 import test1 from 'test1/foo' 26 import test2 from 'test2/foo' 27 import test3 from 'test3/foo' 28 import test4 from 'test4/foo' 29 import test5 from 'test5/foo' 30 import absoluteIn from './absolute-in' 31 import absoluteInStar from './absolute-in-star' 32 import absoluteOut from './absolute-out' 33 import absoluteOutStar from './absolute-out-star' 34 export default { 35 test0, 36 test1, 37 test2, 38 test3, 39 test4, 40 test5, 41 absoluteIn, 42 absoluteInStar, 43 absoluteOut, 44 absoluteOutStar, 45 } 46 `, 47 "/Users/user/project/baseurl_dot/tsconfig.json": ` 48 { 49 "compilerOptions": { 50 "baseUrl": ".", 51 "paths": { 52 "test0": ["./test0-success.ts"], 53 "test1/*": ["./test1-success.ts"], 54 "test2/*": ["./test2-success/*"], 55 "t*t3/foo": ["./test3-succ*s.ts"], 56 "test4/*": ["./test4-first/*", "./test4-second/*"], 57 "test5/*": ["./test5-first/*", "./test5-second/*"], 58 "/virtual-in/test": ["./actual/test"], 59 "/virtual-in-star/*": ["./actual/*"], 60 "/virtual-out/test": ["/Users/user/project/baseurl_dot/actual/test"], 61 "/virtual-out-star/*": ["/Users/user/project/baseurl_dot/actual/*"], 62 } 63 } 64 } 65 `, 66 "/Users/user/project/baseurl_dot/test0-success.ts": ` 67 export default 'test0-success' 68 `, 69 "/Users/user/project/baseurl_dot/test1-success.ts": ` 70 export default 'test1-success' 71 `, 72 "/Users/user/project/baseurl_dot/test2-success/foo.ts": ` 73 export default 'test2-success' 74 `, 75 "/Users/user/project/baseurl_dot/test3-success.ts": ` 76 export default 'test3-success' 77 `, 78 "/Users/user/project/baseurl_dot/test4-first/foo.ts": ` 79 export default 'test4-success' 80 `, 81 "/Users/user/project/baseurl_dot/test5-second/foo.ts": ` 82 export default 'test5-success' 83 `, 84 "/Users/user/project/baseurl_dot/absolute-in.ts": ` 85 export {default} from '/virtual-in/test' 86 `, 87 "/Users/user/project/baseurl_dot/absolute-in-star.ts": ` 88 export {default} from '/virtual-in-star/test' 89 `, 90 "/Users/user/project/baseurl_dot/absolute-out.ts": ` 91 export {default} from '/virtual-out/test' 92 `, 93 "/Users/user/project/baseurl_dot/absolute-out-star.ts": ` 94 export {default} from '/virtual-out-star/test' 95 `, 96 "/Users/user/project/baseurl_dot/actual/test.ts": ` 97 export default 'absolute-success' 98 `, 99 100 // Tests with "baseUrl": "nested" 101 "/Users/user/project/baseurl_nested/index.ts": ` 102 import test0 from 'test0' 103 import test1 from 'test1/foo' 104 import test2 from 'test2/foo' 105 import test3 from 'test3/foo' 106 import test4 from 'test4/foo' 107 import test5 from 'test5/foo' 108 import absoluteIn from './absolute-in' 109 import absoluteInStar from './absolute-in-star' 110 import absoluteOut from './absolute-out' 111 import absoluteOutStar from './absolute-out-star' 112 export default { 113 test0, 114 test1, 115 test2, 116 test3, 117 test4, 118 test5, 119 absoluteIn, 120 absoluteInStar, 121 absoluteOut, 122 absoluteOutStar, 123 } 124 `, 125 "/Users/user/project/baseurl_nested/tsconfig.json": ` 126 { 127 "compilerOptions": { 128 "baseUrl": "nested", 129 "paths": { 130 "test0": ["./test0-success.ts"], 131 "test1/*": ["./test1-success.ts"], 132 "test2/*": ["./test2-success/*"], 133 "t*t3/foo": ["./test3-succ*s.ts"], 134 "test4/*": ["./test4-first/*", "./test4-second/*"], 135 "test5/*": ["./test5-first/*", "./test5-second/*"], 136 "/virtual-in/test": ["./actual/test"], 137 "/virtual-in-star/*": ["./actual/*"], 138 "/virtual-out/test": ["/Users/user/project/baseurl_nested/nested/actual/test"], 139 "/virtual-out-star/*": ["/Users/user/project/baseurl_nested/nested/actual/*"], 140 } 141 } 142 } 143 `, 144 "/Users/user/project/baseurl_nested/nested/test0-success.ts": ` 145 export default 'test0-success' 146 `, 147 "/Users/user/project/baseurl_nested/nested/test1-success.ts": ` 148 export default 'test1-success' 149 `, 150 "/Users/user/project/baseurl_nested/nested/test2-success/foo.ts": ` 151 export default 'test2-success' 152 `, 153 "/Users/user/project/baseurl_nested/nested/test3-success.ts": ` 154 export default 'test3-success' 155 `, 156 "/Users/user/project/baseurl_nested/nested/test4-first/foo.ts": ` 157 export default 'test4-success' 158 `, 159 "/Users/user/project/baseurl_nested/nested/test5-second/foo.ts": ` 160 export default 'test5-success' 161 `, 162 "/Users/user/project/baseurl_nested/absolute-in.ts": ` 163 export {default} from '/virtual-in/test' 164 `, 165 "/Users/user/project/baseurl_nested/absolute-in-star.ts": ` 166 export {default} from '/virtual-in/test' 167 `, 168 "/Users/user/project/baseurl_nested/absolute-out.ts": ` 169 export {default} from '/virtual-out/test' 170 `, 171 "/Users/user/project/baseurl_nested/absolute-out-star.ts": ` 172 export {default} from '/virtual-out-star/test' 173 `, 174 "/Users/user/project/baseurl_nested/nested/actual/test.ts": ` 175 export default 'absolute-success' 176 `, 177 }, 178 entryPaths: []string{"/Users/user/project/entry.ts"}, 179 options: config.Options{ 180 Mode: config.ModeBundle, 181 AbsOutputFile: "/Users/user/project/out.js", 182 }, 183 }) 184 } 185 186 func TestTsconfigPathsNoBaseURL(t *testing.T) { 187 tsconfig_suite.expectBundled(t, bundled{ 188 files: map[string]string{ 189 "/Users/user/project/entry.ts": ` 190 import simple from './simple' 191 import extended from './extended' 192 console.log(simple, extended) 193 `, 194 195 // Tests with "baseUrl": "." 196 "/Users/user/project/simple/index.ts": ` 197 import test0 from 'test0' 198 import test1 from 'test1/foo' 199 import test2 from 'test2/foo' 200 import test3 from 'test3/foo' 201 import test4 from 'test4/foo' 202 import test5 from 'test5/foo' 203 import absolute from './absolute' 204 export default { 205 test0, 206 test1, 207 test2, 208 test3, 209 test4, 210 test5, 211 absolute, 212 } 213 `, 214 "/Users/user/project/simple/tsconfig.json": ` 215 { 216 "compilerOptions": { 217 "paths": { 218 "test0": ["./test0-success.ts"], 219 "test1/*": ["./test1-success.ts"], 220 "test2/*": ["./test2-success/*"], 221 "t*t3/foo": ["./test3-succ*s.ts"], 222 "test4/*": ["./test4-first/*", "./test4-second/*"], 223 "test5/*": ["./test5-first/*", "./test5-second/*"], 224 "/virtual/*": ["./actual/*"], 225 } 226 } 227 } 228 `, 229 "/Users/user/project/simple/test0-success.ts": ` 230 export default 'test0-success' 231 `, 232 "/Users/user/project/simple/test1-success.ts": ` 233 export default 'test1-success' 234 `, 235 "/Users/user/project/simple/test2-success/foo.ts": ` 236 export default 'test2-success' 237 `, 238 "/Users/user/project/simple/test3-success.ts": ` 239 export default 'test3-success' 240 `, 241 "/Users/user/project/simple/test4-first/foo.ts": ` 242 export default 'test4-success' 243 `, 244 "/Users/user/project/simple/test5-second/foo.ts": ` 245 export default 'test5-success' 246 `, 247 "/Users/user/project/simple/absolute.ts": ` 248 export {default} from '/virtual/test' 249 `, 250 "/Users/user/project/simple/actual/test.ts": ` 251 export default 'absolute-success' 252 `, 253 254 // Tests with "baseUrl": "nested" 255 "/Users/user/project/extended/index.ts": ` 256 import test0 from 'test0' 257 import test1 from 'test1/foo' 258 import test2 from 'test2/foo' 259 import test3 from 'test3/foo' 260 import test4 from 'test4/foo' 261 import test5 from 'test5/foo' 262 import absolute from './absolute' 263 export default { 264 test0, 265 test1, 266 test2, 267 test3, 268 test4, 269 test5, 270 absolute, 271 } 272 `, 273 "/Users/user/project/extended/tsconfig.json": ` 274 { 275 "extends": "./nested/tsconfig.json" 276 } 277 `, 278 "/Users/user/project/extended/nested/tsconfig.json": ` 279 { 280 "compilerOptions": { 281 "paths": { 282 "test0": ["./test0-success.ts"], 283 "test1/*": ["./test1-success.ts"], 284 "test2/*": ["./test2-success/*"], 285 "t*t3/foo": ["./test3-succ*s.ts"], 286 "test4/*": ["./test4-first/*", "./test4-second/*"], 287 "test5/*": ["./test5-first/*", "./test5-second/*"], 288 "/virtual/*": ["./actual/*"], 289 } 290 } 291 } 292 `, 293 "/Users/user/project/extended/nested/test0-success.ts": ` 294 export default 'test0-success' 295 `, 296 "/Users/user/project/extended/nested/test1-success.ts": ` 297 export default 'test1-success' 298 `, 299 "/Users/user/project/extended/nested/test2-success/foo.ts": ` 300 export default 'test2-success' 301 `, 302 "/Users/user/project/extended/nested/test3-success.ts": ` 303 export default 'test3-success' 304 `, 305 "/Users/user/project/extended/nested/test4-first/foo.ts": ` 306 export default 'test4-success' 307 `, 308 "/Users/user/project/extended/nested/test5-second/foo.ts": ` 309 export default 'test5-success' 310 `, 311 "/Users/user/project/extended/absolute.ts": ` 312 export {default} from '/virtual/test' 313 `, 314 "/Users/user/project/extended/nested/actual/test.ts": ` 315 export default 'absolute-success' 316 `, 317 }, 318 entryPaths: []string{"/Users/user/project/entry.ts"}, 319 options: config.Options{ 320 Mode: config.ModeBundle, 321 AbsOutputFile: "/Users/user/project/out.js", 322 }, 323 }) 324 } 325 326 func TestTsconfigBadPathsNoBaseURL(t *testing.T) { 327 tsconfig_suite.expectBundled(t, bundled{ 328 files: map[string]string{ 329 "/Users/user/project/entry.ts": ` 330 import "should-not-be-imported" 331 `, 332 "/Users/user/project/should-not-be-imported.ts": ` 333 `, 334 "/Users/user/project/tsconfig.json": ` 335 { 336 "compilerOptions": { 337 "paths": { 338 "test": [ 339 ".", 340 "..", 341 "./good", 342 ".\\good", 343 "../good", 344 "..\\good", 345 "/good", 346 "\\good", 347 "c:/good", 348 "c:\\good", 349 "C:/good", 350 "C:\\good", 351 352 "bad", 353 "@bad/core", 354 ".*/bad", 355 "..*/bad", 356 "c*:\\bad", 357 "c:*\\bad", 358 "http://bad" 359 ] 360 } 361 } 362 } 363 `, 364 }, 365 entryPaths: []string{"/Users/user/project/entry.ts"}, 366 options: config.Options{ 367 Mode: config.ModeBundle, 368 AbsOutputFile: "/Users/user/project/out.js", 369 }, 370 expectedScanLog: `Users/user/project/entry.ts: ERROR: Could not resolve "should-not-be-imported" 371 NOTE: Use the relative path "./should-not-be-imported" to reference the file "Users/user/project/should-not-be-imported.ts". Without the leading "./", the path "should-not-be-imported" is being interpreted as a package path instead. 372 Users/user/project/tsconfig.json: WARNING: Non-relative path "bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 373 Users/user/project/tsconfig.json: WARNING: Non-relative path "@bad/core" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 374 Users/user/project/tsconfig.json: WARNING: Non-relative path ".*/bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 375 Users/user/project/tsconfig.json: WARNING: Non-relative path "..*/bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 376 Users/user/project/tsconfig.json: WARNING: Non-relative path "c*:\\bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 377 Users/user/project/tsconfig.json: WARNING: Non-relative path "c:*\\bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 378 Users/user/project/tsconfig.json: WARNING: Non-relative path "http://bad" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 379 `, 380 }) 381 } 382 383 // https://github.com/evanw/esbuild/issues/913 384 func TestTsconfigPathsOverriddenBaseURL(t *testing.T) { 385 tsconfig_suite.expectBundled(t, bundled{ 386 files: map[string]string{ 387 "/Users/user/project/src/entry.ts": ` 388 import test from '#/test' 389 console.log(test) 390 `, 391 "/Users/user/project/src/test.ts": ` 392 export default 123 393 `, 394 "/Users/user/project/tsconfig.json": ` 395 { 396 "extends": "./tsconfig.paths.json", 397 "compilerOptions": { 398 "baseUrl": "./src" 399 } 400 } 401 `, 402 "/Users/user/project/tsconfig.paths.json": ` 403 { 404 "compilerOptions": { 405 "paths": { 406 "#/*": ["./*"] 407 } 408 } 409 } 410 `, 411 }, 412 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 413 options: config.Options{ 414 Mode: config.ModeBundle, 415 AbsOutputFile: "/Users/user/project/out.js", 416 }, 417 }) 418 } 419 420 func TestTsconfigPathsOverriddenBaseURLDifferentDir(t *testing.T) { 421 tsconfig_suite.expectBundled(t, bundled{ 422 files: map[string]string{ 423 "/Users/user/project/src/entry.ts": ` 424 import test from '#/test' 425 console.log(test) 426 `, 427 "/Users/user/project/src/test.ts": ` 428 export default 123 429 `, 430 "/Users/user/project/src/tsconfig.json": ` 431 { 432 "extends": "../tsconfig.paths.json", 433 "compilerOptions": { 434 "baseUrl": "./" 435 } 436 } 437 `, 438 "/Users/user/project/tsconfig.paths.json": ` 439 { 440 "compilerOptions": { 441 "paths": { 442 "#/*": ["./*"] 443 } 444 } 445 } 446 `, 447 }, 448 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 449 options: config.Options{ 450 Mode: config.ModeBundle, 451 AbsOutputFile: "/Users/user/project/out.js", 452 }, 453 }) 454 } 455 456 func TestTsconfigPathsMissingBaseURL(t *testing.T) { 457 tsconfig_suite.expectBundled(t, bundled{ 458 files: map[string]string{ 459 "/Users/user/project/src/entry.ts": ` 460 import test from '#/test' 461 console.log(test) 462 `, 463 "/Users/user/project/src/test.ts": ` 464 export default 123 465 `, 466 "/Users/user/project/src/tsconfig.json": ` 467 { 468 "extends": "../tsconfig.paths.json", 469 "compilerOptions": { 470 } 471 } 472 `, 473 "/Users/user/project/tsconfig.paths.json": ` 474 { 475 "compilerOptions": { 476 "paths": { 477 "#/*": ["./*"] 478 } 479 } 480 } 481 `, 482 }, 483 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 484 options: config.Options{ 485 Mode: config.ModeBundle, 486 AbsOutputFile: "/Users/user/project/out.js", 487 }, 488 expectedScanLog: `Users/user/project/src/entry.ts: ERROR: Could not resolve "#/test" 489 NOTE: You can mark the path "#/test" as external to exclude it from the bundle, which will remove this error and leave the unresolved path in the bundle. 490 `, 491 }) 492 } 493 494 func TestTsconfigPathsTypeOnly(t *testing.T) { 495 tsconfig_suite.expectBundled(t, bundled{ 496 files: map[string]string{ 497 "/Users/user/project/entry.ts": ` 498 import { fib } from "fib"; 499 500 console.log(fib(10)); 501 `, 502 "/Users/user/project/node_modules/fib/index.js": ` 503 export function fib(input) { 504 if (input < 2) { 505 return input; 506 } 507 return fib(input - 1) + fib(input - 2); 508 } 509 `, 510 "/Users/user/project/fib-local.d.ts": ` 511 export function fib(input: number): number; 512 `, 513 "/Users/user/project/tsconfig.json": ` 514 { 515 "compilerOptions": { 516 "baseUrl": ".", 517 "paths": { 518 "fib": ["fib-local.d.ts"] 519 } 520 } 521 } 522 `, 523 }, 524 entryPaths: []string{"/Users/user/project/entry.ts"}, 525 options: config.Options{ 526 Mode: config.ModeBundle, 527 AbsOutputFile: "/Users/user/project/out.js", 528 }, 529 }) 530 } 531 532 func TestTsconfigJSX(t *testing.T) { 533 tsconfig_suite.expectBundled(t, bundled{ 534 files: map[string]string{ 535 "/Users/user/project/entry.tsx": ` 536 console.log(<><div/><div/></>) 537 `, 538 "/Users/user/project/tsconfig.json": ` 539 { 540 "compilerOptions": { 541 "jsxFactory": "R.c", 542 "jsxFragmentFactory": "R.F" 543 } 544 } 545 `, 546 }, 547 entryPaths: []string{"/Users/user/project/entry.tsx"}, 548 options: config.Options{ 549 Mode: config.ModeBundle, 550 AbsOutputFile: "/Users/user/project/out.js", 551 }, 552 }) 553 } 554 555 func TestTsconfigNestedJSX(t *testing.T) { 556 tsconfig_suite.expectBundled(t, bundled{ 557 files: map[string]string{ 558 "/Users/user/project/entry.ts": ` 559 import factory from './factory' 560 import fragment from './fragment' 561 import both from './both' 562 console.log(factory, fragment, both) 563 `, 564 "/Users/user/project/factory/index.tsx": ` 565 export default <><div/><div/></> 566 `, 567 "/Users/user/project/factory/tsconfig.json": ` 568 { 569 "compilerOptions": { 570 "jsxFactory": "h" 571 } 572 } 573 `, 574 "/Users/user/project/fragment/index.tsx": ` 575 export default <><div/><div/></> 576 `, 577 "/Users/user/project/fragment/tsconfig.json": ` 578 { 579 "compilerOptions": { 580 "jsxFragmentFactory": "a.b" 581 } 582 } 583 `, 584 "/Users/user/project/both/index.tsx": ` 585 export default <><div/><div/></> 586 `, 587 "/Users/user/project/both/tsconfig.json": ` 588 { 589 "compilerOptions": { 590 "jsxFactory": "R.c", 591 "jsxFragmentFactory": "R.F" 592 } 593 } 594 `, 595 }, 596 entryPaths: []string{"/Users/user/project/entry.ts"}, 597 options: config.Options{ 598 Mode: config.ModeBundle, 599 AbsOutputFile: "/Users/user/project/out.js", 600 }, 601 }) 602 } 603 604 func TestTsconfigPreserveJSX(t *testing.T) { 605 tsconfig_suite.expectBundled(t, bundled{ 606 files: map[string]string{ 607 "/Users/user/project/entry.tsx": ` 608 console.log(<><div/><div/></>) 609 `, 610 "/Users/user/project/tsconfig.json": ` 611 { 612 "compilerOptions": { 613 "jsx": "preserve" // This should be ignored 614 } 615 } 616 `, 617 }, 618 entryPaths: []string{"/Users/user/project/entry.tsx"}, 619 options: config.Options{ 620 Mode: config.ModeBundle, 621 AbsOutputFile: "/Users/user/project/out.js", 622 }, 623 }) 624 } 625 626 func TestTsconfigPreserveJSXAutomatic(t *testing.T) { 627 tsconfig_suite.expectBundled(t, bundled{ 628 files: map[string]string{ 629 "/Users/user/project/entry.tsx": ` 630 console.log(<><div/><div/></>) 631 `, 632 "/Users/user/project/tsconfig.json": ` 633 { 634 "compilerOptions": { 635 "jsx": "preserve" // This should be ignored 636 } 637 } 638 `, 639 }, 640 entryPaths: []string{"/Users/user/project/entry.tsx"}, 641 options: config.Options{ 642 Mode: config.ModeBundle, 643 AbsOutputFile: "/Users/user/project/out.js", 644 JSX: config.JSXOptions{ 645 AutomaticRuntime: true, 646 }, 647 ExternalSettings: config.ExternalSettings{ 648 PreResolve: config.ExternalMatchers{Exact: map[string]bool{ 649 "react/jsx-runtime": true, 650 }}, 651 }, 652 }, 653 }) 654 } 655 656 func TestTsconfigReactJSX(t *testing.T) { 657 tsconfig_suite.expectBundled(t, bundled{ 658 files: map[string]string{ 659 "/Users/user/project/entry.tsx": ` 660 console.log(<><div/><div/></>) 661 `, 662 "/Users/user/project/tsconfig.json": ` 663 { 664 "compilerOptions": { 665 "jsx": "react-jsx", 666 "jsxImportSource": "notreact" 667 } 668 } 669 `, 670 }, 671 entryPaths: []string{"/Users/user/project/entry.tsx"}, 672 options: config.Options{ 673 Mode: config.ModeBundle, 674 AbsOutputFile: "/Users/user/project/out.js", 675 ExternalSettings: config.ExternalSettings{ 676 PreResolve: config.ExternalMatchers{Exact: map[string]bool{ 677 "notreact/jsx-runtime": true, 678 }}, 679 }, 680 }, 681 }) 682 } 683 684 func TestTsconfigReactJSXDev(t *testing.T) { 685 tsconfig_suite.expectBundled(t, bundled{ 686 files: map[string]string{ 687 "/Users/user/project/entry.tsx": ` 688 console.log(<><div/><div/></>) 689 `, 690 "/Users/user/project/tsconfig.json": ` 691 { 692 "compilerOptions": { 693 "jsx": "react-jsxdev" 694 } 695 } 696 `, 697 }, 698 entryPaths: []string{"/Users/user/project/entry.tsx"}, 699 options: config.Options{ 700 Mode: config.ModeBundle, 701 AbsOutputFile: "/Users/user/project/out.js", 702 ExternalSettings: config.ExternalSettings{ 703 PreResolve: config.ExternalMatchers{Exact: map[string]bool{ 704 "react/jsx-dev-runtime": true, 705 }}, 706 }, 707 }, 708 }) 709 } 710 711 func TestTsconfigReactJSXWithDevInMainConfig(t *testing.T) { 712 tsconfig_suite.expectBundled(t, bundled{ 713 files: map[string]string{ 714 "/Users/user/project/entry.tsx": ` 715 console.log(<><div/><div/></>) 716 `, 717 "/Users/user/project/tsconfig.json": ` 718 { 719 "compilerOptions": { 720 "jsx": "react-jsx" 721 } 722 } 723 `, 724 }, 725 entryPaths: []string{"/Users/user/project/entry.tsx"}, 726 options: config.Options{ 727 Mode: config.ModeBundle, 728 AbsOutputFile: "/Users/user/project/out.js", 729 JSX: config.JSXOptions{ 730 Development: true, 731 }, 732 ExternalSettings: config.ExternalSettings{ 733 PreResolve: config.ExternalMatchers{Exact: map[string]bool{ 734 "react/jsx-dev-runtime": true, 735 }}, 736 }, 737 }, 738 }) 739 } 740 741 func TestTsconfigJsonBaseUrl(t *testing.T) { 742 tsconfig_suite.expectBundled(t, bundled{ 743 files: map[string]string{ 744 "/Users/user/project/src/app/entry.js": ` 745 import fn from 'lib/util' 746 console.log(fn()) 747 `, 748 "/Users/user/project/src/tsconfig.json": ` 749 { 750 "compilerOptions": { 751 "baseUrl": "." 752 } 753 } 754 `, 755 "/Users/user/project/src/lib/util.js": ` 756 module.exports = function() { 757 return 123 758 } 759 `, 760 }, 761 entryPaths: []string{"/Users/user/project/src/app/entry.js"}, 762 options: config.Options{ 763 Mode: config.ModeBundle, 764 AbsOutputFile: "/Users/user/project/out.js", 765 }, 766 }) 767 } 768 769 func TestJsconfigJsonBaseUrl(t *testing.T) { 770 tsconfig_suite.expectBundled(t, bundled{ 771 files: map[string]string{ 772 "/Users/user/project/src/app/entry.js": ` 773 import fn from 'lib/util' 774 console.log(fn()) 775 `, 776 "/Users/user/project/src/jsconfig.json": ` 777 { 778 "compilerOptions": { 779 "baseUrl": "." 780 } 781 } 782 `, 783 "/Users/user/project/src/lib/util.js": ` 784 module.exports = function() { 785 return 123 786 } 787 `, 788 }, 789 entryPaths: []string{"/Users/user/project/src/app/entry.js"}, 790 options: config.Options{ 791 Mode: config.ModeBundle, 792 AbsOutputFile: "/Users/user/project/out.js", 793 }, 794 }) 795 } 796 797 func TestTsconfigJsonAbsoluteBaseUrl(t *testing.T) { 798 tsconfig_suite.expectBundled(t, bundled{ 799 files: map[string]string{ 800 "/Users/user/project/src/app/entry.js": ` 801 import fn from 'lib/util' 802 console.log(fn()) 803 `, 804 "/Users/user/project/src/tsconfig.json": ` 805 { 806 "compilerOptions": { 807 "baseUrl": "/Users/user/project/src" 808 } 809 } 810 `, 811 "/Users/user/project/src/lib/util.js": ` 812 module.exports = function() { 813 return 123 814 } 815 `, 816 }, 817 entryPaths: []string{"/Users/user/project/src/app/entry.js"}, 818 options: config.Options{ 819 Mode: config.ModeBundle, 820 AbsOutputFile: "/Users/user/project/out.js", 821 }, 822 }) 823 } 824 825 func TestTsconfigJsonCommentAllowed(t *testing.T) { 826 tsconfig_suite.expectBundled(t, bundled{ 827 files: map[string]string{ 828 "/Users/user/project/src/app/entry.js": ` 829 import fn from 'lib/util' 830 console.log(fn()) 831 `, 832 "/Users/user/project/src/tsconfig.json": ` 833 { 834 // Single-line comment 835 "compilerOptions": { 836 "baseUrl": "." 837 } 838 } 839 `, 840 "/Users/user/project/src/lib/util.js": ` 841 module.exports = function() { 842 return 123 843 } 844 `, 845 }, 846 entryPaths: []string{"/Users/user/project/src/app/entry.js"}, 847 options: config.Options{ 848 Mode: config.ModeBundle, 849 AbsOutputFile: "/Users/user/project/out.js", 850 }, 851 }) 852 } 853 854 func TestTsconfigJsonTrailingCommaAllowed(t *testing.T) { 855 tsconfig_suite.expectBundled(t, bundled{ 856 files: map[string]string{ 857 "/Users/user/project/src/app/entry.js": ` 858 import fn from 'lib/util' 859 console.log(fn()) 860 `, 861 "/Users/user/project/src/tsconfig.json": ` 862 { 863 "compilerOptions": { 864 "baseUrl": ".", 865 }, 866 } 867 `, 868 "/Users/user/project/src/lib/util.js": ` 869 module.exports = function() { 870 return 123 871 } 872 `, 873 }, 874 entryPaths: []string{"/Users/user/project/src/app/entry.js"}, 875 options: config.Options{ 876 Mode: config.ModeBundle, 877 AbsOutputFile: "/Users/user/project/out.js", 878 }, 879 }) 880 } 881 882 func TestTsconfigJsonExtends(t *testing.T) { 883 tsconfig_suite.expectBundled(t, bundled{ 884 files: map[string]string{ 885 "/entry.jsx": ` 886 console.log(<div/>, <></>) 887 `, 888 "/tsconfig.json": ` 889 { 890 "extends": "./base", 891 "compilerOptions": { 892 "jsxFragmentFactory": "derivedFragment" 893 } 894 } 895 `, 896 "/base.json": ` 897 { 898 "compilerOptions": { 899 "jsxFactory": "baseFactory", 900 "jsxFragmentFactory": "baseFragment" 901 } 902 } 903 `, 904 }, 905 entryPaths: []string{"/entry.jsx"}, 906 options: config.Options{ 907 Mode: config.ModeBundle, 908 AbsOutputFile: "/out.js", 909 }, 910 }) 911 } 912 913 func TestTsconfigJsonExtendsAbsolute(t *testing.T) { 914 tsconfig_suite.expectBundledUnix(t, bundled{ 915 files: map[string]string{ 916 "/Users/user/project/entry.jsx": ` 917 console.log(<div/>, <></>) 918 `, 919 "/Users/user/project/tsconfig.json": ` 920 { 921 "extends": "/Users/user/project/base.json", 922 "compilerOptions": { 923 "jsxFragmentFactory": "derivedFragment" 924 } 925 } 926 `, 927 "/Users/user/project/base.json": ` 928 { 929 "compilerOptions": { 930 "jsxFactory": "baseFactory", 931 "jsxFragmentFactory": "baseFragment" 932 } 933 } 934 `, 935 }, 936 entryPaths: []string{"/Users/user/project/entry.jsx"}, 937 options: config.Options{ 938 Mode: config.ModeBundle, 939 AbsOutputFile: "/out.js", 940 }, 941 }) 942 943 tsconfig_suite.expectBundledWindows(t, bundled{ 944 files: map[string]string{ 945 "/Users/user/project/entry.jsx": ` 946 console.log(<div/>, <></>) 947 `, 948 "/Users/user/project/tsconfig.json": ` 949 { 950 "extends": "C:\\Users\\user\\project\\base.json", 951 "compilerOptions": { 952 "jsxFragmentFactory": "derivedFragment" 953 } 954 } 955 `, 956 "/Users/user/project/base.json": ` 957 { 958 "compilerOptions": { 959 "jsxFactory": "baseFactory", 960 "jsxFragmentFactory": "baseFragment" 961 } 962 } 963 `, 964 }, 965 entryPaths: []string{"/Users/user/project/entry.jsx"}, 966 options: config.Options{ 967 Mode: config.ModeBundle, 968 AbsOutputFile: "/out.js", 969 }, 970 }) 971 } 972 973 func TestTsconfigJsonExtendsThreeLevels(t *testing.T) { 974 tsconfig_suite.expectBundled(t, bundled{ 975 files: map[string]string{ 976 "/Users/user/project/src/entry.jsx": ` 977 import "test/import.js" 978 console.log(<div/>, <></>) 979 `, 980 "/Users/user/project/src/tsconfig.json": ` 981 { 982 "extends": "./path1/base", 983 "compilerOptions": { 984 "jsxFragmentFactory": "derivedFragment" 985 } 986 } 987 `, 988 "/Users/user/project/src/path1/base.json": ` 989 { 990 "extends": "../path2/base2" 991 } 992 `, 993 "/Users/user/project/src/path2/base2.json": ` 994 { 995 "compilerOptions": { 996 "baseUrl": ".", 997 "paths": { 998 "test/*": ["./works/*"] 999 }, 1000 "jsxFactory": "baseFactory", 1001 "jsxFragmentFactory": "baseFragment" 1002 } 1003 } 1004 `, 1005 "/Users/user/project/src/path2/works/import.js": ` 1006 console.log('works') 1007 `, 1008 }, 1009 entryPaths: []string{"/Users/user/project/src/entry.jsx"}, 1010 options: config.Options{ 1011 Mode: config.ModeBundle, 1012 AbsOutputFile: "/out.js", 1013 }, 1014 }) 1015 } 1016 1017 func TestTsconfigJsonExtendsLoop(t *testing.T) { 1018 tsconfig_suite.expectBundled(t, bundled{ 1019 files: map[string]string{ 1020 "/entry.js": ` 1021 console.log(123) 1022 `, 1023 "/tsconfig.json": ` 1024 { 1025 "extends": "./base.json" 1026 } 1027 `, 1028 "/base.json": ` 1029 { 1030 "extends": "./tsconfig" 1031 } 1032 `, 1033 }, 1034 entryPaths: []string{"/entry.js"}, 1035 options: config.Options{ 1036 Mode: config.ModeBundle, 1037 AbsOutputFile: "/out.js", 1038 }, 1039 expectedScanLog: `base.json: WARNING: Base config file "./tsconfig" forms cycle 1040 `, 1041 }) 1042 } 1043 1044 func TestTsconfigJsonExtendsPackage(t *testing.T) { 1045 tsconfig_suite.expectBundled(t, bundled{ 1046 files: map[string]string{ 1047 "/Users/user/project/src/app/entry.jsx": ` 1048 console.log(<div/>) 1049 `, 1050 "/Users/user/project/src/tsconfig.json": ` 1051 { 1052 "extends": "@package/foo/tsconfig.json" 1053 } 1054 `, 1055 "/Users/user/project/node_modules/@package/foo/tsconfig.json": ` 1056 { 1057 "compilerOptions": { 1058 "jsxFactory": "worked" 1059 } 1060 } 1061 `, 1062 }, 1063 entryPaths: []string{"/Users/user/project/src/app/entry.jsx"}, 1064 options: config.Options{ 1065 Mode: config.ModeBundle, 1066 AbsOutputFile: "/Users/user/project/out.js", 1067 }, 1068 }) 1069 } 1070 1071 func TestTsconfigJsonOverrideMissing(t *testing.T) { 1072 tsconfig_suite.expectBundled(t, bundled{ 1073 files: map[string]string{ 1074 "/Users/user/project/src/app/entry.ts": ` 1075 import 'foo' 1076 `, 1077 "/Users/user/project/src/foo-bad.ts": ` 1078 console.log('bad') 1079 `, 1080 "/Users/user/project/src/tsconfig.json": ` 1081 { 1082 "compilerOptions": { 1083 "baseUrl": ".", 1084 "paths": { 1085 "foo": ["./foo-bad.ts"] 1086 } 1087 } 1088 } 1089 `, 1090 "/Users/user/project/other/foo-good.ts": ` 1091 console.log('good') 1092 `, 1093 "/Users/user/project/other/config-for-ts.json": ` 1094 { 1095 "compilerOptions": { 1096 "baseUrl": ".", 1097 "paths": { 1098 "foo": ["./foo-good.ts"] 1099 } 1100 } 1101 } 1102 `, 1103 }, 1104 entryPaths: []string{"/Users/user/project/src/app/entry.ts"}, 1105 options: config.Options{ 1106 Mode: config.ModeBundle, 1107 AbsOutputFile: "/Users/user/project/out.js", 1108 TSConfigPath: "/Users/user/project/other/config-for-ts.json", 1109 }, 1110 }) 1111 } 1112 1113 func TestTsconfigJsonOverrideNodeModules(t *testing.T) { 1114 tsconfig_suite.expectBundled(t, bundled{ 1115 files: map[string]string{ 1116 "/Users/user/project/src/app/entry.ts": ` 1117 import 'foo' 1118 `, 1119 "/Users/user/project/src/node_modules/foo/index.js": ` 1120 console.log('default') 1121 `, 1122 "/Users/user/project/src/foo-bad.ts": ` 1123 console.log('bad') 1124 `, 1125 "/Users/user/project/src/tsconfig.json": ` 1126 { 1127 "compilerOptions": { 1128 "baseUrl": ".", 1129 "paths": { 1130 "foo": ["./foo-bad.ts"] 1131 } 1132 } 1133 } 1134 `, 1135 "/Users/user/project/other/foo-good.ts": ` 1136 console.log('good') 1137 `, 1138 "/Users/user/project/other/config-for-ts.json": ` 1139 { 1140 "compilerOptions": { 1141 "baseUrl": ".", 1142 "paths": { 1143 "foo": ["./foo-good.ts"] 1144 } 1145 } 1146 } 1147 `, 1148 }, 1149 entryPaths: []string{"/Users/user/project/src/app/entry.ts"}, 1150 options: config.Options{ 1151 Mode: config.ModeBundle, 1152 AbsOutputFile: "/Users/user/project/out.js", 1153 TSConfigPath: "/Users/user/project/other/config-for-ts.json", 1154 }, 1155 }) 1156 } 1157 1158 func TestTsconfigJsonOverrideInvalid(t *testing.T) { 1159 tsconfig_suite.expectBundled(t, bundled{ 1160 files: map[string]string{ 1161 "/entry.ts": ``, 1162 }, 1163 entryPaths: []string{"/entry.ts"}, 1164 options: config.Options{ 1165 Mode: config.ModeBundle, 1166 AbsOutputFile: "/out.js", 1167 TSConfigPath: "/this/file/doesn't/exist/tsconfig.json", 1168 }, 1169 expectedScanLog: `ERROR: Cannot find tsconfig file "this/file/doesn't/exist/tsconfig.json" 1170 `, 1171 }) 1172 } 1173 1174 func TestTsconfigJsonNodeModulesImplicitFile(t *testing.T) { 1175 tsconfig_suite.expectBundled(t, bundled{ 1176 files: map[string]string{ 1177 "/Users/user/project/src/app/entry.tsx": ` 1178 console.log(<div/>) 1179 `, 1180 "/Users/user/project/src/tsconfig.json": ` 1181 { 1182 "extends": "foo" 1183 } 1184 `, 1185 "/Users/user/project/src/node_modules/foo/tsconfig.json": ` 1186 { 1187 "compilerOptions": { 1188 "jsx": "react", 1189 "jsxFactory": "worked" 1190 } 1191 } 1192 `, 1193 }, 1194 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1195 options: config.Options{ 1196 Mode: config.ModeBundle, 1197 AbsOutputFile: "/Users/user/project/out.js", 1198 }, 1199 }) 1200 } 1201 1202 func TestTsconfigJsonNodeModulesTsconfigPathExact(t *testing.T) { 1203 tsconfig_suite.expectBundled(t, bundled{ 1204 files: map[string]string{ 1205 "/Users/user/project/src/app/entry.tsx": ` 1206 console.log(<div/>) 1207 `, 1208 "/Users/user/project/src/tsconfig.json": ` 1209 { 1210 "extends": "foo" 1211 } 1212 `, 1213 "/Users/user/project/src/node_modules/foo/package.json": ` 1214 { 1215 "tsconfig": "over/here.json" 1216 } 1217 `, 1218 "/Users/user/project/src/node_modules/foo/over/here.json": ` 1219 { 1220 "compilerOptions": { 1221 "jsx": "react", 1222 "jsxFactory": "worked" 1223 } 1224 } 1225 `, 1226 }, 1227 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1228 options: config.Options{ 1229 Mode: config.ModeBundle, 1230 AbsOutputFile: "/Users/user/project/out.js", 1231 }, 1232 }) 1233 } 1234 1235 func TestTsconfigJsonNodeModulesTsconfigPathImplicitJson(t *testing.T) { 1236 tsconfig_suite.expectBundled(t, bundled{ 1237 files: map[string]string{ 1238 "/Users/user/project/src/app/entry.tsx": ` 1239 console.log(<div/>) 1240 `, 1241 "/Users/user/project/src/tsconfig.json": ` 1242 { 1243 "extends": "foo" 1244 } 1245 `, 1246 "/Users/user/project/src/node_modules/foo/package.json": ` 1247 { 1248 "tsconfig": "over/here" 1249 } 1250 `, 1251 "/Users/user/project/src/node_modules/foo/over/here.json": ` 1252 { 1253 "compilerOptions": { 1254 "jsx": "react", 1255 "jsxFactory": "worked" 1256 } 1257 } 1258 `, 1259 }, 1260 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1261 options: config.Options{ 1262 Mode: config.ModeBundle, 1263 AbsOutputFile: "/Users/user/project/out.js", 1264 }, 1265 }) 1266 } 1267 1268 func TestTsconfigJsonNodeModulesTsconfigPathDirectory(t *testing.T) { 1269 tsconfig_suite.expectBundled(t, bundled{ 1270 files: map[string]string{ 1271 "/Users/user/project/src/app/entry.tsx": ` 1272 console.log(<div/>) 1273 `, 1274 "/Users/user/project/src/tsconfig.json": ` 1275 { 1276 "extends": "foo" 1277 } 1278 `, 1279 "/Users/user/project/src/node_modules/foo/package.json": ` 1280 { 1281 "tsconfig": "over/here" 1282 } 1283 `, 1284 "/Users/user/project/src/node_modules/foo/over/here/tsconfig.json": ` 1285 { 1286 "compilerOptions": { 1287 "jsx": "react", 1288 "jsxFactory": "worked" 1289 } 1290 } 1291 `, 1292 }, 1293 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1294 options: config.Options{ 1295 Mode: config.ModeBundle, 1296 AbsOutputFile: "/Users/user/project/out.js", 1297 }, 1298 }) 1299 } 1300 1301 func TestTsconfigJsonNodeModulesTsconfigPathBad(t *testing.T) { 1302 tsconfig_suite.expectBundled(t, bundled{ 1303 files: map[string]string{ 1304 "/Users/user/project/src/app/entry.tsx": ` 1305 console.log(<div/>) 1306 `, 1307 "/Users/user/project/src/tsconfig.json": ` 1308 { 1309 "extends": "foo" 1310 } 1311 `, 1312 "/Users/user/project/src/node_modules/foo/package.json": ` 1313 { 1314 "tsconfig": "over/here.json" 1315 } 1316 `, 1317 "/Users/user/project/src/node_modules/foo/tsconfig.json": ` 1318 { 1319 "compilerOptions": { 1320 "jsx": "react", 1321 "jsxFactory": "THIS SHOULD NOT BE LOADED" 1322 } 1323 } 1324 `, 1325 }, 1326 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1327 options: config.Options{ 1328 Mode: config.ModeBundle, 1329 AbsOutputFile: "/Users/user/project/out.js", 1330 }, 1331 expectedScanLog: `Users/user/project/src/tsconfig.json: WARNING: Cannot find base config file "foo" 1332 `, 1333 }) 1334 } 1335 1336 func TestTsconfigJsonInsideNodeModules(t *testing.T) { 1337 tsconfig_suite.expectBundled(t, bundled{ 1338 files: map[string]string{ 1339 "/Users/user/project/src/app/entry.tsx": ` 1340 import 'foo' 1341 `, 1342 "/Users/user/project/src/node_modules/foo/index.tsx": ` 1343 console.log(<div/>) 1344 `, 1345 "/Users/user/project/src/node_modules/foo/tsconfig.json": ` 1346 { 1347 "compilerOptions": { 1348 "jsxFactory": "TEST_FAILED" 1349 } 1350 } 1351 `, 1352 }, 1353 entryPaths: []string{"/Users/user/project/src/app/entry.tsx"}, 1354 options: config.Options{ 1355 Mode: config.ModeBundle, 1356 AbsOutputFile: "/Users/user/project/out.js", 1357 }, 1358 }) 1359 } 1360 1361 func TestTsconfigWarningsInsideNodeModules(t *testing.T) { 1362 tsconfig_suite.expectBundled(t, bundled{ 1363 files: map[string]string{ 1364 "/Users/user/project/src/entry.tsx": ` 1365 import "./foo" 1366 import "bar" 1367 `, 1368 1369 "/Users/user/project/src/foo/tsconfig.json": `{ "extends": "extends for foo" }`, 1370 "/Users/user/project/src/foo/index.js": ``, 1371 1372 "/Users/user/project/src/node_modules/bar/tsconfig.json": `{ "extends": "extends for bar" }`, 1373 "/Users/user/project/src/node_modules/bar/index.js": ``, 1374 }, 1375 entryPaths: []string{"/Users/user/project/src/entry.tsx"}, 1376 options: config.Options{ 1377 Mode: config.ModeBundle, 1378 AbsOutputFile: "/Users/user/project/out.js", 1379 }, 1380 expectedScanLog: `Users/user/project/src/foo/tsconfig.json: WARNING: Cannot find base config file "extends for foo" 1381 `, 1382 }) 1383 } 1384 1385 func TestTsconfigRemoveUnusedImports(t *testing.T) { 1386 tsconfig_suite.expectBundled(t, bundled{ 1387 files: map[string]string{ 1388 "/Users/user/project/src/entry.ts": ` 1389 import {x, y} from "./foo" 1390 console.log(1 as x) 1391 `, 1392 "/Users/user/project/src/tsconfig.json": `{ 1393 "compilerOptions": { 1394 "importsNotUsedAsValues": "remove" 1395 } 1396 }`, 1397 }, 1398 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1399 options: config.Options{ 1400 Mode: config.ModeBundle, 1401 AbsOutputFile: "/Users/user/project/out.js", 1402 }, 1403 }) 1404 } 1405 1406 func TestTsconfigPreserveUnusedImports(t *testing.T) { 1407 tsconfig_suite.expectBundled(t, bundled{ 1408 files: map[string]string{ 1409 "/Users/user/project/src/entry.ts": ` 1410 import {x, y} from "./foo" 1411 console.log(1 as x) 1412 `, 1413 "/Users/user/project/src/tsconfig.json": `{ 1414 "compilerOptions": { 1415 "importsNotUsedAsValues": "preserve" 1416 } 1417 }`, 1418 }, 1419 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1420 options: config.Options{ 1421 Mode: config.ModeBundle, 1422 AbsOutputFile: "/Users/user/project/out.js", 1423 ExternalSettings: config.ExternalSettings{ 1424 PostResolve: config.ExternalMatchers{Exact: map[string]bool{ 1425 "/Users/user/project/src/foo": true, 1426 }}, 1427 }, 1428 }, 1429 }) 1430 } 1431 1432 func TestTsconfigImportsNotUsedAsValuesPreserve(t *testing.T) { 1433 tsconfig_suite.expectBundled(t, bundled{ 1434 files: map[string]string{ 1435 "/Users/user/project/src/entry.ts": ` 1436 import {x, y} from "./foo" 1437 import z from "./foo" 1438 import * as ns from "./foo" 1439 console.log(1 as x, 2 as z, 3 as ns.y) 1440 `, 1441 "/Users/user/project/src/tsconfig.json": `{ 1442 "compilerOptions": { 1443 "importsNotUsedAsValues": "preserve" 1444 } 1445 }`, 1446 }, 1447 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1448 options: config.Options{ 1449 Mode: config.ModeConvertFormat, 1450 OutputFormat: config.FormatESModule, 1451 AbsOutputFile: "/Users/user/project/out.js", 1452 ExternalSettings: config.ExternalSettings{ 1453 PostResolve: config.ExternalMatchers{Exact: map[string]bool{ 1454 "/Users/user/project/src/foo": true, 1455 }}, 1456 }, 1457 }, 1458 }) 1459 } 1460 1461 func TestTsconfigPreserveValueImports(t *testing.T) { 1462 tsconfig_suite.expectBundled(t, bundled{ 1463 files: map[string]string{ 1464 "/Users/user/project/src/entry.ts": ` 1465 import {} from "a" 1466 import {b1} from "b" 1467 import {c1, type c2} from "c" 1468 import {d1, d2, type d3} from "d" 1469 import {type e1, type e2} from "e" 1470 import f1, {} from "f" 1471 import g1, {g2} from "g" 1472 import h1, {type h2} from "h" 1473 import * as i1 from "i" 1474 import "j" 1475 `, 1476 "/Users/user/project/src/tsconfig.json": `{ 1477 "compilerOptions": { 1478 "preserveValueImports": true 1479 } 1480 }`, 1481 }, 1482 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1483 options: config.Options{ 1484 Mode: config.ModeConvertFormat, 1485 OutputFormat: config.FormatESModule, 1486 AbsOutputFile: "/Users/user/project/out.js", 1487 ExternalSettings: config.ExternalSettings{ 1488 PostResolve: config.ExternalMatchers{Exact: map[string]bool{ 1489 "/Users/user/project/src/foo": true, 1490 }}, 1491 }, 1492 }, 1493 }) 1494 } 1495 1496 func TestTsconfigPreserveValueImportsAndImportsNotUsedAsValuesPreserve(t *testing.T) { 1497 tsconfig_suite.expectBundled(t, bundled{ 1498 files: map[string]string{ 1499 "/Users/user/project/src/entry.ts": ` 1500 import {} from "a" 1501 import {b1} from "b" 1502 import {c1, type c2} from "c" 1503 import {d1, d2, type d3} from "d" 1504 import {type e1, type e2} from "e" 1505 import f1, {} from "f" 1506 import g1, {g2} from "g" 1507 import h1, {type h2} from "h" 1508 import * as i1 from "i" 1509 import "j" 1510 `, 1511 "/Users/user/project/src/tsconfig.json": `{ 1512 "compilerOptions": { 1513 "importsNotUsedAsValues": "preserve", 1514 "preserveValueImports": true 1515 } 1516 }`, 1517 }, 1518 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1519 options: config.Options{ 1520 Mode: config.ModeConvertFormat, 1521 OutputFormat: config.FormatESModule, 1522 AbsOutputFile: "/Users/user/project/out.js", 1523 ExternalSettings: config.ExternalSettings{ 1524 PostResolve: config.ExternalMatchers{Exact: map[string]bool{ 1525 "/Users/user/project/src/foo": true, 1526 }}, 1527 }, 1528 }, 1529 }) 1530 } 1531 1532 func TestTsconfigUseDefineForClassFieldsES2020(t *testing.T) { 1533 tsconfig_suite.expectBundled(t, bundled{ 1534 files: map[string]string{ 1535 "/Users/user/project/src/entry.ts": ` 1536 Foo = class { 1537 useDefine = false 1538 } 1539 `, 1540 "/Users/user/project/src/tsconfig.json": `{ 1541 "compilerOptions": { 1542 "target": "ES2020" 1543 } 1544 }`, 1545 }, 1546 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1547 options: config.Options{ 1548 Mode: config.ModeBundle, 1549 AbsOutputFile: "/Users/user/project/out.js", 1550 OriginalTargetEnv: "esnext", 1551 }, 1552 }) 1553 } 1554 1555 func TestTsconfigUseDefineForClassFieldsESNext(t *testing.T) { 1556 tsconfig_suite.expectBundled(t, bundled{ 1557 files: map[string]string{ 1558 "/Users/user/project/src/entry.ts": ` 1559 Foo = class { 1560 useDefine = true 1561 } 1562 `, 1563 "/Users/user/project/src/tsconfig.json": `{ 1564 "compilerOptions": { 1565 "target": "ESNext" 1566 } 1567 }`, 1568 }, 1569 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1570 options: config.Options{ 1571 Mode: config.ModeBundle, 1572 AbsOutputFile: "/Users/user/project/out.js", 1573 OriginalTargetEnv: "esnext", 1574 }, 1575 }) 1576 } 1577 1578 func TestTsconfigUnrecognizedTargetWarning(t *testing.T) { 1579 tsconfig_suite.expectBundled(t, bundled{ 1580 files: map[string]string{ 1581 "/Users/user/project/src/entry.ts": ` 1582 import "./a" 1583 import "b" 1584 `, 1585 "/Users/user/project/src/a/index.ts": ``, 1586 "/Users/user/project/src/a/tsconfig.json": `{ 1587 "compilerOptions": { 1588 "target": "es4" 1589 } 1590 }`, 1591 "/Users/user/project/src/node_modules/b/index.ts": ``, 1592 "/Users/user/project/src/node_modules/b/tsconfig.json": `{ 1593 "compilerOptions": { 1594 "target": "es4" 1595 } 1596 }`, 1597 }, 1598 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1599 options: config.Options{ 1600 Mode: config.ModeBundle, 1601 AbsOutputFile: "/Users/user/project/out.js", 1602 }, 1603 expectedScanLog: `Users/user/project/src/a/tsconfig.json: WARNING: Unrecognized target environment "es4" 1604 `, 1605 }) 1606 } 1607 1608 func TestTsconfigIgnoredTargetSilent(t *testing.T) { 1609 tsconfig_suite.expectBundled(t, bundled{ 1610 files: map[string]string{ 1611 "/Users/user/project/src/entry.ts": ` 1612 import "./a" 1613 import "b" 1614 `, 1615 "/Users/user/project/src/a/index.ts": ``, 1616 "/Users/user/project/src/a/tsconfig.json": `{ 1617 "compilerOptions": { 1618 "target": "es5" 1619 } 1620 }`, 1621 "/Users/user/project/src/node_modules/b/index.ts": ``, 1622 "/Users/user/project/src/node_modules/b/tsconfig.json": `{ 1623 "compilerOptions": { 1624 "target": "es5" 1625 } 1626 }`, 1627 }, 1628 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1629 options: config.Options{ 1630 Mode: config.ModeBundle, 1631 AbsOutputFile: "/Users/user/project/out.js", 1632 UnsupportedJSFeatures: es(5), 1633 OriginalTargetEnv: "ES5", 1634 }, 1635 }) 1636 } 1637 1638 func TestTsconfigNoBaseURLExtendsPaths(t *testing.T) { 1639 tsconfig_suite.expectBundled(t, bundled{ 1640 files: map[string]string{ 1641 "/Users/user/project/src/entry.ts": ` 1642 import { foo } from "foo" 1643 console.log(foo) 1644 `, 1645 "/Users/user/project/lib/foo.ts": ` 1646 export let foo = 123 1647 `, 1648 "/Users/user/project/tsconfig.json": `{ 1649 "extends": "./base/defaults" 1650 }`, 1651 "/Users/user/project/base/defaults.json": `{ 1652 "compilerOptions": { 1653 "paths": { 1654 "*": ["lib/*"] 1655 } 1656 } 1657 }`, 1658 }, 1659 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1660 options: config.Options{ 1661 Mode: config.ModeBundle, 1662 AbsOutputFile: "/Users/user/project/out.js", 1663 }, 1664 expectedScanLog: `Users/user/project/base/defaults.json: WARNING: Non-relative path "lib/*" is not allowed when "baseUrl" is not set (did you forget a leading "./"?) 1665 Users/user/project/src/entry.ts: ERROR: Could not resolve "foo" 1666 NOTE: You can mark the path "foo" as external to exclude it from the bundle, which will remove this error and leave the unresolved path in the bundle. 1667 `, 1668 }) 1669 } 1670 1671 func TestTsconfigBaseURLExtendsPaths(t *testing.T) { 1672 tsconfig_suite.expectBundled(t, bundled{ 1673 files: map[string]string{ 1674 "/Users/user/project/src/entry.ts": ` 1675 import { foo } from "foo" 1676 console.log(foo) 1677 `, 1678 "/Users/user/project/lib/foo.ts": ` 1679 export let foo = 123 1680 `, 1681 "/Users/user/project/tsconfig.json": `{ 1682 "extends": "./base/defaults", 1683 "compilerOptions": { 1684 "baseUrl": "." 1685 } 1686 }`, 1687 "/Users/user/project/base/defaults.json": `{ 1688 "compilerOptions": { 1689 "paths": { 1690 "*": ["lib/*"] 1691 } 1692 } 1693 }`, 1694 }, 1695 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1696 options: config.Options{ 1697 Mode: config.ModeBundle, 1698 AbsOutputFile: "/Users/user/project/out.js", 1699 }, 1700 }) 1701 } 1702 1703 func TestTsconfigPathsExtendsBaseURL(t *testing.T) { 1704 tsconfig_suite.expectBundled(t, bundled{ 1705 files: map[string]string{ 1706 "/Users/user/project/src/entry.ts": ` 1707 import { foo } from "foo" 1708 console.log(foo) 1709 `, 1710 "/Users/user/project/base/test/lib/foo.ts": ` 1711 export let foo = 123 1712 `, 1713 "/Users/user/project/tsconfig.json": `{ 1714 "extends": "./base/defaults", 1715 "compilerOptions": { 1716 "paths": { 1717 "*": ["lib/*"] 1718 } 1719 } 1720 }`, 1721 "/Users/user/project/base/defaults.json": `{ 1722 "compilerOptions": { 1723 "baseUrl": "test" 1724 } 1725 }`, 1726 }, 1727 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1728 options: config.Options{ 1729 Mode: config.ModeBundle, 1730 AbsOutputFile: "/Users/user/project/out.js", 1731 }, 1732 }) 1733 } 1734 1735 func TestTsconfigPathsInNodeModulesIssue2386(t *testing.T) { 1736 tsconfig_suite.expectBundled(t, bundled{ 1737 files: map[string]string{ 1738 "/Users/user/project/main.js": ` 1739 import first from "wow/first"; 1740 import next from "wow/next"; 1741 console.log(first, next); 1742 `, 1743 "/Users/user/project/node_modules/wow/package.json": `{ 1744 "name": "wow", 1745 "type": "module", 1746 "private": true, 1747 "exports": { 1748 "./*": "./dist/*.js" 1749 }, 1750 "typesVersions": { 1751 "*": { 1752 "*": [ 1753 "dist/*" 1754 ] 1755 } 1756 } 1757 }`, 1758 "/Users/user/project/node_modules/wow/tsconfig.json": `{ 1759 "compilerOptions": { 1760 "paths": { "wow/*": [ "./*" ] } 1761 } 1762 }`, 1763 "/Users/user/project/node_modules/wow/dist/first.js": ` 1764 export default "dist"; 1765 `, 1766 "/Users/user/project/node_modules/wow/dist/next.js": ` 1767 import next from "wow/first"; 1768 export default next; 1769 `, 1770 "/Users/user/project/node_modules/wow/first.ts": ` 1771 export default "source"; 1772 `, 1773 }, 1774 entryPaths: []string{"/Users/user/project/main.js"}, 1775 options: config.Options{ 1776 Mode: config.ModeBundle, 1777 AbsOutputFile: "/Users/user/project/out.js", 1778 }, 1779 }) 1780 } 1781 1782 func TestTsconfigWithStatementAlwaysStrictFalse(t *testing.T) { 1783 tsconfig_suite.expectBundled(t, bundled{ 1784 files: map[string]string{ 1785 "/Users/user/project/src/entry.ts": ` 1786 with (x) y 1787 `, 1788 "/Users/user/project/tsconfig.json": `{ 1789 "compilerOptions": { 1790 "alwaysStrict": false 1791 } 1792 }`, 1793 }, 1794 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1795 options: config.Options{ 1796 Mode: config.ModeBundle, 1797 AbsOutputFile: "/Users/user/project/out.js", 1798 OutputFormat: config.FormatIIFE, 1799 }, 1800 }) 1801 } 1802 1803 func TestTsconfigWithStatementAlwaysStrictTrue(t *testing.T) { 1804 tsconfig_suite.expectBundled(t, bundled{ 1805 files: map[string]string{ 1806 "/Users/user/project/src/entry.ts": ` 1807 with (x) y 1808 `, 1809 "/Users/user/project/tsconfig.json": `{ 1810 "compilerOptions": { 1811 "alwaysStrict": true 1812 } 1813 }`, 1814 }, 1815 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1816 options: config.Options{ 1817 Mode: config.ModeBundle, 1818 AbsOutputFile: "/Users/user/project/out.js", 1819 }, 1820 expectedScanLog: `Users/user/project/src/entry.ts: ERROR: With statements cannot be used in strict mode 1821 Users/user/project/tsconfig.json: NOTE: TypeScript's "alwaysStrict" setting was enabled here: 1822 `, 1823 }) 1824 } 1825 1826 func TestTsconfigWithStatementStrictFalse(t *testing.T) { 1827 tsconfig_suite.expectBundled(t, bundled{ 1828 files: map[string]string{ 1829 "/Users/user/project/src/entry.ts": ` 1830 with (x) y 1831 `, 1832 "/Users/user/project/tsconfig.json": `{ 1833 "compilerOptions": { 1834 "strict": false 1835 } 1836 }`, 1837 }, 1838 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1839 options: config.Options{ 1840 Mode: config.ModeBundle, 1841 AbsOutputFile: "/Users/user/project/out.js", 1842 OutputFormat: config.FormatIIFE, 1843 }, 1844 }) 1845 } 1846 1847 func TestTsconfigWithStatementStrictTrue(t *testing.T) { 1848 tsconfig_suite.expectBundled(t, bundled{ 1849 files: map[string]string{ 1850 "/Users/user/project/src/entry.ts": ` 1851 with (x) y 1852 `, 1853 "/Users/user/project/tsconfig.json": `{ 1854 "compilerOptions": { 1855 "strict": true 1856 } 1857 }`, 1858 }, 1859 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1860 options: config.Options{ 1861 Mode: config.ModeBundle, 1862 AbsOutputFile: "/Users/user/project/out.js", 1863 }, 1864 expectedScanLog: `Users/user/project/src/entry.ts: ERROR: With statements cannot be used in strict mode 1865 Users/user/project/tsconfig.json: NOTE: TypeScript's "strict" setting was enabled here: 1866 `, 1867 }) 1868 } 1869 1870 func TestTsconfigWithStatementStrictFalseAlwaysStrictTrue(t *testing.T) { 1871 tsconfig_suite.expectBundled(t, bundled{ 1872 files: map[string]string{ 1873 "/Users/user/project/src/entry.ts": ` 1874 with (x) y 1875 `, 1876 "/Users/user/project/tsconfig.json": `{ 1877 "compilerOptions": { 1878 "strict": false, 1879 "alwaysStrict": true 1880 } 1881 }`, 1882 }, 1883 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1884 options: config.Options{ 1885 Mode: config.ModeBundle, 1886 AbsOutputFile: "/Users/user/project/out.js", 1887 }, 1888 expectedScanLog: `Users/user/project/src/entry.ts: ERROR: With statements cannot be used in strict mode 1889 Users/user/project/tsconfig.json: NOTE: TypeScript's "alwaysStrict" setting was enabled here: 1890 `, 1891 }) 1892 } 1893 1894 func TestTsconfigWithStatementStrictTrueAlwaysStrictFalse(t *testing.T) { 1895 tsconfig_suite.expectBundled(t, bundled{ 1896 files: map[string]string{ 1897 "/Users/user/project/src/entry.ts": ` 1898 with (x) y 1899 `, 1900 "/Users/user/project/tsconfig.json": `{ 1901 "compilerOptions": { 1902 "strict": true, 1903 "alwaysStrict": false 1904 } 1905 }`, 1906 }, 1907 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 1908 options: config.Options{ 1909 Mode: config.ModeBundle, 1910 AbsOutputFile: "/Users/user/project/out.js", 1911 OutputFormat: config.FormatIIFE, 1912 }, 1913 }) 1914 } 1915 1916 func TestTsconfigAlwaysStrictTrueEmitDirectivePassThrough(t *testing.T) { 1917 tsconfig_suite.expectBundled(t, bundled{ 1918 files: map[string]string{ 1919 "/Users/user/project/src/implicit.ts": ` 1920 console.log('this file should start with "use strict"') 1921 `, 1922 "/Users/user/project/src/explicit.ts": ` 1923 'use strict' 1924 console.log('this file should start with "use strict"') 1925 `, 1926 "/Users/user/project/tsconfig.json": `{ 1927 "compilerOptions": { 1928 "alwaysStrict": true 1929 } 1930 }`, 1931 }, 1932 entryPaths: []string{ 1933 "/Users/user/project/src/implicit.ts", 1934 "/Users/user/project/src/explicit.ts", 1935 }, 1936 options: config.Options{ 1937 Mode: config.ModePassThrough, 1938 AbsOutputDir: "/Users/user/project/out", 1939 }, 1940 }) 1941 } 1942 1943 func TestTsconfigAlwaysStrictTrueEmitDirectiveFormat(t *testing.T) { 1944 tsconfig_suite.expectBundled(t, bundled{ 1945 files: map[string]string{ 1946 "/Users/user/project/src/implicit.ts": ` 1947 console.log('this file should start with "use strict"') 1948 `, 1949 "/Users/user/project/src/explicit.ts": ` 1950 'use strict' 1951 console.log('this file should start with "use strict"') 1952 `, 1953 "/Users/user/project/tsconfig.json": `{ 1954 "compilerOptions": { 1955 "alwaysStrict": true 1956 } 1957 }`, 1958 }, 1959 entryPaths: []string{ 1960 "/Users/user/project/src/implicit.ts", 1961 "/Users/user/project/src/explicit.ts", 1962 }, 1963 options: config.Options{ 1964 Mode: config.ModeConvertFormat, 1965 AbsOutputDir: "/Users/user/project/out", 1966 }, 1967 }) 1968 } 1969 1970 func TestTsconfigAlwaysStrictTrueEmitDirectiveBundleIIFE(t *testing.T) { 1971 tsconfig_suite.expectBundled(t, bundled{ 1972 files: map[string]string{ 1973 "/Users/user/project/src/implicit.ts": ` 1974 console.log('this file should start with "use strict"') 1975 `, 1976 "/Users/user/project/src/explicit.ts": ` 1977 'use strict' 1978 console.log('this file should start with "use strict"') 1979 `, 1980 "/Users/user/project/tsconfig.json": `{ 1981 "compilerOptions": { 1982 "alwaysStrict": true 1983 } 1984 }`, 1985 }, 1986 entryPaths: []string{ 1987 "/Users/user/project/src/implicit.ts", 1988 "/Users/user/project/src/explicit.ts", 1989 }, 1990 options: config.Options{ 1991 Mode: config.ModeBundle, 1992 AbsOutputDir: "/Users/user/project/out", 1993 OutputFormat: config.FormatIIFE, 1994 }, 1995 }) 1996 } 1997 1998 func TestTsconfigAlwaysStrictTrueEmitDirectiveBundleCJS(t *testing.T) { 1999 tsconfig_suite.expectBundled(t, bundled{ 2000 files: map[string]string{ 2001 "/Users/user/project/src/implicit.ts": ` 2002 console.log('this file should start with "use strict"') 2003 `, 2004 "/Users/user/project/src/explicit.ts": ` 2005 'use strict' 2006 console.log('this file should start with "use strict"') 2007 `, 2008 "/Users/user/project/tsconfig.json": `{ 2009 "compilerOptions": { 2010 "alwaysStrict": true 2011 } 2012 }`, 2013 }, 2014 entryPaths: []string{ 2015 "/Users/user/project/src/implicit.ts", 2016 "/Users/user/project/src/explicit.ts", 2017 }, 2018 options: config.Options{ 2019 Mode: config.ModeBundle, 2020 AbsOutputDir: "/Users/user/project/out", 2021 OutputFormat: config.FormatCommonJS, 2022 }, 2023 }) 2024 } 2025 2026 func TestTsconfigAlwaysStrictTrueEmitDirectiveBundleESM(t *testing.T) { 2027 tsconfig_suite.expectBundled(t, bundled{ 2028 files: map[string]string{ 2029 "/Users/user/project/src/implicit.ts": ` 2030 console.log('this file should not start with "use strict"') 2031 `, 2032 "/Users/user/project/src/explicit.ts": ` 2033 'use strict' 2034 console.log('this file should not start with "use strict"') 2035 `, 2036 "/Users/user/project/tsconfig.json": `{ 2037 "compilerOptions": { 2038 "alwaysStrict": true 2039 } 2040 }`, 2041 }, 2042 entryPaths: []string{ 2043 "/Users/user/project/src/implicit.ts", 2044 "/Users/user/project/src/explicit.ts", 2045 }, 2046 options: config.Options{ 2047 Mode: config.ModeBundle, 2048 AbsOutputDir: "/Users/user/project/out", 2049 OutputFormat: config.FormatESModule, 2050 }, 2051 }) 2052 } 2053 2054 func TestTsconfigExtendsDotWithoutSlash(t *testing.T) { 2055 tsconfig_suite.expectBundled(t, bundled{ 2056 files: map[string]string{ 2057 "/Users/user/project/src/main.tsx": ` 2058 console.log(<div/>) 2059 `, 2060 "/Users/user/project/src/foo.json": `{ 2061 "extends": "." 2062 }`, 2063 "/Users/user/project/src/tsconfig.json": `{ 2064 "compilerOptions": { 2065 "jsxFactory": "success" 2066 } 2067 }`, 2068 }, 2069 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2070 options: config.Options{ 2071 Mode: config.ModeBundle, 2072 AbsOutputDir: "/Users/user/project/out", 2073 OutputFormat: config.FormatESModule, 2074 TSConfigPath: "/Users/user/project/src/foo.json", 2075 }, 2076 }) 2077 } 2078 2079 func TestTsconfigExtendsDotDotWithoutSlash(t *testing.T) { 2080 tsconfig_suite.expectBundled(t, bundled{ 2081 files: map[string]string{ 2082 "/Users/user/project/src/main.tsx": ` 2083 console.log(<div/>) 2084 `, 2085 "/Users/user/project/src/tsconfig.json": `{ 2086 "extends": ".." 2087 }`, 2088 "/Users/user/project/tsconfig.json": `{ 2089 "compilerOptions": { 2090 "jsxFactory": "success" 2091 } 2092 }`, 2093 }, 2094 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2095 options: config.Options{ 2096 Mode: config.ModeBundle, 2097 AbsOutputDir: "/Users/user/project/out", 2098 OutputFormat: config.FormatESModule, 2099 }, 2100 }) 2101 } 2102 2103 func TestTsconfigExtendsDotWithSlash(t *testing.T) { 2104 tsconfig_suite.expectBundled(t, bundled{ 2105 files: map[string]string{ 2106 "/Users/user/project/src/main.tsx": ` 2107 console.log(<div/>) 2108 `, 2109 "/Users/user/project/src/foo.json": `{ 2110 "extends": "./" 2111 }`, 2112 "/Users/user/project/src/tsconfig.json": `{ 2113 "compilerOptions": { 2114 "jsxFactory": "FAILURE" 2115 } 2116 }`, 2117 }, 2118 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2119 options: config.Options{ 2120 Mode: config.ModeBundle, 2121 AbsOutputDir: "/Users/user/project/out", 2122 OutputFormat: config.FormatESModule, 2123 TSConfigPath: "/Users/user/project/src/foo.json", 2124 }, 2125 expectedScanLog: `Users/user/project/src/foo.json: WARNING: Cannot find base config file "./" 2126 `, 2127 }) 2128 } 2129 2130 func TestTsconfigExtendsDotDotWithSlash(t *testing.T) { 2131 tsconfig_suite.expectBundled(t, bundled{ 2132 files: map[string]string{ 2133 "/Users/user/project/src/main.tsx": ` 2134 console.log(<div/>) 2135 `, 2136 "/Users/user/project/src/tsconfig.json": `{ 2137 "extends": "../" 2138 }`, 2139 "/Users/user/project/tsconfig.json": `{ 2140 "compilerOptions": { 2141 "jsxFactory": "FAILURE" 2142 } 2143 }`, 2144 }, 2145 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2146 options: config.Options{ 2147 Mode: config.ModeBundle, 2148 AbsOutputDir: "/Users/user/project/out", 2149 OutputFormat: config.FormatESModule, 2150 }, 2151 expectedScanLog: `Users/user/project/src/tsconfig.json: WARNING: Cannot find base config file "../" 2152 `, 2153 }) 2154 } 2155 2156 func TestTsconfigExtendsWithExports(t *testing.T) { 2157 tsconfig_suite.expectBundled(t, bundled{ 2158 files: map[string]string{ 2159 "/Users/user/project/src/main.tsx": ` 2160 console.log(<div/>) 2161 `, 2162 "/Users/user/project/tsconfig.json": `{ 2163 "extends": "@whatever/tsconfig/a/b/c" 2164 }`, 2165 "/Users/user/project/node_modules/@whatever/tsconfig/package.json": `{ 2166 "exports": { 2167 "./a/b/c": "./foo.json" 2168 } 2169 }`, 2170 "/Users/user/project/node_modules/@whatever/tsconfig/foo.json": `{ 2171 "compilerOptions": { 2172 "jsxFactory": "success" 2173 } 2174 }`, 2175 }, 2176 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2177 options: config.Options{ 2178 Mode: config.ModeBundle, 2179 AbsOutputDir: "/Users/user/project/out", 2180 OutputFormat: config.FormatESModule, 2181 }, 2182 }) 2183 } 2184 2185 func TestTsconfigExtendsWithExportsStar(t *testing.T) { 2186 tsconfig_suite.expectBundled(t, bundled{ 2187 files: map[string]string{ 2188 "/Users/user/project/src/main.tsx": ` 2189 console.log(<div/>) 2190 `, 2191 "/Users/user/project/tsconfig.json": `{ 2192 "extends": "@whatever/tsconfig/a/b/c" 2193 }`, 2194 "/Users/user/project/node_modules/@whatever/tsconfig/package.json": `{ 2195 "exports": { 2196 "./*": "./tsconfig.*.json" 2197 } 2198 }`, 2199 "/Users/user/project/node_modules/@whatever/tsconfig/tsconfig.a/b/c.json": `{ 2200 "compilerOptions": { 2201 "jsxFactory": "success" 2202 } 2203 }`, 2204 }, 2205 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2206 options: config.Options{ 2207 Mode: config.ModeBundle, 2208 AbsOutputDir: "/Users/user/project/out", 2209 OutputFormat: config.FormatESModule, 2210 }, 2211 }) 2212 } 2213 2214 func TestTsconfigExtendsWithExportsStarTrailing(t *testing.T) { 2215 tsconfig_suite.expectBundled(t, bundled{ 2216 files: map[string]string{ 2217 "/Users/user/project/src/main.tsx": ` 2218 console.log(<div/>) 2219 `, 2220 "/Users/user/project/tsconfig.json": `{ 2221 "extends": "@whatever/tsconfig/a/b/c.json" 2222 }`, 2223 "/Users/user/project/node_modules/@whatever/tsconfig/package.json": `{ 2224 "exports": { 2225 "./*": "./tsconfig.*" 2226 } 2227 }`, 2228 "/Users/user/project/node_modules/@whatever/tsconfig/tsconfig.a/b/c.json": `{ 2229 "compilerOptions": { 2230 "jsxFactory": "success" 2231 } 2232 }`, 2233 }, 2234 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2235 options: config.Options{ 2236 Mode: config.ModeBundle, 2237 AbsOutputDir: "/Users/user/project/out", 2238 OutputFormat: config.FormatESModule, 2239 }, 2240 }) 2241 } 2242 2243 func TestTsconfigExtendsWithExportsRequire(t *testing.T) { 2244 tsconfig_suite.expectBundled(t, bundled{ 2245 files: map[string]string{ 2246 "/Users/user/project/src/main.tsx": ` 2247 console.log(<div/>) 2248 `, 2249 "/Users/user/project/tsconfig.json": `{ 2250 "extends": "@whatever/tsconfig/a/b/c.json" 2251 }`, 2252 "/Users/user/project/node_modules/@whatever/tsconfig/package.json": `{ 2253 "exports": { 2254 "./*": { 2255 "import": "./import.json", 2256 "require": "./require.json", 2257 "default": "./default.json" 2258 } 2259 } 2260 }`, 2261 "/Users/user/project/node_modules/@whatever/tsconfig/import.json": `FAILURE`, 2262 "/Users/user/project/node_modules/@whatever/tsconfig/default.json": `FAILURE`, 2263 "/Users/user/project/node_modules/@whatever/tsconfig/require.json": `{ 2264 "compilerOptions": { 2265 "jsxFactory": "success" 2266 } 2267 }`, 2268 }, 2269 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2270 options: config.Options{ 2271 Mode: config.ModeBundle, 2272 AbsOutputDir: "/Users/user/project/out", 2273 OutputFormat: config.FormatESModule, 2274 }, 2275 }) 2276 } 2277 2278 func TestTsconfigVerbatimModuleSyntaxTrue(t *testing.T) { 2279 tsconfig_suite.expectBundled(t, bundled{ 2280 files: map[string]string{ 2281 "/Users/user/project/src/main.ts": ` 2282 export { Car } from "./car"; 2283 import type * as car from "./car"; 2284 import { type Car } from "./car"; 2285 export { type Car } from "./car"; 2286 import type { A } from "a"; 2287 import { b, type c, type d } from "bcd"; 2288 import { type xyz } from "xyz"; 2289 `, 2290 "/Users/user/project/tsconfig.json": `{ 2291 "compilerOptions": { 2292 "verbatimModuleSyntax": true 2293 } 2294 }`, 2295 }, 2296 entryPaths: []string{"/Users/user/project/src/main.ts"}, 2297 options: config.Options{ 2298 Mode: config.ModePassThrough, 2299 AbsOutputDir: "/Users/user/project/out", 2300 }, 2301 }) 2302 } 2303 2304 func TestTsconfigVerbatimModuleSyntaxFalse(t *testing.T) { 2305 tsconfig_suite.expectBundled(t, bundled{ 2306 files: map[string]string{ 2307 "/Users/user/project/src/main.ts": ` 2308 export { Car } from "./car"; 2309 import type * as car from "./car"; 2310 import { type Car } from "./car"; 2311 export { type Car } from "./car"; 2312 import type { A } from "a"; 2313 import { b, type c, type d } from "bcd"; 2314 import { type xyz } from "xyz"; 2315 `, 2316 "/Users/user/project/tsconfig.json": `{ 2317 "compilerOptions": { 2318 "verbatimModuleSyntax": false 2319 } 2320 }`, 2321 }, 2322 entryPaths: []string{"/Users/user/project/src/main.ts"}, 2323 options: config.Options{ 2324 Mode: config.ModePassThrough, 2325 AbsOutputDir: "/Users/user/project/out", 2326 }, 2327 }) 2328 } 2329 2330 func TestTsconfigExtendsArray(t *testing.T) { 2331 tsconfig_suite.expectBundled(t, bundled{ 2332 files: map[string]string{ 2333 "/Users/user/project/src/main.tsx": ` 2334 declare let h: any, frag: any 2335 console.log(<><div /></>) 2336 `, 2337 "/Users/user/project/tsconfig.json": `{ 2338 "extends": [ 2339 "./a.json", 2340 "./b.json", 2341 ], 2342 }`, 2343 "/Users/user/project/a.json": `{ 2344 "compilerOptions": { 2345 "jsxFactory": "h", 2346 "jsxFragmentFactory": "FAILURE", 2347 }, 2348 }`, 2349 "/Users/user/project/b.json": `{ 2350 "compilerOptions": { 2351 "jsxFragmentFactory": "frag", 2352 }, 2353 }`, 2354 }, 2355 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2356 options: config.Options{ 2357 Mode: config.ModePassThrough, 2358 AbsOutputDir: "/Users/user/project/out", 2359 }, 2360 }) 2361 } 2362 2363 func TestTsconfigExtendsArrayNested(t *testing.T) { 2364 tsconfig_suite.expectBundled(t, bundled{ 2365 files: map[string]string{ 2366 "/Users/user/project/src/main.tsx": ` 2367 import { foo } from 'foo' 2368 declare let b: any, bBase: any 2369 export class Foo { 2370 render = () => <><div /></> 2371 } 2372 `, 2373 "/Users/user/project/tsconfig.json": `{ 2374 "extends": [ 2375 "./a.json", 2376 "./b.json", 2377 ], 2378 }`, 2379 "/Users/user/project/a.json": `{ 2380 "extends": "./a-base.json", 2381 "compilerOptions": { 2382 "jsxFactory": "a", 2383 "jsxFragmentFactory": "a", 2384 "target": "ES2015", 2385 }, 2386 }`, 2387 "/Users/user/project/a-base.json": `{ 2388 "compilerOptions": { 2389 "jsxFactory": "aBase", 2390 "jsxFragmentFactory": "aBase", 2391 "target": "ES2022", 2392 "verbatimModuleSyntax": true, 2393 }, 2394 }`, 2395 "/Users/user/project/b.json": `{ 2396 "extends": "./b-base.json", 2397 "compilerOptions": { 2398 "jsxFactory": "b", 2399 }, 2400 }`, 2401 "/Users/user/project/b-base.json": `{ 2402 "compilerOptions": { 2403 "jsxFactory": "bBase", 2404 "jsxFragmentFactory": "bBase", 2405 }, 2406 }`, 2407 }, 2408 entryPaths: []string{"/Users/user/project/src/main.tsx"}, 2409 options: config.Options{ 2410 Mode: config.ModePassThrough, 2411 AbsOutputDir: "/Users/user/project/out", 2412 OriginalTargetEnv: "esnext", 2413 }, 2414 }) 2415 } 2416 2417 func TestTsconfigIgnoreInsideNodeModules(t *testing.T) { 2418 tsconfig_suite.expectBundled(t, bundled{ 2419 files: map[string]string{ 2420 "/Users/user/project/src/main.ts": ` 2421 import { foo } from 'js-pkg' 2422 import { bar } from 'ts-pkg' 2423 import { foo as shimFoo, bar as shimBar } from 'pkg' 2424 if (foo !== 'foo') throw 'fail: foo' 2425 if (bar !== 'bar') throw 'fail: bar' 2426 if (shimFoo !== 'shimFoo') throw 'fail: shimFoo' 2427 if (shimBar !== 'shimBar') throw 'fail: shimBar' 2428 `, 2429 "/Users/user/project/shim.ts": ` 2430 export let foo = 'shimFoo' 2431 export let bar = 'shimBar' 2432 `, 2433 "/Users/user/project/tsconfig.json": `{ 2434 "compilerOptions": { 2435 "paths": { 2436 "pkg": ["./shim"], 2437 }, 2438 }, 2439 }`, 2440 "/Users/user/project/node_modules/js-pkg/index.js": ` 2441 import { foo as pkgFoo } from 'pkg' 2442 export let foo = pkgFoo 2443 `, 2444 "/Users/user/project/node_modules/ts-pkg/index.ts": ` 2445 import { bar as pkgBar } from 'pkg' 2446 export let bar = pkgBar 2447 `, 2448 "/Users/user/project/node_modules/pkg/index.js": ` 2449 export let foo = 'foo' 2450 export let bar = 'bar' 2451 `, 2452 }, 2453 entryPaths: []string{"/Users/user/project/src/main.ts"}, 2454 options: config.Options{ 2455 Mode: config.ModeBundle, 2456 AbsOutputDir: "/Users/user/project/out", 2457 }, 2458 }) 2459 } 2460 2461 func TestTsconfigJsonPackagesExternal(t *testing.T) { 2462 tsconfig_suite.expectBundled(t, bundled{ 2463 files: map[string]string{ 2464 "/Users/user/project/src/entry.js": ` 2465 import truePkg from 'pkg1' 2466 import falsePkg from 'internal/pkg2' 2467 truePkg() 2468 falsePkg() 2469 `, 2470 "/Users/user/project/src/tsconfig.json": ` 2471 { 2472 "compilerOptions": { 2473 "paths": { 2474 "internal/*": ["./stuff/*"] 2475 } 2476 } 2477 } 2478 `, 2479 "/Users/user/project/src/stuff/pkg2.js": ` 2480 export default success 2481 `, 2482 }, 2483 entryPaths: []string{"/Users/user/project/src/entry.js"}, 2484 options: config.Options{ 2485 Mode: config.ModeBundle, 2486 AbsOutputFile: "/Users/user/project/out.js", 2487 ExternalPackages: true, 2488 }, 2489 }) 2490 } 2491 2492 func TestTsconfigJsonTopLevelMistakeWarning(t *testing.T) { 2493 tsconfig_suite.expectBundled(t, bundled{ 2494 files: map[string]string{ 2495 "/Users/user/project/src/entry.ts": ` 2496 @foo 2497 class Foo {} 2498 `, 2499 "/Users/user/project/src/tsconfig.json": ` 2500 { 2501 "experimentalDecorators": true 2502 } 2503 `, 2504 }, 2505 entryPaths: []string{"/Users/user/project/src/entry.ts"}, 2506 options: config.Options{ 2507 Mode: config.ModeBundle, 2508 AbsOutputFile: "/Users/user/project/out.js", 2509 }, 2510 expectedScanLog: `Users/user/project/src/tsconfig.json: WARNING: Expected the "experimentalDecorators" option to be nested inside a "compilerOptions" object 2511 `, 2512 }) 2513 } 2514 2515 // https://github.com/evanw/esbuild/issues/3307 2516 func TestTsconfigJsonBaseUrlIssue3307(t *testing.T) { 2517 tsconfig_suite.expectBundled(t, bundled{ 2518 files: map[string]string{ 2519 "/Users/user/project/src/tsconfig.json": ` 2520 { 2521 "compilerOptions": { 2522 "baseUrl": "./subdir" 2523 } 2524 } 2525 `, 2526 "/Users/user/project/src/test.ts": ` 2527 export const foo = "well, this is correct..."; 2528 `, 2529 "/Users/user/project/src/subdir/test.ts": ` 2530 export const foo = "WRONG"; 2531 `, 2532 }, 2533 entryPaths: []string{"test.ts"}, 2534 absWorkingDir: "/Users/user/project/src", 2535 options: config.Options{ 2536 Mode: config.ModeBundle, 2537 AbsOutputFile: "/Users/user/project/out.js", 2538 }, 2539 }) 2540 } 2541 2542 // https://github.com/evanw/esbuild/issues/3354 2543 func TestTsconfigJsonAsteriskNameCollisionIssue3354(t *testing.T) { 2544 tsconfig_suite.expectBundled(t, bundled{ 2545 files: map[string]string{ 2546 "/Users/user/project/src/entry.ts": ` 2547 import {foo} from "foo"; 2548 foo(); 2549 `, 2550 "/Users/user/project/src/tsconfig.json": ` 2551 { 2552 "compilerOptions": { 2553 "baseUrl": ".", 2554 "paths": { 2555 "*": ["web/*"] 2556 } 2557 } 2558 } 2559 `, 2560 "/Users/user/project/src/web/foo.ts": ` 2561 import {foo as barFoo} from 'bar/foo'; 2562 export function foo() { 2563 console.log('web/foo'); 2564 barFoo(); 2565 } 2566 `, 2567 "/Users/user/project/src/web/bar/foo/foo.ts": ` 2568 export function foo() { 2569 console.log('bar/foo'); 2570 } 2571 `, 2572 "/Users/user/project/src/web/bar/foo/index.ts": ` 2573 export {foo} from './foo' 2574 `, 2575 }, 2576 entryPaths: []string{"entry.ts"}, 2577 absWorkingDir: "/Users/user/project/src", 2578 options: config.Options{ 2579 Mode: config.ModeBundle, 2580 AbsOutputFile: "/Users/user/project/out.js", 2581 }, 2582 }) 2583 } 2584 2585 // https://github.com/evanw/esbuild/issues/3698 2586 func TestTsconfigPackageJsonExportsYarnPnP(t *testing.T) { 2587 tsconfig_suite.expectBundled(t, bundled{ 2588 files: map[string]string{ 2589 "/Users/user/project/packages/app/index.tsx": ` 2590 console.log(<div/>) 2591 `, 2592 "/Users/user/project/packages/app/tsconfig.json": ` 2593 { 2594 "extends": "tsconfigs/config" 2595 } 2596 `, 2597 "/Users/user/project/packages/tsconfigs/package.json": ` 2598 { 2599 "exports": { 2600 "./config": "./configs/tsconfig.json" 2601 } 2602 } 2603 `, 2604 "/Users/user/project/packages/tsconfigs/configs/tsconfig.json": ` 2605 { 2606 "compilerOptions": { 2607 "jsxFactory": "success" 2608 } 2609 } 2610 `, 2611 "/Users/user/project/.pnp.data.json": ` 2612 { 2613 "packageRegistryData": [ 2614 [ 2615 "app", 2616 [ 2617 [ 2618 "workspace:packages/app", 2619 { 2620 "packageLocation": "./packages/app/", 2621 "packageDependencies": [ 2622 [ 2623 "tsconfigs", 2624 "workspace:packages/tsconfigs" 2625 ] 2626 ], 2627 "linkType": "SOFT" 2628 } 2629 ] 2630 ] 2631 ], 2632 [ 2633 "tsconfigs", 2634 [ 2635 [ 2636 "workspace:packages/tsconfigs", 2637 { 2638 "packageLocation": "./packages/tsconfigs/", 2639 "packageDependencies": [], 2640 "linkType": "SOFT" 2641 } 2642 ] 2643 ] 2644 ] 2645 ] 2646 } 2647 `, 2648 }, 2649 entryPaths: []string{"/Users/user/project/packages/app/index.tsx"}, 2650 absWorkingDir: "/Users/user/project", 2651 options: config.Options{ 2652 Mode: config.ModeBundle, 2653 AbsOutputFile: "/Users/user/project/out.js", 2654 }, 2655 }) 2656 }