Add support for copying files and folders.
This commit is contained in:
385
vendor/github.com/evanw/esbuild/internal/graph/graph.go
generated
vendored
Normal file
385
vendor/github.com/evanw/esbuild/internal/graph/graph.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
||||
package graph
|
||||
|
||||
// This graph represents the set of files that the linker operates on. Each
|
||||
// linker has a separate one of these graphs (there is one linker when code
|
||||
// splitting is on, but one linker per entry point when code splitting is off).
|
||||
//
|
||||
// The input data to the linker constructor must be considered immutable because
|
||||
// it's shared between linker invocations and is also stored in the cache for
|
||||
// incremental builds.
|
||||
//
|
||||
// The linker constructor makes a shallow clone of the input data and is careful
|
||||
// to pre-clone ahead of time the AST fields that it may modify. The Go language
|
||||
// doesn't have any type system features for immutability so this has to be
|
||||
// manually enforced. Please be careful.
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/evanw/esbuild/internal/ast"
|
||||
"github.com/evanw/esbuild/internal/helpers"
|
||||
"github.com/evanw/esbuild/internal/js_ast"
|
||||
"github.com/evanw/esbuild/internal/logger"
|
||||
"github.com/evanw/esbuild/internal/runtime"
|
||||
)
|
||||
|
||||
type entryPointKind uint8
|
||||
|
||||
const (
|
||||
entryPointNone entryPointKind = iota
|
||||
entryPointUserSpecified
|
||||
entryPointDynamicImport
|
||||
)
|
||||
|
||||
type LinkerFile struct {
|
||||
InputFile InputFile
|
||||
|
||||
// This holds all entry points that can reach this file. It will be used to
|
||||
// assign the parts in this file to a chunk.
|
||||
EntryBits helpers.BitSet
|
||||
|
||||
// This is lazily-allocated because it's only needed if there are warnings
|
||||
// logged, which should be relatively rare.
|
||||
lazyLineColumnTracker *logger.LineColumnTracker
|
||||
|
||||
// The minimum number of links in the module graph to get from an entry point
|
||||
// to this file
|
||||
DistanceFromEntryPoint uint32
|
||||
|
||||
// If "entryPointKind" is not "entryPointNone", this is the index of the
|
||||
// corresponding entry point chunk.
|
||||
EntryPointChunkIndex uint32
|
||||
|
||||
// This file is an entry point if and only if this is not "entryPointNone".
|
||||
// Note that dynamically-imported files are allowed to also be specified by
|
||||
// the user as top-level entry points, so some dynamically-imported files
|
||||
// may be "entryPointUserSpecified" instead of "entryPointDynamicImport".
|
||||
entryPointKind entryPointKind
|
||||
|
||||
// This is true if this file has been marked as live by the tree shaking
|
||||
// algorithm.
|
||||
IsLive bool
|
||||
}
|
||||
|
||||
func (f *LinkerFile) IsEntryPoint() bool {
|
||||
return f.entryPointKind != entryPointNone
|
||||
}
|
||||
|
||||
func (f *LinkerFile) IsUserSpecifiedEntryPoint() bool {
|
||||
return f.entryPointKind == entryPointUserSpecified
|
||||
}
|
||||
|
||||
// Note: This is not guarded by a mutex. Make sure this isn't called from a
|
||||
// parallel part of the code.
|
||||
func (f *LinkerFile) LineColumnTracker() *logger.LineColumnTracker {
|
||||
if f.lazyLineColumnTracker == nil {
|
||||
tracker := logger.MakeLineColumnTracker(&f.InputFile.Source)
|
||||
f.lazyLineColumnTracker = &tracker
|
||||
}
|
||||
return f.lazyLineColumnTracker
|
||||
}
|
||||
|
||||
type EntryPoint struct {
|
||||
// This may be an absolute path or a relative path. If absolute, it will
|
||||
// eventually be turned into a relative path by computing the path relative
|
||||
// to the "outbase" directory. Then this relative path will be joined onto
|
||||
// the "outdir" directory to form the final output path for this entry point.
|
||||
OutputPath string
|
||||
|
||||
// This is the source index of the entry point. This file must have a valid
|
||||
// entry point kind (i.e. not "none").
|
||||
SourceIndex uint32
|
||||
|
||||
// Manually specified output paths are ignored when computing the default
|
||||
// "outbase" directory, which is computed as the lowest common ancestor of
|
||||
// all automatically generated output paths.
|
||||
OutputPathWasAutoGenerated bool
|
||||
}
|
||||
|
||||
type LinkerGraph struct {
|
||||
Files []LinkerFile
|
||||
entryPoints []EntryPoint
|
||||
Symbols js_ast.SymbolMap
|
||||
|
||||
// We should avoid traversing all files in the bundle, because the linker
|
||||
// should be able to run a linking operation on a large bundle where only
|
||||
// a few files are needed (e.g. an incremental compilation scenario). This
|
||||
// holds all files that could possibly be reached through the entry points.
|
||||
// If you need to iterate over all files in the linking operation, iterate
|
||||
// over this array. This array is also sorted in a deterministic ordering
|
||||
// to help ensure deterministic builds (source indices are random).
|
||||
ReachableFiles []uint32
|
||||
|
||||
// This maps from unstable source index to stable reachable file index. This
|
||||
// is useful as a deterministic key for sorting if you need to sort something
|
||||
// containing a source index (such as "js_ast.Ref" symbol references).
|
||||
StableSourceIndices []uint32
|
||||
}
|
||||
|
||||
func CloneLinkerGraph(
|
||||
inputFiles []InputFile,
|
||||
reachableFiles []uint32,
|
||||
originalEntryPoints []EntryPoint,
|
||||
codeSplitting bool,
|
||||
) LinkerGraph {
|
||||
entryPoints := append([]EntryPoint{}, originalEntryPoints...)
|
||||
symbols := js_ast.NewSymbolMap(len(inputFiles))
|
||||
files := make([]LinkerFile, len(inputFiles))
|
||||
|
||||
// Mark all entry points so we don't add them again for import() expressions
|
||||
for _, entryPoint := range entryPoints {
|
||||
files[entryPoint.SourceIndex].entryPointKind = entryPointUserSpecified
|
||||
}
|
||||
|
||||
// Clone various things since we may mutate them later. Do this in parallel
|
||||
// for a speedup (around ~2x faster for this function in the three.js
|
||||
// benchmark on a 6-core laptop).
|
||||
var dynamicImportEntryPoints []uint32
|
||||
var dynamicImportEntryPointsMutex sync.Mutex
|
||||
waitGroup := sync.WaitGroup{}
|
||||
waitGroup.Add(len(reachableFiles))
|
||||
stableSourceIndices := make([]uint32, len(inputFiles))
|
||||
for stableIndex, sourceIndex := range reachableFiles {
|
||||
// Create a way to convert source indices to a stable ordering
|
||||
stableSourceIndices[sourceIndex] = uint32(stableIndex)
|
||||
|
||||
go func(sourceIndex uint32) {
|
||||
file := &files[sourceIndex]
|
||||
file.InputFile = inputFiles[sourceIndex]
|
||||
|
||||
switch repr := file.InputFile.Repr.(type) {
|
||||
case *JSRepr:
|
||||
// Clone the representation
|
||||
{
|
||||
clone := *repr
|
||||
repr = &clone
|
||||
file.InputFile.Repr = repr
|
||||
}
|
||||
|
||||
// Clone the symbol map
|
||||
fileSymbols := append([]js_ast.Symbol{}, repr.AST.Symbols...)
|
||||
symbols.SymbolsForSource[sourceIndex] = fileSymbols
|
||||
repr.AST.Symbols = nil
|
||||
|
||||
// Clone the parts
|
||||
repr.AST.Parts = append([]js_ast.Part{}, repr.AST.Parts...)
|
||||
for i := range repr.AST.Parts {
|
||||
part := &repr.AST.Parts[i]
|
||||
clone := make(map[js_ast.Ref]js_ast.SymbolUse, len(part.SymbolUses))
|
||||
for ref, uses := range part.SymbolUses {
|
||||
clone[ref] = uses
|
||||
}
|
||||
part.SymbolUses = clone
|
||||
part.Dependencies = append([]js_ast.Dependency{}, part.Dependencies...)
|
||||
}
|
||||
|
||||
// Clone the import records
|
||||
repr.AST.ImportRecords = append([]ast.ImportRecord{}, repr.AST.ImportRecords...)
|
||||
|
||||
// Add dynamic imports as additional entry points if code splitting is active
|
||||
if codeSplitting {
|
||||
for importRecordIndex := range repr.AST.ImportRecords {
|
||||
if record := &repr.AST.ImportRecords[importRecordIndex]; record.SourceIndex.IsValid() && record.Kind == ast.ImportDynamic {
|
||||
dynamicImportEntryPointsMutex.Lock()
|
||||
dynamicImportEntryPoints = append(dynamicImportEntryPoints, record.SourceIndex.GetIndex())
|
||||
dynamicImportEntryPointsMutex.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the import map
|
||||
namedImports := make(map[js_ast.Ref]js_ast.NamedImport, len(repr.AST.NamedImports))
|
||||
for k, v := range repr.AST.NamedImports {
|
||||
namedImports[k] = v
|
||||
}
|
||||
repr.AST.NamedImports = namedImports
|
||||
|
||||
// Clone the export map
|
||||
resolvedExports := make(map[string]ExportData)
|
||||
for alias, name := range repr.AST.NamedExports {
|
||||
resolvedExports[alias] = ExportData{
|
||||
Ref: name.Ref,
|
||||
SourceIndex: sourceIndex,
|
||||
NameLoc: name.AliasLoc,
|
||||
}
|
||||
}
|
||||
|
||||
// Clone the top-level scope so we can generate more variables
|
||||
{
|
||||
new := &js_ast.Scope{}
|
||||
*new = *repr.AST.ModuleScope
|
||||
new.Generated = append([]js_ast.Ref{}, new.Generated...)
|
||||
repr.AST.ModuleScope = new
|
||||
}
|
||||
|
||||
// Also associate some default metadata with the file
|
||||
repr.Meta.ResolvedExports = resolvedExports
|
||||
repr.Meta.IsProbablyTypeScriptType = make(map[js_ast.Ref]bool)
|
||||
repr.Meta.ImportsToBind = make(map[js_ast.Ref]ImportData)
|
||||
|
||||
case *CSSRepr:
|
||||
// Clone the representation
|
||||
{
|
||||
clone := *repr
|
||||
repr = &clone
|
||||
file.InputFile.Repr = repr
|
||||
}
|
||||
|
||||
// Clone the import records
|
||||
repr.AST.ImportRecords = append([]ast.ImportRecord{}, repr.AST.ImportRecords...)
|
||||
}
|
||||
|
||||
// All files start off as far as possible from an entry point
|
||||
file.DistanceFromEntryPoint = ^uint32(0)
|
||||
waitGroup.Done()
|
||||
}(sourceIndex)
|
||||
}
|
||||
waitGroup.Wait()
|
||||
|
||||
// Process dynamic entry points after merging control flow again
|
||||
stableEntryPoints := make([]int, 0, len(dynamicImportEntryPoints))
|
||||
for _, sourceIndex := range dynamicImportEntryPoints {
|
||||
if otherFile := &files[sourceIndex]; otherFile.entryPointKind == entryPointNone {
|
||||
stableEntryPoints = append(stableEntryPoints, int(stableSourceIndices[sourceIndex]))
|
||||
otherFile.entryPointKind = entryPointDynamicImport
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure to add dynamic entry points in a deterministic order
|
||||
sort.Ints(stableEntryPoints)
|
||||
for _, stableIndex := range stableEntryPoints {
|
||||
entryPoints = append(entryPoints, EntryPoint{SourceIndex: reachableFiles[stableIndex]})
|
||||
}
|
||||
|
||||
// Allocate the entry bit set now that the number of entry points is known
|
||||
bitCount := uint(len(entryPoints))
|
||||
for _, sourceIndex := range reachableFiles {
|
||||
files[sourceIndex].EntryBits = helpers.NewBitSet(bitCount)
|
||||
}
|
||||
|
||||
return LinkerGraph{
|
||||
Symbols: symbols,
|
||||
entryPoints: entryPoints,
|
||||
Files: files,
|
||||
ReachableFiles: reachableFiles,
|
||||
StableSourceIndices: stableSourceIndices,
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent packages that depend on us from adding or removing entry points
|
||||
func (g *LinkerGraph) EntryPoints() []EntryPoint {
|
||||
return g.entryPoints
|
||||
}
|
||||
|
||||
func (g *LinkerGraph) AddPartToFile(sourceIndex uint32, part js_ast.Part) uint32 {
|
||||
// Invariant: this map is never null
|
||||
if part.SymbolUses == nil {
|
||||
part.SymbolUses = make(map[js_ast.Ref]js_ast.SymbolUse)
|
||||
}
|
||||
|
||||
repr := g.Files[sourceIndex].InputFile.Repr.(*JSRepr)
|
||||
partIndex := uint32(len(repr.AST.Parts))
|
||||
repr.AST.Parts = append(repr.AST.Parts, part)
|
||||
|
||||
// Invariant: the parts for all top-level symbols can be found in the file-level map
|
||||
for _, declaredSymbol := range part.DeclaredSymbols {
|
||||
if declaredSymbol.IsTopLevel {
|
||||
// Check for an existing overlay
|
||||
partIndices, ok := repr.Meta.TopLevelSymbolToPartsOverlay[declaredSymbol.Ref]
|
||||
|
||||
// If missing, initialize using the original values from the parser
|
||||
if !ok {
|
||||
partIndices = append(partIndices, repr.AST.TopLevelSymbolToPartsFromParser[declaredSymbol.Ref]...)
|
||||
}
|
||||
|
||||
// Add this part to the overlay
|
||||
partIndices = append(partIndices, partIndex)
|
||||
if repr.Meta.TopLevelSymbolToPartsOverlay == nil {
|
||||
repr.Meta.TopLevelSymbolToPartsOverlay = make(map[js_ast.Ref][]uint32)
|
||||
}
|
||||
repr.Meta.TopLevelSymbolToPartsOverlay[declaredSymbol.Ref] = partIndices
|
||||
}
|
||||
}
|
||||
|
||||
return partIndex
|
||||
}
|
||||
|
||||
func (g *LinkerGraph) GenerateNewSymbol(sourceIndex uint32, kind js_ast.SymbolKind, originalName string) js_ast.Ref {
|
||||
sourceSymbols := &g.Symbols.SymbolsForSource[sourceIndex]
|
||||
|
||||
ref := js_ast.Ref{
|
||||
SourceIndex: sourceIndex,
|
||||
InnerIndex: uint32(len(*sourceSymbols)),
|
||||
}
|
||||
|
||||
*sourceSymbols = append(*sourceSymbols, js_ast.Symbol{
|
||||
Kind: kind,
|
||||
OriginalName: originalName,
|
||||
Link: js_ast.InvalidRef,
|
||||
})
|
||||
|
||||
generated := &g.Files[sourceIndex].InputFile.Repr.(*JSRepr).AST.ModuleScope.Generated
|
||||
*generated = append(*generated, ref)
|
||||
return ref
|
||||
}
|
||||
|
||||
func (g *LinkerGraph) GenerateSymbolImportAndUse(
|
||||
sourceIndex uint32,
|
||||
partIndex uint32,
|
||||
ref js_ast.Ref,
|
||||
useCount uint32,
|
||||
sourceIndexToImportFrom uint32,
|
||||
) {
|
||||
if useCount == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
repr := g.Files[sourceIndex].InputFile.Repr.(*JSRepr)
|
||||
part := &repr.AST.Parts[partIndex]
|
||||
|
||||
// Mark this symbol as used by this part
|
||||
use := part.SymbolUses[ref]
|
||||
use.CountEstimate += useCount
|
||||
part.SymbolUses[ref] = use
|
||||
|
||||
// Uphold invariants about the CommonJS "exports" and "module" symbols
|
||||
if ref == repr.AST.ExportsRef {
|
||||
repr.AST.UsesExportsRef = true
|
||||
}
|
||||
if ref == repr.AST.ModuleRef {
|
||||
repr.AST.UsesModuleRef = true
|
||||
}
|
||||
|
||||
// Track that this specific symbol was imported
|
||||
if sourceIndexToImportFrom != sourceIndex {
|
||||
repr.Meta.ImportsToBind[ref] = ImportData{
|
||||
SourceIndex: sourceIndexToImportFrom,
|
||||
Ref: ref,
|
||||
}
|
||||
}
|
||||
|
||||
// Pull in all parts that declare this symbol
|
||||
targetRepr := g.Files[sourceIndexToImportFrom].InputFile.Repr.(*JSRepr)
|
||||
for _, partIndex := range targetRepr.TopLevelSymbolToParts(ref) {
|
||||
part.Dependencies = append(part.Dependencies, js_ast.Dependency{
|
||||
SourceIndex: sourceIndexToImportFrom,
|
||||
PartIndex: partIndex,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *LinkerGraph) GenerateRuntimeSymbolImportAndUse(
|
||||
sourceIndex uint32,
|
||||
partIndex uint32,
|
||||
name string,
|
||||
useCount uint32,
|
||||
) {
|
||||
if useCount == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
runtimeRepr := g.Files[runtime.SourceIndex].InputFile.Repr.(*JSRepr)
|
||||
ref := runtimeRepr.AST.NamedExports[name].Ref
|
||||
g.GenerateSymbolImportAndUse(sourceIndex, partIndex, ref, useCount, runtime.SourceIndex)
|
||||
}
|
117
vendor/github.com/evanw/esbuild/internal/graph/input.go
generated
vendored
Normal file
117
vendor/github.com/evanw/esbuild/internal/graph/input.go
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
package graph
|
||||
|
||||
// The code in this file mainly represents data that passes from the scan phase
|
||||
// to the compile phase of the bundler. There is currently one exception: the
|
||||
// "meta" member of the JavaScript file representation. That could have been
|
||||
// stored separately but is stored together for convenience and to avoid an
|
||||
// extra level of indirection. Instead it's kept in a separate type to keep
|
||||
// things organized.
|
||||
|
||||
import (
|
||||
"github.com/evanw/esbuild/internal/ast"
|
||||
"github.com/evanw/esbuild/internal/config"
|
||||
"github.com/evanw/esbuild/internal/css_ast"
|
||||
"github.com/evanw/esbuild/internal/js_ast"
|
||||
"github.com/evanw/esbuild/internal/logger"
|
||||
"github.com/evanw/esbuild/internal/resolver"
|
||||
"github.com/evanw/esbuild/internal/sourcemap"
|
||||
)
|
||||
|
||||
type InputFile struct {
|
||||
Source logger.Source
|
||||
Repr InputFileRepr
|
||||
InputSourceMap *sourcemap.SourceMap
|
||||
|
||||
// If this file ends up being used in the bundle, these are additional files
|
||||
// that must be written to the output directory. It's used by the "file"
|
||||
// loader.
|
||||
AdditionalFiles []OutputFile
|
||||
UniqueKeyForFileLoader string
|
||||
|
||||
SideEffects SideEffects
|
||||
Loader config.Loader
|
||||
}
|
||||
|
||||
type OutputFile struct {
|
||||
AbsPath string
|
||||
Contents []byte
|
||||
|
||||
// If "AbsMetadataFile" is present, this will be filled out with information
|
||||
// about this file in JSON format. This is a partial JSON file that will be
|
||||
// fully assembled later.
|
||||
JSONMetadataChunk string
|
||||
|
||||
IsExecutable bool
|
||||
}
|
||||
|
||||
type SideEffects struct {
|
||||
// This is optional additional information for use in error messages
|
||||
Data *resolver.SideEffectsData
|
||||
|
||||
Kind SideEffectsKind
|
||||
}
|
||||
|
||||
type SideEffectsKind uint8
|
||||
|
||||
const (
|
||||
// The default value conservatively considers all files to have side effects.
|
||||
HasSideEffects SideEffectsKind = iota
|
||||
|
||||
// This file was listed as not having side effects by a "package.json"
|
||||
// file in one of our containing directories with a "sideEffects" field.
|
||||
NoSideEffects_PackageJSON
|
||||
|
||||
// This file is considered to have no side effects because the AST was empty
|
||||
// after parsing finished. This should be the case for ".d.ts" files.
|
||||
NoSideEffects_EmptyAST
|
||||
|
||||
// This file was loaded using a data-oriented loader (e.g. "text") that is
|
||||
// known to not have side effects.
|
||||
NoSideEffects_PureData
|
||||
|
||||
// Same as above but it came from a plugin. We don't want to warn about
|
||||
// unused imports to these files since running the plugin is a side effect.
|
||||
// Removing the import would not call the plugin which is observable.
|
||||
NoSideEffects_PureData_FromPlugin
|
||||
)
|
||||
|
||||
type InputFileRepr interface {
|
||||
ImportRecords() *[]ast.ImportRecord
|
||||
}
|
||||
|
||||
type JSRepr struct {
|
||||
AST js_ast.AST
|
||||
Meta JSReprMeta
|
||||
|
||||
// If present, this is the CSS file that this JavaScript stub corresponds to.
|
||||
// A JavaScript stub is automatically generated for a CSS file when it's
|
||||
// imported from a JavaScript file.
|
||||
CSSSourceIndex ast.Index32
|
||||
}
|
||||
|
||||
func (repr *JSRepr) ImportRecords() *[]ast.ImportRecord {
|
||||
return &repr.AST.ImportRecords
|
||||
}
|
||||
|
||||
func (repr *JSRepr) TopLevelSymbolToParts(ref js_ast.Ref) []uint32 {
|
||||
// Overlay the mutable map from the linker
|
||||
if parts, ok := repr.Meta.TopLevelSymbolToPartsOverlay[ref]; ok {
|
||||
return parts
|
||||
}
|
||||
|
||||
// Fall back to the immutable map from the parser
|
||||
return repr.AST.TopLevelSymbolToPartsFromParser[ref]
|
||||
}
|
||||
|
||||
type CSSRepr struct {
|
||||
AST css_ast.AST
|
||||
|
||||
// If present, this is the JavaScript stub corresponding to this CSS file.
|
||||
// A JavaScript stub is automatically generated for a CSS file when it's
|
||||
// imported from a JavaScript file.
|
||||
JSSourceIndex ast.Index32
|
||||
}
|
||||
|
||||
func (repr *CSSRepr) ImportRecords() *[]ast.ImportRecord {
|
||||
return &repr.AST.ImportRecords
|
||||
}
|
203
vendor/github.com/evanw/esbuild/internal/graph/meta.go
generated
vendored
Normal file
203
vendor/github.com/evanw/esbuild/internal/graph/meta.go
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
package graph
|
||||
|
||||
// The code in this file represents data that is required by the compile phase
|
||||
// of the bundler but that is not required by the scan phase.
|
||||
|
||||
import (
|
||||
"github.com/evanw/esbuild/internal/ast"
|
||||
"github.com/evanw/esbuild/internal/js_ast"
|
||||
"github.com/evanw/esbuild/internal/logger"
|
||||
)
|
||||
|
||||
type WrapKind uint8
|
||||
|
||||
const (
|
||||
WrapNone WrapKind = iota
|
||||
|
||||
// The module will be bundled CommonJS-style like this:
|
||||
//
|
||||
// // foo.ts
|
||||
// let require_foo = __commonJS((exports, module) => {
|
||||
// exports.foo = 123;
|
||||
// });
|
||||
//
|
||||
// // bar.ts
|
||||
// let foo = flag ? require_foo() : null;
|
||||
//
|
||||
WrapCJS
|
||||
|
||||
// The module will be bundled ESM-style like this:
|
||||
//
|
||||
// // foo.ts
|
||||
// var foo, foo_exports = {};
|
||||
// __export(foo_exports, {
|
||||
// foo: () => foo
|
||||
// });
|
||||
// let init_foo = __esm(() => {
|
||||
// foo = 123;
|
||||
// });
|
||||
//
|
||||
// // bar.ts
|
||||
// let foo = flag ? (init_foo(), __toCommonJS(foo_exports)) : null;
|
||||
//
|
||||
WrapESM
|
||||
)
|
||||
|
||||
// This contains linker-specific metadata corresponding to a "file" struct
|
||||
// from the initial scan phase of the bundler. It's separated out because it's
|
||||
// conceptually only used for a single linking operation and because multiple
|
||||
// linking operations may be happening in parallel with different metadata for
|
||||
// the same file.
|
||||
type JSReprMeta struct {
|
||||
// This is only for TypeScript files. If an import symbol is in this map, it
|
||||
// means the import couldn't be found and doesn't actually exist. This is not
|
||||
// an error in TypeScript because the import is probably just a type.
|
||||
//
|
||||
// Normally we remove all unused imports for TypeScript files during parsing,
|
||||
// which automatically removes type-only imports. But there are certain re-
|
||||
// export situations where it's impossible to tell if an import is a type or
|
||||
// not:
|
||||
//
|
||||
// import {typeOrNotTypeWhoKnows} from 'path';
|
||||
// export {typeOrNotTypeWhoKnows};
|
||||
//
|
||||
// Really people should be using the TypeScript "isolatedModules" flag with
|
||||
// bundlers like this one that compile TypeScript files independently without
|
||||
// type checking. That causes the TypeScript type checker to emit the error
|
||||
// "Re-exporting a type when the '--isolatedModules' flag is provided requires
|
||||
// using 'export type'." But we try to be robust to such code anyway.
|
||||
IsProbablyTypeScriptType map[js_ast.Ref]bool
|
||||
|
||||
// Imports are matched with exports in a separate pass from when the matched
|
||||
// exports are actually bound to the imports. Here "binding" means adding non-
|
||||
// local dependencies on the parts in the exporting file that declare the
|
||||
// exported symbol to all parts in the importing file that use the imported
|
||||
// symbol.
|
||||
//
|
||||
// This must be a separate pass because of the "probably TypeScript type"
|
||||
// check above. We can't generate the part for the export namespace until
|
||||
// we've matched imports with exports because the generated code must omit
|
||||
// type-only imports in the export namespace code. And we can't bind exports
|
||||
// to imports until the part for the export namespace is generated since that
|
||||
// part needs to participate in the binding.
|
||||
//
|
||||
// This array holds the deferred imports to bind so the pass can be split
|
||||
// into two separate passes.
|
||||
ImportsToBind map[js_ast.Ref]ImportData
|
||||
|
||||
// This includes both named exports and re-exports.
|
||||
//
|
||||
// Named exports come from explicit export statements in the original file,
|
||||
// and are copied from the "NamedExports" field in the AST.
|
||||
//
|
||||
// Re-exports come from other files and are the result of resolving export
|
||||
// star statements (i.e. "export * from 'foo'").
|
||||
ResolvedExports map[string]ExportData
|
||||
ResolvedExportStar *ExportData
|
||||
|
||||
// Never iterate over "resolvedExports" directly. Instead, iterate over this
|
||||
// array. Some exports in that map aren't meant to end up in generated code.
|
||||
// This array excludes these exports and is also sorted, which avoids non-
|
||||
// determinism due to random map iteration order.
|
||||
SortedAndFilteredExportAliases []string
|
||||
|
||||
// If this is an entry point, this array holds a reference to one free
|
||||
// temporary symbol for each entry in "sortedAndFilteredExportAliases".
|
||||
// These may be needed to store copies of CommonJS re-exports in ESM.
|
||||
CJSExportCopies []js_ast.Ref
|
||||
|
||||
// This is merged on top of the corresponding map from the parser in the AST.
|
||||
// You should call "TopLevelSymbolToParts" to access this instead of accessing
|
||||
// it directly.
|
||||
TopLevelSymbolToPartsOverlay map[js_ast.Ref][]uint32
|
||||
|
||||
// The index of the automatically-generated part used to represent the
|
||||
// CommonJS or ESM wrapper. This part is empty and is only useful for tree
|
||||
// shaking and code splitting. The wrapper can't be inserted into the part
|
||||
// because the wrapper contains other parts, which can't be represented by
|
||||
// the current part system. Only wrapped files have one of these.
|
||||
WrapperPartIndex ast.Index32
|
||||
|
||||
// The index of the automatically-generated part used to handle entry point
|
||||
// specific stuff. If a certain part is needed by the entry point, it's added
|
||||
// as a dependency of this part. This is important for parts that are marked
|
||||
// as removable when unused and that are not used by anything else. Only
|
||||
// entry point files have one of these.
|
||||
EntryPointPartIndex ast.Index32
|
||||
|
||||
// This is true if this file is affected by top-level await, either by having
|
||||
// a top-level await inside this file or by having an import/export statement
|
||||
// that transitively imports such a file. It is forbidden to call "require()"
|
||||
// on these files since they are evaluated asynchronously.
|
||||
IsAsyncOrHasAsyncDependency bool
|
||||
|
||||
Wrap WrapKind
|
||||
|
||||
// If true, we need to insert "var exports = {};". This is the case for ESM
|
||||
// files when the import namespace is captured via "import * as" and also
|
||||
// when they are the target of a "require()" call.
|
||||
NeedsExportsVariable bool
|
||||
|
||||
// If true, the "__export(exports, { ... })" call will be force-included even
|
||||
// if there are no parts that reference "exports". Otherwise this call will
|
||||
// be removed due to the tree shaking pass. This is used when for entry point
|
||||
// files when code related to the current output format needs to reference
|
||||
// the "exports" variable.
|
||||
ForceIncludeExportsForEntryPoint bool
|
||||
|
||||
// This is set when we need to pull in the "__export" symbol in to the part
|
||||
// at "nsExportPartIndex". This can't be done in "createExportsForFile"
|
||||
// because of concurrent map hazards. Instead, it must be done later.
|
||||
NeedsExportSymbolFromRuntime bool
|
||||
|
||||
// Wrapped files must also ensure that their dependencies are wrapped. This
|
||||
// flag is used during the traversal that enforces this invariant, and is used
|
||||
// to detect when the fixed point has been reached.
|
||||
DidWrapDependencies bool
|
||||
}
|
||||
|
||||
type ImportData struct {
|
||||
// This is an array of intermediate statements that re-exported this symbol
|
||||
// in a chain before getting to the final symbol. This can be done either with
|
||||
// "export * from" or "export {} from". If this is done with "export * from"
|
||||
// then this may not be the result of a single chain but may instead form
|
||||
// a diamond shape if this same symbol was re-exported multiple times from
|
||||
// different files.
|
||||
ReExports []js_ast.Dependency
|
||||
|
||||
NameLoc logger.Loc // Optional, goes with sourceIndex, ignore if zero
|
||||
Ref js_ast.Ref
|
||||
SourceIndex uint32
|
||||
}
|
||||
|
||||
type ExportData struct {
|
||||
Ref js_ast.Ref
|
||||
|
||||
// Export star resolution happens first before import resolution. That means
|
||||
// it cannot yet determine if duplicate names from export star resolution are
|
||||
// ambiguous (point to different symbols) or not (point to the same symbol).
|
||||
// This issue can happen in the following scenario:
|
||||
//
|
||||
// // entry.js
|
||||
// export * from './a'
|
||||
// export * from './b'
|
||||
//
|
||||
// // a.js
|
||||
// export * from './c'
|
||||
//
|
||||
// // b.js
|
||||
// export {x} from './c'
|
||||
//
|
||||
// // c.js
|
||||
// export let x = 1, y = 2
|
||||
//
|
||||
// In this case "entry.js" should have two exports "x" and "y", neither of
|
||||
// which are ambiguous. To handle this case, ambiguity resolution must be
|
||||
// deferred until import resolution time. That is done using this array.
|
||||
PotentiallyAmbiguousExportStarRefs []ImportData
|
||||
|
||||
// This is the file that the named export above came from. This will be
|
||||
// different from the file that contains this object if this is a re-export.
|
||||
NameLoc logger.Loc // Optional, goes with sourceIndex, ignore if zero
|
||||
SourceIndex uint32
|
||||
}
|
Reference in New Issue
Block a user