@wevu/compiler 6.7.3 → 6.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.mts +20 -17
  2. package/dist/index.mjs +1741 -1759
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1,22 +1,21 @@
1
1
  import { createRequire } from "node:module";
2
- import * as t from "@babel/types";
3
2
  import { removeExtensionDeep } from "@weapp-core/shared";
4
3
  import path from "pathe";
5
- import { parse as parse$2 } from "@babel/parser";
6
4
  import { NodeTypes, baseParse } from "@vue/compiler-core";
7
- import { LRUCache } from "lru-cache";
8
5
  import { createHash } from "node:crypto";
6
+ import * as t from "@babel/types";
9
7
  import fs from "fs-extra";
10
8
  import MagicString from "magic-string";
11
9
  import { recursive } from "merge";
12
10
  import { bundleRequire } from "rolldown-require";
11
+ import { parse as parse$2 } from "@babel/parser";
13
12
  import fs$1 from "node:fs";
14
13
  import os from "node:os";
15
14
  import process from "node:process";
15
+ import { LRUCache } from "lru-cache";
16
16
  import { compileScript, parse } from "vue/compiler-sfc";
17
17
  import { fileURLToPath } from "node:url";
18
18
  import { parse as parse$1 } from "comment-json";
19
-
20
19
  //#region src/auto-import-components/builtin.auto.ts
21
20
  const components = [
22
21
  "wxs",
@@ -108,7 +107,6 @@ const components = [
108
107
  "navigation-bar",
109
108
  "page-meta"
110
109
  ];
111
-
112
110
  //#endregion
113
111
  //#region src/auto-import-components/builtin.ts
114
112
  /**
@@ -121,7 +119,6 @@ const builtinComponentsSet = new Set(components);
121
119
  function isBuiltinComponent(tag) {
122
120
  return builtinComponentsSet.has(tag);
123
121
  }
124
-
125
122
  //#endregion
126
123
  //#region src/constants.ts
127
124
  const WE_VU_PAGE_HOOK_TO_FEATURE = {
@@ -150,59 +147,6 @@ const WE_VU_RUNTIME_APIS = {
150
147
  defineComponent: "defineComponent",
151
148
  setWevuDefaults: "setWevuDefaults"
152
149
  };
153
-
154
- //#endregion
155
- //#region src/utils/babel.ts
156
- const BABEL_TS_MODULE_PLUGINS = [
157
- "typescript",
158
- "decorators-legacy",
159
- "classProperties",
160
- "classPrivateProperties",
161
- "classPrivateMethods",
162
- "jsx"
163
- ];
164
- const BABEL_TS_MODULE_PARSER_OPTIONS = {
165
- sourceType: "module",
166
- plugins: BABEL_TS_MODULE_PLUGINS
167
- };
168
- const nodeRequire = createRequire(import.meta.url);
169
- let cachedTraverse;
170
- let cachedGenerate;
171
- function requireCallableDefault(id) {
172
- const mod = nodeRequire(id);
173
- if (typeof mod === "function") return mod;
174
- if (mod && (typeof mod === "object" || typeof mod === "function") && "default" in mod) {
175
- const candidate = mod.default;
176
- if (typeof candidate === "function") return candidate;
177
- }
178
- throw new TypeError(`Invalid module shape for ${id}`);
179
- }
180
- function getTraverse() {
181
- if (!cachedTraverse) cachedTraverse = requireCallableDefault("@babel/traverse");
182
- return cachedTraverse;
183
- }
184
- function getGenerate() {
185
- if (!cachedGenerate) cachedGenerate = requireCallableDefault("@babel/generator");
186
- return cachedGenerate;
187
- }
188
- const traverse = (...args) => {
189
- return getTraverse()(...args);
190
- };
191
- const generate = (...args) => {
192
- return getGenerate()(...args);
193
- };
194
- function parseJsLike(source) {
195
- return parse$2(source, {
196
- sourceType: "module",
197
- plugins: [
198
- ...BABEL_TS_MODULE_PLUGINS,
199
- "dynamicImport",
200
- "optionalChaining",
201
- "nullishCoalescingOperator"
202
- ]
203
- });
204
- }
205
-
206
150
  //#endregion
207
151
  //#region src/utils/vueTemplateTags.ts
208
152
  const RESERVED_VUE_COMPONENT_TAGS = new Set([
@@ -255,578 +199,170 @@ function collectVueTemplateTags(template, options) {
255
199
  }
256
200
  return tags;
257
201
  }
258
-
259
202
  //#endregion
260
- //#region src/plugins/vue/compiler/template/expression/parse.ts
261
- const babelExpressionCache = new LRUCache({ max: 1024 });
262
- const inlineHandlerCache = new LRUCache({ max: 1024 });
263
- const BABEL_GENERATE_MINI_PROGRAM_OPTIONS = {
264
- compact: true,
265
- jsescOption: {
266
- quotes: "single",
267
- minimal: true
203
+ //#region src/plugins/vue/transform/jsonMacros/analyze.ts
204
+ function collectPatternNames(pattern, out) {
205
+ if (!pattern) return;
206
+ if (t.isIdentifier(pattern)) {
207
+ out.add(pattern.name);
208
+ return;
268
209
  }
269
- };
270
- function generateExpression(node) {
271
- const { code } = generate(node, BABEL_GENERATE_MINI_PROGRAM_OPTIONS);
272
- return code;
210
+ if (t.isRestElement(pattern)) {
211
+ collectPatternNames(pattern.argument, out);
212
+ return;
213
+ }
214
+ if (t.isAssignmentPattern(pattern)) {
215
+ collectPatternNames(pattern.left, out);
216
+ return;
217
+ }
218
+ if (t.isObjectPattern(pattern)) {
219
+ for (const prop of pattern.properties) if (t.isRestElement(prop)) collectPatternNames(prop.argument, out);
220
+ else if (t.isObjectProperty(prop)) collectPatternNames(prop.value, out);
221
+ return;
222
+ }
223
+ if (t.isArrayPattern(pattern)) for (const el of pattern.elements) collectPatternNames(el, out);
273
224
  }
274
- function parseBabelExpression(exp) {
275
- const cached = babelExpressionCache.get(exp);
276
- if (cached !== void 0) return cached === false ? null : cached;
277
- try {
278
- const stmt = parse$2(`(${exp})`, {
279
- sourceType: "module",
280
- plugins: ["typescript"]
281
- }).program.body[0];
282
- if (!stmt || !("expression" in stmt)) {
283
- babelExpressionCache.set(exp, false);
284
- return null;
225
+ function declaredNamesInStatement(statement) {
226
+ const out = /* @__PURE__ */ new Set();
227
+ if (t.isImportDeclaration(statement)) {
228
+ for (const specifier of statement.specifiers) if (t.isImportSpecifier(specifier) || t.isImportDefaultSpecifier(specifier) || t.isImportNamespaceSpecifier(specifier)) {
229
+ if (t.isIdentifier(specifier.local)) out.add(specifier.local.name);
285
230
  }
286
- const expression = stmt.expression;
287
- babelExpressionCache.set(exp, expression);
288
- return expression;
289
- } catch {
290
- babelExpressionCache.set(exp, false);
291
- return null;
231
+ return out;
292
232
  }
293
- }
294
- function parseBabelExpressionFile(exp) {
295
- try {
296
- const ast = parse$2(`(${exp})`, {
297
- sourceType: "module",
298
- plugins: ["typescript"]
299
- });
300
- const stmt = ast.program.body[0];
301
- if (!stmt || !("expression" in stmt)) return null;
302
- return {
303
- ast,
304
- expression: stmt.expression
305
- };
306
- } catch {
307
- return null;
233
+ if (t.isVariableDeclaration(statement)) {
234
+ for (const decl of statement.declarations) collectPatternNames(decl.id, out);
235
+ return out;
236
+ }
237
+ if (t.isFunctionDeclaration(statement) || t.isClassDeclaration(statement)) {
238
+ if (statement.id && t.isIdentifier(statement.id)) out.add(statement.id.name);
239
+ return out;
308
240
  }
241
+ if (t.isExportNamedDeclaration(statement) && statement.declaration) return declaredNamesInStatement(statement.declaration);
242
+ return out;
309
243
  }
310
-
311
- //#endregion
312
- //#region src/plugins/vue/compiler/template/expression/wxml.ts
313
- function templateLiteralToConcat(node) {
314
- const segments = [];
315
- node.quasis.forEach((quasi, index) => {
316
- const cooked = quasi.value.cooked ?? quasi.value.raw ?? "";
317
- if (cooked) segments.push(t.stringLiteral(cooked));
318
- if (index < node.expressions.length) {
319
- let inner = node.expressions[index];
320
- if (t.isTemplateLiteral(inner)) inner = templateLiteralToConcat(inner);
321
- segments.push(inner);
244
+ function collectTopLevelReferencedNames(path) {
245
+ const names = /* @__PURE__ */ new Set();
246
+ if (!path) return names;
247
+ const addIfTopLevelReferenced = (p) => {
248
+ if (!p?.isReferencedIdentifier?.()) return;
249
+ const name = p.node.name;
250
+ const binding = p.scope?.getBinding(name);
251
+ if (!binding) return;
252
+ if (binding.scope?.block?.type === "Program") names.add(name);
253
+ };
254
+ addIfTopLevelReferenced(path);
255
+ path.traverse({
256
+ Function(p) {
257
+ if (p.node !== path.node) p.skip();
258
+ },
259
+ Class(p) {
260
+ if (p.node !== path.node) p.skip();
261
+ },
262
+ Identifier(p) {
263
+ addIfTopLevelReferenced(p);
322
264
  }
323
265
  });
324
- if (segments.length === 0) return t.stringLiteral("");
325
- if (segments.length === 1) return segments[0];
326
- return segments.reduce((acc, cur) => t.binaryExpression("+", acc, cur));
327
- }
328
- function isOptionalChainNode(node) {
329
- return Boolean(node && (t.isOptionalMemberExpression(node) || t.isOptionalCallExpression(node)));
266
+ return names;
330
267
  }
331
- function collectOptionalChain(node) {
332
- const operations = [];
333
- let current = node;
334
- while (isOptionalChainNode(current)) {
335
- if (t.isOptionalMemberExpression(current)) {
336
- operations.push({
337
- type: "member",
338
- optional: current.optional === true,
339
- computed: current.computed,
340
- property: t.cloneNode(current.property)
341
- });
342
- current = current.object;
343
- continue;
344
- }
345
- operations.push({
346
- type: "call",
347
- optional: current.optional === true,
348
- args: current.arguments.map((arg) => t.cloneNode(arg))
349
- });
350
- current = current.callee;
268
+ function collectKeptStatementPaths(programPath, macroStatements) {
269
+ const bodyPaths = programPath.get("body");
270
+ const nameToStatementPath = /* @__PURE__ */ new Map();
271
+ for (const statementPath of bodyPaths) {
272
+ const declared = declaredNamesInStatement(statementPath.node);
273
+ for (const name of declared) if (!nameToStatementPath.has(name)) nameToStatementPath.set(name, statementPath);
351
274
  }
352
- if (!t.isExpression(current)) return null;
275
+ const neededNames = /* @__PURE__ */ new Set();
276
+ for (const statementPath of macroStatements) {
277
+ const deps = collectTopLevelReferencedNames(statementPath.get("expression").get("arguments.0"));
278
+ for (const dep of deps) neededNames.add(dep);
279
+ }
280
+ const keptStatementPaths = /* @__PURE__ */ new Set();
281
+ const queue = [...neededNames];
282
+ while (queue.length) {
283
+ const name = queue.pop();
284
+ const declPath = nameToStatementPath.get(name);
285
+ if (!declPath || keptStatementPaths.has(declPath)) continue;
286
+ keptStatementPaths.add(declPath);
287
+ const deps = collectTopLevelReferencedNames(declPath);
288
+ for (const dep of deps) if (dep !== name) queue.push(dep);
289
+ }
290
+ for (const statementPath of macroStatements) keptStatementPaths.add(statementPath);
353
291
  return {
354
- base: t.cloneNode(current),
355
- operations: operations.reverse()
292
+ bodyPaths,
293
+ keptStatementPaths
356
294
  };
357
295
  }
358
- function applyOptionalChainOperation(base, operation) {
359
- if (operation.type === "member") return t.memberExpression(base, t.cloneNode(operation.property), operation.computed);
360
- return t.callExpression(base, operation.args.map((arg) => t.cloneNode(arg)));
361
- }
362
- function lowerOptionalChain(node) {
363
- const chain = collectOptionalChain(node);
364
- if (!chain) return t.cloneNode(node);
365
- const segments = [chain.base];
366
- for (const operation of chain.operations) {
367
- const currentBase = t.cloneNode(segments[segments.length - 1]);
368
- segments.push(applyOptionalChainOperation(currentBase, operation));
369
- }
370
- let lowered = t.cloneNode(segments[segments.length - 1]);
371
- for (let index = chain.operations.length - 1; index >= 0; index--) {
372
- if (!chain.operations[index].optional) continue;
373
- lowered = t.conditionalExpression(t.binaryExpression("==", t.cloneNode(segments[index]), t.nullLiteral()), t.identifier("undefined"), lowered);
296
+ //#endregion
297
+ //#region src/plugins/vue/transform/tempDirLock.ts
298
+ const locks = /* @__PURE__ */ new Map();
299
+ async function withTempDirLock(tempDir, fn) {
300
+ const previous = locks.get(tempDir) ?? Promise.resolve();
301
+ let release;
302
+ const gate = new Promise((resolve) => {
303
+ release = resolve;
304
+ });
305
+ const current = previous.then(() => gate);
306
+ locks.set(tempDir, current);
307
+ try {
308
+ await previous;
309
+ return await fn();
310
+ } finally {
311
+ release?.();
312
+ if (locks.get(tempDir) === current) locks.delete(tempDir);
374
313
  }
375
- return lowered;
376
314
  }
377
- function normalizeWxmlExpression(exp) {
378
- if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.")) return exp;
379
- try {
380
- const ast = parse$2(`(${exp})`, {
381
- sourceType: "module",
382
- plugins: ["typescript"]
383
- });
384
- const stmt = ast.program.body[0];
385
- if (!stmt || !("expression" in stmt)) return exp;
386
- traverse(ast, {
387
- OptionalMemberExpression: { exit(path) {
388
- if (isOptionalChainNode(path.parentPath.node)) return;
389
- path.replaceWith(lowerOptionalChain(path.node));
390
- path.skip();
391
- } },
392
- OptionalCallExpression: { exit(path) {
393
- if (isOptionalChainNode(path.parentPath.node)) return;
394
- path.replaceWith(lowerOptionalChain(path.node));
395
- path.skip();
396
- } },
397
- LogicalExpression(path) {
398
- if (path.node.operator !== "??") return;
399
- const left = path.node.left;
400
- const right = path.node.right;
401
- const test = t.binaryExpression("!=", t.cloneNode(left), t.nullLiteral());
402
- path.replaceWith(t.conditionalExpression(test, t.cloneNode(left), t.cloneNode(right)));
403
- path.skip();
404
- },
405
- TemplateLiteral(path) {
406
- if (t.isTaggedTemplateExpression(path.parent)) return;
407
- path.replaceWith(templateLiteralToConcat(path.node));
408
- }
409
- });
410
- const normalized = stmt.expression;
411
- return generateExpression(normalized);
412
- } catch {
413
- if (exp.startsWith("`") && exp.endsWith("`")) {
414
- let rewritten = `'${exp.slice(1, -1).replace(/\$\{([^}]+)\}/g, "' + ($1) + '")}'`;
415
- rewritten = rewritten.replace(/'\s*\+\s*''/g, "'").replace(/''\s*\+\s*'/g, "'");
416
- rewritten = rewritten.replace(/^\s*''\s*\+\s*/g, "").replace(/\s*\+\s*''\s*$/g, "");
417
- return rewritten;
418
- }
419
- return exp;
420
- }
421
- }
422
-
423
- //#endregion
424
- //#region src/plugins/vue/compiler/template/platforms/alipay.ts
425
- const eventMap$3 = {
426
- click: "tap",
427
- dblclick: "tap",
428
- mousedown: "touchstart",
429
- mouseup: "touchend",
430
- tap: "tap",
431
- input: "input",
432
- change: "change",
433
- submit: "submit",
434
- focus: "focus",
435
- blur: "blur",
436
- confirm: "confirm",
437
- cancel: "cancel",
438
- load: "load",
439
- error: "error",
440
- scroll: "scroll",
441
- scrolltoupper: "scrolltoupper",
442
- scrolltolower: "scrolltolower",
443
- touchcancel: "touchcancel",
444
- longtap: "longtap",
445
- longpress: "longpress"
446
- };
447
- function toOnEventName(eventName) {
448
- if (!eventName) return "on";
449
- return `on${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
450
- }
451
- function parseEventBinding$3(eventName) {
452
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
453
- if (prefixed) return {
454
- prefix: prefixed[1],
455
- name: prefixed[2]
456
- };
457
- return {
458
- prefix: "bind",
459
- name: eventName
460
- };
461
- }
462
- function toAlipayDirectiveEvent(prefix, eventName) {
463
- if (!eventName) return "on";
464
- const pascalEvent = `${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
465
- switch (prefix) {
466
- case "catch": return `catch${pascalEvent}`;
467
- case "capture-bind": return `capture${pascalEvent}`;
468
- case "capture-catch": return `captureCatch${pascalEvent}`;
469
- default: return toOnEventName(eventName);
470
- }
471
- }
472
- /**
473
- * 支付宝小程序平台适配器。
474
- */
475
- const alipayPlatform = {
476
- name: "alipay",
477
- wrapIf: (exp, content, renderMustache) => `<block a:if="${renderMustache(exp)}">${content}</block>`,
478
- wrapElseIf: (exp, content, renderMustache) => `<block a:elif="${renderMustache(exp)}">${content}</block>`,
479
- wrapElse: (content) => `<block a:else>${content}</block>`,
480
- forAttrs: (listExp, renderMustache, item, index) => {
481
- const attrs = [`a:for="${renderMustache(listExp)}"`];
482
- if (item) attrs.push(`a:for-item="${item}"`);
483
- if (index) attrs.push(`a:for-index="${index}"`);
484
- return attrs;
485
- },
486
- keyThisValue: "*this",
487
- keyAttr: (value) => `a:key="${value}"`,
488
- mapEventName: (eventName) => eventMap$3[eventName] || eventName,
489
- eventBindingAttr: (eventName) => {
490
- const { prefix, name } = parseEventBinding$3(eventName);
491
- if (name.includes(":")) return `on:${name}`;
492
- return toAlipayDirectiveEvent(prefix, name);
493
- }
494
- };
495
-
496
315
  //#endregion
497
- //#region src/plugins/vue/compiler/template/platforms/swan.ts
498
- const eventMap$2 = {
499
- click: "tap",
500
- dblclick: "tap",
501
- mousedown: "touchstart",
502
- mouseup: "touchend",
503
- tap: "tap",
504
- input: "input",
505
- change: "change",
506
- submit: "submit",
507
- focus: "focus",
508
- blur: "blur",
509
- confirm: "confirm",
510
- cancel: "cancel",
511
- load: "load",
512
- error: "error",
513
- scroll: "scroll",
514
- scrolltoupper: "scrolltoupper",
515
- scrolltolower: "scrolltolower",
516
- touchcancel: "touchcancel",
517
- longtap: "longtap",
518
- longpress: "longpress"
316
+ //#region src/utils/babel.ts
317
+ const BABEL_TS_MODULE_PLUGINS = [
318
+ "typescript",
319
+ "decorators-legacy",
320
+ "classProperties",
321
+ "classPrivateProperties",
322
+ "classPrivateMethods",
323
+ "jsx"
324
+ ];
325
+ const BABEL_TS_MODULE_PARSER_OPTIONS = {
326
+ sourceType: "module",
327
+ plugins: BABEL_TS_MODULE_PLUGINS
519
328
  };
520
- function parseEventBinding$2(eventName) {
521
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
522
- if (prefixed) return {
523
- prefix: prefixed[1],
524
- name: prefixed[2]
525
- };
526
- return {
527
- prefix: "bind",
528
- name: eventName
529
- };
530
- }
531
- function shouldUseColonEventBinding$2(name) {
532
- return name.includes(":") || name.includes("-");
533
- }
534
- /**
535
- * 百度智能小程序平台适配器。
536
- */
537
- const swanPlatform = {
538
- name: "swan",
539
- wrapIf: (exp, content, renderMustache) => `<block s-if="${renderMustache(exp)}">${content}</block>`,
540
- wrapElseIf: (exp, content, renderMustache) => `<block s-elif="${renderMustache(exp)}">${content}</block>`,
541
- wrapElse: (content) => `<block s-else>${content}</block>`,
542
- forAttrs: (listExp, renderMustache, item, index) => {
543
- const attrs = [`s-for="${renderMustache(listExp)}"`];
544
- if (item) attrs.push(`s-for-item="${item}"`);
545
- if (index) attrs.push(`s-for-index="${index}"`);
546
- return attrs;
547
- },
548
- keyThisValue: "*this",
549
- keyAttr: (value) => `s-key="${value}"`,
550
- mapEventName: (eventName) => eventMap$2[eventName] || eventName,
551
- eventBindingAttr: (eventName) => {
552
- const { prefix, name } = parseEventBinding$2(eventName);
553
- switch (prefix) {
554
- case "catch": return shouldUseColonEventBinding$2(name) ? `catch:${name}` : `catch${name}`;
555
- case "capture-bind": return `capture-bind:${name}`;
556
- case "capture-catch": return `capture-catch:${name}`;
557
- case "mut-bind": return `mut-bind:${name}`;
558
- default: return shouldUseColonEventBinding$2(name) ? `bind:${name}` : `bind${name}`;
559
- }
329
+ const nodeRequire = createRequire(import.meta.url);
330
+ let cachedTraverse;
331
+ let cachedGenerate;
332
+ function requireCallableDefault(id) {
333
+ const mod = nodeRequire(id);
334
+ if (typeof mod === "function") return mod;
335
+ if (mod && (typeof mod === "object" || typeof mod === "function") && "default" in mod) {
336
+ const candidate = mod.default;
337
+ if (typeof candidate === "function") return candidate;
560
338
  }
561
- };
562
-
563
- //#endregion
564
- //#region src/plugins/vue/compiler/template/platforms/tt.ts
565
- const eventMap$1 = {
566
- click: "tap",
567
- dblclick: "tap",
568
- mousedown: "touchstart",
569
- mouseup: "touchend",
570
- tap: "tap",
571
- input: "input",
572
- change: "change",
573
- submit: "submit",
574
- focus: "focus",
575
- blur: "blur",
576
- confirm: "confirm",
577
- cancel: "cancel",
578
- load: "load",
579
- error: "error",
580
- scroll: "scroll",
581
- scrolltoupper: "scrolltoupper",
582
- scrolltolower: "scrolltolower",
583
- touchcancel: "touchcancel",
584
- longtap: "longtap",
585
- longpress: "longpress"
586
- };
587
- function parseEventBinding$1(eventName) {
588
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
589
- if (prefixed) return {
590
- prefix: prefixed[1],
591
- name: prefixed[2]
592
- };
593
- return {
594
- prefix: "bind",
595
- name: eventName
596
- };
597
- }
598
- function shouldUseColonEventBinding$1(name) {
599
- return name.includes(":") || name.includes("-");
339
+ throw new TypeError(`Invalid module shape for ${id}`);
600
340
  }
601
- /**
602
- * 抖音小程序平台适配器。
603
- */
604
- const ttPlatform = {
605
- name: "tt",
606
- wrapIf: (exp, content, renderMustache) => `<block tt:if="${renderMustache(exp)}">${content}</block>`,
607
- wrapElseIf: (exp, content, renderMustache) => `<block tt:elif="${renderMustache(exp)}">${content}</block>`,
608
- wrapElse: (content) => `<block tt:else>${content}</block>`,
609
- forAttrs: (listExp, renderMustache, item, index) => {
610
- const attrs = [`tt:for="${renderMustache(listExp)}"`];
611
- if (item) attrs.push(`tt:for-item="${item}"`);
612
- if (index) attrs.push(`tt:for-index="${index}"`);
613
- return attrs;
614
- },
615
- keyThisValue: "*this",
616
- keyAttr: (value) => `tt:key="${value}"`,
617
- mapEventName: (eventName) => eventMap$1[eventName] || eventName,
618
- eventBindingAttr: (eventName) => {
619
- const { prefix, name } = parseEventBinding$1(eventName);
620
- switch (prefix) {
621
- case "catch": return shouldUseColonEventBinding$1(name) ? `catch:${name}` : `catch${name}`;
622
- case "capture-bind": return `capture-bind:${name}`;
623
- case "capture-catch": return `capture-catch:${name}`;
624
- case "mut-bind": return `mut-bind:${name}`;
625
- default: return shouldUseColonEventBinding$1(name) ? `bind:${name}` : `bind${name}`;
626
- }
627
- }
628
- };
629
-
630
- //#endregion
631
- //#region src/plugins/vue/compiler/template/platforms/wechat.ts
632
- const eventMap = {
633
- click: "tap",
634
- dblclick: "tap",
635
- mousedown: "touchstart",
636
- mouseup: "touchend",
637
- tap: "tap",
638
- input: "input",
639
- change: "change",
640
- submit: "submit",
641
- focus: "focus",
642
- blur: "blur",
643
- confirm: "confirm",
644
- cancel: "cancel",
645
- load: "load",
646
- error: "error",
647
- scroll: "scroll",
648
- scrolltoupper: "scrolltoupper",
649
- scrolltolower: "scrolltolower",
650
- touchcancel: "touchcancel",
651
- longtap: "longtap",
652
- longpress: "longpress"
653
- };
654
- function parseEventBinding(eventName) {
655
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
656
- if (prefixed) return {
657
- prefix: prefixed[1],
658
- name: prefixed[2]
659
- };
660
- return {
661
- prefix: "bind",
662
- name: eventName
663
- };
341
+ function getTraverse() {
342
+ if (!cachedTraverse) cachedTraverse = requireCallableDefault("@babel/traverse");
343
+ return cachedTraverse;
664
344
  }
665
- function shouldUseColonEventBinding(name) {
666
- return name.includes(":") || name.includes("-");
345
+ function getGenerate() {
346
+ if (!cachedGenerate) cachedGenerate = requireCallableDefault("@babel/generator");
347
+ return cachedGenerate;
667
348
  }
668
- /**
669
- * 微信小程序平台适配器。
670
- */
671
- const wechatPlatform = {
672
- name: "wechat",
673
- wrapIf: (exp, content, renderMustache) => `<block wx:if="${renderMustache(exp)}">${content}</block>`,
674
- wrapElseIf: (exp, content, renderMustache) => `<block wx:elif="${renderMustache(exp)}">${content}</block>`,
675
- wrapElse: (content) => `<block wx:else>${content}</block>`,
676
- forAttrs: (listExp, renderMustache, item, index) => {
677
- const attrs = [`wx:for="${renderMustache(listExp)}"`];
678
- if (item) attrs.push(`wx:for-item="${item}"`);
679
- if (index) attrs.push(`wx:for-index="${index}"`);
680
- return attrs;
681
- },
682
- keyThisValue: "*this",
683
- keyAttr: (value) => `wx:key="${value}"`,
684
- mapEventName: (eventName) => eventMap[eventName] || eventName,
685
- eventBindingAttr: (eventName) => {
686
- const { prefix, name } = parseEventBinding(eventName);
687
- switch (prefix) {
688
- case "catch": return shouldUseColonEventBinding(name) ? `catch:${name}` : `catch${name}`;
689
- case "capture-bind": return `capture-bind:${name}`;
690
- case "capture-catch": return `capture-catch:${name}`;
691
- case "mut-bind": return `mut-bind:${name}`;
692
- default: return shouldUseColonEventBinding(name) ? `bind:${name}` : `bind${name}`;
693
- }
694
- }
349
+ const traverse = (...args) => {
350
+ return getTraverse()(...args);
695
351
  };
696
-
697
- //#endregion
698
- //#region src/plugins/vue/compiler/template/platforms/index.ts
699
- const TEMPLATE_PLATFORMS = {
700
- weapp: wechatPlatform,
701
- alipay: alipayPlatform,
702
- tt: ttPlatform,
703
- swan: swanPlatform,
704
- jd: wechatPlatform,
705
- xhs: wechatPlatform
352
+ const generate = (...args) => {
353
+ return getGenerate()(...args);
706
354
  };
707
- /**
708
- * 获取指定平台的模板适配器,默认回退到 wechat。
709
- */
710
- function getMiniProgramTemplatePlatform(platform) {
711
- if (!platform) return wechatPlatform;
712
- return TEMPLATE_PLATFORMS[platform] ?? wechatPlatform;
713
- }
714
-
715
- //#endregion
716
- //#region src/plugins/vue/transform/jsonMacros/analyze.ts
717
- function collectPatternNames(pattern, out) {
718
- if (!pattern) return;
719
- if (t.isIdentifier(pattern)) {
720
- out.add(pattern.name);
721
- return;
722
- }
723
- if (t.isRestElement(pattern)) {
724
- collectPatternNames(pattern.argument, out);
725
- return;
726
- }
727
- if (t.isAssignmentPattern(pattern)) {
728
- collectPatternNames(pattern.left, out);
729
- return;
730
- }
731
- if (t.isObjectPattern(pattern)) {
732
- for (const prop of pattern.properties) if (t.isRestElement(prop)) collectPatternNames(prop.argument, out);
733
- else if (t.isObjectProperty(prop)) collectPatternNames(prop.value, out);
734
- return;
735
- }
736
- if (t.isArrayPattern(pattern)) for (const el of pattern.elements) collectPatternNames(el, out);
737
- }
738
- function declaredNamesInStatement(statement) {
739
- const out = /* @__PURE__ */ new Set();
740
- if (t.isImportDeclaration(statement)) {
741
- for (const specifier of statement.specifiers) if (t.isImportSpecifier(specifier) || t.isImportDefaultSpecifier(specifier) || t.isImportNamespaceSpecifier(specifier)) {
742
- if (t.isIdentifier(specifier.local)) out.add(specifier.local.name);
743
- }
744
- return out;
745
- }
746
- if (t.isVariableDeclaration(statement)) {
747
- for (const decl of statement.declarations) collectPatternNames(decl.id, out);
748
- return out;
749
- }
750
- if (t.isFunctionDeclaration(statement) || t.isClassDeclaration(statement)) {
751
- if (statement.id && t.isIdentifier(statement.id)) out.add(statement.id.name);
752
- return out;
753
- }
754
- if (t.isExportNamedDeclaration(statement) && statement.declaration) return declaredNamesInStatement(statement.declaration);
755
- return out;
756
- }
757
- function collectTopLevelReferencedNames(path) {
758
- const names = /* @__PURE__ */ new Set();
759
- if (!path) return names;
760
- const addIfTopLevelReferenced = (p) => {
761
- if (!p?.isReferencedIdentifier?.()) return;
762
- const name = p.node.name;
763
- const binding = p.scope?.getBinding(name);
764
- if (!binding) return;
765
- if (binding.scope?.block?.type === "Program") names.add(name);
766
- };
767
- addIfTopLevelReferenced(path);
768
- path.traverse({
769
- Function(p) {
770
- if (p.node !== path.node) p.skip();
771
- },
772
- Class(p) {
773
- if (p.node !== path.node) p.skip();
774
- },
775
- Identifier(p) {
776
- addIfTopLevelReferenced(p);
777
- }
778
- });
779
- return names;
780
- }
781
- function collectKeptStatementPaths(programPath, macroStatements) {
782
- const bodyPaths = programPath.get("body");
783
- const nameToStatementPath = /* @__PURE__ */ new Map();
784
- for (const statementPath of bodyPaths) {
785
- const declared = declaredNamesInStatement(statementPath.node);
786
- for (const name of declared) if (!nameToStatementPath.has(name)) nameToStatementPath.set(name, statementPath);
787
- }
788
- const neededNames = /* @__PURE__ */ new Set();
789
- for (const statementPath of macroStatements) {
790
- const deps = collectTopLevelReferencedNames(statementPath.get("expression").get("arguments.0"));
791
- for (const dep of deps) neededNames.add(dep);
792
- }
793
- const keptStatementPaths = /* @__PURE__ */ new Set();
794
- const queue = [...neededNames];
795
- while (queue.length) {
796
- const name = queue.pop();
797
- const declPath = nameToStatementPath.get(name);
798
- if (!declPath || keptStatementPaths.has(declPath)) continue;
799
- keptStatementPaths.add(declPath);
800
- const deps = collectTopLevelReferencedNames(declPath);
801
- for (const dep of deps) if (dep !== name) queue.push(dep);
802
- }
803
- for (const statementPath of macroStatements) keptStatementPaths.add(statementPath);
804
- return {
805
- bodyPaths,
806
- keptStatementPaths
807
- };
808
- }
809
-
810
- //#endregion
811
- //#region src/plugins/vue/transform/tempDirLock.ts
812
- const locks = /* @__PURE__ */ new Map();
813
- async function withTempDirLock(tempDir, fn) {
814
- const previous = locks.get(tempDir) ?? Promise.resolve();
815
- let release;
816
- const gate = new Promise((resolve) => {
817
- release = resolve;
355
+ function parseJsLike(source) {
356
+ return parse$2(source, {
357
+ sourceType: "module",
358
+ plugins: [
359
+ ...BABEL_TS_MODULE_PLUGINS,
360
+ "dynamicImport",
361
+ "optionalChaining",
362
+ "nullishCoalescingOperator"
363
+ ]
818
364
  });
819
- const current = previous.then(() => gate);
820
- locks.set(tempDir, current);
821
- try {
822
- await previous;
823
- return await fn();
824
- } finally {
825
- release?.();
826
- if (locks.get(tempDir) === current) locks.delete(tempDir);
827
- }
828
365
  }
829
-
830
366
  //#endregion
831
367
  //#region src/utils/path.ts
832
368
  const BACKSLASH_RE$1 = /\\/g;
@@ -842,7 +378,6 @@ function stripLeadingSlashes(value) {
842
378
  function normalizeRoot(root) {
843
379
  return toPosixPath(root).replace(DUPLICATE_SLASH_RE, "/").replace(TRIM_SLASH_RE, "");
844
380
  }
845
-
846
381
  //#endregion
847
382
  //#region src/plugins/vue/transform/tempImportRewrite.ts
848
383
  function rewriteRelativeImportSource(source, fromDir, tempDir) {
@@ -893,7 +428,6 @@ function rewriteJsLikeImportsForTempDir(source, fromDir, tempDir) {
893
428
  });
894
429
  return mutated ? ms.toString() : source;
895
430
  }
896
-
897
431
  //#endregion
898
432
  //#region src/plugins/vue/transform/wevuTempDir.ts
899
433
  function getWevuConfigCacheRoot() {
@@ -909,7 +443,6 @@ function resolveWevuConfigTempDir(fromDir) {
909
443
  const key = createHash("sha256").update(path.normalize(fromDir)).digest("hex").slice(0, 8);
910
444
  return path.join(root, key);
911
445
  }
912
-
913
446
  //#endregion
914
447
  //#region src/plugins/vue/transform/jsonMacros/execute.ts
915
448
  function normalizeScriptSetupLang$1(lang) {
@@ -1001,7 +534,6 @@ const __weapp_defineThemeJson = (config) => (__weapp_json_macro_values.push(conf
1001
534
  }
1002
535
  });
1003
536
  }
1004
-
1005
537
  //#endregion
1006
538
  //#region src/plugins/vue/transform/jsonMacros/parse.ts
1007
539
  const JSON_MACROS = new Set([
@@ -1047,7 +579,6 @@ function findProgramPath(ast) {
1047
579
  } });
1048
580
  return programPath;
1049
581
  }
1050
-
1051
582
  //#endregion
1052
583
  //#region src/plugins/vue/transform/jsonMacros/rewrite.ts
1053
584
  /**
@@ -1099,7 +630,6 @@ function stripJsonMacroCallsFromCode(code, filename) {
1099
630
  } });
1100
631
  return ms.toString();
1101
632
  }
1102
-
1103
633
  //#endregion
1104
634
  //#region src/plugins/vue/transform/jsonMacros/index.ts
1105
635
  /**
@@ -1142,7 +672,6 @@ async function evaluateJsonMacroConfig(content, filename, lang, options) {
1142
672
  options
1143
673
  });
1144
674
  }
1145
-
1146
675
  //#endregion
1147
676
  //#region src/plugins/vue/transform/jsonMerge.ts
1148
677
  function toPlainRecord(value) {
@@ -1180,7 +709,6 @@ function createJsonMerger(strategy, baseContext) {
1180
709
  });
1181
710
  };
1182
711
  }
1183
-
1184
712
  //#endregion
1185
713
  //#region src/utils/warn.ts
1186
714
  /**
@@ -1191,7 +719,6 @@ function resolveWarnHandler(warn) {
1191
719
  console.warn(message);
1192
720
  });
1193
721
  }
1194
-
1195
722
  //#endregion
1196
723
  //#region src/plugins/wevu/pageFeatures/astUtils.ts
1197
724
  function isStaticObjectKeyMatch$1(key, expected) {
@@ -1221,7 +748,6 @@ function getObjectMemberIndexByKey(node, key) {
1221
748
  function isTopLevel(path) {
1222
749
  return path.getFunctionParent() == null;
1223
750
  }
1224
-
1225
751
  //#endregion
1226
752
  //#region src/plugins/wevu/pageFeatures/flags.ts
1227
753
  function injectWevuShareLifecycleHooksIntoOptionsObject(_optionsObject, _enabled) {
@@ -1234,7 +760,7 @@ function collectWevuPageFeatureFlags(ast) {
1234
760
  const namedHookLocals = /* @__PURE__ */ new Map();
1235
761
  const namespaceLocals = /* @__PURE__ */ new Set();
1236
762
  for (const stmt of ast.program.body) {
1237
- if (!t.isImportDeclaration(stmt) || stmt.source.value !== WE_VU_MODULE_ID) continue;
763
+ if (!t.isImportDeclaration(stmt) || stmt.source.value !== "wevu") continue;
1238
764
  for (const specifier of stmt.specifiers) if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
1239
765
  const matched = WE_VU_PAGE_HOOK_TO_FEATURE[specifier.imported.name];
1240
766
  if (matched) namedHookLocals.set(specifier.local.name, matched);
@@ -1312,7 +838,6 @@ function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
1312
838
  changed = injectWevuShareLifecycleHooksIntoOptionsObject(optionsObject, enabled) || changed;
1313
839
  return changed;
1314
840
  }
1315
-
1316
841
  //#endregion
1317
842
  //#region src/plugins/wevu/pageFeatures/moduleAnalysis.ts
1318
843
  const externalModuleAnalysisCache = new LRUCache({ max: 256 });
@@ -1360,7 +885,7 @@ function createModuleAnalysis(id, ast) {
1360
885
  const source = stmt.source.value;
1361
886
  for (const specifier of stmt.specifiers) if (t.isImportSpecifier(specifier)) {
1362
887
  const imported = specifier.imported;
1363
- if (source === WE_VU_MODULE_ID && t.isIdentifier(imported)) {
888
+ if (source === "wevu" && t.isIdentifier(imported)) {
1364
889
  const matched = WE_VU_PAGE_HOOK_TO_FEATURE[imported.name];
1365
890
  if (matched) wevuNamedHookLocals.set(specifier.local.name, matched);
1366
891
  }
@@ -1378,7 +903,7 @@ function createModuleAnalysis(id, ast) {
1378
903
  kind: "namespace",
1379
904
  source
1380
905
  });
1381
- if (source === WE_VU_MODULE_ID) wevuNamespaceLocals.add(specifier.local.name);
906
+ if (source === "wevu") wevuNamespaceLocals.add(specifier.local.name);
1382
907
  }
1383
908
  continue;
1384
909
  }
@@ -1459,7 +984,6 @@ function createModuleAnalysis(id, ast) {
1459
984
  exports
1460
985
  };
1461
986
  }
1462
-
1463
987
  //#endregion
1464
988
  //#region src/plugins/wevu/pageFeatures/optionsObjects.ts
1465
989
  function unwrapTypeLikeExpression$2(node) {
@@ -1508,11 +1032,11 @@ function collectTargetOptionsObjects(ast, moduleId) {
1508
1032
  if (!first || !t.isExpression(first)) return;
1509
1033
  const binding = t.isIdentifier(node.callee) ? module.importedBindings.get(node.callee.name) : void 0;
1510
1034
  if (t.isIdentifier(node.callee)) {
1511
- if (binding?.kind !== "named" || binding.source !== WE_VU_MODULE_ID) return;
1035
+ if (binding?.kind !== "named" || binding.source !== "wevu") return;
1512
1036
  if (binding.importedName !== WE_VU_RUNTIME_APIS.defineComponent && binding.importedName !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1513
1037
  } else if (t.isMemberExpression(node.callee) && !node.callee.computed && t.isIdentifier(node.callee.object) && t.isIdentifier(node.callee.property)) {
1514
1038
  const objectBinding = module.importedBindings.get(node.callee.object.name);
1515
- if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1039
+ if (objectBinding?.kind !== "namespace" || objectBinding.source !== "wevu") return;
1516
1040
  if (node.callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && node.callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1517
1041
  } else return;
1518
1042
  const inlineObject = resolveOptionsObjectFromExpression(first);
@@ -1532,11 +1056,11 @@ function collectTargetOptionsObjects(ast, moduleId) {
1532
1056
  if (!first || !t.isExpression(first)) return;
1533
1057
  if (t.isIdentifier(callee)) {
1534
1058
  const binding = module.importedBindings.get(callee.name);
1535
- if (binding?.kind !== "named" || binding.source !== WE_VU_MODULE_ID) return;
1059
+ if (binding?.kind !== "named" || binding.source !== "wevu") return;
1536
1060
  if (binding.importedName !== WE_VU_RUNTIME_APIS.defineComponent && binding.importedName !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1537
1061
  } else if (t.isMemberExpression(callee) && !callee.computed && t.isIdentifier(callee.object) && t.isIdentifier(callee.property)) {
1538
1062
  const objectBinding = module.importedBindings.get(callee.object.name);
1539
- if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1063
+ if (objectBinding?.kind !== "namespace" || objectBinding.source !== "wevu") return;
1540
1064
  if (callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1541
1065
  } else return;
1542
1066
  const inlineObject = resolveOptionsObjectFromExpression(first);
@@ -1557,7 +1081,6 @@ function collectTargetOptionsObjects(ast, moduleId) {
1557
1081
  module
1558
1082
  };
1559
1083
  }
1560
-
1561
1084
  //#endregion
1562
1085
  //#region src/plugins/wevu/pageFeatures/reachability/calls.ts
1563
1086
  function getCallCalleeName(callee) {
@@ -1586,7 +1109,6 @@ function collectCalledBindingsFromFunctionBody(fn) {
1586
1109
  });
1587
1110
  return called;
1588
1111
  }
1589
-
1590
1112
  //#endregion
1591
1113
  //#region src/plugins/wevu/pageFeatures/reachability/hooks.ts
1592
1114
  function collectWevuHookCallsInFunctionBody(module, fn) {
@@ -1620,7 +1142,6 @@ function collectWevuHookCallsInFunctionBody(module, fn) {
1620
1142
  });
1621
1143
  return enabled;
1622
1144
  }
1623
-
1624
1145
  //#endregion
1625
1146
  //#region src/plugins/wevu/pageFeatures/reachability/resolve.ts
1626
1147
  function resolveExportedFunctionNode(module, exportName) {
@@ -1638,7 +1159,7 @@ function resolveExportedFunctionNode(module, exportName) {
1638
1159
  return null;
1639
1160
  }
1640
1161
  async function resolveExternalFunction(resolver, importerId, source, exportName, moduleCache) {
1641
- if (source === WE_VU_MODULE_ID) return null;
1162
+ if (source === "wevu") return null;
1642
1163
  const resolvedId = await resolver.resolveId(source, importerId);
1643
1164
  if (!resolvedId) return null;
1644
1165
  const code = await resolver.loadCode(resolvedId);
@@ -1664,7 +1185,6 @@ async function resolveExternalFunction(resolver, importerId, source, exportName,
1664
1185
  };
1665
1186
  return null;
1666
1187
  }
1667
-
1668
1188
  //#endregion
1669
1189
  //#region src/plugins/wevu/pageFeatures/reachability/walk.ts
1670
1190
  async function walkReachableWevuFeatures(options) {
@@ -1755,7 +1275,6 @@ async function walkReachableWevuFeatures(options) {
1755
1275
  }
1756
1276
  return enabled;
1757
1277
  }
1758
-
1759
1278
  //#endregion
1760
1279
  //#region src/plugins/wevu/pageFeatures/reachability/index.ts
1761
1280
  async function collectWevuFeaturesFromSetupReachableImports(pageModule, setupFn, resolver, moduleCache) {
@@ -1766,7 +1285,6 @@ async function collectWevuFeaturesFromSetupReachableImports(pageModule, setupFn,
1766
1285
  moduleCache
1767
1286
  });
1768
1287
  }
1769
-
1770
1288
  //#endregion
1771
1289
  //#region src/plugins/wevu/pageFeatures/inject.ts
1772
1290
  /**
@@ -1830,7 +1348,6 @@ async function injectWevuPageFeaturesInJsWithResolver(source, options) {
1830
1348
  transformed: true
1831
1349
  };
1832
1350
  }
1833
-
1834
1351
  //#endregion
1835
1352
  //#region src/plugins/wevu/pageFeatures/matcher.ts
1836
1353
  /**
@@ -1881,7 +1398,6 @@ function createPageEntryMatcher(source) {
1881
1398
  }
1882
1399
  };
1883
1400
  }
1884
-
1885
1401
  //#endregion
1886
1402
  //#region src/plugins/vue/transform/scriptTemplateMeta.ts
1887
1403
  function injectTemplateComponentMeta(ast, templateComponentMeta) {
@@ -1925,7 +1441,6 @@ function injectTemplateComponentMeta(ast, templateComponentMeta) {
1925
1441
  }
1926
1442
  return changed;
1927
1443
  }
1928
-
1929
1444
  //#endregion
1930
1445
  //#region src/plugins/vue/transform/scriptVueSfcTransform.ts
1931
1446
  /**
@@ -1966,7 +1481,6 @@ function vueSfcTransformPlugin() {
1966
1481
  }
1967
1482
  };
1968
1483
  }
1969
-
1970
1484
  //#endregion
1971
1485
  //#region src/plugins/vue/transform/scriptComponent.ts
1972
1486
  function isDefineComponentCall(node, aliases) {
@@ -2025,7 +1539,6 @@ function resolveComponentOptionsObject(componentExpr) {
2025
1539
  if (t.isCallExpression(normalized)) return resolveObjectExpressionFromAssignCall(normalized);
2026
1540
  return null;
2027
1541
  }
2028
-
2029
1542
  //#endregion
2030
1543
  //#region src/plugins/vue/transform/transformScript/collect.ts
2031
1544
  function createCollectVisitors(state) {
@@ -2045,11 +1558,9 @@ function createCollectVisitors(state) {
2045
1558
  }
2046
1559
  };
2047
1560
  }
2048
-
2049
1561
  //#endregion
2050
1562
  //#region src/plugins/vue/transform/constants.ts
2051
1563
  const RUNTIME_IMPORT_PATH = WE_VU_MODULE_ID;
2052
-
2053
1564
  //#endregion
2054
1565
  //#region src/plugins/vue/transform/scriptRuntimeImport.ts
2055
1566
  function ensureRuntimeImport(program, importedName, localName = importedName) {
@@ -2065,7 +1576,6 @@ function ensureRuntimeImport(program, importedName, localName = importedName) {
2065
1576
  return t.isIdentifier(spec.local, { name: localName });
2066
1577
  })) targetImport.specifiers.push(t.importSpecifier(t.identifier(localName), t.identifier(importedName)));
2067
1578
  }
2068
-
2069
1579
  //#endregion
2070
1580
  //#region src/plugins/vue/transform/transformScript/imports.ts
2071
1581
  function createImportVisitors(program, state) {
@@ -2126,7 +1636,6 @@ function createImportVisitors(program, state) {
2126
1636
  }
2127
1637
  } };
2128
1638
  }
2129
-
2130
1639
  //#endregion
2131
1640
  //#region src/plugins/vue/transform/transformScript/macros/setupExpose.ts
2132
1641
  function createSetupExposeVisitors(state) {
@@ -2148,7 +1657,6 @@ function createSetupExposeVisitors(state) {
2148
1657
  }
2149
1658
  } };
2150
1659
  }
2151
-
2152
1660
  //#endregion
2153
1661
  //#region src/plugins/vue/transform/transformScript/macros/optional.ts
2154
1662
  function isOptionalPatternNode(node) {
@@ -2186,7 +1694,6 @@ function stripOptionalFromPattern(pattern) {
2186
1694
  }
2187
1695
  return changed;
2188
1696
  }
2189
-
2190
1697
  //#endregion
2191
1698
  //#region src/plugins/vue/transform/transformScript/macros/stripTypes.ts
2192
1699
  function createStripTypesVisitors(state) {
@@ -2321,7 +1828,6 @@ function createStripTypesVisitors(state) {
2321
1828
  }
2322
1829
  };
2323
1830
  }
2324
-
2325
1831
  //#endregion
2326
1832
  //#region src/plugins/vue/transform/transformScript/macros/index.ts
2327
1833
  function createMacroVisitors(state) {
@@ -2330,9 +1836,8 @@ function createMacroVisitors(state) {
2330
1836
  ...createStripTypesVisitors(state)
2331
1837
  };
2332
1838
  }
2333
-
2334
1839
  //#endregion
2335
- //#region src/plugins/vue/transform/classStyleComputed.ts
1840
+ //#region src/plugins/vue/transform/classStyleComputedBuilders.ts
2336
1841
  function createStaticObjectKey$1(key) {
2337
1842
  return t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
2338
1843
  }
@@ -2345,781 +1850,1352 @@ function buildNormalizedExpression(binding, helpers) {
2345
1850
  const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.identifier("undefined");
2346
1851
  return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.tryStatement(t.blockStatement([t.returnStatement(exp)]), t.catchClause(t.identifier("__wv_expr_err"), t.blockStatement([t.returnStatement(t.identifier("undefined"))])), null)])), []);
2347
1852
  }
2348
- const normalizeHelper = binding.type === "class" ? helpers.normalizeClass : helpers.normalizeStyle;
2349
- const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.stringLiteral("");
2350
- const normalizedCall = t.callExpression(t.cloneNode(normalizeHelper), [exp]);
2351
- return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.tryStatement(t.blockStatement([t.returnStatement(normalizedCall)]), t.catchClause(t.identifier("__wv_expr_err"), t.blockStatement([t.returnStatement(t.stringLiteral(""))])), null)])), []);
1853
+ const normalizeHelper = binding.type === "class" ? helpers.normalizeClass : helpers.normalizeStyle;
1854
+ const errorFallback = binding.errorFallback ?? "";
1855
+ const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.stringLiteral("");
1856
+ const normalizedCall = t.callExpression(t.cloneNode(normalizeHelper), [exp]);
1857
+ return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.tryStatement(t.blockStatement([t.returnStatement(normalizedCall)]), t.catchClause(t.identifier("__wv_expr_err"), t.blockStatement([t.returnStatement(t.stringLiteral(errorFallback))])), null)])), []);
1858
+ }
1859
+ function buildArrayMapExpression(binding, forStack, level, listId, helpers) {
1860
+ const itemParam = createValidIdentifier(forStack[level].item, `__wv_item_${level}`);
1861
+ const indexParam = createValidIdentifier(forStack[level].index, `__wv_index_${level}`);
1862
+ const body = [];
1863
+ const keyName = forStack[level].key;
1864
+ if (keyName && t.isValidIdentifier(keyName) && keyName !== indexParam.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(keyName), indexParam)]));
1865
+ const inner = buildForExpression(binding, forStack, level + 1, helpers);
1866
+ body.push(t.returnStatement(inner));
1867
+ const callback = t.arrowFunctionExpression([itemParam, indexParam], t.blockStatement(body));
1868
+ return t.callExpression(t.memberExpression(listId, t.identifier("map")), [callback]);
1869
+ }
1870
+ function buildObjectMapExpression(binding, forStack, level, listId, helpers) {
1871
+ const resId = t.identifier(`__wv_res_${level}`);
1872
+ const keysId = t.identifier(`__wv_keys_${level}`);
1873
+ const loopIndexId = t.identifier(`__wv_i_${level}`);
1874
+ const keyId = t.identifier(`__wv_key_${level}`);
1875
+ const itemId = t.identifier(`__wv_item_${level}`);
1876
+ const itemAlias = forStack[level].item;
1877
+ const indexAlias = forStack[level].index;
1878
+ const keyAlias = forStack[level].key;
1879
+ const hasKeyAlias = Boolean(keyAlias && t.isValidIdentifier(keyAlias));
1880
+ const loopBody = [t.variableDeclaration("const", [t.variableDeclarator(keyId, t.memberExpression(keysId, loopIndexId, true))]), t.variableDeclaration("const", [t.variableDeclarator(itemId, t.memberExpression(listId, keyId, true))])];
1881
+ if (itemAlias && t.isValidIdentifier(itemAlias) && itemAlias !== itemId.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(itemAlias), itemId)]));
1882
+ if (hasKeyAlias && keyAlias && keyAlias !== keyId.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(keyAlias), keyId)]));
1883
+ if (indexAlias && t.isValidIdentifier(indexAlias)) {
1884
+ const source = hasKeyAlias ? loopIndexId : keyId;
1885
+ if (indexAlias !== source.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(indexAlias), source)]));
1886
+ }
1887
+ const inner = buildForExpression(binding, forStack, level + 1, helpers);
1888
+ loopBody.push(t.expressionStatement(t.assignmentExpression("=", t.memberExpression(resId, keyId, true), inner)));
1889
+ const loop = t.forStatement(t.variableDeclaration("let", [t.variableDeclarator(loopIndexId, t.numericLiteral(0))]), t.binaryExpression("<", loopIndexId, t.memberExpression(keysId, t.identifier("length"))), t.updateExpression("++", loopIndexId), t.blockStatement(loopBody));
1890
+ return t.blockStatement([
1891
+ t.variableDeclaration("const", [t.variableDeclarator(resId, t.objectExpression([]))]),
1892
+ t.variableDeclaration("const", [t.variableDeclarator(keysId, t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("keys")), [listId]))]),
1893
+ loop,
1894
+ t.returnStatement(resId)
1895
+ ]);
1896
+ }
1897
+ function buildForExpression(binding, forStack, level, helpers) {
1898
+ if (level >= forStack.length) return buildNormalizedExpression(binding, helpers);
1899
+ const info = forStack[level];
1900
+ const listId = t.identifier(`__wv_list_${level}`);
1901
+ const listExp = info.listExpAst ? t.cloneNode(info.listExpAst, true) : t.arrayExpression([]);
1902
+ const unrefHelper = helpers.unref ? t.cloneNode(helpers.unref) : t.identifier("unref");
1903
+ const listUnrefExp = t.callExpression(unrefHelper, [listExp]);
1904
+ const listDecl = t.variableDeclaration("let", [t.variableDeclarator(listId, t.arrayExpression([]))]);
1905
+ const listSafeAssign = t.tryStatement(t.blockStatement([t.expressionStatement(t.assignmentExpression("=", listId, listUnrefExp))]), t.catchClause(t.identifier(`__wv_err_${level}`), t.blockStatement([t.expressionStatement(t.assignmentExpression("=", listId, t.arrayExpression([])))])), null);
1906
+ const arrayCheck = t.callExpression(t.memberExpression(t.identifier("Array"), t.identifier("isArray")), [listId]);
1907
+ const arrayMap = buildArrayMapExpression(binding, forStack, level, listId, helpers);
1908
+ const objectCheck = t.logicalExpression("&&", t.binaryExpression("!=", listId, t.nullLiteral()), t.binaryExpression("===", t.unaryExpression("typeof", listId), t.stringLiteral("object")));
1909
+ const objectBlock = buildObjectMapExpression(binding, forStack, level, listId, helpers);
1910
+ const fallbackReturn = t.returnStatement(t.arrayExpression([]));
1911
+ const body = t.blockStatement([
1912
+ listDecl,
1913
+ listSafeAssign,
1914
+ t.ifStatement(arrayCheck, t.blockStatement([t.returnStatement(arrayMap)]), t.ifStatement(objectCheck, objectBlock, t.blockStatement([fallbackReturn])))
1915
+ ]);
1916
+ return t.callExpression(t.arrowFunctionExpression([], body), []);
1917
+ }
1918
+ function buildComputedFunctionBody(binding, helpers) {
1919
+ const expr = buildForExpression(binding, binding.forStack ?? [], 0, helpers);
1920
+ return t.blockStatement([t.returnStatement(expr)]);
1921
+ }
1922
+ //#endregion
1923
+ //#region src/plugins/vue/transform/classStyleComputed.ts
1924
+ function buildClassStyleComputedEntries(bindings, helpers) {
1925
+ const entries = [];
1926
+ for (const binding of bindings) {
1927
+ const key = createStaticObjectKey$1(binding.name);
1928
+ const body = buildComputedFunctionBody(binding, helpers);
1929
+ const fn = t.functionExpression(null, [], body);
1930
+ entries.push(t.objectProperty(key, fn));
1931
+ }
1932
+ return entries;
1933
+ }
1934
+ function buildClassStyleComputedObject(bindings, helpers) {
1935
+ if (!bindings.length) return null;
1936
+ const entries = buildClassStyleComputedEntries(bindings, helpers);
1937
+ if (!entries.length) return null;
1938
+ return t.objectExpression(entries);
1939
+ }
1940
+ function buildClassStyleComputedCode(bindings, helpers) {
1941
+ if (!bindings.length) return null;
1942
+ const obj = buildClassStyleComputedObject(bindings, {
1943
+ normalizeClass: t.identifier(helpers.normalizeClassName),
1944
+ normalizeStyle: t.identifier(helpers.normalizeStyleName),
1945
+ unref: t.identifier(helpers.unrefName ?? "unref")
1946
+ });
1947
+ if (!obj) return null;
1948
+ const { code } = generate(obj, { compact: true });
1949
+ return code;
1950
+ }
1951
+ //#endregion
1952
+ //#region src/plugins/vue/transform/transformScript/utils.ts
1953
+ function isPlainRecord(value) {
1954
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
1955
+ const proto = Object.getPrototypeOf(value);
1956
+ return proto === null || proto === Object.prototype;
1957
+ }
1958
+ function isStaticObjectKeyMatch(key, expected) {
1959
+ if (t.isIdentifier(key)) return key.name === expected;
1960
+ if (t.isStringLiteral(key)) return key.value === expected;
1961
+ return false;
1962
+ }
1963
+ function getObjectPropertyByKey$1(node, key) {
1964
+ for (const prop of node.properties) {
1965
+ if (!t.isObjectProperty(prop) || prop.computed) continue;
1966
+ if (isStaticObjectKeyMatch(prop.key, key)) return prop;
1967
+ }
1968
+ return null;
1969
+ }
1970
+ function createStaticObjectKey(key) {
1971
+ return t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
1972
+ }
1973
+ //#endregion
1974
+ //#region src/plugins/vue/transform/transformScript/rewrite/classStyle.ts
1975
+ function injectClassStyleComputed(optionsObject, bindings, warn) {
1976
+ if (!bindings.length) return false;
1977
+ const warnHandler = resolveWarnHandler(warn);
1978
+ const entries = buildClassStyleComputedEntries(bindings, {
1979
+ normalizeClass: t.identifier("__wevuNormalizeClass"),
1980
+ normalizeStyle: t.identifier("__wevuNormalizeStyle"),
1981
+ unref: t.identifier("__wevuUnref")
1982
+ });
1983
+ if (!entries.length) return false;
1984
+ const computedProp = getObjectPropertyByKey$1(optionsObject, "computed");
1985
+ if (!computedProp) {
1986
+ optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey("computed"), t.objectExpression(entries)));
1987
+ return true;
1988
+ }
1989
+ if (t.isObjectExpression(computedProp.value)) {
1990
+ computedProp.value.properties.push(...entries);
1991
+ return true;
1992
+ }
1993
+ if (t.isIdentifier(computedProp.value) || t.isMemberExpression(computedProp.value)) {
1994
+ computedProp.value = t.objectExpression([...entries, t.spreadElement(t.cloneNode(computedProp.value, true))]);
1995
+ return true;
1996
+ }
1997
+ warnHandler("无法自动注入 class/style 计算属性,请手动合并 computed。");
1998
+ return false;
1999
+ }
2000
+ function ensureClassStyleRuntimeImports(program) {
2001
+ ensureRuntimeImport(program, "normalizeClass", "__wevuNormalizeClass");
2002
+ ensureRuntimeImport(program, "normalizeStyle", "__wevuNormalizeStyle");
2003
+ ensureRuntimeImport(program, "unref", "__wevuUnref");
2004
+ }
2005
+ //#endregion
2006
+ //#region src/plugins/vue/transform/transformScript/rewrite/defaults.ts
2007
+ function mergePlainDefaultsIntoObjectExpression(target, defaults) {
2008
+ const entries = Object.entries(defaults);
2009
+ if (!entries.length) return false;
2010
+ let changed = false;
2011
+ const injectedProps = [];
2012
+ for (const [key, value] of entries) {
2013
+ if (getObjectPropertyByKey$1(target, key)) continue;
2014
+ injectedProps.push(t.objectProperty(createStaticObjectKey(key), t.valueToNode(value)));
2015
+ }
2016
+ if (!injectedProps.length) return false;
2017
+ target.properties.splice(0, 0, ...injectedProps);
2018
+ changed = true;
2019
+ return changed;
2020
+ }
2021
+ function mergeNestedDefaults(optionsObject, key, defaultsValue) {
2022
+ if (!isPlainRecord(defaultsValue)) {
2023
+ if (defaultsValue === void 0) return false;
2024
+ if (getObjectPropertyByKey$1(optionsObject, key)) return false;
2025
+ optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(defaultsValue)));
2026
+ return true;
2027
+ }
2028
+ const existing = getObjectPropertyByKey$1(optionsObject, key);
2029
+ if (!existing) {
2030
+ optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(defaultsValue)));
2031
+ return true;
2032
+ }
2033
+ if (t.isObjectExpression(existing.value)) return mergePlainDefaultsIntoObjectExpression(existing.value, defaultsValue);
2034
+ if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2035
+ const injected = t.valueToNode(defaultsValue);
2036
+ if (t.isObjectExpression(injected)) {
2037
+ injected.properties.push(t.spreadElement(t.cloneNode(existing.value, true)));
2038
+ existing.value = injected;
2039
+ return true;
2040
+ }
2041
+ }
2042
+ return false;
2043
+ }
2044
+ function applyWevuDefaultsToOptionsObject(optionsObject, defaults) {
2045
+ let changed = false;
2046
+ for (const [key, value] of Object.entries(defaults)) {
2047
+ if (key === "setData" || key === "options") {
2048
+ changed = mergeNestedDefaults(optionsObject, key, value) || changed;
2049
+ continue;
2050
+ }
2051
+ if (value === void 0 || getObjectPropertyByKey$1(optionsObject, key)) continue;
2052
+ optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(value)));
2053
+ changed = true;
2054
+ }
2055
+ return changed;
2056
+ }
2057
+ function ensureNestedOptionValue(optionsObject, key, nestedKey, value) {
2058
+ const existing = getObjectPropertyByKey$1(optionsObject, key);
2059
+ if (!existing) {
2060
+ const nested = t.objectExpression([t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value))]);
2061
+ optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), nested));
2062
+ return true;
2063
+ }
2064
+ if (t.isObjectExpression(existing.value)) {
2065
+ if (getObjectPropertyByKey$1(existing.value, nestedKey)) return false;
2066
+ existing.value.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value)));
2067
+ return true;
2068
+ }
2069
+ if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2070
+ existing.value = t.objectExpression([t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value)), t.spreadElement(t.cloneNode(existing.value, true))]);
2071
+ return true;
2072
+ }
2073
+ return false;
2074
+ }
2075
+ function stripVirtualHostFromDefaults(defaults) {
2076
+ const next = { ...defaults };
2077
+ const options = next.options;
2078
+ if (!isPlainRecord(options)) return next;
2079
+ if (!Object.prototype.hasOwnProperty.call(options, "virtualHost")) return next;
2080
+ const copiedOptions = { ...options };
2081
+ delete copiedOptions.virtualHost;
2082
+ if (Object.keys(copiedOptions).length > 0) next.options = copiedOptions;
2083
+ else delete next.options;
2084
+ return next;
2085
+ }
2086
+ function serializeWevuDefaults(defaults, warn) {
2087
+ const warnHandler = resolveWarnHandler(warn);
2088
+ const seen = /* @__PURE__ */ new Set();
2089
+ try {
2090
+ return JSON.stringify(defaults, (_key, value) => {
2091
+ if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") throw new TypeError("Wevu defaults 必须可被 JSON 序列化。");
2092
+ if (value && typeof value === "object") {
2093
+ if (seen.has(value)) throw new Error("Wevu defaults 不能包含循环引用。");
2094
+ seen.add(value);
2095
+ if (!Array.isArray(value) && !isPlainRecord(value)) throw new Error("Wevu defaults 只能是普通对象或数组。");
2096
+ }
2097
+ return value;
2098
+ });
2099
+ } catch (error) {
2100
+ warnHandler(`[vue] 序列化 wevu defaults 失败:${error instanceof Error ? error.message : String(error)}`);
2101
+ return;
2102
+ }
2352
2103
  }
2353
- function buildArrayMapExpression(binding, forStack, level, listId, helpers) {
2354
- const itemParam = createValidIdentifier(forStack[level].item, `__wv_item_${level}`);
2355
- const indexParam = createValidIdentifier(forStack[level].index, `__wv_index_${level}`);
2356
- const body = [];
2357
- const keyName = forStack[level].key;
2358
- if (keyName && t.isValidIdentifier(keyName) && keyName !== indexParam.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(keyName), indexParam)]));
2359
- const inner = buildForExpression(binding, forStack, level + 1, helpers);
2360
- body.push(t.returnStatement(inner));
2361
- const callback = t.arrowFunctionExpression([itemParam, indexParam], t.blockStatement(body));
2362
- return t.callExpression(t.memberExpression(listId, t.identifier("map")), [callback]);
2104
+ function insertWevuDefaultsCall(program, serializedDefaults) {
2105
+ const callStatement = t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.setWevuDefaults), [t.valueToNode(JSON.parse(serializedDefaults))]));
2106
+ let insertIndex = 0;
2107
+ while (insertIndex < program.body.length && t.isImportDeclaration(program.body[insertIndex])) insertIndex += 1;
2108
+ program.body.splice(insertIndex, 0, callStatement);
2363
2109
  }
2364
- function buildObjectMapExpression(binding, forStack, level, listId, helpers) {
2365
- const resId = t.identifier(`__wv_res_${level}`);
2366
- const keysId = t.identifier(`__wv_keys_${level}`);
2367
- const loopIndexId = t.identifier(`__wv_i_${level}`);
2368
- const keyId = t.identifier(`__wv_key_${level}`);
2369
- const itemId = t.identifier(`__wv_item_${level}`);
2370
- const itemAlias = forStack[level].item;
2371
- const indexAlias = forStack[level].index;
2372
- const keyAlias = forStack[level].key;
2373
- const hasKeyAlias = Boolean(keyAlias && t.isValidIdentifier(keyAlias));
2374
- const loopBody = [t.variableDeclaration("const", [t.variableDeclarator(keyId, t.memberExpression(keysId, loopIndexId, true))]), t.variableDeclaration("const", [t.variableDeclarator(itemId, t.memberExpression(listId, keyId, true))])];
2375
- if (itemAlias && t.isValidIdentifier(itemAlias) && itemAlias !== itemId.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(itemAlias), itemId)]));
2376
- if (hasKeyAlias && keyAlias && keyAlias !== keyId.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(keyAlias), keyId)]));
2377
- if (indexAlias && t.isValidIdentifier(indexAlias)) {
2378
- const source = hasKeyAlias ? loopIndexId : keyId;
2379
- if (indexAlias !== source.name) loopBody.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(indexAlias), source)]));
2110
+ function applyWevuDefaultsToComponentOptions(params) {
2111
+ const { componentExpr, parsedWevuDefaults, options } = params;
2112
+ let changed = false;
2113
+ if (options?.isApp && parsedWevuDefaults.app && Object.keys(parsedWevuDefaults.app).length > 0) changed = applyWevuDefaultsToOptionsObject(componentExpr, parsedWevuDefaults.app) || changed;
2114
+ if (!options?.isApp && parsedWevuDefaults.component && Object.keys(parsedWevuDefaults.component).length > 0) {
2115
+ const componentDefaults = options?.isPage ? stripVirtualHostFromDefaults(parsedWevuDefaults.component) : parsedWevuDefaults.component;
2116
+ if (Object.keys(componentDefaults).length > 0) changed = applyWevuDefaultsToOptionsObject(componentExpr, componentDefaults) || changed;
2380
2117
  }
2381
- const inner = buildForExpression(binding, forStack, level + 1, helpers);
2382
- loopBody.push(t.expressionStatement(t.assignmentExpression("=", t.memberExpression(resId, keyId, true), inner)));
2383
- const loop = t.forStatement(t.variableDeclaration("let", [t.variableDeclarator(loopIndexId, t.numericLiteral(0))]), t.binaryExpression("<", loopIndexId, t.memberExpression(keysId, t.identifier("length"))), t.updateExpression("++", loopIndexId), t.blockStatement(loopBody));
2384
- return t.blockStatement([
2385
- t.variableDeclaration("const", [t.variableDeclarator(resId, t.objectExpression([]))]),
2386
- t.variableDeclaration("const", [t.variableDeclarator(keysId, t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("keys")), [listId]))]),
2387
- loop,
2388
- t.returnStatement(resId)
2389
- ]);
2118
+ const componentOptionDefaults = parsedWevuDefaults.component?.options;
2119
+ if (options?.isPage && isPlainRecord(componentOptionDefaults) && componentOptionDefaults.virtualHost === true) changed = ensureNestedOptionValue(componentExpr, "options", "virtualHost", false) || changed;
2120
+ return changed;
2390
2121
  }
2391
- function buildForExpression(binding, forStack, level, helpers) {
2392
- if (level >= forStack.length) return buildNormalizedExpression(binding, helpers);
2393
- const info = forStack[level];
2394
- const listId = t.identifier(`__wv_list_${level}`);
2395
- const listExp = info.listExpAst ? t.cloneNode(info.listExpAst, true) : t.arrayExpression([]);
2396
- const unrefHelper = helpers.unref ? t.cloneNode(helpers.unref) : t.identifier("unref");
2397
- const listUnrefExp = t.callExpression(unrefHelper, [listExp]);
2398
- const listDecl = t.variableDeclaration("let", [t.variableDeclarator(listId, t.arrayExpression([]))]);
2399
- const listSafeAssign = t.tryStatement(t.blockStatement([t.expressionStatement(t.assignmentExpression("=", listId, listUnrefExp))]), t.catchClause(t.identifier(`__wv_err_${level}`), t.blockStatement([t.expressionStatement(t.assignmentExpression("=", listId, t.arrayExpression([])))])), null);
2400
- const arrayCheck = t.callExpression(t.memberExpression(t.identifier("Array"), t.identifier("isArray")), [listId]);
2401
- const arrayMap = buildArrayMapExpression(binding, forStack, level, listId, helpers);
2402
- const objectCheck = t.logicalExpression("&&", t.binaryExpression("!=", listId, t.nullLiteral()), t.binaryExpression("===", t.unaryExpression("typeof", listId), t.stringLiteral("object")));
2403
- const objectBlock = buildObjectMapExpression(binding, forStack, level, listId, helpers);
2404
- const fallbackReturn = t.returnStatement(t.arrayExpression([]));
2405
- const body = t.blockStatement([
2406
- listDecl,
2407
- listSafeAssign,
2408
- t.ifStatement(arrayCheck, t.blockStatement([t.returnStatement(arrayMap)]), t.ifStatement(objectCheck, objectBlock, t.blockStatement([fallbackReturn])))
2409
- ]);
2410
- return t.callExpression(t.arrowFunctionExpression([], body), []);
2122
+ function injectWevuDefaultsForApp(params) {
2123
+ const { astProgram, options, serializedWevuDefaults } = params;
2124
+ let changed = false;
2125
+ if (options?.isApp && serializedWevuDefaults) {
2126
+ ensureRuntimeImport(astProgram, WE_VU_RUNTIME_APIS.setWevuDefaults);
2127
+ insertWevuDefaultsCall(astProgram, serializedWevuDefaults);
2128
+ changed = true;
2129
+ }
2130
+ return changed;
2411
2131
  }
2412
- function buildComputedFunctionBody(binding, helpers) {
2413
- const expr = buildForExpression(binding, binding.forStack ?? [], 0, helpers);
2414
- return t.blockStatement([t.returnStatement(expr)]);
2132
+ //#endregion
2133
+ //#region src/plugins/vue/transform/transformScript/rewrite/export.ts
2134
+ function rewriteComponentExport(params) {
2135
+ const { ast, exportPath, componentExpr, isAppFile, skipComponentTransform } = params;
2136
+ const DEFAULT_OPTIONS_IDENTIFIER = "__wevuOptions";
2137
+ if (isAppFile) {
2138
+ ensureRuntimeImport(ast.program, WE_VU_RUNTIME_APIS.createApp);
2139
+ exportPath.replaceWith(t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.createApp), [componentExpr])));
2140
+ return true;
2141
+ }
2142
+ if (skipComponentTransform) {
2143
+ exportPath.replaceWith(t.exportDefaultDeclaration(componentExpr));
2144
+ return true;
2145
+ }
2146
+ ensureRuntimeImport(ast.program, WE_VU_RUNTIME_APIS.createWevuComponent);
2147
+ exportPath.replaceWith(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(DEFAULT_OPTIONS_IDENTIFIER), componentExpr)]));
2148
+ exportPath.insertAfter(t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.createWevuComponent), [t.identifier(DEFAULT_OPTIONS_IDENTIFIER)])));
2149
+ return true;
2415
2150
  }
2416
- function buildClassStyleComputedEntries(bindings, helpers) {
2417
- const entries = [];
2418
- for (const binding of bindings) {
2419
- const key = createStaticObjectKey$1(binding.name);
2420
- const body = buildComputedFunctionBody(binding, helpers);
2421
- const fn = t.functionExpression(null, [], body);
2422
- entries.push(t.objectProperty(key, fn));
2151
+ //#endregion
2152
+ //#region src/plugins/vue/compiler/template/expression/parse.ts
2153
+ const babelExpressionCache = new LRUCache({ max: 1024 });
2154
+ new LRUCache({ max: 1024 });
2155
+ const BABEL_GENERATE_MINI_PROGRAM_OPTIONS = {
2156
+ compact: true,
2157
+ jsescOption: {
2158
+ quotes: "single",
2159
+ minimal: true
2423
2160
  }
2424
- return entries;
2161
+ };
2162
+ function generateExpression(node) {
2163
+ const { code } = generate(node, BABEL_GENERATE_MINI_PROGRAM_OPTIONS);
2164
+ return code;
2425
2165
  }
2426
- function buildClassStyleComputedObject(bindings, helpers) {
2427
- if (!bindings.length) return null;
2428
- const entries = buildClassStyleComputedEntries(bindings, helpers);
2429
- if (!entries.length) return null;
2430
- return t.objectExpression(entries);
2166
+ function parseBabelExpression(exp) {
2167
+ const cached = babelExpressionCache.get(exp);
2168
+ if (cached !== void 0) return cached === false ? null : cached;
2169
+ try {
2170
+ const stmt = parse$2(`(${exp})`, {
2171
+ sourceType: "module",
2172
+ plugins: ["typescript"]
2173
+ }).program.body[0];
2174
+ if (!stmt || !("expression" in stmt)) {
2175
+ babelExpressionCache.set(exp, false);
2176
+ return null;
2177
+ }
2178
+ const expression = stmt.expression;
2179
+ babelExpressionCache.set(exp, expression);
2180
+ return expression;
2181
+ } catch {
2182
+ babelExpressionCache.set(exp, false);
2183
+ return null;
2184
+ }
2431
2185
  }
2432
- function buildClassStyleComputedCode(bindings, helpers) {
2433
- if (!bindings.length) return null;
2434
- const obj = buildClassStyleComputedObject(bindings, {
2435
- normalizeClass: t.identifier(helpers.normalizeClassName),
2436
- normalizeStyle: t.identifier(helpers.normalizeStyleName),
2437
- unref: t.identifier(helpers.unrefName ?? "unref")
2438
- });
2439
- if (!obj) return null;
2440
- const { code } = generate(obj, { compact: true });
2441
- return code;
2186
+ function parseBabelExpressionFile(exp) {
2187
+ try {
2188
+ const ast = parse$2(`(${exp})`, {
2189
+ sourceType: "module",
2190
+ plugins: ["typescript"]
2191
+ });
2192
+ const stmt = ast.program.body[0];
2193
+ if (!stmt || !("expression" in stmt)) return null;
2194
+ return {
2195
+ ast,
2196
+ expression: stmt.expression
2197
+ };
2198
+ } catch {
2199
+ return null;
2200
+ }
2442
2201
  }
2443
-
2444
2202
  //#endregion
2445
- //#region src/plugins/vue/transform/transformScript/utils.ts
2446
- function isPlainRecord(value) {
2447
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
2448
- const proto = Object.getPrototypeOf(value);
2449
- return proto === null || proto === Object.prototype;
2450
- }
2451
- function isStaticObjectKeyMatch(key, expected) {
2452
- if (t.isIdentifier(key)) return key.name === expected;
2453
- if (t.isStringLiteral(key)) return key.value === expected;
2454
- return false;
2203
+ //#region src/plugins/vue/transform/transformScript/rewrite/inlineExpressions.ts
2204
+ function buildInlineMapExpression(inlineExpressions) {
2205
+ const entries = inlineExpressions.map((entry) => {
2206
+ const keysExpr = t.arrayExpression(entry.scopeKeys.map((key) => t.stringLiteral(key)));
2207
+ const exprAst = parseBabelExpression(entry.expression) ?? t.identifier("undefined");
2208
+ const fnExpr = t.arrowFunctionExpression([
2209
+ t.identifier("ctx"),
2210
+ t.identifier("scope"),
2211
+ t.identifier("$event")
2212
+ ], exprAst);
2213
+ const entryObjProps = [t.objectProperty(t.identifier("keys"), keysExpr), t.objectProperty(t.identifier("fn"), fnExpr)];
2214
+ if (entry.indexBindings?.length) {
2215
+ const indexKeysExpr = t.arrayExpression(entry.indexBindings.map((binding) => t.stringLiteral(binding.key)));
2216
+ entryObjProps.push(t.objectProperty(t.identifier("indexKeys"), indexKeysExpr));
2217
+ }
2218
+ if (entry.scopeResolvers?.length) {
2219
+ const resolverMap = new Map(entry.scopeResolvers.map((item) => [item.key, item.expression]));
2220
+ const resolverExpr = t.arrayExpression(entry.scopeKeys.map((key) => {
2221
+ const source = resolverMap.get(key);
2222
+ if (!source) return t.identifier("undefined");
2223
+ return parseBabelExpression(source) ?? t.identifier("undefined");
2224
+ }));
2225
+ entryObjProps.push(t.objectProperty(t.identifier("scopeResolvers"), resolverExpr));
2226
+ }
2227
+ const entryObj = t.objectExpression(entryObjProps);
2228
+ return t.objectProperty(t.stringLiteral(entry.id), entryObj);
2229
+ });
2230
+ return t.objectExpression(entries);
2455
2231
  }
2456
- function getObjectPropertyByKey$1(node, key) {
2457
- for (const prop of node.properties) {
2458
- if (!t.isObjectProperty(prop) || prop.computed) continue;
2459
- if (isStaticObjectKeyMatch(prop.key, key)) return prop;
2232
+ function buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr) {
2233
+ const spreadSources = [];
2234
+ for (const prop of componentExpr.properties) {
2235
+ if (!t.isSpreadElement(prop) || !t.isExpression(prop.argument)) continue;
2236
+ const methodsAccess = t.optionalMemberExpression(t.cloneNode(prop.argument), t.identifier("methods"), false, true);
2237
+ spreadSources.push(t.logicalExpression("||", methodsAccess, t.objectExpression([])));
2460
2238
  }
2461
- return null;
2239
+ if (!spreadSources.length) return null;
2240
+ return t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("assign")), [
2241
+ t.objectExpression([]),
2242
+ ...spreadSources,
2243
+ t.objectExpression([t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr)])
2244
+ ]);
2462
2245
  }
2463
- function createStaticObjectKey(key) {
2464
- return t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
2246
+ function injectInlineExpressions(componentExpr, inlineExpressions) {
2247
+ if (!inlineExpressions.length) return false;
2248
+ const inlineMapExpr = buildInlineMapExpression(inlineExpressions);
2249
+ const methodsProp = getObjectPropertyByKey$1(componentExpr, "methods");
2250
+ if (!methodsProp) {
2251
+ const mergedMethods = buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr);
2252
+ if (mergedMethods) {
2253
+ componentExpr.properties.push(t.objectProperty(createStaticObjectKey("methods"), mergedMethods));
2254
+ return true;
2255
+ }
2256
+ componentExpr.properties.push(t.objectProperty(createStaticObjectKey("methods"), t.objectExpression([t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr)])));
2257
+ return true;
2258
+ }
2259
+ if (!t.isObjectExpression(methodsProp.value)) return false;
2260
+ const mapProp = getObjectPropertyByKey$1(methodsProp.value, "__weapp_vite_inline_map");
2261
+ if (!mapProp) {
2262
+ methodsProp.value.properties.push(t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr));
2263
+ return true;
2264
+ }
2265
+ if (t.isObjectExpression(mapProp.value)) {
2266
+ mapProp.value.properties.push(...inlineMapExpr.properties);
2267
+ return true;
2268
+ }
2269
+ return false;
2465
2270
  }
2466
-
2467
2271
  //#endregion
2468
- //#region src/plugins/vue/transform/transformScript/rewrite/classStyle.ts
2469
- function injectClassStyleComputed(optionsObject, bindings, warn) {
2272
+ //#region src/plugins/vue/transform/transformScript/rewrite/templateRefs.ts
2273
+ function buildTemplateRefEntry(binding) {
2274
+ const props = [t.objectProperty(t.identifier("selector"), t.stringLiteral(binding.selector)), t.objectProperty(t.identifier("inFor"), t.booleanLiteral(binding.inFor))];
2275
+ if (binding.name) props.push(t.objectProperty(t.identifier("name"), t.stringLiteral(binding.name)));
2276
+ if (binding.expAst) {
2277
+ const body = t.blockStatement([t.returnStatement(t.cloneNode(binding.expAst, true))]);
2278
+ props.push(t.objectProperty(t.identifier("get"), t.functionExpression(null, [], body)));
2279
+ }
2280
+ if (binding.kind) props.push(t.objectProperty(t.identifier("kind"), t.stringLiteral(binding.kind)));
2281
+ return t.objectExpression(props);
2282
+ }
2283
+ function injectTemplateRefs(optionsObject, bindings, warn) {
2470
2284
  if (!bindings.length) return false;
2471
2285
  const warnHandler = resolveWarnHandler(warn);
2472
- const entries = buildClassStyleComputedEntries(bindings, {
2473
- normalizeClass: t.identifier("__wevuNormalizeClass"),
2474
- normalizeStyle: t.identifier("__wevuNormalizeStyle"),
2475
- unref: t.identifier("__wevuUnref")
2476
- });
2477
- if (!entries.length) return false;
2478
- const computedProp = getObjectPropertyByKey$1(optionsObject, "computed");
2479
- if (!computedProp) {
2480
- optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey("computed"), t.objectExpression(entries)));
2286
+ const entries = bindings.map((binding) => buildTemplateRefEntry(binding));
2287
+ const refsArray = t.arrayExpression(entries);
2288
+ const key = createStaticObjectKey("__wevuTemplateRefs");
2289
+ const existing = getObjectPropertyByKey$1(optionsObject, "__wevuTemplateRefs");
2290
+ if (!existing) {
2291
+ optionsObject.properties.push(t.objectProperty(key, refsArray));
2481
2292
  return true;
2482
2293
  }
2483
- if (t.isObjectExpression(computedProp.value)) {
2484
- computedProp.value.properties.push(...entries);
2294
+ if (t.isArrayExpression(existing.value)) {
2295
+ existing.value.elements.push(...entries);
2485
2296
  return true;
2486
2297
  }
2487
- if (t.isIdentifier(computedProp.value) || t.isMemberExpression(computedProp.value)) {
2488
- computedProp.value = t.objectExpression([...entries, t.spreadElement(t.cloneNode(computedProp.value, true))]);
2298
+ if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2299
+ existing.value = t.arrayExpression([...entries, t.spreadElement(t.cloneNode(existing.value, true))]);
2489
2300
  return true;
2490
2301
  }
2491
- warnHandler("无法自动注入 class/style 计算属性,请手动合并 computed。");
2302
+ warnHandler("无法自动注入 template ref 元数据,请手动合并 __wevuTemplateRefs。");
2492
2303
  return false;
2493
2304
  }
2494
- function ensureClassStyleRuntimeImports(program) {
2495
- ensureRuntimeImport(program, "normalizeClass", "__wevuNormalizeClass");
2496
- ensureRuntimeImport(program, "normalizeStyle", "__wevuNormalizeStyle");
2497
- ensureRuntimeImport(program, "unref", "__wevuUnref");
2498
- }
2499
-
2500
2305
  //#endregion
2501
- //#region src/plugins/vue/transform/transformScript/rewrite/defaults.ts
2502
- function mergePlainDefaultsIntoObjectExpression(target, defaults) {
2503
- const entries = Object.entries(defaults);
2504
- if (!entries.length) return false;
2505
- let changed = false;
2506
- const injectedProps = [];
2507
- for (const [key, value] of entries) {
2508
- if (getObjectPropertyByKey$1(target, key)) continue;
2509
- injectedProps.push(t.objectProperty(createStaticObjectKey(key), t.valueToNode(value)));
2306
+ //#region src/plugins/vue/transform/transformScript/rewrite/index.ts
2307
+ function hasStaticProperty(target, keyName) {
2308
+ for (const prop of target.properties) {
2309
+ if (prop.type !== "ObjectProperty" && prop.type !== "ObjectMethod" || prop.computed) continue;
2310
+ const key = prop.key;
2311
+ if (key.type === "Identifier" && key.name === keyName) return true;
2312
+ if (key.type === "StringLiteral" && key.value === keyName) return true;
2510
2313
  }
2511
- if (!injectedProps.length) return false;
2512
- target.properties.splice(0, 0, ...injectedProps);
2513
- changed = true;
2514
- return changed;
2314
+ return false;
2515
2315
  }
2516
- function mergeNestedDefaults(optionsObject, key, defaultsValue) {
2517
- if (!isPlainRecord(defaultsValue)) {
2518
- if (defaultsValue === void 0) return false;
2519
- if (getObjectPropertyByKey$1(optionsObject, key)) return false;
2520
- optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(defaultsValue)));
2521
- return true;
2316
+ function isObjectAssignCall(node) {
2317
+ const callee = node.callee;
2318
+ return t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "Object" }) && t.isIdentifier(callee.property, { name: "assign" });
2319
+ }
2320
+ function unwrapTypeLikeExpression(node) {
2321
+ if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapTypeLikeExpression(node.expression);
2322
+ if (t.isParenthesizedExpression(node)) return unwrapTypeLikeExpression(node.expression);
2323
+ return node;
2324
+ }
2325
+ function resolveObjectExpressionFromProgram(program, name) {
2326
+ for (let index = program.body.length - 1; index >= 0; index -= 1) {
2327
+ const statement = program.body[index];
2328
+ if (!t.isVariableDeclaration(statement)) continue;
2329
+ for (const declarator of statement.declarations) {
2330
+ if (!t.isIdentifier(declarator.id, { name }) || !declarator.init || !t.isExpression(declarator.init)) continue;
2331
+ const normalized = unwrapTypeLikeExpression(declarator.init);
2332
+ if (t.isObjectExpression(normalized)) return normalized;
2333
+ if (t.isCallExpression(normalized) && isObjectAssignCall(normalized)) {
2334
+ const lastArg = normalized.arguments[normalized.arguments.length - 1];
2335
+ if (lastArg && !t.isSpreadElement(lastArg) && t.isExpression(lastArg)) {
2336
+ const lastNormalized = unwrapTypeLikeExpression(lastArg);
2337
+ if (t.isObjectExpression(lastNormalized)) return lastNormalized;
2338
+ }
2339
+ }
2340
+ }
2522
2341
  }
2523
- const existing = getObjectPropertyByKey$1(optionsObject, key);
2524
- if (!existing) {
2525
- optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(defaultsValue)));
2526
- return true;
2342
+ return null;
2343
+ }
2344
+ function hasStaticPropertyWithSpreads(target, keyName, program, visited = /* @__PURE__ */ new Set()) {
2345
+ if (hasStaticProperty(target, keyName)) return true;
2346
+ for (const prop of target.properties) {
2347
+ if (!t.isSpreadElement(prop)) continue;
2348
+ const spreadArg = prop.argument;
2349
+ if (t.isObjectExpression(spreadArg) && hasStaticPropertyWithSpreads(spreadArg, keyName, program, visited)) return true;
2350
+ if (!t.isIdentifier(spreadArg) || visited.has(spreadArg.name)) continue;
2351
+ visited.add(spreadArg.name);
2352
+ const resolved = resolveObjectExpressionFromProgram(program, spreadArg.name);
2353
+ if (resolved && hasStaticPropertyWithSpreads(resolved, keyName, program, visited)) return true;
2527
2354
  }
2528
- if (t.isObjectExpression(existing.value)) return mergePlainDefaultsIntoObjectExpression(existing.value, defaultsValue);
2529
- if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2530
- const injected = t.valueToNode(defaultsValue);
2531
- if (t.isObjectExpression(injected)) {
2532
- injected.properties.push(t.spreadElement(t.cloneNode(existing.value, true)));
2533
- existing.value = injected;
2534
- return true;
2355
+ return false;
2356
+ }
2357
+ function hasStaticPropertyInComponentExpression(componentExpr, keyName, program) {
2358
+ const normalized = unwrapTypeLikeExpression(componentExpr);
2359
+ if (t.isObjectExpression(normalized)) return hasStaticPropertyWithSpreads(normalized, keyName, program);
2360
+ if (!t.isCallExpression(normalized) || !isObjectAssignCall(normalized)) return false;
2361
+ for (const arg of normalized.arguments) {
2362
+ if (t.isSpreadElement(arg) || !t.isExpression(arg)) continue;
2363
+ const expr = unwrapTypeLikeExpression(arg);
2364
+ if (t.isObjectExpression(expr) && hasStaticPropertyWithSpreads(expr, keyName, program)) return true;
2365
+ if (t.isIdentifier(expr)) {
2366
+ const resolved = resolveObjectExpressionFromProgram(program, expr.name);
2367
+ if (resolved && hasStaticPropertyWithSpreads(resolved, keyName, program, new Set([expr.name]))) return true;
2535
2368
  }
2536
2369
  }
2537
2370
  return false;
2538
2371
  }
2539
- function applyWevuDefaultsToOptionsObject(optionsObject, defaults) {
2540
- let changed = false;
2541
- for (const [key, value] of Object.entries(defaults)) {
2542
- if (key === "setData" || key === "options") {
2543
- changed = mergeNestedDefaults(optionsObject, key, value) || changed;
2372
+ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializedWevuDefaults, parsedWevuDefaults) {
2373
+ if (!state.defaultExportPath) return false;
2374
+ const warn = resolveWarnHandler(options?.warn);
2375
+ let transformed = false;
2376
+ const exportPath = state.defaultExportPath;
2377
+ const componentExpr = resolveComponentExpression(exportPath.node.declaration, state.defineComponentDecls, state.defineComponentAliases);
2378
+ const componentOptionsObject = resolveComponentOptionsObject(componentExpr);
2379
+ const hasPageMarker = componentExpr ? hasStaticPropertyInComponentExpression(componentExpr, "__wevu_isPage", ast.program) : false;
2380
+ if (componentOptionsObject && options?.isPage && !options?.isApp && !hasPageMarker) {
2381
+ componentOptionsObject.properties.splice(0, 0, t.objectProperty(t.identifier("__wevu_isPage"), t.booleanLiteral(true)));
2382
+ transformed = true;
2383
+ }
2384
+ if (componentOptionsObject && enabledPageFeatures.size) transformed = injectWevuPageFeatureFlagsIntoOptionsObject(componentOptionsObject, enabledPageFeatures) || transformed;
2385
+ if (componentOptionsObject && parsedWevuDefaults) transformed = applyWevuDefaultsToComponentOptions({
2386
+ componentExpr: componentOptionsObject,
2387
+ parsedWevuDefaults,
2388
+ options
2389
+ }) || transformed;
2390
+ const classStyleBindings = options?.classStyleBindings ?? [];
2391
+ if (classStyleBindings.length) if (componentOptionsObject) {
2392
+ ensureClassStyleRuntimeImports(ast.program);
2393
+ transformed = injectClassStyleComputed(componentOptionsObject, classStyleBindings, warn) || transformed;
2394
+ } else warn("无法自动注入 class/style 计算属性:组件选项不是对象字面量。");
2395
+ const templateRefs = options?.templateRefs ?? [];
2396
+ if (templateRefs.length) if (componentOptionsObject) transformed = injectTemplateRefs(componentOptionsObject, templateRefs, warn) || transformed;
2397
+ else warn("无法自动注入 template ref 元数据:组件选项不是对象字面量。");
2398
+ const inlineExpressions = options?.inlineExpressions ?? [];
2399
+ if (inlineExpressions.length) if (componentOptionsObject) {
2400
+ const injected = injectInlineExpressions(componentOptionsObject, inlineExpressions);
2401
+ if (!injected) warn("无法自动注入内联表达式元数据:methods 不是对象字面量。");
2402
+ transformed = injected || transformed;
2403
+ } else warn("无法自动注入内联表达式元数据:组件选项不是对象字面量。");
2404
+ if (componentExpr) {
2405
+ if (options?.isApp) transformed = injectWevuDefaultsForApp({
2406
+ astProgram: ast.program,
2407
+ options,
2408
+ serializedWevuDefaults
2409
+ }) || transformed;
2410
+ transformed = rewriteComponentExport({
2411
+ ast,
2412
+ exportPath,
2413
+ componentExpr,
2414
+ isAppFile: !!options?.isApp,
2415
+ skipComponentTransform: options?.skipComponentTransform
2416
+ }) || transformed;
2417
+ }
2418
+ return transformed;
2419
+ }
2420
+ //#endregion
2421
+ //#region src/plugins/vue/transform/transformScript/index.ts
2422
+ /**
2423
+ * 转换 Vue SFC 脚本:处理宏、导入、默认导出与 wevu 相关注入。
2424
+ */
2425
+ function transformScript(source, options) {
2426
+ const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
2427
+ const warn = resolveWarnHandler(options?.warn);
2428
+ const state = {
2429
+ transformed: false,
2430
+ defineComponentAliases: new Set([WE_VU_RUNTIME_APIS.defineComponent, "_defineComponent"]),
2431
+ defineComponentDecls: /* @__PURE__ */ new Map(),
2432
+ defaultExportPath: null
2433
+ };
2434
+ const enabledPageFeatures = options?.isPage ? collectWevuPageFeatureFlags(ast) : /* @__PURE__ */ new Set();
2435
+ const serializedWevuDefaults = options?.wevuDefaults && Object.keys(options.wevuDefaults).length > 0 ? serializeWevuDefaults(options.wevuDefaults, warn) : void 0;
2436
+ const parsedWevuDefaults = serializedWevuDefaults ? JSON.parse(serializedWevuDefaults) : void 0;
2437
+ traverse(ast, vueSfcTransformPlugin().visitor);
2438
+ traverse(ast, {
2439
+ ...createMacroVisitors(state),
2440
+ ...createImportVisitors(ast.program, state),
2441
+ ...createCollectVisitors(state)
2442
+ });
2443
+ if (options?.templateComponentMeta) state.transformed = injectTemplateComponentMeta(ast, options.templateComponentMeta) || state.transformed;
2444
+ state.transformed = rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializedWevuDefaults, parsedWevuDefaults) || state.transformed;
2445
+ if (!state.transformed) return {
2446
+ code: source,
2447
+ transformed: false
2448
+ };
2449
+ return {
2450
+ code: generate(ast, { retainLines: true }).code,
2451
+ transformed: state.transformed
2452
+ };
2453
+ }
2454
+ //#endregion
2455
+ //#region src/plugins/vue/compiler/template/expression/wxml.ts
2456
+ function templateLiteralToConcat(node) {
2457
+ const segments = [];
2458
+ node.quasis.forEach((quasi, index) => {
2459
+ const cooked = quasi.value.cooked ?? quasi.value.raw ?? "";
2460
+ if (cooked) segments.push(t.stringLiteral(cooked));
2461
+ if (index < node.expressions.length) {
2462
+ let inner = node.expressions[index];
2463
+ if (t.isTemplateLiteral(inner)) inner = templateLiteralToConcat(inner);
2464
+ segments.push(inner);
2465
+ }
2466
+ });
2467
+ if (segments.length === 0) return t.stringLiteral("");
2468
+ if (segments.length === 1) return segments[0];
2469
+ return segments.reduce((acc, cur) => t.binaryExpression("+", acc, cur));
2470
+ }
2471
+ function isOptionalChainNode(node) {
2472
+ return Boolean(node && (t.isOptionalMemberExpression(node) || t.isOptionalCallExpression(node)));
2473
+ }
2474
+ function collectOptionalChain(node) {
2475
+ const operations = [];
2476
+ let current = node;
2477
+ while (isOptionalChainNode(current)) {
2478
+ if (t.isOptionalMemberExpression(current)) {
2479
+ operations.push({
2480
+ type: "member",
2481
+ optional: current.optional === true,
2482
+ computed: current.computed,
2483
+ property: t.cloneNode(current.property)
2484
+ });
2485
+ current = current.object;
2544
2486
  continue;
2545
2487
  }
2546
- if (value === void 0 || getObjectPropertyByKey$1(optionsObject, key)) continue;
2547
- optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), t.valueToNode(value)));
2548
- changed = true;
2488
+ operations.push({
2489
+ type: "call",
2490
+ optional: current.optional === true,
2491
+ args: current.arguments.map((arg) => t.cloneNode(arg))
2492
+ });
2493
+ current = current.callee;
2549
2494
  }
2550
- return changed;
2495
+ if (!t.isExpression(current)) return null;
2496
+ return {
2497
+ base: t.cloneNode(current),
2498
+ operations: operations.reverse()
2499
+ };
2551
2500
  }
2552
- function ensureNestedOptionValue(optionsObject, key, nestedKey, value) {
2553
- const existing = getObjectPropertyByKey$1(optionsObject, key);
2554
- if (!existing) {
2555
- const nested = t.objectExpression([t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value))]);
2556
- optionsObject.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(key), nested));
2557
- return true;
2558
- }
2559
- if (t.isObjectExpression(existing.value)) {
2560
- if (getObjectPropertyByKey$1(existing.value, nestedKey)) return false;
2561
- existing.value.properties.splice(0, 0, t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value)));
2562
- return true;
2501
+ function applyOptionalChainOperation(base, operation) {
2502
+ if (operation.type === "member") return t.memberExpression(base, t.cloneNode(operation.property), operation.computed);
2503
+ return t.callExpression(base, operation.args.map((arg) => t.cloneNode(arg)));
2504
+ }
2505
+ function lowerOptionalChain(node) {
2506
+ const chain = collectOptionalChain(node);
2507
+ if (!chain) return t.cloneNode(node);
2508
+ const segments = [chain.base];
2509
+ for (const operation of chain.operations) {
2510
+ const currentBase = t.cloneNode(segments[segments.length - 1]);
2511
+ segments.push(applyOptionalChainOperation(currentBase, operation));
2563
2512
  }
2564
- if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2565
- existing.value = t.objectExpression([t.objectProperty(createStaticObjectKey(nestedKey), t.valueToNode(value)), t.spreadElement(t.cloneNode(existing.value, true))]);
2566
- return true;
2513
+ let lowered = t.cloneNode(segments[segments.length - 1]);
2514
+ for (let index = chain.operations.length - 1; index >= 0; index--) {
2515
+ if (!chain.operations[index].optional) continue;
2516
+ lowered = t.conditionalExpression(t.binaryExpression("==", t.cloneNode(segments[index]), t.nullLiteral()), t.identifier("undefined"), lowered);
2567
2517
  }
2568
- return false;
2569
- }
2570
- function stripVirtualHostFromDefaults(defaults) {
2571
- const next = { ...defaults };
2572
- const options = next.options;
2573
- if (!isPlainRecord(options)) return next;
2574
- if (!Object.prototype.hasOwnProperty.call(options, "virtualHost")) return next;
2575
- const copiedOptions = { ...options };
2576
- delete copiedOptions.virtualHost;
2577
- if (Object.keys(copiedOptions).length > 0) next.options = copiedOptions;
2578
- else delete next.options;
2579
- return next;
2518
+ return lowered;
2580
2519
  }
2581
- function serializeWevuDefaults(defaults, warn) {
2582
- const warnHandler = resolveWarnHandler(warn);
2583
- const seen = /* @__PURE__ */ new Set();
2520
+ function normalizeWxmlExpression(exp) {
2521
+ if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.")) return exp;
2584
2522
  try {
2585
- return JSON.stringify(defaults, (_key, value) => {
2586
- if (typeof value === "function" || typeof value === "symbol" || typeof value === "bigint") throw new TypeError("Wevu defaults 必须可被 JSON 序列化。");
2587
- if (value && typeof value === "object") {
2588
- if (seen.has(value)) throw new Error("Wevu defaults 不能包含循环引用。");
2589
- seen.add(value);
2590
- if (!Array.isArray(value) && !isPlainRecord(value)) throw new Error("Wevu defaults 只能是普通对象或数组。");
2523
+ const ast = parse$2(`(${exp})`, {
2524
+ sourceType: "module",
2525
+ plugins: ["typescript"]
2526
+ });
2527
+ const stmt = ast.program.body[0];
2528
+ if (!stmt || !("expression" in stmt)) return exp;
2529
+ traverse(ast, {
2530
+ OptionalMemberExpression: { exit(path) {
2531
+ if (isOptionalChainNode(path.parentPath.node)) return;
2532
+ path.replaceWith(lowerOptionalChain(path.node));
2533
+ path.skip();
2534
+ } },
2535
+ OptionalCallExpression: { exit(path) {
2536
+ if (isOptionalChainNode(path.parentPath.node)) return;
2537
+ path.replaceWith(lowerOptionalChain(path.node));
2538
+ path.skip();
2539
+ } },
2540
+ LogicalExpression(path) {
2541
+ if (path.node.operator !== "??") return;
2542
+ const left = path.node.left;
2543
+ const right = path.node.right;
2544
+ const test = t.binaryExpression("!=", t.cloneNode(left), t.nullLiteral());
2545
+ path.replaceWith(t.conditionalExpression(test, t.cloneNode(left), t.cloneNode(right)));
2546
+ path.skip();
2547
+ },
2548
+ TemplateLiteral(path) {
2549
+ if (t.isTaggedTemplateExpression(path.parent)) return;
2550
+ path.replaceWith(templateLiteralToConcat(path.node));
2591
2551
  }
2592
- return value;
2593
2552
  });
2594
- } catch (error) {
2595
- warnHandler(`[vue] 序列化 wevu defaults 失败:${error instanceof Error ? error.message : String(error)}`);
2596
- return;
2553
+ const normalized = stmt.expression;
2554
+ return generateExpression(normalized);
2555
+ } catch {
2556
+ if (exp.startsWith("`") && exp.endsWith("`")) {
2557
+ let rewritten = `'${exp.slice(1, -1).replace(/\$\{([^}]+)\}/g, "' + ($1) + '")}'`;
2558
+ rewritten = rewritten.replace(/'\s*\+\s*''/g, "'").replace(/''\s*\+\s*'/g, "'");
2559
+ rewritten = rewritten.replace(/^\s*''\s*\+\s*/g, "").replace(/\s*\+\s*''\s*$/g, "");
2560
+ return rewritten;
2561
+ }
2562
+ return exp;
2597
2563
  }
2598
2564
  }
2599
- function insertWevuDefaultsCall(program, serializedDefaults) {
2600
- const callStatement = t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.setWevuDefaults), [t.valueToNode(JSON.parse(serializedDefaults))]));
2601
- let insertIndex = 0;
2602
- while (insertIndex < program.body.length && t.isImportDeclaration(program.body[insertIndex])) insertIndex += 1;
2603
- program.body.splice(insertIndex, 0, callStatement);
2565
+ //#endregion
2566
+ //#region src/plugins/jsx/compileJsx/ast.ts
2567
+ const ESCAPED_TEXT_RE = /[&<>]/g;
2568
+ const ESCAPED_ATTR_RE = /[&"<>]/g;
2569
+ const ESCAPED_TEXT_MAP = {
2570
+ "&": "&amp;",
2571
+ "<": "&lt;",
2572
+ ">": "&gt;"
2573
+ };
2574
+ const ESCAPED_ATTR_MAP = {
2575
+ "&": "&amp;",
2576
+ "\"": "&quot;",
2577
+ "<": "&lt;",
2578
+ ">": "&gt;"
2579
+ };
2580
+ function escapeText(value) {
2581
+ return value.replace(ESCAPED_TEXT_RE, (ch) => ESCAPED_TEXT_MAP[ch] || ch);
2604
2582
  }
2605
- function applyWevuDefaultsToComponentOptions(params) {
2606
- const { componentExpr, parsedWevuDefaults, options } = params;
2607
- let changed = false;
2608
- if (options?.isApp && parsedWevuDefaults.app && Object.keys(parsedWevuDefaults.app).length > 0) changed = applyWevuDefaultsToOptionsObject(componentExpr, parsedWevuDefaults.app) || changed;
2609
- if (!options?.isApp && parsedWevuDefaults.component && Object.keys(parsedWevuDefaults.component).length > 0) {
2610
- const componentDefaults = options?.isPage ? stripVirtualHostFromDefaults(parsedWevuDefaults.component) : parsedWevuDefaults.component;
2611
- if (Object.keys(componentDefaults).length > 0) changed = applyWevuDefaultsToOptionsObject(componentExpr, componentDefaults) || changed;
2612
- }
2613
- const componentOptionDefaults = parsedWevuDefaults.component?.options;
2614
- if (options?.isPage && isPlainRecord(componentOptionDefaults) && componentOptionDefaults.virtualHost === true) changed = ensureNestedOptionValue(componentExpr, "options", "virtualHost", false) || changed;
2615
- return changed;
2583
+ function escapeAttr(value) {
2584
+ return value.replace(ESCAPED_ATTR_RE, (ch) => ESCAPED_ATTR_MAP[ch] || ch);
2616
2585
  }
2617
- function injectWevuDefaultsForApp(params) {
2618
- const { astProgram, options, serializedWevuDefaults } = params;
2619
- let changed = false;
2620
- if (options?.isApp && serializedWevuDefaults) {
2621
- ensureRuntimeImport(astProgram, WE_VU_RUNTIME_APIS.setWevuDefaults);
2622
- insertWevuDefaultsCall(astProgram, serializedWevuDefaults);
2623
- changed = true;
2624
- }
2625
- return changed;
2586
+ function normalizeJsxText(value) {
2587
+ return value.replace(/\s+/g, " ");
2626
2588
  }
2627
-
2628
- //#endregion
2629
- //#region src/plugins/vue/transform/transformScript/rewrite/export.ts
2630
- function rewriteComponentExport(params) {
2631
- const { ast, exportPath, componentExpr, isAppFile, skipComponentTransform } = params;
2632
- const DEFAULT_OPTIONS_IDENTIFIER = "__wevuOptions";
2633
- if (isAppFile) {
2634
- ensureRuntimeImport(ast.program, WE_VU_RUNTIME_APIS.createApp);
2635
- exportPath.replaceWith(t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.createApp), [componentExpr])));
2636
- return true;
2637
- }
2638
- if (skipComponentTransform) {
2639
- exportPath.replaceWith(t.exportDefaultDeclaration(componentExpr));
2640
- return true;
2641
- }
2642
- ensureRuntimeImport(ast.program, WE_VU_RUNTIME_APIS.createWevuComponent);
2643
- exportPath.replaceWith(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(DEFAULT_OPTIONS_IDENTIFIER), componentExpr)]));
2644
- exportPath.insertAfter(t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.createWevuComponent), [t.identifier(DEFAULT_OPTIONS_IDENTIFIER)])));
2645
- return true;
2589
+ function printExpression(exp) {
2590
+ return generate(exp).code;
2646
2591
  }
2647
-
2648
- //#endregion
2649
- //#region src/plugins/vue/transform/transformScript/rewrite/inlineExpressions.ts
2650
- function buildInlineMapExpression(inlineExpressions) {
2651
- const entries = inlineExpressions.map((entry) => {
2652
- const keysExpr = t.arrayExpression(entry.scopeKeys.map((key) => t.stringLiteral(key)));
2653
- const exprAst = parseBabelExpression(entry.expression) ?? t.identifier("undefined");
2654
- const fnExpr = t.arrowFunctionExpression([
2655
- t.identifier("ctx"),
2656
- t.identifier("scope"),
2657
- t.identifier("$event")
2658
- ], exprAst);
2659
- const entryObjProps = [t.objectProperty(t.identifier("keys"), keysExpr), t.objectProperty(t.identifier("fn"), fnExpr)];
2660
- if (entry.indexBindings?.length) {
2661
- const indexKeysExpr = t.arrayExpression(entry.indexBindings.map((binding) => t.stringLiteral(binding.key)));
2662
- entryObjProps.push(t.objectProperty(t.identifier("indexKeys"), indexKeysExpr));
2592
+ function unwrapTsExpression$2(exp) {
2593
+ let current = exp;
2594
+ while (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current) || t.isParenthesizedExpression(current) || t.isTSInstantiationExpression(current)) {
2595
+ if (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current)) {
2596
+ current = current.expression;
2597
+ continue;
2663
2598
  }
2664
- if (entry.scopeResolvers?.length) {
2665
- const resolverMap = new Map(entry.scopeResolvers.map((item) => [item.key, item.expression]));
2666
- const resolverExpr = t.arrayExpression(entry.scopeKeys.map((key) => {
2667
- const source = resolverMap.get(key);
2668
- if (!source) return t.identifier("undefined");
2669
- return parseBabelExpression(source) ?? t.identifier("undefined");
2670
- }));
2671
- entryObjProps.push(t.objectProperty(t.identifier("scopeResolvers"), resolverExpr));
2599
+ if (t.isParenthesizedExpression(current)) {
2600
+ current = current.expression;
2601
+ continue;
2672
2602
  }
2673
- const entryObj = t.objectExpression(entryObjProps);
2674
- return t.objectProperty(t.stringLiteral(entry.id), entryObj);
2675
- });
2676
- return t.objectExpression(entries);
2603
+ if (t.isTSInstantiationExpression(current)) current = current.expression;
2604
+ }
2605
+ return current;
2677
2606
  }
2678
- function buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr) {
2679
- const spreadSources = [];
2680
- for (const prop of componentExpr.properties) {
2681
- if (!t.isSpreadElement(prop) || !t.isExpression(prop.argument)) continue;
2682
- const methodsAccess = t.optionalMemberExpression(t.cloneNode(prop.argument), t.identifier("methods"), false, true);
2683
- spreadSources.push(t.logicalExpression("||", methodsAccess, t.objectExpression([])));
2607
+ function normalizeInterpolationExpression(exp) {
2608
+ return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
2609
+ }
2610
+ function renderMustache$1(expression, context) {
2611
+ return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
2612
+ }
2613
+ function pushScope$1(context, names) {
2614
+ for (const name of names) {
2615
+ if (!name) continue;
2616
+ context.scopeStack.push(name);
2684
2617
  }
2685
- if (!spreadSources.length) return null;
2686
- return t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("assign")), [
2687
- t.objectExpression([]),
2688
- ...spreadSources,
2689
- t.objectExpression([t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr)])
2690
- ]);
2691
2618
  }
2692
- function injectInlineExpressions(componentExpr, inlineExpressions) {
2693
- if (!inlineExpressions.length) return false;
2694
- const inlineMapExpr = buildInlineMapExpression(inlineExpressions);
2695
- const methodsProp = getObjectPropertyByKey$1(componentExpr, "methods");
2696
- if (!methodsProp) {
2697
- const mergedMethods = buildMethodsMergeFromSpreadSources(componentExpr, inlineMapExpr);
2698
- if (mergedMethods) {
2699
- componentExpr.properties.push(t.objectProperty(createStaticObjectKey("methods"), mergedMethods));
2700
- return true;
2619
+ function popScope$1(context, count) {
2620
+ for (let i = 0; i < count; i += 1) context.scopeStack.pop();
2621
+ }
2622
+ function collectExpressionScopeBindings(exp, context) {
2623
+ const localSet = new Set(context.scopeStack);
2624
+ if (!localSet.size) return [];
2625
+ const used = [];
2626
+ const usedSet = /* @__PURE__ */ new Set();
2627
+ traverse(t.file(t.program([t.expressionStatement(t.cloneNode(exp, true))])), { Identifier(path) {
2628
+ if (!path.isReferencedIdentifier()) return;
2629
+ const name = path.node.name;
2630
+ if (!localSet.has(name)) return;
2631
+ if (path.scope.hasBinding(name)) return;
2632
+ if (usedSet.has(name)) return;
2633
+ usedSet.add(name);
2634
+ used.push(name);
2635
+ } });
2636
+ return used;
2637
+ }
2638
+ function registerInlineExpression$1(exp, context) {
2639
+ const scopeKeys = collectExpressionScopeBindings(exp, context);
2640
+ const id = `__wv_inline_${context.inlineExpressionSeed++}`;
2641
+ context.inlineExpressions.push({
2642
+ id,
2643
+ expression: printExpression(exp),
2644
+ scopeKeys
2645
+ });
2646
+ return {
2647
+ id,
2648
+ scopeKeys
2649
+ };
2650
+ }
2651
+ function toStaticObjectKey(key) {
2652
+ if (t.isIdentifier(key)) return key.name;
2653
+ if (t.isStringLiteral(key)) return key.value;
2654
+ return null;
2655
+ }
2656
+ function getObjectPropertyByKey(node, key) {
2657
+ for (const prop of node.properties) {
2658
+ if (t.isObjectMethod(prop)) {
2659
+ if (toStaticObjectKey(prop.key) === key) return prop;
2660
+ continue;
2701
2661
  }
2702
- componentExpr.properties.push(t.objectProperty(createStaticObjectKey("methods"), t.objectExpression([t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr)])));
2703
- return true;
2704
- }
2705
- if (!t.isObjectExpression(methodsProp.value)) return false;
2706
- const mapProp = getObjectPropertyByKey$1(methodsProp.value, "__weapp_vite_inline_map");
2707
- if (!mapProp) {
2708
- methodsProp.value.properties.push(t.objectProperty(createStaticObjectKey("__weapp_vite_inline_map"), inlineMapExpr));
2709
- return true;
2710
- }
2711
- if (t.isObjectExpression(mapProp.value)) {
2712
- mapProp.value.properties.push(...inlineMapExpr.properties);
2713
- return true;
2662
+ if (!t.isObjectProperty(prop) || prop.computed) continue;
2663
+ if (toStaticObjectKey(prop.key) === key) return prop;
2714
2664
  }
2715
- return false;
2665
+ return null;
2716
2666
  }
2717
-
2718
- //#endregion
2719
- //#region src/plugins/vue/transform/transformScript/rewrite/templateRefs.ts
2720
- function buildTemplateRefEntry(binding) {
2721
- const props = [t.objectProperty(t.identifier("selector"), t.stringLiteral(binding.selector)), t.objectProperty(t.identifier("inFor"), t.booleanLiteral(binding.inFor))];
2722
- if (binding.name) props.push(t.objectProperty(t.identifier("name"), t.stringLiteral(binding.name)));
2723
- if (binding.expAst) {
2724
- const body = t.blockStatement([t.returnStatement(t.cloneNode(binding.expAst, true))]);
2725
- props.push(t.objectProperty(t.identifier("get"), t.functionExpression(null, [], body)));
2726
- }
2727
- if (binding.kind) props.push(t.objectProperty(t.identifier("kind"), t.stringLiteral(binding.kind)));
2728
- return t.objectExpression(props);
2667
+ function toJsxTagName(name, context) {
2668
+ if (t.isJSXIdentifier(name)) return name.name;
2669
+ if (t.isJSXNamespacedName(name)) return `${name.namespace.name}:${name.name.name}`;
2670
+ context.warnings.push("暂不支持 JSX 成员标签(如 <Foo.Bar />),已回退为 <view />。");
2671
+ return "view";
2729
2672
  }
2730
- function injectTemplateRefs(optionsObject, bindings, warn) {
2731
- if (!bindings.length) return false;
2732
- const warnHandler = resolveWarnHandler(warn);
2733
- const entries = bindings.map((binding) => buildTemplateRefEntry(binding));
2734
- const refsArray = t.arrayExpression(entries);
2735
- const key = createStaticObjectKey("__wevuTemplateRefs");
2736
- const existing = getObjectPropertyByKey$1(optionsObject, "__wevuTemplateRefs");
2737
- if (!existing) {
2738
- optionsObject.properties.push(t.objectProperty(key, refsArray));
2739
- return true;
2673
+ function resolveRenderableExpression(node) {
2674
+ if (t.isObjectMethod(node)) {
2675
+ for (const statement of node.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2676
+ return null;
2740
2677
  }
2741
- if (t.isArrayExpression(existing.value)) {
2742
- existing.value.elements.push(...entries);
2743
- return true;
2678
+ if (!node.value) return null;
2679
+ const value = node.value;
2680
+ if (t.isArrowFunctionExpression(value)) {
2681
+ if (t.isBlockStatement(value.body)) {
2682
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2683
+ return null;
2684
+ }
2685
+ return unwrapTsExpression$2(value.body);
2744
2686
  }
2745
- if (t.isIdentifier(existing.value) || t.isMemberExpression(existing.value)) {
2746
- existing.value = t.arrayExpression([...entries, t.spreadElement(t.cloneNode(existing.value, true))]);
2747
- return true;
2687
+ if (t.isFunctionExpression(value)) {
2688
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2748
2689
  }
2749
- warnHandler("无法自动注入 template ref 元数据,请手动合并 __wevuTemplateRefs。");
2750
- return false;
2690
+ return null;
2751
2691
  }
2752
-
2753
2692
  //#endregion
2754
- //#region src/plugins/vue/transform/transformScript/rewrite/index.ts
2755
- function hasStaticProperty(target, keyName) {
2756
- for (const prop of target.properties) {
2757
- if (prop.type !== "ObjectProperty" && prop.type !== "ObjectMethod" || prop.computed) continue;
2758
- const key = prop.key;
2759
- if (key.type === "Identifier" && key.name === keyName) return true;
2760
- if (key.type === "StringLiteral" && key.value === keyName) return true;
2761
- }
2762
- return false;
2763
- }
2764
- function isObjectAssignCall(node) {
2765
- const callee = node.callee;
2766
- return t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "Object" }) && t.isIdentifier(callee.property, { name: "assign" });
2767
- }
2768
- function unwrapTypeLikeExpression(node) {
2769
- if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node)) return unwrapTypeLikeExpression(node.expression);
2770
- if (t.isParenthesizedExpression(node)) return unwrapTypeLikeExpression(node.expression);
2771
- return node;
2693
+ //#region src/plugins/jsx/compileJsx/script.ts
2694
+ function removeRenderOptionFromObjectExpression(node) {
2695
+ const nextProps = node.properties.filter((prop) => {
2696
+ if (t.isObjectMethod(prop)) return toStaticObjectKey(prop.key) !== "render";
2697
+ if (t.isObjectProperty(prop) && !prop.computed) return toStaticObjectKey(prop.key) !== "render";
2698
+ return true;
2699
+ });
2700
+ const removed = nextProps.length !== node.properties.length;
2701
+ if (removed) node.properties = nextProps;
2702
+ return removed;
2772
2703
  }
2773
- function resolveObjectExpressionFromProgram(program, name) {
2774
- for (let index = program.body.length - 1; index >= 0; index -= 1) {
2775
- const statement = program.body[index];
2776
- if (!t.isVariableDeclaration(statement)) continue;
2777
- for (const declarator of statement.declarations) {
2778
- if (!t.isIdentifier(declarator.id, { name }) || !declarator.init || !t.isExpression(declarator.init)) continue;
2779
- const normalized = unwrapTypeLikeExpression(declarator.init);
2780
- if (t.isObjectExpression(normalized)) return normalized;
2781
- if (t.isCallExpression(normalized) && isObjectAssignCall(normalized)) {
2782
- const lastArg = normalized.arguments[normalized.arguments.length - 1];
2783
- if (lastArg && !t.isSpreadElement(lastArg) && t.isExpression(lastArg)) {
2784
- const lastNormalized = unwrapTypeLikeExpression(lastArg);
2785
- if (t.isObjectExpression(lastNormalized)) return lastNormalized;
2786
- }
2704
+ function stripRenderOptionFromScript(source, filename, warn) {
2705
+ let ast;
2706
+ try {
2707
+ ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
2708
+ } catch {
2709
+ return source;
2710
+ }
2711
+ const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
2712
+ const defineComponentDecls = /* @__PURE__ */ new Map();
2713
+ let removedRender = false;
2714
+ let removedJsonMacroImport = false;
2715
+ traverse(ast, {
2716
+ ImportDeclaration(path) {
2717
+ const importSource = path.node.source.value;
2718
+ if (importSource === "wevu" || importSource === "vue") for (const specifier of path.node.specifiers) {
2719
+ if (!t.isImportSpecifier(specifier)) continue;
2720
+ if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
2721
+ defineComponentAliases.add(specifier.local.name);
2722
+ }
2723
+ if (importSource !== "weapp-vite") return;
2724
+ const retained = path.node.specifiers.filter((specifier) => {
2725
+ if (!t.isImportSpecifier(specifier)) return true;
2726
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : "";
2727
+ return !JSON_MACROS.has(importedName);
2728
+ });
2729
+ if (retained.length === path.node.specifiers.length) return;
2730
+ removedJsonMacroImport = true;
2731
+ if (retained.length === 0) path.remove();
2732
+ else path.node.specifiers = retained;
2733
+ },
2734
+ VariableDeclarator(path) {
2735
+ if (!t.isIdentifier(path.node.id) || !path.node.init) return;
2736
+ if (t.isObjectExpression(path.node.init)) {
2737
+ defineComponentDecls.set(path.node.id.name, path.node.init);
2738
+ return;
2739
+ }
2740
+ if (!t.isCallExpression(path.node.init)) return;
2741
+ const callee = path.node.init.callee;
2742
+ if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
2743
+ const first = path.node.init.arguments[0];
2744
+ if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, first);
2745
+ },
2746
+ ExportDefaultDeclaration(path) {
2747
+ const declaration = path.node.declaration;
2748
+ if (t.isDeclaration(declaration)) return;
2749
+ if (t.isObjectExpression(declaration)) {
2750
+ removedRender = removeRenderOptionFromObjectExpression(declaration) || removedRender;
2751
+ return;
2752
+ }
2753
+ if (t.isCallExpression(declaration)) {
2754
+ const callee = declaration.callee;
2755
+ if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
2756
+ const first = declaration.arguments[0];
2757
+ if (t.isObjectExpression(first)) removedRender = removeRenderOptionFromObjectExpression(first) || removedRender;
2758
+ return;
2759
+ }
2760
+ if (t.isIdentifier(declaration)) {
2761
+ const target = defineComponentDecls.get(declaration.name);
2762
+ if (target) removedRender = removeRenderOptionFromObjectExpression(target) || removedRender;
2787
2763
  }
2788
2764
  }
2789
- }
2790
- return null;
2765
+ });
2766
+ if (!removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
2767
+ if (!removedRender && !removedJsonMacroImport) return source;
2768
+ return generate(ast).code;
2791
2769
  }
2792
- function hasStaticPropertyWithSpreads(target, keyName, program, visited = /* @__PURE__ */ new Set()) {
2793
- if (hasStaticProperty(target, keyName)) return true;
2794
- for (const prop of target.properties) {
2795
- if (!t.isSpreadElement(prop)) continue;
2796
- const spreadArg = prop.argument;
2797
- if (t.isObjectExpression(spreadArg) && hasStaticPropertyWithSpreads(spreadArg, keyName, program, visited)) return true;
2798
- if (!t.isIdentifier(spreadArg) || visited.has(spreadArg.name)) continue;
2799
- visited.add(spreadArg.name);
2800
- const resolved = resolveObjectExpressionFromProgram(program, spreadArg.name);
2801
- if (resolved && hasStaticPropertyWithSpreads(resolved, keyName, program, visited)) return true;
2802
- }
2803
- return false;
2770
+ //#endregion
2771
+ //#region src/plugins/vue/compiler/template/platforms/alipay.ts
2772
+ const eventMap$3 = {
2773
+ click: "tap",
2774
+ dblclick: "tap",
2775
+ mousedown: "touchstart",
2776
+ mouseup: "touchend",
2777
+ tap: "tap",
2778
+ input: "input",
2779
+ change: "change",
2780
+ submit: "submit",
2781
+ focus: "focus",
2782
+ blur: "blur",
2783
+ confirm: "confirm",
2784
+ cancel: "cancel",
2785
+ load: "load",
2786
+ error: "error",
2787
+ scroll: "scroll",
2788
+ scrolltoupper: "scrolltoupper",
2789
+ scrolltolower: "scrolltolower",
2790
+ touchcancel: "touchcancel",
2791
+ longtap: "longtap",
2792
+ longpress: "longpress"
2793
+ };
2794
+ function toOnEventName(eventName) {
2795
+ if (!eventName) return "on";
2796
+ return `on${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
2804
2797
  }
2805
- function hasStaticPropertyInComponentExpression(componentExpr, keyName, program) {
2806
- const normalized = unwrapTypeLikeExpression(componentExpr);
2807
- if (t.isObjectExpression(normalized)) return hasStaticPropertyWithSpreads(normalized, keyName, program);
2808
- if (!t.isCallExpression(normalized) || !isObjectAssignCall(normalized)) return false;
2809
- for (const arg of normalized.arguments) {
2810
- if (t.isSpreadElement(arg) || !t.isExpression(arg)) continue;
2811
- const expr = unwrapTypeLikeExpression(arg);
2812
- if (t.isObjectExpression(expr) && hasStaticPropertyWithSpreads(expr, keyName, program)) return true;
2813
- if (t.isIdentifier(expr)) {
2814
- const resolved = resolveObjectExpressionFromProgram(program, expr.name);
2815
- if (resolved && hasStaticPropertyWithSpreads(resolved, keyName, program, new Set([expr.name]))) return true;
2816
- }
2817
- }
2818
- return false;
2798
+ function parseEventBinding$3(eventName) {
2799
+ const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
2800
+ if (prefixed) return {
2801
+ prefix: prefixed[1],
2802
+ name: prefixed[2]
2803
+ };
2804
+ return {
2805
+ prefix: "bind",
2806
+ name: eventName
2807
+ };
2819
2808
  }
2820
- function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializedWevuDefaults, parsedWevuDefaults) {
2821
- if (!state.defaultExportPath) return false;
2822
- const warn = resolveWarnHandler(options?.warn);
2823
- let transformed = false;
2824
- const exportPath = state.defaultExportPath;
2825
- const componentExpr = resolveComponentExpression(exportPath.node.declaration, state.defineComponentDecls, state.defineComponentAliases);
2826
- const componentOptionsObject = resolveComponentOptionsObject(componentExpr);
2827
- const hasPageMarker = componentExpr ? hasStaticPropertyInComponentExpression(componentExpr, "__wevu_isPage", ast.program) : false;
2828
- if (componentOptionsObject && options?.isPage && !options?.isApp && !hasPageMarker) {
2829
- componentOptionsObject.properties.splice(0, 0, t.objectProperty(t.identifier("__wevu_isPage"), t.booleanLiteral(true)));
2830
- transformed = true;
2831
- }
2832
- if (componentOptionsObject && enabledPageFeatures.size) transformed = injectWevuPageFeatureFlagsIntoOptionsObject(componentOptionsObject, enabledPageFeatures) || transformed;
2833
- if (componentOptionsObject && parsedWevuDefaults) transformed = applyWevuDefaultsToComponentOptions({
2834
- componentExpr: componentOptionsObject,
2835
- parsedWevuDefaults,
2836
- options
2837
- }) || transformed;
2838
- const classStyleBindings = options?.classStyleBindings ?? [];
2839
- if (classStyleBindings.length) if (componentOptionsObject) {
2840
- ensureClassStyleRuntimeImports(ast.program);
2841
- transformed = injectClassStyleComputed(componentOptionsObject, classStyleBindings, warn) || transformed;
2842
- } else warn("无法自动注入 class/style 计算属性:组件选项不是对象字面量。");
2843
- const templateRefs = options?.templateRefs ?? [];
2844
- if (templateRefs.length) if (componentOptionsObject) transformed = injectTemplateRefs(componentOptionsObject, templateRefs, warn) || transformed;
2845
- else warn("无法自动注入 template ref 元数据:组件选项不是对象字面量。");
2846
- const inlineExpressions = options?.inlineExpressions ?? [];
2847
- if (inlineExpressions.length) if (componentOptionsObject) {
2848
- const injected = injectInlineExpressions(componentOptionsObject, inlineExpressions);
2849
- if (!injected) warn("无法自动注入内联表达式元数据:methods 不是对象字面量。");
2850
- transformed = injected || transformed;
2851
- } else warn("无法自动注入内联表达式元数据:组件选项不是对象字面量。");
2852
- if (componentExpr) {
2853
- if (options?.isApp) transformed = injectWevuDefaultsForApp({
2854
- astProgram: ast.program,
2855
- options,
2856
- serializedWevuDefaults
2857
- }) || transformed;
2858
- transformed = rewriteComponentExport({
2859
- ast,
2860
- exportPath,
2861
- componentExpr,
2862
- isAppFile: !!options?.isApp,
2863
- skipComponentTransform: options?.skipComponentTransform
2864
- }) || transformed;
2809
+ function toAlipayDirectiveEvent(prefix, eventName) {
2810
+ if (!eventName) return "on";
2811
+ const pascalEvent = `${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
2812
+ switch (prefix) {
2813
+ case "catch": return `catch${pascalEvent}`;
2814
+ case "capture-bind": return `capture${pascalEvent}`;
2815
+ case "capture-catch": return `captureCatch${pascalEvent}`;
2816
+ default: return toOnEventName(eventName);
2865
2817
  }
2866
- return transformed;
2867
2818
  }
2868
-
2869
- //#endregion
2870
- //#region src/plugins/vue/transform/transformScript/index.ts
2871
2819
  /**
2872
- * 转换 Vue SFC 脚本:处理宏、导入、默认导出与 wevu 相关注入。
2820
+ * 支付宝小程序平台适配器。
2873
2821
  */
2874
- function transformScript(source, options) {
2875
- const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
2876
- const warn = resolveWarnHandler(options?.warn);
2877
- const state = {
2878
- transformed: false,
2879
- defineComponentAliases: new Set([WE_VU_RUNTIME_APIS.defineComponent, "_defineComponent"]),
2880
- defineComponentDecls: /* @__PURE__ */ new Map(),
2881
- defaultExportPath: null
2882
- };
2883
- const enabledPageFeatures = options?.isPage ? collectWevuPageFeatureFlags(ast) : /* @__PURE__ */ new Set();
2884
- const serializedWevuDefaults = options?.wevuDefaults && Object.keys(options.wevuDefaults).length > 0 ? serializeWevuDefaults(options.wevuDefaults, warn) : void 0;
2885
- const parsedWevuDefaults = serializedWevuDefaults ? JSON.parse(serializedWevuDefaults) : void 0;
2886
- traverse(ast, vueSfcTransformPlugin().visitor);
2887
- traverse(ast, {
2888
- ...createMacroVisitors(state),
2889
- ...createImportVisitors(ast.program, state),
2890
- ...createCollectVisitors(state)
2891
- });
2892
- if (options?.templateComponentMeta) state.transformed = injectTemplateComponentMeta(ast, options.templateComponentMeta) || state.transformed;
2893
- state.transformed = rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializedWevuDefaults, parsedWevuDefaults) || state.transformed;
2894
- if (!state.transformed) return {
2895
- code: source,
2896
- transformed: false
2822
+ const alipayPlatform = {
2823
+ name: "alipay",
2824
+ wrapIf: (exp, content, renderMustache) => `<block a:if="${renderMustache(exp)}">${content}</block>`,
2825
+ wrapElseIf: (exp, content, renderMustache) => `<block a:elif="${renderMustache(exp)}">${content}</block>`,
2826
+ wrapElse: (content) => `<block a:else>${content}</block>`,
2827
+ forAttrs: (listExp, renderMustache, item, index) => {
2828
+ const attrs = [`a:for="${renderMustache(listExp)}"`];
2829
+ if (item) attrs.push(`a:for-item="${item}"`);
2830
+ if (index) attrs.push(`a:for-index="${index}"`);
2831
+ return attrs;
2832
+ },
2833
+ keyThisValue: "*this",
2834
+ keyAttr: (value) => `a:key="${value}"`,
2835
+ mapEventName: (eventName) => eventMap$3[eventName] || eventName,
2836
+ eventBindingAttr: (eventName) => {
2837
+ const { prefix, name } = parseEventBinding$3(eventName);
2838
+ if (name.includes(":")) return `on:${name}`;
2839
+ return toAlipayDirectiveEvent(prefix, name);
2840
+ }
2841
+ };
2842
+ //#endregion
2843
+ //#region src/plugins/vue/compiler/template/platforms/swan.ts
2844
+ const eventMap$2 = {
2845
+ click: "tap",
2846
+ dblclick: "tap",
2847
+ mousedown: "touchstart",
2848
+ mouseup: "touchend",
2849
+ tap: "tap",
2850
+ input: "input",
2851
+ change: "change",
2852
+ submit: "submit",
2853
+ focus: "focus",
2854
+ blur: "blur",
2855
+ confirm: "confirm",
2856
+ cancel: "cancel",
2857
+ load: "load",
2858
+ error: "error",
2859
+ scroll: "scroll",
2860
+ scrolltoupper: "scrolltoupper",
2861
+ scrolltolower: "scrolltolower",
2862
+ touchcancel: "touchcancel",
2863
+ longtap: "longtap",
2864
+ longpress: "longpress"
2865
+ };
2866
+ function parseEventBinding$2(eventName) {
2867
+ const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
2868
+ if (prefixed) return {
2869
+ prefix: prefixed[1],
2870
+ name: prefixed[2]
2897
2871
  };
2898
2872
  return {
2899
- code: generate(ast, { retainLines: true }).code,
2900
- transformed: state.transformed
2873
+ prefix: "bind",
2874
+ name: eventName
2901
2875
  };
2902
2876
  }
2903
-
2904
- //#endregion
2905
- //#region src/plugins/jsx/compileJsxFile.ts
2906
- const ESCAPED_TEXT_RE = /[&<>]/g;
2907
- const ESCAPED_ATTR_RE = /[&"<>]/g;
2908
- const ESCAPED_TEXT_MAP = {
2909
- "&": "&amp;",
2910
- "<": "&lt;",
2911
- ">": "&gt;"
2877
+ function shouldUseColonEventBinding$2(name) {
2878
+ return name.includes(":") || name.includes("-");
2879
+ }
2880
+ /**
2881
+ * 百度智能小程序平台适配器。
2882
+ */
2883
+ const swanPlatform = {
2884
+ name: "swan",
2885
+ wrapIf: (exp, content, renderMustache) => `<block s-if="${renderMustache(exp)}">${content}</block>`,
2886
+ wrapElseIf: (exp, content, renderMustache) => `<block s-elif="${renderMustache(exp)}">${content}</block>`,
2887
+ wrapElse: (content) => `<block s-else>${content}</block>`,
2888
+ forAttrs: (listExp, renderMustache, item, index) => {
2889
+ const attrs = [`s-for="${renderMustache(listExp)}"`];
2890
+ if (item) attrs.push(`s-for-item="${item}"`);
2891
+ if (index) attrs.push(`s-for-index="${index}"`);
2892
+ return attrs;
2893
+ },
2894
+ keyThisValue: "*this",
2895
+ keyAttr: (value) => `s-key="${value}"`,
2896
+ mapEventName: (eventName) => eventMap$2[eventName] || eventName,
2897
+ eventBindingAttr: (eventName) => {
2898
+ const { prefix, name } = parseEventBinding$2(eventName);
2899
+ switch (prefix) {
2900
+ case "catch": return shouldUseColonEventBinding$2(name) ? `catch:${name}` : `catch${name}`;
2901
+ case "capture-bind": return `capture-bind:${name}`;
2902
+ case "capture-catch": return `capture-catch:${name}`;
2903
+ case "mut-bind": return `mut-bind:${name}`;
2904
+ default: return shouldUseColonEventBinding$2(name) ? `bind:${name}` : `bind${name}`;
2905
+ }
2906
+ }
2912
2907
  };
2913
- const ESCAPED_ATTR_MAP = {
2914
- "&": "&amp;",
2915
- "\"": "&quot;",
2916
- "<": "&lt;",
2917
- ">": "&gt;"
2908
+ //#endregion
2909
+ //#region src/plugins/vue/compiler/template/platforms/tt.ts
2910
+ const eventMap$1 = {
2911
+ click: "tap",
2912
+ dblclick: "tap",
2913
+ mousedown: "touchstart",
2914
+ mouseup: "touchend",
2915
+ tap: "tap",
2916
+ input: "input",
2917
+ change: "change",
2918
+ submit: "submit",
2919
+ focus: "focus",
2920
+ blur: "blur",
2921
+ confirm: "confirm",
2922
+ cancel: "cancel",
2923
+ load: "load",
2924
+ error: "error",
2925
+ scroll: "scroll",
2926
+ scrolltoupper: "scrolltoupper",
2927
+ scrolltolower: "scrolltolower",
2928
+ touchcancel: "touchcancel",
2929
+ longtap: "longtap",
2930
+ longpress: "longpress"
2918
2931
  };
2919
- function escapeText(value) {
2920
- return value.replace(ESCAPED_TEXT_RE, (ch) => ESCAPED_TEXT_MAP[ch] || ch);
2921
- }
2922
- function escapeAttr(value) {
2923
- return value.replace(ESCAPED_ATTR_RE, (ch) => ESCAPED_ATTR_MAP[ch] || ch);
2924
- }
2925
- function normalizeJsxText(value) {
2926
- return value.replace(/\s+/g, " ");
2932
+ function parseEventBinding$1(eventName) {
2933
+ const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
2934
+ if (prefixed) return {
2935
+ prefix: prefixed[1],
2936
+ name: prefixed[2]
2937
+ };
2938
+ return {
2939
+ prefix: "bind",
2940
+ name: eventName
2941
+ };
2927
2942
  }
2928
- function printExpression(exp) {
2929
- return generate(exp).code;
2943
+ function shouldUseColonEventBinding$1(name) {
2944
+ return name.includes(":") || name.includes("-");
2930
2945
  }
2931
- function unwrapTsExpression$2(exp) {
2932
- let current = exp;
2933
- while (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current) || t.isParenthesizedExpression(current) || t.isTSInstantiationExpression(current)) {
2934
- if (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current)) {
2935
- current = current.expression;
2936
- continue;
2937
- }
2938
- if (t.isParenthesizedExpression(current)) {
2939
- current = current.expression;
2940
- continue;
2946
+ /**
2947
+ * 抖音小程序平台适配器。
2948
+ */
2949
+ const ttPlatform = {
2950
+ name: "tt",
2951
+ wrapIf: (exp, content, renderMustache) => `<block tt:if="${renderMustache(exp)}">${content}</block>`,
2952
+ wrapElseIf: (exp, content, renderMustache) => `<block tt:elif="${renderMustache(exp)}">${content}</block>`,
2953
+ wrapElse: (content) => `<block tt:else>${content}</block>`,
2954
+ forAttrs: (listExp, renderMustache, item, index) => {
2955
+ const attrs = [`tt:for="${renderMustache(listExp)}"`];
2956
+ if (item) attrs.push(`tt:for-item="${item}"`);
2957
+ if (index) attrs.push(`tt:for-index="${index}"`);
2958
+ return attrs;
2959
+ },
2960
+ keyThisValue: "*this",
2961
+ keyAttr: (value) => `tt:key="${value}"`,
2962
+ mapEventName: (eventName) => eventMap$1[eventName] || eventName,
2963
+ eventBindingAttr: (eventName) => {
2964
+ const { prefix, name } = parseEventBinding$1(eventName);
2965
+ switch (prefix) {
2966
+ case "catch": return shouldUseColonEventBinding$1(name) ? `catch:${name}` : `catch${name}`;
2967
+ case "capture-bind": return `capture-bind:${name}`;
2968
+ case "capture-catch": return `capture-catch:${name}`;
2969
+ case "mut-bind": return `mut-bind:${name}`;
2970
+ default: return shouldUseColonEventBinding$1(name) ? `bind:${name}` : `bind${name}`;
2941
2971
  }
2942
- if (t.isTSInstantiationExpression(current)) current = current.expression;
2943
- }
2944
- return current;
2945
- }
2946
- function normalizeInterpolationExpression(exp) {
2947
- return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
2948
- }
2949
- function renderMustache$1(expression, context) {
2950
- return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
2951
- }
2952
- function pushScope$1(context, names) {
2953
- for (const name of names) {
2954
- if (!name) continue;
2955
- context.scopeStack.push(name);
2956
2972
  }
2957
- }
2958
- function popScope$1(context, count) {
2959
- for (let i = 0; i < count; i += 1) context.scopeStack.pop();
2960
- }
2961
- function collectExpressionScopeBindings(exp, context) {
2962
- const localSet = new Set(context.scopeStack);
2963
- if (!localSet.size) return [];
2964
- const used = [];
2965
- const usedSet = /* @__PURE__ */ new Set();
2966
- traverse(t.file(t.program([t.expressionStatement(t.cloneNode(exp, true))])), { Identifier(path) {
2967
- if (!path.isReferencedIdentifier()) return;
2968
- const name = path.node.name;
2969
- if (!localSet.has(name)) return;
2970
- if (path.scope.hasBinding(name)) return;
2971
- if (usedSet.has(name)) return;
2972
- usedSet.add(name);
2973
- used.push(name);
2974
- } });
2975
- return used;
2976
- }
2977
- function registerInlineExpression$1(exp, context) {
2978
- const scopeKeys = collectExpressionScopeBindings(exp, context);
2979
- const id = `__wv_inline_${context.inlineExpressionSeed++}`;
2980
- context.inlineExpressions.push({
2981
- id,
2982
- expression: printExpression(exp),
2983
- scopeKeys
2984
- });
2973
+ };
2974
+ //#endregion
2975
+ //#region src/plugins/vue/compiler/template/platforms/wechat.ts
2976
+ const eventMap = {
2977
+ click: "tap",
2978
+ dblclick: "tap",
2979
+ mousedown: "touchstart",
2980
+ mouseup: "touchend",
2981
+ tap: "tap",
2982
+ input: "input",
2983
+ change: "change",
2984
+ submit: "submit",
2985
+ focus: "focus",
2986
+ blur: "blur",
2987
+ confirm: "confirm",
2988
+ cancel: "cancel",
2989
+ load: "load",
2990
+ error: "error",
2991
+ scroll: "scroll",
2992
+ scrolltoupper: "scrolltoupper",
2993
+ scrolltolower: "scrolltolower",
2994
+ touchcancel: "touchcancel",
2995
+ longtap: "longtap",
2996
+ longpress: "longpress"
2997
+ };
2998
+ function parseEventBinding(eventName) {
2999
+ const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
3000
+ if (prefixed) return {
3001
+ prefix: prefixed[1],
3002
+ name: prefixed[2]
3003
+ };
2985
3004
  return {
2986
- id,
2987
- scopeKeys
3005
+ prefix: "bind",
3006
+ name: eventName
2988
3007
  };
2989
3008
  }
2990
- function toStaticObjectKey(key) {
2991
- if (t.isIdentifier(key)) return key.name;
2992
- if (t.isStringLiteral(key)) return key.value;
2993
- return null;
3009
+ function shouldUseColonEventBinding(name) {
3010
+ return name.includes(":") || name.includes("-");
2994
3011
  }
2995
- function getObjectPropertyByKey(node, key) {
2996
- for (const prop of node.properties) {
2997
- if (t.isObjectMethod(prop)) {
2998
- if (toStaticObjectKey(prop.key) === key) return prop;
2999
- continue;
3012
+ /**
3013
+ * 微信小程序平台适配器。
3014
+ */
3015
+ const wechatPlatform = {
3016
+ name: "wechat",
3017
+ wrapIf: (exp, content, renderMustache) => `<block wx:if="${renderMustache(exp)}">${content}</block>`,
3018
+ wrapElseIf: (exp, content, renderMustache) => `<block wx:elif="${renderMustache(exp)}">${content}</block>`,
3019
+ wrapElse: (content) => `<block wx:else>${content}</block>`,
3020
+ forAttrs: (listExp, renderMustache, item, index) => {
3021
+ const attrs = [`wx:for="${renderMustache(listExp)}"`];
3022
+ if (item) attrs.push(`wx:for-item="${item}"`);
3023
+ if (index) attrs.push(`wx:for-index="${index}"`);
3024
+ return attrs;
3025
+ },
3026
+ keyThisValue: "*this",
3027
+ keyAttr: (value) => `wx:key="${value}"`,
3028
+ mapEventName: (eventName) => eventMap[eventName] || eventName,
3029
+ eventBindingAttr: (eventName) => {
3030
+ const { prefix, name } = parseEventBinding(eventName);
3031
+ switch (prefix) {
3032
+ case "catch": return shouldUseColonEventBinding(name) ? `catch:${name}` : `catch${name}`;
3033
+ case "capture-bind": return `capture-bind:${name}`;
3034
+ case "capture-catch": return `capture-catch:${name}`;
3035
+ case "mut-bind": return `mut-bind:${name}`;
3036
+ default: return shouldUseColonEventBinding(name) ? `bind:${name}` : `bind${name}`;
3000
3037
  }
3001
- if (!t.isObjectProperty(prop) || prop.computed) continue;
3002
- if (toStaticObjectKey(prop.key) === key) return prop;
3003
3038
  }
3004
- return null;
3005
- }
3006
- function toJsxTagName(name, context) {
3007
- if (t.isJSXIdentifier(name)) return name.name;
3008
- if (t.isJSXNamespacedName(name)) return `${name.namespace.name}:${name.name.name}`;
3009
- context.warnings.push("暂不支持 JSX 成员标签(如 <Foo.Bar />),已回退为 <view />。");
3010
- return "view";
3039
+ };
3040
+ //#endregion
3041
+ //#region src/plugins/vue/compiler/template/platforms/index.ts
3042
+ const TEMPLATE_PLATFORMS = {
3043
+ weapp: wechatPlatform,
3044
+ alipay: alipayPlatform,
3045
+ tt: ttPlatform,
3046
+ swan: swanPlatform,
3047
+ jd: wechatPlatform,
3048
+ xhs: wechatPlatform
3049
+ };
3050
+ /**
3051
+ * 获取指定平台的模板适配器,默认回退到 wechat。
3052
+ */
3053
+ function getMiniProgramTemplatePlatform(platform) {
3054
+ if (!platform) return wechatPlatform;
3055
+ return TEMPLATE_PLATFORMS[platform] ?? wechatPlatform;
3011
3056
  }
3012
- function resolveRenderableExpression(node) {
3013
- if (t.isObjectMethod(node)) {
3014
- for (const statement of node.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
3057
+ //#endregion
3058
+ //#region src/plugins/jsx/compileJsx/analysis.ts
3059
+ function resolveRenderExpression(componentExpr, context) {
3060
+ if (!t.isObjectExpression(componentExpr)) {
3061
+ context.warnings.push("JSX 编译仅支持对象字面量组件选项。");
3015
3062
  return null;
3016
3063
  }
3017
- if (!node.value) return null;
3018
- const value = node.value;
3019
- if (t.isArrowFunctionExpression(value)) {
3020
- if (t.isBlockStatement(value.body)) {
3021
- for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
3022
- return null;
3023
- }
3024
- return unwrapTsExpression$2(value.body);
3064
+ const renderNode = getObjectPropertyByKey(componentExpr, "render");
3065
+ if (!renderNode) {
3066
+ context.warnings.push("未找到 render(),请在默认导出组件中声明 render 函数。");
3067
+ return null;
3025
3068
  }
3026
- if (t.isFunctionExpression(value)) {
3027
- for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
3069
+ if (!t.isObjectMethod(renderNode) && !t.isObjectProperty(renderNode)) {
3070
+ context.warnings.push("render 不是可执行函数。");
3071
+ return null;
3028
3072
  }
3029
- return null;
3030
- }
3031
- function removeRenderOptionFromObjectExpression(node) {
3032
- const nextProps = node.properties.filter((prop) => {
3033
- if (t.isObjectMethod(prop)) return toStaticObjectKey(prop.key) !== "render";
3034
- if (t.isObjectProperty(prop) && !prop.computed) return toStaticObjectKey(prop.key) !== "render";
3035
- return true;
3036
- });
3037
- const removed = nextProps.length !== node.properties.length;
3038
- if (removed) node.properties = nextProps;
3039
- return removed;
3073
+ return resolveRenderableExpression(renderNode);
3040
3074
  }
3041
- function stripRenderOptionFromScript(source, filename, warn) {
3042
- let ast;
3043
- try {
3044
- ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3045
- } catch {
3046
- return source;
3047
- }
3075
+ function findExportDefaultExpression(ast) {
3048
3076
  const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
3049
3077
  const defineComponentDecls = /* @__PURE__ */ new Map();
3050
- let removedRender = false;
3051
- let removedJsonMacroImport = false;
3078
+ let exportDefaultExpression = null;
3052
3079
  traverse(ast, {
3053
3080
  ImportDeclaration(path) {
3054
- const importSource = path.node.source.value;
3055
- if (importSource === "wevu" || importSource === "vue") for (const specifier of path.node.specifiers) {
3081
+ const source = path.node.source.value;
3082
+ if (source !== "wevu" && source !== "vue") return;
3083
+ for (const specifier of path.node.specifiers) {
3056
3084
  if (!t.isImportSpecifier(specifier)) continue;
3057
3085
  if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
3058
3086
  defineComponentAliases.add(specifier.local.name);
3059
3087
  }
3060
- if (importSource !== "weapp-vite") return;
3061
- const retained = path.node.specifiers.filter((specifier) => {
3062
- if (!t.isImportSpecifier(specifier)) return true;
3063
- const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : "";
3064
- return !JSON_MACROS.has(importedName);
3065
- });
3066
- if (retained.length === path.node.specifiers.length) return;
3067
- removedJsonMacroImport = true;
3068
- if (retained.length === 0) path.remove();
3069
- else path.node.specifiers = retained;
3070
3088
  },
3071
3089
  VariableDeclarator(path) {
3072
3090
  if (!t.isIdentifier(path.node.id) || !path.node.init) return;
3073
3091
  if (t.isObjectExpression(path.node.init)) {
3074
- defineComponentDecls.set(path.node.id.name, path.node.init);
3092
+ defineComponentDecls.set(path.node.id.name, t.cloneNode(path.node.init, true));
3075
3093
  return;
3076
3094
  }
3077
3095
  if (!t.isCallExpression(path.node.init)) return;
3078
3096
  const callee = path.node.init.callee;
3079
3097
  if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
3080
3098
  const first = path.node.init.arguments[0];
3081
- if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, first);
3099
+ if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, t.cloneNode(first, true));
3082
3100
  },
3083
3101
  ExportDefaultDeclaration(path) {
3084
3102
  const declaration = path.node.declaration;
3085
3103
  if (t.isDeclaration(declaration)) return;
3086
- if (t.isObjectExpression(declaration)) {
3087
- removedRender = removeRenderOptionFromObjectExpression(declaration) || removedRender;
3088
- return;
3089
- }
3090
- if (t.isCallExpression(declaration)) {
3091
- const callee = declaration.callee;
3092
- if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
3093
- const first = declaration.arguments[0];
3094
- if (t.isObjectExpression(first)) removedRender = removeRenderOptionFromObjectExpression(first) || removedRender;
3095
- return;
3096
- }
3097
- if (t.isIdentifier(declaration)) {
3098
- const target = defineComponentDecls.get(declaration.name);
3099
- if (target) removedRender = removeRenderOptionFromObjectExpression(target) || removedRender;
3104
+ exportDefaultExpression = resolveComponentExpression(declaration, defineComponentDecls, defineComponentAliases);
3105
+ }
3106
+ });
3107
+ return exportDefaultExpression;
3108
+ }
3109
+ function isCollectableJsxTemplateTag(tag) {
3110
+ if (!tag) return false;
3111
+ if (RESERVED_VUE_COMPONENT_TAGS.has(tag)) return false;
3112
+ return !isBuiltinComponent(tag);
3113
+ }
3114
+ function collectJsxTemplateTags(renderExpression) {
3115
+ const tags = /* @__PURE__ */ new Set();
3116
+ traverse(t.file(t.program([t.expressionStatement(t.cloneNode(renderExpression, true))])), { JSXOpeningElement(path) {
3117
+ const { name } = path.node;
3118
+ if (t.isJSXMemberExpression(name)) return;
3119
+ let tag = null;
3120
+ if (t.isJSXIdentifier(name)) tag = name.name;
3121
+ else if (t.isJSXNamespacedName(name)) tag = `${name.namespace.name}:${name.name.name}`;
3122
+ if (!tag || !isCollectableJsxTemplateTag(tag)) return;
3123
+ tags.add(tag);
3124
+ } });
3125
+ return tags;
3126
+ }
3127
+ function collectImportedComponents(ast) {
3128
+ const imports = /* @__PURE__ */ new Map();
3129
+ traverse(ast, { ImportDeclaration(path) {
3130
+ if (path.node.importKind === "type") return;
3131
+ if (!t.isStringLiteral(path.node.source)) return;
3132
+ const importSource = path.node.source.value;
3133
+ for (const specifier of path.node.specifiers) {
3134
+ if ("importKind" in specifier && specifier.importKind === "type") continue;
3135
+ if (!("local" in specifier) || !t.isIdentifier(specifier.local)) continue;
3136
+ const localName = specifier.local.name;
3137
+ if (t.isImportDefaultSpecifier(specifier)) {
3138
+ imports.set(localName, {
3139
+ localName,
3140
+ importSource,
3141
+ importedName: "default",
3142
+ kind: "default"
3143
+ });
3144
+ continue;
3100
3145
  }
3146
+ if (!t.isImportSpecifier(specifier)) continue;
3147
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : void 0;
3148
+ imports.set(localName, {
3149
+ localName,
3150
+ importSource,
3151
+ importedName,
3152
+ kind: "named"
3153
+ });
3101
3154
  }
3102
- });
3103
- if (!removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
3104
- if (!removedRender && !removedJsonMacroImport) return source;
3105
- return generate(ast).code;
3155
+ } });
3156
+ return Array.from(imports.values());
3106
3157
  }
3107
- function resolveRenderExpression(componentExpr, context) {
3108
- if (!t.isObjectExpression(componentExpr)) {
3109
- context.warnings.push("JSX 编译仅支持对象字面量组件选项。");
3110
- return null;
3111
- }
3112
- const renderNode = getObjectPropertyByKey(componentExpr, "render");
3113
- if (!renderNode) {
3114
- context.warnings.push("未找到 render(),请在默认导出组件中声明 render 函数。");
3115
- return null;
3158
+ function collectJsxAutoComponentContext(source, filename, context, warn) {
3159
+ const empty = {
3160
+ templateTags: /* @__PURE__ */ new Set(),
3161
+ importedComponents: []
3162
+ };
3163
+ let ast;
3164
+ try {
3165
+ ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3166
+ } catch (error) {
3167
+ const message = error instanceof Error ? error.message : String(error);
3168
+ warn?.(`[JSX 编译] 解析 ${filename} 失败,已跳过自动 usingComponents 推导:${message}`);
3169
+ return empty;
3116
3170
  }
3117
- if (!t.isObjectMethod(renderNode) && !t.isObjectProperty(renderNode)) {
3118
- context.warnings.push("render 不是可执行函数。");
3171
+ const importedComponents = collectImportedComponents(ast);
3172
+ const componentExpr = findExportDefaultExpression(ast);
3173
+ if (!componentExpr) return {
3174
+ templateTags: /* @__PURE__ */ new Set(),
3175
+ importedComponents
3176
+ };
3177
+ const renderExpression = resolveRenderExpression(componentExpr, context);
3178
+ if (!renderExpression) return {
3179
+ templateTags: /* @__PURE__ */ new Set(),
3180
+ importedComponents
3181
+ };
3182
+ return {
3183
+ templateTags: collectJsxTemplateTags(renderExpression),
3184
+ importedComponents
3185
+ };
3186
+ }
3187
+ function findJsxRenderExpression(ast, context) {
3188
+ const componentExpr = findExportDefaultExpression(ast);
3189
+ if (!componentExpr) {
3190
+ context.warnings.push("未识别到默认导出组件。");
3119
3191
  return null;
3120
3192
  }
3121
- return resolveRenderableExpression(renderNode);
3193
+ const renderExpression = resolveRenderExpression(componentExpr, context);
3194
+ if (!renderExpression) return null;
3195
+ return renderExpression;
3122
3196
  }
3197
+ //#endregion
3198
+ //#region src/plugins/jsx/compileJsx/attributes.ts
3123
3199
  function isEventBinding(name) {
3124
3200
  return /^on[A-Z]/.test(name) || /^catch[A-Z]/.test(name) || /^captureBind[A-Z]/.test(name) || /^captureCatch[A-Z]/.test(name) || /^mutBind[A-Z]/.test(name);
3125
3201
  }
@@ -3210,6 +3286,8 @@ function compileJsxAttributes(attributes, context) {
3210
3286
  }
3211
3287
  return output;
3212
3288
  }
3289
+ //#endregion
3290
+ //#region src/plugins/jsx/compileJsx/render.ts
3213
3291
  function compileListExpression(exp) {
3214
3292
  return normalizeInterpolationExpression(exp);
3215
3293
  }
@@ -3327,129 +3405,10 @@ function compileJsxElement(node, context) {
3327
3405
  if (node.openingElement.selfClosing) return `<${tag}${attrsSegment} />`;
3328
3406
  return `<${tag}${attrsSegment}>${compileJsxChildren(node.children, context)}</${tag}>`;
3329
3407
  }
3330
- function findExportDefaultExpression(ast) {
3331
- const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
3332
- const defineComponentDecls = /* @__PURE__ */ new Map();
3333
- let exportDefaultExpression = null;
3334
- traverse(ast, {
3335
- ImportDeclaration(path) {
3336
- const source = path.node.source.value;
3337
- if (source !== "wevu" && source !== "vue") return;
3338
- for (const specifier of path.node.specifiers) {
3339
- if (!t.isImportSpecifier(specifier)) continue;
3340
- if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
3341
- defineComponentAliases.add(specifier.local.name);
3342
- }
3343
- },
3344
- VariableDeclarator(path) {
3345
- if (!t.isIdentifier(path.node.id) || !path.node.init) return;
3346
- if (t.isObjectExpression(path.node.init)) {
3347
- defineComponentDecls.set(path.node.id.name, t.cloneNode(path.node.init, true));
3348
- return;
3349
- }
3350
- if (!t.isCallExpression(path.node.init)) return;
3351
- const callee = path.node.init.callee;
3352
- if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
3353
- const first = path.node.init.arguments[0];
3354
- if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, t.cloneNode(first, true));
3355
- },
3356
- ExportDefaultDeclaration(path) {
3357
- const declaration = path.node.declaration;
3358
- if (t.isDeclaration(declaration)) return;
3359
- exportDefaultExpression = resolveComponentExpression(declaration, defineComponentDecls, defineComponentAliases);
3360
- }
3361
- });
3362
- return exportDefaultExpression;
3363
- }
3364
- function isCollectableJsxTemplateTag(tag) {
3365
- if (!tag) return false;
3366
- if (RESERVED_VUE_COMPONENT_TAGS.has(tag)) return false;
3367
- return !isBuiltinComponent(tag);
3368
- }
3369
- function collectJsxTemplateTags(renderExpression) {
3370
- const tags = /* @__PURE__ */ new Set();
3371
- traverse(t.file(t.program([t.expressionStatement(t.cloneNode(renderExpression, true))])), { JSXOpeningElement(path) {
3372
- const { name } = path.node;
3373
- if (t.isJSXMemberExpression(name)) return;
3374
- let tag = null;
3375
- if (t.isJSXIdentifier(name)) tag = name.name;
3376
- else if (t.isJSXNamespacedName(name)) tag = `${name.namespace.name}:${name.name.name}`;
3377
- if (!tag || !isCollectableJsxTemplateTag(tag)) return;
3378
- tags.add(tag);
3379
- } });
3380
- return tags;
3381
- }
3382
- function collectImportedComponents(ast) {
3383
- const imports = /* @__PURE__ */ new Map();
3384
- traverse(ast, { ImportDeclaration(path) {
3385
- if (path.node.importKind === "type") return;
3386
- if (!t.isStringLiteral(path.node.source)) return;
3387
- const importSource = path.node.source.value;
3388
- for (const specifier of path.node.specifiers) {
3389
- if ("importKind" in specifier && specifier.importKind === "type") continue;
3390
- if (!("local" in specifier) || !t.isIdentifier(specifier.local)) continue;
3391
- const localName = specifier.local.name;
3392
- if (t.isImportDefaultSpecifier(specifier)) {
3393
- imports.set(localName, {
3394
- localName,
3395
- importSource,
3396
- importedName: "default",
3397
- kind: "default"
3398
- });
3399
- continue;
3400
- }
3401
- if (!t.isImportSpecifier(specifier)) continue;
3402
- const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : void 0;
3403
- imports.set(localName, {
3404
- localName,
3405
- importSource,
3406
- importedName,
3407
- kind: "named"
3408
- });
3409
- }
3410
- } });
3411
- return Array.from(imports.values());
3412
- }
3413
- function collectJsxAutoComponentContext(source, filename, warn) {
3414
- const empty = {
3415
- templateTags: /* @__PURE__ */ new Set(),
3416
- importedComponents: []
3417
- };
3418
- let ast;
3419
- try {
3420
- ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3421
- } catch (error) {
3422
- const message = error instanceof Error ? error.message : String(error);
3423
- warn?.(`[JSX 编译] 解析 ${filename} 失败,已跳过自动 usingComponents 推导:${message}`);
3424
- return empty;
3425
- }
3426
- const importedComponents = collectImportedComponents(ast);
3427
- const context = {
3428
- platform: wechatPlatform,
3429
- mustacheInterpolation: "compact",
3430
- warnings: [],
3431
- inlineExpressions: [],
3432
- inlineExpressionSeed: 0,
3433
- scopeStack: []
3434
- };
3435
- const componentExpr = findExportDefaultExpression(ast);
3436
- if (!componentExpr) return {
3437
- templateTags: /* @__PURE__ */ new Set(),
3438
- importedComponents
3439
- };
3440
- const renderExpression = resolveRenderExpression(componentExpr, context);
3441
- if (!renderExpression) return {
3442
- templateTags: /* @__PURE__ */ new Set(),
3443
- importedComponents
3444
- };
3408
+ //#endregion
3409
+ //#region src/plugins/jsx/compileJsx/template.ts
3410
+ function createJsxCompileContext(options) {
3445
3411
  return {
3446
- templateTags: collectJsxTemplateTags(renderExpression),
3447
- importedComponents
3448
- };
3449
- }
3450
- function compileJsxTemplate(source, filename, options) {
3451
- const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3452
- const context = {
3453
3412
  platform: options?.template?.platform ?? wechatPlatform,
3454
3413
  mustacheInterpolation: options?.template?.mustacheInterpolation ?? "compact",
3455
3414
  warnings: [],
@@ -3457,27 +3416,30 @@ function compileJsxTemplate(source, filename, options) {
3457
3416
  inlineExpressionSeed: 0,
3458
3417
  scopeStack: []
3459
3418
  };
3460
- const componentExpr = findExportDefaultExpression(ast);
3461
- if (!componentExpr) {
3462
- context.warnings.push(`未在 ${filename} 中识别到默认导出组件。`);
3419
+ }
3420
+ function compileJsxTemplate(source, filename, options) {
3421
+ const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3422
+ const context = createJsxCompileContext(options);
3423
+ const renderExpression = findJsxRenderExpression(ast, context);
3424
+ if (!renderExpression) {
3425
+ context.warnings = context.warnings.map((message) => message === "未识别到默认导出组件。" ? `未在 ${filename} 中识别到默认导出组件。` : message);
3463
3426
  return {
3464
3427
  template: void 0,
3465
3428
  warnings: context.warnings,
3466
3429
  inlineExpressions: context.inlineExpressions
3467
3430
  };
3468
3431
  }
3469
- const renderExpression = resolveRenderExpression(componentExpr, context);
3470
- if (!renderExpression) return {
3471
- template: void 0,
3472
- warnings: context.warnings,
3473
- inlineExpressions: context.inlineExpressions
3474
- };
3475
3432
  return {
3476
3433
  template: compileRenderableExpression(renderExpression, context),
3477
3434
  warnings: context.warnings,
3478
3435
  inlineExpressions: context.inlineExpressions
3479
3436
  };
3480
3437
  }
3438
+ function collectJsxAutoComponents(source, filename, options) {
3439
+ return collectJsxAutoComponentContext(source, filename, createJsxCompileContext(options), options?.warn);
3440
+ }
3441
+ //#endregion
3442
+ //#region src/plugins/jsx/compileJsxFile.ts
3481
3443
  /**
3482
3444
  * 编译 JSX/TSX 文件,输出 wevu 脚本与 WXML 模板。
3483
3445
  */
@@ -3502,7 +3464,7 @@ async function compileJsxFile(source, filename, options) {
3502
3464
  throw new Error(`解析 ${filename} 失败:${message}`);
3503
3465
  }
3504
3466
  const compiledTemplate = compileJsxTemplate(source, filename, options);
3505
- const autoComponentContext = collectJsxAutoComponentContext(source, filename, options?.warn);
3467
+ const autoComponentContext = collectJsxAutoComponents(source, filename, options);
3506
3468
  const autoUsingComponentsMap = {};
3507
3469
  if (options?.autoUsingComponents?.resolveUsingComponentPath && autoComponentContext.templateTags.size > 0) for (const imported of autoComponentContext.importedComponents) {
3508
3470
  if (!autoComponentContext.templateTags.has(imported.localName)) continue;
@@ -3564,7 +3526,6 @@ async function compileJsxFile(source, filename, options) {
3564
3526
  }
3565
3527
  };
3566
3528
  }
3567
-
3568
3529
  //#endregion
3569
3530
  //#region src/utils/text.ts
3570
3531
  /**
@@ -3574,7 +3535,6 @@ function normalizeLineEndings(source) {
3574
3535
  if (!source.includes("\r")) return source;
3575
3536
  return source.replace(/\r\n?/g, "\n");
3576
3537
  }
3577
-
3578
3538
  //#endregion
3579
3539
  //#region src/plugins/utils/cache.ts
3580
3540
  const mtimeCache = /* @__PURE__ */ new Map();
@@ -3652,7 +3612,6 @@ function clearFileCaches() {
3652
3612
  loadCache.clear();
3653
3613
  pathExistsCache.clear();
3654
3614
  }
3655
-
3656
3615
  //#endregion
3657
3616
  //#region src/utils/cachePolicy.ts
3658
3617
  /**
@@ -3661,7 +3620,6 @@ function clearFileCaches() {
3661
3620
  function getReadFileCheckMtime(config) {
3662
3621
  return Boolean(config?.isDev);
3663
3622
  }
3664
-
3665
3623
  //#endregion
3666
3624
  //#region src/utils/viteId.ts
3667
3625
  const VUE_VIRTUAL_MODULE_PREFIX = "\0vue:";
@@ -3683,7 +3641,6 @@ function normalizeViteId(id, options) {
3683
3641
  if (stripLeadingNullByte && clean.startsWith("\0")) clean = clean.slice(1);
3684
3642
  return clean;
3685
3643
  }
3686
-
3687
3644
  //#endregion
3688
3645
  //#region src/utils/resolvedId.ts
3689
3646
  function isSkippableResolvedId(id) {
@@ -3707,13 +3664,8 @@ function normalizeFsResolvedId(id, options) {
3707
3664
  if (options?.stripLeadingNullByte) normalizeOptions.stripLeadingNullByte = true;
3708
3665
  return normalizeViteId(id, normalizeOptions);
3709
3666
  }
3710
-
3711
3667
  //#endregion
3712
- //#region src/plugins/utils/vueSfc.ts
3713
- const sfcParseCache = new LRUCache({ max: 512 });
3714
- const SCRIPT_SETUP_SRC_ATTR = "data-weapp-vite-src";
3715
- const SCRIPT_SRC_ATTR = "data-weapp-vite-script-src";
3716
- const SCRIPT_SETUP_TAG_RE = /<script\b([^>]*)>/gi;
3668
+ //#region src/plugins/utils/vueSfcBlockSrc.ts
3717
3669
  const SCRIPT_LANG_EXT = new Map([
3718
3670
  [".ts", "ts"],
3719
3671
  [".tsx", "tsx"],
@@ -3725,67 +3677,27 @@ const SCRIPT_LANG_EXT = new Map([
3725
3677
  const STYLE_LANG_EXT = new Map([
3726
3678
  [".css", "css"],
3727
3679
  [".scss", "scss"],
3728
- [".sass", "sass"],
3729
- [".less", "less"],
3730
- [".styl", "styl"],
3731
- [".stylus", "styl"]
3732
- ]);
3733
- const TEMPLATE_LANG_EXT = new Map([
3734
- [".html", "html"],
3735
- [".htm", "html"],
3736
- [".pug", "pug"],
3737
- [".jade", "pug"]
3738
- ]);
3739
- function inferLangFromSrc(src, kind) {
3740
- const ext = path.extname(src).toLowerCase();
3741
- if (!ext) return;
3742
- if (kind === "style") return STYLE_LANG_EXT.get(ext);
3743
- if (kind === "template") return TEMPLATE_LANG_EXT.get(ext);
3744
- return SCRIPT_LANG_EXT.get(ext);
3745
- }
3746
- function getBlockLabel(kind) {
3747
- if (kind === "script setup") return "script setup";
3748
- return kind;
3749
- }
3750
- /**
3751
- * 预处理 `<script setup src>`,避免编译器丢失 src。
3752
- */
3753
- function preprocessScriptSetupSrc(source) {
3754
- if (!source.includes("<script") || !source.includes("setup") || !source.includes("src")) return source;
3755
- return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3756
- if (!/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3757
- return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SETUP_SRC_ATTR}$1`)}>`;
3758
- });
3759
- }
3760
- /**
3761
- * 预处理普通 `<script src>`,避免编译器丢失 src。
3762
- */
3763
- function preprocessScriptSrc(source) {
3764
- if (!source.includes("<script") || !source.includes("src")) return source;
3765
- return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3766
- if (/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3767
- return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SRC_ATTR}$1`)}>`;
3768
- });
3769
- }
3770
- /**
3771
- * 将预处理的 `<script setup src>` 恢复为真实 src。
3772
- */
3773
- function restoreScriptSetupSrc(descriptor) {
3774
- const scriptSetup = descriptor.scriptSetup;
3775
- if (!scriptSetup?.attrs || !(SCRIPT_SETUP_SRC_ATTR in scriptSetup.attrs)) return;
3776
- const raw = scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3777
- if (typeof raw === "string") scriptSetup.src = raw;
3778
- delete scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3680
+ [".sass", "sass"],
3681
+ [".less", "less"],
3682
+ [".styl", "styl"],
3683
+ [".stylus", "styl"]
3684
+ ]);
3685
+ const TEMPLATE_LANG_EXT = new Map([
3686
+ [".html", "html"],
3687
+ [".htm", "html"],
3688
+ [".pug", "pug"],
3689
+ [".jade", "pug"]
3690
+ ]);
3691
+ function inferLangFromSrc(src, kind) {
3692
+ const ext = path.extname(src).toLowerCase();
3693
+ if (!ext) return;
3694
+ if (kind === "style") return STYLE_LANG_EXT.get(ext);
3695
+ if (kind === "template") return TEMPLATE_LANG_EXT.get(ext);
3696
+ return SCRIPT_LANG_EXT.get(ext);
3779
3697
  }
3780
- /**
3781
- * 将预处理的 `<script src>` 恢复为真实 src。
3782
- */
3783
- function restoreScriptSrc(descriptor) {
3784
- const script = descriptor.script;
3785
- if (!script?.attrs || !(SCRIPT_SRC_ATTR in script.attrs)) return;
3786
- const raw = script.attrs[SCRIPT_SRC_ATTR];
3787
- if (typeof raw === "string") script.src = raw;
3788
- delete script.attrs[SCRIPT_SRC_ATTR];
3698
+ function getBlockLabel(kind) {
3699
+ if (kind === "script setup") return "script setup";
3700
+ return kind;
3789
3701
  }
3790
3702
  async function resolveBlockSrcPath(src, filename, options) {
3791
3703
  const normalizedSrc = normalizeFsResolvedId(src);
@@ -3851,6 +3763,52 @@ async function resolveSfcBlockSrc(descriptor, filename, options) {
3851
3763
  deps: Array.from(deps)
3852
3764
  };
3853
3765
  }
3766
+ //#endregion
3767
+ //#region src/plugins/utils/vueSfc.ts
3768
+ const sfcParseCache = new LRUCache({ max: 512 });
3769
+ const SCRIPT_SETUP_SRC_ATTR = "data-weapp-vite-src";
3770
+ const SCRIPT_SRC_ATTR = "data-weapp-vite-script-src";
3771
+ const SCRIPT_SETUP_TAG_RE = /<script\b([^>]*)>/gi;
3772
+ /**
3773
+ * 预处理 `<script setup src>`,避免编译器丢失 src。
3774
+ */
3775
+ function preprocessScriptSetupSrc(source) {
3776
+ if (!source.includes("<script") || !source.includes("setup") || !source.includes("src")) return source;
3777
+ return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3778
+ if (!/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3779
+ return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SETUP_SRC_ATTR}$1`)}>`;
3780
+ });
3781
+ }
3782
+ /**
3783
+ * 预处理普通 `<script src>`,避免编译器丢失 src。
3784
+ */
3785
+ function preprocessScriptSrc(source) {
3786
+ if (!source.includes("<script") || !source.includes("src")) return source;
3787
+ return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3788
+ if (/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3789
+ return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SRC_ATTR}$1`)}>`;
3790
+ });
3791
+ }
3792
+ /**
3793
+ * 将预处理的 `<script setup src>` 恢复为真实 src。
3794
+ */
3795
+ function restoreScriptSetupSrc(descriptor) {
3796
+ const scriptSetup = descriptor.scriptSetup;
3797
+ if (!scriptSetup?.attrs || !(SCRIPT_SETUP_SRC_ATTR in scriptSetup.attrs)) return;
3798
+ const raw = scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3799
+ if (typeof raw === "string") scriptSetup.src = raw;
3800
+ delete scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3801
+ }
3802
+ /**
3803
+ * 将预处理的 `<script src>` 恢复为真实 src。
3804
+ */
3805
+ function restoreScriptSrc(descriptor) {
3806
+ const script = descriptor.script;
3807
+ if (!script?.attrs || !(SCRIPT_SRC_ATTR in script.attrs)) return;
3808
+ const raw = script.attrs[SCRIPT_SRC_ATTR];
3809
+ if (typeof raw === "string") script.src = raw;
3810
+ delete script.attrs[SCRIPT_SRC_ATTR];
3811
+ }
3854
3812
  /**
3855
3813
  * 读取并解析 SFC,支持缓存与 src 解析。
3856
3814
  */
@@ -3907,7 +3865,6 @@ async function readAndParseSfc(filename, options) {
3907
3865
  function getSfcCheckMtime(config) {
3908
3866
  return getReadFileCheckMtime(config);
3909
3867
  }
3910
-
3911
3868
  //#endregion
3912
3869
  //#region src/plugins/vue/compiler/style.ts
3913
3870
  /**
@@ -3983,7 +3940,6 @@ function generateHash(str) {
3983
3940
  }
3984
3941
  return Math.abs(hash).toString(36) + str.length.toString(36);
3985
3942
  }
3986
-
3987
3943
  //#endregion
3988
3944
  //#region src/plugins/vue/compiler/template/classStyleRuntime.ts
3989
3945
  /**
@@ -4002,7 +3958,7 @@ function resolveScriptModuleTag(extension) {
4002
3958
  */
4003
3959
  function buildClassStyleWxsTag(extension, src) {
4004
3960
  const normalized = extension.startsWith(".") ? extension.slice(1) : extension;
4005
- const resolvedSrc = src ?? `./${CLASS_STYLE_WXS_FILE}.${normalized}`;
3961
+ const resolvedSrc = src ?? `./__weapp_vite_class_style.${normalized}`;
4006
3962
  return `<${resolveScriptModuleTag(normalized)} module="${CLASS_STYLE_WXS_MODULE}" src="${resolvedSrc}"/>`;
4007
3963
  }
4008
3964
  /**
@@ -4242,104 +4198,10 @@ function getClassStyleWxsSource(options = {}) {
4242
4198
  ""
4243
4199
  ].join("\n");
4244
4200
  }
4245
-
4246
4201
  //#endregion
4247
- //#region src/plugins/vue/compiler/template/elements/helpers.ts
4202
+ //#region src/plugins/vue/compiler/template/elements/forExpression.ts
4248
4203
  const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
4249
4204
  const FOR_ITEM_ALIAS_PLACEHOLDER = "__wv_for_item__";
4250
- function isStructuralDirective(node) {
4251
- for (const prop of node.props) if (prop.type === NodeTypes.DIRECTIVE) {
4252
- if (prop.name === "if" || prop.name === "else-if" || prop.name === "else") return {
4253
- type: "if",
4254
- directive: prop
4255
- };
4256
- if (prop.name === "for") return {
4257
- type: "for",
4258
- directive: prop
4259
- };
4260
- }
4261
- return {
4262
- type: null,
4263
- directive: void 0
4264
- };
4265
- }
4266
- function pushScope(context, names) {
4267
- if (!names.length) return;
4268
- context.scopeStack.push(new Set(names));
4269
- }
4270
- function popScope(context) {
4271
- if (context.scopeStack.length) context.scopeStack.pop();
4272
- }
4273
- function pushForScope(context, info) {
4274
- if (!info.listExp) return;
4275
- context.forStack.push({ ...info });
4276
- }
4277
- function popForScope(context) {
4278
- if (context.forStack.length) context.forStack.pop();
4279
- }
4280
- function withForScope(context, info, fn) {
4281
- pushForScope(context, info);
4282
- try {
4283
- return fn();
4284
- } finally {
4285
- popForScope(context);
4286
- }
4287
- }
4288
- function pushSlotProps(context, mapping) {
4289
- if (!Object.keys(mapping).length) return;
4290
- context.slotPropStack.push(mapping);
4291
- }
4292
- function popSlotProps(context) {
4293
- if (context.slotPropStack.length) context.slotPropStack.pop();
4294
- }
4295
- function withScope(context, names, fn) {
4296
- pushScope(context, names);
4297
- try {
4298
- return fn();
4299
- } finally {
4300
- popScope(context);
4301
- }
4302
- }
4303
- function withSlotProps(context, mapping, fn) {
4304
- pushSlotProps(context, mapping);
4305
- try {
4306
- return fn();
4307
- } finally {
4308
- popSlotProps(context);
4309
- }
4310
- }
4311
- function collectScopePropMapping(context) {
4312
- const mapping = {};
4313
- if (!context.slotMultipleInstance) return mapping;
4314
- for (const scope of context.scopeStack) for (const name of scope) {
4315
- if (!/^[A-Z_$][\w$]*$/i.test(name)) continue;
4316
- if (!Object.prototype.hasOwnProperty.call(mapping, name)) mapping[name] = name;
4317
- }
4318
- return mapping;
4319
- }
4320
- function buildScopePropsExpression(context) {
4321
- const mapping = collectScopePropMapping(context);
4322
- const keys = Object.keys(mapping);
4323
- if (!keys.length) return null;
4324
- return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${key}`).join(",")}]`;
4325
- }
4326
- function toWxmlStringLiteral$1(value) {
4327
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n")}'`;
4328
- }
4329
- function hashString(input) {
4330
- let hash = 0;
4331
- for (let i = 0; i < input.length; i++) {
4332
- hash = (hash << 5) - hash + input.charCodeAt(i);
4333
- hash |= 0;
4334
- }
4335
- return Math.abs(hash).toString(36);
4336
- }
4337
- function isScopedSlotsDisabled(context) {
4338
- return context.scopedSlotsCompiler === "off";
4339
- }
4340
- function findSlotDirective(node) {
4341
- return node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "slot");
4342
- }
4343
4205
  function isIdentifier(value) {
4344
4206
  return IDENTIFIER_RE$1.test(value);
4345
4207
  }
@@ -4513,46 +4375,140 @@ function collectPatternAliases(node, base, aliases) {
4513
4375
  collectPatternAliases(property.value, nextBase, aliases);
4514
4376
  });
4515
4377
  }
4516
- function parseItemAliases(pattern) {
4378
+ function parseItemAliases(pattern) {
4379
+ try {
4380
+ const stmt = parseJsLike(`(${pattern}) => {}`).program.body[0];
4381
+ if (!stmt || stmt.type !== "ExpressionStatement") return {};
4382
+ const exp = stmt.expression;
4383
+ if (!t.isArrowFunctionExpression(exp) || exp.params.length !== 1) return {};
4384
+ const aliases = {};
4385
+ collectPatternAliases(exp.params[0], FOR_ITEM_ALIAS_PLACEHOLDER, aliases);
4386
+ return aliases;
4387
+ } catch {
4388
+ return {};
4389
+ }
4390
+ }
4391
+ function parseForExpression(exp) {
4392
+ const split = splitForExpression(exp.trim());
4393
+ if (!split) return {};
4394
+ const segments = splitTopLevelByComma(stripOuterParentheses(split.source));
4395
+ if (!segments.length || segments.length > 3) return { listExp: split.list };
4396
+ const result = { listExp: split.list };
4397
+ const rawItem = segments[0]?.trim();
4398
+ if (rawItem) if (isIdentifier(rawItem)) result.item = rawItem;
4399
+ else {
4400
+ const aliases = parseItemAliases(rawItem);
4401
+ if (Object.keys(aliases).length) {
4402
+ result.item = FOR_ITEM_ALIAS_PLACEHOLDER;
4403
+ result.itemAliases = aliases;
4404
+ }
4405
+ }
4406
+ if (segments.length === 2) {
4407
+ const rawIndex = segments[1]?.trim();
4408
+ if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4409
+ } else if (segments.length === 3) {
4410
+ const rawKey = segments[1]?.trim();
4411
+ const rawIndex = segments[2]?.trim();
4412
+ if (rawKey && isIdentifier(rawKey)) result.key = rawKey;
4413
+ if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4414
+ }
4415
+ return result;
4416
+ }
4417
+ //#endregion
4418
+ //#region src/plugins/vue/compiler/template/elements/helpers.ts
4419
+ function isStructuralDirective(node) {
4420
+ for (const prop of node.props) if (prop.type === NodeTypes.DIRECTIVE) {
4421
+ if (prop.name === "if" || prop.name === "else-if" || prop.name === "else") return {
4422
+ type: "if",
4423
+ directive: prop
4424
+ };
4425
+ if (prop.name === "for") return {
4426
+ type: "for",
4427
+ directive: prop
4428
+ };
4429
+ }
4430
+ return {
4431
+ type: null,
4432
+ directive: void 0
4433
+ };
4434
+ }
4435
+ function pushScope(context, names) {
4436
+ if (!names.length) return;
4437
+ context.scopeStack.push(new Set(names));
4438
+ }
4439
+ function popScope(context) {
4440
+ if (context.scopeStack.length) context.scopeStack.pop();
4441
+ }
4442
+ function pushForScope(context, info) {
4443
+ if (!info.listExp) return;
4444
+ context.forStack.push({ ...info });
4445
+ }
4446
+ function popForScope(context) {
4447
+ if (context.forStack.length) context.forStack.pop();
4448
+ }
4449
+ function withForScope(context, info, fn) {
4450
+ pushForScope(context, info);
4451
+ try {
4452
+ return fn();
4453
+ } finally {
4454
+ popForScope(context);
4455
+ }
4456
+ }
4457
+ function pushSlotProps(context, mapping) {
4458
+ if (!Object.keys(mapping).length) return;
4459
+ context.slotPropStack.push(mapping);
4460
+ }
4461
+ function popSlotProps(context) {
4462
+ if (context.slotPropStack.length) context.slotPropStack.pop();
4463
+ }
4464
+ function withScope(context, names, fn) {
4465
+ pushScope(context, names);
4466
+ try {
4467
+ return fn();
4468
+ } finally {
4469
+ popScope(context);
4470
+ }
4471
+ }
4472
+ function withSlotProps(context, mapping, fn) {
4473
+ pushSlotProps(context, mapping);
4517
4474
  try {
4518
- const stmt = parseJsLike(`(${pattern}) => {}`).program.body[0];
4519
- if (!stmt || stmt.type !== "ExpressionStatement") return {};
4520
- const exp = stmt.expression;
4521
- if (!t.isArrowFunctionExpression(exp) || exp.params.length !== 1) return {};
4522
- const aliases = {};
4523
- collectPatternAliases(exp.params[0], FOR_ITEM_ALIAS_PLACEHOLDER, aliases);
4524
- return aliases;
4525
- } catch {
4526
- return {};
4475
+ return fn();
4476
+ } finally {
4477
+ popSlotProps(context);
4527
4478
  }
4528
4479
  }
4529
- function parseForExpression(exp) {
4530
- const split = splitForExpression(exp.trim());
4531
- if (!split) return {};
4532
- const segments = splitTopLevelByComma(stripOuterParentheses(split.source));
4533
- if (!segments.length || segments.length > 3) return { listExp: split.list };
4534
- const result = { listExp: split.list };
4535
- const rawItem = segments[0]?.trim();
4536
- if (rawItem) if (isIdentifier(rawItem)) result.item = rawItem;
4537
- else {
4538
- const aliases = parseItemAliases(rawItem);
4539
- if (Object.keys(aliases).length) {
4540
- result.item = FOR_ITEM_ALIAS_PLACEHOLDER;
4541
- result.itemAliases = aliases;
4542
- }
4480
+ function collectScopePropMapping(context) {
4481
+ const mapping = {};
4482
+ if (!context.slotMultipleInstance) return mapping;
4483
+ for (const scope of context.scopeStack) for (const name of scope) {
4484
+ if (!/^[A-Z_$][\w$]*$/i.test(name)) continue;
4485
+ if (!Object.prototype.hasOwnProperty.call(mapping, name)) mapping[name] = name;
4543
4486
  }
4544
- if (segments.length === 2) {
4545
- const rawIndex = segments[1]?.trim();
4546
- if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4547
- } else if (segments.length === 3) {
4548
- const rawKey = segments[1]?.trim();
4549
- const rawIndex = segments[2]?.trim();
4550
- if (rawKey && isIdentifier(rawKey)) result.key = rawKey;
4551
- if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4487
+ return mapping;
4488
+ }
4489
+ function buildScopePropsExpression(context) {
4490
+ const mapping = collectScopePropMapping(context);
4491
+ const keys = Object.keys(mapping);
4492
+ if (!keys.length) return null;
4493
+ return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${key}`).join(",")}]`;
4494
+ }
4495
+ function toWxmlStringLiteral$1(value) {
4496
+ return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n")}'`;
4497
+ }
4498
+ function hashString(input) {
4499
+ let hash = 0;
4500
+ for (let i = 0; i < input.length; i++) {
4501
+ hash = (hash << 5) - hash + input.charCodeAt(i);
4502
+ hash |= 0;
4552
4503
  }
4553
- return result;
4504
+ return Math.abs(hash).toString(36);
4505
+ }
4506
+ function isScopedSlotsDisabled(context) {
4507
+ return context.scopedSlotsCompiler === "off";
4508
+ }
4509
+ function findSlotDirective(node) {
4510
+ return node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "slot");
4554
4511
  }
4555
-
4556
4512
  //#endregion
4557
4513
  //#region src/plugins/vue/compiler/template/expression/scopedSlot.ts
4558
4514
  const SCOPED_SLOT_GLOBALS = new Set([
@@ -4675,7 +4631,6 @@ function normalizeWxmlExpressionWithContext(exp, context) {
4675
4631
  if (!context.rewriteScopedSlot) return rewriteForAliasExpression(exp, context);
4676
4632
  return rewriteScopedSlotExpression(exp, context);
4677
4633
  }
4678
-
4679
4634
  //#endregion
4680
4635
  //#region src/plugins/vue/compiler/template/expression/bindings.ts
4681
4636
  function normalizeClassBindingExpression(exp, context) {
@@ -4775,7 +4730,6 @@ function normalizeStyleBindingExpression(exp, context) {
4775
4730
  if (!out.length) return [normalizeWxmlExpressionWithContext(exp, context)];
4776
4731
  return out;
4777
4732
  }
4778
-
4779
4733
  //#endregion
4780
4734
  //#region src/plugins/vue/compiler/template/expression/inline.ts
4781
4735
  const INLINE_GLOBALS = new Set([
@@ -4948,7 +4902,6 @@ function registerInlineExpression(exp, context) {
4948
4902
  indexBindings: scopeResolvers.length ? indexBindings.map((binding) => binding.binding) : []
4949
4903
  };
4950
4904
  }
4951
-
4952
4905
  //#endregion
4953
4906
  //#region src/plugins/vue/compiler/template/expression/js.ts
4954
4907
  const JS_RUNTIME_GLOBALS = new Set([
@@ -5096,7 +5049,6 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5096
5049
  const stmt = ast.program.body[0];
5097
5050
  return (stmt && "expression" in stmt ? stmt.expression : null) || null;
5098
5051
  }
5099
-
5100
5052
  //#endregion
5101
5053
  //#region src/plugins/vue/compiler/template/expression/runtimeBinding.ts
5102
5054
  function buildForIndexAccess$1(context) {
@@ -5140,13 +5092,11 @@ function registerRuntimeBindingExpression(exp, context, options) {
5140
5092
  context.classStyleBindings.push(binding);
5141
5093
  return `${binding.name}${buildForIndexAccess$1(context)}`;
5142
5094
  }
5143
-
5144
5095
  //#endregion
5145
5096
  //#region src/plugins/vue/compiler/template/mustache.ts
5146
5097
  function renderMustache(expression, context) {
5147
5098
  return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
5148
5099
  }
5149
-
5150
5100
  //#endregion
5151
5101
  //#region src/plugins/vue/compiler/template/attributes.ts
5152
5102
  function toWxmlStringLiteral(value) {
@@ -5163,6 +5113,15 @@ function generateExpressionCode(exp) {
5163
5113
  const { code } = generate(exp, { compact: true });
5164
5114
  return code;
5165
5115
  }
5116
+ function normalizeStyleFallbackValue(value) {
5117
+ return value.trim().replace(/;+\s*$/, "");
5118
+ }
5119
+ function buildStyleErrorFallback(staticValue, shouldHideByDefault) {
5120
+ const segments = [];
5121
+ if (staticValue?.trim()) segments.push(normalizeStyleFallbackValue(staticValue));
5122
+ if (shouldHideByDefault) segments.push("display: none");
5123
+ return segments.join(";");
5124
+ }
5166
5125
  function mergeJsExpressionParts(parts) {
5167
5126
  if (!parts.length) return t.stringLiteral("");
5168
5127
  if (parts.length === 1) return parts[0];
@@ -5198,15 +5157,17 @@ function shouldPreferJsClassStyleRuntime(exp) {
5198
5157
  };
5199
5158
  return visit(ast);
5200
5159
  }
5201
- function createClassStyleBinding(context, type, exp, expAst) {
5160
+ function createClassStyleBinding(context, type, exp, expAst, errorFallback) {
5202
5161
  const sameTypeCount = context.classStyleBindings.filter((binding) => binding.type === type).length;
5203
- return {
5162
+ const binding = {
5204
5163
  name: type === "class" ? `__wv_cls_${sameTypeCount}` : type === "style" ? `__wv_style_${sameTypeCount}` : `__wv_bind_${sameTypeCount}`,
5205
5164
  type,
5206
5165
  exp,
5207
5166
  expAst,
5208
5167
  forStack: cloneForStack(context)
5209
5168
  };
5169
+ if (errorFallback !== void 0) binding.errorFallback = errorFallback;
5170
+ return binding;
5210
5171
  }
5211
5172
  function renderClassAttribute(staticClass, dynamicClassExp, context) {
5212
5173
  const staticValue = staticClass?.trim();
@@ -5225,7 +5186,7 @@ function renderClassAttribute(staticClass, dynamicClassExp, context) {
5225
5186
  const dynamicAst = normalizeJsExpressionWithContext(dynamicClassExp, context, { hint: "class 绑定" });
5226
5187
  if (dynamicAst) jsParts.push(dynamicAst);
5227
5188
  const expAst = mergeJsExpressionParts(jsParts);
5228
- const binding = createClassStyleBinding(context, "class", generateExpressionCode(expAst), expAst);
5189
+ const binding = createClassStyleBinding(context, "class", generateExpressionCode(expAst), expAst, staticValue ?? "");
5229
5190
  context.classStyleBindings.push(binding);
5230
5191
  const indexAccess = buildForIndexAccess(context);
5231
5192
  return `class="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
@@ -5259,7 +5220,7 @@ function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
5259
5220
  if (showAst) jsParts.push(t.conditionalExpression(showAst, t.stringLiteral(""), t.stringLiteral("display: none")));
5260
5221
  }
5261
5222
  const expAst = mergeJsExpressionParts(jsParts);
5262
- const binding = createClassStyleBinding(context, "style", generateExpressionCode(expAst), expAst);
5223
+ const binding = createClassStyleBinding(context, "style", generateExpressionCode(expAst), expAst, buildStyleErrorFallback(staticValue, Boolean(vShowExp)));
5263
5224
  context.classStyleBindings.push(binding);
5264
5225
  const indexAccess = buildForIndexAccess(context);
5265
5226
  return `style="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
@@ -5270,7 +5231,6 @@ function transformAttribute(node, _context) {
5270
5231
  if (value.type === NodeTypes.TEXT) return `${name}="${value.content}"`;
5271
5232
  return `${name}=""`;
5272
5233
  }
5273
-
5274
5234
  //#endregion
5275
5235
  //#region src/plugins/vue/compiler/template/directives/bind.ts
5276
5236
  function unwrapTsExpression(node) {
@@ -5336,7 +5296,6 @@ function transformBindDirective(node, context, forInfo) {
5336
5296
  }
5337
5297
  return `${argValue}="${renderMustache(normalizeWxmlExpressionWithContext(rawExpValue, context), context)}"`;
5338
5298
  }
5339
-
5340
5299
  //#endregion
5341
5300
  //#region src/plugins/vue/compiler/template/directives/custom.ts
5342
5301
  function transformCustomDirective(name, exp, arg, context) {
@@ -5365,7 +5324,6 @@ function transformCustomDirective(name, exp, arg, context) {
5365
5324
  context.warnings.push(`自定义指令 v-${name} 可能需要运行时支持。已生成 data 属性:${dataAttrName}`);
5366
5325
  return dataAttrName;
5367
5326
  }
5368
-
5369
5327
  //#endregion
5370
5328
  //#region src/plugins/vue/compiler/template/directives/model.ts
5371
5329
  function getElementType(element) {
@@ -5405,7 +5363,6 @@ function transformModelDirective(node, context, elementNode) {
5405
5363
  if (!exp) return null;
5406
5364
  return transformVModel(elementNode, normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context), context);
5407
5365
  }
5408
-
5409
5366
  //#endregion
5410
5367
  //#region src/plugins/vue/compiler/template/directives/on.ts
5411
5368
  const isSimpleHandler = (value) => /^[A-Z_$][\w$]*$/i.test(value);
@@ -5492,7 +5449,6 @@ function transformOnDirective(node, context, options) {
5492
5449
  ].filter(Boolean).join(" ");
5493
5450
  return [detailAttr, `${bindAttr}="${expValue}"`].filter(Boolean).join(" ");
5494
5451
  }
5495
-
5496
5452
  //#endregion
5497
5453
  //#region src/plugins/vue/compiler/template/directives/show.ts
5498
5454
  function transformShowDirective(node, context) {
@@ -5500,7 +5456,6 @@ function transformShowDirective(node, context) {
5500
5456
  if (!exp) return null;
5501
5457
  return `style="${renderMustache(`${normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context)} ? '' : 'display: none'`, context)}"`;
5502
5458
  }
5503
-
5504
5459
  //#endregion
5505
5460
  //#region src/plugins/vue/compiler/template/directives/index.ts
5506
5461
  function transformDirective(node, context, elementNode, forInfo, options) {
@@ -5520,7 +5475,6 @@ function transformDirective(node, context, elementNode, forInfo, options) {
5520
5475
  }
5521
5476
  return transformCustomDirective(name, exp, arg, context);
5522
5477
  }
5523
-
5524
5478
  //#endregion
5525
5479
  //#region src/plugins/vue/compiler/template/elements/attrs.ts
5526
5480
  const builtinTagSet = new Set(components.map((tag) => tag.toLowerCase()));
@@ -5611,7 +5565,91 @@ function collectElementAttributes(node, context, options) {
5611
5565
  vTextExp
5612
5566
  };
5613
5567
  }
5614
-
5568
+ //#endregion
5569
+ //#region src/plugins/vue/compiler/template/elements/slotProps.ts
5570
+ function parseSlotPropsExpression(exp, context) {
5571
+ const trimmed = exp.trim();
5572
+ if (!trimmed) return {};
5573
+ try {
5574
+ const stmt = parse$2(`(${trimmed}) => {}`, {
5575
+ sourceType: "module",
5576
+ plugins: ["typescript"]
5577
+ }).program.body[0];
5578
+ if (!stmt || !("expression" in stmt)) return {};
5579
+ const expression = stmt.expression;
5580
+ if (!t.isArrowFunctionExpression(expression)) return {};
5581
+ const param = expression.params[0];
5582
+ if (!param) return {};
5583
+ if (t.isIdentifier(param)) return { [param.name]: "" };
5584
+ if (t.isObjectPattern(param)) {
5585
+ const mapping = {};
5586
+ for (const prop of param.properties) {
5587
+ if (t.isRestElement(prop)) {
5588
+ context.warnings.push("小程序不支持作用域插槽的剩余解构元素。");
5589
+ continue;
5590
+ }
5591
+ if (!t.isObjectProperty(prop)) continue;
5592
+ const key = prop.key;
5593
+ const propName = t.isIdentifier(key) ? key.name : t.isStringLiteral(key) ? key.value : void 0;
5594
+ if (!propName) {
5595
+ context.warnings.push("小程序不支持作用域插槽的计算属性键。");
5596
+ continue;
5597
+ }
5598
+ const value = prop.value;
5599
+ if (t.isIdentifier(value)) {
5600
+ mapping[value.name] = propName;
5601
+ continue;
5602
+ }
5603
+ if (t.isAssignmentPattern(value) && t.isIdentifier(value.left)) {
5604
+ mapping[value.left.name] = propName;
5605
+ context.warnings.push("不支持作用域插槽参数的默认值,默认值将被忽略。");
5606
+ continue;
5607
+ }
5608
+ context.warnings.push("作用域插槽解构仅支持标识符绑定。");
5609
+ }
5610
+ return mapping;
5611
+ }
5612
+ } catch {
5613
+ context.warnings.push("作用域插槽参数解析失败,已回退为空参数。");
5614
+ }
5615
+ return {};
5616
+ }
5617
+ function collectSlotBindingExpression(node, context) {
5618
+ let bindObjectExp = null;
5619
+ const namedBindings = [];
5620
+ for (const prop of node.props) {
5621
+ if (prop.type === NodeTypes.ATTRIBUTE && prop.name === "name") continue;
5622
+ if (prop.type === NodeTypes.DIRECTIVE && prop.name === "bind") {
5623
+ if (prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION) {
5624
+ const rawExpValue = prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION ? prop.exp.content : "";
5625
+ if (prop.arg.content === "name") continue;
5626
+ if (rawExpValue) namedBindings.push({
5627
+ key: prop.arg.content,
5628
+ value: normalizeWxmlExpressionWithContext(rawExpValue, context)
5629
+ });
5630
+ continue;
5631
+ }
5632
+ if (prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
5633
+ bindObjectExp = normalizeWxmlExpressionWithContext(prop.exp.content, context);
5634
+ continue;
5635
+ }
5636
+ }
5637
+ if (prop.type === NodeTypes.ATTRIBUTE && prop.name !== "name") {
5638
+ const literal = prop.value?.type === NodeTypes.TEXT ? prop.value.content : "";
5639
+ if (literal) namedBindings.push({
5640
+ key: prop.name,
5641
+ value: `'${literal.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`
5642
+ });
5643
+ }
5644
+ }
5645
+ if (bindObjectExp && namedBindings.length) {
5646
+ context.warnings.push("作用域插槽参数使用 v-bind 对象时,将忽略额外的命名绑定。");
5647
+ namedBindings.length = 0;
5648
+ }
5649
+ if (bindObjectExp) return bindObjectExp;
5650
+ if (!namedBindings.length) return null;
5651
+ return `[${namedBindings.map((entry) => `${toWxmlStringLiteral$1(entry.key)},${entry.value}`).join(",")}]`;
5652
+ }
5615
5653
  //#endregion
5616
5654
  //#region src/plugins/vue/compiler/template/elements/tag-slot.ts
5617
5655
  function renderSlotNameAttribute(info, context, attrName) {
@@ -5663,53 +5701,6 @@ function stringifySlotName(info, context) {
5663
5701
  if (info.type === "static") return info.value === "default" ? "'default'" : `'${info.value}'`;
5664
5702
  return normalizeWxmlExpressionWithContext(info.exp, context);
5665
5703
  }
5666
- function parseSlotPropsExpression(exp, context) {
5667
- const trimmed = exp.trim();
5668
- if (!trimmed) return {};
5669
- try {
5670
- const stmt = parse$2(`(${trimmed}) => {}`, {
5671
- sourceType: "module",
5672
- plugins: ["typescript"]
5673
- }).program.body[0];
5674
- if (!stmt || !("expression" in stmt)) return {};
5675
- const expression = stmt.expression;
5676
- if (!t.isArrowFunctionExpression(expression)) return {};
5677
- const param = expression.params[0];
5678
- if (!param) return {};
5679
- if (t.isIdentifier(param)) return { [param.name]: "" };
5680
- if (t.isObjectPattern(param)) {
5681
- const mapping = {};
5682
- for (const prop of param.properties) {
5683
- if (t.isRestElement(prop)) {
5684
- context.warnings.push("小程序不支持作用域插槽的剩余解构元素。");
5685
- continue;
5686
- }
5687
- if (!t.isObjectProperty(prop)) continue;
5688
- const key = prop.key;
5689
- const propName = t.isIdentifier(key) ? key.name : t.isStringLiteral(key) ? key.value : void 0;
5690
- if (!propName) {
5691
- context.warnings.push("小程序不支持作用域插槽的计算属性键。");
5692
- continue;
5693
- }
5694
- const value = prop.value;
5695
- if (t.isIdentifier(value)) {
5696
- mapping[value.name] = propName;
5697
- continue;
5698
- }
5699
- if (t.isAssignmentPattern(value) && t.isIdentifier(value.left)) {
5700
- mapping[value.left.name] = propName;
5701
- context.warnings.push("不支持作用域插槽参数的默认值,默认值将被忽略。");
5702
- continue;
5703
- }
5704
- context.warnings.push("作用域插槽解构仅支持标识符绑定。");
5705
- }
5706
- return mapping;
5707
- }
5708
- } catch {
5709
- context.warnings.push("作用域插槽参数解析失败,已回退为空参数。");
5710
- }
5711
- return {};
5712
- }
5713
5704
  function buildSlotDeclaration(name, propsExp, children, context) {
5714
5705
  return {
5715
5706
  name,
@@ -5767,39 +5758,7 @@ function renderSlotFallback(decl, context, transformNode) {
5767
5758
  function transformSlotElement(node, context, transformNode) {
5768
5759
  if (isScopedSlotsDisabled(context)) return transformSlotElementPlain(node, context, transformNode);
5769
5760
  const slotNameInfo = resolveSlotNameFromSlotElement(node);
5770
- let bindObjectExp = null;
5771
- const namedBindings = [];
5772
- for (const prop of node.props) {
5773
- if (prop.type === NodeTypes.ATTRIBUTE && prop.name === "name") continue;
5774
- if (prop.type === NodeTypes.DIRECTIVE && prop.name === "bind") {
5775
- if (prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION) {
5776
- const rawExpValue = prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION ? prop.exp.content : "";
5777
- if (prop.arg.content === "name") continue;
5778
- if (rawExpValue) namedBindings.push({
5779
- key: prop.arg.content,
5780
- value: normalizeWxmlExpressionWithContext(rawExpValue, context)
5781
- });
5782
- continue;
5783
- }
5784
- if (prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
5785
- bindObjectExp = normalizeWxmlExpressionWithContext(prop.exp.content, context);
5786
- continue;
5787
- }
5788
- }
5789
- if (prop.type === NodeTypes.ATTRIBUTE && prop.name !== "name") {
5790
- const literal = prop.value?.type === NodeTypes.TEXT ? prop.value.content : "";
5791
- if (literal) namedBindings.push({
5792
- key: prop.name,
5793
- value: `'${literal.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`
5794
- });
5795
- }
5796
- }
5797
- if (bindObjectExp && namedBindings.length) {
5798
- context.warnings.push("作用域插槽参数使用 v-bind 对象时,将忽略额外的命名绑定。");
5799
- namedBindings.length = 0;
5800
- }
5801
- let slotPropsExp = bindObjectExp;
5802
- if (!slotPropsExp && namedBindings.length) slotPropsExp = `[${namedBindings.map((entry) => `${toWxmlStringLiteral$1(entry.key)},${entry.value}`).join(",")}]`;
5761
+ let slotPropsExp = collectSlotBindingExpression(node, context);
5803
5762
  let fallbackContent = "";
5804
5763
  if (node.children.length > 0) fallbackContent = node.children.map((child) => transformNode(child, context)).join("");
5805
5764
  if (slotPropsExp && fallbackContent) {
@@ -5814,8 +5773,8 @@ function transformSlotElement(node, context, transformNode) {
5814
5773
  if (context.scopedSlotsRequireProps && !slotPropsExp) return slotTag;
5815
5774
  const genericKey = `scoped-slots-${resolveSlotKey(context, slotNameInfo)}`;
5816
5775
  context.componentGenerics[genericKey] = true;
5817
- const resolvedSlotPropsExp = slotPropsExp ?? "[]";
5818
- const scopedAttrs = [`__wv-owner-id="${renderMustache("__wvSlotOwnerId", context)}"`, `__wv-slot-props="${renderMustache(resolvedSlotPropsExp, context)}"`];
5776
+ slotPropsExp = slotPropsExp ?? "[]";
5777
+ const scopedAttrs = [`__wv-owner-id="${renderMustache("__wvSlotOwnerId", context)}"`, `__wv-slot-props="${renderMustache(slotPropsExp, context)}"`];
5819
5778
  if (context.slotMultipleInstance) scopedAttrs.push(`__wv-slot-scope="${renderMustache("__wvSlotScope", context)}"`);
5820
5779
  return `${slotTag}${`<${genericKey}${scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : ""} />`}`;
5821
5780
  }
@@ -5832,7 +5791,6 @@ function transformSlotElementPlain(node, context, transformNode) {
5832
5791
  const slotAttrString = slotAttrs.length ? ` ${slotAttrs.join(" ")}` : "";
5833
5792
  return fallbackContent ? `<slot${slotAttrString}>${fallbackContent}</slot>` : `<slot${slotAttrString} />`;
5834
5793
  }
5835
-
5836
5794
  //#endregion
5837
5795
  //#region src/plugins/vue/compiler/template/elements/tag-component.ts
5838
5796
  function transformComponentWithSlots(node, context, transformNode, options) {
@@ -5985,7 +5943,6 @@ function transformComponentElement(node, context, transformNode) {
5985
5943
  context.warnings.push("动态组件使用 data-is 属性,可能需要小程序运行时支持。");
5986
5944
  return `<component data-is="${renderMustache(componentVar, context)}"${attrString}>${children}</component>`;
5987
5945
  }
5988
-
5989
5946
  //#endregion
5990
5947
  //#region src/plugins/vue/compiler/template/elements/tag-normal.ts
5991
5948
  function transformNormalElement(node, context, transformNode) {
@@ -6000,7 +5957,6 @@ function transformNormalElement(node, context, transformNode) {
6000
5957
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6001
5958
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6002
5959
  }
6003
-
6004
5960
  //#endregion
6005
5961
  //#region src/plugins/vue/compiler/template/elements/tag-structural.ts
6006
5962
  function resolveConditionExpression$1(rawExpValue, context, hint) {
@@ -6035,7 +5991,7 @@ function transformForElement(node, context, transformNode) {
6035
5991
  const forDirective = node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "for");
6036
5992
  if (!forDirective || !forDirective.exp) return transformNormalElement(node, context, transformNode);
6037
5993
  const forInfo = parseForExpression(forDirective.exp.type === NodeTypes.SIMPLE_EXPRESSION ? forDirective.exp.content : "");
6038
- if (forInfo.item === FOR_ITEM_ALIAS_PLACEHOLDER) {
5994
+ if (forInfo.item === "__wv_for_item__") {
6039
5995
  const generatedItem = `__wv_item_${context.forIndexSeed++}`;
6040
5996
  forInfo.item = generatedItem;
6041
5997
  if (forInfo.itemAliases) {
@@ -6088,7 +6044,6 @@ function transformForElement(node, context, transformNode) {
6088
6044
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6089
6045
  }));
6090
6046
  }
6091
-
6092
6047
  //#endregion
6093
6048
  //#region src/plugins/vue/compiler/template/elements/tag-builtin.ts
6094
6049
  function resolveConditionExpression(rawExpValue, context, hint) {
@@ -6158,7 +6113,6 @@ function transformTemplateElement(node, context, transformNode) {
6158
6113
  if (dataAttr) attrs.push(`data="${dataAttr}"`);
6159
6114
  return `<template${attrs.length ? ` ${attrs.join(" ")}` : ""}>${children}</template>`;
6160
6115
  }
6161
-
6162
6116
  //#endregion
6163
6117
  //#region src/plugins/vue/compiler/template/elements/index.ts
6164
6118
  function transformElement(node, context, transformNode) {
@@ -6173,7 +6127,6 @@ function transformElement(node, context, transformNode) {
6173
6127
  if (type === "for") return transformForElement(node, context, transformNode);
6174
6128
  return transformNormalElement(node, context, transformNode);
6175
6129
  }
6176
-
6177
6130
  //#endregion
6178
6131
  //#region src/plugins/vue/compiler/template/nodes.ts
6179
6132
  function escapeWxmlText(value) {
@@ -6203,9 +6156,24 @@ function transformNode(node, context) {
6203
6156
  return "";
6204
6157
  }
6205
6158
  }
6206
-
6207
6159
  //#endregion
6208
6160
  //#region src/plugins/vue/compiler/template.ts
6161
+ const HTML_VOID_TAGS = new Set([
6162
+ "area",
6163
+ "base",
6164
+ "br",
6165
+ "col",
6166
+ "embed",
6167
+ "hr",
6168
+ "img",
6169
+ "input",
6170
+ "link",
6171
+ "meta",
6172
+ "param",
6173
+ "source",
6174
+ "track",
6175
+ "wbr"
6176
+ ]);
6209
6177
  /**
6210
6178
  * 将 Vue 模板编译为 WXML。
6211
6179
  */
@@ -6216,9 +6184,12 @@ function compileVueTemplateToWxml(template, filename, options) {
6216
6184
  const wxsExtension = options?.wxsExtension;
6217
6185
  const scopedSlotsRequireProps = options?.scopedSlotsRequireProps ?? options?.scopedSlotsCompiler !== "augmented";
6218
6186
  try {
6219
- const ast = baseParse(template, { onError: (error) => {
6220
- warnings.push(`模板解析失败:${error.message}`);
6221
- } });
6187
+ const ast = baseParse(template, {
6188
+ isVoidTag: (tag) => HTML_VOID_TAGS.has(tag),
6189
+ onError: (error) => {
6190
+ warnings.push(`模板解析失败:${error.message}`);
6191
+ }
6192
+ });
6222
6193
  const context = {
6223
6194
  source: template,
6224
6195
  filename,
@@ -6270,7 +6241,6 @@ function compileVueTemplateToWxml(template, filename, options) {
6270
6241
  };
6271
6242
  }
6272
6243
  }
6273
-
6274
6244
  //#endregion
6275
6245
  //#region src/plugins/vue/transform/config.ts
6276
6246
  /**
@@ -6361,7 +6331,6 @@ async function compileConfigBlocks(blocks, filename, options) {
6361
6331
  if (Reflect.has(accumulator, "$schema")) delete accumulator.$schema;
6362
6332
  return JSON.stringify(accumulator, null, 2);
6363
6333
  }
6364
-
6365
6334
  //#endregion
6366
6335
  //#region src/plugins/vue/transform/compileVueFile/config.ts
6367
6336
  function collectTemplateAutoImportTags(template, filename, warn) {
@@ -6421,7 +6390,6 @@ async function compileConfigPhase(params) {
6421
6390
  if (scriptSetupMacroConfig && Object.keys(scriptSetupMacroConfig).length > 0) configObj = mergeJson(configObj ?? {}, scriptSetupMacroConfig, "macro");
6422
6391
  if (configObj && Object.keys(configObj).length > 0) result.config = JSON.stringify(configObj, null, 2);
6423
6392
  }
6424
-
6425
6393
  //#endregion
6426
6394
  //#region src/plugins/vue/transform/compileVueFile/finalize.ts
6427
6395
  function finalizeResult(result, options) {
@@ -6429,9 +6397,16 @@ function finalizeResult(result, options) {
6429
6397
  if (result.meta && options.scriptSetupMacroHash) result.meta.jsonMacroHash = options.scriptSetupMacroHash;
6430
6398
  if (result.meta && options.defineOptionsHash) result.meta.defineOptionsHash = options.defineOptionsHash;
6431
6399
  }
6432
-
6433
6400
  //#endregion
6434
- //#region src/plugins/vue/transform/defineOptions/inline.ts
6401
+ //#region src/plugins/vue/transform/defineOptions/serialize.ts
6402
+ function getErrorMessage(error) {
6403
+ if (error instanceof Error) return error.message;
6404
+ return typeof error === "string" ? error : "";
6405
+ }
6406
+ function shouldFallbackToRawDefineOptions(error) {
6407
+ const message = getErrorMessage(error);
6408
+ return /\bBehavior is not defined\b/.test(message);
6409
+ }
6435
6410
  function normalizeScriptSetupLang(lang) {
6436
6411
  if (!lang) return "ts";
6437
6412
  const lower = lang.toLowerCase();
@@ -6528,6 +6503,8 @@ function serializeStaticValueToExpression(value, seen = /* @__PURE__ */ new Weak
6528
6503
  }
6529
6504
  throw new Error(`defineOptions 的参数中包含不支持的值类型:${valueType}`);
6530
6505
  }
6506
+ //#endregion
6507
+ //#region src/plugins/vue/transform/defineOptions/inline.ts
6531
6508
  function collectDefineOptionsStatements(content, filename) {
6532
6509
  const ast = parse$2(content, BABEL_TS_MODULE_PARSER_OPTIONS);
6533
6510
  const statements = [];
@@ -6623,12 +6600,24 @@ async function inlineScriptSetupDefineOptionsArgs(content, filename, lang) {
6623
6600
  code: content,
6624
6601
  dependencies: []
6625
6602
  };
6626
- const { values, dependencies } = await evaluateDefineOptionsValues({
6627
- content,
6628
- filename,
6629
- lang,
6630
- statements
6631
- });
6603
+ let values = [];
6604
+ let dependencies = [];
6605
+ try {
6606
+ const evaluated = await evaluateDefineOptionsValues({
6607
+ content,
6608
+ filename,
6609
+ lang,
6610
+ statements
6611
+ });
6612
+ values = evaluated.values;
6613
+ dependencies = evaluated.dependencies;
6614
+ } catch (error) {
6615
+ if (shouldFallbackToRawDefineOptions(error)) return {
6616
+ code: content,
6617
+ dependencies: []
6618
+ };
6619
+ throw error;
6620
+ }
6632
6621
  const ms = new MagicString(content);
6633
6622
  for (let index = 0; index < statements.length; index += 1) {
6634
6623
  const argNode = statements[index].argPath?.node;
@@ -6641,7 +6630,6 @@ async function inlineScriptSetupDefineOptionsArgs(content, filename, lang) {
6641
6630
  dependencies: dependencies.filter(Boolean)
6642
6631
  };
6643
6632
  }
6644
-
6645
6633
  //#endregion
6646
6634
  //#region src/plugins/vue/transform/compileVueFile/parse.ts
6647
6635
  function extractDefineOptionsHash(content) {
@@ -6789,7 +6777,6 @@ async function parseVueFile(source, filename, options) {
6789
6777
  isAppFile
6790
6778
  };
6791
6779
  }
6792
-
6793
6780
  //#endregion
6794
6781
  //#region src/plugins/vue/transform/compileVueFile/script.ts
6795
6782
  function collectTemplateComponentNames(template, filename, warn) {
@@ -6882,7 +6869,6 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
6882
6869
  autoComponentMeta
6883
6870
  };
6884
6871
  }
6885
-
6886
6872
  //#endregion
6887
6873
  //#region src/plugins/vue/transform/scopedId.ts
6888
6874
  /**
@@ -6894,7 +6880,6 @@ function generateScopedId(filename) {
6894
6880
  }, 0);
6895
6881
  return Math.abs(hash).toString(36);
6896
6882
  }
6897
-
6898
6883
  //#endregion
6899
6884
  //#region src/plugins/vue/transform/compileVueFile/style.ts
6900
6885
  function compileStylePhase(descriptor, filename, result) {
@@ -6920,7 +6905,6 @@ const __cssModules = ${JSON.stringify(modulesMap, null, 2)}
6920
6905
  ${result.script}
6921
6906
  `;
6922
6907
  }
6923
-
6924
6908
  //#endregion
6925
6909
  //#region src/plugins/vue/transform/compileVueFile/template.ts
6926
6910
  function compileTemplatePhase(descriptor, filename, options, result) {
@@ -6932,7 +6916,6 @@ function compileTemplatePhase(descriptor, filename, options, result) {
6932
6916
  if (templateCompiled.classStyleWxs) result.classStyleWxs = true;
6933
6917
  return templateCompiled;
6934
6918
  }
6935
-
6936
6919
  //#endregion
6937
6920
  //#region src/plugins/vue/transform/compileVueFile/index.ts
6938
6921
  /**
@@ -6965,6 +6948,5 @@ async function compileVueFile(source, filename, options) {
6965
6948
  });
6966
6949
  return result;
6967
6950
  }
6968
-
6969
6951
  //#endregion
6970
- export { CLASS_STYLE_WXS_FILE, CLASS_STYLE_WXS_MODULE, RESERVED_VUE_COMPONENT_TAGS, VUE_COMPONENT_TAG_RE, WE_VU_MODULE_ID, WE_VU_PAGE_HOOK_TO_FEATURE, WE_VU_RUNTIME_APIS, alipayPlatform, buildClassStyleComputedCode, buildClassStyleWxsTag, builtinComponentsSet, clearFileCaches, collectVueTemplateTags, collectWevuPageFeatureFlags, compileConfigBlocks, compileJsxFile, compileVueFile as compileSfc, compileVueFile, compileVueStyleToWxss as compileStyle, compileVueStyleToWxss, compileVueTemplateToWxml as compileTemplate, compileVueTemplateToWxml, createJsonMerger, createPageEntryMatcher, evaluateJsLikeConfig, extractJsonMacroFromScriptSetup, generateScopedId, getClassStyleWxsSource, getMiniProgramTemplatePlatform, getSfcCheckMtime, injectWevuPageFeatureFlagsIntoOptionsObject, injectWevuPageFeaturesInJs, injectWevuPageFeaturesInJsWithResolver, invalidateFileCache, isAutoImportCandidateTag, isBuiltinComponent, isInvalidate, isJsonLikeLang, loadCache, mergeJsonWithStrategy, mtimeCache, normalizeConfigLang, pathExists, preprocessScriptSetupSrc, preprocessScriptSrc, readAndParseSfc, readFile, resolveClassStyleWxsLocation, resolveJsLikeLang, resolveSfcBlockSrc, restoreScriptSetupSrc, restoreScriptSrc, stripJsonMacroCallsFromCode, swanPlatform, transformScript, transformScript as transformSfcScript, ttPlatform, wechatPlatform };
6952
+ export { CLASS_STYLE_WXS_FILE, CLASS_STYLE_WXS_MODULE, RESERVED_VUE_COMPONENT_TAGS, VUE_COMPONENT_TAG_RE, WE_VU_MODULE_ID, WE_VU_PAGE_HOOK_TO_FEATURE, WE_VU_RUNTIME_APIS, alipayPlatform, buildClassStyleComputedCode, buildClassStyleWxsTag, builtinComponentsSet, clearFileCaches, collectVueTemplateTags, collectWevuPageFeatureFlags, compileConfigBlocks, compileJsxFile, compileVueFile as compileSfc, compileVueFile, compileVueStyleToWxss as compileStyle, compileVueStyleToWxss, compileVueTemplateToWxml as compileTemplate, compileVueTemplateToWxml, createJsonMerger, createPageEntryMatcher, evaluateJsLikeConfig, extractJsonMacroFromScriptSetup, generateScopedId, getClassStyleWxsSource, getMiniProgramTemplatePlatform, getSfcCheckMtime, injectWevuPageFeatureFlagsIntoOptionsObject, injectWevuPageFeaturesInJs, injectWevuPageFeaturesInJsWithResolver, invalidateFileCache, isAutoImportCandidateTag, isBuiltinComponent, isInvalidate, isJsonLikeLang, loadCache, mergeJsonWithStrategy, mtimeCache, normalizeConfigLang, pathExists, preprocessScriptSetupSrc, preprocessScriptSrc, readAndParseSfc, readFile, resolveClassStyleWxsLocation, resolveJsLikeLang, resolveSfcBlockSrc, restoreScriptSetupSrc, restoreScriptSrc, stripJsonMacroCallsFromCode, swanPlatform, transformScript, transformScript as transformSfcScript, ttPlatform, wechatPlatform };