@generaltranslation/vue-extractor 0.0.0 → 0.1.0-iris.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/LICENSE.md +18 -102
- package/dist/detect.d.ts +8 -0
- package/dist/detect.js +2 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/inspect.d.ts +9 -0
- package/dist/inspect.js +2 -0
- package/dist/integration.d.ts +69 -0
- package/dist/integration.js +162 -0
- package/dist/integration.js.map +1 -0
- package/dist/internal/config/configFiles.d.ts +6 -0
- package/dist/internal/config/configFiles.js +34 -0
- package/dist/internal/config/configFiles.js.map +1 -0
- package/dist/internal/config/resolveVueCompilerOptions.d.ts +6 -0
- package/dist/internal/config/resolveVueCompilerOptions.js +74 -56
- package/dist/internal/config/resolveVueCompilerOptions.js.map +1 -1
- package/dist/internal/extractFromVueSource.d.ts +4 -3
- package/dist/internal/extractFromVueSource.js +255 -12
- package/dist/internal/extractFromVueSource.js.map +1 -1
- package/dist/internal/project/consumerUsage.d.ts +34 -0
- package/dist/internal/project/consumerUsage.js +1220 -0
- package/dist/internal/project/consumerUsage.js.map +1 -0
- package/dist/internal/project/detectVueProject.d.ts +13 -0
- package/dist/internal/project/detectVueProject.js +65 -0
- package/dist/internal/project/detectVueProject.js.map +1 -0
- package/dist/internal/project/extractFromVueProject.d.ts +10 -0
- package/dist/internal/project/extractFromVueProject.js +579 -0
- package/dist/internal/project/extractFromVueProject.js.map +1 -0
- package/dist/internal/project/inspectVueProject.d.ts +48 -0
- package/dist/internal/project/inspectVueProject.js +143 -0
- package/dist/internal/project/inspectVueProject.js.map +1 -0
- package/dist/internal/project/manifest.d.ts +64 -0
- package/dist/internal/project/manifest.js +270 -0
- package/dist/internal/project/manifest.js.map +1 -0
- package/dist/internal/project/mergeVueProjectExtraction.d.ts +18 -0
- package/dist/internal/project/mergeVueProjectExtraction.js +79 -0
- package/dist/internal/project/mergeVueProjectExtraction.js.map +1 -0
- package/dist/internal/project/moduleResolver.d.ts +18 -0
- package/dist/internal/project/moduleResolver.js +325 -0
- package/dist/internal/project/moduleResolver.js.map +1 -0
- package/dist/internal/project/scopes.d.ts +31 -0
- package/dist/internal/project/scopes.js +182 -0
- package/dist/internal/project/scopes.js.map +1 -0
- package/dist/internal/project/sourcePatterns.d.ts +4 -0
- package/dist/internal/project/sourcePatterns.js +32 -0
- package/dist/internal/project/sourcePatterns.js.map +1 -0
- package/dist/internal/project/viteAliases.d.ts +42 -0
- package/dist/internal/project/viteAliases.js +1020 -0
- package/dist/internal/project/viteAliases.js.map +1 -0
- package/dist/internal/project/vueSourceClassification.d.ts +13 -0
- package/dist/internal/project/vueSourceClassification.js +146 -0
- package/dist/internal/project/vueSourceClassification.js.map +1 -0
- package/dist/internal/project/workspaces.d.ts +31 -0
- package/dist/internal/project/workspaces.js +326 -0
- package/dist/internal/project/workspaces.js.map +1 -0
- package/dist/internal/project/wrapperProvenance.d.ts +21 -0
- package/dist/internal/project/wrapperProvenance.js +287 -0
- package/dist/internal/project/wrapperProvenance.js.map +1 -0
- package/dist/internal/script/analyze.js +252 -85
- package/dist/internal/script/analyze.js.map +1 -1
- package/dist/internal/script/jsx.d.ts +7 -4
- package/dist/internal/script/jsx.js +351 -79
- package/dist/internal/script/jsx.js.map +1 -1
- package/dist/internal/script/localModules.d.ts +23 -2
- package/dist/internal/script/localModules.js +533 -20
- package/dist/internal/script/localModules.js.map +1 -1
- package/dist/internal/script/model.d.ts +9 -2
- package/dist/internal/script/parser.js +2 -1
- package/dist/internal/script/parser.js.map +1 -1
- package/dist/internal/script/runtimeModules.d.ts +10 -0
- package/dist/internal/script/runtimeModules.js +27 -0
- package/dist/internal/script/runtimeModules.js.map +1 -0
- package/dist/internal/stringCalls.js +1 -1
- package/dist/internal/stringCalls.js.map +1 -1
- package/dist/internal/template.js +263 -141
- package/dist/internal/template.js.map +1 -1
- package/dist/internal/types.d.ts +4 -1
- package/dist/internal/utils.d.ts +14 -3
- package/dist/internal/utils.js +63 -3
- package/dist/internal/utils.js.map +1 -1
- package/dist/internal/vueCompiler.d.ts +9 -1
- package/dist/internal/vueCompiler.js +37 -14
- package/dist/internal/vueCompiler.js.map +1 -1
- package/dist/project.d.ts +11 -0
- package/dist/project.js +3 -0
- package/dist/types.d.ts +95 -4
- package/package.json +30 -4
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseScriptAst } from "./parser.js";
|
|
2
|
+
import { isKnownNonVueGTRuntime } from "./runtimeModules.js";
|
|
3
|
+
import { addVueError, babelLocation, readStaticGlobalPrimitive, readStaticPrimitive, unwrapExpression } from "../utils.js";
|
|
2
4
|
import { processVueStringCall } from "../stringCalls.js";
|
|
3
5
|
import { appendTemplatePath, unknownTemplatePathSegment } from "../templatePath.js";
|
|
4
6
|
import { createReplayAnalysis } from "./replay.js";
|
|
5
7
|
import { createSnapshotAnalysis } from "./snapshot.js";
|
|
6
8
|
import { COMPONENT_IMPORTS, ORDINARY_GLOBAL_VALUES, READONLY_ARRAY_TRANSFORMS, VUE_BUILTIN_IMPORTS, knownExport, knownValueKey } from "./knownValues.js";
|
|
7
9
|
import { extractVueJSXTranslation, isNestedInVueJSXTranslation, resolveVueJSXElementIdentity, validateVueJSXVariableComponent } from "./jsx.js";
|
|
8
|
-
import { parseScriptAst } from "./parser.js";
|
|
9
10
|
import { isAssignmentTargetWrapper, isBindingPattern, isStaticallyUndefined, patternContains, readMemberProperty, readPatternIdentifier, readPropertyKey } from "./syntax.js";
|
|
10
11
|
import traverseModule from "@babel/traverse";
|
|
11
12
|
//#region src/internal/script/analyze.ts
|
|
@@ -33,6 +34,7 @@ function createVueScriptAnalysis(stats) {
|
|
|
33
34
|
directBindings: /* @__PURE__ */ new Set(),
|
|
34
35
|
gtComponentFactories: /* @__PURE__ */ new Set(),
|
|
35
36
|
gtContainerFactories: /* @__PURE__ */ new Set(),
|
|
37
|
+
hasGTSourceReference: false,
|
|
36
38
|
possibleGTContainers: /* @__PURE__ */ new Set(),
|
|
37
39
|
possibleStaticStrings: /* @__PURE__ */ new Map(),
|
|
38
40
|
staticValues: /* @__PURE__ */ new Map(),
|
|
@@ -81,6 +83,7 @@ function collectVueScriptImports(source, language, analysis) {
|
|
|
81
83
|
/** Extracts calls and component bindings from one padded Vue script block. */
|
|
82
84
|
function parseVueScript(source, language, context, templateBindings, exposeToTemplate, analysis = createVueScriptAnalysis(), analyzeOptionsApi = true) {
|
|
83
85
|
if (!source.trim()) return true;
|
|
86
|
+
const initialErrorCount = context.errors.length;
|
|
84
87
|
let ast;
|
|
85
88
|
try {
|
|
86
89
|
ast = parseScriptAst(source, language);
|
|
@@ -121,8 +124,14 @@ function parseVueScript(source, language, context, templateBindings, exposeToTem
|
|
|
121
124
|
if (state.activeTranslationFunctions.size > 0 && resolveKnownCallTargetWithoutParameterSubstitutions(path.node.callee, path.scope, path.node.start ?? Number.POSITIVE_INFINITY, state).value?.type === "string") return;
|
|
122
125
|
const vueHelper = readImportedFunctionName(path.node.callee, path.scope, "vue", state);
|
|
123
126
|
const firstArgument = path.node.arguments[0];
|
|
124
|
-
if (vueHelper && ["createVNode", "h"].includes(vueHelper) && firstArgument && firstArgument.type !== "ArgumentPlaceholder" && firstArgument.type !== "SpreadElement" && expressionContainsGTReference(firstArgument, path.scope, state))
|
|
125
|
-
|
|
127
|
+
if (vueHelper && ["createVNode", "h"].includes(vueHelper) && firstArgument && firstArgument.type !== "ArgumentPlaceholder" && firstArgument.type !== "SpreadElement" && expressionContainsGTReference(firstArgument, path.scope, state)) {
|
|
128
|
+
state.analysis.hasGTSourceReference = true;
|
|
129
|
+
addVueError(context, consumerLocation, "Found an unsupported gt-vue <T> component in a Vue render function", "Move the rich translation into a Vue single-file component template");
|
|
130
|
+
}
|
|
131
|
+
if (vueHelper === "defineAsyncComponent" && firstArgument && firstArgument.type !== "ArgumentPlaceholder" && firstArgument.type !== "SpreadElement" && expressionContainsGTReference(firstArgument, path.scope, state)) {
|
|
132
|
+
state.analysis.hasGTSourceReference = true;
|
|
133
|
+
addVueError(context, consumerLocation, "Could not statically extract a gt-vue <T> component behind defineAsyncComponent()", "Use a direct gt-vue component binding in the Vue template");
|
|
134
|
+
}
|
|
126
135
|
const callTarget = resolveKnownCallTargetAtPosition(path.node.callee, path.scope, path.node.start ?? Number.POSITIVE_INFINITY, state);
|
|
127
136
|
const value = callTarget.value;
|
|
128
137
|
if (value?.type !== "string") {
|
|
@@ -133,6 +142,7 @@ function parseVueScript(source, language, context, templateBindings, exposeToTem
|
|
|
133
142
|
processForwardedTranslationCalls(path, consumerLocation);
|
|
134
143
|
return;
|
|
135
144
|
}
|
|
145
|
+
state.analysis.hasGTSourceReference = true;
|
|
136
146
|
processVueStringCall(path.node, value.kind, consumerLocation, context, (node) => {
|
|
137
147
|
if (!node) return { ok: false };
|
|
138
148
|
const materialized = materializeParameterExpression(node, path.scope, state);
|
|
@@ -172,16 +182,20 @@ function parseVueScript(source, language, context, templateBindings, exposeToTem
|
|
|
172
182
|
OptionalCallExpression: processCall,
|
|
173
183
|
TaggedTemplateExpression(path) {
|
|
174
184
|
if (resolveKnownExpression(path.node.tag, path.scope, state, /* @__PURE__ */ new Set())?.type !== "string") return;
|
|
185
|
+
state.analysis.hasGTSourceReference = true;
|
|
175
186
|
addVueError(context, babelLocation(path.node.loc), "Found an unsupported tagged template translation in gt-vue", "Call the translation function with a string literal instead");
|
|
176
187
|
},
|
|
177
188
|
JSXElement(path) {
|
|
178
189
|
const value = resolveVueJSXElementIdentity(path.node.openingElement.name, path.scope, jsxAnalysis);
|
|
190
|
+
if (value?.type === "component") state.analysis.hasGTSourceReference = true;
|
|
179
191
|
if (value?.type === "component" && (value.name === "Var" || value.name === "Num" || value.name === "DateTime" || value.name === "Currency")) validateVueJSXVariableComponent(path.node, value.name, context);
|
|
180
192
|
if (value?.type !== "component" || value.name !== "T") return;
|
|
181
193
|
if (isNestedInVueJSXTranslation(path, jsxAnalysis)) return;
|
|
182
194
|
extractVueJSXTranslation(path, context, jsxAnalysis);
|
|
183
195
|
}
|
|
184
196
|
});
|
|
197
|
+
if (state.unsupportedDynamicGTReference && context.errors.length === initialErrorCount) addVueError(context, void 0, "Could not statically resolve possible gt-vue string function alias from a dynamic import", "Use a static gt-vue import so translation ownership can be extracted deterministically");
|
|
198
|
+
if (state.unsupportedMalformedGTReference && context.errors.length === initialErrorCount) addVueError(context, void 0, "Could not statically resolve a gt-vue reference imported through a malformed local module", "Fix the local module syntax so translation ownership can be extracted deterministically");
|
|
185
199
|
return true;
|
|
186
200
|
}
|
|
187
201
|
/** Indexes Babel's lexical scopes so deferred function analysis stays exact. */
|
|
@@ -234,6 +248,8 @@ function createScriptState(ast, analysis) {
|
|
|
234
248
|
transformArrayEntries: /* @__PURE__ */ new Map(),
|
|
235
249
|
transformArrayEntriesInProgress: /* @__PURE__ */ new Set(),
|
|
236
250
|
uncertainTranslationHelperBindings: /* @__PURE__ */ new Set(),
|
|
251
|
+
unsupportedDynamicGTReference: false,
|
|
252
|
+
unsupportedMalformedGTReference: false,
|
|
237
253
|
unsafeMutableNamespaceSources: /* @__PURE__ */ new Set()
|
|
238
254
|
};
|
|
239
255
|
traverse(ast, { enter(path) {
|
|
@@ -281,8 +297,9 @@ function memberChainWrites(memberPath) {
|
|
|
281
297
|
function collectImports(ast, state, importerFile = state.analysis.entryFile) {
|
|
282
298
|
traverse(ast, {
|
|
283
299
|
ImportDeclaration(path) {
|
|
284
|
-
if (path.node.importKind
|
|
300
|
+
if (isTypeOnlyImportKind(path.node.importKind)) return;
|
|
285
301
|
const source = path.node.source.value;
|
|
302
|
+
if (source === "gt-vue" && hasRuntimeImport(path.node) && importerFile === state.analysis.entryFile) state.analysis.hasGTSourceReference = true;
|
|
286
303
|
if (source !== "gt-vue" && source !== "vue") {
|
|
287
304
|
registerLocalImportDeclaration(path.node, path.scope, importerFile, state);
|
|
288
305
|
return;
|
|
@@ -297,16 +314,32 @@ function collectImports(ast, state, importerFile = state.analysis.entryFile) {
|
|
|
297
314
|
}, specifierPath.scope, state);
|
|
298
315
|
continue;
|
|
299
316
|
}
|
|
300
|
-
if (specifier.type !== "ImportSpecifier" || specifier.importKind
|
|
317
|
+
if (specifier.type !== "ImportSpecifier" || isTypeOnlyImportKind(specifier.importKind)) continue;
|
|
301
318
|
const value = knownExport(source, specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value);
|
|
302
319
|
if (value) registerImport(specifier.local.name, value, specifierPath.scope, state);
|
|
303
320
|
}
|
|
304
321
|
},
|
|
322
|
+
ExportNamedDeclaration(path) {
|
|
323
|
+
if (path.node.exportKind === "type" || !path.node.source || importerFile !== state.analysis.entryFile) return;
|
|
324
|
+
const exportNames = path.node.specifiers.flatMap((specifier) => {
|
|
325
|
+
if (specifier.type === "ExportSpecifier" && isTypeOnlyImportKind(specifier.exportKind)) return [];
|
|
326
|
+
if (specifier.type === "ExportNamespaceSpecifier") return ["*"];
|
|
327
|
+
if (specifier.type !== "ExportSpecifier") return [];
|
|
328
|
+
return [specifier.local.name];
|
|
329
|
+
});
|
|
330
|
+
recordRuntimeReexport(path.node.source.value, exportNames, importerFile, state);
|
|
331
|
+
},
|
|
332
|
+
ExportAllDeclaration(path) {
|
|
333
|
+
if (path.node.exportKind === "type" || importerFile !== state.analysis.entryFile) return;
|
|
334
|
+
recordRuntimeReexport(path.node.source.value, ["*"], importerFile, state);
|
|
335
|
+
},
|
|
305
336
|
TSImportEqualsDeclaration(path) {
|
|
337
|
+
if (path.node.importKind === "type") return;
|
|
306
338
|
const reference = path.node.moduleReference;
|
|
307
339
|
if (reference.type !== "TSExternalModuleReference" || reference.expression.type !== "StringLiteral") return;
|
|
308
340
|
const source = reference.expression.value;
|
|
309
341
|
if (source !== "gt-vue" && source !== "vue") return;
|
|
342
|
+
if (source === "gt-vue" && importerFile === state.analysis.entryFile) state.analysis.hasGTSourceReference = true;
|
|
310
343
|
registerImport(path.node.id.name, {
|
|
311
344
|
type: "namespace",
|
|
312
345
|
source,
|
|
@@ -321,11 +354,38 @@ function collectImports(ast, state, importerFile = state.analysis.entryFile) {
|
|
|
321
354
|
}
|
|
322
355
|
const namespace = readRequireNamespace(path.node.init, path.scope);
|
|
323
356
|
if (!namespace) return;
|
|
357
|
+
if (namespace.source === "gt-vue" && importerFile === state.analysis.entryFile) state.analysis.hasGTSourceReference = true;
|
|
324
358
|
registerRequirePattern(path.node.id, namespace, path.scope, state);
|
|
325
359
|
}
|
|
326
360
|
});
|
|
327
361
|
propagateUncertainTranslationHelperAliases(ast, state);
|
|
328
362
|
}
|
|
363
|
+
/** Marks only runtime re-exports statically connected to gt-vue. */
|
|
364
|
+
function recordRuntimeReexport(source, exportNames, importerFile, state) {
|
|
365
|
+
if (!importerFile || exportNames.length === 0) return;
|
|
366
|
+
if (source === "gt-vue") {
|
|
367
|
+
state.analysis.hasGTSourceReference = true;
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (source === "vue" || isKnownNonVueGTRuntime(source)) return;
|
|
371
|
+
const resolver = state.analysis.localModules;
|
|
372
|
+
const modulePath = resolver?.resolveModule(importerFile, source);
|
|
373
|
+
if (!resolver || !modulePath || !resolver.isProjectModule(modulePath)) return;
|
|
374
|
+
if ((exportNames.includes("*") ? [
|
|
375
|
+
...COMPONENT_IMPORTS,
|
|
376
|
+
"msg",
|
|
377
|
+
"useGT",
|
|
378
|
+
"useMessages"
|
|
379
|
+
] : exportNames).some((name) => resolver.hasGTExportReference(modulePath, name))) state.analysis.hasGTSourceReference = true;
|
|
380
|
+
}
|
|
381
|
+
/** Returns whether an import causes a runtime module reference. */
|
|
382
|
+
function hasRuntimeImport(declaration) {
|
|
383
|
+
return declaration.specifiers.length === 0 || declaration.specifiers.some((specifier) => specifier.type !== "ImportSpecifier" || !isTypeOnlyImportKind(specifier.importKind));
|
|
384
|
+
}
|
|
385
|
+
/** Returns whether Babel classified an ESM binding as type-only. */
|
|
386
|
+
function isTypeOnlyImportKind(kind) {
|
|
387
|
+
return kind === "type" || kind === "typeof";
|
|
388
|
+
}
|
|
329
389
|
/** Retains unresolved-helper provenance through simple immutable aliases. */
|
|
330
390
|
function propagateUncertainTranslationHelperAliases(ast, state) {
|
|
331
391
|
const candidates = [];
|
|
@@ -371,18 +431,26 @@ function readDynamicImport(node) {
|
|
|
371
431
|
/** Marks GT-shaped values selected from a dynamic namespace as unresolved. */
|
|
372
432
|
function recordDynamicImportPattern(pattern, source, scope, importerFile, state) {
|
|
373
433
|
if (pattern.type === "VoidPattern") return;
|
|
434
|
+
if (source && isKnownNonVueGTRuntime(source)) return;
|
|
435
|
+
if (source === "gt-vue" && importerFile === state.analysis.entryFile) {
|
|
436
|
+
state.analysis.hasGTSourceReference = true;
|
|
437
|
+
state.unsupportedDynamicGTReference = true;
|
|
438
|
+
}
|
|
374
439
|
const resolver = state.analysis.localModules;
|
|
375
440
|
const modulePath = source && source !== "gt-vue" && source !== "vue" && importerFile ? resolver?.resolveModule(importerFile, source) : void 0;
|
|
376
441
|
if (source === "vue") return;
|
|
377
442
|
if (source && source !== "gt-vue" && !modulePath) return;
|
|
443
|
+
if (modulePath && resolver && !resolver.isProjectModule(modulePath)) return;
|
|
378
444
|
if (pattern.type === "Identifier") {
|
|
379
|
-
if (modulePath && resolver)
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
445
|
+
if (modulePath && resolver) {
|
|
446
|
+
const binding = scope.getBinding(pattern.name);
|
|
447
|
+
for (const exportName of [
|
|
448
|
+
...COMPONENT_IMPORTS,
|
|
449
|
+
"msg",
|
|
450
|
+
"useGT",
|
|
451
|
+
"useMessages"
|
|
452
|
+
]) recordDynamicImportBinding(appendTemplatePath(pattern.name, exportName), exportName, modulePath, state, bindingReferencesNamespaceMember(binding, exportName, state));
|
|
453
|
+
} else {
|
|
386
454
|
for (const component of COMPONENT_IMPORTS) {
|
|
387
455
|
const path = appendTemplatePath(pattern.name, component);
|
|
388
456
|
state.analysis.uncertainComponents.add(path);
|
|
@@ -401,61 +469,102 @@ function recordDynamicImportPattern(pattern, source, scope, importerFile, state)
|
|
|
401
469
|
if (property.type !== "ObjectProperty") continue;
|
|
402
470
|
const exportedName = readPropertyKey(property);
|
|
403
471
|
const localName = readPatternIdentifier(property.value);
|
|
404
|
-
if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state);
|
|
472
|
+
if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state, importerFile === state.analysis.entryFile);
|
|
405
473
|
else recordUnresolvedGTShapedBinding(localName, exportedName, state);
|
|
406
474
|
}
|
|
407
475
|
for (const property of pattern.properties) {
|
|
408
476
|
if (property.type !== "ObjectProperty" || !property.computed) continue;
|
|
409
477
|
const exportedName = readResolvedPropertyKey(property, scope, state);
|
|
410
478
|
const localName = readPatternIdentifier(property.value);
|
|
411
|
-
if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state);
|
|
479
|
+
if (exportedName && localName) if (modulePath) recordDynamicImportBinding(localName, exportedName, modulePath, state, importerFile === state.analysis.entryFile);
|
|
412
480
|
else recordUnresolvedGTShapedBinding(localName, exportedName, state);
|
|
413
481
|
}
|
|
414
482
|
}
|
|
483
|
+
/** Returns whether one namespace binding is used through a static member. */
|
|
484
|
+
function bindingReferencesNamespaceMember(binding, memberName, state, seen = /* @__PURE__ */ new Set()) {
|
|
485
|
+
if (!binding || seen.has(binding)) return false;
|
|
486
|
+
const nextSeen = new Set(seen).add(binding);
|
|
487
|
+
return Boolean(binding.referencePaths.some((referencePath) => {
|
|
488
|
+
let reference = referencePath;
|
|
489
|
+
while (reference.parentPath && unwrapExpression(reference.parentPath.node) === reference.node) reference = reference.parentPath;
|
|
490
|
+
const parent = reference.parentPath;
|
|
491
|
+
if (parent?.isMemberExpression() || parent?.isOptionalMemberExpression()) return parent.node.object === reference.node && readResolvedMemberProperty(parent.node, parent.scope, state) === memberName;
|
|
492
|
+
if (parent?.isJSXMemberExpression()) return parent.node.object === reference.node && parent.node.property.name === memberName;
|
|
493
|
+
if (parent?.isVariableDeclarator() && parent.node.init === reference.node) {
|
|
494
|
+
if (parent.node.id.type === "Identifier") return bindingReferencesNamespaceMember(parent.scope.getBinding(parent.node.id.name), memberName, state, nextSeen);
|
|
495
|
+
if (parent.node.id.type === "ObjectPattern") return parent.node.id.properties.some((property) => property.type === "RestElement" || property.type === "ObjectProperty" && readResolvedPropertyKey(property, parent.scope, state) === memberName);
|
|
496
|
+
}
|
|
497
|
+
if (parent?.isCallExpression() || parent?.isNewExpression() || parent?.isReturnStatement() || parent?.isSpreadElement() || parent?.isArrayExpression() || parent?.isObjectProperty()) return true;
|
|
498
|
+
return false;
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
415
501
|
/** Marks only GT roles proven reachable from one static dynamic import. */
|
|
416
|
-
function recordDynamicImportBinding(localName, exportName, modulePath, state) {
|
|
502
|
+
function recordDynamicImportBinding(localName, exportName, modulePath, state, establishesEntryProvenance) {
|
|
417
503
|
const resolution = state.analysis.localModules?.resolveExport(modulePath, exportName);
|
|
418
504
|
if (!resolution || resolution.status === "absent") return;
|
|
419
505
|
if (resolution.status !== "resolved") {
|
|
420
|
-
|
|
506
|
+
if (resolution.status === "invalid" && materializeRecoveredOrdinaryResolution(resolution, state) !== void 0) return;
|
|
507
|
+
if (establishesEntryProvenance && resolution.status === "invalid" && resolution.hasGTSourceReference) {
|
|
508
|
+
state.analysis.hasGTSourceReference = true;
|
|
509
|
+
state.unsupportedDynamicGTReference = true;
|
|
510
|
+
state.unsupportedMalformedGTReference = true;
|
|
511
|
+
}
|
|
512
|
+
if (resolution.status === "invalid" && resolution.hasGTSourceReference) recordInvalidGTResolution(localName, resolution, state);
|
|
513
|
+
else recordUnresolvedGTShapedBinding(localName, exportName, state);
|
|
421
514
|
return;
|
|
422
515
|
}
|
|
423
|
-
|
|
516
|
+
const materialized = materializeLocalExport(resolution.target, state);
|
|
517
|
+
if (establishesEntryProvenance && materialized.hasGTSourceReference) {
|
|
518
|
+
state.analysis.hasGTSourceReference = true;
|
|
519
|
+
state.unsupportedDynamicGTReference = true;
|
|
520
|
+
}
|
|
521
|
+
recordMaterializedLocalUncertainty(localName, materialized, state, true);
|
|
424
522
|
}
|
|
425
523
|
/** Resolves one ESM import through a local, read-only source module graph. */
|
|
426
524
|
function registerLocalImportDeclaration(declaration, scope, importerFile, state) {
|
|
427
525
|
const resolver = state.analysis.localModules;
|
|
428
526
|
const source = declaration.source.value;
|
|
527
|
+
if (isKnownNonVueGTRuntime(source)) return;
|
|
429
528
|
const modulePath = resolver && importerFile ? resolver.resolveModule(importerFile, source) : void 0;
|
|
430
|
-
if (
|
|
529
|
+
if (modulePath && resolver && !resolver.isProjectModule(modulePath)) return;
|
|
530
|
+
if (!resolver || !modulePath) {
|
|
431
531
|
recordUnresolvedTranslationHelperImports(declaration, scope, state);
|
|
432
532
|
if (source.startsWith(".") || source.startsWith("/") || resolver?.hasCustomResolver) recordUnresolvedGTShapedImports(declaration, state);
|
|
433
533
|
return;
|
|
434
534
|
}
|
|
435
535
|
for (const specifier of declaration.specifiers) {
|
|
436
|
-
if (specifier.type === "ImportSpecifier" && specifier.importKind
|
|
536
|
+
if (specifier.type === "ImportSpecifier" && isTypeOnlyImportKind(specifier.importKind)) continue;
|
|
437
537
|
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
438
538
|
const value = {
|
|
439
539
|
type: "local-namespace",
|
|
440
540
|
modulePath
|
|
441
541
|
};
|
|
442
542
|
registerImport(specifier.local.name, value, scope, state);
|
|
443
|
-
if (importerFile === state.analysis.entryFile) recordLocalNamespaceMembers(specifier.local.name, modulePath, state);
|
|
543
|
+
if (importerFile === state.analysis.entryFile) recordLocalNamespaceMembers(specifier.local.name, modulePath, state, scope.getBinding(specifier.local.name));
|
|
444
544
|
continue;
|
|
445
545
|
}
|
|
446
546
|
const exportName = specifier.type === "ImportDefaultSpecifier" ? "default" : specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
|
|
447
547
|
const resolution = resolver.resolveExport(modulePath, exportName);
|
|
548
|
+
let materialized;
|
|
448
549
|
if (resolution.status !== "resolved") {
|
|
449
|
-
|
|
450
|
-
if (
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
550
|
+
if (resolution.status === "invalid") materialized = materializeRecoveredOrdinaryResolution(resolution, state, true);
|
|
551
|
+
if (!materialized) {
|
|
552
|
+
if (importerFile === state.analysis.entryFile && resolution.status === "invalid" && resolution.hasGTSourceReference) {
|
|
553
|
+
state.analysis.hasGTSourceReference = true;
|
|
554
|
+
state.unsupportedMalformedGTReference = true;
|
|
555
|
+
}
|
|
556
|
+
recordUncertainTranslationHelperBinding(specifier.local.name, scope, state);
|
|
557
|
+
if (resolution.status === "ambiguous") recordAmbiguousLocalBinding(specifier.local.name, state);
|
|
558
|
+
else if (resolution.status === "invalid" && resolution.hasGTSourceReference) recordInvalidGTResolution(specifier.local.name, resolution, state);
|
|
559
|
+
else recordUnresolvedGTShapedBinding(specifier.local.name, exportName, state);
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
} else materialized = materializeLocalExport(resolution.target, state);
|
|
563
|
+
if (importerFile === state.analysis.entryFile && materialized.hasGTSourceReference) state.analysis.hasGTSourceReference = true;
|
|
455
564
|
const binding = scope.getBinding(specifier.local.name);
|
|
456
565
|
if (materialized.value) {
|
|
457
566
|
registerImport(specifier.local.name, materialized.value, scope, state);
|
|
458
|
-
if (materialized.value.type === "local-namespace" && importerFile === state.analysis.entryFile) recordLocalNamespaceMembers(specifier.local.name, materialized.value.modulePath, state);
|
|
567
|
+
if (materialized.value.type === "local-namespace" && importerFile === state.analysis.entryFile) recordLocalNamespaceMembers(specifier.local.name, materialized.value.modulePath, state, binding);
|
|
459
568
|
}
|
|
460
569
|
if (binding && materialized.callable) state.localCallableBindings.set(binding, materialized.callable);
|
|
461
570
|
recordMaterializedLocalUncertainty(specifier.local.name, materialized, state);
|
|
@@ -472,25 +581,35 @@ function attachLocalModule(record, state) {
|
|
|
472
581
|
} });
|
|
473
582
|
collectImports(record.ast, state, record.filePath);
|
|
474
583
|
}
|
|
475
|
-
/** Converts a graph export into an analyzer identity or callable. */
|
|
476
584
|
function materializeLocalExport(target, state) {
|
|
477
|
-
if (target.type === "external") return {
|
|
478
|
-
if (target.type === "external
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
585
|
+
if (target.type === "ordinary-external") return {};
|
|
586
|
+
if (target.type === "external") return {
|
|
587
|
+
hasGTSourceReference: target.source === "gt-vue",
|
|
588
|
+
value: knownExport(target.source, target.exportName)
|
|
589
|
+
};
|
|
590
|
+
if (target.type === "external-namespace") return {
|
|
591
|
+
hasGTSourceReference: target.source === "gt-vue",
|
|
592
|
+
value: {
|
|
593
|
+
mutable: false,
|
|
594
|
+
source: target.source,
|
|
595
|
+
type: "namespace"
|
|
596
|
+
}
|
|
597
|
+
};
|
|
483
598
|
if (target.type === "namespace") return { value: {
|
|
484
599
|
type: "local-namespace",
|
|
485
600
|
modulePath: target.modulePath
|
|
486
601
|
} };
|
|
487
602
|
attachLocalModule(target.record, state);
|
|
488
|
-
if (target.type === "expression")
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
603
|
+
if (target.type === "expression") {
|
|
604
|
+
const materialized = {
|
|
605
|
+
callable: resolveCalledFunction(target.node, target.record.programScope, state, /* @__PURE__ */ new Set()),
|
|
606
|
+
value: resolveKnownExpression(target.node, target.record.programScope, state, /* @__PURE__ */ new Set()),
|
|
607
|
+
possibleGTComponent: expressionMayProduceComponent(target.node, target.record.programScope, state, /* @__PURE__ */ new Set(), "translation"),
|
|
608
|
+
possibleStringFunction: expressionMayProduceStringFunction(target.node, target.record.programScope, state, /* @__PURE__ */ new Set())
|
|
609
|
+
};
|
|
610
|
+
materialized.hasGTSourceReference = isKnownGTValue(materialized.value);
|
|
611
|
+
return materialized;
|
|
612
|
+
}
|
|
494
613
|
const binding = target.record.programScope.getBinding(target.exportName);
|
|
495
614
|
if (!binding) return {};
|
|
496
615
|
const possibleGTComponent = expressionMayProduceComponent(binding.identifier, target.record.programScope, state, /* @__PURE__ */ new Set(), "translation");
|
|
@@ -500,15 +619,59 @@ function materializeLocalExport(target, state) {
|
|
|
500
619
|
possibleStringFunction,
|
|
501
620
|
unsafeCallable: bindingMayReferenceLocalCallable(binding, state)
|
|
502
621
|
};
|
|
503
|
-
|
|
622
|
+
const materialized = {
|
|
504
623
|
callable: resolveCalledFunction(binding.identifier, target.record.programScope, state, /* @__PURE__ */ new Set()),
|
|
505
624
|
possibleGTComponent,
|
|
506
625
|
possibleStringFunction,
|
|
507
626
|
value: resolveKnownBinding(binding, state, /* @__PURE__ */ new Set())
|
|
508
627
|
};
|
|
628
|
+
materialized.hasGTSourceReference = isKnownGTValue(materialized.value);
|
|
629
|
+
return materialized;
|
|
630
|
+
}
|
|
631
|
+
/** Returns whether an exact analyzer identity came from gt-vue. */
|
|
632
|
+
function isKnownGTValue(value) {
|
|
633
|
+
return value?.type === "component" || value?.type === "hook" || value?.type === "string" || value?.type === "namespace" && value.source === "gt-vue";
|
|
634
|
+
}
|
|
635
|
+
/** Materializes the one ordinary origin proven through a malformed module. */
|
|
636
|
+
function materializeRecoveredOrdinaryResolution(resolution, state, preserveLocalIdentity = false) {
|
|
637
|
+
if (resolution.hasGTSourceReference || resolution.gtExportName || resolution.recoveredTargets?.length !== 1) return;
|
|
638
|
+
const target = resolution.recoveredTargets[0];
|
|
639
|
+
if (target.type === "ordinary-external") return {};
|
|
640
|
+
if (target.type === "external" || target.type === "external-namespace") return target.source === "vue" ? materializeLocalExport(target, state) : void 0;
|
|
641
|
+
if (target.type === "namespace") return void 0;
|
|
642
|
+
const materialized = materializeLocalExport(target, state);
|
|
643
|
+
if (materialized.hasGTSourceReference || materialized.possibleGTComponent || materialized.possibleStringFunction || materialized.unsafeCallable || isKnownGTValue(materialized.value)) return;
|
|
644
|
+
if (localTargetAliasesKnownNonVueRuntime(target)) return materialized;
|
|
645
|
+
return preserveLocalIdentity && materialized.callable && isOrdinaryIdentityFunction(materialized.callable.node) ? materialized : void 0;
|
|
646
|
+
}
|
|
647
|
+
/** Proves a direct immutable alias back to an official non-Vue GT runtime. */
|
|
648
|
+
function localTargetAliasesKnownNonVueRuntime(target) {
|
|
649
|
+
if (target.type === "expression") return expressionAliasesKnownNonVueRuntime(target.node, target.record.programScope, /* @__PURE__ */ new Set());
|
|
650
|
+
const binding = target.record.programScope.getBinding(target.exportName);
|
|
651
|
+
if (!binding) return false;
|
|
652
|
+
const source = getBindingSource(binding);
|
|
653
|
+
if (!source || source.pattern.type !== "Identifier") return false;
|
|
654
|
+
return expressionAliasesKnownNonVueRuntime(source.expression.node, source.expression.scope, new Set([binding]));
|
|
655
|
+
}
|
|
656
|
+
/** Follows only immutable identifier aliases to named or default imports. */
|
|
657
|
+
function expressionAliasesKnownNonVueRuntime(node, scope, seen) {
|
|
658
|
+
const expression = unwrapExpression(node);
|
|
659
|
+
if (expression?.type !== "Identifier") return false;
|
|
660
|
+
const binding = scope.getBinding(expression.name);
|
|
661
|
+
if (!binding || seen.has(binding)) return false;
|
|
662
|
+
const declaration = binding.path.parentPath;
|
|
663
|
+
if (declaration?.isImportDeclaration() && isKnownNonVueGTRuntime(declaration.node.source.value)) return true;
|
|
664
|
+
const source = getBindingSource(binding);
|
|
665
|
+
return Boolean(source && source.pattern.type === "Identifier" && expressionAliasesKnownNonVueRuntime(source.expression.node, source.expression.scope, new Set(seen).add(binding)));
|
|
666
|
+
}
|
|
667
|
+
/** Proves the narrow local helper form without following unknown dependencies. */
|
|
668
|
+
function isOrdinaryIdentityFunction(node) {
|
|
669
|
+
if (node.async || node.generator || node.params.length !== 1 || node.params[0]?.type !== "Identifier") return false;
|
|
670
|
+
const expression = unwrapExpression(node.body.type === "BlockStatement" ? node.body.body.length === 1 && node.body.body[0]?.type === "ReturnStatement" ? node.body.body[0].argument : void 0 : node.body);
|
|
671
|
+
return expression?.type === "Identifier" && expression.name === node.params[0].name;
|
|
509
672
|
}
|
|
510
673
|
/** Makes statically known members of a local namespace visible to templates. */
|
|
511
|
-
function recordLocalNamespaceMembers(localName, modulePath, state) {
|
|
674
|
+
function recordLocalNamespaceMembers(localName, modulePath, state, binding) {
|
|
512
675
|
const resolver = state.analysis.localModules;
|
|
513
676
|
if (!resolver) return;
|
|
514
677
|
const exportNames = new Set([
|
|
@@ -523,8 +686,14 @@ function recordLocalNamespaceMembers(localName, modulePath, state) {
|
|
|
523
686
|
const resolution = resolver.resolveExport(modulePath, exportName);
|
|
524
687
|
if (resolution.status === "absent") continue;
|
|
525
688
|
if (resolution.status !== "resolved") {
|
|
689
|
+
if (resolution.status === "invalid" && materializeRecoveredOrdinaryResolution(resolution, state) !== void 0) continue;
|
|
690
|
+
if (resolution.status === "invalid" && resolution.hasGTSourceReference && bindingReferencesNamespaceMember(binding, exportName, state)) {
|
|
691
|
+
state.analysis.hasGTSourceReference = true;
|
|
692
|
+
state.unsupportedMalformedGTReference = true;
|
|
693
|
+
}
|
|
526
694
|
state.analysis.uncertainTranslationHelpers.add(memberPath);
|
|
527
695
|
if (resolution.status === "ambiguous") recordAmbiguousLocalBinding(memberPath, state);
|
|
696
|
+
else if (resolution.status === "invalid" && resolution.hasGTSourceReference) recordInvalidGTResolution(memberPath, resolution, state);
|
|
528
697
|
else recordUnresolvedGTShapedBinding(memberPath, exportName, state);
|
|
529
698
|
continue;
|
|
530
699
|
}
|
|
@@ -533,6 +702,31 @@ function recordLocalNamespaceMembers(localName, modulePath, state) {
|
|
|
533
702
|
recordMaterializedLocalUncertainty(memberPath, materialized, state);
|
|
534
703
|
}
|
|
535
704
|
}
|
|
705
|
+
/** Retains the original gt-vue role hidden by a malformed re-export alias. */
|
|
706
|
+
function recordInvalidGTResolution(localName, resolution, state) {
|
|
707
|
+
if (resolution.gtExportName === "*") {
|
|
708
|
+
recordUnresolvedGTNamespace(localName, state);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
if (resolution.gtExportName) {
|
|
712
|
+
recordUnresolvedGTShapedBinding(localName, resolution.gtExportName, state);
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
state.analysis.uncertainTranslationHelpers.add(localName);
|
|
716
|
+
}
|
|
717
|
+
/** Marks the GT-shaped members of one unresolved namespace path. */
|
|
718
|
+
function recordUnresolvedGTNamespace(localName, state) {
|
|
719
|
+
for (const component of COMPONENT_IMPORTS) {
|
|
720
|
+
const componentPath = appendTemplatePath(localName, component);
|
|
721
|
+
state.analysis.uncertainComponents.add(componentPath);
|
|
722
|
+
state.analysis.uncertainGTComponents.add(componentPath);
|
|
723
|
+
}
|
|
724
|
+
for (const name of [
|
|
725
|
+
"msg",
|
|
726
|
+
"useGT",
|
|
727
|
+
"useMessages"
|
|
728
|
+
]) state.analysis.uncertainStringFunctions.add(appendTemplatePath(localName, name));
|
|
729
|
+
}
|
|
536
730
|
/** Records unresolved roles only when a local export can actually be GT. */
|
|
537
731
|
function recordMaterializedLocalUncertainty(localName, materialized, state, forceKnownValues = false) {
|
|
538
732
|
if (materialized.possibleGTComponent || forceKnownValues && materialized.value?.type === "component") {
|
|
@@ -552,19 +746,10 @@ function bindingMayReferenceLocalCallable(binding, state) {
|
|
|
552
746
|
function recordUnresolvedGTShapedImports(declaration, state) {
|
|
553
747
|
for (const specifier of declaration.specifiers) {
|
|
554
748
|
if (specifier.type === "ImportNamespaceSpecifier") {
|
|
555
|
-
|
|
556
|
-
const path = appendTemplatePath(specifier.local.name, component);
|
|
557
|
-
state.analysis.uncertainComponents.add(path);
|
|
558
|
-
state.analysis.uncertainGTComponents.add(path);
|
|
559
|
-
}
|
|
560
|
-
for (const name of [
|
|
561
|
-
"msg",
|
|
562
|
-
"useGT",
|
|
563
|
-
"useMessages"
|
|
564
|
-
]) state.analysis.uncertainStringFunctions.add(appendTemplatePath(specifier.local.name, name));
|
|
749
|
+
recordUnresolvedGTNamespace(specifier.local.name, state);
|
|
565
750
|
continue;
|
|
566
751
|
}
|
|
567
|
-
if (specifier.type === "ImportSpecifier" && specifier.importKind
|
|
752
|
+
if (specifier.type === "ImportSpecifier" && isTypeOnlyImportKind(specifier.importKind)) continue;
|
|
568
753
|
const importedName = specifier.type === "ImportDefaultSpecifier" ? specifier.local.name : specifier.imported.type === "Identifier" ? specifier.imported.name : specifier.imported.value;
|
|
569
754
|
recordUnresolvedGTShapedBinding(specifier.local.name, importedName, state);
|
|
570
755
|
}
|
|
@@ -572,7 +757,7 @@ function recordUnresolvedGTShapedImports(declaration, state) {
|
|
|
572
757
|
/** Marks unresolved imports only when a call later passes a translator. */
|
|
573
758
|
function recordUnresolvedTranslationHelperImports(declaration, scope, state) {
|
|
574
759
|
for (const specifier of declaration.specifiers) {
|
|
575
|
-
if (specifier.type === "ImportSpecifier" && specifier.importKind
|
|
760
|
+
if (specifier.type === "ImportSpecifier" && isTypeOnlyImportKind(specifier.importKind)) continue;
|
|
576
761
|
recordUncertainTranslationHelperBinding(specifier.local.name, scope, state);
|
|
577
762
|
}
|
|
578
763
|
}
|
|
@@ -4187,7 +4372,7 @@ function collectTransformArrayEntries(node, scope, state, seen, atPosition = nod
|
|
|
4187
4372
|
ok: true,
|
|
4188
4373
|
value: fallback
|
|
4189
4374
|
};
|
|
4190
|
-
const value = readStaticFromScope(node, scope, /* @__PURE__ */ new Set(), node.end ?? atPosition, state.analysis
|
|
4375
|
+
const value = readStaticFromScope(node, scope, /* @__PURE__ */ new Set(), node.end ?? atPosition, state.analysis);
|
|
4191
4376
|
if (!value.ok || typeof value.value === "bigint") return { ok: false };
|
|
4192
4377
|
try {
|
|
4193
4378
|
const numeric = Number(value.value);
|
|
@@ -4402,7 +4587,7 @@ function collectTransformArrayEntries(node, scope, state, seen, atPosition = nod
|
|
|
4402
4587
|
let entries = collectTransformArrayEntries(callee.object, scope, state, nextSeen, atPosition);
|
|
4403
4588
|
if (!entries) return void 0;
|
|
4404
4589
|
const depthNode = argument(0);
|
|
4405
|
-
const staticDepth = depthNode ? readStaticFromScope(depthNode, scope, /* @__PURE__ */ new Set(), depthNode.end ?? atPosition, state.analysis
|
|
4590
|
+
const staticDepth = depthNode ? readStaticFromScope(depthNode, scope, /* @__PURE__ */ new Set(), depthNode.end ?? atPosition, state.analysis) : {
|
|
4406
4591
|
ok: true,
|
|
4407
4592
|
value: 1
|
|
4408
4593
|
};
|
|
@@ -4640,35 +4825,24 @@ function memberChainCanMutate(memberPath, allowCalls) {
|
|
|
4640
4825
|
}
|
|
4641
4826
|
return true;
|
|
4642
4827
|
}
|
|
4643
|
-
function readStaticFromScope(node, scope, seen, atPosition, analysis
|
|
4828
|
+
function readStaticFromScope(node, scope, seen, atPosition, analysis) {
|
|
4644
4829
|
return readStaticPrimitive(node, (identifier) => {
|
|
4645
4830
|
const binding = scope.getBinding(identifier.name);
|
|
4646
4831
|
if (!binding) {
|
|
4647
|
-
const value = analysis?.staticValues.get(identifier.name);
|
|
4648
4832
|
if (analysis?.staticValues.has(identifier.name)) return {
|
|
4649
4833
|
ok: true,
|
|
4650
|
-
value
|
|
4651
|
-
};
|
|
4652
|
-
if (allowNumericGlobals && identifier.name === "Infinity") return {
|
|
4653
|
-
ok: true,
|
|
4654
|
-
value: Number.POSITIVE_INFINITY
|
|
4834
|
+
value: analysis.staticValues.get(identifier.name)
|
|
4655
4835
|
};
|
|
4656
|
-
|
|
4657
|
-
ok: true,
|
|
4658
|
-
value: NaN
|
|
4659
|
-
};
|
|
4660
|
-
return { ok: false };
|
|
4836
|
+
return readStaticGlobalPrimitive(identifier.name);
|
|
4661
4837
|
}
|
|
4662
4838
|
const cacheable = analysis !== void 0 && atPosition === Number.POSITIVE_INFINITY;
|
|
4663
|
-
const cached = cacheable ? staticBindingResults.get(analysis)?.get(binding)
|
|
4839
|
+
const cached = cacheable ? staticBindingResults.get(analysis)?.get(binding) : void 0;
|
|
4664
4840
|
if (cached) return cached;
|
|
4665
4841
|
if (seen.has(binding)) return { ok: false };
|
|
4666
4842
|
if (cacheable) {
|
|
4667
|
-
const active = staticBindingsInProgress.get(analysis) ?? /* @__PURE__ */ new
|
|
4668
|
-
|
|
4669
|
-
|
|
4670
|
-
modes.add(allowNumericGlobals);
|
|
4671
|
-
active.set(binding, modes);
|
|
4843
|
+
const active = staticBindingsInProgress.get(analysis) ?? /* @__PURE__ */ new Set();
|
|
4844
|
+
if (active.has(binding)) return { ok: false };
|
|
4845
|
+
active.add(binding);
|
|
4672
4846
|
staticBindingsInProgress.set(analysis, active);
|
|
4673
4847
|
}
|
|
4674
4848
|
const nextSeen = new Set(seen);
|
|
@@ -4676,22 +4850,15 @@ function readStaticFromScope(node, scope, seen, atPosition, analysis, allowNumer
|
|
|
4676
4850
|
try {
|
|
4677
4851
|
const source = getBindingSource(binding);
|
|
4678
4852
|
const expression = source && (source.expression.node.end ?? 0) <= atPosition ? selectPatternExpression(source.pattern, source.expression.node, binding.identifier.name, source.expression.scope, source.expression.node.end ?? Number.POSITIVE_INFINITY) : void 0;
|
|
4679
|
-
const result = expression ? readStaticFromScope(expression.node, expression.scope, nextSeen, atPosition, analysis
|
|
4853
|
+
const result = expression ? readStaticFromScope(expression.node, expression.scope, nextSeen, atPosition, analysis) : { ok: false };
|
|
4680
4854
|
if (cacheable) {
|
|
4681
4855
|
const results = staticBindingResults.get(analysis) ?? /* @__PURE__ */ new Map();
|
|
4682
|
-
|
|
4683
|
-
modes.set(allowNumericGlobals, result);
|
|
4684
|
-
results.set(binding, modes);
|
|
4856
|
+
results.set(binding, result);
|
|
4685
4857
|
staticBindingResults.set(analysis, results);
|
|
4686
4858
|
}
|
|
4687
4859
|
return result;
|
|
4688
4860
|
} finally {
|
|
4689
|
-
if (cacheable)
|
|
4690
|
-
const active = staticBindingsInProgress.get(analysis);
|
|
4691
|
-
const modes = active?.get(binding);
|
|
4692
|
-
modes?.delete(allowNumericGlobals);
|
|
4693
|
-
if (modes?.size === 0) active?.delete(binding);
|
|
4694
|
-
}
|
|
4861
|
+
if (cacheable) staticBindingsInProgress.get(analysis)?.delete(binding);
|
|
4695
4862
|
}
|
|
4696
4863
|
});
|
|
4697
4864
|
}
|