package resolver

import (
	
	
	
	
	
	

	
	
	
	
	
	
	
	
)

Note that this means if a package specifies "main", "module", and "browser" then "browser" will win out over "module". This is the same behavior as webpack: https://github.com/webpack/webpack/issues/4674. This is deliberate because the presence of the "browser" field is a good signal that the "module" field may have non-browser stuff in it, which will crash or fail to be bundled when targeting the browser.
	config.PlatformBrowser: {"browser", "module", "main"},
Note that this means if a package specifies "module" and "main", the ES6 module will not be selected. This means tree shaking will not work when targeting node environments. This is unfortunately necessary for compatibility. Some packages incorrectly treat the "module" field as "code for the browser". It actually means "code for ES6 environments" which includes both node and the browser. For example, the package "@firebase/app" prints a warning on startup about the bundler incorrectly using code meant for the browser if the bundler selects the "module" field instead of the "main" field. If you want to enable tree shaking when targeting node, you will have to configure the main fields to be "module" and then "main". Keep in mind that some packages may break if you do this.
	config.PlatformNode: {"main", "module"},
The neutral platform is for people that don't want esbuild to try to pick good defaults for their platform. In that case, the list of main fields is empty by default. You must explicitly configure it yourself.
Path resolution is a mess. One tricky issue is the "module" override for the "main" field in "package.json" files. Bundlers generally prefer "module" over "main" but that breaks packages that export a function in "main" for use with "require()", since resolving to "module" means an object will be returned. We attempt to handle this automatically by having import statements resolve to "module" but switch that out later for "main" if "require()" is used too.
Either secondary will be empty, or primary will be "module" and secondary will be "main"
	Primary   logger.Path
	Secondary logger.Path
}

func ( *PathPair) () []*logger.Path {
	 := []*logger.Path{&.Primary, &.Secondary}
	if !.HasSecondary() {
		 = [:1]
	}
	return 
}

func ( *PathPair) () bool {
	return .Secondary.Text != ""
}

type IgnoreIfUnusedData struct {
	Source *logger.Source
	Range  logger.Range
If true, "sideEffects" was an array. If false, "sideEffects" was false.
If this was resolved by a plugin, the plugin gets to store its data here
	PluginData interface{}
If not empty, these should override the default values
	JSXFactory  []string // Default if empty: "React.createElement"
	JSXFragment []string // Default if empty: "React.Fragment"

	IsExternal    bool
	DifferentCase *fs.DifferentCase
If true, any ES6 imports to this file can be considered to have no side effects. This means they should be removed if unused.
If true, the class field transform should use Object.defineProperty().
If true, unused imports are retained in TypeScript code. This matches the behavior of the "importsNotUsedAsValues" field in "tsconfig.json" when the value is not "remove".
	PreserveUnusedImportsTS bool
}

type Resolver interface {
	Resolve(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult
	ResolveAbs(absPath string) *ResolveResult
	PrettyPath(path logger.Path) string
This tries to run "Resolve" on a package path as a relative path. If successful, the user just forgot a leading "./" in front of the path.
	ProbeResolvePackageAsRelative(sourceDir string, importPath string, kind ast.ImportKind) *ResolveResult
}

type resolver struct {
	fs      fs.FS
	log     logger.Log
	caches  *cache.CacheSet
	options config.Options
A special filtered import order for CSS "@import" imports. The "resolve extensions" setting determines the order of implicit extensions to try when resolving imports with the extension omitted. Sometimes people create a JavaScript/TypeScript file and a CSS file with the same name when they create a component. At a high level, users expect implicit extensions to resolve to the JS file when being imported from JS and to resolve to the CSS file when being imported from CSS. Different bundlers handle this in different ways. Parcel handles this by having the resolver prefer the same extension as the importing file in front of the configured "resolve extensions" order. Webpack's "css-loader" plugin just explicitly configures a special "resolve extensions" order consisting of only ".css" for CSS files. It's unclear what behavior is best here. What we currently do is to create a special filtered version of the configured "resolve extensions" order for CSS files that filters out any extension that has been explicitly configured with a non-CSS loader. This still gives users control over the order but avoids the scenario where we match an import in a CSS file to a JavaScript-related file. It's probably not perfect with plugins in the picture but it's better than some alternatives and probably pretty good.
This mutex serves two purposes. First of all, it guards access to "dirCache" which is potentially mutated during path resolution. But this mutex is also necessary for performance. The "React admin" benchmark mysteriously runs twice as fast when this mutex is locked around the whole resolve operation instead of around individual accesses to "dirCache". For some reason, reducing parallelism in the resolver helps the rest of the bundler go faster. I'm not sure why this is but please don't change this unless you do a lot of testing with various benchmarks and there aren't any regressions.
This cache maps a directory path to information about that directory and all parent directories
Bundling for node implies allowing node's builtin modules
	if .Platform == config.PlatformNode {
		 := make(map[string]bool)
		if .ExternalModules.NodeModules != nil {
			for  := range .ExternalModules.NodeModules {
				[] = true
			}
		}
		for  := range BuiltInNodeModules {
			[] = true
		}
		.ExternalModules.NodeModules = 
	}
Filter out non-CSS extensions for CSS "@import" imports
	 := make([]string, 0, len(.ExtensionOrder))
	for ,  := range .ExtensionOrder {
		if ,  := .ExtensionToLoader[];  &&  != config.LoaderCSS {
			continue
		}
		 = append(, )
	}

	return &resolver{
		fs:                     ,
		log:                    ,
		options:                ,
		caches:                 ,
		dirCache:               make(map[string]*dirInfo),
		atImportExtensionOrder: ,
	}
}

Certain types of URLs default to being external for convenience
	if .isExternalPattern() ||
"fill: url(#filter);"
		(.IsFromCSS() && strings.HasPrefix(, "#")) ||
"background: url(http://example.com/images/image.png);"
		strings.HasPrefix(, "http://") ||
"background: url(https://example.com/images/image.png);"
		strings.HasPrefix(, "https://") ||
"background: url(//example.com/images/image.png);"
		strings.HasPrefix(, "//") {

		return &ResolveResult{
			PathPair:   PathPair{Primary: logger.Path{Text: }},
			IsExternal: true,
		}
	}

"import 'data:text/javascript,console.log(123)';" "@import 'data:text/css,body{background:white}';"
		if .DecodeMIMEType() != MIMETypeUnsupported {
			return &ResolveResult{
				PathPair: PathPair{Primary: logger.Path{Text: , Namespace: "dataurl"}},
			}
		}
"background: url(data:image/png;base64,iVBORw0KGgo=);"
Fail now if there is no directory to resolve in. This can happen for virtual modules (e.g. stdin) if a resolve directory is not specified.
	if  == "" {
		return nil
	}

	.mutex.Lock()
	defer .mutex.Unlock()

	 := .resolveWithoutSymlinks(, , )
If resolution failed, try again with the URL query and/or hash removed
		 := strings.IndexAny(, "?#")
		if  < 1 {
			return nil
		}
		 = .resolveWithoutSymlinks(, [:], )
		if  == nil {
			return nil
		}
		.PathPair.Primary.IgnoredSuffix = [:]
		if .PathPair.HasSecondary() {
			.PathPair.Secondary.IgnoredSuffix = [:]
		}
	}
If successful, resolve symlinks using the directory info cache
	.finalizeResolve()
	return 
}

func ( *resolver) ( string) bool {
	for ,  := range .options.ExternalModules.Patterns {
		if len() >= len(.Prefix)+len(.Suffix) &&
			strings.HasPrefix(, .Prefix) &&
			strings.HasSuffix(, .Suffix) {
			return true
		}
	}
	return false
}

func ( *resolver) ( string) *ResolveResult {
	.mutex.Lock()
	defer .mutex.Unlock()
Just decorate the absolute path with information from parent directories
	 := &ResolveResult{PathPair: PathPair{Primary: logger.Path{Text: , Namespace: "file"}}}
	.finalizeResolve()
	return 
}

func ( *resolver) ( string,  string,  ast.ImportKind) *ResolveResult {
	 := .fs.Join(, )

	.mutex.Lock()
	defer .mutex.Unlock()

	if , ,  := .loadAsFileOrDirectory(, );  {
		 := &ResolveResult{PathPair: , DifferentCase: }
		.finalizeResolve()
		return 
	}
	return nil
}

func ( string) bool {
This is written in a platform-independent manner because it's run on user-specified paths which can be arbitrary non-file-system things. So for example Windows paths may end up being used on Unix or URLs may end up being used on Windows. Be consistently agnostic to which kind of slash is used on all platforms.
		 := strings.LastIndexAny(, "/\\")
		if  == -1 {
			return false
		}
		,  := [:], [+1:]
		if  == "node_modules" {
			return true
		}
		 = 
	}
}

func ( *resolver) ( *ResolveResult) {
	for ,  := range .PathPair.iter() {
		if .Namespace == "file" {
			if  := .dirInfoCached(.fs.Dir(.Text));  != nil {
				 := .fs.Base(.Text)
Look up this file in the "sideEffects" map in the nearest enclosing directory with a "package.json" file. Only do this for the primary path. Some packages have the primary path marked as having side effects and the secondary path marked as not having side effects. This is likely a bug in the package definition but we don't want to consider the primary path as not having side effects just because the secondary path is marked as not having side effects.
				if * == .PathPair.Primary {
					for  := ;  != nil;  = .parent {
						if .packageJSON != nil {
							if .packageJSON.sideEffectsMap != nil {
								 := false
Fast path: map lookup
									 = true
Slow path: glob tests
									for ,  := range .packageJSON.sideEffectsRegexps {
										if .MatchString(.Text) {
											 = true
											break
										}
									}
								}
								if ! {
									.IgnorePrimaryIfUnused = .packageJSON.ignoreIfUnusedData
								}
							}
							break
						}
					}
				}
Copy various fields from the nearest enclosing "tsconfig.json" file if present
				if  == &.PathPair.Primary && .tsConfigJSON != nil {
					.JSXFactory = .tsConfigJSON.JSXFactory
					.JSXFragment = .tsConfigJSON.JSXFragmentFactory
					.UseDefineForClassFieldsTS = .tsConfigJSON.UseDefineForClassFields
					.PreserveUnusedImportsTS = .tsConfigJSON.PreserveImportsNotUsedAsValues
				}

				if !.options.PreserveSymlinks {
					if ,  := .entries.Get();  != nil {
Is this entry itself a symlink?
							.Text = 
Is there at least one parent directory with a symlink?
							.Text = .fs.Join(.absRealPath, )
						}
					}
				}
			}
		}
	}
}

This implements the module resolution algorithm from node.js, which is described here: https://nodejs.org/api/modules.html#modules_all_together
	var  ResolveResult
Return early if this is already an absolute path. In addition to asking the file system whether this is an absolute path, we also explicitly check whether it starts with a "/" and consider that an absolute path too. This is because relative paths can technically start with a "/" on Windows because it's not an absolute path on Windows. Then people might write code with imports that start with a "/" that works fine on Windows only to experience unexpected build failures later on other operating systems. Treating these paths as absolute paths on all platforms means Windows users will not be able to accidentally make use of these paths.
First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file
		if  := .dirInfoCached();  != nil && .tsConfigJSON != nil && .tsConfigJSON.Paths != nil {
			if , ,  := .matchTSConfigPaths(.tsConfigJSON, , );  {
				return &ResolveResult{PathPair: , DifferentCase: }
			}
		}

If the string literal in the source text is an absolute path and has been marked as an external module, mark it as *not* an absolute path. That way we preserve the literal text in the output and don't generate a relative path from the output directory to that path.
Run node's resolution rules (e.g. adding ".js")
		if , ,  := .loadAsFileOrDirectory(, );  {
			return &ResolveResult{PathPair: , DifferentCase: }
		}
		return nil
	}
Check both relative and package paths for CSS URL tokens, with relative paths taking precedence over package paths to match Webpack behavior.
	 := IsPackagePath()
	 := ! ||  == ast.ImportURL
	 := 

	if  {
		 := .fs.Join(, )
Check for external packages first
Check the non-package "browser" map for the first time (1 out of 2)
		 := .dirInfoCached(.fs.Dir())
		if  != nil && .enclosingBrowserScope != nil {
			if  := .enclosingBrowserScope.packageJSON; .browserNonPackageMap != nil {
				if ,  := .browserNonPackageMap[];  {
					if  == nil {
						return &ResolveResult{PathPair: PathPair{Primary: logger.Path{Text: , Namespace: "file", Flags: logger.PathDisabled}}}
					} else if , ,  := .resolveWithoutRemapping(.enclosingBrowserScope, *, );  {
						 = ResolveResult{PathPair: , DifferentCase: }
						 = false
						 = false
					}
				}
			}
		}

		if  {
			if , ,  := .loadAsFileOrDirectory(, );  {
				 = false
				 = ResolveResult{PathPair: , DifferentCase: }
			} else if ! {
				return nil
			}
		}
	}

Check for external packages first
		if .options.ExternalModules.NodeModules != nil {
			 := 
			for {
				if .options.ExternalModules.NodeModules[] {
					return &ResolveResult{PathPair: PathPair{Primary: logger.Path{Text: }}, IsExternal: true}
				}
If the module "foo" has been marked as external, we also want to treat paths into that module such as "foo/bar" as external too.
				 := strings.LastIndexByte(, '/')
				if  == -1 {
					break
				}
				 = [:]
			}
		}

		 := .dirInfoCached()
Bail if the directory is missing for some reason
			return nil
		}
Support remapping one package path to another via the "browser" field
		if .enclosingBrowserScope != nil {
			 := .enclosingBrowserScope.packageJSON
			if .browserPackageMap != nil {
				if ,  := .browserPackageMap[];  {
"browser": {"module": false}
						if , ,  := .loadNodeModules(, , );  {
							.Primary = logger.Path{Text: .Primary.Text, Namespace: "file", Flags: logger.PathDisabled}
							if .HasSecondary() {
								.Secondary = logger.Path{Text: .Secondary.Text, Namespace: "file", Flags: logger.PathDisabled}
							}
							return &ResolveResult{PathPair: , DifferentCase: }
						} else {
							return &ResolveResult{PathPair: PathPair{Primary: logger.Path{Text: , Flags: logger.PathDisabled}}, DifferentCase: }
						}
"browser": {"module": "./some-file"} "browser": {"module": "another-module"}
						 = *
						 = .enclosingBrowserScope
					}
				}
			}
		}

		if , ,  := .resolveWithoutRemapping(, , );  {
			 = ResolveResult{PathPair: , DifferentCase: }
Note: node's "self references" are not currently supported
			return nil
		}
	}
Check the directory that contains this file
	for ,  := range .PathPair.iter() {
		 := .fs.Dir(.Text)
		 := .dirInfoCached()
Check the non-package "browser" map for the second time (2 out of 2)
		if  != nil && .enclosingBrowserScope != nil {
			 := .enclosingBrowserScope.packageJSON
			if .browserNonPackageMap != nil {
				if ,  := .browserNonPackageMap[.Text];  {
					if  == nil {
						.Flags |= logger.PathDisabled
					} else if , ,  := .resolveWithoutRemapping(.enclosingBrowserScope, *, );  {
						* = .Primary
					} else {
						return nil
					}
				}
			}
		}
	}

	return &
}

func ( *resolver) ( *dirInfo,  string,  ast.ImportKind) (PathPair, bool, *fs.DifferentCase) {
	if IsPackagePath() {
		return .loadNodeModules(, , )
	} else {
		return .loadAsFileOrDirectory(.fs.Join(.absPath, ), )
	}
}

func ( *resolver) ( logger.Path) string {
	if .Namespace == "file" {
		if ,  := .fs.Rel(.fs.Cwd(), .Text);  {
			.Text = 
		}
These human-readable paths are used in error messages, comments in output files, source names in source maps, and paths in the metadata JSON file. These should be platform-independent so our output doesn't depend on which operating system it was run. Replace Windows backward slashes with standard forward slashes.
		.Text = strings.ReplaceAll(.Text, "\\", "/")
	} else if .Namespace != "" {
		.Text = fmt.Sprintf("%s:%s", .Namespace, .Text)
	}

	if .IsDisabled() {
		.Text = "(disabled):" + .Text
	}

	return .Text + .IgnoredSuffix
}
//////////////////////////////////////////////////////////////////////////////
Present if the "browser" field is present. This field is intended to be used by bundlers and lets you redirect the paths of certain 3rd-party modules that don't work in the browser to other modules that shim that functionality. That way you don't have to rewrite the code for those 3rd- party modules. For example, you might remap the native "util" node module to something like https://www.npmjs.com/package/util so it works in the browser. This field contains a mapping of absolute paths to absolute paths. Mapping to an empty path indicates that the module is disabled. As far as I can tell, the official spec is a GitHub repo hosted by a user account: https://github.com/defunctzombie/package-browser-field-spec. The npm docs say almost nothing: https://docs.npmjs.com/files/package.json. Note that the non-package "browser" map has to be checked twice to match Webpack's behavior: once before resolution and once after resolution. It leads to some unintuitive failure cases that we must emulate around missing file extensions: * Given the mapping "./no-ext": "./no-ext-browser.js" the query "./no-ext" should match but the query "./no-ext.js" should NOT match. * Given the mapping "./ext.js": "./ext-browser.js" the query "./ext.js" should match and the query "./ext" should ALSO match.
If this is non-nil, each entry in this map is the absolute path of a file with side effects. Any entry not in this map should be considered to have no side effects, which means import statements for these files can be removed if none of the imports are used. This is a convention from Webpack: https://webpack.js.org/guides/tree-shaking/. Note that if a file is included, all statements that can't be proven to be free of side effects must be included. This convention does not say anything about whether any statements within the file have side effects or not.
These objects are immutable, so we can just point to the parent directory and avoid having to lock the cache again
A pointer to the enclosing dirInfo with a valid "browser" field in package.json. We need this to remap paths after they have been resolved.
All relevant information about this directory
	absPath        string
	entries        fs.DirEntries
	hasNodeModules bool          // Is there a "node_modules" subdirectory?
	absPathIndex   *string       // Is there an "index.js" file?
	packageJSON    *packageJSON  // Is there a "package.json" file?
	tsConfigJSON   *TSConfigJSON // Is there a "tsconfig.json" file in this directory or a parent directory?
	absRealPath    string        // If non-empty, this is the real absolute path resolving any symlinks
}

First, check the cache
	,  := .dirCache[]
Cache hit: stop now
	if  {
		return 
	}
Cache miss: read the info
	 := .dirInfoUncached()
Update the cache unconditionally. Even if the read failed, we don't want to retry again later. The directory is inaccessible so trying again is wasted.
	.dirCache[] = 
	return 
}

var parseErrorImportCycle = errors.New("(import cycle)")
var parseErrorAlreadyLogged = errors.New("(error already logged)")
This may return "parseErrorAlreadyLogged" in which case there was a syntax error, but it's already been reported. No further errors should be logged. Nested calls may also return "parseErrorImportCycle". In that case the caller is responsible for logging an appropriate error message.
Don't infinite loop if a series of "extends" links forms a cycle
	if [] {
		return nil, parseErrorImportCycle
	}
	[] = true

	,  := .caches.FSCache.ReadFile(.fs, )
	if  != nil {
		return nil, 
	}

	 := logger.Path{Text: , Namespace: "file"}
	 := logger.Source{
		KeyPath:    ,
		PrettyPath: .PrettyPath(),
		Contents:   ,
	}
	 := .fs.Dir()

	 := ParseTSConfigJSON(.log, , &.caches.JSONCache, func( string,  logger.Range) *TSConfigJSON {
If this is a package path, try to resolve it to a "node_modules" folder. This doesn't use the normal node module resolution algorithm both because it's different (e.g. we don't want to match a directory) and because it would deadlock since we're currently in the middle of populating the directory info cache.
			 := 
Skip "node_modules" folders
				if .fs.Base() != "node_modules" {
					 := .fs.Join(, "node_modules", )
					 := []string{.fs.Join(, "tsconfig.json"), ,  + ".json"}
					for ,  := range  {
						,  := .(, )
						if  == nil {
							return 
						} else if  == syscall.ENOENT {
							continue
						} else if  == parseErrorImportCycle {
							.log.AddRangeWarning(&, ,
								fmt.Sprintf("Base config file %q forms cycle", ))
						} else if  != parseErrorAlreadyLogged {
							.log.AddRangeError(&, ,
								fmt.Sprintf("Cannot read file %q: %s",
									.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
						}
						return nil
					}
				}
Go to the parent directory, stopping at the file system root
				 := .fs.Dir()
				if  ==  {
					break
				}
				 = 
			}
If this is a regular path, search relative to the enclosing directory
			 := 
			if !.fs.IsAbs() {
				 = .fs.Join(, )
			}
			for ,  := range []string{,  + ".json"} {
				,  := .(, )
				if  == nil {
					return 
				} else if  == syscall.ENOENT {
					continue
				} else if  == parseErrorImportCycle {
					.log.AddRangeWarning(&, ,
						fmt.Sprintf("Base config file %q forms cycle", ))
				} else if  != parseErrorAlreadyLogged {
					.log.AddRangeError(&, ,
						fmt.Sprintf("Cannot read file %q: %s",
							.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
				}
				return nil
			}
		}
Suppress warnings about missing base config files inside "node_modules"
		if !IsInsideNodeModules() {
			.log.AddRangeWarning(&, ,
				fmt.Sprintf("Cannot find base config file %q", ))
		}

		return nil
	})

	if  == nil {
		return nil, parseErrorAlreadyLogged
	}

	if .BaseURL != nil && !.fs.IsAbs(*.BaseURL) {
		*.BaseURL = .fs.Join(, *.BaseURL)
	}

	if .Paths != nil && !.fs.IsAbs(.BaseURLForPaths) {
		.BaseURLForPaths = .fs.Join(, .BaseURLForPaths)
	}

	return , nil
}

Get the info for the parent directory
	var  *dirInfo
	 := .fs.Dir()
	if  !=  {
		 = .dirInfoCached()
Stop now if the parent directory doesn't exist
		if  == nil {
			return nil
		}
	}
List the directories
	,  := .fs.ReadDirectory()
Ignore "ENOTDIR" here so that calling "ReadDirectory" on a file behaves as if there is nothing there at all instead of causing an error due to the directory actually being a file. This is a workaround for situations where people try to import from a path containing a file as a parent directory. The "pnpm" package manager generates a faulty "NODE_PATH" list which contains such paths and treating them as missing means we just ignore them during path resolution.
		if  != syscall.ENOENT &&  != syscall.ENOTDIR {
			.log.AddError(nil, logger.Loc{},
				fmt.Sprintf("Cannot read directory %q: %s",
					.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
		}
		return nil
	}
	 := &dirInfo{
		absPath: ,
		parent:  ,
		entries: ,
	}
A "node_modules" directory isn't allowed to directly contain another "node_modules" directory
	 := .fs.Base()
	if  != "node_modules" {
		if ,  := .Get("node_modules");  != nil {
			.hasNodeModules = .Kind(.fs) == fs.DirEntry
		}
	}
Propagate the browser scope into child directories
	if  != nil {
		.enclosingBrowserScope = .enclosingBrowserScope
Make sure "absRealPath" is the real path of the directory (resolving any symlinks)
		if !.options.PreserveSymlinks {
			if ,  := .entries.Get();  != nil {
				if  := .Symlink(.fs);  != "" {
					.absRealPath = 
				} else if .absRealPath != "" {
					.absRealPath = .fs.Join(.absRealPath, )
				}
			}
		}
	}
Record if this directory has a package.json file
	if ,  := .Get("package.json");  != nil && .Kind(.fs) == fs.FileEntry {
		.packageJSON = .parsePackageJSON()
Propagate this browser scope into child directories
Record if this directory has a tsconfig.json or jsconfig.json file
	{
		var  string
		if  := .options.TsConfigOverride;  == "" {
			if ,  := .Get("tsconfig.json");  != nil && .Kind(.fs) == fs.FileEntry {
				 = .fs.Join(, "tsconfig.json")
			} else if ,  := .Get("jsconfig.json");  != nil && .Kind(.fs) == fs.FileEntry {
				 = .fs.Join(, "jsconfig.json")
			}
If there is a tsconfig.json override, mount it at the root directory
			 = 
		}
		if  != "" {
			var  error
			.tsConfigJSON,  = .parseTSConfig(, make(map[string]bool))
			if  != nil {
				if  == syscall.ENOENT {
					.log.AddError(nil, logger.Loc{}, fmt.Sprintf("Cannot find tsconfig file %q",
						.PrettyPath(logger.Path{Text: , Namespace: "file"})))
				} else if  != parseErrorAlreadyLogged {
					.log.AddError(nil, logger.Loc{},
						fmt.Sprintf("Cannot read file %q: %s",
							.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
				}
			}
		}
	}
Propagate the enclosing tsconfig.json from the parent directory
	if .tsConfigJSON == nil &&  != nil {
		.tsConfigJSON = .tsConfigJSON
	}
Look for an "index" file with known extensions
	if , ,  := .loadAsIndex(, );  {
		.absPathIndex = &
	}

	return 
}

func ( *resolver) ( string) *packageJSON {
	 := .fs.Join(, "package.json")
	,  := .caches.FSCache.ReadFile(.fs, )
	if  != nil {
		.log.AddError(nil, logger.Loc{},
			fmt.Sprintf("Cannot read file %q: %s",
				.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
		return nil
	}

	 := logger.Path{Text: , Namespace: "file"}
	 := logger.Source{
		KeyPath:    ,
		PrettyPath: .PrettyPath(),
		Contents:   ,
	}

	,  := .caches.JSONCache.Parse(.log, , js_parser.JSONOptions{})
	if ! {
		return nil
	}

Is it a file?
		if , ,  := .loadAsFile(, .options.ExtensionOrder);  {
			return &
		}
Is it a directory?
Look for an "index" file with known extensions
			if , ,  := .loadAsIndex(, );  {
				return &
			}
		} else if  != syscall.ENOENT {
			.log.AddRangeError(&, ,
				fmt.Sprintf("Cannot read directory %q: %s",
					.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
		}
		return nil
	}

	 := &packageJSON{}
Read the "main" fields
	 := .options.MainFields
	if  == nil {
		 = defaultMainFields[.options.Platform]
	}
	for ,  := range  {
		if , ,  := getProperty(, );  {
			if ,  := getString();  {
				if .absMainFields == nil {
					.absMainFields = make(map[string]string)
				}
				if  := (.fs.Join(, ), .RangeOfString(.Loc));  != nil {
					.absMainFields[] = *
				}
			}
		}
	}
Read the "browser" property, but only when targeting the browser
We both want the ability to have the option of CJS vs. ESM and the option of having node vs. browser. The way to do this is to use the object literal form of the "browser" field like this: "main": "dist/index.node.cjs.js", "module": "dist/index.node.esm.js", "browser": { "./dist/index.node.cjs.js": "./dist/index.browser.cjs.js", "./dist/index.node.esm.js": "./dist/index.browser.esm.js" },
The value is an object
			 := make(map[string]*string)
			 := make(map[string]*string)
Remap all files in the browser field
			for ,  := range .Properties {
				if ,  := getString(.Key);  && .Value != nil {
					 := IsPackagePath()
Make this an absolute path if it's not a package
					if ! {
						 = .fs.Join(, )
					}

If this is a string, it's a replacement package
						if  {
							[] = &
						} else {
							[] = &
						}
If this is false, it means the package is disabled
						if  {
							[] = nil
						} else {
							[] = nil
						}
					}
				}
			}

			.browserPackageMap = 
			.browserNonPackageMap = 
		}
	}
Read the "sideEffects" property
	if , ,  := getProperty(, "sideEffects");  {
		switch data := .Data.(type) {
		case *js_ast.EBoolean:
Make an empty map for "sideEffects: false", which indicates all files in this module can be considered to not have side effects.
				.sideEffectsMap = make(map[string]bool)
				.ignoreIfUnusedData = &IgnoreIfUnusedData{
					IsSideEffectsArrayInJSON: false,
					Source:                   &,
					Range:                    .RangeOfString(),
				}
			}

The "sideEffects: []" format means all files in this module but not in the array can be considered to not have side effects.
			.sideEffectsMap = make(map[string]bool)
			.ignoreIfUnusedData = &IgnoreIfUnusedData{
				IsSideEffectsArrayInJSON: true,
				Source:                   &,
				Range:                    .RangeOfString(),
			}
			for ,  := range .Items {
				,  := .Data.(*js_ast.EString)
				if ! || .Value == nil {
					.log.AddWarning(&, .Loc,
						"Expected string in array for \"sideEffects\"")
					continue
				}

				 := .fs.Join(, js_lexer.UTF16ToString(.Value))
				,  := globToEscapedRegexp()
Wildcard patterns require more expensive matching
				if  {
					.sideEffectsRegexps = append(.sideEffectsRegexps, regexp.MustCompile())
					continue
				}
Normal strings can be matched with a map lookup
				.sideEffectsMap[] = true
			}

		default:
			.log.AddWarning(&, .Loc,
				"The value for \"sideEffects\" must be a boolean or an array")
		}
	}

	return 
}

func ( string) (string, bool) {
	 := strings.Builder{}
	.WriteByte('^')
	 := false

	for ,  := range  {
		switch  {
		case '\\', '^', '$', '.', '+', '|', '(', ')', '[', ']', '{', '}':
			.WriteByte('\\')
			.WriteRune()

		case '*':
			.WriteString(".*")
			 = true

		case '?':
			.WriteByte('.')
			 = true

		default:
			.WriteRune()
		}
	}

	.WriteByte('$')
	return .String(), 
}

Read the directory entries once to minimize locking
	 := .fs.Dir()
	,  := .fs.ReadDirectory()
	if  != nil {
		if  != syscall.ENOENT {
			.log.AddError(nil, logger.Loc{},
				fmt.Sprintf("Cannot read directory %q: %s",
					.PrettyPath(logger.Path{Text: , Namespace: "file"}), .Error()))
		}
		return "", false, nil
	}

	 := .fs.Base()
Try the plain path without any extensions
	if ,  := .Get();  != nil && .Kind(.fs) == fs.FileEntry {
		return , true, 
	}
Try the path with extensions
	for ,  := range  {
		if ,  := .Get( + );  != nil && .Kind(.fs) == fs.FileEntry {
			return  + , true, 
		}
	}
TypeScript-specific behavior: if the extension is ".js" or ".jsx", try replacing it with ".ts" or ".tsx". At the time of writing this specific behavior comes from the function "loadModuleFromFile()" in the file "moduleNameResolver.ts" in the TypeScript compiler source code. It contains this comment: If that didn't work, try stripping a ".js" or ".jsx" extension and replacing it with a TypeScript one; e.g. "./foo.js" can be matched by "./foo.ts" or "./foo.d.ts" We don't care about ".d.ts" files because we can't do anything with those, so we ignore that part of the behavior. See the discussion here for more historical context: https://github.com/microsoft/TypeScript/issues/4595
	if strings.HasSuffix(, ".js") || strings.HasSuffix(, ".jsx") {
Note that the official compiler code always tries ".ts" before ".tsx" even if the original extension was ".jsx".
		for ,  := range []string{".ts", ".tsx"} {
			if ,  := .Get([:] + );  != nil && .Kind(.fs) == fs.FileEntry {
				return [:len()-(len()-)] + , true, 
			}
		}
	}

	return "", false, nil
}
We want to minimize the number of times directory contents are listed. For this reason, the directory entries are computed by the caller and then passed down to us.
Try the "index" file with extensions
	for ,  := range .options.ExtensionOrder {
		 := "index" + 
		if ,  := .Get();  != nil && .Kind(.fs) == fs.FileEntry {
			return .fs.Join(, ), true, 
		}
	}

	return "", false, nil
}

func ( js_ast.Expr,  string) (js_ast.Expr, logger.Loc, bool) {
	if ,  := .Data.(*js_ast.EObject);  {
		for ,  := range .Properties {
			if ,  := .Key.Data.(*js_ast.EString);  && .Value != nil &&
				len(.Value) == len() && js_lexer.UTF16ToString(.Value) ==  {
				return *.Value, .Key.Loc, true
			}
		}
	}
	return js_ast.Expr{}, logger.Loc{}, false
}

func ( js_ast.Expr) (string, bool) {
	if ,  := .Data.(*js_ast.EString);  {
		return js_lexer.UTF16ToString(.Value), true
	}
	return "", false
}

func ( js_ast.Expr) (bool, bool) {
	if ,  := .Data.(*js_ast.EBoolean);  {
		return .Value, true
	}
	return false, false
}

Use a special import order for CSS "@import" imports
	 := .options.ExtensionOrder
	if  == ast.ImportAt {
		 = .atImportExtensionOrder
	}
Is this a file?
	, ,  := .loadAsFile(, )
	if  {
		return PathPair{Primary: logger.Path{Text: , Namespace: "file"}}, true, 
	}
Is this a directory?
	 := .dirInfoCached()
	if  == nil {
		return PathPair{}, false, nil
	}
Try using the main field(s) from "package.json"
	if .packageJSON != nil && .packageJSON.absMainFields != nil {
		 := .packageJSON.absMainFields
		 := .options.MainFields
		 := false
If the user has not explicitly specified a "main" field order, use a default one determined by the current platform target
		if  == nil {
			 = defaultMainFields[.options.Platform]
			 = true
		}

		for ,  := range  {
If the user did not manually configure a "main" field order, then use a special per-module automatic algorithm to decide whether to use "module" or "main" based on whether the package is imported using "import" or "require".
				if  &&  == "module" {
					,  := ["main"]
Some packages have a "module" field without a "main" field but still have an implicit "index.js" file. In that case, treat that as the value for "main".
					if ! && .absPathIndex != nil {
						 = *.absPathIndex
						 = true
					}

If both the "main" and "module" fields exist, use "main" if the path is for "require" and "module" if the path is for "import". If we're using "module", return enough information to be able to fall back to "main" later if something ended up using "require()" with this same path. The goal of this code is to avoid having both the "module" file and the "main" file in the bundle at the same time.
						if  != ast.ImportRequire {
This is the whole point of the path pair
								Primary:   logger.Path{Text: , Namespace: "file"},
								Secondary: logger.Path{Text: , Namespace: "file"},
							}, true, nil
						} else {
							return PathPair{Primary: logger.Path{Text: , Namespace: "file"}}, true, nil
						}
					}
				}

				return PathPair{Primary: logger.Path{Text: , Namespace: "file"}}, true, nil
			}
		}
	}
Return the "index.js" file
	if .absPathIndex != nil {
		return PathPair{Primary: logger.Path{Text: *.absPathIndex, Namespace: "file"}}, true, nil
	}

	return PathPair{}, false, nil
}
This closely follows the behavior of "tryLoadModuleUsingPaths()" in the official TypeScript compiler
func ( *resolver) ( *TSConfigJSON,  string,  ast.ImportKind) (PathPair, bool, *fs.DifferentCase) {
	 := .BaseURLForPaths
The explicit base URL should take precedence over the implicit base URL if present. This matters when a tsconfig.json file overrides "baseUrl" from another extended tsconfig.json file but doesn't override "paths".
	if .BaseURL != nil {
		 = *.BaseURL
	}
Check for exact matches first
	for ,  := range .Paths {
		if  ==  {
Load the original path relative to the "baseUrl" from tsconfig.json
				 := 
				if !.fs.IsAbs() {
					 = .fs.Join(, )
				}
				if , ,  := .loadAsFileOrDirectory(, );  {
					return , true, 
				}
			}
			return PathPair{}, false, nil
		}
	}

	type  struct {
		        string
		        string
		 []string
	}
Check for pattern matches next
	 := -1
	 := -1
	var  
	for ,  := range .Paths {
		if  := strings.IndexByte(, '*');  != -1 {
			,  := [:], [+1:]
Find the match with the longest prefix. If two matches have the same prefix length, pick the one with the longest suffix. This second edge case isn't handled by the TypeScript compiler, but we handle it because we want the output to always be deterministic and Go map iteration order is deliberately non-deterministic.
			if strings.HasPrefix(, ) && strings.HasSuffix(, ) && (len() >  ||
				(len() ==  && len() > )) {
				 = len()
				 = len()
				 = {
					:        ,
					:        ,
					: ,
				}
			}
		}
	}
If there is at least one match, only consider the one with the longest prefix. This matches the behavior of the TypeScript compiler.
	if  != -1 {
Swap out the "*" in the original path for whatever the "*" matched
			 := [len(.) : len()-len(.)]
			 = strings.Replace(, "*", , 1)
Load the original path relative to the "baseUrl" from tsconfig.json
			 := 
			if !.fs.IsAbs() {
				 = .fs.Join(, )
			}
			if , ,  := .loadAsFileOrDirectory(, );  {
				return , true, 
			}
		}
	}

	return PathPair{}, false, nil
}

First, check path overrides from the nearest enclosing TypeScript "tsconfig.json" file
Try path substitutions first
		if .tsConfigJSON.Paths != nil {
			if , ,  := .matchTSConfigPaths(.tsConfigJSON, , );  {
				return , true, 
			}
		}
Try looking up the path relative to the base URL
		if .tsConfigJSON.BaseURL != nil {
			 := .fs.Join(*.tsConfigJSON.BaseURL, )
			if , ,  := .loadAsFileOrDirectory(, );  {
				return , true, 
			}
		}
	}
Then check the global "NODE_PATH" environment variable
	for ,  := range .options.AbsNodePaths {
		 := .fs.Join(, )
		if , ,  := .loadAsFileOrDirectory(, );  {
			return , true, 
		}
	}
Then check for the package in any enclosing "node_modules" directories
Skip directories that are themselves called "node_modules", since we don't ever want to search for "node_modules/node_modules"
		if .hasNodeModules {
			 := .fs.Join(.absPath, "node_modules", )
Check the non-package "browser" map for the first time (1 out of 2)
			 := .dirInfoCached(.fs.Dir())
			if  != nil && .enclosingBrowserScope != nil {
				if  := .enclosingBrowserScope.packageJSON; .browserNonPackageMap != nil {
					if ,  := .browserNonPackageMap[];  {
						if  == nil {
							return PathPair{Primary: logger.Path{Text: , Namespace: "file", Flags: logger.PathDisabled}}, true, nil
						} else if , ,  := .resolveWithoutRemapping(.enclosingBrowserScope, *, );  {
							return , true, 
						}
					}
				}
			}

			if , ,  := .loadAsFileOrDirectory(, );  {
				return , true, 
			}
		}
Go to the parent directory, stopping at the file system root
		 = .parent
		if  == nil {
			break
		}
	}

	return PathPair{}, false, nil
}
Package paths are loaded from a "node_modules" directory. Non-package paths are relative or absolute paths.
func ( string) bool {
	return !strings.HasPrefix(, "/") && !strings.HasPrefix(, "./") &&
		!strings.HasPrefix(, "../") &&  != "." &&  != ".."
}

var BuiltInNodeModules = map[string]bool{
	"assert":         true,
	"async_hooks":    true,
	"buffer":         true,
	"child_process":  true,
	"cluster":        true,
	"console":        true,
	"constants":      true,
	"crypto":         true,
	"dgram":          true,
	"dns":            true,
	"domain":         true,
	"events":         true,
	"fs":             true,
	"http":           true,
	"http2":          true,
	"https":          true,
	"inspector":      true,
	"module":         true,
	"net":            true,
	"os":             true,
	"path":           true,
	"perf_hooks":     true,
	"process":        true,
	"punycode":       true,
	"querystring":    true,
	"readline":       true,
	"repl":           true,
	"stream":         true,
	"string_decoder": true,
	"sys":            true,
	"timers":         true,
	"tls":            true,
	"trace_events":   true,
	"tty":            true,
	"url":            true,
	"util":           true,
	"v8":             true,
	"vm":             true,
	"worker_threads": true,
	"zlib":           true,