@unmagic/vms 0.0.5 → 0.1.0

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