github.com/evanw/esbuild@v0.21.4/internal/graph/meta.go (about)

     1  package graph
     2  
     3  // The code in this file represents data that is required by the compile phase
     4  // of the bundler but that is not required by the scan phase.
     5  
     6  import (
     7  	"github.com/evanw/esbuild/internal/ast"
     8  	"github.com/evanw/esbuild/internal/helpers"
     9  	"github.com/evanw/esbuild/internal/js_ast"
    10  	"github.com/evanw/esbuild/internal/logger"
    11  )
    12  
    13  type WrapKind uint8
    14  
    15  const (
    16  	WrapNone WrapKind = iota
    17  
    18  	// The module will be bundled CommonJS-style like this:
    19  	//
    20  	//   // foo.ts
    21  	//   let require_foo = __commonJS((exports, module) => {
    22  	//     exports.foo = 123;
    23  	//   });
    24  	//
    25  	//   // bar.ts
    26  	//   let foo = flag ? require_foo() : null;
    27  	//
    28  	WrapCJS
    29  
    30  	// The module will be bundled ESM-style like this:
    31  	//
    32  	//   // foo.ts
    33  	//   var foo, foo_exports = {};
    34  	//   __export(foo_exports, {
    35  	//     foo: () => foo
    36  	//   });
    37  	//   let init_foo = __esm(() => {
    38  	//     foo = 123;
    39  	//   });
    40  	//
    41  	//   // bar.ts
    42  	//   let foo = flag ? (init_foo(), __toCommonJS(foo_exports)) : null;
    43  	//
    44  	WrapESM
    45  )
    46  
    47  // This contains linker-specific metadata corresponding to a "file" struct
    48  // from the initial scan phase of the bundler. It's separated out because it's
    49  // conceptually only used for a single linking operation and because multiple
    50  // linking operations may be happening in parallel with different metadata for
    51  // the same file.
    52  type JSReprMeta struct {
    53  	// This is only for TypeScript files. If an import symbol is in this map, it
    54  	// means the import couldn't be found and doesn't actually exist. This is not
    55  	// an error in TypeScript because the import is probably just a type.
    56  	//
    57  	// Normally we remove all unused imports for TypeScript files during parsing,
    58  	// which automatically removes type-only imports. But there are certain re-
    59  	// export situations where it's impossible to tell if an import is a type or
    60  	// not:
    61  	//
    62  	//   import {typeOrNotTypeWhoKnows} from 'path';
    63  	//   export {typeOrNotTypeWhoKnows};
    64  	//
    65  	// Really people should be using the TypeScript "isolatedModules" flag with
    66  	// bundlers like this one that compile TypeScript files independently without
    67  	// type checking. That causes the TypeScript type checker to emit the error
    68  	// "Re-exporting a type when the '--isolatedModules' flag is provided requires
    69  	// using 'export type'." But we try to be robust to such code anyway.
    70  	IsProbablyTypeScriptType map[ast.Ref]bool
    71  
    72  	// Imports are matched with exports in a separate pass from when the matched
    73  	// exports are actually bound to the imports. Here "binding" means adding non-
    74  	// local dependencies on the parts in the exporting file that declare the
    75  	// exported symbol to all parts in the importing file that use the imported
    76  	// symbol.
    77  	//
    78  	// This must be a separate pass because of the "probably TypeScript type"
    79  	// check above. We can't generate the part for the export namespace until
    80  	// we've matched imports with exports because the generated code must omit
    81  	// type-only imports in the export namespace code. And we can't bind exports
    82  	// to imports until the part for the export namespace is generated since that
    83  	// part needs to participate in the binding.
    84  	//
    85  	// This array holds the deferred imports to bind so the pass can be split
    86  	// into two separate passes.
    87  	ImportsToBind map[ast.Ref]ImportData
    88  
    89  	// This includes both named exports and re-exports.
    90  	//
    91  	// Named exports come from explicit export statements in the original file,
    92  	// and are copied from the "NamedExports" field in the AST.
    93  	//
    94  	// Re-exports come from other files and are the result of resolving export
    95  	// star statements (i.e. "export * from 'foo'").
    96  	ResolvedExports     map[string]ExportData
    97  	ResolvedExportStar  *ExportData
    98  	ResolvedExportTypos *helpers.TypoDetector
    99  
   100  	// Never iterate over "resolvedExports" directly. Instead, iterate over this
   101  	// array. Some exports in that map aren't meant to end up in generated code.
   102  	// This array excludes these exports and is also sorted, which avoids non-
   103  	// determinism due to random map iteration order.
   104  	SortedAndFilteredExportAliases []string
   105  
   106  	// This is merged on top of the corresponding map from the parser in the AST.
   107  	// You should call "TopLevelSymbolToParts" to access this instead of accessing
   108  	// it directly.
   109  	TopLevelSymbolToPartsOverlay map[ast.Ref][]uint32
   110  
   111  	// If this is an entry point, this array holds a reference to one free
   112  	// temporary symbol for each entry in "sortedAndFilteredExportAliases".
   113  	// These may be needed to store copies of CommonJS re-exports in ESM.
   114  	CJSExportCopies []ast.Ref
   115  
   116  	// The index of the automatically-generated part used to represent the
   117  	// CommonJS or ESM wrapper. This part is empty and is only useful for tree
   118  	// shaking and code splitting. The wrapper can't be inserted into the part
   119  	// because the wrapper contains other parts, which can't be represented by
   120  	// the current part system. Only wrapped files have one of these.
   121  	WrapperPartIndex ast.Index32
   122  
   123  	// The index of the automatically-generated part used to handle entry point
   124  	// specific stuff. If a certain part is needed by the entry point, it's added
   125  	// as a dependency of this part. This is important for parts that are marked
   126  	// as removable when unused and that are not used by anything else. Only
   127  	// entry point files have one of these.
   128  	EntryPointPartIndex ast.Index32
   129  
   130  	// This is true if this file is affected by top-level await, either by having
   131  	// a top-level await inside this file or by having an import/export statement
   132  	// that transitively imports such a file. It is forbidden to call "require()"
   133  	// on these files since they are evaluated asynchronously.
   134  	IsAsyncOrHasAsyncDependency bool
   135  
   136  	Wrap WrapKind
   137  
   138  	// If true, we need to insert "var exports = {};". This is the case for ESM
   139  	// files when the import namespace is captured via "import * as" and also
   140  	// when they are the target of a "require()" call.
   141  	NeedsExportsVariable bool
   142  
   143  	// If true, the "__export(exports, { ... })" call will be force-included even
   144  	// if there are no parts that reference "exports". Otherwise this call will
   145  	// be removed due to the tree shaking pass. This is used when for entry point
   146  	// files when code related to the current output format needs to reference
   147  	// the "exports" variable.
   148  	ForceIncludeExportsForEntryPoint bool
   149  
   150  	// This is set when we need to pull in the "__export" symbol in to the part
   151  	// at "nsExportPartIndex". This can't be done in "createExportsForFile"
   152  	// because of concurrent map hazards. Instead, it must be done later.
   153  	NeedsExportSymbolFromRuntime bool
   154  
   155  	// Wrapped files must also ensure that their dependencies are wrapped. This
   156  	// flag is used during the traversal that enforces this invariant, and is used
   157  	// to detect when the fixed point has been reached.
   158  	DidWrapDependencies bool
   159  }
   160  
   161  type ImportData struct {
   162  	// This is an array of intermediate statements that re-exported this symbol
   163  	// in a chain before getting to the final symbol. This can be done either with
   164  	// "export * from" or "export {} from". If this is done with "export * from"
   165  	// then this may not be the result of a single chain but may instead form
   166  	// a diamond shape if this same symbol was re-exported multiple times from
   167  	// different files.
   168  	ReExports []js_ast.Dependency
   169  
   170  	NameLoc     logger.Loc // Optional, goes with sourceIndex, ignore if zero
   171  	Ref         ast.Ref
   172  	SourceIndex uint32
   173  }
   174  
   175  type ExportData struct {
   176  	// Export star resolution happens first before import resolution. That means
   177  	// it cannot yet determine if duplicate names from export star resolution are
   178  	// ambiguous (point to different symbols) or not (point to the same symbol).
   179  	// This issue can happen in the following scenario:
   180  	//
   181  	//   // entry.js
   182  	//   export * from './a'
   183  	//   export * from './b'
   184  	//
   185  	//   // a.js
   186  	//   export * from './c'
   187  	//
   188  	//   // b.js
   189  	//   export {x} from './c'
   190  	//
   191  	//   // c.js
   192  	//   export let x = 1, y = 2
   193  	//
   194  	// In this case "entry.js" should have two exports "x" and "y", neither of
   195  	// which are ambiguous. To handle this case, ambiguity resolution must be
   196  	// deferred until import resolution time. That is done using this array.
   197  	PotentiallyAmbiguousExportStarRefs []ImportData
   198  
   199  	Ref ast.Ref
   200  
   201  	// This is the file that the named export above came from. This will be
   202  	// different from the file that contains this object if this is a re-export.
   203  	NameLoc     logger.Loc // Optional, goes with sourceIndex, ignore if zero
   204  	SourceIndex uint32
   205  }