@tanstack/start-plugin-core 1.167.35 → 1.169.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/import-protection/adapterUtils.d.ts +27 -0
- package/dist/esm/import-protection/adapterUtils.js +31 -0
- package/dist/esm/import-protection/adapterUtils.js.map +1 -0
- package/dist/esm/import-protection/analysis.d.ts +36 -0
- package/dist/esm/import-protection/analysis.js +407 -0
- package/dist/esm/import-protection/analysis.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/ast.js +1 -1
- package/dist/esm/import-protection/ast.js.map +1 -0
- package/dist/esm/import-protection/constants.d.ts +11 -0
- package/dist/esm/{import-protection-plugin → import-protection}/constants.js +7 -2
- package/dist/esm/import-protection/constants.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/defaults.js +1 -1
- package/dist/esm/import-protection/defaults.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.js +2 -2
- package/dist/esm/import-protection/extensionlessAbsoluteIdResolver.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/matchers.js +1 -1
- package/dist/esm/import-protection/matchers.js.map +1 -0
- package/dist/esm/{import-protection-plugin/rewriteDeniedImports.d.ts → import-protection/rewrite.d.ts} +0 -4
- package/dist/esm/import-protection/rewrite.js +121 -0
- package/dist/esm/import-protection/rewrite.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.d.ts +32 -3
- package/dist/esm/{import-protection-plugin → import-protection}/sourceLocation.js +65 -10
- package/dist/esm/import-protection/sourceLocation.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/trace.d.ts +0 -1
- package/dist/esm/{import-protection-plugin → import-protection}/trace.js +1 -1
- package/dist/esm/import-protection/trace.js.map +1 -0
- package/dist/esm/{import-protection-plugin → import-protection}/utils.d.ts +18 -1
- package/dist/esm/{import-protection-plugin → import-protection}/utils.js +13 -20
- package/dist/esm/import-protection/utils.js.map +1 -0
- package/dist/esm/import-protection/virtualModules.d.ts +25 -0
- package/dist/esm/{import-protection-plugin → import-protection}/virtualModules.js +5 -117
- package/dist/esm/import-protection/virtualModules.js.map +1 -0
- package/dist/esm/index.d.ts +1 -5
- package/dist/esm/index.js +2 -4
- package/dist/esm/post-build.d.ts +9 -0
- package/dist/esm/post-build.js +37 -0
- package/dist/esm/post-build.js.map +1 -0
- package/dist/esm/prerender.d.ts +11 -0
- package/dist/esm/prerender.js +159 -0
- package/dist/esm/prerender.js.map +1 -0
- package/dist/esm/rsbuild/dev-server.d.ts +21 -0
- package/dist/esm/rsbuild/dev-server.js +76 -0
- package/dist/esm/rsbuild/dev-server.js.map +1 -0
- package/dist/esm/rsbuild/import-protection.d.ts +10 -0
- package/dist/esm/rsbuild/import-protection.js +775 -0
- package/dist/esm/rsbuild/import-protection.js.map +1 -0
- package/dist/esm/rsbuild/index.d.ts +4 -0
- package/dist/esm/rsbuild/index.js +3 -0
- package/dist/esm/rsbuild/normalized-client-build.d.ts +18 -0
- package/dist/esm/rsbuild/normalized-client-build.js +207 -0
- package/dist/esm/rsbuild/normalized-client-build.js.map +1 -0
- package/dist/esm/rsbuild/planning.d.ts +52 -0
- package/dist/esm/rsbuild/planning.js +108 -0
- package/dist/esm/rsbuild/planning.js.map +1 -0
- package/dist/esm/rsbuild/plugin.d.ts +4 -0
- package/dist/esm/rsbuild/plugin.js +344 -0
- package/dist/esm/rsbuild/plugin.js.map +1 -0
- package/dist/esm/rsbuild/post-build.d.ts +6 -0
- package/dist/esm/rsbuild/post-build.js +57 -0
- package/dist/esm/rsbuild/post-build.js.map +1 -0
- package/dist/esm/rsbuild/schema.d.ts +3372 -0
- package/dist/esm/rsbuild/schema.js +12 -0
- package/dist/esm/rsbuild/schema.js.map +1 -0
- package/dist/esm/rsbuild/start-compiler-host.d.ts +20 -0
- package/dist/esm/rsbuild/start-compiler-host.js +150 -0
- package/dist/esm/rsbuild/start-compiler-host.js.map +1 -0
- package/dist/esm/rsbuild/start-router-plugin.d.ts +18 -0
- package/dist/esm/rsbuild/start-router-plugin.js +63 -0
- package/dist/esm/rsbuild/start-router-plugin.js.map +1 -0
- package/dist/esm/rsbuild/swc-rsc.d.ts +14 -0
- package/dist/esm/rsbuild/swc-rsc.js +93 -0
- package/dist/esm/rsbuild/swc-rsc.js.map +1 -0
- package/dist/esm/rsbuild/types.d.ts +17 -0
- package/dist/esm/rsbuild/types.js +0 -0
- package/dist/esm/rsbuild/virtual-modules.d.ts +53 -0
- package/dist/esm/rsbuild/virtual-modules.js +287 -0
- package/dist/esm/rsbuild/virtual-modules.js.map +1 -0
- package/dist/esm/schema.d.ts +43 -43
- package/dist/esm/start-compiler/compiler.d.ts +1 -1
- package/dist/esm/start-compiler/compiler.js +80 -9
- package/dist/esm/start-compiler/compiler.js.map +1 -1
- package/dist/esm/start-compiler/handleCreateServerFn.js +9 -0
- package/dist/esm/start-compiler/handleCreateServerFn.js.map +1 -1
- package/dist/esm/start-compiler/host.js +5 -1
- package/dist/esm/start-compiler/host.js.map +1 -1
- package/dist/esm/start-compiler/types.d.ts +1 -0
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.js +10 -1
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.js +41 -92
- package/dist/esm/vite/import-protection-plugin/plugin.js.map +1 -0
- package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/types.d.ts +5 -5
- package/dist/esm/vite/import-protection-plugin/virtualModules.d.ts +8 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js +49 -0
- package/dist/esm/vite/import-protection-plugin/virtualModules.js.map +1 -0
- package/dist/esm/vite/index.d.ts +5 -0
- package/dist/esm/vite/index.js +4 -0
- package/dist/esm/vite/plugin.js +1 -1
- package/dist/esm/vite/plugin.js.map +1 -1
- package/dist/esm/vite/post-server-build.js +14 -32
- package/dist/esm/vite/post-server-build.js.map +1 -1
- package/dist/esm/vite/prerender.d.ts +2 -2
- package/dist/esm/vite/prerender.js +17 -147
- package/dist/esm/vite/prerender.js.map +1 -1
- package/dist/esm/vite/schema.d.ts +23 -23
- package/dist/esm/vite/start-compiler-plugin/hot-update.d.ts +2 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js +16 -0
- package/dist/esm/vite/start-compiler-plugin/hot-update.js.map +1 -0
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js +9 -4
- package/dist/esm/vite/start-compiler-plugin/module-specifier.js.map +1 -1
- package/dist/esm/vite/start-compiler-plugin/plugin.js +86 -13
- package/dist/esm/vite/start-compiler-plugin/plugin.js.map +1 -1
- package/package.json +32 -4
- package/src/import-protection/INTERNALS.md +266 -0
- package/src/import-protection/adapterUtils.ts +94 -0
- package/src/import-protection/analysis.ts +853 -0
- package/src/{import-protection-plugin → import-protection}/constants.ts +7 -0
- package/src/import-protection/rewrite.ts +229 -0
- package/src/{import-protection-plugin → import-protection}/sourceLocation.ts +125 -9
- package/src/{import-protection-plugin → import-protection}/trace.ts +0 -1
- package/src/{import-protection-plugin → import-protection}/utils.ts +36 -21
- package/src/{import-protection-plugin → import-protection}/virtualModules.ts +30 -177
- package/src/index.ts +1 -8
- package/src/post-build.ts +64 -0
- package/src/prerender.ts +292 -0
- package/src/rsbuild/INTERNALS-import-protection.md +169 -0
- package/src/rsbuild/dev-server.ts +129 -0
- package/src/rsbuild/import-protection.ts +1599 -0
- package/src/rsbuild/index.ts +4 -0
- package/src/rsbuild/normalized-client-build.ts +346 -0
- package/src/rsbuild/planning.ts +234 -0
- package/src/rsbuild/plugin.ts +754 -0
- package/src/rsbuild/post-build.ts +96 -0
- package/src/rsbuild/schema.ts +31 -0
- package/src/rsbuild/start-compiler-host.ts +250 -0
- package/src/rsbuild/start-router-plugin.ts +86 -0
- package/src/rsbuild/swc-rsc.ts +166 -0
- package/src/rsbuild/types.ts +20 -0
- package/src/rsbuild/virtual-modules.ts +565 -0
- package/src/start-compiler/compiler.ts +153 -19
- package/src/start-compiler/handleCreateServerFn.ts +18 -0
- package/src/start-compiler/types.ts +1 -0
- package/src/utils.ts +14 -0
- package/src/vite/import-protection-plugin/INTERNALS.md +187 -0
- package/src/{import-protection-plugin → vite/import-protection-plugin}/plugin.ts +73 -158
- package/src/{import-protection-plugin → vite/import-protection-plugin}/types.ts +5 -5
- package/src/vite/import-protection-plugin/virtualModules.ts +122 -0
- package/src/vite/index.ts +8 -0
- package/src/vite/plugin.ts +1 -1
- package/src/vite/post-server-build.ts +14 -57
- package/src/vite/prerender.ts +19 -260
- package/src/vite/start-compiler-plugin/hot-update.ts +24 -0
- package/src/vite/start-compiler-plugin/module-specifier.ts +15 -5
- package/src/vite/start-compiler-plugin/plugin.ts +193 -18
- package/dist/esm/import-protection-plugin/ast.js.map +0 -1
- package/dist/esm/import-protection-plugin/constants.d.ts +0 -6
- package/dist/esm/import-protection-plugin/constants.js.map +0 -1
- package/dist/esm/import-protection-plugin/defaults.js.map +0 -1
- package/dist/esm/import-protection-plugin/extensionlessAbsoluteIdResolver.js.map +0 -1
- package/dist/esm/import-protection-plugin/matchers.js.map +0 -1
- package/dist/esm/import-protection-plugin/plugin.js.map +0 -1
- package/dist/esm/import-protection-plugin/postCompileUsage.d.ts +0 -13
- package/dist/esm/import-protection-plugin/postCompileUsage.js +0 -63
- package/dist/esm/import-protection-plugin/postCompileUsage.js.map +0 -1
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js +0 -205
- package/dist/esm/import-protection-plugin/rewriteDeniedImports.js.map +0 -1
- package/dist/esm/import-protection-plugin/sourceLocation.js.map +0 -1
- package/dist/esm/import-protection-plugin/trace.js.map +0 -1
- package/dist/esm/import-protection-plugin/utils.js.map +0 -1
- package/dist/esm/import-protection-plugin/virtualModules.d.ts +0 -78
- package/dist/esm/import-protection-plugin/virtualModules.js.map +0 -1
- package/dist/esm/start-compiler/load-module.d.ts +0 -14
- package/dist/esm/start-compiler/load-module.js +0 -18
- package/dist/esm/start-compiler/load-module.js.map +0 -1
- package/src/import-protection-plugin/INTERNALS.md +0 -700
- package/src/import-protection-plugin/postCompileUsage.ts +0 -100
- package/src/import-protection-plugin/rewriteDeniedImports.ts +0 -379
- package/src/start-compiler/load-module.ts +0 -31
- /package/dist/esm/{import-protection-plugin → import-protection}/ast.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/defaults.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → import-protection}/matchers.d.ts +0 -0
- /package/dist/esm/{import-protection-plugin → vite/import-protection-plugin}/plugin.d.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/ast.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/defaults.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/extensionlessAbsoluteIdResolver.ts +0 -0
- /package/src/{import-protection-plugin → import-protection}/matchers.ts +0 -0
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
import * as t from '@babel/types'
|
|
2
|
+
|
|
3
|
+
import { parseImportProtectionAst } from './ast'
|
|
4
|
+
import { buildLineIndex } from './sourceLocation'
|
|
5
|
+
import { getOrCreate } from './utils'
|
|
6
|
+
import type { LineIndex, TransformResult } from './sourceLocation'
|
|
7
|
+
import type { ParsedAst } from './ast'
|
|
8
|
+
|
|
9
|
+
export type UsagePos = { line: number; column0: number }
|
|
10
|
+
|
|
11
|
+
type BoundaryEnv = 'client' | 'server'
|
|
12
|
+
|
|
13
|
+
type ImportBindingInfo = {
|
|
14
|
+
importedLocalNames: Set<string>
|
|
15
|
+
memberBindingToSource: Map<string, string>
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type UsageCacheKey = `${BoundaryEnv | 'post'}::${string}`
|
|
19
|
+
|
|
20
|
+
export type ImportAnalysis = {
|
|
21
|
+
ast: ParsedAst
|
|
22
|
+
lineIndex: LineIndex
|
|
23
|
+
importSourcesInOrder: Array<string>
|
|
24
|
+
importSpecifierLocationIndex: Map<string, number>
|
|
25
|
+
importBindingsBySource: Map<string, ImportBindingInfo>
|
|
26
|
+
mockExportNamesBySource: Map<string, Array<string>>
|
|
27
|
+
namedExports: Array<string>
|
|
28
|
+
usageByKey: Map<UsageCacheKey, UsagePos | null>
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeTransientResult(code: string): TransformResult {
|
|
32
|
+
return {
|
|
33
|
+
code,
|
|
34
|
+
map: undefined,
|
|
35
|
+
originalCode: undefined,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getModuleExportName(node: t.Identifier | t.StringLiteral): string {
|
|
40
|
+
return t.isIdentifier(node) ? node.name : node.value
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getStringLiteralValueStart(node: t.StringLiteral): number {
|
|
44
|
+
if (node.start == null) {
|
|
45
|
+
return -1
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const raw = node.extra?.raw
|
|
49
|
+
if (typeof raw === 'string' && (raw.startsWith("'") || raw.startsWith('"'))) {
|
|
50
|
+
return node.start + 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return node.start
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function collectIdentifiersFromPattern(
|
|
57
|
+
pattern: t.LVal,
|
|
58
|
+
add: (name: string) => void,
|
|
59
|
+
): void {
|
|
60
|
+
if (t.isIdentifier(pattern)) {
|
|
61
|
+
add(pattern.name)
|
|
62
|
+
} else if (t.isObjectPattern(pattern)) {
|
|
63
|
+
for (const prop of pattern.properties) {
|
|
64
|
+
if (t.isRestElement(prop)) {
|
|
65
|
+
collectIdentifiersFromPattern(prop.argument as t.LVal, add)
|
|
66
|
+
} else {
|
|
67
|
+
collectIdentifiersFromPattern(prop.value as t.LVal, add)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} else if (t.isArrayPattern(pattern)) {
|
|
71
|
+
for (const elem of pattern.elements) {
|
|
72
|
+
if (elem) collectIdentifiersFromPattern(elem as t.LVal, add)
|
|
73
|
+
}
|
|
74
|
+
} else if (t.isAssignmentPattern(pattern)) {
|
|
75
|
+
collectIdentifiersFromPattern(pattern.left, add)
|
|
76
|
+
} else if (t.isRestElement(pattern)) {
|
|
77
|
+
collectIdentifiersFromPattern(pattern.argument as t.LVal, add)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function isValidExportName(name: string): boolean {
|
|
82
|
+
if (name === 'default' || name.length === 0) return false
|
|
83
|
+
const first = name.charCodeAt(0)
|
|
84
|
+
if (
|
|
85
|
+
!(
|
|
86
|
+
(first >= 65 && first <= 90) ||
|
|
87
|
+
(first >= 97 && first <= 122) ||
|
|
88
|
+
first === 95 ||
|
|
89
|
+
first === 36
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
return false
|
|
93
|
+
for (let i = 1; i < name.length; i++) {
|
|
94
|
+
const ch = name.charCodeAt(i)
|
|
95
|
+
if (
|
|
96
|
+
!(
|
|
97
|
+
(ch >= 65 && ch <= 90) ||
|
|
98
|
+
(ch >= 97 && ch <= 122) ||
|
|
99
|
+
(ch >= 48 && ch <= 57) ||
|
|
100
|
+
ch === 95 ||
|
|
101
|
+
ch === 36
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function buildImportAnalysis(result: TransformResult): ImportAnalysis {
|
|
110
|
+
const ast = result.parsedAst ?? parseImportProtectionAst(result.code)
|
|
111
|
+
result.parsedAst = ast
|
|
112
|
+
|
|
113
|
+
const importSourcesInOrder: Array<string> = []
|
|
114
|
+
const importSpecifierLocationIndex = new Map<string, number>()
|
|
115
|
+
const importBindingsBySource = new Map<string, ImportBindingInfo>()
|
|
116
|
+
const mockNamesBySource = new Map<string, Set<string>>()
|
|
117
|
+
const namedExports = new Set<string>()
|
|
118
|
+
|
|
119
|
+
const getBindingInfo = (source: string): ImportBindingInfo =>
|
|
120
|
+
getOrCreate(importBindingsBySource, source, () => ({
|
|
121
|
+
importedLocalNames: new Set<string>(),
|
|
122
|
+
memberBindingToSource: new Map<string, string>(),
|
|
123
|
+
}))
|
|
124
|
+
|
|
125
|
+
const addSpecifierLocation = (node: t.StringLiteral) => {
|
|
126
|
+
importSourcesInOrder.push(node.value)
|
|
127
|
+
|
|
128
|
+
const index = getStringLiteralValueStart(node)
|
|
129
|
+
if (index === -1) {
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const prev = importSpecifierLocationIndex.get(node.value)
|
|
134
|
+
if (prev == null || index < prev) {
|
|
135
|
+
importSpecifierLocationIndex.set(node.value, index)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const addMockName = (source: string, name: string) => {
|
|
140
|
+
if (name === 'default' || name.length === 0) return
|
|
141
|
+
getOrCreate(mockNamesBySource, source, () => new Set<string>()).add(name)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const addNamedExport = (name: string) => {
|
|
145
|
+
if (name !== 'default' && name.length > 0) {
|
|
146
|
+
namedExports.add(name)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const visit = (node: t.Node): void => {
|
|
151
|
+
if (t.isImportDeclaration(node)) {
|
|
152
|
+
addSpecifierLocation(node.source)
|
|
153
|
+
if (node.importKind !== 'type') {
|
|
154
|
+
const source = node.source.value
|
|
155
|
+
const bindingInfo = getBindingInfo(source)
|
|
156
|
+
for (const specifier of node.specifiers) {
|
|
157
|
+
if (t.isImportNamespaceSpecifier(specifier)) {
|
|
158
|
+
bindingInfo.importedLocalNames.add(specifier.local.name)
|
|
159
|
+
bindingInfo.memberBindingToSource.set(specifier.local.name, source)
|
|
160
|
+
continue
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (t.isImportDefaultSpecifier(specifier)) {
|
|
164
|
+
bindingInfo.importedLocalNames.add(specifier.local.name)
|
|
165
|
+
bindingInfo.memberBindingToSource.set(specifier.local.name, source)
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!t.isImportSpecifier(specifier)) continue
|
|
170
|
+
if (specifier.importKind === 'type') continue
|
|
171
|
+
|
|
172
|
+
bindingInfo.importedLocalNames.add(specifier.local.name)
|
|
173
|
+
const importedName = getModuleExportName(specifier.imported)
|
|
174
|
+
if (importedName !== 'default') {
|
|
175
|
+
addMockName(source, importedName)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} else if (t.isExportNamedDeclaration(node)) {
|
|
180
|
+
if (node.source && t.isStringLiteral(node.source)) {
|
|
181
|
+
addSpecifierLocation(node.source)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (node.exportKind !== 'type' && node.source?.value) {
|
|
185
|
+
const source = node.source.value
|
|
186
|
+
for (const specifier of node.specifiers) {
|
|
187
|
+
if (!t.isExportSpecifier(specifier)) continue
|
|
188
|
+
if (specifier.exportKind === 'type') continue
|
|
189
|
+
addMockName(source, getModuleExportName(specifier.local))
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (node.exportKind !== 'type') {
|
|
194
|
+
if (node.declaration) {
|
|
195
|
+
const decl = node.declaration
|
|
196
|
+
if (t.isFunctionDeclaration(decl) || t.isClassDeclaration(decl)) {
|
|
197
|
+
if (decl.id?.name) addNamedExport(decl.id.name)
|
|
198
|
+
} else if (t.isVariableDeclaration(decl)) {
|
|
199
|
+
for (const d of decl.declarations) {
|
|
200
|
+
collectIdentifiersFromPattern(d.id as t.LVal, addNamedExport)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (const specifier of node.specifiers) {
|
|
206
|
+
if (!t.isExportSpecifier(specifier)) continue
|
|
207
|
+
if (specifier.exportKind === 'type') continue
|
|
208
|
+
const exportedName = getModuleExportName(specifier.exported)
|
|
209
|
+
addNamedExport(exportedName)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
} else if (t.isExportAllDeclaration(node)) {
|
|
213
|
+
addSpecifierLocation(node.source)
|
|
214
|
+
} else if (t.isImportExpression(node)) {
|
|
215
|
+
if (t.isStringLiteral(node.source)) {
|
|
216
|
+
addSpecifierLocation(node.source)
|
|
217
|
+
}
|
|
218
|
+
} else if (t.isCallExpression(node) && t.isImport(node.callee)) {
|
|
219
|
+
const sourceNode = node.arguments[0]
|
|
220
|
+
if (t.isStringLiteral(sourceNode)) {
|
|
221
|
+
addSpecifierLocation(sourceNode)
|
|
222
|
+
}
|
|
223
|
+
} else if (
|
|
224
|
+
t.isMemberExpression(node) ||
|
|
225
|
+
t.isOptionalMemberExpression(node)
|
|
226
|
+
) {
|
|
227
|
+
const object = node.object
|
|
228
|
+
if (t.isIdentifier(object)) {
|
|
229
|
+
for (const [source, bindingInfo] of importBindingsBySource) {
|
|
230
|
+
if (!bindingInfo.memberBindingToSource.has(object.name)) {
|
|
231
|
+
continue
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const property = node.property
|
|
235
|
+
if (!node.computed && t.isIdentifier(property)) {
|
|
236
|
+
addMockName(source, property.name)
|
|
237
|
+
} else if (node.computed && t.isStringLiteral(property)) {
|
|
238
|
+
addMockName(source, property.value)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const keys = t.VISITOR_KEYS[node.type]
|
|
245
|
+
if (!keys) return
|
|
246
|
+
for (const key of keys) {
|
|
247
|
+
const child = (node as unknown as Record<string, unknown>)[key]
|
|
248
|
+
if (Array.isArray(child)) {
|
|
249
|
+
for (const item of child) {
|
|
250
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
251
|
+
visit(item as t.Node)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
} else if (child && typeof child === 'object' && 'type' in child) {
|
|
255
|
+
visit(child as t.Node)
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
visit(ast.program)
|
|
261
|
+
|
|
262
|
+
const mockExportNamesBySource = new Map<string, Array<string>>()
|
|
263
|
+
for (const [source, names] of mockNamesBySource) {
|
|
264
|
+
mockExportNamesBySource.set(source, Array.from(names).sort())
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const lineIndex = result.lineIndex ?? buildLineIndex(result.code)
|
|
268
|
+
result.lineIndex = lineIndex
|
|
269
|
+
|
|
270
|
+
const analysis = {
|
|
271
|
+
ast,
|
|
272
|
+
lineIndex,
|
|
273
|
+
importSourcesInOrder,
|
|
274
|
+
importSpecifierLocationIndex,
|
|
275
|
+
importBindingsBySource,
|
|
276
|
+
mockExportNamesBySource,
|
|
277
|
+
namedExports: Array.from(namedExports).sort(),
|
|
278
|
+
usageByKey: new Map(),
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return analysis
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export function getOrCreateImportAnalysis(
|
|
285
|
+
result: TransformResult,
|
|
286
|
+
): ImportAnalysis {
|
|
287
|
+
if (!result.analysis) {
|
|
288
|
+
result.analysis = buildImportAnalysis(result)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return result.analysis
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function getImportSourcesFromResult(
|
|
295
|
+
result: TransformResult,
|
|
296
|
+
): Array<string> {
|
|
297
|
+
return getOrCreateImportAnalysis(result).importSourcesInOrder
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function getImportSources(code: string): Array<string> {
|
|
301
|
+
return getImportSourcesFromResult(makeTransientResult(code))
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function getImportSpecifierLocationFromResult(
|
|
305
|
+
result: TransformResult,
|
|
306
|
+
source: string,
|
|
307
|
+
): number {
|
|
308
|
+
return (
|
|
309
|
+
getOrCreateImportAnalysis(result).importSpecifierLocationIndex.get(
|
|
310
|
+
source,
|
|
311
|
+
) ?? -1
|
|
312
|
+
)
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export function getMockExportNamesBySourceFromResult(
|
|
316
|
+
result: TransformResult,
|
|
317
|
+
): Map<string, Array<string>> {
|
|
318
|
+
return getOrCreateImportAnalysis(result).mockExportNamesBySource
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function getMockExportNamesBySource(
|
|
322
|
+
code: string,
|
|
323
|
+
): Map<string, Array<string>> {
|
|
324
|
+
return getMockExportNamesBySourceFromResult(makeTransientResult(code))
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function getNamedExportsFromResult(
|
|
328
|
+
result: TransformResult,
|
|
329
|
+
): Array<string> {
|
|
330
|
+
return getOrCreateImportAnalysis(result).namedExports
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export function getNamedExports(code: string): Array<string> {
|
|
334
|
+
return getNamedExportsFromResult(makeTransientResult(code))
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function isCompilerSafeBoundaryCall(
|
|
338
|
+
call: t.CallExpression,
|
|
339
|
+
fnNode: t.Function,
|
|
340
|
+
envType: BoundaryEnv,
|
|
341
|
+
): boolean {
|
|
342
|
+
const directArgument = call.arguments.some((arg) => arg === fnNode)
|
|
343
|
+
if (!directArgument) {
|
|
344
|
+
return false
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const callee = call.callee
|
|
348
|
+
|
|
349
|
+
if (t.isIdentifier(callee)) {
|
|
350
|
+
return envType === 'client'
|
|
351
|
+
? callee.name === 'createServerOnlyFn'
|
|
352
|
+
: callee.name === 'createClientOnlyFn'
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (!t.isMemberExpression(callee) || callee.computed) {
|
|
356
|
+
return false
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (!t.isIdentifier(callee.property)) {
|
|
360
|
+
return false
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const prop = callee.property.name
|
|
364
|
+
const rootName = getCalleeRootName(callee.object)
|
|
365
|
+
|
|
366
|
+
if (envType === 'client') {
|
|
367
|
+
if (prop === 'handler') {
|
|
368
|
+
return rootName === 'createServerFn' || /ServerFn$/.test(rootName ?? '')
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (prop === 'server') {
|
|
372
|
+
return (
|
|
373
|
+
rootName === 'createMiddleware' ||
|
|
374
|
+
rootName === 'createIsomorphicFn' ||
|
|
375
|
+
/Middleware$/.test(rootName ?? '')
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return false
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (prop === 'client') {
|
|
383
|
+
return rootName === 'createIsomorphicFn'
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return false
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function getCalleeRootName(
|
|
390
|
+
node: t.Expression | t.Super | t.V8IntrinsicIdentifier,
|
|
391
|
+
): string | undefined {
|
|
392
|
+
if (t.isIdentifier(node)) {
|
|
393
|
+
return node.name
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (t.isCallExpression(node)) {
|
|
397
|
+
return getCalleeRootName(node.callee)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (t.isMemberExpression(node)) {
|
|
401
|
+
return getCalleeRootName(node.object)
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return undefined
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function getBoundNamesFromPattern(pattern: t.LVal, out: Set<string>): void {
|
|
408
|
+
if (t.isIdentifier(pattern)) {
|
|
409
|
+
out.add(pattern.name)
|
|
410
|
+
} else if (t.isObjectPattern(pattern)) {
|
|
411
|
+
for (const prop of pattern.properties) {
|
|
412
|
+
if (t.isRestElement(prop)) {
|
|
413
|
+
getBoundNamesFromPattern(prop.argument as t.LVal, out)
|
|
414
|
+
} else {
|
|
415
|
+
getBoundNamesFromPattern(prop.value as t.LVal, out)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
} else if (t.isArrayPattern(pattern)) {
|
|
419
|
+
for (const elem of pattern.elements) {
|
|
420
|
+
if (elem) getBoundNamesFromPattern(elem as t.LVal, out)
|
|
421
|
+
}
|
|
422
|
+
} else if (t.isAssignmentPattern(pattern)) {
|
|
423
|
+
getBoundNamesFromPattern(pattern.left, out)
|
|
424
|
+
} else if (t.isRestElement(pattern)) {
|
|
425
|
+
getBoundNamesFromPattern(pattern.argument as t.LVal, out)
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function addPatternBindingsIfTracked(
|
|
430
|
+
pattern: t.LVal,
|
|
431
|
+
tracked: Set<string>,
|
|
432
|
+
out: Set<string>,
|
|
433
|
+
): void {
|
|
434
|
+
const names = new Set<string>()
|
|
435
|
+
getBoundNamesFromPattern(pattern, names)
|
|
436
|
+
for (const name of names) {
|
|
437
|
+
if (tracked.has(name)) {
|
|
438
|
+
out.add(name)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function collectHoistedVarBindings(
|
|
444
|
+
node: t.Node,
|
|
445
|
+
tracked: Set<string>,
|
|
446
|
+
out: Set<string>,
|
|
447
|
+
isRoot = true,
|
|
448
|
+
): void {
|
|
449
|
+
if (!isRoot && t.isFunction(node)) {
|
|
450
|
+
return
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (t.isVariableDeclaration(node) && node.kind === 'var') {
|
|
454
|
+
for (const decl of node.declarations) {
|
|
455
|
+
addPatternBindingsIfTracked(decl.id as t.LVal, tracked, out)
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
const keys = t.VISITOR_KEYS[node.type]
|
|
460
|
+
if (!keys) return
|
|
461
|
+
for (const key of keys) {
|
|
462
|
+
const child = (node as unknown as Record<string, unknown>)[key]
|
|
463
|
+
if (Array.isArray(child)) {
|
|
464
|
+
for (const item of child) {
|
|
465
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
466
|
+
collectHoistedVarBindings(item as t.Node, tracked, out, false)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
} else if (child && typeof child === 'object' && 'type' in child) {
|
|
470
|
+
collectHoistedVarBindings(child as t.Node, tracked, out, false)
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function collectProgramBindings(
|
|
476
|
+
program: t.Program,
|
|
477
|
+
tracked: Set<string>,
|
|
478
|
+
): Set<string> {
|
|
479
|
+
const bindings = new Set<string>()
|
|
480
|
+
|
|
481
|
+
for (const node of program.body) {
|
|
482
|
+
if (t.isVariableDeclaration(node)) {
|
|
483
|
+
for (const decl of node.declarations) {
|
|
484
|
+
addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)
|
|
485
|
+
}
|
|
486
|
+
continue
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {
|
|
490
|
+
if (node.id && tracked.has(node.id.name)) {
|
|
491
|
+
bindings.add(node.id.name)
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return bindings
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function collectBlockBindings(
|
|
500
|
+
block: t.BlockStatement,
|
|
501
|
+
tracked: Set<string>,
|
|
502
|
+
): Set<string> {
|
|
503
|
+
const bindings = new Set<string>()
|
|
504
|
+
|
|
505
|
+
for (const node of block.body) {
|
|
506
|
+
if (t.isVariableDeclaration(node) && node.kind !== 'var') {
|
|
507
|
+
for (const decl of node.declarations) {
|
|
508
|
+
addPatternBindingsIfTracked(decl.id as t.LVal, tracked, bindings)
|
|
509
|
+
}
|
|
510
|
+
continue
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (t.isFunctionDeclaration(node) || t.isClassDeclaration(node)) {
|
|
514
|
+
if (node.id && tracked.has(node.id.name)) {
|
|
515
|
+
bindings.add(node.id.name)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return bindings
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function collectFunctionBindings(
|
|
524
|
+
fn: t.Function,
|
|
525
|
+
tracked: Set<string>,
|
|
526
|
+
): Set<string> {
|
|
527
|
+
const bindings = new Set<string>()
|
|
528
|
+
|
|
529
|
+
if (
|
|
530
|
+
(t.isFunctionDeclaration(fn) || t.isFunctionExpression(fn)) &&
|
|
531
|
+
fn.id &&
|
|
532
|
+
tracked.has(fn.id.name)
|
|
533
|
+
) {
|
|
534
|
+
bindings.add(fn.id.name)
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
for (const param of fn.params) {
|
|
538
|
+
addPatternBindingsIfTracked(param as t.LVal, tracked, bindings)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (t.isBlockStatement(fn.body)) {
|
|
542
|
+
collectHoistedVarBindings(fn.body, tracked, bindings)
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return bindings
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
type UsageWalkContext = {
|
|
549
|
+
parents: Array<t.Node>
|
|
550
|
+
scopeStack: Array<Set<string>>
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function isShadowedByScope(
|
|
554
|
+
name: string,
|
|
555
|
+
scopeStack: Array<Set<string>>,
|
|
556
|
+
): boolean {
|
|
557
|
+
for (let i = scopeStack.length - 1; i >= 0; i--) {
|
|
558
|
+
if (scopeStack[i]?.has(name)) {
|
|
559
|
+
return true
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return false
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function isBindingIdentifierInParent(
|
|
566
|
+
node: t.Identifier,
|
|
567
|
+
parent: t.Node | undefined,
|
|
568
|
+
): boolean {
|
|
569
|
+
if (!parent) return false
|
|
570
|
+
|
|
571
|
+
if (t.isImportSpecifier(parent) || t.isImportDefaultSpecifier(parent)) {
|
|
572
|
+
return parent.local === node
|
|
573
|
+
}
|
|
574
|
+
if (t.isImportNamespaceSpecifier(parent)) {
|
|
575
|
+
return parent.local === node
|
|
576
|
+
}
|
|
577
|
+
if (t.isFunctionDeclaration(parent) || t.isFunctionExpression(parent)) {
|
|
578
|
+
return (
|
|
579
|
+
parent.id === node || parent.params.includes(node as unknown as t.Pattern)
|
|
580
|
+
)
|
|
581
|
+
}
|
|
582
|
+
if (t.isArrowFunctionExpression(parent)) {
|
|
583
|
+
return parent.params.includes(node as unknown as t.Pattern)
|
|
584
|
+
}
|
|
585
|
+
if (t.isClassDeclaration(parent) || t.isClassExpression(parent)) {
|
|
586
|
+
return parent.id === node
|
|
587
|
+
}
|
|
588
|
+
if (t.isVariableDeclarator(parent)) {
|
|
589
|
+
return parent.id === node
|
|
590
|
+
}
|
|
591
|
+
if (t.isCatchClause(parent)) {
|
|
592
|
+
return parent.param === node
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return false
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function isInsideCompilerSafeBoundaryNodes(
|
|
599
|
+
parents: Array<t.Node>,
|
|
600
|
+
envType: BoundaryEnv,
|
|
601
|
+
): boolean {
|
|
602
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
|
603
|
+
const node = parents[i]!
|
|
604
|
+
if (!t.isFunction(node)) {
|
|
605
|
+
continue
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const call = parents[i - 1]
|
|
609
|
+
if (
|
|
610
|
+
call &&
|
|
611
|
+
t.isCallExpression(call) &&
|
|
612
|
+
isCompilerSafeBoundaryCall(call, node, envType)
|
|
613
|
+
) {
|
|
614
|
+
return true
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return false
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function findUsagePosInAnalysis(
|
|
622
|
+
result: TransformResult,
|
|
623
|
+
source: string,
|
|
624
|
+
envType?: BoundaryEnv,
|
|
625
|
+
): UsagePos | undefined {
|
|
626
|
+
const analysis = getOrCreateImportAnalysis(result)
|
|
627
|
+
const cacheKey: UsageCacheKey = `${envType ?? 'post'}::${source}`
|
|
628
|
+
if (analysis.usageByKey.has(cacheKey)) {
|
|
629
|
+
return analysis.usageByKey.get(cacheKey) ?? undefined
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const imported =
|
|
633
|
+
analysis.importBindingsBySource.get(source)?.importedLocalNames
|
|
634
|
+
if (!imported || imported.size === 0) {
|
|
635
|
+
analysis.usageByKey.set(cacheKey, null)
|
|
636
|
+
return undefined
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
let preferred: UsagePos | undefined
|
|
640
|
+
let anyUsage: UsagePos | undefined
|
|
641
|
+
|
|
642
|
+
const visit = (node: t.Node, ctx: UsageWalkContext): void => {
|
|
643
|
+
if (preferred && anyUsage) {
|
|
644
|
+
return
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
if (t.isProgram(node)) {
|
|
648
|
+
const nextCtx = {
|
|
649
|
+
parents: [...ctx.parents, node],
|
|
650
|
+
scopeStack: [...ctx.scopeStack, collectProgramBindings(node, imported)],
|
|
651
|
+
}
|
|
652
|
+
for (const child of node.body) {
|
|
653
|
+
visit(child, nextCtx)
|
|
654
|
+
}
|
|
655
|
+
return
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (t.isFunction(node)) {
|
|
659
|
+
const functionCtx = {
|
|
660
|
+
parents: [...ctx.parents, node],
|
|
661
|
+
scopeStack: [
|
|
662
|
+
...ctx.scopeStack,
|
|
663
|
+
collectFunctionBindings(node, imported),
|
|
664
|
+
],
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
visit(node.body, functionCtx)
|
|
668
|
+
return
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (t.isBlockStatement(node)) {
|
|
672
|
+
const nextCtx = {
|
|
673
|
+
parents: [...ctx.parents, node],
|
|
674
|
+
scopeStack: [...ctx.scopeStack, collectBlockBindings(node, imported)],
|
|
675
|
+
}
|
|
676
|
+
for (const child of node.body) {
|
|
677
|
+
visit(child, nextCtx)
|
|
678
|
+
}
|
|
679
|
+
return
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
if (t.isCatchClause(node)) {
|
|
683
|
+
const bindings = new Set<string>()
|
|
684
|
+
if (node.param) {
|
|
685
|
+
addPatternBindingsIfTracked(node.param as t.LVal, imported, bindings)
|
|
686
|
+
}
|
|
687
|
+
const nextCtx = {
|
|
688
|
+
parents: [...ctx.parents, node],
|
|
689
|
+
scopeStack: bindings.size
|
|
690
|
+
? [...ctx.scopeStack, bindings]
|
|
691
|
+
: ctx.scopeStack,
|
|
692
|
+
}
|
|
693
|
+
visit(node.body, nextCtx)
|
|
694
|
+
return
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
if (
|
|
698
|
+
t.isForStatement(node) &&
|
|
699
|
+
t.isVariableDeclaration(node.init) &&
|
|
700
|
+
node.init.kind !== 'var'
|
|
701
|
+
) {
|
|
702
|
+
const bindings = new Set<string>()
|
|
703
|
+
for (const decl of node.init.declarations) {
|
|
704
|
+
addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)
|
|
705
|
+
}
|
|
706
|
+
const nextCtx = {
|
|
707
|
+
parents: [...ctx.parents, node],
|
|
708
|
+
scopeStack: bindings.size
|
|
709
|
+
? [...ctx.scopeStack, bindings]
|
|
710
|
+
: ctx.scopeStack,
|
|
711
|
+
}
|
|
712
|
+
visit(node.init, nextCtx)
|
|
713
|
+
if (node.test) visit(node.test, nextCtx)
|
|
714
|
+
if (node.update) visit(node.update, nextCtx)
|
|
715
|
+
visit(node.body, nextCtx)
|
|
716
|
+
return
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (
|
|
720
|
+
(t.isForInStatement(node) || t.isForOfStatement(node)) &&
|
|
721
|
+
t.isVariableDeclaration(node.left) &&
|
|
722
|
+
node.left.kind !== 'var'
|
|
723
|
+
) {
|
|
724
|
+
const bindings = new Set<string>()
|
|
725
|
+
for (const decl of node.left.declarations) {
|
|
726
|
+
addPatternBindingsIfTracked(decl.id as t.LVal, imported, bindings)
|
|
727
|
+
}
|
|
728
|
+
const nextCtx = {
|
|
729
|
+
parents: [...ctx.parents, node],
|
|
730
|
+
scopeStack: bindings.size
|
|
731
|
+
? [...ctx.scopeStack, bindings]
|
|
732
|
+
: ctx.scopeStack,
|
|
733
|
+
}
|
|
734
|
+
visit(node.left, nextCtx)
|
|
735
|
+
visit(node.right, nextCtx)
|
|
736
|
+
visit(node.body, nextCtx)
|
|
737
|
+
return
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const nextParents = [...ctx.parents, node]
|
|
741
|
+
|
|
742
|
+
if (t.isIdentifier(node)) {
|
|
743
|
+
const parent = ctx.parents[ctx.parents.length - 1]
|
|
744
|
+
if (imported.has(node.name)) {
|
|
745
|
+
if (!isBindingIdentifierInParent(node, parent)) {
|
|
746
|
+
if (
|
|
747
|
+
!(
|
|
748
|
+
t.isObjectProperty(parent) &&
|
|
749
|
+
parent.key === node &&
|
|
750
|
+
!parent.computed &&
|
|
751
|
+
!parent.shorthand
|
|
752
|
+
) &&
|
|
753
|
+
!(
|
|
754
|
+
t.isObjectMethod(parent) &&
|
|
755
|
+
parent.key === node &&
|
|
756
|
+
!parent.computed
|
|
757
|
+
) &&
|
|
758
|
+
!(t.isExportSpecifier(parent) && parent.exported === node) &&
|
|
759
|
+
!isShadowedByScope(node.name, ctx.scopeStack) &&
|
|
760
|
+
!(
|
|
761
|
+
envType && isInsideCompilerSafeBoundaryNodes(ctx.parents, envType)
|
|
762
|
+
)
|
|
763
|
+
) {
|
|
764
|
+
const loc = node.loc?.start
|
|
765
|
+
if (loc) {
|
|
766
|
+
const pos: UsagePos = { line: loc.line, column0: loc.column }
|
|
767
|
+
const isPreferred =
|
|
768
|
+
(t.isCallExpression(parent) && parent.callee === node) ||
|
|
769
|
+
(t.isNewExpression(parent) && parent.callee === node) ||
|
|
770
|
+
((t.isMemberExpression(parent) ||
|
|
771
|
+
t.isOptionalMemberExpression(parent)) &&
|
|
772
|
+
parent.object === node)
|
|
773
|
+
|
|
774
|
+
if (isPreferred) {
|
|
775
|
+
preferred ||= pos
|
|
776
|
+
} else {
|
|
777
|
+
anyUsage ||= pos
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
if (t.isImportDeclaration(node)) {
|
|
786
|
+
return
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
const keys = t.VISITOR_KEYS[node.type]
|
|
790
|
+
if (!keys) return
|
|
791
|
+
for (const key of keys) {
|
|
792
|
+
const child = (node as unknown as Record<string, unknown>)[key]
|
|
793
|
+
if (Array.isArray(child)) {
|
|
794
|
+
for (const item of child) {
|
|
795
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
796
|
+
visit(item as t.Node, {
|
|
797
|
+
parents: nextParents,
|
|
798
|
+
scopeStack: ctx.scopeStack,
|
|
799
|
+
})
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
} else if (child && typeof child === 'object' && 'type' in child) {
|
|
803
|
+
visit(child as t.Node, {
|
|
804
|
+
parents: nextParents,
|
|
805
|
+
scopeStack: ctx.scopeStack,
|
|
806
|
+
})
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
visit(analysis.ast.program, {
|
|
812
|
+
parents: [],
|
|
813
|
+
scopeStack: [],
|
|
814
|
+
})
|
|
815
|
+
|
|
816
|
+
const pos = preferred ?? anyUsage ?? null
|
|
817
|
+
analysis.usageByKey.set(cacheKey, pos)
|
|
818
|
+
return pos ?? undefined
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
export function findPostCompileUsagePosFromResult(
|
|
822
|
+
result: TransformResult,
|
|
823
|
+
source: string,
|
|
824
|
+
): UsagePos | undefined {
|
|
825
|
+
return findUsagePosInAnalysis(result, source)
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
export function findPostCompileUsagePos(
|
|
829
|
+
code: string,
|
|
830
|
+
source: string,
|
|
831
|
+
): UsagePos | undefined {
|
|
832
|
+
return findPostCompileUsagePosFromResult(makeTransientResult(code), source)
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
export function findOriginalUnsafeUsagePosFromResult(
|
|
836
|
+
result: TransformResult,
|
|
837
|
+
source: string,
|
|
838
|
+
envType: BoundaryEnv,
|
|
839
|
+
): UsagePos | undefined {
|
|
840
|
+
return findUsagePosInAnalysis(result, source, envType)
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
export function findOriginalUnsafeUsagePos(
|
|
844
|
+
code: string,
|
|
845
|
+
source: string,
|
|
846
|
+
envType: BoundaryEnv,
|
|
847
|
+
): UsagePos | undefined {
|
|
848
|
+
return findOriginalUnsafeUsagePosFromResult(
|
|
849
|
+
makeTransientResult(code),
|
|
850
|
+
source,
|
|
851
|
+
envType,
|
|
852
|
+
)
|
|
853
|
+
}
|