@generaltranslation/vue-extractor 0.0.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.
Files changed (62) hide show
  1. package/LICENSE.md +105 -0
  2. package/dist/config.d.ts +2 -0
  3. package/dist/config.js +2 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.js +2 -0
  6. package/dist/internal/compilerAst.d.ts +43 -0
  7. package/dist/internal/compilerAst.js +77 -0
  8. package/dist/internal/compilerAst.js.map +1 -0
  9. package/dist/internal/config/resolveVueCompilerOptions.d.ts +23 -0
  10. package/dist/internal/config/resolveVueCompilerOptions.js +987 -0
  11. package/dist/internal/config/resolveVueCompilerOptions.js.map +1 -0
  12. package/dist/internal/extractFromVueSource.d.ts +9 -0
  13. package/dist/internal/extractFromVueSource.js +332 -0
  14. package/dist/internal/extractFromVueSource.js.map +1 -0
  15. package/dist/internal/script/analyze.d.ts +13 -0
  16. package/dist/internal/script/analyze.js +4761 -0
  17. package/dist/internal/script/analyze.js.map +1 -0
  18. package/dist/internal/script/jsx.d.ts +36 -0
  19. package/dist/internal/script/jsx.js +667 -0
  20. package/dist/internal/script/jsx.js.map +1 -0
  21. package/dist/internal/script/knownValues.d.ts +14 -0
  22. package/dist/internal/script/knownValues.js +148 -0
  23. package/dist/internal/script/knownValues.js.map +1 -0
  24. package/dist/internal/script/localModules.d.ts +80 -0
  25. package/dist/internal/script/localModules.js +364 -0
  26. package/dist/internal/script/localModules.js.map +1 -0
  27. package/dist/internal/script/model.d.ts +317 -0
  28. package/dist/internal/script/model.js +1 -0
  29. package/dist/internal/script/parser.d.ts +3 -0
  30. package/dist/internal/script/parser.js +21 -0
  31. package/dist/internal/script/parser.js.map +1 -0
  32. package/dist/internal/script/replay.d.ts +53 -0
  33. package/dist/internal/script/replay.js +1611 -0
  34. package/dist/internal/script/replay.js.map +1 -0
  35. package/dist/internal/script/snapshot.d.ts +25 -0
  36. package/dist/internal/script/snapshot.js +293 -0
  37. package/dist/internal/script/snapshot.js.map +1 -0
  38. package/dist/internal/script/syntax.d.ts +21 -0
  39. package/dist/internal/script/syntax.js +46 -0
  40. package/dist/internal/script/syntax.js.map +1 -0
  41. package/dist/internal/script.d.ts +2 -0
  42. package/dist/internal/script.js +2 -0
  43. package/dist/internal/stringCalls.d.ts +7 -0
  44. package/dist/internal/stringCalls.js +82 -0
  45. package/dist/internal/stringCalls.js.map +1 -0
  46. package/dist/internal/template.d.ts +4 -0
  47. package/dist/internal/template.js +2198 -0
  48. package/dist/internal/template.js.map +1 -0
  49. package/dist/internal/templatePath.d.ts +12 -0
  50. package/dist/internal/templatePath.js +23 -0
  51. package/dist/internal/templatePath.js.map +1 -0
  52. package/dist/internal/types.d.ts +69 -0
  53. package/dist/internal/types.js +1 -0
  54. package/dist/internal/utils.d.ts +19 -0
  55. package/dist/internal/utils.js +149 -0
  56. package/dist/internal/utils.js.map +1 -0
  57. package/dist/internal/vueCompiler.d.ts +35 -0
  58. package/dist/internal/vueCompiler.js +320 -0
  59. package/dist/internal/vueCompiler.js.map +1 -0
  60. package/dist/types.d.ts +80 -0
  61. package/dist/types.js +1 -0
  62. package/package.json +78 -0
@@ -0,0 +1,293 @@
1
+ import { readStaticPrimitive, unwrapExpression } from "../utils.js";
2
+ //#region src/internal/script/snapshot.ts
3
+ /** Creates the conservative finite-container snapshot analyzer. */
4
+ function createSnapshotAnalysis({ readonlyArrayTransforms: READONLY_ARRAY_TRANSFORMS, collectObjectEntries, collectTransformArrayEntries, memberChainIsReadOnly, readBindingContainerWritePolicy, readResolvedMemberPath, readResolvedMemberProperty, readStaticFromScope, resolveKnownExpression, resolveVueTemplateContainerSources }) {
5
+ /** Copies a replay snapshot before another binding applies its own writes. */
6
+ function cloneFinalContainerSnapshot(snapshot) {
7
+ return snapshot.kind === "array" ? {
8
+ kind: "array",
9
+ entries: [...snapshot.entries]
10
+ } : {
11
+ kind: "object",
12
+ entries: new Map(snapshot.entries)
13
+ };
14
+ }
15
+ /** Reads an exact finite container without assuming arbitrary calls are pure. */
16
+ function readFinalContainerSnapshot(node, scope, state) {
17
+ if (state.analysis.stats) state.analysis.stats.finalContainerSnapshotReads += 1;
18
+ if (resolveKnownExpression(node, scope, state, /* @__PURE__ */ new Set())) return void 0;
19
+ const array = collectTransformArrayEntries(node, scope, state, /* @__PURE__ */ new Set(), Number.POSITIVE_INFINITY);
20
+ if (array) return {
21
+ kind: "array",
22
+ entries: [...array]
23
+ };
24
+ const object = collectObjectEntries(node, scope, /* @__PURE__ */ new Set(), Number.POSITIVE_INFINITY, state);
25
+ if (!object.unknownAll && object.unknownNames.size === 0) return {
26
+ kind: "object",
27
+ entries: new Map(object.entries)
28
+ };
29
+ const sources = resolveVueTemplateContainerSources(node, scope, state);
30
+ if (sources?.length !== 1) return void 0;
31
+ const sourceExpression = unwrapExpression(sources[0].node);
32
+ if (sourceExpression?.type === "Identifier") {
33
+ const sourceBinding = sources[0].scope.getBinding(sourceExpression.name);
34
+ if (sourceBinding) {
35
+ const finalSource = readDefiniteFinalContainerSnapshot(sourceBinding, state);
36
+ if (finalSource) return finalSource;
37
+ }
38
+ }
39
+ return readFinalContainerSnapshot(sources[0].node, sources[0].scope, state);
40
+ }
41
+ /** Determines whether a finite expression definitely contains T anywhere. */
42
+ function readDefiniteExpressionHasGT(node, scope, state, seen) {
43
+ const expression = unwrapExpression(node);
44
+ if (!expression || seen.has(expression)) return void 0;
45
+ const nextSeen = new Set(seen).add(expression);
46
+ const known = resolveKnownExpression(expression, scope, state, /* @__PURE__ */ new Set());
47
+ if (known) return known.type === "component" ? known.name === "T" : false;
48
+ if (readStaticFromScope(expression, scope, /* @__PURE__ */ new Set(), expression.end ?? Number.POSITIVE_INFINITY, state.analysis).ok) return false;
49
+ if (expression.type === "Identifier" && !scope.getBinding(expression.name) && [
50
+ "Array",
51
+ "BigInt",
52
+ "Boolean",
53
+ "Date",
54
+ "Error",
55
+ "Map",
56
+ "Number",
57
+ "Object",
58
+ "RegExp",
59
+ "Set",
60
+ "String",
61
+ "Symbol",
62
+ "WeakMap",
63
+ "WeakSet",
64
+ "undefined"
65
+ ].includes(expression.name)) return false;
66
+ const snapshot = readFinalContainerSnapshot(expression, scope, state);
67
+ if (!snapshot) return void 0;
68
+ const values = snapshot.kind === "array" ? snapshot.entries.filter((entry) => entry !== void 0) : [...snapshot.entries.values()];
69
+ let unknown = false;
70
+ for (const value of values) {
71
+ const hasGT = readDefiniteExpressionHasGT(value.node, value.scope, state, nextSeen);
72
+ if (hasGT) return true;
73
+ if (hasGT === void 0) unknown = true;
74
+ }
75
+ return unknown ? void 0 : false;
76
+ }
77
+ /** Coerces a statically known array index with JavaScript integer semantics. */
78
+ function readDefiniteArrayInteger(node, fallback, scope, state) {
79
+ if (!node) return fallback;
80
+ const expression = unwrapExpression(node);
81
+ if (expression?.type === "Identifier" && expression.name === "undefined" && !scope.getBinding("undefined")) return 0;
82
+ const value = readStaticFromScope(node, scope, /* @__PURE__ */ new Set(), node.end ?? Number.POSITIVE_INFINITY, state.analysis, true);
83
+ if (!value.ok || typeof value.value === "bigint") return void 0;
84
+ try {
85
+ const numeric = Number(value.value);
86
+ return Number.isNaN(numeric) ? 0 : Math.trunc(numeric);
87
+ } catch {
88
+ return;
89
+ }
90
+ }
91
+ /** Accepts only synchronous top-level operations that definitely run in order. */
92
+ function isUnconditionalSiblingOperation(binding, operation) {
93
+ const declarationStatement = binding.path.getStatementParent();
94
+ const operationStatement = operation.getStatementParent();
95
+ return Boolean(declarationStatement && (operationStatement?.isExpressionStatement() || operationStatement?.isVariableDeclaration()) && declarationStatement.parentPath?.node === operationStatement.parentPath?.node && binding.referencePaths.every((reference) => reference.getFunctionParent()?.node === operation.getFunctionParent()?.node));
96
+ }
97
+ /** Applies one direct member replacement to a finite container snapshot. */
98
+ function replaceFinalContainerMember(snapshot, property, value) {
99
+ if (snapshot.kind === "object") {
100
+ snapshot.entries.set(property, value);
101
+ return snapshot;
102
+ }
103
+ if (property === "length") {
104
+ const length = readStaticPrimitive(value.node, () => ({ ok: false }));
105
+ if (!length.ok || typeof length.value !== "number" || !Number.isInteger(length.value) || length.value < 0) return;
106
+ snapshot.entries.length = length.value;
107
+ return snapshot;
108
+ }
109
+ if (!/^(0|[1-9]\d*)$/.test(property)) return void 0;
110
+ snapshot.entries[Number(property)] = value;
111
+ return snapshot;
112
+ }
113
+ /**
114
+ * Evaluates the final value of a directly mutated finite container.
115
+ * Unknown control flow, dynamic keys, callbacks, and escapes return unknown so
116
+ * the normal fail-closed provenance remains in place.
117
+ */
118
+ function readDefiniteFinalContainerSnapshot(binding, state) {
119
+ const cached = state.finalContainerSnapshots.get(binding);
120
+ if (cached) return cloneFinalContainerSnapshot(cached);
121
+ if (state.finalContainerSnapshotsInProgress.has(binding)) return void 0;
122
+ state.finalContainerSnapshotsInProgress.add(binding);
123
+ try {
124
+ const replay = computeDefiniteFinalContainerSnapshot(binding, state);
125
+ if (!replay) return void 0;
126
+ for (const relatedBinding of replay.relatedBindings) state.finalContainerSnapshots.set(relatedBinding, cloneFinalContainerSnapshot(replay.snapshot));
127
+ return cloneFinalContainerSnapshot(replay.snapshot);
128
+ } finally {
129
+ state.finalContainerSnapshotsInProgress.delete(binding);
130
+ }
131
+ }
132
+ /** Replays exact writes and returns aliases that retain the same identity. */
133
+ function computeDefiniteFinalContainerSnapshot(binding, state) {
134
+ const declaration = binding.path.node;
135
+ if (declaration.type !== "VariableDeclarator" || declaration.id.type !== "Identifier" || !declaration.init) return;
136
+ let snapshot = readFinalContainerSnapshot(declaration.init, binding.path.scope, state);
137
+ if (!snapshot) return void 0;
138
+ const operations = [];
139
+ const addRootAssignment = (assignment) => {
140
+ if (assignment.node.operator !== "=" || assignment.node.left.type !== "Identifier" || assignment.node.left.name !== binding.identifier.name || !isUnconditionalSiblingOperation(binding, assignment)) return false;
141
+ operations.push({
142
+ position: assignment.node.start ?? Number.POSITIVE_INFINITY,
143
+ apply: () => readFinalContainerSnapshot(assignment.node.right, assignment.scope, state)
144
+ });
145
+ return true;
146
+ };
147
+ for (const violation of binding.constantViolations) if (!violation.isAssignmentExpression() || !addRootAssignment(violation)) return;
148
+ const pendingBindings = [binding];
149
+ const seenBindings = /* @__PURE__ */ new Set();
150
+ for (let bindingIndex = 0; bindingIndex < pendingBindings.length; bindingIndex += 1) {
151
+ const currentBinding = pendingBindings[bindingIndex];
152
+ if (!currentBinding || seenBindings.has(currentBinding)) continue;
153
+ seenBindings.add(currentBinding);
154
+ if (currentBinding !== binding && currentBinding.constantViolations.length > 0) return;
155
+ const writePolicy = readBindingContainerWritePolicy(currentBinding, state);
156
+ const blocksWriteAtDepth = (depth) => writePolicy === "readonly-deep" || writePolicy === "readonly-shallow" && depth <= 1;
157
+ for (const reference of currentBinding.referencePaths) {
158
+ const parent = reference.parentPath;
159
+ if (!parent) return void 0;
160
+ if (parent.isAssignmentExpression() && parent.node.left === reference.node) continue;
161
+ if (parent.isVariableDeclarator() && parent.node.init === reference.node && parent.node.id.type === "Identifier") {
162
+ if (binding.constantViolations.length > 0) return void 0;
163
+ if (!isUnconditionalSiblingOperation(binding, parent)) return void 0;
164
+ const alias = parent.scope.getBinding(parent.node.id.name);
165
+ if (!alias) return void 0;
166
+ pendingBindings.push(alias);
167
+ continue;
168
+ }
169
+ if (parent.isCallExpression() && parent.node.arguments.includes(reference.node)) {
170
+ const wrapper = resolveKnownExpression(parent.node.callee, parent.scope, state, /* @__PURE__ */ new Set());
171
+ if (wrapper?.type === "container-wrapper" && wrapper.writePolicy !== "forward") continue;
172
+ const callee = readResolvedMemberPath(parent.node.callee, parent.scope, state);
173
+ const argumentIndex = parent.node.arguments.indexOf(reference.node);
174
+ if (callee !== "Object.assign" || parent.scope.getBinding("Object") || argumentIndex !== 0 || !isUnconditionalSiblingOperation(binding, parent)) return;
175
+ if (blocksWriteAtDepth(1)) continue;
176
+ const sources = parent.node.arguments.slice(1);
177
+ operations.push({
178
+ position: parent.node.start ?? Number.POSITIVE_INFINITY,
179
+ apply: (current) => {
180
+ if (current.kind !== "object") return void 0;
181
+ for (const source of sources) {
182
+ if (source.type === "ArgumentPlaceholder" || source.type === "SpreadElement") return;
183
+ const entries = collectObjectEntries(source, parent.scope, /* @__PURE__ */ new Set(), source.end ?? Number.POSITIVE_INFINITY, state);
184
+ if (entries.unknownAll || entries.unknownNames.size > 0) return;
185
+ for (const [key, value] of entries.entries) current.entries.set(key, value);
186
+ }
187
+ return current;
188
+ }
189
+ });
190
+ continue;
191
+ }
192
+ if (!parent.isMemberExpression() && !parent.isOptionalMemberExpression()) return;
193
+ const firstMember = parent;
194
+ let current = firstMember;
195
+ let depth = 1;
196
+ while (current.parentPath && (current.parentPath.isMemberExpression() || current.parentPath.isOptionalMemberExpression()) && current.parentPath.node.object === current.node) {
197
+ current = current.parentPath;
198
+ depth += 1;
199
+ }
200
+ const terminal = current.parentPath;
201
+ const property = readResolvedMemberProperty(firstMember.node, firstMember.scope, state);
202
+ if (depth === 1 && property !== void 0 && terminal?.isAssignmentExpression() && terminal.node.left === current.node && terminal.node.operator === "=" && isUnconditionalSiblingOperation(binding, terminal)) {
203
+ if (blocksWriteAtDepth(1)) continue;
204
+ operations.push({
205
+ position: terminal.node.start ?? Number.POSITIVE_INFINITY,
206
+ apply: (value) => replaceFinalContainerMember(value, property, {
207
+ node: terminal.node.right,
208
+ scope: terminal.scope
209
+ })
210
+ });
211
+ continue;
212
+ }
213
+ if (depth === 1 && property !== void 0 && terminal?.isCallExpression() && terminal.node.callee === current.node && isUnconditionalSiblingOperation(binding, terminal)) {
214
+ if (blocksWriteAtDepth(1)) continue;
215
+ const method = property;
216
+ const args = terminal.node.arguments;
217
+ if (args.some((argument) => argument.type === "ArgumentPlaceholder" || argument.type === "SpreadElement")) return;
218
+ operations.push({
219
+ position: terminal.node.start ?? Number.POSITIVE_INFINITY,
220
+ apply: (value) => {
221
+ if (value.kind !== "array") return void 0;
222
+ const entries = value.entries;
223
+ const scoped = (index) => {
224
+ const argument = args[index];
225
+ return argument && argument.type !== "ArgumentPlaceholder" ? {
226
+ node: argument,
227
+ scope: terminal.scope
228
+ } : void 0;
229
+ };
230
+ if (method === "pop") entries.pop();
231
+ else if (method === "shift") entries.shift();
232
+ else if (method === "push") entries.push(...args.map((argument) => ({
233
+ node: argument,
234
+ scope: terminal.scope
235
+ })));
236
+ else if (method === "unshift") entries.unshift(...args.map((argument) => ({
237
+ node: argument,
238
+ scope: terminal.scope
239
+ })));
240
+ else if (method === "splice") {
241
+ const start = readDefiniteArrayInteger(scoped(0)?.node, 0, terminal.scope, state);
242
+ const deleteCount = readDefiniteArrayInteger(scoped(1)?.node, args.length < 2 ? Number.POSITIVE_INFINITY : 0, terminal.scope, state);
243
+ if (start === void 0 || deleteCount === void 0) return;
244
+ entries.splice(start, Math.max(0, deleteCount), ...args.slice(2).map((argument) => ({
245
+ node: argument,
246
+ scope: terminal.scope
247
+ })));
248
+ } else return READONLY_ARRAY_TRANSFORMS.has(method) ? value : void 0;
249
+ return value;
250
+ }
251
+ });
252
+ continue;
253
+ }
254
+ if (memberChainIsReadOnly(firstMember)) continue;
255
+ return;
256
+ }
257
+ }
258
+ for (const operation of operations.sort((first, second) => first.position - second.position)) {
259
+ snapshot = operation.apply(snapshot);
260
+ if (!snapshot) return void 0;
261
+ }
262
+ return {
263
+ snapshot,
264
+ relatedBindings: seenBindings
265
+ };
266
+ }
267
+ /** Returns whether the exact final finite container contains T anywhere. */
268
+ function readDefiniteFinalContainerHasGT(binding, state) {
269
+ const snapshot = readDefiniteFinalContainerSnapshot(binding, state);
270
+ if (!snapshot) return void 0;
271
+ const values = readFinalContainerValues(snapshot);
272
+ let unknown = false;
273
+ for (const value of values) {
274
+ const hasGT = readDefiniteExpressionHasGT(value.node, value.scope, state, /* @__PURE__ */ new Set());
275
+ if (hasGT) return true;
276
+ if (hasGT === void 0) unknown = true;
277
+ }
278
+ return unknown ? void 0 : false;
279
+ }
280
+ /** Lists the concrete values held by a finite container snapshot. */
281
+ function readFinalContainerValues(snapshot) {
282
+ return snapshot.kind === "array" ? snapshot.entries.filter((entry) => entry !== void 0) : [...snapshot.entries.values()];
283
+ }
284
+ return {
285
+ readDefiniteArrayInteger,
286
+ readDefiniteFinalContainerHasGT,
287
+ readDefiniteFinalContainerSnapshot
288
+ };
289
+ }
290
+ //#endregion
291
+ export { createSnapshotAnalysis };
292
+
293
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","names":[],"sources":["../../../src/internal/script/snapshot.ts"],"sourcesContent":["import type { Binding, NodePath, Scope } from '@babel/traverse';\nimport type * as t from '@babel/types';\nimport {\n readStaticPrimitive,\n unwrapExpression,\n type StaticPrimitiveResult,\n} from '../utils.js';\nimport type {\n CollectedObjectEntries,\n ContainerWritePolicy,\n FinalContainerOperation,\n FinalContainerSnapshot,\n KnownValue,\n ScopedExpression,\n ScriptState,\n VueScriptAnalysis,\n} from './model.js';\n\n/** Static-analysis operations consumed by finite snapshot evaluation. */\nexport type SnapshotAnalysisDependencies = {\n readonlyArrayTransforms: ReadonlySet<string>;\n collectObjectEntries: (\n node: t.Node,\n scope: Scope,\n seen: Set<t.Node>,\n atPosition?: number,\n state?: ScriptState\n ) => CollectedObjectEntries;\n collectTransformArrayEntries: (\n node: t.Node,\n scope: Scope,\n state: ScriptState,\n seen: Set<t.Node>,\n atPosition?: number\n ) => Array<ScopedExpression | undefined> | undefined;\n memberChainIsReadOnly: (\n memberPath: NodePath<t.MemberExpression | t.OptionalMemberExpression>\n ) => boolean;\n readBindingContainerWritePolicy: (\n binding: Binding,\n state: ScriptState,\n seen?: Set<Binding>\n ) => ContainerWritePolicy | undefined;\n readResolvedMemberPath: (\n node: t.Node,\n scope: Scope,\n state: ScriptState\n ) => string | undefined;\n readResolvedMemberProperty: (\n node: t.MemberExpression | t.OptionalMemberExpression,\n scope: Scope,\n state: ScriptState\n ) => string | undefined;\n readStaticFromScope: (\n node: t.Node | null | undefined,\n scope: Scope,\n seen: Set<Binding>,\n atPosition: number,\n analysis?: VueScriptAnalysis,\n allowNumericGlobals?: boolean\n ) => StaticPrimitiveResult;\n resolveKnownExpression: (\n node: t.Node | null | undefined,\n scope: Scope,\n state: ScriptState,\n seen: Set<Binding>\n ) => KnownValue | undefined;\n resolveVueTemplateContainerSources: (\n node: t.Node,\n scope: Scope,\n state: ScriptState\n ) => ScopedExpression[] | undefined;\n};\n\n/** Narrow snapshot queries used by replay and conservative provenance. */\nexport type SnapshotAnalysis = {\n readDefiniteArrayInteger: (\n node: t.Node | undefined,\n fallback: number,\n scope: Scope,\n state: ScriptState\n ) => number | undefined;\n readDefiniteFinalContainerHasGT: (\n binding: Binding,\n state: ScriptState\n ) => boolean | undefined;\n readDefiniteFinalContainerSnapshot: (\n binding: Binding,\n state: ScriptState\n ) => FinalContainerSnapshot | undefined;\n};\n\n/** Creates the conservative finite-container snapshot analyzer. */\nexport function createSnapshotAnalysis({\n readonlyArrayTransforms: READONLY_ARRAY_TRANSFORMS,\n collectObjectEntries,\n collectTransformArrayEntries,\n memberChainIsReadOnly,\n readBindingContainerWritePolicy,\n readResolvedMemberPath,\n readResolvedMemberProperty,\n readStaticFromScope,\n resolveKnownExpression,\n resolveVueTemplateContainerSources,\n}: SnapshotAnalysisDependencies): SnapshotAnalysis {\n /** Copies a replay snapshot before another binding applies its own writes. */\n function cloneFinalContainerSnapshot(\n snapshot: FinalContainerSnapshot\n ): FinalContainerSnapshot {\n return snapshot.kind === 'array'\n ? { kind: 'array', entries: [...snapshot.entries] }\n : { kind: 'object', entries: new Map(snapshot.entries) };\n }\n\n /** Reads an exact finite container without assuming arbitrary calls are pure. */\n function readFinalContainerSnapshot(\n node: t.Node,\n scope: Scope,\n state: ScriptState\n ): FinalContainerSnapshot | undefined {\n if (state.analysis.stats) {\n state.analysis.stats.finalContainerSnapshotReads += 1;\n }\n // A resolved GT/Vue identity or string function is an exact scalar, not a\n // finite container. This shortcut is especially important for immutable\n // alias chains whose final value is later stored in a mutable registry.\n if (resolveKnownExpression(node, scope, state, new Set())) return undefined;\n const array = collectTransformArrayEntries(\n node,\n scope,\n state,\n new Set(),\n Number.POSITIVE_INFINITY\n );\n if (array) return { kind: 'array', entries: [...array] };\n const object = collectObjectEntries(\n node,\n scope,\n new Set(),\n Number.POSITIVE_INFINITY,\n state\n );\n if (!object.unknownAll && object.unknownNames.size === 0) {\n return { kind: 'object', entries: new Map(object.entries) };\n }\n const sources = resolveVueTemplateContainerSources(node, scope, state);\n if (sources?.length !== 1) return undefined;\n const sourceExpression = unwrapExpression(sources[0].node);\n if (sourceExpression?.type === 'Identifier') {\n const sourceBinding = sources[0].scope.getBinding(sourceExpression.name);\n if (sourceBinding) {\n const finalSource = readDefiniteFinalContainerSnapshot(\n sourceBinding,\n state\n );\n if (finalSource) return finalSource;\n }\n }\n return readFinalContainerSnapshot(sources[0].node, sources[0].scope, state);\n }\n\n /** Determines whether a finite expression definitely contains T anywhere. */\n function readDefiniteExpressionHasGT(\n node: t.Node,\n scope: Scope,\n state: ScriptState,\n seen: Set<t.Node>\n ): boolean | undefined {\n const expression = unwrapExpression(node);\n if (!expression || seen.has(expression)) return undefined;\n const nextSeen = new Set(seen).add(expression);\n const known = resolveKnownExpression(expression, scope, state, new Set());\n if (known) {\n return known.type === 'component' ? known.name === 'T' : false;\n }\n const primitive = readStaticFromScope(\n expression,\n scope,\n new Set(),\n expression.end ?? Number.POSITIVE_INFINITY,\n state.analysis\n );\n if (primitive.ok) return false;\n if (\n expression.type === 'Identifier' &&\n !scope.getBinding(expression.name) &&\n [\n 'Array',\n 'BigInt',\n 'Boolean',\n 'Date',\n 'Error',\n 'Map',\n 'Number',\n 'Object',\n 'RegExp',\n 'Set',\n 'String',\n 'Symbol',\n 'WeakMap',\n 'WeakSet',\n 'undefined',\n ].includes(expression.name)\n ) {\n return false;\n }\n const snapshot = readFinalContainerSnapshot(expression, scope, state);\n if (!snapshot) return undefined;\n const values =\n snapshot.kind === 'array'\n ? snapshot.entries.filter(\n (entry): entry is ScopedExpression => entry !== undefined\n )\n : [...snapshot.entries.values()];\n let unknown = false;\n for (const value of values) {\n const hasGT = readDefiniteExpressionHasGT(\n value.node,\n value.scope,\n state,\n nextSeen\n );\n if (hasGT) return true;\n if (hasGT === undefined) unknown = true;\n }\n return unknown ? undefined : false;\n }\n\n /** Coerces a statically known array index with JavaScript integer semantics. */\n function readDefiniteArrayInteger(\n node: t.Node | undefined,\n fallback: number,\n scope: Scope,\n state: ScriptState\n ): number | undefined {\n if (!node) return fallback;\n const expression = unwrapExpression(node);\n if (\n expression?.type === 'Identifier' &&\n expression.name === 'undefined' &&\n !scope.getBinding('undefined')\n ) {\n return 0;\n }\n const value = readStaticFromScope(\n node,\n scope,\n new Set(),\n node.end ?? Number.POSITIVE_INFINITY,\n state.analysis,\n true\n );\n if (!value.ok || typeof value.value === 'bigint') return undefined;\n try {\n const numeric = Number(value.value);\n return Number.isNaN(numeric) ? 0 : Math.trunc(numeric);\n } catch {\n return undefined;\n }\n }\n\n /** Accepts only synchronous top-level operations that definitely run in order. */\n function isUnconditionalSiblingOperation(\n binding: Binding,\n operation: NodePath<t.Node>\n ): boolean {\n const declarationStatement = binding.path.getStatementParent();\n const operationStatement = operation.getStatementParent();\n return Boolean(\n declarationStatement &&\n (operationStatement?.isExpressionStatement() ||\n operationStatement?.isVariableDeclaration()) &&\n declarationStatement.parentPath?.node ===\n operationStatement.parentPath?.node &&\n binding.referencePaths.every(\n (reference) =>\n reference.getFunctionParent()?.node ===\n operation.getFunctionParent()?.node\n )\n );\n }\n\n /** Applies one direct member replacement to a finite container snapshot. */\n function replaceFinalContainerMember(\n snapshot: FinalContainerSnapshot,\n property: string,\n value: ScopedExpression\n ): FinalContainerSnapshot | undefined {\n if (snapshot.kind === 'object') {\n snapshot.entries.set(property, value);\n return snapshot;\n }\n if (property === 'length') {\n const length = readStaticPrimitive(value.node, () => ({ ok: false }));\n if (\n !length.ok ||\n typeof length.value !== 'number' ||\n !Number.isInteger(length.value) ||\n length.value < 0\n ) {\n return undefined;\n }\n snapshot.entries.length = length.value;\n return snapshot;\n }\n if (!/^(0|[1-9]\\d*)$/.test(property)) return undefined;\n snapshot.entries[Number(property)] = value;\n return snapshot;\n }\n\n /**\n * Evaluates the final value of a directly mutated finite container.\n * Unknown control flow, dynamic keys, callbacks, and escapes return unknown so\n * the normal fail-closed provenance remains in place.\n */\n function readDefiniteFinalContainerSnapshot(\n binding: Binding,\n state: ScriptState\n ): FinalContainerSnapshot | undefined {\n const cached = state.finalContainerSnapshots.get(binding);\n if (cached) return cloneFinalContainerSnapshot(cached);\n if (state.finalContainerSnapshotsInProgress.has(binding)) return undefined;\n state.finalContainerSnapshotsInProgress.add(binding);\n try {\n const replay = computeDefiniteFinalContainerSnapshot(binding, state);\n if (!replay) return undefined;\n for (const relatedBinding of replay.relatedBindings) {\n state.finalContainerSnapshots.set(\n relatedBinding,\n cloneFinalContainerSnapshot(replay.snapshot)\n );\n }\n return cloneFinalContainerSnapshot(replay.snapshot);\n } finally {\n state.finalContainerSnapshotsInProgress.delete(binding);\n }\n }\n\n /** Replays exact writes and returns aliases that retain the same identity. */\n function computeDefiniteFinalContainerSnapshot(\n binding: Binding,\n state: ScriptState\n ):\n | {\n snapshot: FinalContainerSnapshot;\n relatedBindings: Set<Binding>;\n }\n | undefined {\n const declaration = binding.path.node;\n if (\n declaration.type !== 'VariableDeclarator' ||\n declaration.id.type !== 'Identifier' ||\n !declaration.init\n ) {\n return undefined;\n }\n let snapshot = readFinalContainerSnapshot(\n declaration.init,\n binding.path.scope,\n state\n );\n if (!snapshot) return undefined;\n const operations: FinalContainerOperation[] = [];\n const addRootAssignment = (\n assignment: NodePath<t.AssignmentExpression>\n ): boolean => {\n if (\n assignment.node.operator !== '=' ||\n assignment.node.left.type !== 'Identifier' ||\n assignment.node.left.name !== binding.identifier.name ||\n !isUnconditionalSiblingOperation(binding, assignment)\n ) {\n return false;\n }\n operations.push({\n position: assignment.node.start ?? Number.POSITIVE_INFINITY,\n apply: () =>\n readFinalContainerSnapshot(\n assignment.node.right,\n assignment.scope,\n state\n ),\n });\n return true;\n };\n for (const violation of binding.constantViolations) {\n if (\n !violation.isAssignmentExpression() ||\n !addRootAssignment(violation)\n ) {\n return undefined;\n }\n }\n\n const pendingBindings = [binding];\n const seenBindings = new Set<Binding>();\n for (\n let bindingIndex = 0;\n bindingIndex < pendingBindings.length;\n bindingIndex += 1\n ) {\n const currentBinding = pendingBindings[bindingIndex];\n if (!currentBinding || seenBindings.has(currentBinding)) continue;\n seenBindings.add(currentBinding);\n if (\n currentBinding !== binding &&\n currentBinding.constantViolations.length > 0\n ) {\n return undefined;\n }\n const writePolicy = readBindingContainerWritePolicy(\n currentBinding,\n state\n );\n const blocksWriteAtDepth = (depth: number): boolean =>\n writePolicy === 'readonly-deep' ||\n (writePolicy === 'readonly-shallow' && depth <= 1);\n for (const reference of currentBinding.referencePaths) {\n const parent = reference.parentPath;\n if (!parent) return undefined;\n if (\n parent.isAssignmentExpression() &&\n parent.node.left === reference.node\n ) {\n continue;\n }\n if (\n parent.isVariableDeclarator() &&\n parent.node.init === reference.node &&\n parent.node.id.type === 'Identifier'\n ) {\n if (binding.constantViolations.length > 0) return undefined;\n if (!isUnconditionalSiblingOperation(binding, parent))\n return undefined;\n const alias = parent.scope.getBinding(parent.node.id.name);\n if (!alias) return undefined;\n pendingBindings.push(alias);\n continue;\n }\n if (\n parent.isCallExpression() &&\n parent.node.arguments.includes(\n reference.node as t.Expression | t.SpreadElement\n )\n ) {\n const wrapper = resolveKnownExpression(\n parent.node.callee,\n parent.scope,\n state,\n new Set()\n );\n if (\n wrapper?.type === 'container-wrapper' &&\n wrapper.writePolicy !== 'forward'\n ) {\n continue;\n }\n const callee = readResolvedMemberPath(\n parent.node.callee,\n parent.scope,\n state\n );\n const argumentIndex = parent.node.arguments.indexOf(\n reference.node as t.Expression | t.SpreadElement\n );\n if (\n callee !== 'Object.assign' ||\n parent.scope.getBinding('Object') ||\n argumentIndex !== 0 ||\n !isUnconditionalSiblingOperation(binding, parent)\n ) {\n return undefined;\n }\n if (blocksWriteAtDepth(1)) continue;\n const sources = parent.node.arguments.slice(1);\n operations.push({\n position: parent.node.start ?? Number.POSITIVE_INFINITY,\n apply: (current) => {\n if (current.kind !== 'object') return undefined;\n for (const source of sources) {\n if (\n source.type === 'ArgumentPlaceholder' ||\n source.type === 'SpreadElement'\n ) {\n return undefined;\n }\n const entries = collectObjectEntries(\n source,\n parent.scope,\n new Set(),\n source.end ?? Number.POSITIVE_INFINITY,\n state\n );\n if (entries.unknownAll || entries.unknownNames.size > 0) {\n return undefined;\n }\n for (const [key, value] of entries.entries) {\n current.entries.set(key, value);\n }\n }\n return current;\n },\n });\n continue;\n }\n if (\n !parent.isMemberExpression() &&\n !parent.isOptionalMemberExpression()\n ) {\n return undefined;\n }\n const firstMember = parent;\n let current: NodePath<t.Node> = firstMember;\n let depth = 1;\n while (\n current.parentPath &&\n (current.parentPath.isMemberExpression() ||\n current.parentPath.isOptionalMemberExpression()) &&\n current.parentPath.node.object === current.node\n ) {\n current = current.parentPath;\n depth += 1;\n }\n const terminal = current.parentPath;\n const property = readResolvedMemberProperty(\n firstMember.node,\n firstMember.scope,\n state\n );\n if (\n depth === 1 &&\n property !== undefined &&\n terminal?.isAssignmentExpression() &&\n terminal.node.left === current.node &&\n terminal.node.operator === '=' &&\n isUnconditionalSiblingOperation(binding, terminal)\n ) {\n if (blocksWriteAtDepth(1)) continue;\n operations.push({\n position: terminal.node.start ?? Number.POSITIVE_INFINITY,\n apply: (value) =>\n replaceFinalContainerMember(value, property, {\n node: terminal.node.right,\n scope: terminal.scope,\n }),\n });\n continue;\n }\n if (\n depth === 1 &&\n property !== undefined &&\n terminal?.isCallExpression() &&\n terminal.node.callee === current.node &&\n isUnconditionalSiblingOperation(binding, terminal)\n ) {\n if (blocksWriteAtDepth(1)) continue;\n const method = property;\n const args = terminal.node.arguments;\n if (\n args.some(\n (argument) =>\n argument.type === 'ArgumentPlaceholder' ||\n argument.type === 'SpreadElement'\n )\n ) {\n return undefined;\n }\n operations.push({\n position: terminal.node.start ?? Number.POSITIVE_INFINITY,\n apply: (value) => {\n if (value.kind !== 'array') return undefined;\n const entries = value.entries;\n const scoped = (index: number): ScopedExpression | undefined => {\n const argument = args[index];\n return argument && argument.type !== 'ArgumentPlaceholder'\n ? { node: argument, scope: terminal.scope }\n : undefined;\n };\n if (method === 'pop') entries.pop();\n else if (method === 'shift') entries.shift();\n else if (method === 'push') {\n entries.push(\n ...args.map((argument) => ({\n node: argument as t.Expression,\n scope: terminal.scope,\n }))\n );\n } else if (method === 'unshift') {\n entries.unshift(\n ...args.map((argument) => ({\n node: argument as t.Expression,\n scope: terminal.scope,\n }))\n );\n } else if (method === 'splice') {\n const start = readDefiniteArrayInteger(\n scoped(0)?.node,\n 0,\n terminal.scope,\n state\n );\n const deleteCount = readDefiniteArrayInteger(\n scoped(1)?.node,\n args.length < 2 ? Number.POSITIVE_INFINITY : 0,\n terminal.scope,\n state\n );\n if (start === undefined || deleteCount === undefined) {\n return undefined;\n }\n entries.splice(\n start,\n Math.max(0, deleteCount),\n ...args.slice(2).map((argument) => ({\n node: argument as t.Expression,\n scope: terminal.scope,\n }))\n );\n } else {\n return READONLY_ARRAY_TRANSFORMS.has(method)\n ? value\n : undefined;\n }\n return value;\n },\n });\n continue;\n }\n if (memberChainIsReadOnly(firstMember)) continue;\n return undefined;\n }\n }\n\n for (const operation of operations.sort(\n (first, second) => first.position - second.position\n )) {\n snapshot = operation.apply(snapshot);\n if (!snapshot) return undefined;\n }\n return { snapshot, relatedBindings: seenBindings };\n }\n\n /** Returns whether the exact final finite container contains T anywhere. */\n function readDefiniteFinalContainerHasGT(\n binding: Binding,\n state: ScriptState\n ): boolean | undefined {\n const snapshot = readDefiniteFinalContainerSnapshot(binding, state);\n if (!snapshot) return undefined;\n const values = readFinalContainerValues(snapshot);\n let unknown = false;\n for (const value of values) {\n const hasGT = readDefiniteExpressionHasGT(\n value.node,\n value.scope,\n state,\n new Set()\n );\n if (hasGT) return true;\n if (hasGT === undefined) unknown = true;\n }\n return unknown ? undefined : false;\n }\n\n /** Lists the concrete values held by a finite container snapshot. */\n function readFinalContainerValues(\n snapshot: FinalContainerSnapshot\n ): ScopedExpression[] {\n return snapshot.kind === 'array'\n ? snapshot.entries.filter(\n (entry): entry is ScopedExpression => entry !== undefined\n )\n : [...snapshot.entries.values()];\n }\n\n return {\n readDefiniteArrayInteger,\n readDefiniteFinalContainerHasGT,\n readDefiniteFinalContainerSnapshot,\n };\n}\n"],"mappings":";;;AA6FA,SAAgB,uBAAuB,EACrC,yBAAyB,2BACzB,sBACA,8BACA,uBACA,iCACA,wBACA,4BACA,qBACA,wBACA,sCACiD;;CAEjD,SAAS,4BACP,UACwB;AACxB,SAAO,SAAS,SAAS,UACrB;GAAE,MAAM;GAAS,SAAS,CAAC,GAAG,SAAS,QAAQ;GAAE,GACjD;GAAE,MAAM;GAAU,SAAS,IAAI,IAAI,SAAS,QAAQ;GAAE;;;CAI5D,SAAS,2BACP,MACA,OACA,OACoC;AACpC,MAAI,MAAM,SAAS,MACjB,OAAM,SAAS,MAAM,+BAA+B;AAKtD,MAAI,uBAAuB,MAAM,OAAO,uBAAO,IAAI,KAAK,CAAC,CAAE,QAAO,KAAA;EAClE,MAAM,QAAQ,6BACZ,MACA,OACA,uBACA,IAAI,KAAK,EACT,OAAO,kBACR;AACD,MAAI,MAAO,QAAO;GAAE,MAAM;GAAS,SAAS,CAAC,GAAG,MAAM;GAAE;EACxD,MAAM,SAAS,qBACb,MACA,uBACA,IAAI,KAAK,EACT,OAAO,mBACP,MACD;AACD,MAAI,CAAC,OAAO,cAAc,OAAO,aAAa,SAAS,EACrD,QAAO;GAAE,MAAM;GAAU,SAAS,IAAI,IAAI,OAAO,QAAQ;GAAE;EAE7D,MAAM,UAAU,mCAAmC,MAAM,OAAO,MAAM;AACtE,MAAI,SAAS,WAAW,EAAG,QAAO,KAAA;EAClC,MAAM,mBAAmB,iBAAiB,QAAQ,GAAG,KAAK;AAC1D,MAAI,kBAAkB,SAAS,cAAc;GAC3C,MAAM,gBAAgB,QAAQ,GAAG,MAAM,WAAW,iBAAiB,KAAK;AACxE,OAAI,eAAe;IACjB,MAAM,cAAc,mCAClB,eACA,MACD;AACD,QAAI,YAAa,QAAO;;;AAG5B,SAAO,2BAA2B,QAAQ,GAAG,MAAM,QAAQ,GAAG,OAAO,MAAM;;;CAI7E,SAAS,4BACP,MACA,OACA,OACA,MACqB;EACrB,MAAM,aAAa,iBAAiB,KAAK;AACzC,MAAI,CAAC,cAAc,KAAK,IAAI,WAAW,CAAE,QAAO,KAAA;EAChD,MAAM,WAAW,IAAI,IAAI,KAAK,CAAC,IAAI,WAAW;EAC9C,MAAM,QAAQ,uBAAuB,YAAY,OAAO,uBAAO,IAAI,KAAK,CAAC;AACzE,MAAI,MACF,QAAO,MAAM,SAAS,cAAc,MAAM,SAAS,MAAM;AAS3D,MAPkB,oBAChB,YACA,uBACA,IAAI,KAAK,EACT,WAAW,OAAO,OAAO,mBACzB,MAAM,SAEK,CAAC,GAAI,QAAO;AACzB,MACE,WAAW,SAAS,gBACpB,CAAC,MAAM,WAAW,WAAW,KAAK,IAClC;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC,SAAS,WAAW,KAAK,CAE3B,QAAO;EAET,MAAM,WAAW,2BAA2B,YAAY,OAAO,MAAM;AACrE,MAAI,CAAC,SAAU,QAAO,KAAA;EACtB,MAAM,SACJ,SAAS,SAAS,UACd,SAAS,QAAQ,QACd,UAAqC,UAAU,KAAA,EACjD,GACD,CAAC,GAAG,SAAS,QAAQ,QAAQ,CAAC;EACpC,IAAI,UAAU;AACd,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,QAAQ,4BACZ,MAAM,MACN,MAAM,OACN,OACA,SACD;AACD,OAAI,MAAO,QAAO;AAClB,OAAI,UAAU,KAAA,EAAW,WAAU;;AAErC,SAAO,UAAU,KAAA,IAAY;;;CAI/B,SAAS,yBACP,MACA,UACA,OACA,OACoB;AACpB,MAAI,CAAC,KAAM,QAAO;EAClB,MAAM,aAAa,iBAAiB,KAAK;AACzC,MACE,YAAY,SAAS,gBACrB,WAAW,SAAS,eACpB,CAAC,MAAM,WAAW,YAAY,CAE9B,QAAO;EAET,MAAM,QAAQ,oBACZ,MACA,uBACA,IAAI,KAAK,EACT,KAAK,OAAO,OAAO,mBACnB,MAAM,UACN,KACD;AACD,MAAI,CAAC,MAAM,MAAM,OAAO,MAAM,UAAU,SAAU,QAAO,KAAA;AACzD,MAAI;GACF,MAAM,UAAU,OAAO,MAAM,MAAM;AACnC,UAAO,OAAO,MAAM,QAAQ,GAAG,IAAI,KAAK,MAAM,QAAQ;UAChD;AACN;;;;CAKJ,SAAS,gCACP,SACA,WACS;EACT,MAAM,uBAAuB,QAAQ,KAAK,oBAAoB;EAC9D,MAAM,qBAAqB,UAAU,oBAAoB;AACzD,SAAO,QACL,yBACC,oBAAoB,uBAAuB,IAC1C,oBAAoB,uBAAuB,KAC7C,qBAAqB,YAAY,SAC/B,mBAAmB,YAAY,QACjC,QAAQ,eAAe,OACpB,cACC,UAAU,mBAAmB,EAAE,SAC/B,UAAU,mBAAmB,EAAE,KAClC,CACF;;;CAIH,SAAS,4BACP,UACA,UACA,OACoC;AACpC,MAAI,SAAS,SAAS,UAAU;AAC9B,YAAS,QAAQ,IAAI,UAAU,MAAM;AACrC,UAAO;;AAET,MAAI,aAAa,UAAU;GACzB,MAAM,SAAS,oBAAoB,MAAM,aAAa,EAAE,IAAI,OAAO,EAAE;AACrE,OACE,CAAC,OAAO,MACR,OAAO,OAAO,UAAU,YACxB,CAAC,OAAO,UAAU,OAAO,MAAM,IAC/B,OAAO,QAAQ,EAEf;AAEF,YAAS,QAAQ,SAAS,OAAO;AACjC,UAAO;;AAET,MAAI,CAAC,iBAAiB,KAAK,SAAS,CAAE,QAAO,KAAA;AAC7C,WAAS,QAAQ,OAAO,SAAS,IAAI;AACrC,SAAO;;;;;;;CAQT,SAAS,mCACP,SACA,OACoC;EACpC,MAAM,SAAS,MAAM,wBAAwB,IAAI,QAAQ;AACzD,MAAI,OAAQ,QAAO,4BAA4B,OAAO;AACtD,MAAI,MAAM,kCAAkC,IAAI,QAAQ,CAAE,QAAO,KAAA;AACjE,QAAM,kCAAkC,IAAI,QAAQ;AACpD,MAAI;GACF,MAAM,SAAS,sCAAsC,SAAS,MAAM;AACpE,OAAI,CAAC,OAAQ,QAAO,KAAA;AACpB,QAAK,MAAM,kBAAkB,OAAO,gBAClC,OAAM,wBAAwB,IAC5B,gBACA,4BAA4B,OAAO,SAAS,CAC7C;AAEH,UAAO,4BAA4B,OAAO,SAAS;YAC3C;AACR,SAAM,kCAAkC,OAAO,QAAQ;;;;CAK3D,SAAS,sCACP,SACA,OAMY;EACZ,MAAM,cAAc,QAAQ,KAAK;AACjC,MACE,YAAY,SAAS,wBACrB,YAAY,GAAG,SAAS,gBACxB,CAAC,YAAY,KAEb;EAEF,IAAI,WAAW,2BACb,YAAY,MACZ,QAAQ,KAAK,OACb,MACD;AACD,MAAI,CAAC,SAAU,QAAO,KAAA;EACtB,MAAM,aAAwC,EAAE;EAChD,MAAM,qBACJ,eACY;AACZ,OACE,WAAW,KAAK,aAAa,OAC7B,WAAW,KAAK,KAAK,SAAS,gBAC9B,WAAW,KAAK,KAAK,SAAS,QAAQ,WAAW,QACjD,CAAC,gCAAgC,SAAS,WAAW,CAErD,QAAO;AAET,cAAW,KAAK;IACd,UAAU,WAAW,KAAK,SAAS,OAAO;IAC1C,aACE,2BACE,WAAW,KAAK,OAChB,WAAW,OACX,MACD;IACJ,CAAC;AACF,UAAO;;AAET,OAAK,MAAM,aAAa,QAAQ,mBAC9B,KACE,CAAC,UAAU,wBAAwB,IACnC,CAAC,kBAAkB,UAAU,CAE7B;EAIJ,MAAM,kBAAkB,CAAC,QAAQ;EACjC,MAAM,+BAAe,IAAI,KAAc;AACvC,OACE,IAAI,eAAe,GACnB,eAAe,gBAAgB,QAC/B,gBAAgB,GAChB;GACA,MAAM,iBAAiB,gBAAgB;AACvC,OAAI,CAAC,kBAAkB,aAAa,IAAI,eAAe,CAAE;AACzD,gBAAa,IAAI,eAAe;AAChC,OACE,mBAAmB,WACnB,eAAe,mBAAmB,SAAS,EAE3C;GAEF,MAAM,cAAc,gCAClB,gBACA,MACD;GACD,MAAM,sBAAsB,UAC1B,gBAAgB,mBACf,gBAAgB,sBAAsB,SAAS;AAClD,QAAK,MAAM,aAAa,eAAe,gBAAgB;IACrD,MAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO,KAAA;AACpB,QACE,OAAO,wBAAwB,IAC/B,OAAO,KAAK,SAAS,UAAU,KAE/B;AAEF,QACE,OAAO,sBAAsB,IAC7B,OAAO,KAAK,SAAS,UAAU,QAC/B,OAAO,KAAK,GAAG,SAAS,cACxB;AACA,SAAI,QAAQ,mBAAmB,SAAS,EAAG,QAAO,KAAA;AAClD,SAAI,CAAC,gCAAgC,SAAS,OAAO,CACnD,QAAO,KAAA;KACT,MAAM,QAAQ,OAAO,MAAM,WAAW,OAAO,KAAK,GAAG,KAAK;AAC1D,SAAI,CAAC,MAAO,QAAO,KAAA;AACnB,qBAAgB,KAAK,MAAM;AAC3B;;AAEF,QACE,OAAO,kBAAkB,IACzB,OAAO,KAAK,UAAU,SACpB,UAAU,KACX,EACD;KACA,MAAM,UAAU,uBACd,OAAO,KAAK,QACZ,OAAO,OACP,uBACA,IAAI,KAAK,CACV;AACD,SACE,SAAS,SAAS,uBAClB,QAAQ,gBAAgB,UAExB;KAEF,MAAM,SAAS,uBACb,OAAO,KAAK,QACZ,OAAO,OACP,MACD;KACD,MAAM,gBAAgB,OAAO,KAAK,UAAU,QAC1C,UAAU,KACX;AACD,SACE,WAAW,mBACX,OAAO,MAAM,WAAW,SAAS,IACjC,kBAAkB,KAClB,CAAC,gCAAgC,SAAS,OAAO,CAEjD;AAEF,SAAI,mBAAmB,EAAE,CAAE;KAC3B,MAAM,UAAU,OAAO,KAAK,UAAU,MAAM,EAAE;AAC9C,gBAAW,KAAK;MACd,UAAU,OAAO,KAAK,SAAS,OAAO;MACtC,QAAQ,YAAY;AAClB,WAAI,QAAQ,SAAS,SAAU,QAAO,KAAA;AACtC,YAAK,MAAM,UAAU,SAAS;AAC5B,YACE,OAAO,SAAS,yBAChB,OAAO,SAAS,gBAEhB;QAEF,MAAM,UAAU,qBACd,QACA,OAAO,uBACP,IAAI,KAAK,EACT,OAAO,OAAO,OAAO,mBACrB,MACD;AACD,YAAI,QAAQ,cAAc,QAAQ,aAAa,OAAO,EACpD;AAEF,aAAK,MAAM,CAAC,KAAK,UAAU,QAAQ,QACjC,SAAQ,QAAQ,IAAI,KAAK,MAAM;;AAGnC,cAAO;;MAEV,CAAC;AACF;;AAEF,QACE,CAAC,OAAO,oBAAoB,IAC5B,CAAC,OAAO,4BAA4B,CAEpC;IAEF,MAAM,cAAc;IACpB,IAAI,UAA4B;IAChC,IAAI,QAAQ;AACZ,WACE,QAAQ,eACP,QAAQ,WAAW,oBAAoB,IACtC,QAAQ,WAAW,4BAA4B,KACjD,QAAQ,WAAW,KAAK,WAAW,QAAQ,MAC3C;AACA,eAAU,QAAQ;AAClB,cAAS;;IAEX,MAAM,WAAW,QAAQ;IACzB,MAAM,WAAW,2BACf,YAAY,MACZ,YAAY,OACZ,MACD;AACD,QACE,UAAU,KACV,aAAa,KAAA,KACb,UAAU,wBAAwB,IAClC,SAAS,KAAK,SAAS,QAAQ,QAC/B,SAAS,KAAK,aAAa,OAC3B,gCAAgC,SAAS,SAAS,EAClD;AACA,SAAI,mBAAmB,EAAE,CAAE;AAC3B,gBAAW,KAAK;MACd,UAAU,SAAS,KAAK,SAAS,OAAO;MACxC,QAAQ,UACN,4BAA4B,OAAO,UAAU;OAC3C,MAAM,SAAS,KAAK;OACpB,OAAO,SAAS;OACjB,CAAC;MACL,CAAC;AACF;;AAEF,QACE,UAAU,KACV,aAAa,KAAA,KACb,UAAU,kBAAkB,IAC5B,SAAS,KAAK,WAAW,QAAQ,QACjC,gCAAgC,SAAS,SAAS,EAClD;AACA,SAAI,mBAAmB,EAAE,CAAE;KAC3B,MAAM,SAAS;KACf,MAAM,OAAO,SAAS,KAAK;AAC3B,SACE,KAAK,MACF,aACC,SAAS,SAAS,yBAClB,SAAS,SAAS,gBACrB,CAED;AAEF,gBAAW,KAAK;MACd,UAAU,SAAS,KAAK,SAAS,OAAO;MACxC,QAAQ,UAAU;AAChB,WAAI,MAAM,SAAS,QAAS,QAAO,KAAA;OACnC,MAAM,UAAU,MAAM;OACtB,MAAM,UAAU,UAAgD;QAC9D,MAAM,WAAW,KAAK;AACtB,eAAO,YAAY,SAAS,SAAS,wBACjC;SAAE,MAAM;SAAU,OAAO,SAAS;SAAO,GACzC,KAAA;;AAEN,WAAI,WAAW,MAAO,SAAQ,KAAK;gBAC1B,WAAW,QAAS,SAAQ,OAAO;gBACnC,WAAW,OAClB,SAAQ,KACN,GAAG,KAAK,KAAK,cAAc;QACzB,MAAM;QACN,OAAO,SAAS;QACjB,EAAE,CACJ;gBACQ,WAAW,UACpB,SAAQ,QACN,GAAG,KAAK,KAAK,cAAc;QACzB,MAAM;QACN,OAAO,SAAS;QACjB,EAAE,CACJ;gBACQ,WAAW,UAAU;QAC9B,MAAM,QAAQ,yBACZ,OAAO,EAAE,EAAE,MACX,GACA,SAAS,OACT,MACD;QACD,MAAM,cAAc,yBAClB,OAAO,EAAE,EAAE,MACX,KAAK,SAAS,IAAI,OAAO,oBAAoB,GAC7C,SAAS,OACT,MACD;AACD,YAAI,UAAU,KAAA,KAAa,gBAAgB,KAAA,EACzC;AAEF,gBAAQ,OACN,OACA,KAAK,IAAI,GAAG,YAAY,EACxB,GAAG,KAAK,MAAM,EAAE,CAAC,KAAK,cAAc;SAClC,MAAM;SACN,OAAO,SAAS;SACjB,EAAE,CACJ;aAED,QAAO,0BAA0B,IAAI,OAAO,GACxC,QACA,KAAA;AAEN,cAAO;;MAEV,CAAC;AACF;;AAEF,QAAI,sBAAsB,YAAY,CAAE;AACxC;;;AAIJ,OAAK,MAAM,aAAa,WAAW,MAChC,OAAO,WAAW,MAAM,WAAW,OAAO,SAC5C,EAAE;AACD,cAAW,UAAU,MAAM,SAAS;AACpC,OAAI,CAAC,SAAU,QAAO,KAAA;;AAExB,SAAO;GAAE;GAAU,iBAAiB;GAAc;;;CAIpD,SAAS,gCACP,SACA,OACqB;EACrB,MAAM,WAAW,mCAAmC,SAAS,MAAM;AACnE,MAAI,CAAC,SAAU,QAAO,KAAA;EACtB,MAAM,SAAS,yBAAyB,SAAS;EACjD,IAAI,UAAU;AACd,OAAK,MAAM,SAAS,QAAQ;GAC1B,MAAM,QAAQ,4BACZ,MAAM,MACN,MAAM,OACN,uBACA,IAAI,KAAK,CACV;AACD,OAAI,MAAO,QAAO;AAClB,OAAI,UAAU,KAAA,EAAW,WAAU;;AAErC,SAAO,UAAU,KAAA,IAAY;;;CAI/B,SAAS,yBACP,UACoB;AACpB,SAAO,SAAS,SAAS,UACrB,SAAS,QAAQ,QACd,UAAqC,UAAU,KAAA,EACjD,GACD,CAAC,GAAG,SAAS,QAAQ,QAAQ,CAAC;;AAGpC,QAAO;EACL;EACA;EACA;EACD"}
@@ -0,0 +1,21 @@
1
+ import type { NodePath, Scope } from '@babel/traverse';
2
+ import type * as t from '@babel/types';
3
+ /** Reads a member key that is already a static property literal. */
4
+ export declare function readMemberProperty(node: t.MemberExpression | t.OptionalMemberExpression): string | undefined;
5
+ /** Reads a direct identifier, string, or numeric object key. */
6
+ export declare function readObjectKey(node: t.Node): string | undefined;
7
+ /** Reads a property key without evaluating a computed expression. */
8
+ export declare function readPropertyKey(property: {
9
+ computed: boolean;
10
+ key: t.Node;
11
+ }): string | undefined;
12
+ /** Reads the identifier introduced by a direct or defaulted pattern. */
13
+ export declare function readPatternIdentifier(node: t.Node): string | undefined;
14
+ /** Recognizes expressions that are statically JavaScript `undefined`. */
15
+ export declare function isStaticallyUndefined(node: t.Node, scope: Scope): boolean;
16
+ /** Returns whether a binding pattern introduces the requested name. */
17
+ export declare function patternContains(node: t.Node, name: string): boolean;
18
+ /** Returns whether a node can introduce one or more lexical bindings. */
19
+ export declare function isBindingPattern(node: t.Node): boolean;
20
+ /** Identifies AST wrappers that can contain a nested assignment target. */
21
+ export declare function isAssignmentTargetWrapper(parent: NodePath<t.Node>, child: NodePath<t.Node>): boolean;
@@ -0,0 +1,46 @@
1
+ import { unwrapExpression } from "../utils.js";
2
+ //#region src/internal/script/syntax.ts
3
+ /** Reads a member key that is already a static property literal. */
4
+ function readMemberProperty(node) {
5
+ if (!node.computed && node.property.type === "Identifier") return node.property.name;
6
+ return node.computed && node.property.type === "StringLiteral" ? node.property.value : node.computed && node.property.type === "NumericLiteral" ? String(node.property.value) : void 0;
7
+ }
8
+ /** Reads a direct identifier, string, or numeric object key. */
9
+ function readObjectKey(node) {
10
+ return node.type === "Identifier" ? node.name : node.type === "StringLiteral" ? node.value : node.type === "NumericLiteral" ? String(node.value) : void 0;
11
+ }
12
+ /** Reads a property key without evaluating a computed expression. */
13
+ function readPropertyKey(property) {
14
+ return property.computed && property.key.type !== "StringLiteral" ? void 0 : readObjectKey(property.key);
15
+ }
16
+ /** Reads the identifier introduced by a direct or defaulted pattern. */
17
+ function readPatternIdentifier(node) {
18
+ if (node.type === "Identifier") return node.name;
19
+ if (node.type === "AssignmentPattern") return readPatternIdentifier(node.left);
20
+ }
21
+ /** Recognizes expressions that are statically JavaScript `undefined`. */
22
+ function isStaticallyUndefined(node, scope) {
23
+ const expression = unwrapExpression(node);
24
+ return expression?.type === "Identifier" && expression.name === "undefined" && !scope.getBinding("undefined") || expression?.type === "UnaryExpression" && expression.operator === "void";
25
+ }
26
+ /** Returns whether a binding pattern introduces the requested name. */
27
+ function patternContains(node, name) {
28
+ if (node.type === "Identifier") return node.name === name;
29
+ if (node.type === "AssignmentPattern") return patternContains(node.left, name);
30
+ if (node.type === "RestElement") return patternContains(node.argument, name);
31
+ if (node.type === "ArrayPattern") return node.elements.some((element) => element && patternContains(element, name));
32
+ if (node.type === "ObjectPattern") return node.properties.some((property) => property.type === "RestElement" ? patternContains(property.argument, name) : patternContains(property.value, name));
33
+ return false;
34
+ }
35
+ /** Returns whether a node can introduce one or more lexical bindings. */
36
+ function isBindingPattern(node) {
37
+ return node.type === "Identifier" || node.type === "ObjectPattern" || node.type === "ArrayPattern" || node.type === "AssignmentPattern" || node.type === "RestElement";
38
+ }
39
+ /** Identifies AST wrappers that can contain a nested assignment target. */
40
+ function isAssignmentTargetWrapper(parent, child) {
41
+ return parent.isObjectProperty() && parent.node.value === child.node && parent.parentPath?.isObjectPattern() === true || parent.isObjectPattern() || parent.isArrayPattern() || parent.isRestElement() && parent.node.argument === child.node || parent.isAssignmentPattern() && parent.node.left === child.node;
42
+ }
43
+ //#endregion
44
+ export { isAssignmentTargetWrapper, isBindingPattern, isStaticallyUndefined, patternContains, readMemberProperty, readObjectKey, readPatternIdentifier, readPropertyKey };
45
+
46
+ //# sourceMappingURL=syntax.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syntax.js","names":[],"sources":["../../../src/internal/script/syntax.ts"],"sourcesContent":["import type { NodePath, Scope } from '@babel/traverse';\nimport type * as t from '@babel/types';\nimport { unwrapExpression } from '../utils.js';\n\n/** Reads a member key that is already a static property literal. */\nexport function readMemberProperty(\n node: t.MemberExpression | t.OptionalMemberExpression\n): string | undefined {\n if (!node.computed && node.property.type === 'Identifier') {\n return node.property.name;\n }\n return node.computed && node.property.type === 'StringLiteral'\n ? node.property.value\n : node.computed && node.property.type === 'NumericLiteral'\n ? String(node.property.value)\n : undefined;\n}\n\n/** Reads a direct identifier, string, or numeric object key. */\nexport function readObjectKey(node: t.Node): string | undefined {\n return node.type === 'Identifier'\n ? node.name\n : node.type === 'StringLiteral'\n ? node.value\n : node.type === 'NumericLiteral'\n ? String(node.value)\n : undefined;\n}\n\n/** Reads a property key without evaluating a computed expression. */\nexport function readPropertyKey(property: {\n computed: boolean;\n key: t.Node;\n}): string | undefined {\n return property.computed && property.key.type !== 'StringLiteral'\n ? undefined\n : readObjectKey(property.key);\n}\n\n/** Reads the identifier introduced by a direct or defaulted pattern. */\nexport function readPatternIdentifier(node: t.Node): string | undefined {\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'AssignmentPattern') {\n return readPatternIdentifier(node.left);\n }\n return undefined;\n}\n\n/** Recognizes expressions that are statically JavaScript `undefined`. */\nexport function isStaticallyUndefined(node: t.Node, scope: Scope): boolean {\n const expression = unwrapExpression(node);\n return (\n (expression?.type === 'Identifier' &&\n expression.name === 'undefined' &&\n !scope.getBinding('undefined')) ||\n (expression?.type === 'UnaryExpression' && expression.operator === 'void')\n );\n}\n\n/** Returns whether a binding pattern introduces the requested name. */\nexport function patternContains(node: t.Node, name: string): boolean {\n if (node.type === 'Identifier') return node.name === name;\n if (node.type === 'AssignmentPattern') {\n return patternContains(node.left, name);\n }\n if (node.type === 'RestElement') return patternContains(node.argument, name);\n if (node.type === 'ArrayPattern') {\n return node.elements.some(\n (element) => element && patternContains(element, name)\n );\n }\n if (node.type === 'ObjectPattern') {\n return node.properties.some((property) =>\n property.type === 'RestElement'\n ? patternContains(property.argument, name)\n : patternContains(property.value, name)\n );\n }\n return false;\n}\n\n/** Returns whether a node can introduce one or more lexical bindings. */\nexport function isBindingPattern(node: t.Node): boolean {\n return (\n node.type === 'Identifier' ||\n node.type === 'ObjectPattern' ||\n node.type === 'ArrayPattern' ||\n node.type === 'AssignmentPattern' ||\n node.type === 'RestElement'\n );\n}\n\n/** Identifies AST wrappers that can contain a nested assignment target. */\nexport function isAssignmentTargetWrapper(\n parent: NodePath<t.Node>,\n child: NodePath<t.Node>\n): boolean {\n return (\n (parent.isObjectProperty() &&\n parent.node.value === child.node &&\n parent.parentPath?.isObjectPattern() === true) ||\n parent.isObjectPattern() ||\n parent.isArrayPattern() ||\n (parent.isRestElement() && parent.node.argument === child.node) ||\n (parent.isAssignmentPattern() && parent.node.left === child.node)\n );\n}\n"],"mappings":";;;AAKA,SAAgB,mBACd,MACoB;AACpB,KAAI,CAAC,KAAK,YAAY,KAAK,SAAS,SAAS,aAC3C,QAAO,KAAK,SAAS;AAEvB,QAAO,KAAK,YAAY,KAAK,SAAS,SAAS,kBAC3C,KAAK,SAAS,QACd,KAAK,YAAY,KAAK,SAAS,SAAS,mBACtC,OAAO,KAAK,SAAS,MAAM,GAC3B,KAAA;;;AAIR,SAAgB,cAAc,MAAkC;AAC9D,QAAO,KAAK,SAAS,eACjB,KAAK,OACL,KAAK,SAAS,kBACZ,KAAK,QACL,KAAK,SAAS,mBACZ,OAAO,KAAK,MAAM,GAClB,KAAA;;;AAIV,SAAgB,gBAAgB,UAGT;AACrB,QAAO,SAAS,YAAY,SAAS,IAAI,SAAS,kBAC9C,KAAA,IACA,cAAc,SAAS,IAAI;;;AAIjC,SAAgB,sBAAsB,MAAkC;AACtE,KAAI,KAAK,SAAS,aAAc,QAAO,KAAK;AAC5C,KAAI,KAAK,SAAS,oBAChB,QAAO,sBAAsB,KAAK,KAAK;;;AAM3C,SAAgB,sBAAsB,MAAc,OAAuB;CACzE,MAAM,aAAa,iBAAiB,KAAK;AACzC,QACG,YAAY,SAAS,gBACpB,WAAW,SAAS,eACpB,CAAC,MAAM,WAAW,YAAY,IAC/B,YAAY,SAAS,qBAAqB,WAAW,aAAa;;;AAKvE,SAAgB,gBAAgB,MAAc,MAAuB;AACnE,KAAI,KAAK,SAAS,aAAc,QAAO,KAAK,SAAS;AACrD,KAAI,KAAK,SAAS,oBAChB,QAAO,gBAAgB,KAAK,MAAM,KAAK;AAEzC,KAAI,KAAK,SAAS,cAAe,QAAO,gBAAgB,KAAK,UAAU,KAAK;AAC5E,KAAI,KAAK,SAAS,eAChB,QAAO,KAAK,SAAS,MAClB,YAAY,WAAW,gBAAgB,SAAS,KAAK,CACvD;AAEH,KAAI,KAAK,SAAS,gBAChB,QAAO,KAAK,WAAW,MAAM,aAC3B,SAAS,SAAS,gBACd,gBAAgB,SAAS,UAAU,KAAK,GACxC,gBAAgB,SAAS,OAAO,KAAK,CAC1C;AAEH,QAAO;;;AAIT,SAAgB,iBAAiB,MAAuB;AACtD,QACE,KAAK,SAAS,gBACd,KAAK,SAAS,mBACd,KAAK,SAAS,kBACd,KAAK,SAAS,uBACd,KAAK,SAAS;;;AAKlB,SAAgB,0BACd,QACA,OACS;AACT,QACG,OAAO,kBAAkB,IACxB,OAAO,KAAK,UAAU,MAAM,QAC5B,OAAO,YAAY,iBAAiB,KAAK,QAC3C,OAAO,iBAAiB,IACxB,OAAO,gBAAgB,IACtB,OAAO,eAAe,IAAI,OAAO,KAAK,aAAa,MAAM,QACzD,OAAO,qBAAqB,IAAI,OAAO,KAAK,SAAS,MAAM"}
@@ -0,0 +1,2 @@
1
+ export { collectVueScriptImports, createVueScriptAnalysis, createVueScriptAnalysisStats, exposeVueScriptImportsToTemplate, parseVueScript, } from './script/analyze.js';
2
+ export type { VueScriptAnalysis, VueScriptAnalysisStats, } from './script/model.js';
@@ -0,0 +1,2 @@
1
+ import { collectVueScriptImports, createVueScriptAnalysis, createVueScriptAnalysisStats, exposeVueScriptImportsToTemplate, parseVueScript } from "./script/analyze.js";
2
+ export { collectVueScriptImports, createVueScriptAnalysis, createVueScriptAnalysisStats, exposeVueScriptImportsToTemplate, parseVueScript };
@@ -0,0 +1,7 @@
1
+ import type * as t from '@babel/types';
2
+ import type { ExtractionLocation, StringFunctionKind, VueExtractionContext } from './types.js';
3
+ import { type StaticPrimitiveResult } from './utils.js';
4
+ type VueStringCall = t.CallExpression | t.OptionalCallExpression;
5
+ type StaticPrimitiveReader = (input: t.Node | null | undefined) => StaticPrimitiveResult;
6
+ export declare function processVueStringCall(call: VueStringCall, kind: StringFunctionKind, location: ExtractionLocation | undefined, context: VueExtractionContext, readStatic?: StaticPrimitiveReader): void;
7
+ export {};
@@ -0,0 +1,82 @@
1
+ import { addVueError, createInlineMetadata, readStaticPrimitive, unwrapExpression } from "./utils.js";
2
+ //#region src/internal/stringCalls.ts
3
+ function processVueStringCall(call, kind, location, context, readStatic = readStaticPrimitive) {
4
+ const firstArgument = call.arguments[0];
5
+ const unwrappedFirstArgument = unwrapExpression(firstArgument);
6
+ if (kind === "msg" && unwrappedFirstArgument?.type === "ArrayExpression") {
7
+ const options = readContextOptions(call.arguments[1], location, context, readStatic);
8
+ if (!options.ok) return;
9
+ if (call.arguments.length > 2) {
10
+ addUnsupportedArgumentsError(location, context);
11
+ return;
12
+ }
13
+ const messages = [];
14
+ for (const element of unwrappedFirstArgument.elements) {
15
+ const value = readStatic(element);
16
+ if (!value.ok || typeof value.value !== "string") {
17
+ addVueError(context, location, "Found a dynamic entry in a gt-vue msg() message list", "Use only string literals or template literals without expressions");
18
+ return;
19
+ }
20
+ messages.push(value.value);
21
+ }
22
+ for (const message of messages) addStringUpdate(message, options.context, location, context);
23
+ return;
24
+ }
25
+ const value = unwrappedFirstArgument?.type === "SpreadElement" || unwrappedFirstArgument?.type === "ArgumentPlaceholder" ? { ok: false } : readStatic(unwrappedFirstArgument);
26
+ if (!value.ok || typeof value.value !== "string") {
27
+ if (kind === "messages") return;
28
+ addVueError(context, location, `Found dynamic content in a gt-vue ${kind === "gt" ? "gt()" : "msg()"} call`, "Use a string literal or a template literal without expressions");
29
+ return;
30
+ }
31
+ const options = readContextOptions(call.arguments[1], location, context, readStatic);
32
+ if (!options.ok) return;
33
+ if (call.arguments.length > 2) {
34
+ addUnsupportedArgumentsError(location, context);
35
+ return;
36
+ }
37
+ addStringUpdate(value.value, options.context, location, context);
38
+ }
39
+ function addStringUpdate(source, translationContext, location, context) {
40
+ context.results.push({
41
+ dataFormat: "STRING",
42
+ source,
43
+ metadata: createInlineMetadata(context, location, translationContext)
44
+ });
45
+ }
46
+ function readContextOptions(argument, location, context, readStatic) {
47
+ if (argument === void 0) return { ok: true };
48
+ const options = unwrapExpression(argument);
49
+ if (options?.type !== "ObjectExpression") {
50
+ addVueError(context, location, "Found dynamic options in a gt-vue string translation call", "Pass a static object containing only a string $context field");
51
+ return { ok: false };
52
+ }
53
+ let translationContext;
54
+ for (const property of options.properties) {
55
+ if (property.type !== "ObjectProperty" || property.computed && property.key.type !== "StringLiteral") {
56
+ addVueError(context, location, "Found unsupported options in a gt-vue string translation call", "Pass a static object containing only a string $context field");
57
+ return { ok: false };
58
+ }
59
+ const key = property.key.type === "Identifier" ? property.key.name : property.key.type === "StringLiteral" ? property.key.value : void 0;
60
+ if (key !== "$context") {
61
+ addVueError(context, location, `Found unsupported gt-vue string option ${key ? `"${key}"` : ""}`.trim(), "gt-vue string translation currently supports only $context");
62
+ return { ok: false };
63
+ }
64
+ const value = readStatic(property.value);
65
+ if (!value.ok || typeof value.value !== "string") {
66
+ addVueError(context, location, "Found a dynamic $context in a gt-vue string translation call", "Use a string literal or a template literal without expressions");
67
+ return { ok: false };
68
+ }
69
+ translationContext = value.value;
70
+ }
71
+ return {
72
+ ok: true,
73
+ context: translationContext
74
+ };
75
+ }
76
+ function addUnsupportedArgumentsError(location, context) {
77
+ addVueError(context, location, "Found unsupported arguments in a gt-vue string translation call", "Pass the source string and, optionally, an object containing only $context");
78
+ }
79
+ //#endregion
80
+ export { processVueStringCall };
81
+
82
+ //# sourceMappingURL=stringCalls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringCalls.js","names":[],"sources":["../../src/internal/stringCalls.ts"],"sourcesContent":["import type * as t from '@babel/types';\nimport type {\n ExtractionLocation,\n StringFunctionKind,\n VueExtractionContext,\n} from './types.js';\nimport {\n addVueError,\n createInlineMetadata,\n readStaticPrimitive,\n type StaticPrimitiveResult,\n unwrapExpression,\n} from './utils.js';\n\ntype VueStringCall = t.CallExpression | t.OptionalCallExpression;\ntype StaticPrimitiveReader = (\n input: t.Node | null | undefined\n) => StaticPrimitiveResult;\n\nexport function processVueStringCall(\n call: VueStringCall,\n kind: StringFunctionKind,\n location: ExtractionLocation | undefined,\n context: VueExtractionContext,\n readStatic: StaticPrimitiveReader = readStaticPrimitive\n): void {\n const firstArgument = call.arguments[0];\n const unwrappedFirstArgument = unwrapExpression(firstArgument);\n\n if (kind === 'msg' && unwrappedFirstArgument?.type === 'ArrayExpression') {\n const options = readContextOptions(\n call.arguments[1],\n location,\n context,\n readStatic\n );\n if (!options.ok) return;\n if (call.arguments.length > 2) {\n addUnsupportedArgumentsError(location, context);\n return;\n }\n\n const messages: string[] = [];\n for (const element of unwrappedFirstArgument.elements) {\n const value = readStatic(element);\n if (!value.ok || typeof value.value !== 'string') {\n addVueError(\n context,\n location,\n 'Found a dynamic entry in a gt-vue msg() message list',\n 'Use only string literals or template literals without expressions'\n );\n return;\n }\n messages.push(value.value);\n }\n for (const message of messages) {\n addStringUpdate(message, options.context, location, context);\n }\n return;\n }\n\n const value =\n unwrappedFirstArgument?.type === 'SpreadElement' ||\n unwrappedFirstArgument?.type === 'ArgumentPlaceholder'\n ? { ok: false as const }\n : readStatic(unwrappedFirstArgument);\n\n // useMessages() can receive a previously encoded msg() value. Only direct\n // literal calls register new source content.\n if (!value.ok || typeof value.value !== 'string') {\n if (kind === 'messages') return;\n addVueError(\n context,\n location,\n `Found dynamic content in a gt-vue ${kind === 'gt' ? 'gt()' : 'msg()'} call`,\n 'Use a string literal or a template literal without expressions'\n );\n return;\n }\n\n const options = readContextOptions(\n call.arguments[1],\n location,\n context,\n readStatic\n );\n if (!options.ok) return;\n if (call.arguments.length > 2) {\n addUnsupportedArgumentsError(location, context);\n return;\n }\n addStringUpdate(value.value, options.context, location, context);\n}\n\nfunction addStringUpdate(\n source: string,\n translationContext: string | undefined,\n location: ExtractionLocation | undefined,\n context: VueExtractionContext\n): void {\n context.results.push({\n dataFormat: 'STRING',\n source,\n metadata: createInlineMetadata(context, location, translationContext),\n });\n}\n\nfunction readContextOptions(\n argument: VueStringCall['arguments'][number] | undefined,\n location: ExtractionLocation | undefined,\n context: VueExtractionContext,\n readStatic: StaticPrimitiveReader\n): { ok: true; context?: string } | { ok: false } {\n if (argument === undefined) return { ok: true };\n const options = unwrapExpression(argument);\n if (options?.type !== 'ObjectExpression') {\n addVueError(\n context,\n location,\n 'Found dynamic options in a gt-vue string translation call',\n 'Pass a static object containing only a string $context field'\n );\n return { ok: false };\n }\n\n let translationContext: string | undefined;\n for (const property of options.properties) {\n if (\n property.type !== 'ObjectProperty' ||\n (property.computed && property.key.type !== 'StringLiteral')\n ) {\n addVueError(\n context,\n location,\n 'Found unsupported options in a gt-vue string translation call',\n 'Pass a static object containing only a string $context field'\n );\n return { ok: false };\n }\n const key =\n property.key.type === 'Identifier'\n ? property.key.name\n : property.key.type === 'StringLiteral'\n ? property.key.value\n : undefined;\n if (key !== '$context') {\n addVueError(\n context,\n location,\n `Found unsupported gt-vue string option ${key ? `\"${key}\"` : ''}`.trim(),\n 'gt-vue string translation currently supports only $context'\n );\n return { ok: false };\n }\n const value = readStatic(property.value);\n if (!value.ok || typeof value.value !== 'string') {\n addVueError(\n context,\n location,\n 'Found a dynamic $context in a gt-vue string translation call',\n 'Use a string literal or a template literal without expressions'\n );\n return { ok: false };\n }\n translationContext = value.value;\n }\n return { ok: true, context: translationContext };\n}\n\nfunction addUnsupportedArgumentsError(\n location: ExtractionLocation | undefined,\n context: VueExtractionContext\n): void {\n addVueError(\n context,\n location,\n 'Found unsupported arguments in a gt-vue string translation call',\n 'Pass the source string and, optionally, an object containing only $context'\n );\n}\n"],"mappings":";;AAmBA,SAAgB,qBACd,MACA,MACA,UACA,SACA,aAAoC,qBAC9B;CACN,MAAM,gBAAgB,KAAK,UAAU;CACrC,MAAM,yBAAyB,iBAAiB,cAAc;AAE9D,KAAI,SAAS,SAAS,wBAAwB,SAAS,mBAAmB;EACxE,MAAM,UAAU,mBACd,KAAK,UAAU,IACf,UACA,SACA,WACD;AACD,MAAI,CAAC,QAAQ,GAAI;AACjB,MAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,gCAA6B,UAAU,QAAQ;AAC/C;;EAGF,MAAM,WAAqB,EAAE;AAC7B,OAAK,MAAM,WAAW,uBAAuB,UAAU;GACrD,MAAM,QAAQ,WAAW,QAAQ;AACjC,OAAI,CAAC,MAAM,MAAM,OAAO,MAAM,UAAU,UAAU;AAChD,gBACE,SACA,UACA,wDACA,oEACD;AACD;;AAEF,YAAS,KAAK,MAAM,MAAM;;AAE5B,OAAK,MAAM,WAAW,SACpB,iBAAgB,SAAS,QAAQ,SAAS,UAAU,QAAQ;AAE9D;;CAGF,MAAM,QACJ,wBAAwB,SAAS,mBACjC,wBAAwB,SAAS,wBAC7B,EAAE,IAAI,OAAgB,GACtB,WAAW,uBAAuB;AAIxC,KAAI,CAAC,MAAM,MAAM,OAAO,MAAM,UAAU,UAAU;AAChD,MAAI,SAAS,WAAY;AACzB,cACE,SACA,UACA,qCAAqC,SAAS,OAAO,SAAS,QAAQ,QACtE,iEACD;AACD;;CAGF,MAAM,UAAU,mBACd,KAAK,UAAU,IACf,UACA,SACA,WACD;AACD,KAAI,CAAC,QAAQ,GAAI;AACjB,KAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,+BAA6B,UAAU,QAAQ;AAC/C;;AAEF,iBAAgB,MAAM,OAAO,QAAQ,SAAS,UAAU,QAAQ;;AAGlE,SAAS,gBACP,QACA,oBACA,UACA,SACM;AACN,SAAQ,QAAQ,KAAK;EACnB,YAAY;EACZ;EACA,UAAU,qBAAqB,SAAS,UAAU,mBAAmB;EACtE,CAAC;;AAGJ,SAAS,mBACP,UACA,UACA,SACA,YACgD;AAChD,KAAI,aAAa,KAAA,EAAW,QAAO,EAAE,IAAI,MAAM;CAC/C,MAAM,UAAU,iBAAiB,SAAS;AAC1C,KAAI,SAAS,SAAS,oBAAoB;AACxC,cACE,SACA,UACA,6DACA,+DACD;AACD,SAAO,EAAE,IAAI,OAAO;;CAGtB,IAAI;AACJ,MAAK,MAAM,YAAY,QAAQ,YAAY;AACzC,MACE,SAAS,SAAS,oBACjB,SAAS,YAAY,SAAS,IAAI,SAAS,iBAC5C;AACA,eACE,SACA,UACA,iEACA,+DACD;AACD,UAAO,EAAE,IAAI,OAAO;;EAEtB,MAAM,MACJ,SAAS,IAAI,SAAS,eAClB,SAAS,IAAI,OACb,SAAS,IAAI,SAAS,kBACpB,SAAS,IAAI,QACb,KAAA;AACR,MAAI,QAAQ,YAAY;AACtB,eACE,SACA,UACA,0CAA0C,MAAM,IAAI,IAAI,KAAK,KAAK,MAAM,EACxE,6DACD;AACD,UAAO,EAAE,IAAI,OAAO;;EAEtB,MAAM,QAAQ,WAAW,SAAS,MAAM;AACxC,MAAI,CAAC,MAAM,MAAM,OAAO,MAAM,UAAU,UAAU;AAChD,eACE,SACA,UACA,gEACA,iEACD;AACD,UAAO,EAAE,IAAI,OAAO;;AAEtB,uBAAqB,MAAM;;AAE7B,QAAO;EAAE,IAAI;EAAM,SAAS;EAAoB;;AAGlD,SAAS,6BACP,UACA,SACM;AACN,aACE,SACA,UACA,mEACA,6EACD"}
@@ -0,0 +1,4 @@
1
+ import { type ParserPlugin } from '@babel/parser';
2
+ import type { RootNode } from '@vue/compiler-dom';
3
+ import type { TemplateBindings, VueExtractionContext } from './types.js';
4
+ export declare function parseVueTemplate(root: RootNode, bindings: TemplateBindings, expressionPlugins: ParserPlugin[], context: VueExtractionContext): void;