@unmagic/vms 0.0.5 → 0.1.1

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.
@@ -0,0 +1,4620 @@
1
+ import { parse } from "@vue/compiler-sfc";
2
+ import fs, { createReadStream, existsSync, readFileSync } from "node:fs";
3
+ import path, { basename, dirname, join, relative, resolve } from "node:path";
4
+ import { mkdir, stat, writeFile } from "node:fs/promises";
5
+ import { createHash } from "node:crypto";
6
+ import { parse as parse$1, parseExpression } from "@babel/parser";
7
+ import * as t$1 from "@babel/types";
8
+ import t from "@babel/types";
9
+ import { generate } from "@babel/generator";
10
+ import _traverse from "@babel/traverse";
11
+ import { codeFrameColumns } from "@babel/code-frame";
12
+ import { bold, green, red } from "kolorist";
13
+ import { createTransformContext, traverseNode } from "@vue/compiler-dom";
14
+ import { fileURLToPath, pathToFileURL } from "node:url";
15
+ import fs$1 from "fs-extra";
16
+ import { NodeTypes } from "@vue/compiler-core";
17
+ import { transformAsync, transformFileAsync, transformFromAstSync } from "@babel/core";
18
+ import { createRequire } from "node:module";
19
+ import chokidar from "chokidar";
20
+ import { getPackageInfo } from "local-pkg";
21
+ import os from "node:os";
22
+ import process$1 from "node:process";
23
+ import { rolldown } from "rolldown";
24
+ import { minify } from "terser";
25
+ import { performance } from "perf_hooks";
26
+ //#endregion
27
+ //#region src/babel.config.ts
28
+ const config = {
29
+ targets: {
30
+ chrome: "60",
31
+ ios: "10"
32
+ },
33
+ assumptions: {
34
+ constantReexports: true,
35
+ constantSuper: true,
36
+ enumerableModuleMeta: true,
37
+ ignoreFunctionLength: true,
38
+ ignoreToPrimitiveHint: true,
39
+ mutableTemplateObject: true,
40
+ noClassCalls: true,
41
+ noDocumentAll: true,
42
+ noNewArrows: true,
43
+ objectRestNoSymbols: true,
44
+ privateFieldsAsProperties: true,
45
+ pureGetters: true,
46
+ setClassMethods: true,
47
+ setComputedProperties: true,
48
+ setPublicClassFields: true,
49
+ setSpreadProperties: true,
50
+ skipForOfIteratorClosing: true,
51
+ superIsCallableConstructor: true
52
+ },
53
+ presets: [["@babel/preset-env", {
54
+ bugfixes: true,
55
+ modules: "commonjs",
56
+ exclude: [
57
+ "@babel/plugin-transform-shorthand-properties",
58
+ "@babel/plugin-transform-arrow-functions",
59
+ "@babel/plugin-transform-template-literals",
60
+ "@babel/plugin-transform-spread",
61
+ "@babel/plugin-transform-destructuring",
62
+ "@babel/plugin-transform-parameters",
63
+ "@babel/plugin-transform-for-of"
64
+ ]
65
+ }], ["@babel/preset-typescript", {
66
+ allowNamespaces: true,
67
+ allowDeclareFields: true,
68
+ optimizeConstEnums: true,
69
+ allExtensions: true,
70
+ isTSX: true
71
+ }]],
72
+ plugins: [
73
+ ["@babel/plugin-transform-runtime", { version: "7.29.2" }],
74
+ "transform-inline-environment-variables",
75
+ ["module-resolver", { alias: { "@": "./src" } }],
76
+ "autocomplete-index"
77
+ ]
78
+ };
79
+ //#endregion
80
+ //#region src/style/index.ts
81
+ function parseStyles(styles) {
82
+ if (!styles || styles.length === 0) return "";
83
+ return styles.map((style) => {
84
+ if (style.scoped) return style.content.replace(/\[data-v-[a-zA-Z0-9]+\]/g, "");
85
+ return style.content;
86
+ }).join("\n");
87
+ }
88
+ //#endregion
89
+ //#region src/utils/babelTraverse.ts
90
+ /**
91
+ * 统一的 @babel/traverse ESM 兼容处理
92
+ *
93
+ * @babel/traverse 的 ESM 导出在某些环境下需要手动解构 default 导出。
94
+ * 此模块封装该兼容逻辑,避免在多个文件中重复相同的 hack。
95
+ */
96
+ const traverse = _traverse.default || _traverse;
97
+ //#endregion
98
+ //#region src/utils/errorHandler.ts
99
+ /**
100
+ * 统一的错误处理工具
101
+ * 使用 @babel/code-frame 输出友好的错误信息
102
+ */
103
+ /**
104
+ * 安全提取错误消息
105
+ * 用于 catch (error: unknown) 场景,替代不安全的 (error as any).message
106
+ */
107
+ function getErrorMessage(error) {
108
+ if (error instanceof Error) return error.message;
109
+ if (typeof error === "string") return error;
110
+ return String(error);
111
+ }
112
+ /**
113
+ * 获取干净的错误消息,剥离 babel 内嵌的 code-frame 和编译后文件路径
114
+ * babel transformAsync 错误 message 格式为: "/path/to/file.js: description (line:col)\n\n> line | code\n"
115
+ * 只保留 "description (line:col)" 部分
116
+ */
117
+ function getCleanErrorMessage(error) {
118
+ const msg = error.message || String(error);
119
+ const firstLine = msg.split("\n")[0];
120
+ if (!firstLine) return msg;
121
+ const colonIndex = firstLine.indexOf(": ");
122
+ if (colonIndex > 0) return firstLine.slice(colonIndex + 2);
123
+ return firstLine;
124
+ }
125
+ /**
126
+ * 从错误对象中提取位置信息
127
+ * 支持两种格式:
128
+ * 1. CompileError 格式:error.cause?.loc(start/end 结构)
129
+ * 2. babel 标准格式:error.loc(line/column 结构)
130
+ */
131
+ function extractErrorLoc(error) {
132
+ const err = error;
133
+ if (err.cause?.loc) return err.cause.loc;
134
+ if (err.loc && typeof err.loc.line === "number" && typeof err.loc.column === "number") return { start: {
135
+ line: err.loc.line,
136
+ column: err.loc.column + 1
137
+ } };
138
+ return null;
139
+ }
140
+ /**
141
+ * 创建带有位置信息的错误
142
+ * @param message 错误消息
143
+ * @param loc 错误位置
144
+ * @returns 错误对象
145
+ */
146
+ function createCompileError(message, loc) {
147
+ const error = new Error(message);
148
+ if (loc) error.cause = { loc };
149
+ return error;
150
+ }
151
+ /**
152
+ * 使用 code-frame 输出错误信息
153
+ * @param source 源代码
154
+ * @param error 错误对象
155
+ * @param filePath 文件路径(可选)
156
+ */
157
+ function printErrorWithCodeFrame(source, error, filePath) {
158
+ const prefix = filePath ? `\n❌ Error in ${filePath}:\n` : "\n❌ Error:\n";
159
+ const loc = extractErrorLoc(error);
160
+ if (loc && source) {
161
+ const codeFrame = codeFrameColumns(source, loc, {
162
+ highlightCode: true,
163
+ message: error.message
164
+ });
165
+ console.error(prefix + codeFrame);
166
+ } else console.error(prefix + error.message);
167
+ if (error.stack) console.error("\nStack trace:", error.stack);
168
+ }
169
+ /**
170
+ * 处理并输出错误
171
+ * 如果错误包含位置信息,使用 code-frame 输出;否则直接输出错误消息
172
+ * @param source 源代码
173
+ * @param error 错误对象
174
+ * @param filePath 文件路径(可选)
175
+ * @returns 是否成功处理了错误(有位置信息)
176
+ */
177
+ function handleCompileError(source, error, filePath) {
178
+ const err = error;
179
+ if (extractErrorLoc(error) && source) {
180
+ printErrorWithCodeFrame(source, err, filePath);
181
+ return true;
182
+ }
183
+ const prefix = filePath ? `❌ Error in ${filePath}: ` : "❌ Error: ";
184
+ console.error(prefix + getCleanErrorMessage(err));
185
+ return false;
186
+ }
187
+ //#endregion
188
+ //#region src/script/macro/expose.ts
189
+ const EXPOSE_KEY = "__vmsExposed__";
190
+ function createComponentExport(path, expression, returnValue) {
191
+ if (t$1.isIdentifier(expression.callee) && expression.callee.name === "defineExpose") if (expression.arguments && expression.arguments.length > 0) {
192
+ const arg = expression.arguments[0];
193
+ if (t$1.isObjectExpression(arg)) {
194
+ let exposeExistIndex = returnValue.properties.findIndex((item) => t$1.isObjectProperty(item) && t$1.isIdentifier(item.key) && item.key.name === EXPOSE_KEY);
195
+ if (exposeExistIndex === -1) exposeExistIndex = returnValue.properties.push(t$1.objectProperty(t$1.identifier(EXPOSE_KEY), t$1.objectExpression([]))) - 1;
196
+ const exposeObjectExpressionProperties = returnValue.properties[exposeExistIndex].value.properties;
197
+ const exposeExportExpression = t$1.objectExpression([]);
198
+ arg.properties.forEach((prop) => {
199
+ if ((t$1.isObjectProperty(prop) || t$1.isObjectMethod(prop)) && t$1.isIdentifier(prop.key)) {
200
+ const key = prop.key.name;
201
+ if (!exposeObjectExpressionProperties.some((p) => (t$1.isObjectProperty(p) || t$1.isObjectMethod(p)) && t$1.isIdentifier(p.key) && p.key.name === key)) {
202
+ exposeObjectExpressionProperties.push(prop);
203
+ exposeExportExpression.properties.push(t$1.objectProperty(prop.key, t$1.memberExpression(t$1.memberExpression(t$1.memberExpression(t$1.thisExpression(), t$1.identifier("data")), t$1.identifier(EXPOSE_KEY)), prop.key)));
204
+ }
205
+ } else throw createCompileError("defineExpose参数必须是对象且属性名必须为identity", prop.loc || void 0);
206
+ });
207
+ path.remove();
208
+ return exposeExportExpression;
209
+ } else {
210
+ console.log(bold(red("defineExpose中传入的参数必须为对象")));
211
+ path.remove();
212
+ return null;
213
+ }
214
+ } else {
215
+ path.remove();
216
+ return null;
217
+ }
218
+ return null;
219
+ }
220
+ //#endregion
221
+ //#region src/script/macro/emits.ts
222
+ function dealMacroEmits(path, decl, defineContextVarName) {
223
+ const eventNameIdentifier = t.identifier("eventName");
224
+ eventNameIdentifier.typeAnnotation = t.tsTypeAnnotation(t.tsStringKeyword());
225
+ const valueIdentifier = t.identifier("value");
226
+ valueIdentifier.typeAnnotation = t.tsTypeAnnotation(t.tsAnyKeyword());
227
+ const arrowFunction = t.arrowFunctionExpression([eventNameIdentifier, valueIdentifier], t.callExpression(t.memberExpression(t.identifier(defineContextVarName), t.identifier("triggerEvent")), [t.identifier("eventName"), t.identifier("value")]));
228
+ const newVarDecl = t.variableDeclaration("const", [t.variableDeclarator(t.identifier(decl.id.name), arrowFunction)]);
229
+ path.replaceWith(newVarDecl);
230
+ }
231
+ //#endregion
232
+ //#region src/script/macro/props.ts
233
+ /**
234
+ * 处理 defineProps 宏
235
+ * - 提取 props 变量名
236
+ * - 收集解构的 props 信息(包括别名和默认值)
237
+ * - 从类型参数中提取未解构的 props
238
+ * - 移除 defineProps 声明
239
+ */
240
+ function dealMacroProps(path, decl, sfcContext) {
241
+ if (t.isIdentifier(decl.id)) sfcContext.propsVarName = decl.id.name;
242
+ else if (t.isObjectPattern(decl.id)) for (const prop of decl.id.properties) {
243
+ if (t.isRestElement(prop)) {
244
+ if (t.isIdentifier(prop.argument)) sfcContext.propsVarRestName = prop.argument.name;
245
+ continue;
246
+ }
247
+ if (!t.isObjectProperty(prop) || !t.isIdentifier(prop.key)) continue;
248
+ const propName = prop.key.name;
249
+ if (t.isAssignmentPattern(prop.value) && t.isIdentifier(prop.value.left)) {
250
+ if (propName === "style" && prop.value.left.name !== "style") sfcContext.propsVarsMap.delete("style");
251
+ sfcContext.propsVarsMap.set(prop.value.left.name, {
252
+ defaultValue: prop.value.right,
253
+ originName: propName,
254
+ isDestructured: true
255
+ });
256
+ } else if (t.isIdentifier(prop.value)) {
257
+ if (propName === "style" && prop.value.name !== "style") sfcContext.propsVarsMap.delete("style");
258
+ sfcContext.propsVarsMap.set(prop.value.name, {
259
+ originName: propName,
260
+ isDestructured: true
261
+ });
262
+ }
263
+ }
264
+ const init = decl.init;
265
+ if (t.isCallExpression(init) && init.typeParameters?.params && init.typeParameters.params.length > 0) {
266
+ const typeParams = init.typeParameters.params[0];
267
+ if (t.isTSTypeLiteral(typeParams)) typeParams.members.forEach((member) => {
268
+ if (t.isTSPropertySignature(member) && t.isIdentifier(member.key)) {
269
+ const aliasName = member.key.name;
270
+ if (!sfcContext.propsVarsMap.has(aliasName)) {
271
+ if (![...sfcContext.propsVarsMap.values()].some((v) => v.originName === aliasName)) sfcContext.propsVarsMap.set(aliasName, {
272
+ originName: aliasName,
273
+ isDestructured: false
274
+ });
275
+ }
276
+ }
277
+ });
278
+ }
279
+ path.remove();
280
+ }
281
+ /**
282
+ * 在 AST 中全局替换 props 变量
283
+ * 将解构的 props 变量(如 record)替换为成员访问(如 __vmsProps.record)
284
+ *
285
+ * @param ast - 要处理的 AST(Program 或 BlockStatement)
286
+ * @param sfcContext - SFC 上下文,包含 props 信息
287
+ *
288
+ * 处理规则:
289
+ * 1. 跳过成员表达式的属性部分(obj.property 中的 property)
290
+ * 2. 跳过对象属性的 key 部分({ key: value } 中的 key)
291
+ * 3. 跳过声明位置(let foo = 1 中的 foo)
292
+ * 4. 保留有效的局部变量(函数内的同名变量)
293
+ * 5. 处理对象简写属性({ foo } → { foo: __vmsProps.foo })
294
+ */
295
+ function replacePropsVariablesInAST(ast, sfcContext) {
296
+ const vmsPropsIdentifier = t.identifier(sfcContext.propsVarName);
297
+ traverse(ast, { Identifier(path) {
298
+ const name = path.node.name;
299
+ const parentNode = path.parentPath.node;
300
+ if (t.isTSTypeLiteral(parentNode) || t.isTSPropertySignature(parentNode) || t.isTSTypeReference(parentNode) || t.isTSInterfaceBody(parentNode) || t.isTSTypeAliasDeclaration(parentNode) || t.isTSTypeParameterInstantiation(parentNode) || t.isTSTypeAnnotation(parentNode)) return;
301
+ if (sfcContext.propsVarRestName && name === sfcContext.propsVarRestName) {
302
+ if (path.parentPath.isMemberExpression() && path.parentPath.node.property === path.node && !path.parentPath.node.computed || path.parentPath.isObjectProperty() && path.parentPath.node.key === path.node && !path.parentPath.node.computed) return;
303
+ if (path.isBindingIdentifier() && (path.parentPath.isVariableDeclarator() || path.parentPath.isFunctionDeclaration() || path.parentPath.isClassDeclaration() || path.parentPath.isCatchClause())) return;
304
+ if (path.scope.hasBinding(name)) {
305
+ const binding = path.scope.getBinding(name);
306
+ if (binding.path) {
307
+ if (!(binding.scope.block === ast) && !binding.path.removed) return;
308
+ }
309
+ }
310
+ path.replaceWith(t.cloneNode(vmsPropsIdentifier));
311
+ return;
312
+ }
313
+ if (path.parentPath.isMemberExpression() && path.parentPath.node.property === path.node && !path.parentPath.node.computed || path.parentPath.isOptionalMemberExpression() && path.parentPath.node.property === path.node && !path.parentPath.node.computed || path.parentPath.isObjectProperty() && path.parentPath.node.key === path.node && !path.parentPath.node.computed) return;
314
+ const propInfo = sfcContext.propsVarsMap.get(name);
315
+ if (!propInfo?.isDestructured) return;
316
+ if (path.isBindingIdentifier() && (path.parentPath.isVariableDeclarator() || path.parentPath.isFunctionDeclaration() || path.parentPath.isClassDeclaration() || path.parentPath.isCatchClause())) return;
317
+ if (path.scope.hasBinding(name)) {
318
+ const binding = path.scope.getBinding(name);
319
+ if (binding.path) {
320
+ if (!(binding.scope.block === ast) && !binding.path.removed) return;
321
+ }
322
+ }
323
+ const replacement = t.memberExpression(t.cloneNode(vmsPropsIdentifier), t.identifier(propInfo.originName));
324
+ if (path.parentPath.isObjectProperty() && path.parentPath.node.value === path.node && path.parentPath.node.shorthand) path.parentPath.node.shorthand = false;
325
+ path.replaceWith(replacement);
326
+ } });
327
+ }
328
+ //#endregion
329
+ //#region src/script/macro/options.ts
330
+ /**
331
+ * 将 Babel AST 节点转换为普通 JS 值(仅支持字面量、数组、对象)
332
+ */
333
+ function astToValue(node) {
334
+ if (t$1.isStringLiteral(node) || t$1.isNumericLiteral(node) || t$1.isBooleanLiteral(node)) return node.value;
335
+ if (t$1.isNullLiteral(node)) return null;
336
+ if (t$1.isArrayExpression(node)) return node.elements.map((el) => {
337
+ if (!el) return null;
338
+ if (t$1.isSpreadElement(el)) throw createCompileError("defineOptions 数组中不支持展开运算符", el.loc || void 0);
339
+ return astToValue(el);
340
+ });
341
+ if (t$1.isObjectExpression(node)) {
342
+ const obj = {};
343
+ for (const prop of node.properties) {
344
+ if (!t$1.isObjectProperty(prop)) throw createCompileError("defineOptions 对象中不支持方法或展开属性", prop.loc || void 0);
345
+ const key = t$1.isIdentifier(prop.key) ? prop.key.name : t$1.isStringLiteral(prop.key) ? prop.key.value : null;
346
+ if (key === null) throw createCompileError("defineOptions 对象的属性名必须是标识符或字符串", prop.loc || void 0);
347
+ obj[key] = astToValue(prop.value);
348
+ }
349
+ return obj;
350
+ }
351
+ throw createCompileError(`defineOptions 不支持动态值(如变量、函数调用等),请使用字面量。节点类型:${node.type}`, node.loc || void 0);
352
+ }
353
+ /**
354
+ * 处理 defineOptions 宏,提取参数对象并移除调用节点
355
+ */
356
+ function dealMacroOptions(path, expression) {
357
+ if (!t$1.isIdentifier(expression.callee) || expression.callee.name !== "defineOptions") return null;
358
+ if (!expression.arguments || expression.arguments.length === 0) {
359
+ path.remove();
360
+ return null;
361
+ }
362
+ const arg = expression.arguments[0];
363
+ if (!t$1.isObjectExpression(arg)) {
364
+ console.log(bold(red("defineOptions 的参数必须是对象字面量")));
365
+ path.remove();
366
+ return null;
367
+ }
368
+ const result = astToValue(arg);
369
+ path.remove();
370
+ return result;
371
+ }
372
+ //#endregion
373
+ //#region src/script/collectImports.ts
374
+ function collectImports(path, sfcContext) {
375
+ const source = path.node.source.value;
376
+ if (!source.endsWith(".vue")) {
377
+ if (source.endsWith(".ts") || source.endsWith(".js")) {
378
+ if (source.startsWith("@/") || source.startsWith("./") || source.startsWith("/") || source.startsWith("../")) path.node.source.value = source.replace(/\.(ts|js)$/, "");
379
+ }
380
+ sfcContext.importAST.push(path.node);
381
+ } else path.node.specifiers.forEach((specifier) => {
382
+ sfcContext.vueComponentImports.push({
383
+ name: specifier.local.name,
384
+ path: source,
385
+ importWay: `${specifier.local.name}`
386
+ });
387
+ });
388
+ path.remove();
389
+ }
390
+ //#endregion
391
+ //#region src/utils/globalWhitelist.ts
392
+ /**
393
+ * 全局变量白名单
394
+ * 这些变量不会被收集到 __vmsRenderState 或 __vmsInternalState
395
+ *
396
+ * 仅包含微信小程序运行时实际存在的全局标识符,
397
+ * 不包含任何 Web / DOM / Node.js 专属 API。
398
+ */
399
+ const GLOBAL_WHITELIST = new Set([
400
+ "wx",
401
+ "getApp",
402
+ "getCurrentPages",
403
+ "Page",
404
+ "Component",
405
+ "App",
406
+ "console",
407
+ "Math",
408
+ "Date",
409
+ "JSON",
410
+ "Object",
411
+ "Array",
412
+ "String",
413
+ "Number",
414
+ "Boolean",
415
+ "RegExp",
416
+ "Error",
417
+ "Promise",
418
+ "Map",
419
+ "Set",
420
+ "WeakMap",
421
+ "WeakSet",
422
+ "Symbol",
423
+ "BigInt",
424
+ "Proxy",
425
+ "Reflect",
426
+ "Intl",
427
+ "undefined",
428
+ "null",
429
+ "true",
430
+ "false",
431
+ "NaN",
432
+ "Infinity",
433
+ "-Infinity",
434
+ "parseInt",
435
+ "parseFloat",
436
+ "isNaN",
437
+ "isFinite",
438
+ "encodeURI",
439
+ "encodeURIComponent",
440
+ "decodeURI",
441
+ "decodeURIComponent",
442
+ "escape",
443
+ "unescape",
444
+ "eval",
445
+ "setTimeout",
446
+ "setInterval",
447
+ "clearTimeout",
448
+ "clearInterval",
449
+ "requestAnimationFrame",
450
+ "cancelAnimationFrame",
451
+ "ArrayBuffer",
452
+ "SharedArrayBuffer",
453
+ "DataView",
454
+ "Float32Array",
455
+ "Float64Array",
456
+ "Int8Array",
457
+ "Int16Array",
458
+ "Int32Array",
459
+ "Uint8Array",
460
+ "Uint16Array",
461
+ "Uint32Array",
462
+ "Uint8ClampedArray",
463
+ "URL",
464
+ "URLSearchParams",
465
+ "TextEncoder",
466
+ "TextDecoder"
467
+ ]);
468
+ /**
469
+ * 检查变量名是否在全局白名单中
470
+ */
471
+ function isGlobalVariable(name) {
472
+ return GLOBAL_WHITELIST.has(name);
473
+ }
474
+ //#endregion
475
+ //#region src/script/scopeAnalyzer.ts
476
+ /**
477
+ * Script 阶段作用域分析器
478
+ * 收集脚本中声明的所有变量及其来源
479
+ */
480
+ /**
481
+ * 创建空的 ScriptScope
482
+ */
483
+ function createEmptyScriptScope() {
484
+ return {
485
+ props: /* @__PURE__ */ new Map(),
486
+ macros: /* @__PURE__ */ new Map(),
487
+ imports: /* @__PURE__ */ new Map(),
488
+ declarations: /* @__PURE__ */ new Map(),
489
+ globals: /* @__PURE__ */ new Set()
490
+ };
491
+ }
492
+ /**
493
+ * 分析脚本作用域
494
+ * @param scriptContent script 内容
495
+ * @param filePath 文件路径(用于错误信息展示)
496
+ * @returns ScriptScope
497
+ */
498
+ function analyzeScriptScope(scriptContent, filePath) {
499
+ const scope = createEmptyScriptScope();
500
+ try {
501
+ traverse(parse$1(scriptContent, {
502
+ sourceType: "module",
503
+ plugins: ["typescript"]
504
+ }), {
505
+ ImportDeclaration(path) {
506
+ path.node.specifiers.forEach((spec) => {
507
+ if (t$1.isImportSpecifier(spec) && t$1.isIdentifier(spec.imported)) {
508
+ const name = spec.local.name;
509
+ scope.imports.set(name, {
510
+ name,
511
+ source: {
512
+ type: "import",
513
+ accessPath: name,
514
+ originalName: spec.imported.name
515
+ }
516
+ });
517
+ } else if (t$1.isImportDefaultSpecifier(spec) || t$1.isImportNamespaceSpecifier(spec)) {
518
+ const name = spec.local.name;
519
+ scope.imports.set(name, {
520
+ name,
521
+ source: {
522
+ type: "import",
523
+ accessPath: name
524
+ }
525
+ });
526
+ }
527
+ });
528
+ },
529
+ VariableDeclaration(path) {
530
+ path.node.declarations.forEach((decl) => {
531
+ if (!t$1.isIdentifier(decl.id)) return;
532
+ const name = decl.id.name;
533
+ if (decl.init && t$1.isCallExpression(decl.init)) switch (t$1.isIdentifier(decl.init.callee) ? decl.init.callee.name : "") {
534
+ case "defineProps":
535
+ handleDefineProps(decl, scope);
536
+ return;
537
+ case "defineEmits":
538
+ handleDefineEmits(decl, scope);
539
+ return;
540
+ case "defineContext":
541
+ handleDefineContext(decl, scope);
542
+ return;
543
+ }
544
+ scope.declarations.set(name, {
545
+ name,
546
+ source: {
547
+ type: "declaration",
548
+ accessPath: "__vmsProxyRefs"
549
+ }
550
+ });
551
+ });
552
+ },
553
+ FunctionDeclaration(path) {
554
+ if (path.node.id) {
555
+ const name = path.node.id.name;
556
+ scope.declarations.set(name, {
557
+ name,
558
+ source: {
559
+ type: "declaration",
560
+ accessPath: "__vmsProxyRefs"
561
+ }
562
+ });
563
+ }
564
+ }
565
+ });
566
+ } catch (error) {
567
+ const loc = extractErrorLoc(error);
568
+ if (loc) {
569
+ const compileError = createCompileError(getErrorMessage(error), loc);
570
+ handleCompileError(scriptContent, compileError, filePath);
571
+ throw compileError;
572
+ }
573
+ console.error(`❌ Failed to parse script${filePath ? ` in ${filePath}` : ""}: ${getErrorMessage(error)}`);
574
+ throw error;
575
+ }
576
+ return scope;
577
+ }
578
+ /**
579
+ * 处理 defineProps
580
+ */
581
+ function handleDefineProps(decl, scope) {
582
+ if (t$1.isIdentifier(decl.id)) {
583
+ scope.propsVarName = decl.id.name;
584
+ return;
585
+ }
586
+ if (t$1.isObjectPattern(decl.id)) decl.id.properties.forEach((prop) => {
587
+ if (t$1.isRestElement(prop) && t$1.isIdentifier(prop.argument)) scope.propsRestName = prop.argument.name;
588
+ else if (t$1.isObjectProperty(prop)) {
589
+ const keyName = t$1.isIdentifier(prop.key) ? prop.key.name : "";
590
+ const valueName = t$1.isIdentifier(prop.value) ? prop.value.name : "";
591
+ if (keyName && valueName) scope.props.set(valueName, {
592
+ name: valueName,
593
+ source: {
594
+ type: "props",
595
+ accessPath: "__vmsProps",
596
+ originalName: keyName
597
+ }
598
+ });
599
+ }
600
+ });
601
+ }
602
+ /**
603
+ * 处理 defineEmits
604
+ */
605
+ function handleDefineEmits(decl, scope) {
606
+ if (t$1.isIdentifier(decl.id)) {
607
+ const name = decl.id.name;
608
+ scope.macros.set(name, {
609
+ name,
610
+ source: {
611
+ type: "macro",
612
+ accessPath: name
613
+ }
614
+ });
615
+ }
616
+ }
617
+ /**
618
+ * 处理 defineContext
619
+ */
620
+ function handleDefineContext(decl, scope) {
621
+ if (t$1.isIdentifier(decl.id)) {
622
+ const name = decl.id.name;
623
+ scope.macros.set(name, {
624
+ name,
625
+ source: {
626
+ type: "macro",
627
+ accessPath: name
628
+ }
629
+ });
630
+ }
631
+ }
632
+ /**
633
+ * 判断变量是否是 props
634
+ */
635
+ function isPropsVariable(name, scope) {
636
+ return scope.props.has(name);
637
+ }
638
+ /**
639
+ * 判断变量是否是宏变量
640
+ */
641
+ function isMacroVariable(name, scope) {
642
+ return scope.macros.has(name);
643
+ }
644
+ /**
645
+ * 判断变量是否是导入的变量
646
+ */
647
+ function isImportVariable(name, scope) {
648
+ return scope.imports.has(name);
649
+ }
650
+ /**
651
+ * 判断变量是否是全局变量
652
+ */
653
+ function isGlobalVariableInScope(name, scope) {
654
+ return scope.globals.has(name) || isGlobalVariable(name);
655
+ }
656
+ //#endregion
657
+ //#region src/script/index.ts
658
+ function checkSlotsUsage(templateContent) {
659
+ if (!templateContent) return false;
660
+ return templateContent.includes("slot") || templateContent.includes("Slot");
661
+ }
662
+ /**
663
+ * 确保 @unmagic/vue-mini 中导入了指定的 specifierName。
664
+ * 如果已存在则跳过,否则追加到已有的 @unmagic/vue-mini import 或新建一个。
665
+ */
666
+ function ensureCoreImport(sfcContext, specifierName) {
667
+ if (sfcContext.importAST.some((importNode) => importNode.source.value === "@unmagic/vue-mini" && importNode.specifiers.some((spec) => t$1.isImportSpecifier(spec) && t$1.isIdentifier(spec.imported) && spec.imported.name === specifierName))) return;
668
+ const vueImport = sfcContext.importAST.find((importNode) => t$1.isImportDeclaration(importNode) && importNode.source.value === "@unmagic/vue-mini");
669
+ if (vueImport && t$1.isImportDeclaration(vueImport)) vueImport.specifiers.push(t$1.importSpecifier(t$1.identifier(specifierName), t$1.identifier(specifierName)));
670
+ else sfcContext.importAST.push(t$1.importDeclaration([t$1.importSpecifier(t$1.identifier(specifierName), t$1.identifier(specifierName))], t$1.stringLiteral("@unmagic/vue-mini")));
671
+ }
672
+ async function extractSetupBodyUsingAST(scriptContent, returnValue, bridgedFunctions, internalVars, renderVars, needsProxyRefs, isPage, scriptScope) {
673
+ let ast;
674
+ try {
675
+ ast = parse$1(scriptContent ?? "", {
676
+ sourceType: "module",
677
+ plugins: ["typescript"],
678
+ ranges: true,
679
+ tokens: true,
680
+ errorRecovery: true
681
+ });
682
+ } catch (error) {
683
+ console.error(`❌ Failed to parse script content: ${getErrorMessage(error)}`);
684
+ ast = {
685
+ type: "File",
686
+ program: {
687
+ type: "Program",
688
+ sourceType: "module",
689
+ directives: [],
690
+ body: []
691
+ }
692
+ };
693
+ }
694
+ const sfcContext = {
695
+ importAST: [],
696
+ propsVarName: "__vmsProps",
697
+ propsVarRestName: void 0,
698
+ contextVarName: "__vmsContext",
699
+ exposeObject: null,
700
+ defineOptionsObject: null,
701
+ vueComponentImports: [],
702
+ functionVarsAndDecl: /* @__PURE__ */ new Set(),
703
+ propsVarsMap: isPage ? /* @__PURE__ */ new Map() : new Map([["style", {
704
+ defaultValue: null,
705
+ originName: "style"
706
+ }]]),
707
+ macroInfoList: []
708
+ };
709
+ traverse(ast, {
710
+ ImportDeclaration(path) {
711
+ collectImports(path, sfcContext);
712
+ },
713
+ VariableDeclaration(path) {
714
+ const decl = path.node.declarations[0];
715
+ if (decl && decl.init && t$1.isCallExpression(decl.init)) switch (t$1.isIdentifier(decl.init.callee) ? decl.init.callee.name : "") {
716
+ case "defineContext":
717
+ if (t$1.isIdentifier(decl.id)) sfcContext.contextVarName = decl.id.name;
718
+ sfcContext.macroInfoList.push({
719
+ path,
720
+ decl,
721
+ type: "defineContext"
722
+ });
723
+ break;
724
+ case "defineProps":
725
+ sfcContext.macroInfoList.push({
726
+ path,
727
+ decl,
728
+ type: "defineProps"
729
+ });
730
+ break;
731
+ case "defineEmits":
732
+ sfcContext.macroInfoList.push({
733
+ path,
734
+ decl,
735
+ type: "defineEmits"
736
+ });
737
+ break;
738
+ }
739
+ },
740
+ FunctionDeclaration(path) {
741
+ const nodeName = path.node.id?.name;
742
+ if (nodeName) sfcContext.functionVarsAndDecl.add(nodeName);
743
+ },
744
+ ExpressionStatement(path) {
745
+ const expression = path.node.expression;
746
+ if (t$1.isCallExpression(expression) && t$1.isIdentifier(expression.callee)) {
747
+ if (expression.callee.name === "defineExpose") sfcContext.macroInfoList.push({
748
+ path,
749
+ expression,
750
+ type: "defineExpose"
751
+ });
752
+ else if (expression.callee.name === "defineOptions") sfcContext.macroInfoList.push({
753
+ path,
754
+ expression,
755
+ type: "defineOptions"
756
+ });
757
+ }
758
+ }
759
+ });
760
+ sfcContext.macroInfoList.forEach((item) => {
761
+ switch (item.type) {
762
+ case "defineContext":
763
+ item.path.remove();
764
+ break;
765
+ case "defineProps":
766
+ dealMacroProps(item.path, item.decl, sfcContext);
767
+ break;
768
+ case "defineEmits":
769
+ dealMacroEmits(item.path, item.decl, sfcContext.contextVarName);
770
+ break;
771
+ case "defineExpose":
772
+ sfcContext.exposeObject = createComponentExport(item.path, item.expression, returnValue);
773
+ break;
774
+ case "defineOptions":
775
+ sfcContext.defineOptionsObject = dealMacroOptions(item.path, item.expression);
776
+ break;
777
+ }
778
+ });
779
+ if ([...sfcContext.propsVarsMap.values()].some((v) => v.isDestructured) || sfcContext.propsVarRestName) {
780
+ replacePropsVariablesInAST(ast.program, sfcContext);
781
+ const aliasPropsToAdd = [];
782
+ let needsComputedImport = false;
783
+ returnValue.properties = returnValue.properties.filter((prop) => {
784
+ if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && prop.shorthand) {
785
+ const propInfo = sfcContext.propsVarsMap.get(prop.key.name);
786
+ if (propInfo?.isDestructured) {
787
+ if (propInfo.originName !== prop.key.name) {
788
+ needsComputedImport = true;
789
+ aliasPropsToAdd.push(t$1.objectProperty(t$1.identifier(prop.key.name), t$1.callExpression(t$1.identifier("computed"), [t$1.arrowFunctionExpression([], t$1.memberExpression(t$1.identifier(sfcContext.propsVarName), t$1.identifier(propInfo.originName)))])));
790
+ }
791
+ return false;
792
+ } else if (sfcContext.propsVarRestName === prop.key.name) {
793
+ aliasPropsToAdd.push(t$1.objectProperty(t$1.identifier(prop.key.name), t$1.identifier(sfcContext.propsVarName)));
794
+ return false;
795
+ }
796
+ }
797
+ return true;
798
+ });
799
+ returnValue.properties.push(...aliasPropsToAdd);
800
+ sfcContext.propsVarsMap.forEach((_, varName) => {
801
+ renderVars.delete(varName);
802
+ internalVars.delete(varName);
803
+ });
804
+ if (needsComputedImport) ensureCoreImport(sfcContext, "computed");
805
+ }
806
+ const setupBody = ast.program.body;
807
+ const hasInlineFunctions = returnValue.properties.some((prop) => t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && prop.key.name.startsWith("__fun_"));
808
+ const inlineFunctions = [];
809
+ const renderProperties = [];
810
+ const internalProperties = [];
811
+ const importProperties = [];
812
+ if (hasInlineFunctions) {
813
+ if (needsProxyRefs) ensureCoreImport(sfcContext, "proxyRefs");
814
+ const renderKeys = /* @__PURE__ */ new Set();
815
+ returnValue.properties.forEach((prop) => {
816
+ if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key)) {
817
+ if (!prop.key.name.startsWith("__fun_") && renderVars.has(prop.key.name)) renderKeys.add(prop.key.name);
818
+ }
819
+ });
820
+ const allPropsVarNames = new Set([...sfcContext.propsVarsMap.keys(), ...sfcContext.propsVarRestName ? [sfcContext.propsVarRestName] : []]);
821
+ if (allPropsVarNames.size > 0) returnValue.properties.forEach((prop) => {
822
+ if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && prop.key.name.startsWith("__fun_") && (t$1.isFunctionExpression(prop.value) || t$1.isArrowFunctionExpression(prop.value))) replacePropsAccessInFunction(prop.value, allPropsVarNames, sfcContext.propsVarName);
823
+ });
824
+ returnValue.properties.forEach((prop) => {
825
+ if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && prop.key.name.startsWith("__fun_")) inlineFunctions.push(prop);
826
+ else if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && internalVars.has(prop.key.name) && !renderKeys.has(prop.key.name)) internalProperties.push(prop);
827
+ else if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key) && scriptScope && isImportVariable(prop.key.name, scriptScope)) importProperties.push(prop);
828
+ else renderProperties.push(prop);
829
+ });
830
+ setupBody.forEach((statement) => {
831
+ if (t$1.isFunctionDeclaration(statement) && statement.id) {
832
+ if (bridgedFunctions.has(statement.id.name)) return;
833
+ const prop = t$1.objectProperty(t$1.identifier(statement.id.name), t$1.identifier(statement.id.name), false, true);
834
+ if (internalVars.has(statement.id.name) && !renderKeys.has(statement.id.name)) internalProperties.push(prop);
835
+ else renderProperties.push(prop);
836
+ }
837
+ });
838
+ const setupStateDecl = t$1.variableDeclaration("const", [t$1.variableDeclarator(t$1.identifier("__vmsRenderState"), t$1.objectExpression(renderProperties))]);
839
+ const hasInternalState = internalProperties.length > 0;
840
+ const inlineFunctionDecls = [];
841
+ inlineFunctions.forEach((prop) => {
842
+ const funcValue = prop.value;
843
+ const isArrow = t$1.isArrowFunctionExpression(funcValue);
844
+ const isFuncExpr = t$1.isFunctionExpression(funcValue);
845
+ if (isArrow || isFuncExpr) {
846
+ const funcName = prop.key.name;
847
+ const params = funcValue.params;
848
+ const body = funcValue.body;
849
+ const isAsync = funcValue.async || false;
850
+ const funcDecl = t$1.functionDeclaration(t$1.identifier(funcName), params, t$1.isBlockStatement(body) ? body : t$1.blockStatement([t$1.returnStatement(body)]), false, isAsync);
851
+ inlineFunctionDecls.push(funcDecl);
852
+ inlineFunctionDecls.push(t$1.expressionStatement(t$1.assignmentExpression("=", t$1.memberExpression(t$1.identifier("__vmsRenderState"), t$1.identifier(funcName)), t$1.identifier(funcName))));
853
+ }
854
+ });
855
+ setupBody.push(setupStateDecl);
856
+ if (hasInternalState) setupBody.push(t$1.variableDeclaration("const", [t$1.variableDeclarator(t$1.identifier("__vmsInternalState"), t$1.objectExpression(internalProperties))]));
857
+ if (needsProxyRefs) {
858
+ const proxyRefsArg = hasInternalState ? t$1.objectExpression([t$1.spreadElement(t$1.identifier("__vmsRenderState")), t$1.spreadElement(t$1.identifier("__vmsInternalState"))]) : t$1.identifier("__vmsRenderState");
859
+ setupBody.push(t$1.variableDeclaration("const", [t$1.variableDeclarator(t$1.identifier("__vmsProxyRefs"), t$1.callExpression(t$1.identifier("proxyRefs"), [proxyRefsArg]))]));
860
+ }
861
+ setupBody.push(...inlineFunctionDecls);
862
+ if (importProperties.length > 0) {
863
+ const returnObject = t$1.objectExpression([t$1.spreadElement(t$1.identifier("__vmsRenderState")), ...importProperties]);
864
+ setupBody.push(t$1.returnStatement(returnObject));
865
+ } else setupBody.push(t$1.returnStatement(t$1.identifier("__vmsRenderState")));
866
+ } else if (importProperties.length > 0) {
867
+ const nonImportProperties = returnValue.properties.filter((prop) => {
868
+ if (t$1.isObjectProperty(prop) && t$1.isIdentifier(prop.key)) return !(scriptScope && isImportVariable(prop.key.name, scriptScope));
869
+ return true;
870
+ });
871
+ const newReturnValue = t$1.objectExpression([...nonImportProperties, ...importProperties]);
872
+ setupBody.push(t$1.returnStatement(newReturnValue));
873
+ } else setupBody.push(t$1.returnStatement(returnValue));
874
+ return {
875
+ sfcContext,
876
+ setupFunAst: t$1.objectMethod("method", t$1.identifier("setup"), [t$1.identifier(sfcContext.propsVarName), t$1.identifier(sfcContext.contextVarName)], t$1.blockStatement(setupBody))
877
+ };
878
+ }
879
+ async function parseScript(descriptor, returnValue, bridgedFunctions = /* @__PURE__ */ new Set(), internalVars = /* @__PURE__ */ new Set(), renderVars = /* @__PURE__ */ new Set(), needsProxyRefs = false, isPage = false, scriptScope) {
880
+ const script = descriptor.scriptSetup?.content;
881
+ const hasSlots = checkSlotsUsage(descriptor.template?.content);
882
+ const { sfcContext, setupFunAst } = await extractSetupBodyUsingAST(script, returnValue, bridgedFunctions, internalVars, renderVars, needsProxyRefs, isPage, scriptScope);
883
+ const programBody = [t$1.importDeclaration([t$1.importSpecifier(t$1.identifier("defineComponent"), t$1.identifier("defineComponent"))], t$1.stringLiteral("@unmagic/vue-mini")), ...sfcContext.importAST];
884
+ const defineComponentParams = [t$1.objectProperty(t$1.identifier("behaviors"), t$1.arrayExpression([t$1.stringLiteral("wx://component-export")]))];
885
+ if (sfcContext.propsVarsMap.size > 0) defineComponentParams.push(t$1.objectProperty(t$1.identifier("properties"), t$1.objectExpression([...sfcContext.propsVarsMap].map(([_aliasName, { defaultValue, originName }]) => {
886
+ return t$1.objectProperty(t$1.identifier(originName), t$1.objectExpression(defaultValue ? [t$1.objectProperty(t$1.identifier("type"), t$1.nullLiteral()), t$1.objectProperty(t$1.identifier("value"), defaultValue)] : [t$1.objectProperty(t$1.identifier("type"), t$1.nullLiteral())]));
887
+ }))));
888
+ const optionsProperties = [];
889
+ if (hasSlots) optionsProperties.push(t$1.objectProperty(t$1.identifier("multipleSlots"), t$1.booleanLiteral(true)));
890
+ let isPushVirtualHost = false;
891
+ if (sfcContext.defineOptionsObject) {
892
+ if (Object.hasOwn(sfcContext.defineOptionsObject, "virtualHost")) {
893
+ const virtualHostVal = sfcContext.defineOptionsObject.virtualHost;
894
+ optionsProperties.push(t$1.objectProperty(t$1.identifier("virtualHost"), typeof virtualHostVal === "boolean" ? t$1.booleanLiteral(virtualHostVal) : t$1.valueToNode(virtualHostVal)));
895
+ isPushVirtualHost = true;
896
+ const { virtualHost: _removed, ...rest } = sfcContext.defineOptionsObject;
897
+ sfcContext.defineOptionsObject = Object.keys(rest).length > 0 ? rest : null;
898
+ }
899
+ }
900
+ if (!isPushVirtualHost && !isPage) optionsProperties.push(t$1.objectProperty(t$1.identifier("virtualHost"), t$1.booleanLiteral(true)));
901
+ if (optionsProperties.length > 0) defineComponentParams.push(t$1.objectProperty(t$1.identifier("options"), t$1.objectExpression(optionsProperties)));
902
+ if (!isPage && ![...sfcContext.propsVarsMap.values()].some((v) => v.originName === "class")) defineComponentParams.push(t$1.objectProperty(t$1.identifier("externalClasses"), t$1.arrayExpression([t$1.stringLiteral("class")])));
903
+ if (sfcContext.exposeObject) defineComponentParams.push(t$1.objectMethod("method", t$1.identifier("export"), [], t$1.blockStatement([t$1.returnStatement(sfcContext.exposeObject)])));
904
+ defineComponentParams.push(setupFunAst);
905
+ programBody.push(t$1.expressionStatement(t$1.callExpression(t$1.identifier("defineComponent"), [t$1.objectExpression(defineComponentParams)])));
906
+ return {
907
+ script: generate(t$1.program(programBody)).code,
908
+ vueComponentImports: sfcContext.vueComponentImports,
909
+ hasSlots,
910
+ sfcContext,
911
+ defineOptionsObject: sfcContext.defineOptionsObject
912
+ };
913
+ }
914
+ /**
915
+ * 替换函数中的 props 变量访问
916
+ * 将 __vmsProxyRefs.propName 替换为 __vmsProps.propName
917
+ * 使用 Babel VISITOR_KEYS 进行正确的 AST 遍历,
918
+ * 只访问有意义的子节点,避免遍历 Babel 内部属性。
919
+ */
920
+ function replacePropsAccessInFunction(func, propsVarNames, propsVarName) {
921
+ function traverseNode(node) {
922
+ if (!node || typeof node !== "object") return;
923
+ if (t$1.isMemberExpression(node)) {
924
+ if (t$1.isIdentifier(node.object, { name: "__vmsProxyRefs" }) && t$1.isIdentifier(node.property) && propsVarNames.has(node.property.name)) node.object = t$1.identifier(propsVarName);
925
+ }
926
+ const visitorKeys = t$1.VISITOR_KEYS[node.type];
927
+ if (!visitorKeys) return;
928
+ for (const key of visitorKeys) {
929
+ const value = node[key];
930
+ if (Array.isArray(value)) {
931
+ for (const child of value) if (child && typeof child === "object" && Object.hasOwn(child, "type")) traverseNode(child);
932
+ } else if (value && typeof value === "object" && Object.hasOwn(value, "type")) traverseNode(value);
933
+ }
934
+ }
935
+ traverseNode(func);
936
+ }
937
+ //#endregion
938
+ //#region src/utils/configLoader.ts
939
+ async function loadUserConfig() {
940
+ for (const configFile of [
941
+ "vms.config.js",
942
+ "vms.config.ts",
943
+ "vms.config.mjs"
944
+ ]) {
945
+ const configPath = resolve(configFile);
946
+ if (fs$1.existsSync(configPath)) try {
947
+ const config = await import(pathToFileURL(configPath).href);
948
+ return config.default || config.config;
949
+ } catch (error) {
950
+ console.warn(`配置文件 ${configFile} 加载失败:`, getErrorMessage(error));
951
+ }
952
+ }
953
+ return Promise.reject("未找到配置文件");
954
+ }
955
+ //#endregion
956
+ //#region src/utils/componentMatcher.ts
957
+ var ComponentMatcher = class {
958
+ prefix = "";
959
+ pathPrefix = "";
960
+ exactMatches = /* @__PURE__ */ new Map();
961
+ isConfigPrefix = false;
962
+ isConfigMatch = false;
963
+ constructor(config) {
964
+ if (config) {
965
+ if (!config.prefix && config.pathPrefix || config.prefix && !config.pathPrefix) throw new Error("请设置组件匹配的前缀和路径前缀");
966
+ if (config.prefix && config.pathPrefix) {
967
+ this.prefix = config.prefix;
968
+ this.pathPrefix = config.pathPrefix;
969
+ this.isConfigPrefix = true;
970
+ }
971
+ if (config.match?.length) {
972
+ config.match.forEach((item) => {
973
+ this.exactMatches.set(item.name, item.path);
974
+ });
975
+ this.isConfigMatch = true;
976
+ }
977
+ }
978
+ }
979
+ /**
980
+ * 根据组件名称匹配组件路径
981
+ * @param componentName 组件名称
982
+ * @returns 匹配的组件路径,如果没有匹配则返回null
983
+ */
984
+ match(componentName) {
985
+ if (this.exactMatches.has(componentName)) return this.exactMatches.get(componentName) || null;
986
+ if (this.isConfigPrefix && componentName.startsWith(this.prefix)) {
987
+ const relativePath = componentName.slice(this.prefix.length);
988
+ const path = `${this.pathPrefix}/${relativePath}/${relativePath}`;
989
+ if (!this.exactMatches.has(componentName)) {
990
+ this.exactMatches.set(componentName, path);
991
+ this.isConfigMatch = true;
992
+ }
993
+ return path;
994
+ }
995
+ return null;
996
+ }
997
+ /**
998
+ * 检查是否存在任何匹配配置
999
+ */
1000
+ hasConfig() {
1001
+ return this.isConfigPrefix || this.isConfigMatch;
1002
+ }
1003
+ };
1004
+ //#endregion
1005
+ //#region src/utils/constants.ts
1006
+ const userConfig = await loadUserConfig();
1007
+ if (!userConfig.wx) throw new Error("请在vms.config.*s中配置完整的wx");
1008
+ process.env.APP_VERSION = userConfig.wx.version;
1009
+ if (!userConfig.sourceDir) userConfig.sourceDir = "src";
1010
+ if (!userConfig.outputDir) userConfig.outputDir = "dist";
1011
+ const OUTPUT_DIR = path.resolve(userConfig.outputDir, "dev");
1012
+ const POLYFILL_OUTPUT_DIR = path.resolve(OUTPUT_DIR, "polyfill");
1013
+ const getComponentMatcher = new ComponentMatcher(userConfig.component);
1014
+ function findPolyfillDirectory(baseDir) {
1015
+ let polyfillPath = path.resolve(baseDir, "polyfill");
1016
+ if (fs.existsSync(polyfillPath)) return polyfillPath;
1017
+ polyfillPath = path.resolve(baseDir, "../../polyfill");
1018
+ if (fs.existsSync(polyfillPath)) return polyfillPath;
1019
+ throw new Error("找不到Polyfill文件夹");
1020
+ }
1021
+ const POLYFILL_VMS_DIR = findPolyfillDirectory(path.dirname(fileURLToPath(import.meta.url)));
1022
+ const WX_TAG_MAP = new Map([
1023
+ ["div", "view"],
1024
+ ["img", "image"],
1025
+ ["template", "block"]
1026
+ ]);
1027
+ const WXS_NAMESPACE = "wms_wxs";
1028
+ //#endregion
1029
+ //#region src/utils/ast.ts
1030
+ /**
1031
+ * 获取表达式的AST,可解析 Typescript 语法
1032
+ * @param expression
1033
+ */
1034
+ function getExpressionTSAst(expression) {
1035
+ return parseExpression(expression, { plugins: ["typescript"] });
1036
+ }
1037
+ /**
1038
+ * 获取AST中,非父级v-for的变量
1039
+ * @param ast
1040
+ * @param vForVars
1041
+ */
1042
+ function getIdentifiersWithoutVForVariables(ast, vForVars) {
1043
+ try {
1044
+ const identifiers = /* @__PURE__ */ new Set();
1045
+ collectVariablesFromAST(ast, identifiers);
1046
+ vForVars.forEach((vForVar) => identifiers.delete(vForVar));
1047
+ return identifiers;
1048
+ } catch (error) {
1049
+ console.error(`❌ 解析表达式时出错: ${getErrorMessage(error)}`);
1050
+ return /* @__PURE__ */ new Set();
1051
+ }
1052
+ }
1053
+ /**
1054
+ * 从AST中收集变量
1055
+ * @param node
1056
+ * @param variables
1057
+ * @param excludedVars
1058
+ */
1059
+ function collectVariablesFromAST(node, variables, excludedVars) {
1060
+ if (!node) return;
1061
+ switch (node.type) {
1062
+ case "Identifier":
1063
+ if (!excludedVars || !excludedVars.has(node.name)) variables.add(node.name);
1064
+ break;
1065
+ case "MemberExpression":
1066
+ if (node.object.type === "Identifier") {
1067
+ if (!excludedVars || !excludedVars.has(node.object.name)) variables.add(node.object.name);
1068
+ } else collectVariablesFromAST(node.object, variables, excludedVars);
1069
+ if (node.computed) collectVariablesFromAST(node.property, variables, excludedVars);
1070
+ break;
1071
+ case "OptionalMemberExpression":
1072
+ if (node.object.type === "Identifier") {
1073
+ if (!excludedVars || !excludedVars.has(node.object.name)) variables.add(node.object.name);
1074
+ } else collectVariablesFromAST(node.object, variables, excludedVars);
1075
+ if (node.computed) collectVariablesFromAST(node.property, variables, excludedVars);
1076
+ break;
1077
+ case "BinaryExpression":
1078
+ case "LogicalExpression":
1079
+ collectVariablesFromAST(node.left, variables, excludedVars);
1080
+ collectVariablesFromAST(node.right, variables, excludedVars);
1081
+ break;
1082
+ case "UnaryExpression":
1083
+ collectVariablesFromAST(node.argument, variables, excludedVars);
1084
+ break;
1085
+ case "ConditionalExpression":
1086
+ collectVariablesFromAST(node.test, variables, excludedVars);
1087
+ collectVariablesFromAST(node.consequent, variables, excludedVars);
1088
+ collectVariablesFromAST(node.alternate, variables, excludedVars);
1089
+ break;
1090
+ case "CallExpression":
1091
+ case "OptionalCallExpression":
1092
+ collectVariablesFromAST(node.callee, variables, excludedVars);
1093
+ node.arguments.forEach((arg) => collectVariablesFromAST(arg, variables, excludedVars));
1094
+ if (node.callee && node.callee.type === "Identifier") {}
1095
+ break;
1096
+ case "FunctionDeclaration":
1097
+ case "FunctionExpression":
1098
+ case "ArrowFunctionExpression": {
1099
+ const paramNames = /* @__PURE__ */ new Set();
1100
+ const localVariables = excludedVars ?? /* @__PURE__ */ new Set();
1101
+ if (node.params) node.params.forEach((param) => {
1102
+ if (param.type === "Identifier") paramNames.add(param.name);
1103
+ else if (param.type === "ObjectPattern") collectPatternVariables(param, paramNames);
1104
+ else if (param.type === "ArrayPattern") collectPatternVariables(param, paramNames);
1105
+ });
1106
+ if (node.body) {
1107
+ const functionBodyVariables = /* @__PURE__ */ new Set();
1108
+ collectVariablesFromAST(node.body, functionBodyVariables, localVariables);
1109
+ functionBodyVariables.forEach((variable) => {
1110
+ if (!paramNames.has(variable) && !localVariables.has(variable)) variables.add(variable);
1111
+ });
1112
+ }
1113
+ if (node.type === "FunctionDeclaration" && node.id && node.id.name) variables.add(node.id.name);
1114
+ break;
1115
+ }
1116
+ case "VariableDeclaration":
1117
+ node.declarations.forEach((declaration) => {
1118
+ const localVariables = excludedVars ?? /* @__PURE__ */ new Set();
1119
+ if (declaration.id.type !== "VoidPattern") collectPatternVariables(declaration.id, localVariables);
1120
+ if (declaration.init) collectVariablesFromAST(declaration.init, variables, localVariables);
1121
+ });
1122
+ break;
1123
+ case "BlockStatement":
1124
+ if (node.body) node.body.forEach((statement) => {
1125
+ collectVariablesFromAST(statement, variables, excludedVars);
1126
+ });
1127
+ break;
1128
+ case "ReturnStatement":
1129
+ if (node.argument) collectVariablesFromAST(node.argument, variables, excludedVars);
1130
+ break;
1131
+ case "ObjectExpression":
1132
+ if (node.properties) node.properties.forEach((property) => {
1133
+ if (property.type === "ObjectProperty") {
1134
+ if (property.computed) collectVariablesFromAST(property.key, variables, excludedVars);
1135
+ collectVariablesFromAST(property.value, variables, excludedVars);
1136
+ } else if (property.type === "ObjectMethod") {
1137
+ if (property.body) collectVariablesFromAST(property.body, variables, excludedVars);
1138
+ } else if (property.type === "SpreadElement") collectVariablesFromAST(property.argument, variables, excludedVars);
1139
+ });
1140
+ break;
1141
+ case "TemplateLiteral":
1142
+ if (node.expressions) node.expressions.forEach((expr) => {
1143
+ collectVariablesFromAST(expr, variables, excludedVars);
1144
+ });
1145
+ break;
1146
+ case "TSAsExpression":
1147
+ case "TSTypeAssertion":
1148
+ collectVariablesFromAST(node.expression, variables, excludedVars);
1149
+ break;
1150
+ case "TSNonNullExpression":
1151
+ collectVariablesFromAST(node.expression, variables, excludedVars);
1152
+ break;
1153
+ case "TSEnumDeclaration":
1154
+ if (node.id && node.id.type === "Identifier") variables.add(node.id.name);
1155
+ if (node.members) node.members.forEach((member) => {
1156
+ if (member.initializer) collectVariablesFromAST(member.initializer, variables, excludedVars);
1157
+ });
1158
+ break;
1159
+ case "TSInterfaceDeclaration":
1160
+ case "TSTypeAliasDeclaration":
1161
+ if (node.id && node.id.type === "Identifier") variables.add(node.id.name);
1162
+ break;
1163
+ }
1164
+ }
1165
+ function collectPatternVariables(pattern, variables) {
1166
+ switch (pattern.type) {
1167
+ case "Identifier":
1168
+ variables.add(pattern.name);
1169
+ break;
1170
+ case "ObjectPattern":
1171
+ pattern.properties.forEach((prop) => {
1172
+ if (prop.type === "ObjectProperty") collectPatternVariables(prop.value, variables);
1173
+ else if (prop.type === "RestElement") collectPatternVariables(prop.argument, variables);
1174
+ });
1175
+ break;
1176
+ case "ArrayPattern":
1177
+ pattern.elements.forEach((element) => {
1178
+ if (element) collectPatternVariables(element, variables);
1179
+ });
1180
+ break;
1181
+ case "RestElement":
1182
+ collectPatternVariables(pattern.argument, variables);
1183
+ break;
1184
+ }
1185
+ }
1186
+ /**
1187
+ * 从模板的表达式AST中提取变量
1188
+ * @param ast
1189
+ * @return {string[]}
1190
+ */
1191
+ function extractVariablesFromExpressionAST(ast) {
1192
+ try {
1193
+ const variables = /* @__PURE__ */ new Set();
1194
+ collectVariablesFromAST(ast, variables);
1195
+ GLOBAL_WHITELIST.forEach((builtIn) => variables.delete(builtIn));
1196
+ return Array.from(variables);
1197
+ } catch (e) {
1198
+ console.warn("Failed to extract variables from expression:", ast.loc?.source, e);
1199
+ return [];
1200
+ }
1201
+ }
1202
+ //#endregion
1203
+ //#region src/template/tools.ts
1204
+ /**
1205
+ * 创建编译期上下文,每次 parseTemplate 调用时新建,不跨编译复用
1206
+ * @param scriptScope 可选的 ScriptScope,用于变量来源分析
1207
+ */
1208
+ function createVMSTransformContext(scriptScope) {
1209
+ return {
1210
+ vForInfoMap: /* @__PURE__ */ new WeakMap(),
1211
+ bridgedFunctions: /* @__PURE__ */ new Set(),
1212
+ internalVars: /* @__PURE__ */ new Set(),
1213
+ renderVars: /* @__PURE__ */ new Set(),
1214
+ needsProxyRefs: false,
1215
+ scriptScope,
1216
+ rootElementNode: null
1217
+ };
1218
+ }
1219
+ function setVForInfoList(ctx, node, list) {
1220
+ ctx.vForInfoMap.set(node, list);
1221
+ }
1222
+ function getVForInfoList(ctx, node) {
1223
+ return ctx.vForInfoMap.get(node);
1224
+ }
1225
+ /**
1226
+ * 获取或创建节点的 codegenNode
1227
+ * 节点自身持有 codegenNode,不再通过 ctx 存储
1228
+ */
1229
+ function getCodegenNode(node) {
1230
+ return node.__vmsCodegenNode;
1231
+ }
1232
+ /**
1233
+ * 获取或创建节点的 codegenNode 下的 Props
1234
+ * 节点自身持有 codegenNode,不再通过 ctx 存储
1235
+ */
1236
+ function getCodegenNodeProps(node) {
1237
+ return getCodegenNode(node)?.props ?? /* @__PURE__ */ new Map();
1238
+ }
1239
+ /**
1240
+ * 设置节点的 codegenNode
1241
+ * @param forceUpdate 是否强制更新 codegenNode
1242
+ */
1243
+ function setCodegenNode(node, codegenNode) {
1244
+ const existingCodegen = getCodegenNode(node);
1245
+ if (existingCodegen?.tag?.startsWith("_vms_")) {
1246
+ node.__vmsCodegenNode = codegenNode;
1247
+ if (codegenNode) node.__vmsCodegenNode.tag = existingCodegen.tag;
1248
+ } else node.__vmsCodegenNode = codegenNode;
1249
+ }
1250
+ /**
1251
+ * 判断是否为 v-for 属性
1252
+ * @param prop
1253
+ */
1254
+ function isVForProp(prop) {
1255
+ return prop.type === NodeTypes.DIRECTIVE && prop.rawName === "v-for";
1256
+ }
1257
+ /**
1258
+ * 判断节点是否为 v-for 节点
1259
+ * @param node
1260
+ */
1261
+ function isVForNode(node) {
1262
+ return node.props?.find(isVForProp);
1263
+ }
1264
+ /**
1265
+ * 收集第三方组件及小程序原生的自定义组件库
1266
+ * @param node
1267
+ * @param thirdPartyComponents
1268
+ */
1269
+ function collectThirdComponents(node, thirdPartyComponents) {
1270
+ const tag = node.tag;
1271
+ if (node.type === 1) {
1272
+ if (tag) {
1273
+ const path = getComponentMatcher.match(tag);
1274
+ if (path) thirdPartyComponents.set(tag, path);
1275
+ }
1276
+ }
1277
+ }
1278
+ /**
1279
+ * 添加返回值变量(内部路径,不标记为渲染变量)
1280
+ * @param {ObjectExpression} returnValue
1281
+ * @param {string} key
1282
+ */
1283
+ function addProperty(returnValue, key) {
1284
+ if (!returnValue.properties.some((p) => p.key.name === key)) {
1285
+ const bindingVarId = t$1.identifier(key);
1286
+ returnValue.properties.push(t$1.objectProperty(bindingVarId, bindingVarId, false, true));
1287
+ }
1288
+ }
1289
+ /**
1290
+ * 添加返回值变量,并标记为模板直接绑定的渲染变量
1291
+ * @param {ObjectExpression} returnValue
1292
+ * @param {string} key
1293
+ * @param {VMSTransformContext} ctx
1294
+ */
1295
+ /**
1296
+ * 检查变量是否应该被收集到 render state
1297
+ * 使用 scriptScope 进行变量来源分析
1298
+ * @returns 'render' | 'import' | 'skip' - 分别表示:收集到 renderVars、是导入变量、跳过
1299
+ */
1300
+ function shouldCollectVariable(varName, scriptScope) {
1301
+ if (!scriptScope) return "render";
1302
+ if (isPropsVariable(varName, scriptScope)) return "skip";
1303
+ if (isMacroVariable(varName, scriptScope)) return "skip";
1304
+ if (isGlobalVariableInScope(varName, scriptScope)) return "skip";
1305
+ if (isImportVariable(varName, scriptScope)) return "import";
1306
+ return "render";
1307
+ }
1308
+ function addRenderProperty(returnValue, key, ctx) {
1309
+ const collectType = shouldCollectVariable(key, ctx.scriptScope);
1310
+ if (collectType === "skip") return;
1311
+ addProperty(returnValue, key);
1312
+ if (collectType === "render") ctx.renderVars.add(key);
1313
+ }
1314
+ /**
1315
+ * 根据表达式,收集setup的返回值变量,并排除掉指定的变量名称
1316
+ */
1317
+ function collectBindingVarsWithExpression(expression, node, returnValue, ctx, excludedBindingVars = []) {
1318
+ const extraBindingVars = getIdentifiersWithoutVForVariables(getExpressionTSAst(expression), getVForVariables(ctx, node));
1319
+ excludedBindingVars.forEach((item) => extraBindingVars.delete(item));
1320
+ extraBindingVars.forEach((bindingVar) => {
1321
+ addRenderProperty(returnValue, bindingVar, ctx);
1322
+ });
1323
+ }
1324
+ /**
1325
+ * 根据AST,收集setup的返回值变量,并排除掉指定的变量名称
1326
+ * 现在使用 scriptScope 进行更精确的变量来源分析
1327
+ */
1328
+ function collectBindingVarsWithAST(ast, node, returnValue, ctx, excludedBindingVars = []) {
1329
+ const extraBindingVars = getIdentifiersWithoutVForVariables(ast, getVForVariables(ctx, node));
1330
+ excludedBindingVars.forEach((item) => extraBindingVars.delete(item));
1331
+ extraBindingVars.forEach((varName) => {
1332
+ if (shouldCollectVariable(varName, ctx.scriptScope) === "skip") return;
1333
+ addRenderProperty(returnValue, varName, ctx);
1334
+ });
1335
+ }
1336
+ /**
1337
+ * 根据变量名,收集setup的返回值变量
1338
+ */
1339
+ function collectBindingVarsWithVarName(varName, node, returnValue, ctx) {
1340
+ if (getVForVariables(ctx, node).has(varName)) return;
1341
+ addRenderProperty(returnValue, varName, ctx);
1342
+ }
1343
+ /**
1344
+ * 根据变量名列表,收集setup的返回值变量
1345
+ */
1346
+ function collectBindingVarsWithVarNameList(varNameList, node, returnValue, ctx) {
1347
+ const vForVars = getVForVariables(ctx, node);
1348
+ varNameList.filter((item) => !vForVars.has(item)).forEach((varName) => addRenderProperty(returnValue, varName, ctx));
1349
+ }
1350
+ /**
1351
+ * WXS 环境中可安全调用的全局标识符白名单
1352
+ */
1353
+ const WXS_SAFE_GLOBALS = new Set([
1354
+ "String",
1355
+ "Number",
1356
+ "Boolean",
1357
+ "parseInt",
1358
+ "parseFloat",
1359
+ "isNaN",
1360
+ "isFinite",
1361
+ "Math",
1362
+ "Date",
1363
+ "JSON"
1364
+ ]);
1365
+ /**
1366
+ * 检查调用表达式是否包含外部函数调用
1367
+ * @param node
1368
+ * @returns {boolean}
1369
+ */
1370
+ function containsExternalFunctionCall(node) {
1371
+ if (node.callee?.type === "Identifier") {
1372
+ if (WXS_SAFE_GLOBALS.has(node.callee.name)) return false;
1373
+ return true;
1374
+ }
1375
+ return false;
1376
+ }
1377
+ /**
1378
+ * 检查表达式AST中是否包含外部函数调用
1379
+ * @param ast
1380
+ * @returns {boolean}
1381
+ */
1382
+ function containsExternalFunctionInExpression(ast) {
1383
+ if (!ast) return false;
1384
+ let hasExternalFunction = false;
1385
+ function traverse(node) {
1386
+ if (!node || hasExternalFunction) return;
1387
+ if (node.type === "CallExpression") {
1388
+ if (containsExternalFunctionCall(node)) {
1389
+ hasExternalFunction = true;
1390
+ return;
1391
+ }
1392
+ }
1393
+ for (const key in node) if (Object.prototype.hasOwnProperty.call(node, key)) {
1394
+ const child = node[key];
1395
+ if (typeof child === "object" && child !== null) if (Array.isArray(child)) child.forEach(traverse);
1396
+ else traverse(child);
1397
+ }
1398
+ }
1399
+ traverse(ast);
1400
+ return hasExternalFunction;
1401
+ }
1402
+ /**
1403
+ * 检查表达式是否为复杂表达式
1404
+ * @param ast
1405
+ * @returns {boolean}
1406
+ */
1407
+ function isComplexExpression(ast) {
1408
+ if (!ast) return false;
1409
+ switch (ast.type) {
1410
+ case "StringLiteral":
1411
+ case "NumericLiteral":
1412
+ case "BooleanLiteral":
1413
+ case "Identifier":
1414
+ case "NullLiteral": return false;
1415
+ case "ConditionalExpression": return true;
1416
+ case "UnaryExpression":
1417
+ if (ast.operator === "typeof") return true;
1418
+ return isComplexExpression(ast.argument);
1419
+ case "BinaryExpression": return isComplexExpression(ast.left) || isComplexExpression(ast.right);
1420
+ case "MemberExpression": return isComplexExpression(ast.object) || isComplexExpression(ast.property);
1421
+ case "OptionalMemberExpression": return true;
1422
+ case "CallExpression": return true;
1423
+ default: return true;
1424
+ }
1425
+ }
1426
+ /**
1427
+ * 获取v-for变量集合(从 WeakMap context 读取)
1428
+ */
1429
+ function getVForVariables(ctx, node) {
1430
+ const variables = /* @__PURE__ */ new Set();
1431
+ const list = ctx.vForInfoMap.get(node);
1432
+ if (!list) return variables;
1433
+ for (const vForInfo of list) {
1434
+ const parseResult = vForInfo.forParseResult;
1435
+ if (parseResult.value?.type === NodeTypes.SIMPLE_EXPRESSION) variables.add(parseResult.value.content);
1436
+ if (parseResult.key?.type === NodeTypes.SIMPLE_EXPRESSION) variables.add(parseResult.key.content);
1437
+ }
1438
+ return variables;
1439
+ }
1440
+ /**
1441
+ * 极简内存优化的v-for信息分配,写入 WeakMap 而非原始 AST 节点
1442
+ *
1443
+ * ⚠️ **必须在 `traverseNode` 之前调用**(即在 createTransformContext/traverseNode 之前)。
1444
+ *
1445
+ * 原因:此函数对整棵 AST 树做一次前序遍历,将每个节点的祖先 v-for 上下文信息
1446
+ * 预填充到 `ctx.vForInfoMap` 中。后续的 nodeTransforms(如 transformVForProp、
1447
+ * transformKeyProp 等)在运行时会通过 `getVForInfoList(ctx, node)` 读取这些信息。
1448
+ *
1449
+ * 如果在 `traverseNode` 之后调用,或根本未调用,v-for 相关的转换器将读取到空数据,
1450
+ * 导致嵌套 v-for 的 item/index 变量名计算错误。
1451
+ *
1452
+ * 调用示例(正确顺序):
1453
+ * ```ts
1454
+ * assignVForInfoListMinimal(templateAST, ctx) // ← 必须第一步
1455
+ * const context = createTransformContext(templateAST, { nodeTransforms })
1456
+ * traverseNode(templateAST, context)
1457
+ * ```
1458
+ */
1459
+ function assignVForInfoListMinimal(rootNode, ctx) {
1460
+ if (!rootNode) return;
1461
+ const stack = [];
1462
+ stack.push({
1463
+ node: rootNode,
1464
+ parentVForInfoList: void 0,
1465
+ hasVForInAncestry: false
1466
+ });
1467
+ while (stack.length > 0) {
1468
+ const { node, parentVForInfoList, hasVForInAncestry } = stack.pop();
1469
+ const vFor = isVForNode(node);
1470
+ if (vFor && vFor.type === NodeTypes.DIRECTIVE && vFor.forParseResult) {
1471
+ const vForInfo = {
1472
+ forParseResult: vFor.forParseResult,
1473
+ depth: parentVForInfoList ? parentVForInfoList.length : 0,
1474
+ parent: parentVForInfoList?.length ? parentVForInfoList[parentVForInfoList.length - 1] : void 0
1475
+ };
1476
+ const newVForInfoList = parentVForInfoList ? [...parentVForInfoList, vForInfo] : [vForInfo];
1477
+ setVForInfoList(ctx, node, newVForInfoList);
1478
+ const children = node.children;
1479
+ if (Array.isArray(children)) for (let i = children.length - 1; i >= 0; i--) stack.push({
1480
+ node: children[i],
1481
+ parentVForInfoList: newVForInfoList,
1482
+ hasVForInAncestry: true
1483
+ });
1484
+ } else {
1485
+ if (hasVForInAncestry && parentVForInfoList) setVForInfoList(ctx, node, parentVForInfoList);
1486
+ const children = node.children;
1487
+ if (Array.isArray(children)) for (let i = children.length - 1; i >= 0; i--) stack.push({
1488
+ node: children[i],
1489
+ parentVForInfoList,
1490
+ hasVForInAncestry
1491
+ });
1492
+ }
1493
+ }
1494
+ }
1495
+ function isNotMergeProps(prop) {
1496
+ return prop.name !== "style" && prop.name !== "class";
1497
+ }
1498
+ //#endregion
1499
+ //#region src/template/generator.ts
1500
+ function createAttr(prop, key) {
1501
+ return typeof prop?.content === "undefined" ? ` ${key}` : ` ${key}="${prop.content}"`;
1502
+ }
1503
+ var WXMLGenerator = class {
1504
+ code;
1505
+ indentLevel;
1506
+ indent;
1507
+ constructor() {
1508
+ this.code = [];
1509
+ this.indentLevel = 0;
1510
+ this.indent = " ";
1511
+ }
1512
+ generate(wxsScripts, ast) {
1513
+ this.code.splice(0, this.code.length);
1514
+ if (wxsScripts) this.code.push(wxsScripts);
1515
+ this.indentLevel = 0;
1516
+ const rootCodegen = getCodegenNode(ast);
1517
+ if (rootCodegen?.children) rootCodegen.children.forEach((child, index) => {
1518
+ this.traverseCodegenNode(child);
1519
+ if (index < rootCodegen.children.length - 1) this.code.push("\n");
1520
+ });
1521
+ return this.code.join("");
1522
+ }
1523
+ /**
1524
+ * 遍历 codegenNode 生成 WXML
1525
+ */
1526
+ traverseCodegenNode(node) {
1527
+ if (!node) return;
1528
+ switch (node.type) {
1529
+ case NodeTypes.ELEMENT:
1530
+ this.generateElement(node);
1531
+ break;
1532
+ case NodeTypes.TEXT:
1533
+ case NodeTypes.COMMENT:
1534
+ case NodeTypes.INTERPOLATION:
1535
+ this.generateLeafNode(node);
1536
+ break;
1537
+ default: break;
1538
+ }
1539
+ }
1540
+ /**
1541
+ * 生成元素节点(基于 codegenNode)
1542
+ */
1543
+ generateElement(node) {
1544
+ const indentation = this.indent.repeat(this.indentLevel);
1545
+ const tag = node.tag && WX_TAG_MAP.has(node.tag) ? WX_TAG_MAP.get(node.tag) : node.tag || "";
1546
+ if (tag === "block" && (!node.props || node.props.size === 0)) {
1547
+ node.children?.forEach((child) => {
1548
+ this.traverseCodegenNode(child);
1549
+ });
1550
+ return;
1551
+ }
1552
+ this.code.push(`${indentation}<${tag}`);
1553
+ this.generateProps(node.props);
1554
+ if (node.children && node.children.length > 0) {
1555
+ this.code.push(">");
1556
+ const isNeedIndent = this.shouldIndentChildren(node);
1557
+ if (isNeedIndent) {
1558
+ this.code.push("\n");
1559
+ this.indentLevel++;
1560
+ }
1561
+ node.children.forEach((child, index) => {
1562
+ this.traverseCodegenNode(child);
1563
+ if (isNeedIndent && index < node.children.length - 1) this.code.push("\n");
1564
+ });
1565
+ if (isNeedIndent) {
1566
+ this.indentLevel--;
1567
+ this.code.push(`\n${indentation}`);
1568
+ }
1569
+ this.code.push(`</${tag}>`);
1570
+ } else this.code.push(" />");
1571
+ }
1572
+ /**
1573
+ * 生成属性列表
1574
+ */
1575
+ generateProps(props) {
1576
+ if (!props) return;
1577
+ props.forEach((prop, key) => {
1578
+ this.code.push(createAttr(prop, key));
1579
+ });
1580
+ }
1581
+ generateLeafNode(node) {
1582
+ this.code.push(node.content || "");
1583
+ }
1584
+ shouldIndentChildren(node) {
1585
+ return !node.children?.every((child) => child.type === NodeTypes.TEXT || child.type === NodeTypes.INTERPOLATION);
1586
+ }
1587
+ };
1588
+ function generateWxml(wxsScripts, ast) {
1589
+ return new WXMLGenerator().generate(wxsScripts, ast);
1590
+ }
1591
+ //#endregion
1592
+ //#region src/template/nodeProps/slot.ts
1593
+ function transformSlotsAndTemplate(node) {
1594
+ if (node.type !== NodeTypes.ELEMENT || node.tag !== "template" || !node.props) return;
1595
+ const templateNode = node;
1596
+ const slotProp = templateNode.props.find((p) => p.type === NodeTypes.DIRECTIVE && p.name === "slot");
1597
+ if (slotProp) {
1598
+ if (slotProp.exp) throw createCompileError("暂不支持作用域插槽(v-slot)编译为小程序,请改为在父组件中直接使用数据渲染列表 / 条件。", slotProp.loc);
1599
+ if (slotProp.arg?.type === NodeTypes.SIMPLE_EXPRESSION) {
1600
+ const slotName = slotProp.arg.content;
1601
+ processNamedSlot(templateNode, slotName, slotProp);
1602
+ }
1603
+ } else transformToBlock(templateNode);
1604
+ }
1605
+ function processNamedSlot(node, slotName, slotProp) {
1606
+ if (node.children.length === 0) {
1607
+ setCodegenNode(node, {
1608
+ type: NodeTypes.COMMENT,
1609
+ content: `因${slotName}插槽下没有子节点,已被替换为注释节点`
1610
+ });
1611
+ return;
1612
+ }
1613
+ for (const child of node.children) if (child.type === NodeTypes.TEXT) throw createCompileError(`插槽${slotName}下需使用div等标签元素作为子节点!`, slotProp.loc);
1614
+ else if (child.type === NodeTypes.ELEMENT) createChildWithMergedProps(child, slotName);
1615
+ transformToBlock(node);
1616
+ }
1617
+ function transformToBlock(node) {
1618
+ const forDirective = isVForNode(node);
1619
+ if (!forDirective || forDirective.type !== NodeTypes.DIRECTIVE || !forDirective.forParseResult) {
1620
+ const filteredProps = new Map(node.props.filter((item) => item.type === NodeTypes.ATTRIBUTE && item.name !== "slot").map((p) => [p.name, p.value]));
1621
+ setCodegenNode(node, {
1622
+ type: NodeTypes.ELEMENT,
1623
+ tag: node.tag,
1624
+ props: filteredProps,
1625
+ children: [],
1626
+ loc: node.loc
1627
+ });
1628
+ }
1629
+ }
1630
+ function createChildWithMergedProps(childNode, slotName) {
1631
+ const mergedProps = childNode.props ? new Map(childNode.props?.filter((p) => p.type === NodeTypes.ATTRIBUTE && isNotMergeProps(p)).map((p) => [p.name, p.value])) : /* @__PURE__ */ new Map();
1632
+ if (slotName !== "default") mergedProps.set("slot", { content: slotName });
1633
+ setCodegenNode(childNode, {
1634
+ type: childNode.type,
1635
+ tag: childNode.tag,
1636
+ props: mergedProps,
1637
+ children: [],
1638
+ loc: childNode.loc
1639
+ });
1640
+ }
1641
+ //#endregion
1642
+ //#region src/utils/tools.ts
1643
+ /**
1644
+ * 从 VForInfo 中提取 item 名称
1645
+ */
1646
+ function getVForItemName(vForInfo) {
1647
+ const forParseResult = vForInfo.forParseResult;
1648
+ if (forParseResult.value && forParseResult.value.type === NodeTypes.SIMPLE_EXPRESSION) return forParseResult.value.content;
1649
+ return "";
1650
+ }
1651
+ /**
1652
+ * 从 VForInfo 中提取 index 名称
1653
+ */
1654
+ function getVForIndexName(vForInfo) {
1655
+ const forParseResult = vForInfo.forParseResult;
1656
+ if (forParseResult.key && forParseResult.key.type === NodeTypes.SIMPLE_EXPRESSION) return forParseResult.key.content;
1657
+ }
1658
+ /**
1659
+ * 从 VForInfo 中提取源表达式
1660
+ */
1661
+ function getVForSourceExpression(vForInfo) {
1662
+ const forParseResult = vForInfo.forParseResult;
1663
+ if (forParseResult.source && forParseResult.source.type === NodeTypes.SIMPLE_EXPRESSION) return forParseResult.source.content;
1664
+ return "";
1665
+ }
1666
+ /**
1667
+ * 添加polyfill文件复制功能
1668
+ */
1669
+ async function copyPolyfillFiles() {
1670
+ try {
1671
+ if (await fs$1.pathExists(POLYFILL_VMS_DIR)) {
1672
+ if (await fs$1.pathExists(POLYFILL_OUTPUT_DIR)) return;
1673
+ await fs$1.copy(POLYFILL_VMS_DIR, POLYFILL_OUTPUT_DIR);
1674
+ } else console.log(red("Polyfill源文件夹不存在:" + POLYFILL_VMS_DIR));
1675
+ } catch (error) {
1676
+ console.error(red("❌ 复制polyfill文件失败:" + getErrorMessage(error)));
1677
+ }
1678
+ }
1679
+ /**
1680
+ * 获取polyfill文件在当前文件的相对路径
1681
+ * @param polyfillFileName polyfill文件名
1682
+ * @param filePath 当前文件路径
1683
+ */
1684
+ function getPolyfillFileRelativePath(polyfillFileName, filePath) {
1685
+ return path.relative(path.dirname(filePath.replace(userConfig.sourceDir, OUTPUT_DIR)), path.join(OUTPUT_DIR, "polyfill", polyfillFileName)).split(path.sep).join("/");
1686
+ }
1687
+ function copyProjectConfigFile() {
1688
+ return fs$1.readJson(path.join(process.cwd(), "project.config.json")).then((config) => {
1689
+ Reflect.deleteProperty(config, "miniprogramRoot");
1690
+ Reflect.deleteProperty(config, "srcMiniprogramRoot");
1691
+ config.projectName = config.projectName + "-dev";
1692
+ return fs$1.writeFile(path.join(OUTPUT_DIR, "project.config.json"), JSON.stringify(config, null, 2));
1693
+ });
1694
+ }
1695
+ //#endregion
1696
+ //#region src/template/nodeProps/eventHelpers.ts
1697
+ const EVENT_PARAM_NAME = "__vms_event";
1698
+ /**
1699
+ * 生成函数索引字符
1700
+ */
1701
+ function getFunctionIndexChar(index) {
1702
+ let result = "";
1703
+ let num = index;
1704
+ while (num >= 0) {
1705
+ result = String.fromCharCode(97 + num % 26) + result;
1706
+ num = Math.floor(num / 26) - 1;
1707
+ if (num < 0) break;
1708
+ }
1709
+ return result;
1710
+ }
1711
+ /**
1712
+ * 构建从 __vmsProxyRefs 或 __vmsProps 访问 v-for item 的表达式
1713
+ * 例:__vmsProxyRefs.statCards[_statCards_index]
1714
+ * 嵌套 v-for 例:__vmsProxyRefs.props.fields[_fields_index].stringKey[_stringKey__index]
1715
+ * 复杂 source 例:__vmsProxyRefs.groupedSelectedItemsMap[field.stringKey][_stringKey__index]
1716
+ *
1717
+ * 对于复杂的 source 表达式(如 groupedSelectedItemsMap[field.stringKey]),
1718
+ * 返回的表达式会依赖之前已声明的 v-for item 变量
1719
+ * 现在支持 scriptScope 来判断 source 中的变量是否是 props
1720
+ */
1721
+ function buildProxyRefsItemAccess(vForInfoList, targetItemIndex, scriptScope, useProxyRefsBase = false) {
1722
+ const indices = vForInfoList.map((info) => getVForIndexName(info) || "index");
1723
+ const targetInfo = vForInfoList[targetItemIndex];
1724
+ const sourceExpr = getVForSourceExpression(targetInfo);
1725
+ const outerVForItems = vForInfoList.slice(0, targetItemIndex);
1726
+ const outerVForItemNames = new Set(outerVForItems.map((info) => getVForItemName(info)));
1727
+ const bracketParts = sourceExpr.split("[");
1728
+ const firstPart = bracketParts[0];
1729
+ const firstPartProps = firstPart ? firstPart.split(".") : [];
1730
+ const firstProp = firstPartProps[0];
1731
+ let expr;
1732
+ if (useProxyRefsBase) {
1733
+ expr = t.identifier("__vmsProxyRefs");
1734
+ for (const prop of firstPartProps) expr = t.memberExpression(expr, t.identifier(prop));
1735
+ } else if (firstProp && outerVForItemNames.has(firstProp)) {
1736
+ expr = t.identifier(firstProp);
1737
+ for (let i = 1; i < firstPartProps.length; i++) expr = t.memberExpression(expr, t.identifier(firstPartProps[i]));
1738
+ } else if (firstProp && scriptScope?.props.has(firstProp)) {
1739
+ const propsVarName = scriptScope.propsVarName || "__vmsProps";
1740
+ expr = t.identifier(propsVarName);
1741
+ for (const prop of firstPartProps) expr = t.memberExpression(expr, t.identifier(prop));
1742
+ } else {
1743
+ expr = t.identifier("__vmsProxyRefs");
1744
+ for (const prop of firstPartProps) expr = t.memberExpression(expr, t.identifier(prop));
1745
+ }
1746
+ for (let i = 1; i < bracketParts.length; i++) {
1747
+ const part = bracketParts[i];
1748
+ const indexContent = part.endsWith("]") ? part.slice(0, -1) : part;
1749
+ const indexParts = indexContent.split(".");
1750
+ const firstIndexPart = indexParts[0];
1751
+ if (outerVForItemNames.has(firstIndexPart)) {
1752
+ let indexExpr = t.identifier(firstIndexPart);
1753
+ for (let j = 1; j < indexParts.length; j++) indexExpr = t.memberExpression(indexExpr, t.identifier(indexParts[j]));
1754
+ expr = t.memberExpression(expr, indexExpr, true);
1755
+ } else expr = t.memberExpression(expr, t.identifier(indexContent), true);
1756
+ }
1757
+ expr = t.memberExpression(expr, t.identifier(indices[targetItemIndex]), true);
1758
+ return expr;
1759
+ }
1760
+ /**
1761
+ * 将一个调用参数 AST 节点转换为桥接函数内的访问表达式:
1762
+ * - v-for item 标识符 → __vmsProxyRefs.list[index]
1763
+ * - v-for item 成员表达式(card.id)→ __vmsProxyRefs.list[index].id
1764
+ * - props 变量 → __vmsProps.varName
1765
+ * - 外部变量标识符 → __vmsProxyRefs.varName
1766
+ * - $event / __vms_event → __vms_event
1767
+ * - 字面量 / 其他 → 原样保留
1768
+ * 现在支持 scriptScope 进行变量来源分析
1769
+ */
1770
+ function buildProxyRefsArgument(arg, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope) {
1771
+ if (t.isSpreadElement(arg)) return arg;
1772
+ if (t.isIdentifier(arg)) {
1773
+ if (arg.name === "$event" || arg.name === "__vms_event") return t.identifier(EVENT_PARAM_NAME);
1774
+ if (localVarNames && localVarNames.has(arg.name)) return arg;
1775
+ if (vForInfoList && vForItemNames.has(arg.name)) {
1776
+ const itemIndex = vForInfoList.findIndex((info) => getVForItemName(info) === arg.name);
1777
+ if (itemIndex !== -1) return buildProxyRefsItemAccess(vForInfoList, itemIndex, scriptScope);
1778
+ }
1779
+ if (arrowFunctionArgumentNames && arrowFunctionArgumentNames.has(arg.name)) return t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("detail"));
1780
+ if (vForInfoList) {
1781
+ if (vForInfoList.map((info) => getVForIndexName(info) || "index").includes(arg.name)) return arg;
1782
+ }
1783
+ if (scriptScope?.props.has(arg.name)) {
1784
+ const propsVarName = scriptScope.propsVarName || "__vmsProps";
1785
+ return t.memberExpression(t.identifier(propsVarName), t.identifier(arg.name));
1786
+ }
1787
+ return t.memberExpression(t.identifier("__vmsProxyRefs"), t.identifier(arg.name));
1788
+ }
1789
+ if (t.isOptionalMemberExpression(arg)) {
1790
+ const processedObject = buildProxyRefsArgument(arg.object, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope);
1791
+ return t.optionalMemberExpression(processedObject, arg.property, arg.computed, arg.optional);
1792
+ }
1793
+ if (t.isMemberExpression(arg)) {
1794
+ const processedObject = buildProxyRefsArgument(arg.object, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope);
1795
+ return t.memberExpression(processedObject, arg.property, arg.computed);
1796
+ }
1797
+ if (t.isObjectExpression(arg)) {
1798
+ const processedProperties = arg.properties.map((prop) => {
1799
+ if (t.isObjectProperty(prop)) {
1800
+ const processedValue = buildProxyRefsArgument(prop.value, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames);
1801
+ return t.objectProperty(prop.key, processedValue, prop.computed);
1802
+ }
1803
+ return prop;
1804
+ });
1805
+ return t.objectExpression(processedProperties);
1806
+ }
1807
+ if (t.isTSAsExpression(arg)) {
1808
+ const processedExpression = buildProxyRefsArgument(arg.expression, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope);
1809
+ return t.tsAsExpression(processedExpression, arg.typeAnnotation);
1810
+ }
1811
+ if (t.isTSNonNullExpression(arg)) {
1812
+ const processedExpression = buildProxyRefsArgument(arg.expression, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope);
1813
+ return t.tsNonNullExpression(processedExpression);
1814
+ }
1815
+ if (t.isArrayExpression(arg)) {
1816
+ const processedElements = arg.elements.map((el) => {
1817
+ if (el === null) return null;
1818
+ return buildProxyRefsArgument(el, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope);
1819
+ });
1820
+ return t.arrayExpression(processedElements);
1821
+ }
1822
+ if (t.isConditionalExpression(arg)) return t.conditionalExpression(buildProxyRefsArgument(arg.test, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope), buildProxyRefsArgument(arg.consequent, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope), buildProxyRefsArgument(arg.alternate, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope));
1823
+ if (t.isLogicalExpression(arg)) return t.logicalExpression(arg.operator, buildProxyRefsArgument(arg.left, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope), buildProxyRefsArgument(arg.right, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope));
1824
+ return arg;
1825
+ }
1826
+ /**
1827
+ * 解析需要声明为局部变量的 v-for item 集合
1828
+ * 从种子 item 出发,递归检查每个 item 的 source 是否依赖其他 v-for item,
1829
+ * 将所有依赖项也加入集合(确保声明顺序正确)
1830
+ */
1831
+ function resolveItemsToDeclare(seedItems, vForInfoList) {
1832
+ const itemsToDeclare = new Set(seedItems);
1833
+ let changed = true;
1834
+ while (changed) {
1835
+ changed = false;
1836
+ vForInfoList.forEach((info) => {
1837
+ const name = getVForItemName(info);
1838
+ if (name && itemsToDeclare.has(name)) {
1839
+ const sourceFirstPart = getVForSourceExpression(info).split(/[.[]/)[0];
1840
+ if (sourceFirstPart) {
1841
+ if (vForInfoList.find((i) => getVForItemName(i) === sourceFirstPart) && !itemsToDeclare.has(sourceFirstPart)) {
1842
+ itemsToDeclare.add(sourceFirstPart);
1843
+ changed = true;
1844
+ }
1845
+ }
1846
+ }
1847
+ });
1848
+ }
1849
+ return itemsToDeclare;
1850
+ }
1851
+ /**
1852
+ * 按 v-for 嵌套顺序将需要的 item 声明推入 statements
1853
+ * 外层先声明,确保内层可以引用外层 item
1854
+ */
1855
+ function declareVForItems(itemsToDeclare, vForInfoList, statements, scriptScope) {
1856
+ vForInfoList.forEach((info, idx) => {
1857
+ const name = getVForItemName(info);
1858
+ if (name && itemsToDeclare.has(name)) {
1859
+ const expr = buildProxyRefsItemAccess(vForInfoList, idx, scriptScope);
1860
+ statements.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(name), expr)]));
1861
+ }
1862
+ });
1863
+ }
1864
+ /**
1865
+ * 从 dataset 解构 v-for 索引并推入 statements
1866
+ */
1867
+ function declareDatasetIndices(dataKey, vForInfoList, statements) {
1868
+ const indexVars = vForInfoList.map((info) => getVForIndexName(info) || "index").map((idx) => t.identifier(idx));
1869
+ statements.push(t.variableDeclaration("const", [t.variableDeclarator(t.objectPattern([t.objectProperty(t.identifier(dataKey), t.arrayPattern(indexVars), false, false)]), t.memberExpression(t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("currentTarget")), t.identifier("dataset")))]));
1870
+ }
1871
+ /**
1872
+ * 生成通过 __vmsProxyRefs 访问 v-for item 方法的桥接函数体
1873
+ * data-a 只传 v-for 索引,item 和参数均从 __vmsProxyRefs 取
1874
+ * 现在支持 scriptScope 来判断变量是否是 props
1875
+ */
1876
+ function getASTWithVForItemFromProxyRefs(dataKey, calleeAst, argumentsAst, vForInfoList, arrowFunctionArgumentNames, scriptScope) {
1877
+ const vForItemNames = new Set(vForInfoList.map((info) => getVForItemName(info)).filter(Boolean));
1878
+ const itemName = calleeAst.object.name;
1879
+ const statements = [];
1880
+ declareDatasetIndices(dataKey, vForInfoList, statements);
1881
+ declareVForItems(resolveItemsToDeclare([itemName], vForInfoList), vForInfoList, statements, scriptScope);
1882
+ const localVarNames = new Set([itemName]);
1883
+ let callArgs;
1884
+ if (!argumentsAst || argumentsAst.length === 0) callArgs = [t.identifier(EVENT_PARAM_NAME)];
1885
+ else callArgs = argumentsAst.map((arg) => buildProxyRefsArgument(arg, vForInfoList, vForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope));
1886
+ statements.push(t.returnStatement(t.callExpression(t.memberExpression(t.identifier(itemName), calleeAst.property, calleeAst.computed), callArgs)));
1887
+ return t.blockStatement(statements);
1888
+ }
1889
+ /**
1890
+ * 生成通过 __vmsProxyRefs 访问外部变量的桥接函数体(非 v-for 场景)
1891
+ * 如果在 v-for 中,data-a 传递索引,桥接函数中需要从 dataset 解构索引
1892
+ * 现在支持 scriptScope 来判断变量是否是 props
1893
+ */
1894
+ function getASTWithoutVForItemFromProxyRefs(calleeAst, argumentsAst, arrowFunctionArgumentNames, vForInfoList, vForItemNames, dataKey, shouldPassIndices, scriptScope) {
1895
+ const effectiveVForItemNames = vForItemNames || /* @__PURE__ */ new Set();
1896
+ const statements = [];
1897
+ const usedVForItems = /* @__PURE__ */ new Set();
1898
+ function collectVForItems(node) {
1899
+ if (!node) return;
1900
+ if (t.isIdentifier(node) && effectiveVForItemNames.has(node.name)) usedVForItems.add(node.name);
1901
+ else if (t.isMemberExpression(node)) collectVForItems(node.object);
1902
+ else if (t.isObjectExpression(node)) node.properties.forEach((prop) => {
1903
+ if (t.isObjectProperty(prop)) collectVForItems(prop.value);
1904
+ });
1905
+ else if (t.isArrayExpression(node)) node.elements.forEach((el) => collectVForItems(el));
1906
+ }
1907
+ if (argumentsAst && vForInfoList && effectiveVForItemNames.size > 0) argumentsAst.forEach((arg) => collectVForItems(arg));
1908
+ if (shouldPassIndices && vForInfoList && vForInfoList.length > 0 && dataKey) {
1909
+ declareDatasetIndices(dataKey, vForInfoList, statements);
1910
+ declareVForItems(resolveItemsToDeclare(usedVForItems, vForInfoList), vForInfoList, statements, scriptScope);
1911
+ }
1912
+ const localVarNames = new Set(usedVForItems);
1913
+ let callArgs;
1914
+ if (!argumentsAst || argumentsAst.length === 0) callArgs = [t.identifier(EVENT_PARAM_NAME)];
1915
+ else callArgs = argumentsAst.map((arg) => buildProxyRefsArgument(arg, vForInfoList, effectiveVForItemNames, arrowFunctionArgumentNames, localVarNames, scriptScope));
1916
+ statements.push(t.returnStatement(t.callExpression(calleeAst, callArgs)));
1917
+ return t.blockStatement(statements);
1918
+ }
1919
+ /**
1920
+ * 检查是否应该创建局部引用
1921
+ */
1922
+ function shouldCreateLocalReference(usages) {
1923
+ if (usages.length <= 1) return false;
1924
+ if (usages.some((u) => u.isReassignment)) return false;
1925
+ if (usages.some((u) => u.isUpdate && !u.isMemberExpression)) return false;
1926
+ return true;
1927
+ }
1928
+ //#endregion
1929
+ //#region src/template/wxsPolyfill.ts
1930
+ const WXS_POLYFILL_REGISTRY = {
1931
+ find: { type: "instance" },
1932
+ findLast: { type: "instance" },
1933
+ findIndex: { type: "instance" },
1934
+ findLastIndex: { type: "instance" },
1935
+ includes: { type: "instance" },
1936
+ filter: { type: "instance" },
1937
+ map: { type: "instance" },
1938
+ reduce: { type: "instance" },
1939
+ reduceRight: { type: "instance" },
1940
+ some: { type: "instance" },
1941
+ every: { type: "instance" },
1942
+ flat: { type: "instance" },
1943
+ flatMap: { type: "instance" },
1944
+ at: { type: "instance" },
1945
+ padStart: { type: "instance" },
1946
+ padEnd: { type: "instance" },
1947
+ trimStart: { type: "instance" },
1948
+ trimEnd: { type: "instance" },
1949
+ replaceAll: { type: "instance" },
1950
+ entries: {
1951
+ type: "static",
1952
+ object: "Object"
1953
+ },
1954
+ fromEntries: {
1955
+ type: "static",
1956
+ object: "Object"
1957
+ },
1958
+ assign: {
1959
+ type: "static",
1960
+ object: "Object"
1961
+ },
1962
+ isNaN: {
1963
+ type: "static",
1964
+ object: "Number"
1965
+ },
1966
+ isFinite: {
1967
+ type: "static",
1968
+ object: "Number"
1969
+ },
1970
+ isInteger: {
1971
+ type: "static",
1972
+ object: "Number"
1973
+ }
1974
+ };
1975
+ const WXS_UTILS_NAMESPACE = "__vmsWXSUtils";
1976
+ function walkChildren(node, callback) {
1977
+ if (!node || typeof node !== "object") return node;
1978
+ for (const key of Object.keys(node)) {
1979
+ if (key === "type" || key === "start" || key === "end" || key === "loc") continue;
1980
+ const child = node[key];
1981
+ if (Array.isArray(child)) {
1982
+ for (let i = 0; i < child.length; i++) if (child[i] && typeof child[i] === "object" && child[i].type) {
1983
+ const result = callback(child[i], key, i);
1984
+ if (result !== void 0) child[i] = result;
1985
+ }
1986
+ } else if (child && typeof child === "object" && child.type) {
1987
+ const result = callback(child, key);
1988
+ if (result !== void 0) node[key] = result;
1989
+ }
1990
+ }
1991
+ }
1992
+ /**
1993
+ * 简单递归遍历 AST 节点,对每个节点调用 visitor
1994
+ * 不依赖 @babel/traverse 的 scope 机制,避免 "Couldn't find a Program" 错误
1995
+ */
1996
+ function walkNode(node, visitor) {
1997
+ if (!node || typeof node !== "object") return;
1998
+ visitor(node);
1999
+ walkChildren(node, (child) => {
2000
+ walkNode(child, visitor);
2001
+ });
2002
+ }
2003
+ /**
2004
+ * 检测 AST 中使用了哪些需要 polyfill 的方法(只读,不修改 AST)
2005
+ */
2006
+ function detectPolyfillMethods(ast) {
2007
+ const detected = /* @__PURE__ */ new Set();
2008
+ walkNode(ast, (node) => {
2009
+ if (node.type === "CallExpression") {
2010
+ const callee = node.callee;
2011
+ if (callee && callee.type === "MemberExpression" && !callee.computed && callee.property && callee.property.type === "Identifier") {
2012
+ const methodName = callee.property.name;
2013
+ if (methodName in WXS_POLYFILL_REGISTRY) detected.add(methodName);
2014
+ }
2015
+ } else if (node.type === "UnaryExpression" && node.operator === "typeof") detected.add("__typeof__");
2016
+ });
2017
+ return detected;
2018
+ }
2019
+ /**
2020
+ * 在 AST 上原地替换所有 polyfill 方法调用(应在深拷贝上调用)
2021
+ * 使用迭代方式处理,支持链式调用和嵌套回调
2022
+ */
2023
+ function applyPolyfillTransform(node) {
2024
+ if (!node || typeof node !== "object") return node;
2025
+ walkChildren(node, (child) => applyPolyfillTransform(child));
2026
+ if (node.type === "CallExpression") {
2027
+ const callee = node.callee;
2028
+ if (callee && callee.type === "MemberExpression" && !callee.computed) {
2029
+ const property = callee.property;
2030
+ if (property && property.type === "Identifier") {
2031
+ const methodName = property.name;
2032
+ const entry = WXS_POLYFILL_REGISTRY[methodName];
2033
+ if (entry) {
2034
+ if (entry.type === "instance") {
2035
+ if (callee.object && callee.object.type === "Identifier" && callee.object.name === WXS_UTILS_NAMESPACE) return node;
2036
+ return t$1.callExpression(t$1.memberExpression(t$1.identifier(WXS_UTILS_NAMESPACE), t$1.identifier(methodName)), [callee.object, ...node.arguments]);
2037
+ } else if (entry.type === "static" && entry.object) {
2038
+ const objectNode = callee.object;
2039
+ if (objectNode && objectNode.type === "Identifier" && objectNode.name === entry.object) {
2040
+ const wxsName = entry.object.toLowerCase() + methodName[0].toUpperCase() + methodName.slice(1);
2041
+ return t$1.callExpression(t$1.memberExpression(t$1.identifier(WXS_UTILS_NAMESPACE), t$1.identifier(wxsName)), [...node.arguments]);
2042
+ }
2043
+ }
2044
+ }
2045
+ }
2046
+ }
2047
+ }
2048
+ return node;
2049
+ }
2050
+ //#endregion
2051
+ //#region src/template/expression.ts
2052
+ /**
2053
+ * 对 babel 输出的代码进行 WXS 兼容性清理
2054
+ * - $ → _(WXS 不支持 $ 标识符)
2055
+ * - void 0 → undefined(WXS 不支持 void 关键字)
2056
+ */
2057
+ function sanitizeWxsCode(code) {
2058
+ return code.replace(/[_a-zA-Z][$\w]*/g, (match) => match.replace(/[$]/g, "_")).replace(/void\s+0/g, "undefined");
2059
+ }
2060
+ function makeBabelOptions() {
2061
+ return {
2062
+ filename: "temp.ts",
2063
+ presets: ["@babel/preset-env", "@babel/preset-typescript"],
2064
+ plugins: ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-template-literals"],
2065
+ generatorOpts: { jsescOption: { minimal: true } }
2066
+ };
2067
+ }
2068
+ /**
2069
+ * 将表达式 AST 节点通过 babel 降级为 ES5 兼容的代码字符串
2070
+ * 处理可选链(?.)、箭头函数、模板字符串等现代语法
2071
+ *
2072
+ * 返回代码字符串而非 AST 节点,因为 @babel/generator 会在输出时
2073
+ * 将降级后的条件表达式反向优化回 ?. 等简写形式。
2074
+ *
2075
+ * 后处理:$ → _(WXS 不支持 $)、void 0 → undefined(WXS 不支持 void)
2076
+ */
2077
+ function downlevelExpressionCode(expr) {
2078
+ const result = transformFromAstSync(t$1.program([t$1.expressionStatement(expr)]), void 0, makeBabelOptions());
2079
+ if (!result?.code) throw createCompileError("无法将表达式转换为 WXS 兼容语法", expr.loc);
2080
+ const lines = result.code.trim().split("\n");
2081
+ const declarations = [];
2082
+ const exprLines = [];
2083
+ for (const line of lines) {
2084
+ const trimmed = line.trim();
2085
+ if (/^\s*var\s+/.test(trimmed)) declarations.push(trimmed);
2086
+ else if (trimmed) exprLines.push(trimmed);
2087
+ }
2088
+ return {
2089
+ code: sanitizeWxsCode(exprLines.join("\n").trim().replace(/;?\s*$/, "")),
2090
+ declarations: declarations.join("\n")
2091
+ };
2092
+ }
2093
+ /**
2094
+ * 将降级后的代码字符串解析为 AST 语句列表
2095
+ * parse 回 AST 是为了锁定展开形式,避免 @babel/generator 反向优化回 ?. 等简写
2096
+ */
2097
+ function parseDownleveledCode(code) {
2098
+ return parse$1(code, { sourceType: "script" }).program.body;
2099
+ }
2100
+ /**
2101
+ * Vue compiler 解析失败时的 fallback:用 babel 重新解析表达式
2102
+ *
2103
+ * prop.exp.ast 有四种值:
2104
+ * null — Vue compiler 判定为简单标识符,无需解析
2105
+ * false — Vue compiler 解析失败(语法错误),需要 fallback 重新解析
2106
+ * undefined — 静态节点或 filter 语法(极少见)
2107
+ * Program | Expression — 正常解析结果
2108
+ *
2109
+ * 当 rawAst === false 时,尝试用 @babel/parser 重新解析。
2110
+ * 返回解析后的 AST 表达式节点,或 null(解析也失败)。
2111
+ */
2112
+ function fallbackParseExpression(rawAst, expression) {
2113
+ if (rawAst !== false) return rawAst;
2114
+ try {
2115
+ const stmt = parse$1(expression, {
2116
+ sourceType: "script",
2117
+ plugins: ["typescript"]
2118
+ }).program.body[0];
2119
+ return stmt?.type === "ExpressionStatement" ? stmt.expression : null;
2120
+ } catch {
2121
+ return null;
2122
+ }
2123
+ }
2124
+ function getTemplateNodeProp(node, prop, returnValue, counter, wxsExpressionStatements, ctx, wxsStatementsFun) {
2125
+ if (prop.exp?.type !== NodeTypes.SIMPLE_EXPRESSION) return { content: "" };
2126
+ const originalExpression = prop.exp.content;
2127
+ const rawAst = prop.exp.ast;
2128
+ const ast = fallbackParseExpression(rawAst, originalExpression);
2129
+ const notSupportMethodsSet = ast ? detectPolyfillMethods(ast) : /* @__PURE__ */ new Set();
2130
+ if (ast) if (isComplexExpression(ast) || notSupportMethodsSet.size > 0) if (!containsExternalFunctionInExpression(ast)) {
2131
+ const wxsFunctionName = counter.generateWxsFunctionName();
2132
+ const variables = extractVariablesFromExpressionAST(ast);
2133
+ const clonedAst = t$1.cloneNode(ast);
2134
+ const programAST = t$1.program([t$1.expressionStatement(clonedAst)]);
2135
+ if (notSupportMethodsSet.size > 0) applyPolyfillTransform(programAST);
2136
+ const result = transformFromAstSync(programAST, originalExpression, makeBabelOptions());
2137
+ if (result?.code) {
2138
+ const statements = parseDownleveledCode(sanitizeWxsCode(result.code));
2139
+ const lastIndex = statements.length - 1;
2140
+ const wxsStmt = t$1.expressionStatement(t$1.assignmentExpression("=", t$1.memberExpression(t$1.memberExpression(t$1.identifier("module"), t$1.identifier("exports")), t$1.identifier(wxsFunctionName)), t$1.functionExpression(null, variables.map((item) => t$1.identifier(item)), t$1.blockStatement(typeof wxsStatementsFun === "function" ? wxsStatementsFun(statements, lastIndex) : statements.map((item, index) => {
2141
+ if (index === lastIndex) return item.type === "ExpressionStatement" ? t$1.returnStatement(item.expression) : item;
2142
+ return item;
2143
+ })))));
2144
+ wxsExpressionStatements.push(wxsStmt);
2145
+ const wxsCallParams = variables.length > 0 ? `${variables.join(", ")}` : "";
2146
+ collectBindingVarsWithVarNameList(variables, node, returnValue, ctx);
2147
+ return {
2148
+ content: `{{${WXS_NAMESPACE}.${wxsFunctionName}(${wxsCallParams})}}`,
2149
+ wxsStatement: wxsStmt
2150
+ };
2151
+ } else throw createCompileError("无法将表达式转换为es5语法", prop.loc);
2152
+ } else throw createCompileError("无法处理表达式", prop.loc);
2153
+ else {
2154
+ collectBindingVarsWithAST(ast, node, returnValue, ctx);
2155
+ return { content: `{{${originalExpression}}}` };
2156
+ }
2157
+ else if (originalExpression === "true" || originalExpression === "false") return { content: `{{${originalExpression}}}` };
2158
+ else {
2159
+ collectBindingVarsWithVarName(originalExpression, node, returnValue, ctx);
2160
+ return { content: `{{${originalExpression}}}` };
2161
+ }
2162
+ }
2163
+ //#endregion
2164
+ //#region src/template/nodeProps/eventProcessor.ts
2165
+ /**
2166
+ * 将 BlockStatement "重生"为完整 AST(File 节点)。
2167
+ *
2168
+ * 因为 traverse 需要一个顶层 Program/File 才能提供 scope 信息,
2169
+ * 而 BlockStatement 本身缺少顶层作用域,所以需要:
2170
+ * 1. generate(code) — 序列化为字符串
2171
+ * 2. babelParse(code) — 重新解析为完整 AST
2172
+ *
2173
+ * 注意:isAsync 必须正确传递,否则 babel 无法解析 await 关键字。
2174
+ */
2175
+ function reparseBodyAsAST(body, isAsync) {
2176
+ const code = generate(t.arrowFunctionExpression([], body, isAsync), { compact: true }).code;
2177
+ return parse$1(code, {
2178
+ sourceType: "module",
2179
+ plugins: ["typescript"]
2180
+ });
2181
+ }
2182
+ /**
2183
+ * 检查变量是否应该被跳过(不收集到 internalVars)
2184
+ * 统一封装 scriptScope 变量来源分析,避免散布在多处的四连判断
2185
+ */
2186
+ function shouldSkipVariable(name, scriptScope) {
2187
+ if (!scriptScope) return false;
2188
+ return isPropsVariable(name, scriptScope) || isMacroVariable(name, scriptScope) || isImportVariable(name, scriptScope) || isGlobalVariableInScope(name, scriptScope);
2189
+ }
2190
+ /**
2191
+ * 扫描调用参数中的外部变量(非 v-for item、非字面量、非 $event),
2192
+ * 注册到 returnValue 和 ctx.internalVars,确保 __vmsProxyRefs 能访问到
2193
+ * 现在使用 scriptScope 进行更精确的变量来源分析
2194
+ */
2195
+ function collectExternalVarsFromArgs(args, vForItemNames, vForInfoList, returnValue, ctx, arrowFunctionArgumentNames) {
2196
+ const vForIndices = new Set(vForInfoList ? vForInfoList.map((info) => getVForIndexName(info) || "index") : []);
2197
+ function scanNode(node) {
2198
+ if (t.isIdentifier(node)) {
2199
+ const name = node.name;
2200
+ if (name === "__vms_event" || name === "$event" || vForItemNames.has(name) || vForIndices.has(name) || GLOBAL_WHITELIST.has(name) || arrowFunctionArgumentNames && arrowFunctionArgumentNames.has(name)) return;
2201
+ if (shouldSkipVariable(name, ctx.scriptScope)) return;
2202
+ addProperty(returnValue, name);
2203
+ ctx.internalVars.add(name);
2204
+ } else if (t.isMemberExpression(node) || t.isOptionalMemberExpression(node)) scanNode(node.object);
2205
+ else if (t.isObjectExpression(node)) node.properties.forEach((prop) => {
2206
+ if (t.isObjectProperty(prop)) scanNode(prop.value);
2207
+ });
2208
+ else if (t.isArrayExpression(node)) node.elements.forEach((el) => el && scanNode(el));
2209
+ else if (t.isSpreadElement(node)) scanNode(node.argument);
2210
+ }
2211
+ args.forEach((arg) => scanNode(arg));
2212
+ }
2213
+ /**
2214
+ * 处理事件属性
2215
+ */
2216
+ function processEventProperty(prop, node, counter, callExpressionWithArgs, returnValue, ctx) {
2217
+ if (prop.type !== 7 || prop.name !== "on") return null;
2218
+ const exp = prop.exp;
2219
+ if (!exp) return null;
2220
+ let content = "";
2221
+ const excludeBindingVars = [];
2222
+ const vForInfoList = getVForInfoList(ctx, node);
2223
+ const vForItemName = /* @__PURE__ */ new Set();
2224
+ if (vForInfoList) for (const info of vForInfoList) {
2225
+ const name = getVForItemName(info);
2226
+ if (name) vForItemName.add(name);
2227
+ }
2228
+ const expContent = exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "";
2229
+ let ast = fallbackParseExpression(exp.ast, expContent);
2230
+ if (!ast) {
2231
+ if (exp.type === NodeTypes.SIMPLE_EXPRESSION) {
2232
+ content = exp.content;
2233
+ collectBindingVarsWithAST(t.identifier(content), node, returnValue, ctx);
2234
+ }
2235
+ } else {
2236
+ if (t.isProgram(ast) && ast.body.length > 0) {
2237
+ const firstStatement = ast.body[0];
2238
+ if (t.isExpressionStatement(firstStatement)) ast = firstStatement.expression;
2239
+ }
2240
+ content = processASTExpression(ast, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, node, returnValue, ctx);
2241
+ const allExcluded = [...excludeBindingVars, ...ctx.internalVars];
2242
+ collectBindingVarsWithAST(ast, node, returnValue, ctx, allExcluded);
2243
+ excludeBindingVars.forEach((name) => ctx.bridgedFunctions.add(name));
2244
+ }
2245
+ return processEventName(prop, content);
2246
+ }
2247
+ /**
2248
+ * 处理AST表达式
2249
+ */
2250
+ function processASTExpression(ast, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, node, returnValue, ctx) {
2251
+ const vForInfoList = getVForInfoList(ctx, node);
2252
+ if (t.isCallExpression(ast)) return processCallableExpression(ast.callee, ast.arguments, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue);
2253
+ else if (t.isMemberExpression(ast)) return processCallableExpression(ast, null, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue);
2254
+ else if (t.isArrowFunctionExpression(ast)) return processArrowFunctionExpression(ast, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, node, returnValue, ctx);
2255
+ return "";
2256
+ }
2257
+ /**
2258
+ * 统一处理所有可调用表达式的事件绑定:
2259
+ * - onClick(args) → callee=Identifier, argumentsAst=args
2260
+ * - card.onClick(args) → callee=MemberExpression, argumentsAst=args
2261
+ * - card.onClick → callee=MemberExpression, argumentsAst=null
2262
+ * - (e) => onClick(args) → 同上,加 arrowFunctionArgumentNames
2263
+ */
2264
+ function processCallableExpression(callee, argumentsAst, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames) {
2265
+ const content = counter.generateFunctionPropertyName();
2266
+ const dataKey = getFunctionIndexChar(counter.nodeDataKeyIndex++);
2267
+ const args = argumentsAst ?? [];
2268
+ if (t.isIdentifier(callee)) handleIdentifierCallee(callee, args, content, dataKey, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames);
2269
+ else if (t.isMemberExpression(callee) && t.isIdentifier(callee.object)) handleMemberExpressionCallee(callee, argumentsAst, args, content, dataKey, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames);
2270
+ ctx.needsProxyRefs = true;
2271
+ return content;
2272
+ }
2273
+ /** Identifier callee:onClick(args) */
2274
+ function handleIdentifierCallee(callee, args, content, dataKey, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames) {
2275
+ const effectiveVForItemName = vForItemName || /* @__PURE__ */ new Set();
2276
+ collectExternalVarsFromArgs(args, effectiveVForItemName, vForInfoList, returnValue, ctx, arrowFunctionArgumentNames);
2277
+ const indices = vForInfoList ? vForInfoList.map((info) => getVForIndexName(info) || "index") : [];
2278
+ const shouldPassIndices = vForInfoList && vForInfoList.length > 0;
2279
+ callExpressionWithArgs.set(content, {
2280
+ dataKey,
2281
+ dataArgsAst: shouldPassIndices ? indices.map((idx) => t.identifier(idx)) : null,
2282
+ returnValueBodyAst: getASTWithoutVForItemFromProxyRefs(callee, args, arrowFunctionArgumentNames, vForInfoList, effectiveVForItemName, dataKey, shouldPassIndices, ctx.scriptScope),
2283
+ isAsync: false
2284
+ });
2285
+ excludeBindingVars.push(callee.name);
2286
+ }
2287
+ /** MemberExpression callee:card.onClick(args) 或 obj.method(args) */
2288
+ function handleMemberExpressionCallee(callee, argumentsAst, args, content, dataKey, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames) {
2289
+ const calleeName = callee.object.name;
2290
+ collectExternalVarsFromArgs(args, vForItemName, vForInfoList, returnValue, ctx, arrowFunctionArgumentNames);
2291
+ if (vForItemName.has(calleeName) && vForInfoList && vForInfoList.length > 0) {
2292
+ const indices = vForInfoList.map((info) => getVForIndexName(info) || "index");
2293
+ callExpressionWithArgs.set(content, {
2294
+ dataKey,
2295
+ dataArgsAst: indices.map((idx) => t.identifier(idx)),
2296
+ returnValueBodyAst: getASTWithVForItemFromProxyRefs(dataKey, callee, argumentsAst, vForInfoList, arrowFunctionArgumentNames, ctx.scriptScope),
2297
+ isAsync: false
2298
+ });
2299
+ } else {
2300
+ if (!GLOBAL_WHITELIST.has(calleeName) && !shouldSkipVariable(calleeName, ctx.scriptScope)) {
2301
+ addProperty(returnValue, calleeName);
2302
+ ctx.internalVars.add(calleeName);
2303
+ }
2304
+ callExpressionWithArgs.set(content, {
2305
+ dataKey,
2306
+ dataArgsAst: null,
2307
+ returnValueBodyAst: getASTWithoutVForItemFromProxyRefs(callee, argumentsAst, arrowFunctionArgumentNames, vForInfoList, vForItemName, void 0, false, ctx.scriptScope),
2308
+ isAsync: false
2309
+ });
2310
+ }
2311
+ excludeBindingVars.push(calleeName);
2312
+ }
2313
+ /**
2314
+ * 处理箭头函数表达式
2315
+ */
2316
+ function processArrowFunctionExpression(ast, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, node, returnValue, ctx) {
2317
+ const arrowFunctionArguments = ast.params;
2318
+ const body = ast.body;
2319
+ const isAsync = ast.async || false;
2320
+ const vForInfoList = getVForInfoList(ctx, node);
2321
+ const arrowFunctionArgumentNames = arrowFunctionArguments.length > 0 ? new Set(arrowFunctionArguments.map((p) => t.isIdentifier(p) ? p.name : "").filter(Boolean)) : void 0;
2322
+ if (t.isBlockStatement(body)) return processInlineArrowFunction(body, arrowFunctionArguments, counter, callExpressionWithArgs, excludeBindingVars, node, returnValue, ctx, isAsync);
2323
+ else if (t.isCallExpression(body)) return processCallableExpression(body.callee, body.arguments, counter, callExpressionWithArgs, excludeBindingVars, vForItemName, vForInfoList, ctx, returnValue, arrowFunctionArgumentNames);
2324
+ else if (t.isAssignmentExpression(body)) return processInlineArrowFunction(t.blockStatement([t.expressionStatement(body)]), arrowFunctionArguments, counter, callExpressionWithArgs, excludeBindingVars, node, returnValue, ctx, isAsync);
2325
+ else if (t.isConditionalExpression(body) || t.isLogicalExpression(body)) return createShortExprHandler(body, arrowFunctionArguments, callExpressionWithArgs, getVForInfoList(ctx, node), getVForVariables(ctx, node), ctx, counter, returnValue, isAsync);
2326
+ return "";
2327
+ }
2328
+ function collectExternalVarsFromExpression(body, arrowFunctionArgumentNames, vForVars) {
2329
+ const varsToCollect = /* @__PURE__ */ new Set();
2330
+ const collectVarsFromNode = (node) => {
2331
+ if (t.isIdentifier(node)) {
2332
+ const name = node.name;
2333
+ if (name !== "__vms_event" && name !== "$event" && !GLOBAL_WHITELIST.has(name) && !(arrowFunctionArgumentNames && arrowFunctionArgumentNames.has(name)) && !vForVars.has(name)) varsToCollect.add(name);
2334
+ } else if (t.isMemberExpression(node)) collectVarsFromNode(node.object);
2335
+ else if (t.isCallExpression(node)) {
2336
+ collectVarsFromNode(node.callee);
2337
+ node.arguments.forEach((arg) => collectVarsFromNode(arg));
2338
+ } else if (t.isConditionalExpression(node)) {
2339
+ collectVarsFromNode(node.test);
2340
+ collectVarsFromNode(node.consequent);
2341
+ collectVarsFromNode(node.alternate);
2342
+ } else if (t.isLogicalExpression(node) || t.isBinaryExpression(node)) {
2343
+ collectVarsFromNode(node.left);
2344
+ collectVarsFromNode(node.right);
2345
+ } else if (t.isUnaryExpression(node)) collectVarsFromNode(node.argument);
2346
+ };
2347
+ if (t.isConditionalExpression(body)) {
2348
+ collectVarsFromNode(body.test);
2349
+ collectVarsFromNode(body.consequent);
2350
+ collectVarsFromNode(body.alternate);
2351
+ } else {
2352
+ collectVarsFromNode(body.left);
2353
+ collectVarsFromNode(body.right);
2354
+ }
2355
+ return varsToCollect;
2356
+ }
2357
+ /**
2358
+ * 重写表达式中的变量引用
2359
+ * 将外部变量、props、箭头函数参数替换为正确的访问路径
2360
+ */
2361
+ function rewriteExpressionVars(expr, varsToCollect, arrowFunctionArgumentNames, ctx) {
2362
+ const processExpr = (node) => {
2363
+ if (t.isIdentifier(node)) {
2364
+ const name = node.name;
2365
+ if (arrowFunctionArgumentNames && arrowFunctionArgumentNames.has(name)) return t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("detail"));
2366
+ if (ctx.scriptScope?.props.has(name)) {
2367
+ const propsVarName = ctx.scriptScope.propsVarName || "__vmsProps";
2368
+ return t.memberExpression(t.identifier(propsVarName), t.identifier(name));
2369
+ }
2370
+ if (varsToCollect.has(name)) return t.memberExpression(t.identifier("__vmsProxyRefs"), t.identifier(name));
2371
+ return node;
2372
+ } else if (t.isMemberExpression(node)) return t.memberExpression(processExpr(node.object), node.property, node.computed);
2373
+ else if (t.isCallExpression(node)) return t.callExpression(processExpr(node.callee), node.arguments.map((arg) => processExpr(arg)));
2374
+ else if (t.isConditionalExpression(node)) return t.conditionalExpression(processExpr(node.test), processExpr(node.consequent), processExpr(node.alternate));
2375
+ else if (t.isLogicalExpression(node)) return t.logicalExpression(node.operator, processExpr(node.left), processExpr(node.right));
2376
+ else if (t.isBinaryExpression(node)) return t.binaryExpression(node.operator, processExpr(node.left), processExpr(node.right));
2377
+ else if (t.isUnaryExpression(node)) return t.unaryExpression(node.operator, processExpr(node.argument));
2378
+ return node;
2379
+ };
2380
+ return processExpr(expr);
2381
+ }
2382
+ /**
2383
+ * 创建简短表达式(条件/逻辑表达式)的箭头函数处理器
2384
+ * 供 processArrowFunctionExpression 中条件表达式和逻辑表达式分支复用
2385
+ */
2386
+ function createShortExprHandler(body, arrowFunctionArguments, callExpressionWithArgs, vForInfoList, vForVars, ctx, counter, returnValue, isAsync) {
2387
+ const arrowFunctionArgumentNames = arrowFunctionArguments.length > 0 ? new Set(arrowFunctionArguments.map((p) => t.isIdentifier(p) ? p.name : "").filter(Boolean)) : void 0;
2388
+ const varsToCollect = collectExternalVarsFromExpression(body, arrowFunctionArgumentNames, vForVars);
2389
+ varsToCollect.forEach((varName) => {
2390
+ if (!shouldSkipVariable(varName, ctx.scriptScope)) {
2391
+ addProperty(returnValue, varName);
2392
+ ctx.internalVars.add(varName);
2393
+ }
2394
+ });
2395
+ if (varsToCollect.size > 0) ctx.needsProxyRefs = true;
2396
+ const functionName = counter.generateFunctionPropertyName();
2397
+ const dataKey = vForInfoList && vForInfoList.length > 0 ? getFunctionIndexChar(counter.nodeDataKeyIndex++) : "";
2398
+ const statements = [];
2399
+ if (arrowFunctionArguments.length > 0) {
2400
+ const param = arrowFunctionArguments[0];
2401
+ if (t.isIdentifier(param) && param.name !== "$event" && param.name !== "__vms_event") statements.push(t.variableDeclaration("const", [t.variableDeclarator(param, t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("detail")))]));
2402
+ }
2403
+ if (vForInfoList && vForInfoList.length > 0) {
2404
+ const indexVars = vForInfoList.map((info) => getVForIndexName(info) || "index").map((idx) => t.identifier(idx));
2405
+ statements.push(t.variableDeclaration("const", [t.variableDeclarator(t.objectPattern([t.objectProperty(t.identifier(dataKey), t.arrayPattern(indexVars), false, false)]), t.memberExpression(t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("currentTarget")), t.identifier("dataset")))]));
2406
+ }
2407
+ const processedBody = rewriteExpressionVars(body, varsToCollect, arrowFunctionArgumentNames, ctx);
2408
+ statements.push(t.returnStatement(processedBody));
2409
+ const functionBody = t.blockStatement(statements);
2410
+ const dataArgsAst = vForInfoList && vForInfoList.length > 0 ? vForInfoList.map((info) => t.identifier(getVForIndexName(info) || "index")) : null;
2411
+ callExpressionWithArgs.set(functionName, {
2412
+ dataKey,
2413
+ dataArgsAst,
2414
+ returnValueBodyAst: functionBody,
2415
+ isAsync
2416
+ });
2417
+ return functionName;
2418
+ }
2419
+ /**
2420
+ * 处理事件名转换
2421
+ * 规则:
2422
+ * 1. 事件名原样保留,不做 click -> tap 转换
2423
+ * 2. .stop 转为 catch:
2424
+ * 3. .mut 转为 mut-bind:
2425
+ * 4. .capture 转为 capture-bind:
2426
+ * 5. .capture-stop 转为 capture-catch:
2427
+ */
2428
+ function processEventName(prop, content) {
2429
+ if (prop.type !== NodeTypes.DIRECTIVE) return null;
2430
+ const arg = prop.arg;
2431
+ if (!arg) return null;
2432
+ if (arg.type === NodeTypes.SIMPLE_EXPRESSION) {
2433
+ const eventName = arg.content;
2434
+ const modifiers = prop.modifiers || [];
2435
+ const hasMutModifier = modifiers.some((item) => item.content === "mut");
2436
+ const hasCaptureModifier = modifiers.some((item) => item.content === "capture");
2437
+ const hasCaptureStopModifier = modifiers.some((item) => item.content === "capture-stop");
2438
+ const hasStopModifier = modifiers.some((item) => item.content === "stop");
2439
+ let bindType;
2440
+ if (hasCaptureStopModifier) bindType = "capture-catch";
2441
+ else if (hasCaptureModifier) bindType = "capture-bind";
2442
+ else if (hasMutModifier) bindType = "mut-bind";
2443
+ else if (hasStopModifier) bindType = "catch";
2444
+ else bindType = "bind";
2445
+ return {
2446
+ name: `${bindType}:${eventName}`,
2447
+ content
2448
+ };
2449
+ } else throw createCompileError("事件名必须是简单表达式:" + prop.arg, prop.loc);
2450
+ }
2451
+ /**
2452
+ * 添加生成的函数到returnValue
2453
+ * 返回生成的 data- 属性列表
2454
+ */
2455
+ function addGeneratedFunctions(callExpressionWithArgs, _props, returnValue) {
2456
+ const dataProps = [];
2457
+ callExpressionWithArgs.forEach(({ dataKey, dataArgsAst, returnValueBodyAst, isAsync }, funName) => {
2458
+ const propName = `data-${dataKey}`;
2459
+ if (Array.isArray(dataArgsAst) && dataArgsAst.length > 0) {
2460
+ const content = `{{[${dataArgsAst.map((arg) => generate(arg, { compact: true }).code).join(",")}]}}`;
2461
+ dataProps.push({
2462
+ name: propName,
2463
+ content
2464
+ });
2465
+ }
2466
+ if (returnValueBodyAst) {
2467
+ let functionExpression;
2468
+ const body = t.isBlockStatement(returnValueBodyAst) ? returnValueBodyAst : t.blockStatement([t.returnStatement(returnValueBodyAst)]);
2469
+ if (isAsync) functionExpression = t.functionExpression(null, [t.identifier(EVENT_PARAM_NAME)], body, false, true);
2470
+ else functionExpression = t.arrowFunctionExpression([t.identifier(EVENT_PARAM_NAME)], body);
2471
+ returnValue.properties.push(t.objectProperty(t.identifier(funName), functionExpression));
2472
+ }
2473
+ });
2474
+ return dataProps;
2475
+ }
2476
+ /**
2477
+ * 处理内联箭头函数
2478
+ */
2479
+ function processInlineArrowFunction(body, arrowFunctionArguments, counter, callExpressionWithArgs, excludeBindingVars, node, returnValue, ctx, isAsync = false) {
2480
+ const functionName = counter.generateFunctionPropertyName();
2481
+ const vForInfoList = getVForInfoList(ctx, node);
2482
+ const usedVars = collectUsedVariables(body, arrowFunctionArguments, vForInfoList, isAsync);
2483
+ const vForVars = getVForVariables(ctx, node);
2484
+ usedVars.forEach((varName) => {
2485
+ if (!vForVars.has(varName) && !GLOBAL_WHITELIST.has(varName) && !shouldSkipVariable(varName, ctx.scriptScope)) {
2486
+ addProperty(returnValue, varName);
2487
+ ctx.internalVars.add(varName);
2488
+ }
2489
+ });
2490
+ let vForItemUsage = null;
2491
+ if (vForInfoList && vForInfoList.length > 0) {
2492
+ vForItemUsage = analyzeVForItemUsage(body, vForInfoList, isAsync);
2493
+ const lastVForInfo = vForInfoList[vForInfoList.length - 1];
2494
+ const itemName = getVForItemName(lastVForInfo);
2495
+ if (itemName) excludeBindingVars.push(itemName);
2496
+ }
2497
+ if (usedVars.size > 0 || vForItemUsage?.shouldCreateReference) ctx.needsProxyRefs = true;
2498
+ const functionIndex = counter.functionPropertyCounter - 1;
2499
+ const dataKey = vForInfoList && vForInfoList.length > 0 ? getFunctionIndexChar(functionIndex) : "";
2500
+ const functionBody = createInlineHandlerBody(body, arrowFunctionArguments, usedVars, vForInfoList, vForItemUsage, isAsync, dataKey);
2501
+ const dataArgsAst = vForInfoList && vForInfoList.length > 0 ? vForInfoList.map((info) => {
2502
+ const indexName = getVForIndexName(info) || "index";
2503
+ return t.identifier(indexName);
2504
+ }) : null;
2505
+ callExpressionWithArgs.set(functionName, {
2506
+ dataKey,
2507
+ dataArgsAst,
2508
+ returnValueBodyAst: functionBody,
2509
+ isAsync
2510
+ });
2511
+ return functionName;
2512
+ }
2513
+ /**
2514
+ * 创建局部变量声明收集 visitor
2515
+ * 将 AST 遍历中重复的变量声明收集逻辑(VariableDeclarator、FunctionDeclaration、
2516
+ * CatchClause、ForStatement)提取为可复用的 visitor 工厂
2517
+ */
2518
+ function createLocalVarCollector(localVars) {
2519
+ return {
2520
+ VariableDeclarator(path) {
2521
+ const id = path.node.id;
2522
+ if (t.isIdentifier(id)) localVars.add(id.name);
2523
+ else if (t.isObjectPattern(id)) id.properties.forEach((prop) => {
2524
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.value)) localVars.add(prop.value.name);
2525
+ else if (t.isRestElement(prop) && t.isIdentifier(prop.argument)) localVars.add(prop.argument.name);
2526
+ });
2527
+ else if (t.isArrayPattern(id)) id.elements.forEach((elem) => {
2528
+ if (elem && t.isIdentifier(elem)) localVars.add(elem.name);
2529
+ });
2530
+ },
2531
+ FunctionDeclaration(path) {
2532
+ if (path.node.id) localVars.add(path.node.id.name);
2533
+ path.node.params.forEach((param) => {
2534
+ if (t.isIdentifier(param)) localVars.add(param.name);
2535
+ });
2536
+ },
2537
+ CatchClause(path) {
2538
+ if (path.node.param && t.isIdentifier(path.node.param)) localVars.add(path.node.param.name);
2539
+ },
2540
+ ForStatement(path) {
2541
+ const init = path.node.init;
2542
+ if (t.isVariableDeclaration(init)) init.declarations.forEach((decl) => {
2543
+ if (t.isIdentifier(decl.id)) localVars.add(decl.id.name);
2544
+ });
2545
+ }
2546
+ };
2547
+ }
2548
+ /**
2549
+ * 收集函数体中使用的外部变量
2550
+ */
2551
+ function collectUsedVariables(body, arrowFunctionArguments, vForInfoList, isAsync = false) {
2552
+ const usedVars = /* @__PURE__ */ new Set();
2553
+ const localVars = /* @__PURE__ */ new Set();
2554
+ arrowFunctionArguments.forEach((param) => {
2555
+ if (t.isIdentifier(param)) localVars.add(param.name);
2556
+ else if (t.isObjectPattern(param)) param.properties.forEach((prop) => {
2557
+ if (t.isObjectProperty(prop) && t.isIdentifier(prop.value)) localVars.add(prop.value.name);
2558
+ });
2559
+ else if (t.isAssignmentPattern(param)) {
2560
+ if (t.isIdentifier(param.left)) localVars.add(param.left.name);
2561
+ } else if (t.isRestElement(param)) {
2562
+ if (t.isIdentifier(param.argument)) localVars.add(param.argument.name);
2563
+ }
2564
+ });
2565
+ if (vForInfoList && vForInfoList.length > 0) vForInfoList.forEach((info) => {
2566
+ const itemName = getVForItemName(info);
2567
+ const indexName = getVForIndexName(info) || "index";
2568
+ if (itemName) localVars.add(itemName);
2569
+ localVars.add(indexName);
2570
+ });
2571
+ traverse(reparseBodyAsAST(body, isAsync), {
2572
+ ...createLocalVarCollector(localVars),
2573
+ Identifier(path) {
2574
+ const name = path.node.name;
2575
+ if (!localVars.has(name) && !GLOBAL_WHITELIST.has(name) && !path.scope.hasBinding(name, true)) {
2576
+ const parent = path.parent;
2577
+ if (t.isObjectProperty(parent) && parent.key === path.node && !parent.computed) return;
2578
+ if (t.isMemberExpression(parent) && parent.property === path.node && !parent.computed) return;
2579
+ if (t.isOptionalMemberExpression(parent) && parent.property === path.node && !parent.computed) return;
2580
+ usedVars.add(name);
2581
+ }
2582
+ }
2583
+ });
2584
+ return usedVars;
2585
+ }
2586
+ /**
2587
+ * 分析 v-for item 的使用情况
2588
+ */
2589
+ function analyzeVForItemUsage(body, vForInfoList, isAsync = false) {
2590
+ const lastVForInfo = vForInfoList[vForInfoList.length - 1];
2591
+ const itemName = getVForItemName(lastVForInfo);
2592
+ const usages = [];
2593
+ const ast = reparseBodyAsAST(body, isAsync);
2594
+ const localVars = /* @__PURE__ */ new Set();
2595
+ let hasLocalItemVar = false;
2596
+ traverse(ast, {
2597
+ ...createLocalVarCollector(localVars),
2598
+ VariableDeclarator(path) {
2599
+ const id = path.node.id;
2600
+ if (t.isIdentifier(id) && id.name === itemName) hasLocalItemVar = true;
2601
+ },
2602
+ FunctionDeclaration(path) {
2603
+ if (path.node.id && path.node.id.name === itemName) hasLocalItemVar = true;
2604
+ path.node.params.forEach((param) => {
2605
+ if (t.isIdentifier(param) && param.name === itemName) hasLocalItemVar = true;
2606
+ });
2607
+ },
2608
+ Identifier(path) {
2609
+ if (path.node.name !== itemName) return;
2610
+ const parent = path.parent;
2611
+ if (t.isVariableDeclarator(parent) && parent.id === path.node) return;
2612
+ const usage = {
2613
+ type: parent.type,
2614
+ isMemberExpression: t.isMemberExpression(parent) && parent.object === path.node,
2615
+ isReassignment: t.isAssignmentExpression(parent) && parent.left === path.node && parent.operator === "=",
2616
+ isUpdate: t.isUpdateExpression(parent) && parent.argument === path.node
2617
+ };
2618
+ usages.push(usage);
2619
+ }
2620
+ });
2621
+ if (hasLocalItemVar) return {
2622
+ itemName,
2623
+ usageCount: 0,
2624
+ usages: [],
2625
+ shouldCreateReference: false
2626
+ };
2627
+ const shouldCreate = shouldCreateLocalReference(usages);
2628
+ return {
2629
+ itemName,
2630
+ usageCount: usages.length,
2631
+ usages,
2632
+ shouldCreateReference: shouldCreate
2633
+ };
2634
+ }
2635
+ /**
2636
+ * 创建内联处理函数的函数体
2637
+ */
2638
+ function createInlineHandlerBody(body, arrowFunctionArguments, externalVars, vForInfoList, vForItemUsage, isAsync = false, dataKey = "a") {
2639
+ const statements = [];
2640
+ const paramNameMapping = /* @__PURE__ */ new Map();
2641
+ if (arrowFunctionArguments.length > 0) {
2642
+ const param = arrowFunctionArguments[0];
2643
+ if (t.isIdentifier(param)) {
2644
+ if (param.name !== "$event" && param.name !== "__vms_event") statements.push(t.variableDeclaration("const", [t.variableDeclarator(param, t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("detail")))]));
2645
+ else if (param.name === "$event") paramNameMapping.set("$event", EVENT_PARAM_NAME);
2646
+ } else if (t.isObjectPattern(param)) statements.push(t.variableDeclaration("const", [t.variableDeclarator(param, t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("detail")))]));
2647
+ }
2648
+ if (vForInfoList && vForInfoList.length > 0) {
2649
+ const indexVars = vForInfoList.map((info) => getVForIndexName(info) || "index").map((idx) => t.identifier(idx));
2650
+ statements.push(t.variableDeclaration("const", [t.variableDeclarator(t.objectPattern([t.objectProperty(t.identifier(dataKey), t.arrayPattern(indexVars), false, false)]), t.memberExpression(t.memberExpression(t.identifier(EVENT_PARAM_NAME), t.identifier("currentTarget")), t.identifier("dataset")))]));
2651
+ if (vForItemUsage?.shouldCreateReference) statements.push(createLocalReference(vForInfoList, vForItemUsage));
2652
+ }
2653
+ const transformedBody = replaceVariableAccess(t.cloneNode(body, true), externalVars, vForInfoList, vForItemUsage, paramNameMapping, isAsync);
2654
+ statements.push(...transformedBody.body);
2655
+ return t.blockStatement(statements);
2656
+ }
2657
+ /**
2658
+ * 创建局部引用语句
2659
+ * 注意:这里需要从 __vmsProxyRefs 而不是外层 item 标识符开始构建路径,
2660
+ * 因为 createInlineHandlerBody 中外层 item 会被 replaceVariableAccess 替换,
2661
+ * 而不会先声明为局部变量
2662
+ */
2663
+ function createLocalReference(vForInfoList, vForItemUsage) {
2664
+ const itemName = vForItemUsage.itemName;
2665
+ const accessExpression = buildProxyRefsItemAccess(vForInfoList, vForInfoList.findIndex((info) => getVForItemName(info) === itemName), void 0, true);
2666
+ return t.variableDeclaration("const", [t.variableDeclarator(t.identifier(itemName), accessExpression)]);
2667
+ }
2668
+ /**
2669
+ * 替换变量访问
2670
+ */
2671
+ function replaceVariableAccess(body, externalVars, vForInfoList, vForItemUsage, paramNameMapping, isAsync = false) {
2672
+ const localVars = /* @__PURE__ */ new Set();
2673
+ const ast = reparseBodyAsAST(body, isAsync);
2674
+ traverse(ast, { ...createLocalVarCollector(localVars) });
2675
+ traverse(ast, { Identifier(path) {
2676
+ const name = path.node.name;
2677
+ if (paramNameMapping && paramNameMapping.has(name)) {
2678
+ const mappedName = paramNameMapping.get(name);
2679
+ path.replaceWith(t.identifier(mappedName));
2680
+ return;
2681
+ }
2682
+ if (localVars.has(name)) return;
2683
+ const parent = path.parent;
2684
+ if (t.isObjectProperty(parent) && parent.key === path.node && !parent.computed) return;
2685
+ if (t.isMemberExpression(parent) && parent.property === path.node && !parent.computed) return;
2686
+ if (t.isOptionalMemberExpression(parent) && parent.property === path.node && !parent.computed) return;
2687
+ if (vForInfoList && vForInfoList.length > 0) {
2688
+ let isVForItem = false;
2689
+ let itemIndex = -1;
2690
+ for (let i = 0; i < vForInfoList.length; i++) {
2691
+ const vForInfo = vForInfoList[i];
2692
+ if (name === getVForItemName(vForInfo)) {
2693
+ isVForItem = true;
2694
+ itemIndex = i;
2695
+ break;
2696
+ }
2697
+ }
2698
+ if (isVForItem) if (itemIndex === vForInfoList.length - 1 && vForItemUsage?.shouldCreateReference) return;
2699
+ else {
2700
+ const accessExpression = buildProxyRefsItemAccess(vForInfoList, itemIndex);
2701
+ path.replaceWith(accessExpression);
2702
+ return;
2703
+ }
2704
+ if (vForInfoList.map((info) => getVForIndexName(info) || "index").includes(name)) return;
2705
+ }
2706
+ if (externalVars.has(name)) path.replaceWith(t.memberExpression(t.identifier("__vmsProxyRefs"), t.identifier(name)));
2707
+ } });
2708
+ return ast.program.body[0].expression.body;
2709
+ }
2710
+ //#endregion
2711
+ //#region src/template/nodeProps/event.ts
2712
+ function transformEventHandlers(node, returnValue, counter, ctx) {
2713
+ if (node.type !== NodeTypes.ELEMENT) return;
2714
+ counter.nodeDataKeyIndex = 0;
2715
+ const callExpressionWithArgs = /* @__PURE__ */ new Map();
2716
+ const props = node.props || [];
2717
+ const eventProps = [];
2718
+ for (const prop of props) {
2719
+ const result = processEventProperty(prop, node, counter, callExpressionWithArgs, returnValue, ctx);
2720
+ if (result) eventProps.push(result);
2721
+ }
2722
+ const dataProps = addGeneratedFunctions(callExpressionWithArgs, props, returnValue);
2723
+ if (eventProps.length > 0 || dataProps.length > 0) {
2724
+ const existingCodegenProps = getCodegenNodeProps(node);
2725
+ [...eventProps, ...dataProps].forEach((prop) => {
2726
+ existingCodegenProps.set(prop.name, { content: prop.content });
2727
+ });
2728
+ setCodegenNode(node, {
2729
+ type: node.type,
2730
+ tag: node.tag,
2731
+ props: existingCodegenProps,
2732
+ loc: node.loc
2733
+ });
2734
+ }
2735
+ }
2736
+ //#endregion
2737
+ //#region src/template/nodeProps/clazz.ts
2738
+ function transformTemplateClass(node, returnValue, counter, wxsExpressionStatements, ctx, isPage = false) {
2739
+ if (node.type === NodeTypes.ROOT) {
2740
+ const rootChildren = node.children.filter((child) => child.type === NodeTypes.ELEMENT);
2741
+ if (!isPage && rootChildren.length === 1) ctx.rootElementNode = rootChildren[0];
2742
+ return;
2743
+ }
2744
+ if (node.type !== NodeTypes.ELEMENT) return;
2745
+ const props = node.props;
2746
+ const isPushParentClass = !isPage && ctx.rootElementNode === node;
2747
+ const classPropContent = [];
2748
+ if (props) {
2749
+ const classBindProp = props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.rawName === ":class");
2750
+ const classStaticProp = props.find((prop) => prop.type === NodeTypes.ATTRIBUTE && prop.name === "class");
2751
+ if (classStaticProp && classStaticProp.value) classPropContent.push(classStaticProp.value.content.replace(/\s+/g, " ").trim());
2752
+ if (isPushParentClass) classPropContent.push("class");
2753
+ if (classBindProp) {
2754
+ const exp = classBindProp.exp;
2755
+ if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
2756
+ const classBindPropExpContent = exp.content;
2757
+ const rawAst = exp.ast;
2758
+ const ast = fallbackParseExpression(rawAst, classBindPropExpContent);
2759
+ if (ast) {
2760
+ const allElements = transformClassAst(ast);
2761
+ const dynamicElements = allElements.filter((item) => !t$1.isStringLiteral(item));
2762
+ const stringLiteralElements = allElements.filter((item) => t$1.isStringLiteral(item));
2763
+ if (stringLiteralElements.length > 0) classPropContent.push(...stringLiteralElements.map((item) => item.value));
2764
+ if (dynamicElements.length > 0) {
2765
+ const variables = extractVariablesFromArrayElements(dynamicElements);
2766
+ const functionName = counter.generateWxsFunctionName();
2767
+ const downleveled = dynamicElements.map((el) => downlevelExpressionCode(el));
2768
+ const allDeclarations = [...new Set(downleveled.map((d) => d.declarations).filter(Boolean))];
2769
+ const declarationsBlock = allDeclarations.length > 0 ? allDeclarations.join(" ") + " " : "";
2770
+ const funcAst = parse$1(`module.exports.${functionName} = function (${variables.join(", ")}) { ${declarationsBlock}return ${downleveled.length === 1 ? downleveled[0].code : `[${downleveled.map((d) => d.code).join(", ")}].filter(function (v) { return v; }).join(' ')`}; }`, { sourceType: "script" }).program.body[0];
2771
+ if (funcAst?.type === "ExpressionStatement") wxsExpressionStatements.push(funcAst);
2772
+ collectBindingVarsWithVarNameList(variables, node, returnValue, ctx);
2773
+ const wxsCallParams = variables.length > 0 ? `${variables.join(", ")}` : "";
2774
+ classPropContent.push(`{{${WXS_NAMESPACE}.${functionName}(${wxsCallParams})}}`);
2775
+ }
2776
+ } else {
2777
+ classPropContent.push(`{{${classBindPropExpContent}}}`);
2778
+ collectBindingVarsWithExpression(classBindPropExpContent, node, returnValue, ctx);
2779
+ }
2780
+ }
2781
+ }
2782
+ } else if (isPushParentClass) classPropContent.push("class");
2783
+ if (classPropContent.length > 0) {
2784
+ const existingCodegenProps = getCodegenNodeProps(node);
2785
+ existingCodegenProps.set("class", { content: classPropContent.join(" ") });
2786
+ setCodegenNode(node, {
2787
+ type: node.type,
2788
+ tag: node.tag,
2789
+ props: existingCodegenProps,
2790
+ loc: node.loc
2791
+ });
2792
+ }
2793
+ }
2794
+ function extractVariablesFromArrayElements(arrayElements) {
2795
+ const allVariables = /* @__PURE__ */ new Set();
2796
+ arrayElements.forEach((element) => {
2797
+ extractVariablesFromExpressionAST(element).forEach((v) => allVariables.add(v));
2798
+ });
2799
+ return Array.from(allVariables);
2800
+ }
2801
+ function isConditionEqualTo(condition, expectedValue) {
2802
+ return t$1.isBooleanLiteral(condition) && condition.value === expectedValue;
2803
+ }
2804
+ /**
2805
+ * 将模板字符串(TemplateLiteral)转换为字符串拼接表达式(BinaryExpression)
2806
+ * 例:`stat-card--${card.color}` → "stat-card--" + card.color
2807
+ */
2808
+ function templateLiteralToConcat(node) {
2809
+ const parts = [];
2810
+ node.quasis.forEach((quasi, i) => {
2811
+ const raw = quasi.value.cooked ?? quasi.value.raw;
2812
+ if (raw) parts.push(t$1.stringLiteral(raw));
2813
+ if (i < node.expressions.length) parts.push(node.expressions[i]);
2814
+ });
2815
+ if (parts.length === 0) return t$1.stringLiteral("");
2816
+ return parts.reduce((acc, cur) => t$1.binaryExpression("+", acc, cur));
2817
+ }
2818
+ function transformClassAst(ast) {
2819
+ const arrayElements = [];
2820
+ if (ast.type === "ArrayExpression") ast.elements.forEach((element) => {
2821
+ if (!element) return;
2822
+ if (t$1.isConditionalExpression(element)) {
2823
+ if (isConditionEqualTo(element.test, false)) return;
2824
+ if (isConditionEqualTo(element.test, true)) {
2825
+ arrayElements.push(element.consequent);
2826
+ return;
2827
+ }
2828
+ arrayElements.push(element);
2829
+ } else if (t$1.isStringLiteral(element)) arrayElements.push(element);
2830
+ else if (t$1.isIdentifier(element)) arrayElements.push(element);
2831
+ else if (t$1.isTemplateLiteral(element)) arrayElements.push(templateLiteralToConcat(element));
2832
+ else if (t$1.isObjectExpression(element)) transformObjectProperties(element, arrayElements);
2833
+ else arrayElements.push(element);
2834
+ });
2835
+ else if (t$1.isObjectExpression(ast)) transformObjectProperties(ast, arrayElements);
2836
+ else {
2837
+ const expr = ast;
2838
+ arrayElements.push(t$1.isTemplateLiteral(expr) ? templateLiteralToConcat(expr) : expr);
2839
+ }
2840
+ return arrayElements;
2841
+ }
2842
+ /**
2843
+ * 将 ObjectExpression 的属性展开为条件表达式数组
2844
+ * 提取自 transformClassAst 中两处重复的对象属性处理逻辑
2845
+ */
2846
+ function transformObjectProperties(objExpr, arrayElements) {
2847
+ objExpr.properties.forEach((property) => {
2848
+ if (!t$1.isObjectProperty(property)) return;
2849
+ const condition = property.value;
2850
+ if (!t$1.isExpression(condition)) return;
2851
+ if (isConditionEqualTo(condition, false)) return;
2852
+ let classNameExpression;
2853
+ if (property.computed && t$1.isExpression(property.key)) classNameExpression = property.key;
2854
+ else if (t$1.isIdentifier(property.key)) classNameExpression = t$1.stringLiteral(property.key.name);
2855
+ else if (t$1.isStringLiteral(property.key)) classNameExpression = property.key;
2856
+ else return;
2857
+ if (isConditionEqualTo(condition, true)) {
2858
+ arrayElements.push(classNameExpression);
2859
+ return;
2860
+ }
2861
+ arrayElements.push(t$1.conditionalExpression(condition, classNameExpression, t$1.stringLiteral("")));
2862
+ });
2863
+ }
2864
+ //#endregion
2865
+ //#region src/template/nodeProps/style.ts
2866
+ function toKebabCase(keyName) {
2867
+ if (keyName.includes("-")) return keyName;
2868
+ return keyName.replace(/([A-Z])/g, (_, c) => `-${c.toLowerCase()}`).replace(/^-/, "");
2869
+ }
2870
+ function buildStyleStringFromObject(objectExpression) {
2871
+ const keyValueExpressions = [];
2872
+ objectExpression.properties.forEach((prop) => {
2873
+ if (prop.type !== "ObjectProperty") return;
2874
+ const valueExpression = prop.value;
2875
+ if (t$1.isRestElement(valueExpression) || t$1.isAssignmentPattern(valueExpression) || t$1.isArrayPattern(valueExpression) || t$1.isObjectPattern(valueExpression) || t$1.isVoidPattern(valueExpression)) return;
2876
+ if (prop.computed && t$1.isExpression(prop.key)) keyValueExpressions.push(t$1.binaryExpression("+", t$1.binaryExpression("+", prop.key, t$1.stringLiteral(":")), valueExpression));
2877
+ else if (prop.key.type === "Identifier" || prop.key.type === "StringLiteral") {
2878
+ const kebabKey = toKebabCase(prop.key.type === "Identifier" ? prop.key.name : prop.key.value);
2879
+ keyValueExpressions.push(t$1.binaryExpression("+", t$1.stringLiteral(`${kebabKey}:`), valueExpression));
2880
+ }
2881
+ });
2882
+ if (keyValueExpressions.length === 0) return null;
2883
+ return keyValueExpressions.reduce((acc, cur) => t$1.binaryExpression("+", t$1.binaryExpression("+", acc, t$1.stringLiteral(";")), cur));
2884
+ }
2885
+ function buildStyleStringFromArray(arrayExpression) {
2886
+ const parts = [];
2887
+ arrayExpression.elements.forEach((element) => {
2888
+ if (!element) return;
2889
+ if (t$1.isObjectExpression(element)) {
2890
+ const expr = buildStyleStringFromObject(element);
2891
+ if (expr) parts.push(expr);
2892
+ } else if (t$1.isStringLiteral(element) || t$1.isTemplateLiteral(element)) parts.push(element);
2893
+ else if (t$1.isIdentifier(element) || t$1.isMemberExpression(element)) parts.push(t$1.callExpression(t$1.memberExpression(t$1.identifier("__vmsWXSUtils"), t$1.identifier("styleToString")), [element]));
2894
+ else if (t$1.isExpression(element)) parts.push(element);
2895
+ });
2896
+ if (parts.length === 0) return null;
2897
+ return parts.reduce((acc, cur) => t$1.binaryExpression("+", t$1.binaryExpression("+", acc, t$1.stringLiteral(";")), cur));
2898
+ }
2899
+ function transformTemplateStyle(node, returnValue, counter, wxsExpressionStatements, ctx, isPage = false) {
2900
+ if (node.type !== NodeTypes.ELEMENT) return;
2901
+ const parentStyleContent = !isPage && ctx.rootElementNode === node ? "{{style}}" : null;
2902
+ const props = node.props;
2903
+ const styleContentList = [];
2904
+ if (props) {
2905
+ const styleBindProp = props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.rawName === ":style");
2906
+ const styleStaticProp = props.find((prop) => prop.type === NodeTypes.ATTRIBUTE && prop.name === "style");
2907
+ if (!styleBindProp && !styleStaticProp && !parentStyleContent) return;
2908
+ if (styleStaticProp && styleStaticProp.value) {
2909
+ const styleStaticPropValue = styleStaticProp.value.content.replace(/\s+/g, " ").replace(/;\s+/g, ";").trim();
2910
+ styleContentList.push(styleStaticPropValue.endsWith(";") ? styleStaticPropValue.slice(0, -1) : styleStaticPropValue);
2911
+ }
2912
+ if (parentStyleContent) styleContentList.push(parentStyleContent);
2913
+ if (styleBindProp) {
2914
+ const { content } = getTemplateNodeProp(node, styleBindProp, returnValue, counter, wxsExpressionStatements, ctx, (statements, lastIndex) => {
2915
+ return statements.map((item, index) => {
2916
+ if (index !== lastIndex) return item;
2917
+ if (item.type !== "ExpressionStatement") return item;
2918
+ const expr = item.expression;
2919
+ if (expr.type === "ObjectExpression") {
2920
+ const finalExpr = buildStyleStringFromObject(expr);
2921
+ if (finalExpr) return t$1.returnStatement(finalExpr);
2922
+ }
2923
+ if (expr.type === "ArrayExpression") {
2924
+ const finalExpr = buildStyleStringFromArray(expr);
2925
+ if (finalExpr) return t$1.returnStatement(finalExpr);
2926
+ }
2927
+ if (expr.type === "StringLiteral" || expr.type === "TemplateLiteral") return t$1.returnStatement(expr);
2928
+ if (t$1.isExpression(expr)) return t$1.returnStatement(expr);
2929
+ return item;
2930
+ });
2931
+ });
2932
+ styleContentList.push(content);
2933
+ }
2934
+ }
2935
+ if (!props && parentStyleContent) styleContentList.push(parentStyleContent);
2936
+ const attributePropContent = styleContentList.join(";");
2937
+ if (attributePropContent) {
2938
+ const codegenProps = getCodegenNodeProps(node);
2939
+ codegenProps.set("style", { content: attributePropContent });
2940
+ setCodegenNode(node, {
2941
+ type: node.type,
2942
+ tag: node.tag,
2943
+ props: codegenProps,
2944
+ loc: node.loc
2945
+ });
2946
+ }
2947
+ }
2948
+ //#endregion
2949
+ //#region src/template/propTransformers.ts
2950
+ /**
2951
+ * 属性转换器 - 将 Vue 模板属性转换为小程序 WXML 属性
2952
+ *
2953
+ * 每个转换器接收一个属性,返回转换结果或 undefined(表示不处理)
2954
+ * 所有转换器在统一节点转换器中被调用,结果按优先级合并
2955
+ */
2956
+ /**
2957
+ * 属性优先级常量
2958
+ */
2959
+ const PROP_PRIORITIES = {
2960
+ "wx:for": 100,
2961
+ "wx:for-item": 100,
2962
+ "wx:for-index": 100,
2963
+ "wx:key": 100,
2964
+ "wx:if": 100,
2965
+ "wx:elif": 100,
2966
+ "wx:else": 100,
2967
+ hidden: 90,
2968
+ class: 50,
2969
+ style: 50,
2970
+ id: 10,
2971
+ src: 10,
2972
+ href: 10,
2973
+ _default: 0
2974
+ };
2975
+ /**
2976
+ * 获取属性优先级
2977
+ */
2978
+ function getPriority(key) {
2979
+ return Object.hasOwn(PROP_PRIORITIES, key) ? PROP_PRIORITIES[key] : PROP_PRIORITIES._default;
2980
+ }
2981
+ /**
2982
+ * 创建转换结果辅助函数
2983
+ */
2984
+ function createResult(key, content, priority) {
2985
+ return {
2986
+ key,
2987
+ value: { content },
2988
+ priority: priority ?? getPriority(key)
2989
+ };
2990
+ }
2991
+ /**
2992
+ * 从 v-for 指令中提取 forItem 和 forIndex
2993
+ * 公共逻辑,供 transformVForProp 共用
2994
+ */
2995
+ function parseForVariables(prop, counter) {
2996
+ const directive = prop;
2997
+ if (!directive.forParseResult) return;
2998
+ const forItem = directive.forParseResult.value?.type === NodeTypes.SIMPLE_EXPRESSION ? directive.forParseResult.value.content : "item";
2999
+ return {
3000
+ forItem,
3001
+ forIndex: directive.forParseResult.key?.type === NodeTypes.SIMPLE_EXPRESSION ? directive.forParseResult.key.content : counter.generateVForIndexName(forItem)
3002
+ };
3003
+ }
3004
+ /**
3005
+ * v-for 转换器
3006
+ * v-for="(item, index) in items" → wx:for="{{items}}" wx:for-item="item" wx:for-index="index" wx:key="..."
3007
+ */
3008
+ function transformVForProp(prop, context) {
3009
+ if (prop.type !== NodeTypes.DIRECTIVE || prop.name !== "for") return;
3010
+ const directive = prop;
3011
+ if (!directive.forParseResult) return;
3012
+ const { content: arrayName } = getTemplateNodeProp(context.node, {
3013
+ loc: directive.loc,
3014
+ exp: directive.forParseResult.source
3015
+ }, context.returnValue, context.counter, context.wxsExpressionStatements, context.ctx);
3016
+ const forVars = parseForVariables(prop, context.counter);
3017
+ if (!forVars) return void 0;
3018
+ if (!(directive.forParseResult.key?.type === NodeTypes.SIMPLE_EXPRESSION)) directive.forParseResult.key = {
3019
+ type: NodeTypes.SIMPLE_EXPRESSION,
3020
+ content: forVars.forIndex,
3021
+ isStatic: false,
3022
+ constType: 0,
3023
+ loc: directive.loc
3024
+ };
3025
+ const results = [createResult("wx:for", arrayName, PROP_PRIORITIES["wx:for"])];
3026
+ if (forVars.forItem !== "item") results.push(createResult("wx:for-item", forVars.forItem, PROP_PRIORITIES["wx:for-item"]));
3027
+ if (forVars.forIndex !== "index") results.push(createResult("wx:for-index", forVars.forIndex, PROP_PRIORITIES["wx:for-index"]));
3028
+ return results;
3029
+ }
3030
+ /**
3031
+ * :key 转换器(配合 v-for 使用)
3032
+ * :key="item.id" → wx:key="id"
3033
+ *
3034
+ * 注意:wx:key 只支持 item 的直接属性名(如 "id"),不支持嵌套路径(如 "subRow.id")。
3035
+ * 对于嵌套路径,输出 *this 作为回退并发出警告。
3036
+ */
3037
+ function transformKeyProp(prop) {
3038
+ if (prop.type === NodeTypes.DIRECTIVE && prop.name === "bind" && prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION && prop.arg.content === "key") {
3039
+ const rawKeyContent = prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION ? prop.exp.content : void 0;
3040
+ if (!rawKeyContent) return createResult("wx:key", void 0, PROP_PRIORITIES["wx:key"]);
3041
+ if (/^\w+$/.test(rawKeyContent)) return createResult("wx:key", rawKeyContent, PROP_PRIORITIES["wx:key"]);
3042
+ const simpleKeyMatch = rawKeyContent.match(/^(\w+)\.(\w+)$/);
3043
+ if (simpleKeyMatch) return createResult("wx:key", simpleKeyMatch[2], PROP_PRIORITIES["wx:key"]);
3044
+ console.warn(`[vms] wx:key 不支持复杂表达式 "${rawKeyContent}",已回退为 "*this"。wx:key 仅支持 item 的直接属性名(如 "id")。`);
3045
+ return createResult("wx:key", "*this", PROP_PRIORITIES["wx:key"]);
3046
+ }
3047
+ }
3048
+ /**
3049
+ * v-if/v-else-if/v-else 转换器
3050
+ */
3051
+ function transformVIfProp(prop, context) {
3052
+ if (prop.type !== NodeTypes.DIRECTIVE) return;
3053
+ if (prop.name === "if") {
3054
+ const { content } = getTemplateNodeProp(context.node, {
3055
+ loc: prop.loc,
3056
+ exp: prop.exp
3057
+ }, context.returnValue, context.counter, context.wxsExpressionStatements, context.ctx);
3058
+ return createResult("wx:if", content, PROP_PRIORITIES["wx:if"]);
3059
+ }
3060
+ if (prop.name === "else-if") {
3061
+ const { content } = getTemplateNodeProp(context.node, {
3062
+ loc: prop.loc,
3063
+ exp: prop.exp
3064
+ }, context.returnValue, context.counter, context.wxsExpressionStatements, context.ctx);
3065
+ return createResult("wx:elif", content, PROP_PRIORITIES["wx:elif"]);
3066
+ }
3067
+ if (prop.name === "else") return createResult("wx:else", void 0, PROP_PRIORITIES["wx:else"]);
3068
+ }
3069
+ /**
3070
+ * v-show 转换器
3071
+ * v-show="condition" → hidden="{{!condition}}"
3072
+ */
3073
+ function transformVShowProp(prop, context) {
3074
+ if (prop.type !== NodeTypes.DIRECTIVE || prop.name !== "show") return;
3075
+ const { content } = getTemplateNodeProp(context.node, {
3076
+ loc: prop.loc,
3077
+ exp: prop.exp
3078
+ }, context.returnValue, context.counter, context.wxsExpressionStatements, context.ctx);
3079
+ return createResult("hidden", `{{!(${content?.slice(2, -2) || ""})}}`, PROP_PRIORITIES["hidden"]);
3080
+ }
3081
+ const SPECIAL_ATTRS_BIND = [
3082
+ "class",
3083
+ "style",
3084
+ "key"
3085
+ ];
3086
+ /**
3087
+ * 普通属性绑定转换器
3088
+ * :id="dynamicId" → id="{{dynamicId}}"
3089
+ * 复杂表达式会生成 WXS 函数
3090
+ */
3091
+ function transformBindProp(prop, context) {
3092
+ if (prop.type === NodeTypes.DIRECTIVE && prop.name === "bind" && prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION) {
3093
+ const attrName = prop.arg.content;
3094
+ if (SPECIAL_ATTRS_BIND.includes(attrName)) return;
3095
+ if (prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
3096
+ const { content } = getTemplateNodeProp(context.node, {
3097
+ exp: prop.exp,
3098
+ loc: prop.loc
3099
+ }, context.returnValue, context.counter, context.wxsExpressionStatements, context.ctx);
3100
+ return createResult(attrName, content, 20);
3101
+ }
3102
+ }
3103
+ }
3104
+ const SPECIAL_ATTRS_STATIC = ["class", "style"];
3105
+ /**
3106
+ * 静态属性转换器
3107
+ * id="foo" → id="foo"
3108
+ */
3109
+ function transformStaticProp(prop) {
3110
+ if (prop.type === NodeTypes.ATTRIBUTE) {
3111
+ if (SPECIAL_ATTRS_STATIC.includes(prop.name)) return;
3112
+ return createResult(prop.name, prop.value?.content, getPriority(prop.name));
3113
+ }
3114
+ }
3115
+ /**
3116
+ * 所有属性转换器列表(按优先级排序)
3117
+ */
3118
+ const propTransformers = [
3119
+ transformVForProp,
3120
+ transformKeyProp,
3121
+ transformVIfProp,
3122
+ transformVShowProp,
3123
+ transformBindProp,
3124
+ transformStaticProp
3125
+ ];
3126
+ /**
3127
+ * 按优先级合并属性转换结果
3128
+ * 高优先级覆盖低优先级
3129
+ */
3130
+ function mergePropResults(results) {
3131
+ const grouped = /* @__PURE__ */ new Map();
3132
+ for (const result of results) {
3133
+ const existing = grouped.get(result.key) || [];
3134
+ existing.push(result);
3135
+ grouped.set(result.key, existing);
3136
+ }
3137
+ const merged = /* @__PURE__ */ new Map();
3138
+ for (const [key, group] of grouped) {
3139
+ const highest = group.reduce((max, current) => current.priority > max.priority ? current : max);
3140
+ merged.set(key, highest.value);
3141
+ }
3142
+ return merged;
3143
+ }
3144
+ //#endregion
3145
+ //#region src/template/index.ts
3146
+ function parseTemplate(templateAST, filePath, isPage = false, scriptScope) {
3147
+ const ctx = createVMSTransformContext(scriptScope);
3148
+ const counter = {
3149
+ wxsFunctionCounter: 0,
3150
+ functionPropertyCounter: 0,
3151
+ nodeDataKeyIndex: 0,
3152
+ vForIndexCounter: 0,
3153
+ generateWxsFunctionName() {
3154
+ return `__wxs_${this.wxsFunctionCounter++}`;
3155
+ },
3156
+ generateFunctionPropertyName() {
3157
+ return `__fun_${this.functionPropertyCounter++}`;
3158
+ },
3159
+ generateVForIndexName(forItem) {
3160
+ return `_${forItem}_${this.vForIndexCounter++}_index`;
3161
+ }
3162
+ };
3163
+ const wxsExpressionStatements = [];
3164
+ const returnValue = t$1.objectExpression([]);
3165
+ const thirdPartyComponents = /* @__PURE__ */ new Map();
3166
+ assignVForInfoListMinimal(templateAST, ctx);
3167
+ const unifiedTransform = createUnifiedNodeTransform(returnValue, counter, wxsExpressionStatements, ctx);
3168
+ traverseNode(templateAST, createTransformContext(templateAST, { nodeTransforms: [
3169
+ ...getComponentMatcher.hasConfig() ? [(node) => collectThirdComponents(node, thirdPartyComponents)] : [],
3170
+ (node) => transformSlotsAndTemplate(node),
3171
+ (node) => transformTemplateClass(node, returnValue, counter, wxsExpressionStatements, ctx, isPage),
3172
+ (node) => transformTemplateStyle(node, returnValue, counter, wxsExpressionStatements, ctx, isPage),
3173
+ unifiedTransform,
3174
+ (node) => transformEventHandlers(node, returnValue, counter, ctx),
3175
+ createRootNodeTransform()
3176
+ ] }));
3177
+ return {
3178
+ wxmlContent: generateWxml(generateWxsScripts(wxsExpressionStatements, filePath), templateAST),
3179
+ returnValue,
3180
+ thirdPartyComponents,
3181
+ bridgedFunctions: ctx.bridgedFunctions,
3182
+ internalVars: ctx.internalVars,
3183
+ renderVars: ctx.renderVars,
3184
+ needsProxyRefs: ctx.needsProxyRefs
3185
+ };
3186
+ }
3187
+ /**
3188
+ * 创建统一节点转换器
3189
+ * 在单次遍历中完成属性转换和 codegenNode 构建
3190
+ */
3191
+ function createUnifiedNodeTransform(returnValue, counter, wxsExpressionStatements, ctx) {
3192
+ const propResultsMap = /* @__PURE__ */ new WeakMap();
3193
+ return (node) => {
3194
+ if (node.type === NodeTypes.INTERPOLATION) {
3195
+ const interpolationNode = node;
3196
+ if (interpolationNode.content?.type === NodeTypes.SIMPLE_EXPRESSION) {
3197
+ const { content } = getTemplateNodeProp(node, {
3198
+ exp: interpolationNode.content,
3199
+ loc: node.loc
3200
+ }, returnValue, counter, wxsExpressionStatements, ctx);
3201
+ setCodegenNode(node, {
3202
+ type: NodeTypes.INTERPOLATION,
3203
+ content,
3204
+ loc: node.loc
3205
+ });
3206
+ }
3207
+ return;
3208
+ }
3209
+ if (node.type === NodeTypes.TEXT || node.type === NodeTypes.COMMENT) {
3210
+ const codegenNode = createSimpleCodegenNode(node);
3211
+ if (codegenNode) setCodegenNode(node, codegenNode);
3212
+ return;
3213
+ }
3214
+ if (node.type !== NodeTypes.ELEMENT) return;
3215
+ const elementNode = node;
3216
+ const transformCtx = {
3217
+ returnValue,
3218
+ counter,
3219
+ wxsExpressionStatements,
3220
+ ctx,
3221
+ node: elementNode
3222
+ };
3223
+ const propResults = [];
3224
+ for (const prop of elementNode.props || []) for (const transformer of propTransformers) {
3225
+ const result = transformer(prop, transformCtx);
3226
+ if (result) {
3227
+ if (Array.isArray(result)) propResults.push(...result);
3228
+ else propResults.push(result);
3229
+ break;
3230
+ }
3231
+ }
3232
+ propResultsMap.set(node, propResults);
3233
+ return () => {
3234
+ const children = [];
3235
+ for (const child of elementNode.children || []) {
3236
+ const childCodegen = getCodegenNode(child);
3237
+ if (childCodegen) children.push(childCodegen);
3238
+ }
3239
+ const finalProps = mergePropResults(propResultsMap.get(node) || []);
3240
+ const existingCodegen = getCodegenNode(node);
3241
+ if (existingCodegen?.props) for (const [key, value] of existingCodegen.props) finalProps.set(key, value);
3242
+ setCodegenNode(node, {
3243
+ type: NodeTypes.ELEMENT,
3244
+ tag: elementNode.tag,
3245
+ props: finalProps,
3246
+ children,
3247
+ loc: elementNode.loc
3248
+ });
3249
+ };
3250
+ };
3251
+ }
3252
+ /**
3253
+ * 为非元素节点创建 codegenNode
3254
+ */
3255
+ function createSimpleCodegenNode(node) {
3256
+ switch (node.type) {
3257
+ case NodeTypes.TEXT: return {
3258
+ type: NodeTypes.TEXT,
3259
+ content: node.content,
3260
+ loc: node.loc
3261
+ };
3262
+ case NodeTypes.INTERPOLATION: {
3263
+ const content = node.content?.type === NodeTypes.SIMPLE_EXPRESSION ? `{{${node.content.content}}}` : `无法转译`;
3264
+ return {
3265
+ type: NodeTypes.INTERPOLATION,
3266
+ content,
3267
+ loc: node.loc
3268
+ };
3269
+ }
3270
+ case NodeTypes.COMMENT: return {
3271
+ type: NodeTypes.COMMENT,
3272
+ content: node.content,
3273
+ loc: node.loc
3274
+ };
3275
+ default: return null;
3276
+ }
3277
+ }
3278
+ /**
3279
+ * 创建根节点转换器
3280
+ * 在遍历结束时构建根节点的 codegenNode
3281
+ */
3282
+ function createRootNodeTransform() {
3283
+ return (node) => {
3284
+ if (node.type !== NodeTypes.ROOT) return;
3285
+ return () => {
3286
+ const rootNode = node;
3287
+ const children = [];
3288
+ for (const child of rootNode.children || []) {
3289
+ const childCodegen = getCodegenNode(child);
3290
+ if (childCodegen) children.push(childCodegen);
3291
+ }
3292
+ setCodegenNode(node, {
3293
+ type: NodeTypes.ROOT,
3294
+ children,
3295
+ loc: node.loc
3296
+ });
3297
+ };
3298
+ };
3299
+ }
3300
+ function generateWxsScripts(wxsFunctions, filePath) {
3301
+ if (wxsFunctions.length > 0) {
3302
+ let hasArrayUtils = false;
3303
+ const functionsCode = wxsFunctions.map((stmt) => {
3304
+ const code = generate(stmt, { jsescOption: { quotes: "single" } }).code;
3305
+ if (!hasArrayUtils) code.includes("__vmsWXSUtils.") && (hasArrayUtils = true);
3306
+ return code;
3307
+ });
3308
+ if (hasArrayUtils) functionsCode.unshift(`var __vmsWXSUtils = require("${getPolyfillFileRelativePath("wxsUtils.wxs", filePath)}");`);
3309
+ return `<wxs module="${WXS_NAMESPACE}">\n${functionsCode.join("\n")}</wxs>\n`;
3310
+ }
3311
+ }
3312
+ //#endregion
3313
+ //#region src/utils/merge.ts
3314
+ /**
3315
+ * 深度合并两个普通对象,合并规则:
3316
+ * 1. 类型不同:新值覆盖旧值
3317
+ * 2. 都是普通对象:递归合并(取并集)
3318
+ * 3. 都是数组:取并集(去重)
3319
+ * 4. 同类型原始值:新值覆盖旧值
3320
+ */
3321
+ function deepMerge(target, source) {
3322
+ const result = { ...target };
3323
+ for (const key of Object.keys(source)) {
3324
+ const srcVal = source[key];
3325
+ const tgtVal = result[key];
3326
+ if (!(key in result)) result[key] = srcVal;
3327
+ else if (!isSameCompositeType(tgtVal, srcVal)) result[key] = srcVal;
3328
+ else if (isPlainObject(tgtVal) && isPlainObject(srcVal)) result[key] = deepMerge(tgtVal, srcVal);
3329
+ else if (Array.isArray(tgtVal) && Array.isArray(srcVal)) result[key] = arrayUnion(tgtVal, srcVal);
3330
+ else result[key] = srcVal;
3331
+ }
3332
+ return result;
3333
+ }
3334
+ function isPlainObject(val) {
3335
+ return val !== null && typeof val === "object" && !Array.isArray(val);
3336
+ }
3337
+ function isSameCompositeType(a, b) {
3338
+ if (Array.isArray(a) && Array.isArray(b)) return true;
3339
+ if (isPlainObject(a) && isPlainObject(b)) return true;
3340
+ return false;
3341
+ }
3342
+ function arrayUnion(a, b) {
3343
+ const seen = new Set(a.map(serialize));
3344
+ const result = [...a];
3345
+ for (const item of b) if (!seen.has(serialize(item))) {
3346
+ result.push(item);
3347
+ seen.add(serialize(item));
3348
+ }
3349
+ return result;
3350
+ }
3351
+ function serialize(val) {
3352
+ return JSON.stringify(val);
3353
+ }
3354
+ //#endregion
3355
+ //#region src/transformer.ts
3356
+ const srcDir = join(process.cwd(), userConfig.sourceDir);
3357
+ function resolveComponentPath(importPath) {
3358
+ if (importPath.startsWith("@/")) return importPath.replace("@/", "/");
3359
+ return importPath;
3360
+ }
3361
+ function generateUsingComponents(imports, thirdPartyComponents) {
3362
+ const usingComponents = {};
3363
+ imports.forEach((imp) => {
3364
+ if (imp.path.endsWith(".vue")) {
3365
+ const componentName = imp.name;
3366
+ usingComponents[componentName] = resolveComponentPath(imp.path).replace(/\.vue$/, "");
3367
+ }
3368
+ });
3369
+ thirdPartyComponents.forEach((value, key) => {
3370
+ usingComponents[key] = value;
3371
+ });
3372
+ return usingComponents;
3373
+ }
3374
+ async function transformVueToMiniProgram(filePath, outputDir, isPage = false, cb) {
3375
+ const { descriptor } = parse(readFileSync(filePath, "utf-8"), {
3376
+ filename: filePath,
3377
+ templateParseOptions: { comments: false }
3378
+ });
3379
+ const { template, scriptSetup, styles } = descriptor;
3380
+ if (!template?.ast) return;
3381
+ try {
3382
+ const scriptScope = !scriptSetup ? createEmptyScriptScope() : analyzeScriptScope(scriptSetup.content, filePath);
3383
+ const { wxmlContent, returnValue, thirdPartyComponents, bridgedFunctions, internalVars, renderVars, needsProxyRefs } = parseTemplate(template.ast, filePath, isPage, scriptScope);
3384
+ const result = await parseScript(descriptor, returnValue, bridgedFunctions, internalVars, renderVars, needsProxyRefs, isPage, scriptScope);
3385
+ const css = parseStyles(styles);
3386
+ const componentDir = join(outputDir, relative(srcDir, dirname(filePath)));
3387
+ if (!existsSync(componentDir)) await mkdir(componentDir, { recursive: true });
3388
+ const baseJsonConfig = {
3389
+ component: true,
3390
+ styleIsolation: isPage ? "shared" : "apply-shared",
3391
+ usingComponents: generateUsingComponents(result.vueComponentImports, thirdPartyComponents)
3392
+ };
3393
+ const jsonConfig = result.defineOptionsObject ? deepMerge(baseJsonConfig, result.defineOptionsObject) : baseJsonConfig;
3394
+ const script = await cb(result.script);
3395
+ const componentName = basename(filePath, ".vue");
3396
+ const wxmlPath = join(componentDir, `${componentName}.wxml`);
3397
+ const jsPath = join(componentDir, `${componentName}.js`);
3398
+ const wxssPath = join(componentDir, `${componentName}.wxss`);
3399
+ const jsonPath = join(componentDir, `${componentName}.json`);
3400
+ const jsonContent = JSON.stringify(jsonConfig, null, 2);
3401
+ return Promise.all([
3402
+ writeFileIfChangedAsync(wxmlPath, wxmlContent),
3403
+ writeFileIfChangedAsync(jsPath, script),
3404
+ writeFileIfChangedAsync(wxssPath, css),
3405
+ writeFileIfChangedAsync(jsonPath, jsonContent)
3406
+ ]);
3407
+ } catch (e) {
3408
+ handleCompileError(descriptor.source, e, filePath);
3409
+ return Promise.reject(e);
3410
+ }
3411
+ }
3412
+ function streamHash(filePath) {
3413
+ return new Promise((resolve, reject) => {
3414
+ const hash = createHash("md5");
3415
+ const stream = createReadStream(filePath);
3416
+ stream.on("data", (chunk) => hash.update(chunk));
3417
+ stream.on("end", () => resolve(hash.digest("hex")));
3418
+ stream.on("error", reject);
3419
+ });
3420
+ }
3421
+ function stringHash(content) {
3422
+ return createHash("md5").update(content).digest("hex");
3423
+ }
3424
+ async function writeFileIfChangedAsync(filePath, newContent) {
3425
+ try {
3426
+ if (!existsSync(filePath)) {
3427
+ await writeFile(filePath, newContent, "utf-8");
3428
+ return;
3429
+ }
3430
+ const existingStat = await stat(filePath);
3431
+ const newContentLength = Buffer.byteLength(newContent, "utf8");
3432
+ if (existingStat.size !== newContentLength) {
3433
+ await writeFile(filePath, newContent, "utf-8");
3434
+ return;
3435
+ }
3436
+ const [existingHash, newHash] = await Promise.all([streamHash(filePath), Promise.resolve(stringHash(newContent))]);
3437
+ if (existingHash === newHash) return;
3438
+ await writeFile(filePath, newContent, "utf-8");
3439
+ } catch (error) {
3440
+ console.error(`❌ 写入文件失败 ${filePath}:`, getErrorMessage(error));
3441
+ throw error;
3442
+ }
3443
+ }
3444
+ //#endregion
3445
+ //#region node_modules/.pnpm/rolldown@1.0.0/node_modules/rolldown/dist/shared/binding-ESkOU1xr.mjs
3446
+ var __create = Object.create;
3447
+ var __defProp = Object.defineProperty;
3448
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3449
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3450
+ var __getProtoOf = Object.getPrototypeOf;
3451
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
3452
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
3453
+ var __copyProps = (to, from, except, desc) => {
3454
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
3455
+ key = keys[i];
3456
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
3457
+ get: ((k) => from[k]).bind(null, key),
3458
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
3459
+ });
3460
+ }
3461
+ return to;
3462
+ };
3463
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
3464
+ value: mod,
3465
+ enumerable: true
3466
+ }) : target, mod));
3467
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3468
+ var require_webcontainer_fallback = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3469
+ const fs = __require("node:fs");
3470
+ const childProcess = __require("node:child_process");
3471
+ const version = JSON.parse(fs.readFileSync(__require.resolve("rolldown/package.json"), "utf-8")).version;
3472
+ const baseDir = `/tmp/rolldown-${version}`;
3473
+ const bindingEntry = `${baseDir}/node_modules/@rolldown/binding-wasm32-wasi/rolldown-binding.wasi.cjs`;
3474
+ if (!fs.existsSync(bindingEntry)) {
3475
+ const bindingPkg = `@rolldown/binding-wasm32-wasi@${version}`;
3476
+ fs.rmSync(baseDir, {
3477
+ recursive: true,
3478
+ force: true
3479
+ });
3480
+ fs.mkdirSync(baseDir, { recursive: true });
3481
+ console.log(`[rolldown] Downloading ${bindingPkg} on WebContainer...`);
3482
+ childProcess.execFileSync("pnpm", ["i", bindingPkg], {
3483
+ cwd: baseDir,
3484
+ stdio: "inherit"
3485
+ });
3486
+ }
3487
+ module.exports = __require(bindingEntry);
3488
+ }));
3489
+ var require_binding = /* @__PURE__ */ __commonJSMin(((exports, module) => {
3490
+ const { readFileSync } = __require("node:fs");
3491
+ let nativeBinding = null;
3492
+ const loadErrors = [];
3493
+ const isMusl = () => {
3494
+ let musl = false;
3495
+ if (process.platform === "linux") {
3496
+ musl = isMuslFromFilesystem();
3497
+ if (musl === null) musl = isMuslFromReport();
3498
+ if (musl === null) musl = isMuslFromChildProcess();
3499
+ }
3500
+ return musl;
3501
+ };
3502
+ const isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
3503
+ const isMuslFromFilesystem = () => {
3504
+ try {
3505
+ return readFileSync("/usr/bin/ldd", "utf-8").includes("musl");
3506
+ } catch {
3507
+ return null;
3508
+ }
3509
+ };
3510
+ const isMuslFromReport = () => {
3511
+ let report = null;
3512
+ if (typeof process.report?.getReport === "function") {
3513
+ process.report.excludeNetwork = true;
3514
+ report = process.report.getReport();
3515
+ }
3516
+ if (!report) return null;
3517
+ if (report.header && report.header.glibcVersionRuntime) return false;
3518
+ if (Array.isArray(report.sharedObjects)) {
3519
+ if (report.sharedObjects.some(isFileMusl)) return true;
3520
+ }
3521
+ return false;
3522
+ };
3523
+ const isMuslFromChildProcess = () => {
3524
+ try {
3525
+ return __require("child_process").execSync("ldd --version", { encoding: "utf8" }).includes("musl");
3526
+ } catch (e) {
3527
+ return false;
3528
+ }
3529
+ };
3530
+ function requireNative() {
3531
+ if (process.env.NAPI_RS_NATIVE_LIBRARY_PATH) try {
3532
+ return __require(process.env.NAPI_RS_NATIVE_LIBRARY_PATH);
3533
+ } catch (err) {
3534
+ loadErrors.push(err);
3535
+ }
3536
+ else if (process.platform === "android") if (process.arch === "arm64") {
3537
+ try {
3538
+ return __require("./rolldown-binding.android-arm64.node");
3539
+ } catch (e) {
3540
+ loadErrors.push(e);
3541
+ }
3542
+ try {
3543
+ const binding = __require("@rolldown/binding-android-arm64");
3544
+ const bindingPackageVersion = __require("@rolldown/binding-android-arm64/package.json").version;
3545
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3546
+ return binding;
3547
+ } catch (e) {
3548
+ loadErrors.push(e);
3549
+ }
3550
+ } else if (process.arch === "arm") {
3551
+ try {
3552
+ return __require("./rolldown-binding.android-arm-eabi.node");
3553
+ } catch (e) {
3554
+ loadErrors.push(e);
3555
+ }
3556
+ try {
3557
+ const binding = __require("@rolldown/binding-android-arm-eabi");
3558
+ const bindingPackageVersion = __require("@rolldown/binding-android-arm-eabi/package.json").version;
3559
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3560
+ return binding;
3561
+ } catch (e) {
3562
+ loadErrors.push(e);
3563
+ }
3564
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on Android ${process.arch}`));
3565
+ else if (process.platform === "win32") if (process.arch === "x64") if (process.config?.variables?.shlib_suffix === "dll.a" || process.config?.variables?.node_target_type === "shared_library") {
3566
+ try {
3567
+ return __require("./rolldown-binding.win32-x64-gnu.node");
3568
+ } catch (e) {
3569
+ loadErrors.push(e);
3570
+ }
3571
+ try {
3572
+ const binding = __require("@rolldown/binding-win32-x64-gnu");
3573
+ const bindingPackageVersion = __require("@rolldown/binding-win32-x64-gnu/package.json").version;
3574
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3575
+ return binding;
3576
+ } catch (e) {
3577
+ loadErrors.push(e);
3578
+ }
3579
+ } else {
3580
+ try {
3581
+ return __require("./rolldown-binding.win32-x64-msvc.node");
3582
+ } catch (e) {
3583
+ loadErrors.push(e);
3584
+ }
3585
+ try {
3586
+ const binding = __require("@rolldown/binding-win32-x64-msvc");
3587
+ const bindingPackageVersion = __require("@rolldown/binding-win32-x64-msvc/package.json").version;
3588
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3589
+ return binding;
3590
+ } catch (e) {
3591
+ loadErrors.push(e);
3592
+ }
3593
+ }
3594
+ else if (process.arch === "ia32") {
3595
+ try {
3596
+ return __require("./rolldown-binding.win32-ia32-msvc.node");
3597
+ } catch (e) {
3598
+ loadErrors.push(e);
3599
+ }
3600
+ try {
3601
+ const binding = __require("@rolldown/binding-win32-ia32-msvc");
3602
+ const bindingPackageVersion = __require("@rolldown/binding-win32-ia32-msvc/package.json").version;
3603
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3604
+ return binding;
3605
+ } catch (e) {
3606
+ loadErrors.push(e);
3607
+ }
3608
+ } else if (process.arch === "arm64") {
3609
+ try {
3610
+ return __require("./rolldown-binding.win32-arm64-msvc.node");
3611
+ } catch (e) {
3612
+ loadErrors.push(e);
3613
+ }
3614
+ try {
3615
+ const binding = __require("@rolldown/binding-win32-arm64-msvc");
3616
+ const bindingPackageVersion = __require("@rolldown/binding-win32-arm64-msvc/package.json").version;
3617
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3618
+ return binding;
3619
+ } catch (e) {
3620
+ loadErrors.push(e);
3621
+ }
3622
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on Windows: ${process.arch}`));
3623
+ else if (process.platform === "darwin") {
3624
+ try {
3625
+ return __require("./rolldown-binding.darwin-universal.node");
3626
+ } catch (e) {
3627
+ loadErrors.push(e);
3628
+ }
3629
+ try {
3630
+ const binding = __require("@rolldown/binding-darwin-universal");
3631
+ const bindingPackageVersion = __require("@rolldown/binding-darwin-universal/package.json").version;
3632
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3633
+ return binding;
3634
+ } catch (e) {
3635
+ loadErrors.push(e);
3636
+ }
3637
+ if (process.arch === "x64") {
3638
+ try {
3639
+ return __require("./rolldown-binding.darwin-x64.node");
3640
+ } catch (e) {
3641
+ loadErrors.push(e);
3642
+ }
3643
+ try {
3644
+ const binding = __require("@rolldown/binding-darwin-x64");
3645
+ const bindingPackageVersion = __require("@rolldown/binding-darwin-x64/package.json").version;
3646
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3647
+ return binding;
3648
+ } catch (e) {
3649
+ loadErrors.push(e);
3650
+ }
3651
+ } else if (process.arch === "arm64") {
3652
+ try {
3653
+ return __require("./rolldown-binding.darwin-arm64.node");
3654
+ } catch (e) {
3655
+ loadErrors.push(e);
3656
+ }
3657
+ try {
3658
+ const binding = __require("@rolldown/binding-darwin-arm64");
3659
+ const bindingPackageVersion = __require("@rolldown/binding-darwin-arm64/package.json").version;
3660
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3661
+ return binding;
3662
+ } catch (e) {
3663
+ loadErrors.push(e);
3664
+ }
3665
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on macOS: ${process.arch}`));
3666
+ } else if (process.platform === "freebsd") if (process.arch === "x64") {
3667
+ try {
3668
+ return __require("./rolldown-binding.freebsd-x64.node");
3669
+ } catch (e) {
3670
+ loadErrors.push(e);
3671
+ }
3672
+ try {
3673
+ const binding = __require("@rolldown/binding-freebsd-x64");
3674
+ const bindingPackageVersion = __require("@rolldown/binding-freebsd-x64/package.json").version;
3675
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3676
+ return binding;
3677
+ } catch (e) {
3678
+ loadErrors.push(e);
3679
+ }
3680
+ } else if (process.arch === "arm64") {
3681
+ try {
3682
+ return __require("./rolldown-binding.freebsd-arm64.node");
3683
+ } catch (e) {
3684
+ loadErrors.push(e);
3685
+ }
3686
+ try {
3687
+ const binding = __require("@rolldown/binding-freebsd-arm64");
3688
+ const bindingPackageVersion = __require("@rolldown/binding-freebsd-arm64/package.json").version;
3689
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3690
+ return binding;
3691
+ } catch (e) {
3692
+ loadErrors.push(e);
3693
+ }
3694
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on FreeBSD: ${process.arch}`));
3695
+ else if (process.platform === "linux") if (process.arch === "x64") if (isMusl()) {
3696
+ try {
3697
+ return __require("./rolldown-binding.linux-x64-musl.node");
3698
+ } catch (e) {
3699
+ loadErrors.push(e);
3700
+ }
3701
+ try {
3702
+ const binding = __require("@rolldown/binding-linux-x64-musl");
3703
+ const bindingPackageVersion = __require("@rolldown/binding-linux-x64-musl/package.json").version;
3704
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3705
+ return binding;
3706
+ } catch (e) {
3707
+ loadErrors.push(e);
3708
+ }
3709
+ } else {
3710
+ try {
3711
+ return __require("../rolldown-binding.linux-x64-gnu.node");
3712
+ } catch (e) {
3713
+ loadErrors.push(e);
3714
+ }
3715
+ try {
3716
+ const binding = __require("@rolldown/binding-linux-x64-gnu");
3717
+ const bindingPackageVersion = __require("@rolldown/binding-linux-x64-gnu/package.json").version;
3718
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3719
+ return binding;
3720
+ } catch (e) {
3721
+ loadErrors.push(e);
3722
+ }
3723
+ }
3724
+ else if (process.arch === "arm64") if (isMusl()) {
3725
+ try {
3726
+ return __require("./rolldown-binding.linux-arm64-musl.node");
3727
+ } catch (e) {
3728
+ loadErrors.push(e);
3729
+ }
3730
+ try {
3731
+ const binding = __require("@rolldown/binding-linux-arm64-musl");
3732
+ const bindingPackageVersion = __require("@rolldown/binding-linux-arm64-musl/package.json").version;
3733
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3734
+ return binding;
3735
+ } catch (e) {
3736
+ loadErrors.push(e);
3737
+ }
3738
+ } else {
3739
+ try {
3740
+ return __require("./rolldown-binding.linux-arm64-gnu.node");
3741
+ } catch (e) {
3742
+ loadErrors.push(e);
3743
+ }
3744
+ try {
3745
+ const binding = __require("@rolldown/binding-linux-arm64-gnu");
3746
+ const bindingPackageVersion = __require("@rolldown/binding-linux-arm64-gnu/package.json").version;
3747
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3748
+ return binding;
3749
+ } catch (e) {
3750
+ loadErrors.push(e);
3751
+ }
3752
+ }
3753
+ else if (process.arch === "arm") if (isMusl()) {
3754
+ try {
3755
+ return __require("./rolldown-binding.linux-arm-musleabihf.node");
3756
+ } catch (e) {
3757
+ loadErrors.push(e);
3758
+ }
3759
+ try {
3760
+ const binding = __require("@rolldown/binding-linux-arm-musleabihf");
3761
+ const bindingPackageVersion = __require("@rolldown/binding-linux-arm-musleabihf/package.json").version;
3762
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3763
+ return binding;
3764
+ } catch (e) {
3765
+ loadErrors.push(e);
3766
+ }
3767
+ } else {
3768
+ try {
3769
+ return __require("./rolldown-binding.linux-arm-gnueabihf.node");
3770
+ } catch (e) {
3771
+ loadErrors.push(e);
3772
+ }
3773
+ try {
3774
+ const binding = __require("@rolldown/binding-linux-arm-gnueabihf");
3775
+ const bindingPackageVersion = __require("@rolldown/binding-linux-arm-gnueabihf/package.json").version;
3776
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3777
+ return binding;
3778
+ } catch (e) {
3779
+ loadErrors.push(e);
3780
+ }
3781
+ }
3782
+ else if (process.arch === "loong64") if (isMusl()) {
3783
+ try {
3784
+ return __require("./rolldown-binding.linux-loong64-musl.node");
3785
+ } catch (e) {
3786
+ loadErrors.push(e);
3787
+ }
3788
+ try {
3789
+ const binding = __require("@rolldown/binding-linux-loong64-musl");
3790
+ const bindingPackageVersion = __require("@rolldown/binding-linux-loong64-musl/package.json").version;
3791
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3792
+ return binding;
3793
+ } catch (e) {
3794
+ loadErrors.push(e);
3795
+ }
3796
+ } else {
3797
+ try {
3798
+ return __require("./rolldown-binding.linux-loong64-gnu.node");
3799
+ } catch (e) {
3800
+ loadErrors.push(e);
3801
+ }
3802
+ try {
3803
+ const binding = __require("@rolldown/binding-linux-loong64-gnu");
3804
+ const bindingPackageVersion = __require("@rolldown/binding-linux-loong64-gnu/package.json").version;
3805
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3806
+ return binding;
3807
+ } catch (e) {
3808
+ loadErrors.push(e);
3809
+ }
3810
+ }
3811
+ else if (process.arch === "riscv64") if (isMusl()) {
3812
+ try {
3813
+ return __require("./rolldown-binding.linux-riscv64-musl.node");
3814
+ } catch (e) {
3815
+ loadErrors.push(e);
3816
+ }
3817
+ try {
3818
+ const binding = __require("@rolldown/binding-linux-riscv64-musl");
3819
+ const bindingPackageVersion = __require("@rolldown/binding-linux-riscv64-musl/package.json").version;
3820
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3821
+ return binding;
3822
+ } catch (e) {
3823
+ loadErrors.push(e);
3824
+ }
3825
+ } else {
3826
+ try {
3827
+ return __require("./rolldown-binding.linux-riscv64-gnu.node");
3828
+ } catch (e) {
3829
+ loadErrors.push(e);
3830
+ }
3831
+ try {
3832
+ const binding = __require("@rolldown/binding-linux-riscv64-gnu");
3833
+ const bindingPackageVersion = __require("@rolldown/binding-linux-riscv64-gnu/package.json").version;
3834
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3835
+ return binding;
3836
+ } catch (e) {
3837
+ loadErrors.push(e);
3838
+ }
3839
+ }
3840
+ else if (process.arch === "ppc64") {
3841
+ try {
3842
+ return __require("./rolldown-binding.linux-ppc64-gnu.node");
3843
+ } catch (e) {
3844
+ loadErrors.push(e);
3845
+ }
3846
+ try {
3847
+ const binding = __require("@rolldown/binding-linux-ppc64-gnu");
3848
+ const bindingPackageVersion = __require("@rolldown/binding-linux-ppc64-gnu/package.json").version;
3849
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3850
+ return binding;
3851
+ } catch (e) {
3852
+ loadErrors.push(e);
3853
+ }
3854
+ } else if (process.arch === "s390x") {
3855
+ try {
3856
+ return __require("./rolldown-binding.linux-s390x-gnu.node");
3857
+ } catch (e) {
3858
+ loadErrors.push(e);
3859
+ }
3860
+ try {
3861
+ const binding = __require("@rolldown/binding-linux-s390x-gnu");
3862
+ const bindingPackageVersion = __require("@rolldown/binding-linux-s390x-gnu/package.json").version;
3863
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3864
+ return binding;
3865
+ } catch (e) {
3866
+ loadErrors.push(e);
3867
+ }
3868
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on Linux: ${process.arch}`));
3869
+ else if (process.platform === "openharmony") if (process.arch === "arm64") {
3870
+ try {
3871
+ return __require("./rolldown-binding.openharmony-arm64.node");
3872
+ } catch (e) {
3873
+ loadErrors.push(e);
3874
+ }
3875
+ try {
3876
+ const binding = __require("@rolldown/binding-openharmony-arm64");
3877
+ const bindingPackageVersion = __require("@rolldown/binding-openharmony-arm64/package.json").version;
3878
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3879
+ return binding;
3880
+ } catch (e) {
3881
+ loadErrors.push(e);
3882
+ }
3883
+ } else if (process.arch === "x64") {
3884
+ try {
3885
+ return __require("./rolldown-binding.openharmony-x64.node");
3886
+ } catch (e) {
3887
+ loadErrors.push(e);
3888
+ }
3889
+ try {
3890
+ const binding = __require("@rolldown/binding-openharmony-x64");
3891
+ const bindingPackageVersion = __require("@rolldown/binding-openharmony-x64/package.json").version;
3892
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3893
+ return binding;
3894
+ } catch (e) {
3895
+ loadErrors.push(e);
3896
+ }
3897
+ } else if (process.arch === "arm") {
3898
+ try {
3899
+ return __require("./rolldown-binding.openharmony-arm.node");
3900
+ } catch (e) {
3901
+ loadErrors.push(e);
3902
+ }
3903
+ try {
3904
+ const binding = __require("@rolldown/binding-openharmony-arm");
3905
+ const bindingPackageVersion = __require("@rolldown/binding-openharmony-arm/package.json").version;
3906
+ if (bindingPackageVersion !== "1.0.0" && process.env.NAPI_RS_ENFORCE_VERSION_CHECK && process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== "0") throw new Error(`Native binding package version mismatch, expected 1.0.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`);
3907
+ return binding;
3908
+ } catch (e) {
3909
+ loadErrors.push(e);
3910
+ }
3911
+ } else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported architecture on OpenHarmony: ${process.arch}`));
3912
+ else loadErrors.push(/* @__PURE__ */ new Error(`Unsupported OS: ${process.platform}, architecture: ${process.arch}`));
3913
+ }
3914
+ nativeBinding = requireNative();
3915
+ if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) {
3916
+ let wasiBinding = null;
3917
+ let wasiBindingError = null;
3918
+ try {
3919
+ wasiBinding = __require("../rolldown-binding.wasi.cjs");
3920
+ nativeBinding = wasiBinding;
3921
+ } catch (err) {
3922
+ if (process.env.NAPI_RS_FORCE_WASI) wasiBindingError = err;
3923
+ }
3924
+ if (!nativeBinding || process.env.NAPI_RS_FORCE_WASI) try {
3925
+ wasiBinding = __require("@rolldown/binding-wasm32-wasi");
3926
+ nativeBinding = wasiBinding;
3927
+ } catch (err) {
3928
+ if (process.env.NAPI_RS_FORCE_WASI) {
3929
+ if (!wasiBindingError) wasiBindingError = err;
3930
+ else wasiBindingError.cause = err;
3931
+ loadErrors.push(err);
3932
+ }
3933
+ }
3934
+ if (process.env.NAPI_RS_FORCE_WASI === "error" && !wasiBinding) {
3935
+ const error = /* @__PURE__ */ new Error("WASI binding not found and NAPI_RS_FORCE_WASI is set to error");
3936
+ error.cause = wasiBindingError;
3937
+ throw error;
3938
+ }
3939
+ }
3940
+ if (!nativeBinding && globalThis.process?.versions?.["webcontainer"]) try {
3941
+ nativeBinding = require_webcontainer_fallback();
3942
+ } catch (err) {
3943
+ loadErrors.push(err);
3944
+ }
3945
+ if (!nativeBinding) {
3946
+ if (loadErrors.length > 0) throw new Error("Cannot find native binding. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.", { cause: loadErrors.reduce((err, cur) => {
3947
+ cur.cause = err;
3948
+ return cur;
3949
+ }) });
3950
+ throw new Error(`Failed to load native binding`);
3951
+ }
3952
+ module.exports = nativeBinding;
3953
+ module.exports.minify = nativeBinding.minify;
3954
+ module.exports.minifySync = nativeBinding.minifySync;
3955
+ module.exports.Severity = nativeBinding.Severity;
3956
+ module.exports.ParseResult = nativeBinding.ParseResult;
3957
+ module.exports.ExportExportNameKind = nativeBinding.ExportExportNameKind;
3958
+ module.exports.ExportImportNameKind = nativeBinding.ExportImportNameKind;
3959
+ module.exports.ExportLocalNameKind = nativeBinding.ExportLocalNameKind;
3960
+ module.exports.ImportNameKind = nativeBinding.ImportNameKind;
3961
+ module.exports.parse = nativeBinding.parse;
3962
+ module.exports.parseSync = nativeBinding.parseSync;
3963
+ module.exports.rawTransferSupported = nativeBinding.rawTransferSupported;
3964
+ module.exports.ResolverFactory = nativeBinding.ResolverFactory;
3965
+ module.exports.EnforceExtension = nativeBinding.EnforceExtension;
3966
+ module.exports.ModuleType = nativeBinding.ModuleType;
3967
+ module.exports.sync = nativeBinding.sync;
3968
+ module.exports.HelperMode = nativeBinding.HelperMode;
3969
+ module.exports.isolatedDeclaration = nativeBinding.isolatedDeclaration;
3970
+ module.exports.isolatedDeclarationSync = nativeBinding.isolatedDeclarationSync;
3971
+ module.exports.moduleRunnerTransform = nativeBinding.moduleRunnerTransform;
3972
+ module.exports.moduleRunnerTransformSync = nativeBinding.moduleRunnerTransformSync;
3973
+ module.exports.transform = nativeBinding.transform;
3974
+ module.exports.transformSync = nativeBinding.transformSync;
3975
+ module.exports.BindingBundleEndEventData = nativeBinding.BindingBundleEndEventData;
3976
+ module.exports.BindingBundleErrorEventData = nativeBinding.BindingBundleErrorEventData;
3977
+ module.exports.BindingBundler = nativeBinding.BindingBundler;
3978
+ module.exports.BindingCallableBuiltinPlugin = nativeBinding.BindingCallableBuiltinPlugin;
3979
+ module.exports.BindingChunkingContext = nativeBinding.BindingChunkingContext;
3980
+ module.exports.BindingDecodedMap = nativeBinding.BindingDecodedMap;
3981
+ module.exports.BindingDevEngine = nativeBinding.BindingDevEngine;
3982
+ module.exports.BindingLoadPluginContext = nativeBinding.BindingLoadPluginContext;
3983
+ module.exports.BindingMagicString = nativeBinding.BindingMagicString;
3984
+ module.exports.BindingModuleInfo = nativeBinding.BindingModuleInfo;
3985
+ module.exports.BindingNormalizedOptions = nativeBinding.BindingNormalizedOptions;
3986
+ module.exports.BindingOutputAsset = nativeBinding.BindingOutputAsset;
3987
+ module.exports.BindingOutputChunk = nativeBinding.BindingOutputChunk;
3988
+ module.exports.BindingPluginContext = nativeBinding.BindingPluginContext;
3989
+ module.exports.BindingRenderedChunk = nativeBinding.BindingRenderedChunk;
3990
+ module.exports.BindingRenderedChunkMeta = nativeBinding.BindingRenderedChunkMeta;
3991
+ module.exports.BindingRenderedModule = nativeBinding.BindingRenderedModule;
3992
+ module.exports.BindingSourceMap = nativeBinding.BindingSourceMap;
3993
+ module.exports.BindingTransformPluginContext = nativeBinding.BindingTransformPluginContext;
3994
+ module.exports.BindingWatcher = nativeBinding.BindingWatcher;
3995
+ module.exports.BindingWatcherBundler = nativeBinding.BindingWatcherBundler;
3996
+ module.exports.BindingWatcherChangeData = nativeBinding.BindingWatcherChangeData;
3997
+ module.exports.BindingWatcherEvent = nativeBinding.BindingWatcherEvent;
3998
+ module.exports.ParallelJsPluginRegistry = nativeBinding.ParallelJsPluginRegistry;
3999
+ module.exports.ScheduledBuild = nativeBinding.ScheduledBuild;
4000
+ module.exports.TraceSubscriberGuard = nativeBinding.TraceSubscriberGuard;
4001
+ module.exports.TsconfigCache = nativeBinding.TsconfigCache;
4002
+ module.exports.BindingAttachDebugInfo = nativeBinding.BindingAttachDebugInfo;
4003
+ module.exports.BindingBuiltinPluginName = nativeBinding.BindingBuiltinPluginName;
4004
+ module.exports.BindingChunkModuleOrderBy = nativeBinding.BindingChunkModuleOrderBy;
4005
+ module.exports.BindingLogLevel = nativeBinding.BindingLogLevel;
4006
+ module.exports.BindingPluginOrder = nativeBinding.BindingPluginOrder;
4007
+ module.exports.BindingPropertyReadSideEffects = nativeBinding.BindingPropertyReadSideEffects;
4008
+ module.exports.BindingPropertyWriteSideEffects = nativeBinding.BindingPropertyWriteSideEffects;
4009
+ module.exports.BindingRebuildStrategy = nativeBinding.BindingRebuildStrategy;
4010
+ module.exports.collapseSourcemaps = nativeBinding.collapseSourcemaps;
4011
+ module.exports.enhancedTransform = nativeBinding.enhancedTransform;
4012
+ module.exports.enhancedTransformSync = nativeBinding.enhancedTransformSync;
4013
+ module.exports.FilterTokenKind = nativeBinding.FilterTokenKind;
4014
+ module.exports.initTraceSubscriber = nativeBinding.initTraceSubscriber;
4015
+ module.exports.registerPlugins = nativeBinding.registerPlugins;
4016
+ module.exports.resolveTsconfig = nativeBinding.resolveTsconfig;
4017
+ module.exports.shutdownAsyncRuntime = nativeBinding.shutdownAsyncRuntime;
4018
+ module.exports.startAsyncRuntime = nativeBinding.startAsyncRuntime;
4019
+ }));
4020
+ //#endregion
4021
+ //#region node_modules/.pnpm/rolldown@1.0.0/node_modules/rolldown/dist/shared/logs-D80CXhvg.mjs
4022
+ const PLUGIN_ERROR = "PLUGIN_ERROR";
4023
+ function logPluginError(error, plugin, { hook, id } = {}) {
4024
+ try {
4025
+ const code = error.code;
4026
+ if (!error.pluginCode && code != null && (typeof code !== "string" || !code.startsWith("PLUGIN_"))) error.pluginCode = code;
4027
+ error.code = PLUGIN_ERROR;
4028
+ error.plugin = plugin;
4029
+ if (hook) error.hook = hook;
4030
+ if (id) error.id = id;
4031
+ } catch (_) {} finally {
4032
+ return error;
4033
+ }
4034
+ }
4035
+ function error(base) {
4036
+ if (!(base instanceof Error)) {
4037
+ base = Object.assign(new Error(base.message), base);
4038
+ Object.defineProperty(base, "name", {
4039
+ value: "RolldownError",
4040
+ writable: true
4041
+ });
4042
+ }
4043
+ throw base;
4044
+ }
4045
+ //#endregion
4046
+ //#region node_modules/.pnpm/rolldown@1.0.0/node_modules/rolldown/dist/shared/normalize-string-or-regex-dAjLOSbp.mjs
4047
+ var import_binding = /* @__PURE__ */ __toESM(require_binding(), 1);
4048
+ var BuiltinPlugin = class {
4049
+ name;
4050
+ _options;
4051
+ /** Vite-specific option to control plugin ordering */
4052
+ enforce;
4053
+ constructor(name, _options) {
4054
+ this.name = name;
4055
+ this._options = _options;
4056
+ }
4057
+ };
4058
+ function makeBuiltinPluginCallable(plugin) {
4059
+ let callablePlugin = new import_binding.BindingCallableBuiltinPlugin(bindingifyBuiltInPlugin(plugin));
4060
+ const wrappedPlugin = plugin;
4061
+ for (const key in callablePlugin) {
4062
+ const wrappedHook = async function(...args) {
4063
+ try {
4064
+ return await callablePlugin[key](...args);
4065
+ } catch (e) {
4066
+ if (e instanceof Error && !e.stack?.includes("at ")) Error.captureStackTrace(e, wrappedPlugin[key]);
4067
+ return error(logPluginError(e, plugin.name, {
4068
+ hook: key,
4069
+ id: key === "transform" ? args[2] : void 0
4070
+ }));
4071
+ }
4072
+ };
4073
+ const order = callablePlugin.getOrder(key);
4074
+ if (order == void 0) wrappedPlugin[key] = wrappedHook;
4075
+ else wrappedPlugin[key] = {
4076
+ handler: wrappedHook,
4077
+ order
4078
+ };
4079
+ }
4080
+ return wrappedPlugin;
4081
+ }
4082
+ function bindingifyBuiltInPlugin(plugin) {
4083
+ return {
4084
+ __name: plugin.name,
4085
+ options: plugin._options
4086
+ };
4087
+ }
4088
+ //#endregion
4089
+ //#region node_modules/.pnpm/rolldown@1.0.0/node_modules/rolldown/dist/plugins-index.mjs
4090
+ /**
4091
+ * Replaces targeted strings in files while bundling.
4092
+ *
4093
+ * @example
4094
+ * **Basic usage**
4095
+ * ```js
4096
+ * replacePlugin({
4097
+ * 'process.env.NODE_ENV': JSON.stringify('production'),
4098
+ * __buildVersion: 15
4099
+ * })
4100
+ * ```
4101
+ * @example
4102
+ * **With options**
4103
+ * ```js
4104
+ * replacePlugin({
4105
+ * 'process.env.NODE_ENV': JSON.stringify('production'),
4106
+ * __buildVersion: 15
4107
+ * }, {
4108
+ * preventAssignment: false,
4109
+ * })
4110
+ * ```
4111
+ *
4112
+ * @see https://rolldown.rs/builtin-plugins/replace
4113
+ * @category Builtin Plugins
4114
+ */
4115
+ function replacePlugin(values = {}, options = {}) {
4116
+ Object.keys(values).forEach((key) => {
4117
+ const value = values[key];
4118
+ if (typeof value !== "string") values[key] = String(value);
4119
+ });
4120
+ return makeBuiltinPluginCallable(new BuiltinPlugin("builtin:replace", {
4121
+ ...options,
4122
+ values
4123
+ }));
4124
+ }
4125
+ //#endregion
4126
+ //#region src/cli.ts
4127
+ const NODE_ENV = process$1.env.NODE_ENV || "production";
4128
+ let pagePaths = null;
4129
+ const pageComponentCache = /* @__PURE__ */ new Map();
4130
+ /**
4131
+ * 清空所有缓存(在 app.json 变更时调用)
4132
+ */
4133
+ function clearAllCaches() {
4134
+ pagePaths = null;
4135
+ pageComponentCache.clear();
4136
+ pathCache.clear();
4137
+ }
4138
+ /**
4139
+ * 读取 app.json 并生成页面路径列表
4140
+ * 页面路径格式: pages/index/Index 或 subHome/pages/home/HomeIndex
4141
+ */
4142
+ async function loadPagePaths() {
4143
+ if (pagePaths) return pagePaths;
4144
+ const appJsonPath = path.join(sourceDir, "app.json");
4145
+ pagePaths = /* @__PURE__ */ new Set();
4146
+ try {
4147
+ const appJson = await fs$1.readJson(appJsonPath);
4148
+ if (appJson.pages) for (const page of appJson.pages) pagePaths.add(page);
4149
+ if (appJson.subPackages) for (const pkg of appJson.subPackages) {
4150
+ const root = pkg.root;
4151
+ for (const page of pkg.pages) pagePaths.add(`${root}/${page}`);
4152
+ }
4153
+ console.log(bold(green(`加载到 ${pagePaths.size} 个页面路径`)));
4154
+ } catch (error) {
4155
+ console.warn("读取 app.json 失败:", getErrorMessage(error));
4156
+ }
4157
+ return pagePaths;
4158
+ }
4159
+ /**
4160
+ * 判断文件路径是否为页面组件
4161
+ * @param filePath 文件路径,如 src/pages/index/Index.vue
4162
+ * @returns 是否为页面组件
4163
+ */
4164
+ function isPageComponent(filePath) {
4165
+ const cached = pageComponentCache.get(filePath);
4166
+ if (typeof cached === "boolean") return cached;
4167
+ if (!pagePaths || pagePaths.size === 0) {
4168
+ pageComponentCache.set(filePath, false);
4169
+ return false;
4170
+ }
4171
+ const normalizedPath = path.relative(sourceDir, filePath).replace(/\.vue$/, "");
4172
+ const isPage = pagePaths.has(normalizedPath);
4173
+ pageComponentCache.set(filePath, isPage);
4174
+ return isPage;
4175
+ }
4176
+ const sourceDir = userConfig.sourceDir;
4177
+ const copyOnlyPatterns = userConfig.copyOnly ?? [];
4178
+ function isCopyOnly(filePath) {
4179
+ if (filePath.endsWith(".min.js")) return true;
4180
+ return copyOnlyPatterns.some((pattern) => filePath.includes(pattern));
4181
+ }
4182
+ const aliasPath = userConfig.alias?.["@"] || `./${sourceDir}`;
4183
+ if (config.plugins) {
4184
+ const moduleResolverPlugin = config.plugins.find((plugin) => Array.isArray(plugin) && plugin[0] === "module-resolver");
4185
+ if (moduleResolverPlugin && Array.isArray(moduleResolverPlugin) && moduleResolverPlugin[1] && typeof moduleResolverPlugin[1] === "object") {
4186
+ const options = moduleResolverPlugin[1];
4187
+ if (options.alias) options.alias["@"] = aliasPath;
4188
+ }
4189
+ }
4190
+ let topLevelJobs = [];
4191
+ let bundleJobs = [];
4192
+ const startTime = Date.now();
4193
+ let __PROD__ = false;
4194
+ let independentPackages = [];
4195
+ const IGNORED_FILES = (file, stats) => {
4196
+ if (!stats?.isFile()) return false;
4197
+ return file.endsWith(".gitkeep") || file.endsWith(".DS_Store") || file.endsWith(".d.ts") || /[\\/]node_modules[\\/]/.test(file) || /[\\/]\.git[\\/]/.test(file);
4198
+ };
4199
+ const CONCURRENT_LIMIT = Math.max(4, os.cpus().length * 2 - 1);
4200
+ async function batchProcess(items, processor, concurrency = CONCURRENT_LIMIT) {
4201
+ if (items.length === 0) return;
4202
+ let index = 0;
4203
+ let running = 0;
4204
+ let completed = 0;
4205
+ const total = items.length;
4206
+ let hasError = false;
4207
+ return new Promise((resolve, reject) => {
4208
+ const runNext = async () => {
4209
+ while (index < total && running < concurrency && !hasError) {
4210
+ const currentIndex = index++;
4211
+ running++;
4212
+ processor(items[currentIndex]).catch((error) => {
4213
+ console.error(`处理失败 [${items[currentIndex]}]:`, error);
4214
+ hasError = true;
4215
+ }).finally(() => {
4216
+ running--;
4217
+ completed++;
4218
+ if (completed === total) if (hasError) reject(/* @__PURE__ */ new Error("部分任务处理失败"));
4219
+ else resolve();
4220
+ else if (!hasError) runNext();
4221
+ });
4222
+ }
4223
+ };
4224
+ runNext();
4225
+ });
4226
+ }
4227
+ const pathCache = /* @__PURE__ */ new Map();
4228
+ function getOutputPath(inputPath) {
4229
+ let cached = pathCache.get(inputPath);
4230
+ if (!cached) {
4231
+ cached = inputPath.startsWith(sourceDir) ? OUTPUT_DIR + inputPath.slice(sourceDir.length) : inputPath;
4232
+ pathCache.set(inputPath, cached);
4233
+ }
4234
+ return cached;
4235
+ }
4236
+ function clearPathCache() {
4237
+ pathCache.clear();
4238
+ }
4239
+ async function findIndependentPackages() {
4240
+ const appJson = await fs$1.readJson(path.resolve(sourceDir, "app.json"));
4241
+ if (appJson.subpackages) independentPackages = appJson.subpackages.filter(({ independent }) => independent).map(({ root }) => root);
4242
+ }
4243
+ const builtLibraries = [];
4244
+ const bundledModules = /* @__PURE__ */ new Map();
4245
+ async function bundleModule(module, pkg) {
4246
+ const bundled = bundledModules.get(pkg);
4247
+ if (bundled?.has(module) || builtLibraries.some((library) => module.startsWith(library))) return false;
4248
+ if (bundled) bundled.add(module);
4249
+ else bundledModules.set(pkg, new Set([module]));
4250
+ const pkInfo = await getPackageInfo(module);
4251
+ if (pkInfo) {
4252
+ const { packageJson: { peerDependencies } } = pkInfo;
4253
+ if (await fs$1.pathExists(path.resolve(pkg.replace(sourceDir, OUTPUT_DIR), "miniprogram_npm", module))) return true;
4254
+ await (await rolldown({
4255
+ input: module,
4256
+ external: peerDependencies ? Object.keys(peerDependencies) : void 0,
4257
+ plugins: [replacePlugin({ "process.env.NODE_ENV": JSON.stringify(NODE_ENV) }, { preventAssignment: true })],
4258
+ treeshake: true
4259
+ })).write({
4260
+ file: `${pkg.replace(sourceDir, OUTPUT_DIR)}/miniprogram_npm/${module}/index.js`,
4261
+ format: "cjs",
4262
+ exports: "named",
4263
+ minify: __PROD__
4264
+ });
4265
+ return true;
4266
+ } else {
4267
+ console.warn(`未找到 ${module} 的依赖信息`);
4268
+ return false;
4269
+ }
4270
+ }
4271
+ function traverseAST(ast, pkg, babelOnly = false) {
4272
+ traverse(ast, { CallExpression({ node }) {
4273
+ if (!t.isIdentifier(node.callee) || node.callee.name !== "require" || !t.isStringLiteral(node.arguments[0]) || node.arguments[0].value.startsWith(".") || babelOnly && !node.arguments[0].value.startsWith("@babel/runtime")) return;
4274
+ const module = node.arguments[0].value;
4275
+ let promise = bundleModule(module, pkg);
4276
+ if (babelOnly) promise = promise.then((valid) => {
4277
+ if (!valid) return;
4278
+ return Promise.all(independentPackages.map((item) => {
4279
+ const bundled = bundledModules.get(item);
4280
+ if (bundled) bundled.add(module);
4281
+ else bundledModules.set(item, new Set([module]));
4282
+ return fs$1.copy(path.join(OUTPUT_DIR, "miniprogram_npm", module), path.join(OUTPUT_DIR, item, "miniprogram_npm", module));
4283
+ }));
4284
+ });
4285
+ bundleJobs?.push(promise);
4286
+ } });
4287
+ }
4288
+ async function buildComponentLibrary(name) {
4289
+ const pkInfo = await getPackageInfo(name);
4290
+ if (pkInfo) {
4291
+ const { rootPath, packageJson: { miniprogram } } = pkInfo;
4292
+ let source = "";
4293
+ if (miniprogram) source = path.join(rootPath, miniprogram);
4294
+ else try {
4295
+ const dist = path.join(rootPath, "miniprogram_dist");
4296
+ if ((await fs$1.stat(dist)).isDirectory()) source = dist;
4297
+ } catch {}
4298
+ if (!source) return;
4299
+ const destination = path.resolve(OUTPUT_DIR, "miniprogram_npm", name);
4300
+ builtLibraries.push(name);
4301
+ if (await fs$1.pathExists(destination)) return;
4302
+ await fs$1.copy(source, destination);
4303
+ const processJsFiles = async (dir) => {
4304
+ const entries = await fs$1.readdir(dir, { withFileTypes: true });
4305
+ const jsFiles = [];
4306
+ for (const entry of entries) {
4307
+ const fullPath = path.join(dir, entry.name);
4308
+ if (entry.isDirectory()) await processJsFiles(fullPath);
4309
+ else if (entry.isFile() && entry.name.endsWith(".js")) jsFiles.push(fullPath);
4310
+ }
4311
+ await batchProcess(jsFiles, async (filePath) => {
4312
+ try {
4313
+ const result = await transformFileAsync(filePath, {
4314
+ ast: true,
4315
+ ...config
4316
+ });
4317
+ if (result) {
4318
+ traverseAST(result.ast, sourceDir, true);
4319
+ const code = __PROD__ ? (await minify(result.code, {
4320
+ ecma: 2016,
4321
+ toplevel: true
4322
+ })).code : result.code;
4323
+ await fs$1.writeFile(filePath, code);
4324
+ }
4325
+ } catch (error) {
4326
+ console.error(`处理 ${filePath} 失败:`, getErrorMessage(error));
4327
+ }
4328
+ }, Math.min(10, CONCURRENT_LIMIT));
4329
+ };
4330
+ await processJsFiles(destination);
4331
+ if (independentPackages.length > 0) await Promise.all(independentPackages.map(async (item) => {
4332
+ const independentDestination = path.join(OUTPUT_DIR, item, "miniprogram_npm", name);
4333
+ if (!await fs$1.pathExists(independentDestination)) return fs$1.copy(destination, independentDestination);
4334
+ }));
4335
+ } else console.warn(`未找到 ${name} 的依赖信息`);
4336
+ }
4337
+ async function scanDependencies() {
4338
+ try {
4339
+ const { dependencies } = await fs$1.readJson("package.json");
4340
+ if (dependencies) {
4341
+ const depNames = Object.keys(dependencies);
4342
+ const depConcurrency = Math.min(5, Math.max(2, Math.ceil(os.cpus().length / 2)));
4343
+ console.log(bold(green(`扫描到 ${depNames.length} 个依赖,开始并行处理(并发=${depConcurrency})...`)));
4344
+ const startDepTime = Date.now();
4345
+ await batchProcess(depNames, async (name) => {
4346
+ await buildComponentLibrary(name);
4347
+ }, depConcurrency);
4348
+ console.log(bold(green(`依赖处理完成,耗时:${Date.now() - startDepTime}ms`)));
4349
+ }
4350
+ } catch (error) {
4351
+ console.warn("读取 package.json 失败:", getErrorMessage(error));
4352
+ }
4353
+ }
4354
+ const normalizedPkgPaths = /* @__PURE__ */ new Map();
4355
+ async function dealScriptCode(filePath, result) {
4356
+ const ast = result.ast;
4357
+ let code = result.code;
4358
+ const pkg = independentPackages.find((item) => {
4359
+ let normalized = normalizedPkgPaths.get(item);
4360
+ if (!normalized) {
4361
+ normalized = path.normalize(`${sourceDir}/${item}`);
4362
+ normalizedPkgPaths.set(item, normalized);
4363
+ }
4364
+ return filePath.startsWith(normalized);
4365
+ });
4366
+ traverseAST(ast, pkg ? path.join(sourceDir, pkg) : sourceDir);
4367
+ if (__PROD__) code = (await minify(code, {
4368
+ ecma: 2016,
4369
+ toplevel: true
4370
+ })).code;
4371
+ return code;
4372
+ }
4373
+ async function processScript(filePath) {
4374
+ try {
4375
+ const result = await transformFileAsync(path.resolve(filePath), {
4376
+ ast: true,
4377
+ ...config
4378
+ });
4379
+ if (result) {
4380
+ const code = await dealScriptCode(filePath, result);
4381
+ const destination = path.join(getOutputPath(filePath).replace(/\.ts$/, ".js"));
4382
+ await fs$1.ensureDir(path.dirname(destination));
4383
+ await fs$1.writeFile(destination, code);
4384
+ }
4385
+ } catch (error) {
4386
+ handleCompileError("", error, filePath);
4387
+ if (__PROD__) throw error;
4388
+ }
4389
+ }
4390
+ const cb = async (filePath, callbacks) => {
4391
+ if (filePath.endsWith(".vue")) {
4392
+ const t = performance.now();
4393
+ try {
4394
+ await transformVueToMiniProgram(filePath, OUTPUT_DIR, isPageComponent(filePath), async (generatedCode) => {
4395
+ try {
4396
+ const result = await transformAsync(generatedCode, {
4397
+ filename: filePath.replace(".vue", ".js"),
4398
+ ...config
4399
+ });
4400
+ if (result) return dealScriptCode(filePath, result);
4401
+ return `Failed to transformAsync ${filePath}`;
4402
+ } catch (error) {
4403
+ handleCompileError("", error, filePath);
4404
+ return `console.error('Failed to compile ${filePath}: ${error.message?.replace(/'/g, "\\'")}');`;
4405
+ }
4406
+ });
4407
+ } catch (error) {
4408
+ if (__PROD__) throw error;
4409
+ return;
4410
+ } finally {
4411
+ callbacks?.vueCb?.(performance.now() - t);
4412
+ }
4413
+ return;
4414
+ }
4415
+ if (filePath.endsWith(".d.ts")) return;
4416
+ if (isCopyOnly(filePath)) {
4417
+ const t = performance.now();
4418
+ const destinationPath = getOutputPath(filePath);
4419
+ await fs$1.ensureDir(path.dirname(destinationPath));
4420
+ await fs$1.copy(filePath, destinationPath);
4421
+ callbacks?.othersCb?.(performance.now() - t);
4422
+ return;
4423
+ }
4424
+ if (filePath.endsWith(".ts") || filePath.endsWith(".js")) {
4425
+ const t = performance.now();
4426
+ await processScript(filePath);
4427
+ callbacks?.jsCb?.(performance.now() - t);
4428
+ return;
4429
+ }
4430
+ const t = performance.now();
4431
+ const destinationPath = path.join(getOutputPath(filePath));
4432
+ await fs$1.copy(filePath, path.normalize(destinationPath));
4433
+ callbacks?.othersCb?.(performance.now() - t);
4434
+ };
4435
+ async function dev() {
4436
+ __PROD__ = false;
4437
+ const t0 = Date.now();
4438
+ copyPolyfillFiles().then(() => {
4439
+ console.log(bold(green(`[timing] copyPolyfillFiles: ${Date.now() - t0}ms`)));
4440
+ return copyProjectConfigFile();
4441
+ }).then(() => {
4442
+ console.log(bold(green(`[timing] copyProjectConfigFile: ${Date.now() - t0}ms`)));
4443
+ return loadPagePaths();
4444
+ }).then(() => {
4445
+ console.log(bold(green(`[timing] loadPagePaths: ${Date.now() - t0}ms`)));
4446
+ return findIndependentPackages();
4447
+ }).then(() => {
4448
+ console.log(bold(green(`[timing] findIndependentPackages: ${Date.now() - t0}ms`)));
4449
+ return scanDependencies();
4450
+ }).then(() => {
4451
+ console.log(bold(green(`[timing] scanDependencies: ${Date.now() - t0}ms`)));
4452
+ const processingFiles = /* @__PURE__ */ new Set();
4453
+ const pendingFiles = /* @__PURE__ */ new Set();
4454
+ const initialFiles = [];
4455
+ let isInitialScan = true;
4456
+ chokidar.watch([sourceDir], {
4457
+ awaitWriteFinish: {
4458
+ stabilityThreshold: 100,
4459
+ pollInterval: 50
4460
+ },
4461
+ ignored: IGNORED_FILES,
4462
+ usePolling: false,
4463
+ interval: 100
4464
+ }).on("add", (filePath) => {
4465
+ if (isInitialScan) initialFiles.push(filePath);
4466
+ else {
4467
+ const promise = cb(filePath);
4468
+ topLevelJobs?.push(promise);
4469
+ }
4470
+ }).on("addDir", (dirPath) => {
4471
+ const outputDir = getOutputPath(dirPath);
4472
+ const promise = fs$1.ensureDir(outputDir);
4473
+ topLevelJobs?.push(promise);
4474
+ }).on("unlink", async (filePath) => {
4475
+ const outputPath = getOutputPath(filePath);
4476
+ const basePath = outputPath.replace(/\.vue$/, "");
4477
+ const filesToDelete = filePath.endsWith(".vue") ? [
4478
+ `${basePath}.js`,
4479
+ `${basePath}.wxml`,
4480
+ `${basePath}.wxss`,
4481
+ `${basePath}.json`
4482
+ ] : [path.join(outputPath)];
4483
+ try {
4484
+ await Promise.all(filesToDelete.map((f) => fs$1.remove(f)));
4485
+ pathCache.delete(filePath);
4486
+ } catch (error) {
4487
+ console.warn(`删除目标文件失败:${filesToDelete.join(", ")}`, getErrorMessage(error));
4488
+ }
4489
+ }).on("unlinkDir", async (dirPath) => {
4490
+ const outputDir = getOutputPath(dirPath);
4491
+ try {
4492
+ await fs$1.remove(outputDir);
4493
+ } catch (error) {
4494
+ console.warn(`删除目标目录失败:${outputDir}`, getErrorMessage(error));
4495
+ }
4496
+ }).on("change", async (filePath) => {
4497
+ if (filePath.endsWith("app.json")) {
4498
+ console.log(bold(green("检测到 app.json 变更,清空缓存并重新加载页面路径...")));
4499
+ clearAllCaches();
4500
+ await loadPagePaths();
4501
+ }
4502
+ if (processingFiles.has(filePath)) {
4503
+ pendingFiles.add(filePath);
4504
+ return;
4505
+ }
4506
+ const runCompile = async (initialPath) => {
4507
+ let targetPath = initialPath;
4508
+ while (targetPath) {
4509
+ processingFiles.add(targetPath);
4510
+ const date = Date.now();
4511
+ console.log(bold(green(`文件已修改:${targetPath}`)));
4512
+ try {
4513
+ await cb(targetPath);
4514
+ console.log(bold(green(`文件已处理完毕,耗时:${Date.now() - date}ms`)));
4515
+ } finally {
4516
+ processingFiles.delete(targetPath);
4517
+ const nextFile = Array.from(pendingFiles)[0];
4518
+ if (nextFile) {
4519
+ pendingFiles.delete(nextFile);
4520
+ targetPath = nextFile;
4521
+ } else targetPath = null;
4522
+ }
4523
+ }
4524
+ };
4525
+ await runCompile(filePath);
4526
+ }).on("ready", async () => {
4527
+ isInitialScan = false;
4528
+ console.log(bold(green(`[timing] chokidar ready(文件扫描完成): ${Date.now() - t0}ms,共 ${initialFiles.length} 个文件`)));
4529
+ const vueFiles = initialFiles.filter((f) => f.endsWith(".vue"));
4530
+ const tsFiles = initialFiles.filter((f) => f.endsWith(".ts") || f.endsWith(".js"));
4531
+ const otherFiles = initialFiles.filter((f) => !f.endsWith(".vue") && !f.endsWith(".ts") && !f.endsWith(".js"));
4532
+ console.log(bold(green(`[timing] 文件分布:vue=${vueFiles.length}, ts/js=${tsFiles.length}, 其他=${otherFiles.length}`)));
4533
+ let vueTime = 0, tsTime = 0, otherTime = 0;
4534
+ const fileProcessor = async (filePath) => {
4535
+ await cb(filePath, {
4536
+ vueCb: (elapsed) => {
4537
+ vueTime += elapsed;
4538
+ },
4539
+ jsCb: (elapsed) => {
4540
+ tsTime += elapsed;
4541
+ },
4542
+ othersCb: (elapsed) => {
4543
+ otherTime += elapsed;
4544
+ }
4545
+ });
4546
+ };
4547
+ if (initialFiles.length > 0) {
4548
+ console.log(bold(green(`开始并行处理 ${initialFiles.length} 个文件(并发=${CONCURRENT_LIMIT})...`)));
4549
+ const processStartTime = Date.now();
4550
+ await batchProcess(initialFiles, fileProcessor, CONCURRENT_LIMIT);
4551
+ console.log(bold(green(`[timing] 并行处理完成:${Date.now() - processStartTime}ms(总耗时 ${Date.now() - t0}ms)`)));
4552
+ console.log(bold(green(`[timing] 耗时分布:vue=${vueTime}ms, ts/js=${tsTime}ms, 其他=${otherTime}ms`)));
4553
+ }
4554
+ await Promise.all(bundleJobs);
4555
+ console.log(bold(green(`启动完成,耗时:${Date.now() - startTime}ms`)));
4556
+ console.log(bold(green("监听文件变化中...")));
4557
+ topLevelJobs = null;
4558
+ bundleJobs = null;
4559
+ });
4560
+ });
4561
+ }
4562
+ async function prod(options) {
4563
+ __PROD__ = true;
4564
+ return new Promise((resolve, reject) => {
4565
+ fs$1.remove(OUTPUT_DIR).then(() => copyPolyfillFiles()).then(() => copyProjectConfigFile()).then(() => loadPagePaths()).then(() => findIndependentPackages()).then(() => scanDependencies()).then(() => {
4566
+ const initialFiles = [];
4567
+ let isInitialScan = true;
4568
+ const watcher = chokidar.watch([sourceDir], { ignored: IGNORED_FILES });
4569
+ watcher.on("add", (filePath) => {
4570
+ if (isInitialScan) initialFiles.push(filePath);
4571
+ else {
4572
+ const promise = cb(filePath);
4573
+ topLevelJobs.push(promise);
4574
+ }
4575
+ });
4576
+ watcher.on("ready", async () => {
4577
+ isInitialScan = false;
4578
+ const fileProcessor = async (filePath) => {
4579
+ await cb(filePath);
4580
+ };
4581
+ if (initialFiles.length > 0) {
4582
+ console.log(bold(green(`开始并行处理 ${initialFiles.length} 个文件...`)));
4583
+ const processStartTime = Date.now();
4584
+ await batchProcess(initialFiles, fileProcessor, CONCURRENT_LIMIT);
4585
+ console.log(bold(green(`并行处理完成,耗时:${Date.now() - processStartTime}ms`)));
4586
+ }
4587
+ const promise = watcher.close();
4588
+ topLevelJobs.push(promise);
4589
+ await Promise.all(topLevelJobs);
4590
+ await Promise.all(bundleJobs);
4591
+ topLevelJobs = null;
4592
+ bundleJobs = null;
4593
+ clearPathCache();
4594
+ normalizedPkgPaths.clear();
4595
+ if (options.upload) {
4596
+ const { default: ci } = await import("miniprogram-ci");
4597
+ const project = new ci.Project({
4598
+ appid: userConfig.wx.appid,
4599
+ type: "miniProgram",
4600
+ projectPath: OUTPUT_DIR,
4601
+ privateKeyPath: userConfig.wx.privateKeyPath,
4602
+ ignores: []
4603
+ });
4604
+ console.log(bold(green("上传中...")));
4605
+ const uploadResult = await ci.upload({
4606
+ project,
4607
+ version: userConfig.wx.version,
4608
+ desc: userConfig.wx.description,
4609
+ setting: { useProjectConfig: true },
4610
+ onProgressUpdate: void 0
4611
+ });
4612
+ console.log(bold(green(`上传结果:`)), uploadResult, "当前编译环境:", NODE_ENV);
4613
+ }
4614
+ resolve();
4615
+ });
4616
+ }).catch(reject);
4617
+ });
4618
+ }
4619
+ //#endregion
4620
+ export { dev, prod };