@litsx/babel-preset-litsx 0.8.2 → 0.9.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/index.cjs +6 -5
- package/dist/index.cjs.map +1 -1
- package/dist/internal/transform-litsx-components.cjs +71 -37
- package/dist/internal/transform-litsx-components.cjs.map +1 -1
- package/dist/internal/transform-litsx-hooks.cjs +616 -9
- package/dist/internal/transform-litsx-hooks.cjs.map +1 -1
- package/dist/internal/transform-litsx-renderer-props.cjs +2 -1
- package/dist/internal/transform-litsx-renderer-props.cjs.map +1 -1
- package/dist/internal/transform-litsx-static-ir.cjs +189 -0
- package/dist/internal/transform-litsx-static-ir.cjs.map +1 -0
- package/dist/pipeline.cjs +15 -7
- package/dist/pipeline.cjs.map +1 -1
- package/dist/shared/{transform-litsx-element-candidates-D0uvqG4Y.cjs → transform-litsx-element-candidates-D8pSZxpL.cjs} +21 -13
- package/dist/shared/transform-litsx-element-candidates-D8pSZxpL.cjs.map +1 -0
- package/package.json +8 -3
- package/src/internal/transform-litsx-class-generation.js +0 -1
- package/src/internal/transform-litsx-components.js +18 -20
- package/src/internal/transform-litsx-element-candidates.js +21 -10
- package/src/internal/transform-litsx-hooks.js +614 -9
- package/src/internal/transform-litsx-static-hoists.js +57 -15
- package/src/internal/transform-litsx-static-ir.js +176 -0
- package/src/pipeline.js +9 -2
- package/dist/shared/transform-litsx-element-candidates-D0uvqG4Y.cjs.map +0 -1
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var babelPluginSharedHooks = require('@litsx/babel-plugin-shared-hooks');
|
|
6
|
+
var fs = require('node:fs');
|
|
7
|
+
var path = require('node:path');
|
|
8
|
+
var traverse = require('@babel/traverse');
|
|
9
|
+
var parser = require('@litsx/babel-parser');
|
|
10
|
+
var internal_transformLitsxProperties = require('./transform-litsx-properties.cjs');
|
|
11
|
+
require('module');
|
|
12
|
+
require('@litsx/typescript-session');
|
|
6
13
|
|
|
7
14
|
const RUNTIME_MODULE = "@litsx/core";
|
|
8
15
|
const IMPORT_SOURCES = [RUNTIME_MODULE];
|
|
@@ -35,6 +42,599 @@ const RUNTIME_HELPERS = [
|
|
|
35
42
|
"useStableId",
|
|
36
43
|
];
|
|
37
44
|
|
|
45
|
+
const SOURCE_EXTENSIONS = [
|
|
46
|
+
"",
|
|
47
|
+
".litsx",
|
|
48
|
+
".tsx",
|
|
49
|
+
".ts",
|
|
50
|
+
".jsx",
|
|
51
|
+
".js",
|
|
52
|
+
".mjs",
|
|
53
|
+
".cjs",
|
|
54
|
+
];
|
|
55
|
+
const DEFAULT_MODULE_RESOLUTION_OPTIONS = {
|
|
56
|
+
moduleResolution: 100,
|
|
57
|
+
allowJs: true,
|
|
58
|
+
checkJs: false,
|
|
59
|
+
jsx: 1,
|
|
60
|
+
target: 99,
|
|
61
|
+
module: 99,
|
|
62
|
+
esModuleInterop: true,
|
|
63
|
+
allowSyntheticDefaultImports: true,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function normalizeFilePath(value) {
|
|
67
|
+
return normalizePath(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getTraverse() {
|
|
71
|
+
return traverse.default || traverse;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function normalizeInMemoryFiles(files) {
|
|
75
|
+
const normalized = new Map();
|
|
76
|
+
if (!files || typeof files !== "object") {
|
|
77
|
+
return normalized;
|
|
78
|
+
}
|
|
79
|
+
for (const [filename, source] of Object.entries(files)) {
|
|
80
|
+
if (typeof source !== "string") continue;
|
|
81
|
+
normalized.set(normalizeFilePath(filename), source);
|
|
82
|
+
}
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function createStructuralHookResolver(options = {}) {
|
|
87
|
+
const inMemoryFiles = normalizeInMemoryFiles(options.inMemoryFiles);
|
|
88
|
+
const moduleCache = new Map();
|
|
89
|
+
const resolvedImportCache = new Map();
|
|
90
|
+
const providedTypescriptSession =
|
|
91
|
+
options?.typescriptSession?.projectSession || options?.typescriptSession || null;
|
|
92
|
+
const compilerOptionsCache = new Map();
|
|
93
|
+
const moduleResolutionHostCache = new Map();
|
|
94
|
+
|
|
95
|
+
function getProgramForFile(filename) {
|
|
96
|
+
if (!providedTypescriptSession?.getProgram || !filename) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
if (providedTypescriptSession.kind === "project") {
|
|
102
|
+
return providedTypescriptSession.getProgram();
|
|
103
|
+
}
|
|
104
|
+
if (providedTypescriptSession.kind === "standalone") {
|
|
105
|
+
return providedTypescriptSession.getProgram(normalizeFilePath(filename));
|
|
106
|
+
}
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function getCompilerOptions(filename) {
|
|
115
|
+
const cacheKey = normalizeFilePath(filename);
|
|
116
|
+
if (compilerOptionsCache.has(cacheKey)) {
|
|
117
|
+
return compilerOptionsCache.get(cacheKey);
|
|
118
|
+
}
|
|
119
|
+
const program = getProgramForFile(filename);
|
|
120
|
+
const compilerOptions =
|
|
121
|
+
program?.getCompilerOptions?.() ||
|
|
122
|
+
options.compilerOptions ||
|
|
123
|
+
DEFAULT_MODULE_RESOLUTION_OPTIONS;
|
|
124
|
+
compilerOptionsCache.set(cacheKey, compilerOptions);
|
|
125
|
+
return compilerOptions;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function getModuleResolutionHost(filename) {
|
|
129
|
+
const cacheKey = normalizeFilePath(filename);
|
|
130
|
+
if (moduleResolutionHostCache.has(cacheKey)) {
|
|
131
|
+
return moduleResolutionHostCache.get(cacheKey);
|
|
132
|
+
}
|
|
133
|
+
const ts = internal_transformLitsxProperties.ensureTypescriptModule();
|
|
134
|
+
const host = providedTypescriptSession?.host || ts.sys;
|
|
135
|
+
moduleResolutionHostCache.set(cacheKey, host);
|
|
136
|
+
return host;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function fileExists(filename) {
|
|
140
|
+
const normalized = normalizeFilePath(filename);
|
|
141
|
+
return inMemoryFiles.has(normalized) || fs.existsSync(normalized);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function readFile(filename) {
|
|
145
|
+
const normalized = normalizeFilePath(filename);
|
|
146
|
+
if (inMemoryFiles.has(normalized)) {
|
|
147
|
+
return inMemoryFiles.get(normalized);
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
return fs.readFileSync(normalized, "utf8");
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function resolveWithExtensions(base) {
|
|
157
|
+
const normalizedBase = normalizeFilePath(base);
|
|
158
|
+
for (const ext of SOURCE_EXTENSIONS) {
|
|
159
|
+
const candidate = `${normalizedBase}${ext}`;
|
|
160
|
+
if (fileExists(candidate)) {
|
|
161
|
+
return normalizeFilePath(candidate);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
for (const ext of SOURCE_EXTENSIONS.filter(Boolean)) {
|
|
165
|
+
const candidate = normalizeFilePath(path.join(base, `index${ext}`));
|
|
166
|
+
if (fileExists(candidate)) {
|
|
167
|
+
return candidate;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function resolvePathAlias(containingFile, source) {
|
|
174
|
+
const compilerOptions = getCompilerOptions(containingFile) || {};
|
|
175
|
+
const baseUrl = compilerOptions.baseUrl
|
|
176
|
+
? normalizeFilePath(
|
|
177
|
+
path.isAbsolute(compilerOptions.baseUrl)
|
|
178
|
+
? compilerOptions.baseUrl
|
|
179
|
+
: path.resolve(path.dirname(containingFile), compilerOptions.baseUrl)
|
|
180
|
+
)
|
|
181
|
+
: normalizeFilePath(path.dirname(containingFile));
|
|
182
|
+
const pathMappings = compilerOptions.paths || {};
|
|
183
|
+
|
|
184
|
+
for (const [pattern, substitutions] of Object.entries(pathMappings)) {
|
|
185
|
+
const starIndex = pattern.indexOf("*");
|
|
186
|
+
const isStarPattern = starIndex !== -1;
|
|
187
|
+
const prefix = isStarPattern ? pattern.slice(0, starIndex) : pattern;
|
|
188
|
+
const suffix = isStarPattern ? pattern.slice(starIndex + 1) : "";
|
|
189
|
+
|
|
190
|
+
if (isStarPattern) {
|
|
191
|
+
if (!source.startsWith(prefix) || !source.endsWith(suffix)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
} else if (source !== pattern) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const wildcardValue = isStarPattern
|
|
199
|
+
? source.slice(prefix.length, source.length - suffix.length)
|
|
200
|
+
: "";
|
|
201
|
+
|
|
202
|
+
for (const substitution of substitutions || []) {
|
|
203
|
+
const substituted = isStarPattern
|
|
204
|
+
? substitution.replace("*", wildcardValue)
|
|
205
|
+
: substitution;
|
|
206
|
+
const candidateBase = path.isAbsolute(substituted)
|
|
207
|
+
? substituted
|
|
208
|
+
: path.join(baseUrl, substituted);
|
|
209
|
+
const resolved = resolveWithExtensions(candidateBase);
|
|
210
|
+
if (resolved) {
|
|
211
|
+
return resolved;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function resolveImport(containingFile, source) {
|
|
220
|
+
if (typeof source !== "string" || !containingFile) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
const cacheKey = `${normalizeFilePath(containingFile)}::${source}`;
|
|
224
|
+
if (resolvedImportCache.has(cacheKey)) {
|
|
225
|
+
return resolvedImportCache.get(cacheKey);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const baseDir = path.dirname(containingFile);
|
|
229
|
+
let resolved = source.startsWith(".") || source.startsWith("/")
|
|
230
|
+
? resolveWithExtensions(path.resolve(baseDir, source))
|
|
231
|
+
: resolvePathAlias(containingFile, source);
|
|
232
|
+
|
|
233
|
+
if (!resolved) {
|
|
234
|
+
const ts = internal_transformLitsxProperties.ensureTypescriptModule();
|
|
235
|
+
try {
|
|
236
|
+
const resolution = ts.resolveModuleName(
|
|
237
|
+
source,
|
|
238
|
+
normalizeFilePath(containingFile),
|
|
239
|
+
getCompilerOptions(containingFile),
|
|
240
|
+
getModuleResolutionHost(containingFile)
|
|
241
|
+
);
|
|
242
|
+
const resolvedFileName = resolution?.resolvedModule?.resolvedFileName;
|
|
243
|
+
if (resolvedFileName) {
|
|
244
|
+
resolved = resolveWithExtensions(resolvedFileName) || normalizeFilePath(resolvedFileName);
|
|
245
|
+
}
|
|
246
|
+
} catch {
|
|
247
|
+
resolved = null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
resolvedImportCache.set(cacheKey, resolved);
|
|
252
|
+
return resolved;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function getParserPluginsForModule(filename, source) {
|
|
256
|
+
if (/\.(?:[cm]?ts|tsx|litsx)$/i.test(filename)) {
|
|
257
|
+
return ["typescript"];
|
|
258
|
+
}
|
|
259
|
+
if (/\b(?:as|satisfies)\s+[^;,)]+/.test(source)) {
|
|
260
|
+
return ["typescript"];
|
|
261
|
+
}
|
|
262
|
+
return [];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function getImportedName(specifier) {
|
|
266
|
+
if (specifier.type === "ImportDefaultSpecifier") return "default";
|
|
267
|
+
if (specifier.type === "ImportNamespaceSpecifier") return "*";
|
|
268
|
+
return specifier.imported?.name ?? specifier.imported?.value ?? null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function isDefineHookCallee(node, analysis) {
|
|
272
|
+
if (!node) return false;
|
|
273
|
+
if (node.type === "Identifier") {
|
|
274
|
+
return analysis.defineHookLocals.has(node.name);
|
|
275
|
+
}
|
|
276
|
+
if (
|
|
277
|
+
node.type === "MemberExpression" &&
|
|
278
|
+
!node.computed &&
|
|
279
|
+
node.property?.type === "Identifier" &&
|
|
280
|
+
node.property.name === "defineHook" &&
|
|
281
|
+
node.object?.type === "Identifier"
|
|
282
|
+
) {
|
|
283
|
+
return analysis.runtimeNamespaceLocals.has(node.object.name);
|
|
284
|
+
}
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function addExportBinding(analysis, exportedName, info) {
|
|
289
|
+
if (exportedName) {
|
|
290
|
+
analysis.exportBindings.set(exportedName, info);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function getDefineHookPhaseInfo(init) {
|
|
295
|
+
const definition = init?.arguments?.[0];
|
|
296
|
+
if (!definition || definition.type !== "ObjectExpression") {
|
|
297
|
+
return {
|
|
298
|
+
hasStaticPhase: false,
|
|
299
|
+
hasInstancePhase: true,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const hasProperty = (name) => definition.properties.some((property) => {
|
|
303
|
+
if (property.type !== "ObjectProperty" && property.type !== "ObjectMethod") {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
const key = property.key;
|
|
307
|
+
return (
|
|
308
|
+
(key.type === "Identifier" && key.name === name) ||
|
|
309
|
+
(key.type === "StringLiteral" && key.value === name)
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
return {
|
|
313
|
+
hasStaticPhase: hasProperty("static"),
|
|
314
|
+
hasInstancePhase: hasProperty("setup") || hasProperty("createState") || hasProperty("middlewares"),
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function analyzeModule(filename) {
|
|
319
|
+
const normalizedFilename = normalizeFilePath(filename);
|
|
320
|
+
if (!normalizedFilename) return null;
|
|
321
|
+
if (moduleCache.has(normalizedFilename)) {
|
|
322
|
+
return moduleCache.get(normalizedFilename);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const source = readFile(normalizedFilename);
|
|
326
|
+
if (typeof source !== "string") {
|
|
327
|
+
moduleCache.set(normalizedFilename, null);
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const analysis = {
|
|
332
|
+
filename: normalizedFilename,
|
|
333
|
+
importBindings: new Map(),
|
|
334
|
+
exportBindings: new Map(),
|
|
335
|
+
defineHookLocals: new Set(),
|
|
336
|
+
runtimeNamespaceLocals: new Set(),
|
|
337
|
+
structuralLocals: new Set(),
|
|
338
|
+
structuralLocalInfo: new Map(),
|
|
339
|
+
customHookPaths: new Map(),
|
|
340
|
+
customHookUsageCache: new Map(),
|
|
341
|
+
};
|
|
342
|
+
moduleCache.set(normalizedFilename, analysis);
|
|
343
|
+
|
|
344
|
+
let ast;
|
|
345
|
+
try {
|
|
346
|
+
ast = parser.parse(source, {
|
|
347
|
+
sourceType: "module",
|
|
348
|
+
plugins: getParserPluginsForModule(normalizedFilename, source),
|
|
349
|
+
});
|
|
350
|
+
} catch {
|
|
351
|
+
moduleCache.set(normalizedFilename, null);
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
getTraverse()(ast, {
|
|
356
|
+
Program(programPath) {
|
|
357
|
+
for (const statementPath of programPath.get("body")) {
|
|
358
|
+
const node = statementPath.node;
|
|
359
|
+
|
|
360
|
+
if (statementPath.isImportDeclaration()) {
|
|
361
|
+
const sourceValue = node.source.value;
|
|
362
|
+
const resolvedSource = resolveImport(normalizedFilename, sourceValue);
|
|
363
|
+
for (const specifier of node.specifiers) {
|
|
364
|
+
const localName = specifier.local?.name;
|
|
365
|
+
if (!localName) continue;
|
|
366
|
+
const importedName = getImportedName(specifier);
|
|
367
|
+
analysis.importBindings.set(localName, {
|
|
368
|
+
importedName,
|
|
369
|
+
source: sourceValue,
|
|
370
|
+
resolvedSource,
|
|
371
|
+
});
|
|
372
|
+
if (sourceValue === RUNTIME_MODULE && importedName === "defineHook") {
|
|
373
|
+
analysis.defineHookLocals.add(localName);
|
|
374
|
+
}
|
|
375
|
+
if (
|
|
376
|
+
sourceValue === RUNTIME_MODULE &&
|
|
377
|
+
(specifier.type === "ImportNamespaceSpecifier" ||
|
|
378
|
+
specifier.type === "ImportDefaultSpecifier")
|
|
379
|
+
) {
|
|
380
|
+
analysis.runtimeNamespaceLocals.add(localName);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const declarationPath = statementPath.isExportNamedDeclaration()
|
|
387
|
+
? statementPath.get("declaration")
|
|
388
|
+
: statementPath;
|
|
389
|
+
|
|
390
|
+
if (declarationPath?.isFunctionDeclaration?.()) {
|
|
391
|
+
const localName = declarationPath.node.id?.name;
|
|
392
|
+
if (localName && /^use[A-Z0-9]/.test(localName)) {
|
|
393
|
+
analysis.customHookPaths.set(localName, declarationPath);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (declarationPath?.isVariableDeclaration?.()) {
|
|
398
|
+
for (const declaratorPath of declarationPath.get("declarations")) {
|
|
399
|
+
const id = declaratorPath.node.id;
|
|
400
|
+
if (id?.type !== "Identifier") continue;
|
|
401
|
+
const init = declaratorPath.node.init;
|
|
402
|
+
if (init?.type === "CallExpression" && isDefineHookCallee(init.callee, analysis)) {
|
|
403
|
+
analysis.structuralLocals.add(id.name);
|
|
404
|
+
analysis.structuralLocalInfo.set(id.name, getDefineHookPhaseInfo(init));
|
|
405
|
+
} else if (
|
|
406
|
+
/^use[A-Z0-9]/.test(id.name) &&
|
|
407
|
+
(
|
|
408
|
+
init?.type === "FunctionExpression" ||
|
|
409
|
+
init?.type === "ArrowFunctionExpression"
|
|
410
|
+
)
|
|
411
|
+
) {
|
|
412
|
+
analysis.customHookPaths.set(id.name, declaratorPath.get("init"));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (statementPath.isExportNamedDeclaration()) {
|
|
418
|
+
const exportNode = statementPath.node;
|
|
419
|
+
const declaration = exportNode.declaration;
|
|
420
|
+
if (declaration?.type === "VariableDeclaration") {
|
|
421
|
+
for (const declarator of declaration.declarations) {
|
|
422
|
+
const localName = declarator.id?.name;
|
|
423
|
+
if (localName) {
|
|
424
|
+
addExportBinding(analysis, localName, { localName });
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
} else if (
|
|
428
|
+
declaration?.type === "FunctionDeclaration" ||
|
|
429
|
+
declaration?.type === "ClassDeclaration"
|
|
430
|
+
) {
|
|
431
|
+
addExportBinding(analysis, declaration.id?.name, {
|
|
432
|
+
localName: declaration.id?.name,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
for (const specifier of exportNode.specifiers) {
|
|
437
|
+
const exportedName = specifier.exported?.name ?? specifier.exported?.value ?? null;
|
|
438
|
+
if (!exportedName) continue;
|
|
439
|
+
const localName = specifier.local?.name ?? specifier.local?.value ?? exportedName;
|
|
440
|
+
if (exportNode.source?.value) {
|
|
441
|
+
addExportBinding(analysis, exportedName, {
|
|
442
|
+
importedName: localName,
|
|
443
|
+
resolvedSource: resolveImport(normalizedFilename, exportNode.source.value),
|
|
444
|
+
});
|
|
445
|
+
} else {
|
|
446
|
+
addExportBinding(analysis, exportedName, { localName });
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
return analysis;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function isNamespaceStructuralUse(analysis, objectName, propertyName, seen) {
|
|
458
|
+
const importInfo = analysis.importBindings.get(objectName);
|
|
459
|
+
if (!importInfo?.resolvedSource || importInfo.importedName !== "*") {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
const importedModule = analyzeModule(importInfo.resolvedSource);
|
|
463
|
+
return (
|
|
464
|
+
isStructuralExport(importedModule, propertyName, seen) ||
|
|
465
|
+
isStructuralCustomExport(importedModule, propertyName, seen)
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function localCustomHookUsesStructural(analysis, localName, seen = new Set()) {
|
|
470
|
+
if (!analysis || !localName) return false;
|
|
471
|
+
const key = `${analysis.filename}:local:${localName}`;
|
|
472
|
+
if (analysis.customHookUsageCache.has(localName)) {
|
|
473
|
+
return analysis.customHookUsageCache.get(localName);
|
|
474
|
+
}
|
|
475
|
+
if (seen.has(key)) return false;
|
|
476
|
+
const nextSeen = new Set(seen);
|
|
477
|
+
nextSeen.add(key);
|
|
478
|
+
|
|
479
|
+
const fnPath = analysis.customHookPaths.get(localName);
|
|
480
|
+
if (!fnPath?.traverse) {
|
|
481
|
+
analysis.customHookUsageCache.set(localName, false);
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
let usesStructural = false;
|
|
486
|
+
fnPath.traverse({
|
|
487
|
+
CallExpression(callPath) {
|
|
488
|
+
if (usesStructural) {
|
|
489
|
+
callPath.stop();
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const callee = callPath.get("callee");
|
|
493
|
+
if (callee.isIdentifier()) {
|
|
494
|
+
const name = callee.node.name;
|
|
495
|
+
if (analysis.structuralLocals.has(name)) {
|
|
496
|
+
usesStructural = true;
|
|
497
|
+
callPath.stop();
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
if (
|
|
501
|
+
analysis.customHookPaths.has(name) &&
|
|
502
|
+
localCustomHookUsesStructural(analysis, name, nextSeen)
|
|
503
|
+
) {
|
|
504
|
+
usesStructural = true;
|
|
505
|
+
callPath.stop();
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
const importInfo = analysis.importBindings.get(name);
|
|
509
|
+
if (importInfo?.resolvedSource && importInfo.importedName !== "*") {
|
|
510
|
+
const importedModule = analyzeModule(importInfo.resolvedSource);
|
|
511
|
+
if (
|
|
512
|
+
isStructuralExport(importedModule, importInfo.importedName, nextSeen) ||
|
|
513
|
+
isStructuralCustomExport(importedModule, importInfo.importedName, nextSeen)
|
|
514
|
+
) {
|
|
515
|
+
usesStructural = true;
|
|
516
|
+
callPath.stop();
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (callee.isMemberExpression({ computed: false })) {
|
|
523
|
+
const object = callee.get("object");
|
|
524
|
+
const property = callee.get("property");
|
|
525
|
+
if (
|
|
526
|
+
object.isIdentifier() &&
|
|
527
|
+
property.isIdentifier() &&
|
|
528
|
+
isNamespaceStructuralUse(analysis, object.node.name, property.node.name, nextSeen)
|
|
529
|
+
) {
|
|
530
|
+
usesStructural = true;
|
|
531
|
+
callPath.stop();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
analysis.customHookUsageCache.set(localName, usesStructural);
|
|
538
|
+
return usesStructural;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function getStructuralExportInfo(analysis, exportedName, seen = new Set()) {
|
|
542
|
+
if (!analysis || !exportedName) return false;
|
|
543
|
+
const key = `${analysis.filename}:${exportedName}`;
|
|
544
|
+
if (seen.has(key)) return false;
|
|
545
|
+
const nextSeen = new Set(seen);
|
|
546
|
+
nextSeen.add(key);
|
|
547
|
+
|
|
548
|
+
const exportInfo = analysis.exportBindings.get(exportedName);
|
|
549
|
+
if (!exportInfo) {
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (exportInfo.resolvedSource) {
|
|
554
|
+
return getStructuralExportInfo(
|
|
555
|
+
analyzeModule(exportInfo.resolvedSource),
|
|
556
|
+
exportInfo.importedName,
|
|
557
|
+
nextSeen
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (analysis.structuralLocals.has(exportInfo.localName)) {
|
|
562
|
+
return {
|
|
563
|
+
kind: "structural-hook",
|
|
564
|
+
...(analysis.structuralLocalInfo.get(exportInfo.localName) || {
|
|
565
|
+
hasStaticPhase: false,
|
|
566
|
+
hasInstancePhase: true,
|
|
567
|
+
}),
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
const importInfo = analysis.importBindings.get(exportInfo.localName);
|
|
572
|
+
if (importInfo?.resolvedSource && importInfo.importedName !== "*") {
|
|
573
|
+
return getStructuralExportInfo(
|
|
574
|
+
analyzeModule(importInfo.resolvedSource),
|
|
575
|
+
importInfo.importedName,
|
|
576
|
+
nextSeen
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function isStructuralExport(analysis, exportedName, seen = new Set()) {
|
|
584
|
+
return Boolean(getStructuralExportInfo(analysis, exportedName, seen));
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
function isStructuralCustomExport(analysis, exportedName, seen = new Set()) {
|
|
588
|
+
if (!analysis || !exportedName) return false;
|
|
589
|
+
const key = `${analysis.filename}:custom:${exportedName}`;
|
|
590
|
+
if (seen.has(key)) return false;
|
|
591
|
+
const nextSeen = new Set(seen);
|
|
592
|
+
nextSeen.add(key);
|
|
593
|
+
|
|
594
|
+
const exportInfo = analysis.exportBindings.get(exportedName);
|
|
595
|
+
if (!exportInfo) {
|
|
596
|
+
return false;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
if (exportInfo.resolvedSource) {
|
|
600
|
+
return isStructuralCustomExport(
|
|
601
|
+
analyzeModule(exportInfo.resolvedSource),
|
|
602
|
+
exportInfo.importedName,
|
|
603
|
+
nextSeen
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (localCustomHookUsesStructural(analysis, exportInfo.localName, nextSeen)) {
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const importInfo = analysis.importBindings.get(exportInfo.localName);
|
|
612
|
+
if (importInfo?.resolvedSource && importInfo.importedName !== "*") {
|
|
613
|
+
return isStructuralCustomExport(
|
|
614
|
+
analyzeModule(importInfo.resolvedSource),
|
|
615
|
+
importInfo.importedName,
|
|
616
|
+
nextSeen
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return function structuralHookResolver({ filename, source, importedName }) {
|
|
624
|
+
const resolved = resolveImport(filename, source);
|
|
625
|
+
if (!resolved) return false;
|
|
626
|
+
const analysis = analyzeModule(resolved);
|
|
627
|
+
const structuralInfo = getStructuralExportInfo(analysis, importedName);
|
|
628
|
+
if (structuralInfo) {
|
|
629
|
+
return structuralInfo;
|
|
630
|
+
}
|
|
631
|
+
if (isStructuralCustomExport(analysis, importedName)) {
|
|
632
|
+
return "structural-custom-hook";
|
|
633
|
+
}
|
|
634
|
+
return false;
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
|
|
38
638
|
function normalizePath(value) {
|
|
39
639
|
return String(value || "").replace(/\\/g, "/");
|
|
40
640
|
}
|
|
@@ -66,15 +666,22 @@ function createStableIdCallsiteMetadata(callPath, state, t) {
|
|
|
66
666
|
return t.stringLiteral(`litsx-stable-${hashStableId(seed)}`);
|
|
67
667
|
}
|
|
68
668
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
669
|
+
function transformLitsxHooks(api, options = {}) {
|
|
670
|
+
const plugin = babelPluginSharedHooks.createRuntimeHooksTransform({
|
|
671
|
+
pluginName: "transform-litsx-hooks",
|
|
672
|
+
runtimeModule: RUNTIME_MODULE,
|
|
673
|
+
importSources: IMPORT_SOURCES,
|
|
674
|
+
helperNames: RUNTIME_HELPERS,
|
|
675
|
+
callMetadataByHelper: {
|
|
676
|
+
useStableId: createStableIdCallsiteMetadata,
|
|
677
|
+
},
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
return plugin(api, {
|
|
681
|
+
...options,
|
|
682
|
+
structuralHookResolver: createStructuralHookResolver(options),
|
|
683
|
+
});
|
|
684
|
+
}
|
|
78
685
|
|
|
79
686
|
exports.default = transformLitsxHooks;
|
|
80
687
|
//# sourceMappingURL=transform-litsx-hooks.cjs.map
|