/
meta.go
201 lines (177 loc) · 8.09 KB
/
meta.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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 = {};
// __exports(foo_exports, {
// foo: () => foo
// });
// let init_foo = __esm(() => {
// foo = 123;
// });
//
// // bar.ts
// let foo = flag ? (init_foo(), 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 the index to the automatically-generated part containing code that
// calls "__export(exports, { ... getters ... })". This is used to generate
// getters on an exports object for ES6 export statements, and is both for
// ES6 star imports and CommonJS-style modules. All files have one of these,
// although it may contain no statements if there is nothing to export.
NSExportPartIndex 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, 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
NeedsMarkAsModuleSymbolFromRuntime 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
}