@wevu/compiler 6.7.3 → 6.7.5

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 +1541 -1377
  3. package/package.json +4 -3
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([
@@ -215,11 +159,12 @@ const RESERVED_VUE_COMPONENT_TAGS = new Set([
215
159
  "suspense"
216
160
  ]);
217
161
  const VUE_COMPONENT_TAG_RE = /^[A-Z_$][\w$]*$/i;
162
+ const PASCAL_CASE_TAG_RE = /^[A-Z][\w$]*$/;
218
163
  /**
219
164
  * 判断模板标签是否可能需要自动导入。
220
165
  */
221
166
  function isAutoImportCandidateTag(tag) {
222
- return tag.includes("-") || /^[A-Z][\w$]*$/.test(tag);
167
+ return tag.includes("-") || PASCAL_CASE_TAG_RE.test(tag);
223
168
  }
224
169
  /**
225
170
  * 收集 Vue 模板中的自定义组件标签。
@@ -255,594 +200,185 @@ function collectVueTemplateTags(template, options) {
255
200
  }
256
201
  return tags;
257
202
  }
258
-
259
203
  //#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
204
+ //#region src/plugins/vue/transform/jsonMacros/analyze.ts
205
+ function collectPatternNames(pattern, out) {
206
+ if (!pattern) return;
207
+ if (t.isIdentifier(pattern)) {
208
+ out.add(pattern.name);
209
+ return;
268
210
  }
269
- };
270
- function generateExpression(node) {
271
- const { code } = generate(node, BABEL_GENERATE_MINI_PROGRAM_OPTIONS);
272
- return code;
211
+ if (t.isRestElement(pattern)) {
212
+ collectPatternNames(pattern.argument, out);
213
+ return;
214
+ }
215
+ if (t.isAssignmentPattern(pattern)) {
216
+ collectPatternNames(pattern.left, out);
217
+ return;
218
+ }
219
+ if (t.isObjectPattern(pattern)) {
220
+ for (const prop of pattern.properties) if (t.isRestElement(prop)) collectPatternNames(prop.argument, out);
221
+ else if (t.isObjectProperty(prop)) collectPatternNames(prop.value, out);
222
+ return;
223
+ }
224
+ if (t.isArrayPattern(pattern)) for (const el of pattern.elements) collectPatternNames(el, out);
273
225
  }
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;
226
+ function declaredNamesInStatement(statement) {
227
+ const out = /* @__PURE__ */ new Set();
228
+ if (t.isImportDeclaration(statement)) {
229
+ for (const specifier of statement.specifiers) if (t.isImportSpecifier(specifier) || t.isImportDefaultSpecifier(specifier) || t.isImportNamespaceSpecifier(specifier)) {
230
+ if (t.isIdentifier(specifier.local)) out.add(specifier.local.name);
285
231
  }
286
- const expression = stmt.expression;
287
- babelExpressionCache.set(exp, expression);
288
- return expression;
289
- } catch {
290
- babelExpressionCache.set(exp, false);
291
- return null;
232
+ return out;
292
233
  }
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;
234
+ if (t.isVariableDeclaration(statement)) {
235
+ for (const decl of statement.declarations) collectPatternNames(decl.id, out);
236
+ return out;
237
+ }
238
+ if (t.isFunctionDeclaration(statement) || t.isClassDeclaration(statement)) {
239
+ if (statement.id && t.isIdentifier(statement.id)) out.add(statement.id.name);
240
+ return out;
308
241
  }
242
+ if (t.isExportNamedDeclaration(statement) && statement.declaration) return declaredNamesInStatement(statement.declaration);
243
+ return out;
309
244
  }
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);
245
+ function collectTopLevelReferencedNames(path) {
246
+ const names = /* @__PURE__ */ new Set();
247
+ if (!path) return names;
248
+ const addIfTopLevelReferenced = (p) => {
249
+ if (!p?.isReferencedIdentifier?.()) return;
250
+ const name = p.node.name;
251
+ const binding = p.scope?.getBinding(name);
252
+ if (!binding) return;
253
+ if (binding.scope?.block?.type === "Program") names.add(name);
254
+ };
255
+ addIfTopLevelReferenced(path);
256
+ path.traverse({
257
+ Function(p) {
258
+ if (p.node !== path.node) p.skip();
259
+ },
260
+ Class(p) {
261
+ if (p.node !== path.node) p.skip();
262
+ },
263
+ Identifier(p) {
264
+ addIfTopLevelReferenced(p);
322
265
  }
323
266
  });
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)));
267
+ return names;
330
268
  }
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;
269
+ function collectKeptStatementPaths(programPath, macroStatements) {
270
+ const bodyPaths = programPath.get("body");
271
+ const nameToStatementPath = /* @__PURE__ */ new Map();
272
+ for (const statementPath of bodyPaths) {
273
+ const declared = declaredNamesInStatement(statementPath.node);
274
+ for (const name of declared) if (!nameToStatementPath.has(name)) nameToStatementPath.set(name, statementPath);
351
275
  }
352
- if (!t.isExpression(current)) return null;
276
+ const neededNames = /* @__PURE__ */ new Set();
277
+ for (const statementPath of macroStatements) {
278
+ const deps = collectTopLevelReferencedNames(statementPath.get("expression").get("arguments.0"));
279
+ for (const dep of deps) neededNames.add(dep);
280
+ }
281
+ const keptStatementPaths = /* @__PURE__ */ new Set();
282
+ const queue = [...neededNames];
283
+ while (queue.length) {
284
+ const name = queue.pop();
285
+ const declPath = nameToStatementPath.get(name);
286
+ if (!declPath || keptStatementPaths.has(declPath)) continue;
287
+ keptStatementPaths.add(declPath);
288
+ const deps = collectTopLevelReferencedNames(declPath);
289
+ for (const dep of deps) if (dep !== name) queue.push(dep);
290
+ }
291
+ for (const statementPath of macroStatements) keptStatementPaths.add(statementPath);
353
292
  return {
354
- base: t.cloneNode(current),
355
- operations: operations.reverse()
293
+ bodyPaths,
294
+ keptStatementPaths
356
295
  };
357
296
  }
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);
297
+ //#endregion
298
+ //#region src/plugins/vue/transform/tempDirLock.ts
299
+ const locks = /* @__PURE__ */ new Map();
300
+ async function withTempDirLock(tempDir, fn) {
301
+ const previous = locks.get(tempDir) ?? Promise.resolve();
302
+ let release;
303
+ const gate = new Promise((resolve) => {
304
+ release = resolve;
305
+ });
306
+ const current = previous.then(() => gate);
307
+ locks.set(tempDir, current);
308
+ try {
309
+ await previous;
310
+ return await fn();
311
+ } finally {
312
+ release?.();
313
+ if (locks.get(tempDir) === current) locks.delete(tempDir);
374
314
  }
375
- return lowered;
376
315
  }
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
316
  //#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"
317
+ //#region src/utils/babel.ts
318
+ const BABEL_TS_MODULE_PLUGINS = [
319
+ "typescript",
320
+ "decorators-legacy",
321
+ "classProperties",
322
+ "classPrivateProperties",
323
+ "classPrivateMethods",
324
+ "jsx"
325
+ ];
326
+ const BABEL_TS_MODULE_PARSER_OPTIONS = {
327
+ sourceType: "module",
328
+ plugins: BABEL_TS_MODULE_PLUGINS
446
329
  };
447
- function toOnEventName(eventName) {
448
- if (!eventName) return "on";
449
- return `on${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
330
+ const nodeRequire = createRequire(import.meta.url);
331
+ let cachedTraverse;
332
+ let cachedGenerate;
333
+ function requireCallableDefault(id) {
334
+ const mod = nodeRequire(id);
335
+ if (typeof mod === "function") return mod;
336
+ if (mod && (typeof mod === "object" || typeof mod === "function") && "default" in mod) {
337
+ const candidate = mod.default;
338
+ if (typeof candidate === "function") return candidate;
339
+ }
340
+ throw new TypeError(`Invalid module shape for ${id}`);
450
341
  }
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
- };
342
+ function getTraverse() {
343
+ if (!cachedTraverse) cachedTraverse = requireCallableDefault("@babel/traverse");
344
+ return cachedTraverse;
461
345
  }
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
- }
346
+ function getGenerate() {
347
+ if (!cachedGenerate) cachedGenerate = requireCallableDefault("@babel/generator");
348
+ return cachedGenerate;
471
349
  }
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
- }
350
+ const traverse = (...args) => {
351
+ return getTraverse()(...args);
494
352
  };
495
-
496
- //#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"
353
+ const generate = (...args) => {
354
+ return getGenerate()(...args);
519
355
  };
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("-");
356
+ function parseJsLike(source) {
357
+ return parse$2(source, {
358
+ sourceType: "module",
359
+ plugins: [
360
+ ...BABEL_TS_MODULE_PLUGINS,
361
+ "dynamicImport",
362
+ "optionalChaining",
363
+ "nullishCoalescingOperator"
364
+ ]
365
+ });
533
366
  }
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
- }
560
- }
561
- };
562
-
563
367
  //#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
- };
368
+ //#region src/utils/path.ts
369
+ const BACKSLASH_RE$4 = /\\/g;
370
+ const LEADING_SLASH_RE = /^[\\/]+/;
371
+ const DUPLICATE_SLASH_RE = /\/{2,}/g;
372
+ const TRIM_SLASH_RE = /^\/+|\/+$/g;
373
+ function toPosixPath(value) {
374
+ return value.replace(BACKSLASH_RE$4, "/");
597
375
  }
598
- function shouldUseColonEventBinding$1(name) {
599
- return name.includes(":") || name.includes("-");
600
- }
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
- };
664
- }
665
- function shouldUseColonEventBinding(name) {
666
- return name.includes(":") || name.includes("-");
667
- }
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
- }
695
- };
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
706
- };
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;
818
- });
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
- }
829
-
830
- //#endregion
831
- //#region src/utils/path.ts
832
- const BACKSLASH_RE$1 = /\\/g;
833
- const LEADING_SLASH_RE = /^[\\/]+/;
834
- const DUPLICATE_SLASH_RE = /\/{2,}/g;
835
- const TRIM_SLASH_RE = /^\/+|\/+$/g;
836
- function toPosixPath(value) {
837
- return value.replace(BACKSLASH_RE$1, "/");
838
- }
839
- function stripLeadingSlashes(value) {
840
- return value.replace(LEADING_SLASH_RE, "");
376
+ function stripLeadingSlashes(value) {
377
+ return value.replace(LEADING_SLASH_RE, "");
841
378
  }
842
379
  function normalizeRoot(root) {
843
380
  return toPosixPath(root).replace(DUPLICATE_SLASH_RE, "/").replace(TRIM_SLASH_RE, "");
844
381
  }
845
-
846
382
  //#endregion
847
383
  //#region src/plugins/vue/transform/tempImportRewrite.ts
848
384
  function rewriteRelativeImportSource(source, fromDir, tempDir) {
@@ -893,7 +429,6 @@ function rewriteJsLikeImportsForTempDir(source, fromDir, tempDir) {
893
429
  });
894
430
  return mutated ? ms.toString() : source;
895
431
  }
896
-
897
432
  //#endregion
898
433
  //#region src/plugins/vue/transform/wevuTempDir.ts
899
434
  function getWevuConfigCacheRoot() {
@@ -909,7 +444,6 @@ function resolveWevuConfigTempDir(fromDir) {
909
444
  const key = createHash("sha256").update(path.normalize(fromDir)).digest("hex").slice(0, 8);
910
445
  return path.join(root, key);
911
446
  }
912
-
913
447
  //#endregion
914
448
  //#region src/plugins/vue/transform/jsonMacros/execute.ts
915
449
  function normalizeScriptSetupLang$1(lang) {
@@ -980,7 +514,7 @@ const __weapp_defineThemeJson = (config) => (__weapp_json_macro_values.push(conf
980
514
  if (typeof next === "function") next = next();
981
515
  if (next && typeof next.then === "function") next = await next;
982
516
  if (!next || typeof next !== "object" || Array.isArray(next)) throw new Error("宏的返回值必须解析为对象。");
983
- if (Object.prototype.hasOwnProperty.call(next, "$schema")) delete next.$schema;
517
+ if (Object.hasOwn(next, "$schema")) delete next.$schema;
984
518
  if (options?.merge) {
985
519
  const merged = options.merge(accumulator, next);
986
520
  if (merged && typeof merged === "object" && !Array.isArray(merged)) accumulator = merged;
@@ -1001,7 +535,6 @@ const __weapp_defineThemeJson = (config) => (__weapp_json_macro_values.push(conf
1001
535
  }
1002
536
  });
1003
537
  }
1004
-
1005
538
  //#endregion
1006
539
  //#region src/plugins/vue/transform/jsonMacros/parse.ts
1007
540
  const JSON_MACROS = new Set([
@@ -1036,7 +569,7 @@ function collectMacroCallPaths(ast, filename) {
1036
569
  };
1037
570
  }
1038
571
  function assertSingleMacro(macroNames, filename) {
1039
- if (macroNames.size > 1) throw new Error(`同一个 <script setup> 仅能使用 ${Array.from(JSON_MACROS).join(", ")} 中的一个(${filename})。`);
572
+ if (macroNames.size > 1) throw new Error(`同一个 <script setup> 仅能使用 ${[...JSON_MACROS].join(", ")} 中的一个(${filename})。`);
1040
573
  return macroNames.values().next().value;
1041
574
  }
1042
575
  function findProgramPath(ast) {
@@ -1047,7 +580,6 @@ function findProgramPath(ast) {
1047
580
  } });
1048
581
  return programPath;
1049
582
  }
1050
-
1051
583
  //#endregion
1052
584
  //#region src/plugins/vue/transform/jsonMacros/rewrite.ts
1053
585
  /**
@@ -1099,7 +631,6 @@ function stripJsonMacroCallsFromCode(code, filename) {
1099
631
  } });
1100
632
  return ms.toString();
1101
633
  }
1102
-
1103
634
  //#endregion
1104
635
  //#region src/plugins/vue/transform/jsonMacros/index.ts
1105
636
  /**
@@ -1142,7 +673,6 @@ async function evaluateJsonMacroConfig(content, filename, lang, options) {
1142
673
  options
1143
674
  });
1144
675
  }
1145
-
1146
676
  //#endregion
1147
677
  //#region src/plugins/vue/transform/jsonMerge.ts
1148
678
  function toPlainRecord(value) {
@@ -1180,7 +710,6 @@ function createJsonMerger(strategy, baseContext) {
1180
710
  });
1181
711
  };
1182
712
  }
1183
-
1184
713
  //#endregion
1185
714
  //#region src/utils/warn.ts
1186
715
  /**
@@ -1191,7 +720,6 @@ function resolveWarnHandler(warn) {
1191
720
  console.warn(message);
1192
721
  });
1193
722
  }
1194
-
1195
723
  //#endregion
1196
724
  //#region src/plugins/wevu/pageFeatures/astUtils.ts
1197
725
  function isStaticObjectKeyMatch$1(key, expected) {
@@ -1207,7 +735,7 @@ function getObjectPropertyByKey$2(node, key) {
1207
735
  return null;
1208
736
  }
1209
737
  function buildInjectedFeaturesObject(enabled) {
1210
- return t.objectExpression(Array.from(enabled).map((key) => {
738
+ return t.objectExpression(Array.from(enabled, (key) => {
1211
739
  return t.objectProperty(t.identifier(key), t.booleanLiteral(true));
1212
740
  }));
1213
741
  }
@@ -1221,7 +749,6 @@ function getObjectMemberIndexByKey(node, key) {
1221
749
  function isTopLevel(path) {
1222
750
  return path.getFunctionParent() == null;
1223
751
  }
1224
-
1225
752
  //#endregion
1226
753
  //#region src/plugins/wevu/pageFeatures/flags.ts
1227
754
  function injectWevuShareLifecycleHooksIntoOptionsObject(_optionsObject, _enabled) {
@@ -1234,7 +761,7 @@ function collectWevuPageFeatureFlags(ast) {
1234
761
  const namedHookLocals = /* @__PURE__ */ new Map();
1235
762
  const namespaceLocals = /* @__PURE__ */ new Set();
1236
763
  for (const stmt of ast.program.body) {
1237
- if (!t.isImportDeclaration(stmt) || stmt.source.value !== WE_VU_MODULE_ID) continue;
764
+ if (!t.isImportDeclaration(stmt) || stmt.source.value !== "wevu") continue;
1238
765
  for (const specifier of stmt.specifiers) if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
1239
766
  const matched = WE_VU_PAGE_HOOK_TO_FEATURE[specifier.imported.name];
1240
767
  if (matched) namedHookLocals.set(specifier.local.name, matched);
@@ -1282,7 +809,7 @@ function collectWevuPageFeatureFlags(ast) {
1282
809
  */
1283
810
  function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
1284
811
  if (!enabled.size) return false;
1285
- const expectedKeys = Array.from(enabled);
812
+ const expectedKeys = [...enabled];
1286
813
  const existingFeaturesProp = getObjectPropertyByKey$2(optionsObject, "features");
1287
814
  let changed = false;
1288
815
  if (!existingFeaturesProp) {
@@ -1312,7 +839,6 @@ function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
1312
839
  changed = injectWevuShareLifecycleHooksIntoOptionsObject(optionsObject, enabled) || changed;
1313
840
  return changed;
1314
841
  }
1315
-
1316
842
  //#endregion
1317
843
  //#region src/plugins/wevu/pageFeatures/moduleAnalysis.ts
1318
844
  const externalModuleAnalysisCache = new LRUCache({ max: 256 });
@@ -1360,7 +886,7 @@ function createModuleAnalysis(id, ast) {
1360
886
  const source = stmt.source.value;
1361
887
  for (const specifier of stmt.specifiers) if (t.isImportSpecifier(specifier)) {
1362
888
  const imported = specifier.imported;
1363
- if (source === WE_VU_MODULE_ID && t.isIdentifier(imported)) {
889
+ if (source === "wevu" && t.isIdentifier(imported)) {
1364
890
  const matched = WE_VU_PAGE_HOOK_TO_FEATURE[imported.name];
1365
891
  if (matched) wevuNamedHookLocals.set(specifier.local.name, matched);
1366
892
  }
@@ -1378,7 +904,7 @@ function createModuleAnalysis(id, ast) {
1378
904
  kind: "namespace",
1379
905
  source
1380
906
  });
1381
- if (source === WE_VU_MODULE_ID) wevuNamespaceLocals.add(specifier.local.name);
907
+ if (source === "wevu") wevuNamespaceLocals.add(specifier.local.name);
1382
908
  }
1383
909
  continue;
1384
910
  }
@@ -1459,7 +985,6 @@ function createModuleAnalysis(id, ast) {
1459
985
  exports
1460
986
  };
1461
987
  }
1462
-
1463
988
  //#endregion
1464
989
  //#region src/plugins/wevu/pageFeatures/optionsObjects.ts
1465
990
  function unwrapTypeLikeExpression$2(node) {
@@ -1508,11 +1033,11 @@ function collectTargetOptionsObjects(ast, moduleId) {
1508
1033
  if (!first || !t.isExpression(first)) return;
1509
1034
  const binding = t.isIdentifier(node.callee) ? module.importedBindings.get(node.callee.name) : void 0;
1510
1035
  if (t.isIdentifier(node.callee)) {
1511
- if (binding?.kind !== "named" || binding.source !== WE_VU_MODULE_ID) return;
1036
+ if (binding?.kind !== "named" || binding.source !== "wevu") return;
1512
1037
  if (binding.importedName !== WE_VU_RUNTIME_APIS.defineComponent && binding.importedName !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1513
1038
  } else if (t.isMemberExpression(node.callee) && !node.callee.computed && t.isIdentifier(node.callee.object) && t.isIdentifier(node.callee.property)) {
1514
1039
  const objectBinding = module.importedBindings.get(node.callee.object.name);
1515
- if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1040
+ if (objectBinding?.kind !== "namespace" || objectBinding.source !== "wevu") return;
1516
1041
  if (node.callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && node.callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1517
1042
  } else return;
1518
1043
  const inlineObject = resolveOptionsObjectFromExpression(first);
@@ -1532,11 +1057,11 @@ function collectTargetOptionsObjects(ast, moduleId) {
1532
1057
  if (!first || !t.isExpression(first)) return;
1533
1058
  if (t.isIdentifier(callee)) {
1534
1059
  const binding = module.importedBindings.get(callee.name);
1535
- if (binding?.kind !== "named" || binding.source !== WE_VU_MODULE_ID) return;
1060
+ if (binding?.kind !== "named" || binding.source !== "wevu") return;
1536
1061
  if (binding.importedName !== WE_VU_RUNTIME_APIS.defineComponent && binding.importedName !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1537
1062
  } else if (t.isMemberExpression(callee) && !callee.computed && t.isIdentifier(callee.object) && t.isIdentifier(callee.property)) {
1538
1063
  const objectBinding = module.importedBindings.get(callee.object.name);
1539
- if (objectBinding?.kind !== "namespace" || objectBinding.source !== WE_VU_MODULE_ID) return;
1064
+ if (objectBinding?.kind !== "namespace" || objectBinding.source !== "wevu") return;
1540
1065
  if (callee.property.name !== WE_VU_RUNTIME_APIS.defineComponent && callee.property.name !== WE_VU_RUNTIME_APIS.createWevuComponent) return;
1541
1066
  } else return;
1542
1067
  const inlineObject = resolveOptionsObjectFromExpression(first);
@@ -1557,7 +1082,6 @@ function collectTargetOptionsObjects(ast, moduleId) {
1557
1082
  module
1558
1083
  };
1559
1084
  }
1560
-
1561
1085
  //#endregion
1562
1086
  //#region src/plugins/wevu/pageFeatures/reachability/calls.ts
1563
1087
  function getCallCalleeName(callee) {
@@ -1586,7 +1110,6 @@ function collectCalledBindingsFromFunctionBody(fn) {
1586
1110
  });
1587
1111
  return called;
1588
1112
  }
1589
-
1590
1113
  //#endregion
1591
1114
  //#region src/plugins/wevu/pageFeatures/reachability/hooks.ts
1592
1115
  function collectWevuHookCallsInFunctionBody(module, fn) {
@@ -1620,7 +1143,6 @@ function collectWevuHookCallsInFunctionBody(module, fn) {
1620
1143
  });
1621
1144
  return enabled;
1622
1145
  }
1623
-
1624
1146
  //#endregion
1625
1147
  //#region src/plugins/wevu/pageFeatures/reachability/resolve.ts
1626
1148
  function resolveExportedFunctionNode(module, exportName) {
@@ -1638,7 +1160,7 @@ function resolveExportedFunctionNode(module, exportName) {
1638
1160
  return null;
1639
1161
  }
1640
1162
  async function resolveExternalFunction(resolver, importerId, source, exportName, moduleCache) {
1641
- if (source === WE_VU_MODULE_ID) return null;
1163
+ if (source === "wevu") return null;
1642
1164
  const resolvedId = await resolver.resolveId(source, importerId);
1643
1165
  if (!resolvedId) return null;
1644
1166
  const code = await resolver.loadCode(resolvedId);
@@ -1664,7 +1186,6 @@ async function resolveExternalFunction(resolver, importerId, source, exportName,
1664
1186
  };
1665
1187
  return null;
1666
1188
  }
1667
-
1668
1189
  //#endregion
1669
1190
  //#region src/plugins/wevu/pageFeatures/reachability/walk.ts
1670
1191
  async function walkReachableWevuFeatures(options) {
@@ -1755,7 +1276,6 @@ async function walkReachableWevuFeatures(options) {
1755
1276
  }
1756
1277
  return enabled;
1757
1278
  }
1758
-
1759
1279
  //#endregion
1760
1280
  //#region src/plugins/wevu/pageFeatures/reachability/index.ts
1761
1281
  async function collectWevuFeaturesFromSetupReachableImports(pageModule, setupFn, resolver, moduleCache) {
@@ -1766,7 +1286,6 @@ async function collectWevuFeaturesFromSetupReachableImports(pageModule, setupFn,
1766
1286
  moduleCache
1767
1287
  });
1768
1288
  }
1769
-
1770
1289
  //#endregion
1771
1290
  //#region src/plugins/wevu/pageFeatures/inject.ts
1772
1291
  /**
@@ -1830,7 +1349,6 @@ async function injectWevuPageFeaturesInJsWithResolver(source, options) {
1830
1349
  transformed: true
1831
1350
  };
1832
1351
  }
1833
-
1834
1352
  //#endregion
1835
1353
  //#region src/plugins/wevu/pageFeatures/matcher.ts
1836
1354
  /**
@@ -1881,7 +1399,6 @@ function createPageEntryMatcher(source) {
1881
1399
  }
1882
1400
  };
1883
1401
  }
1884
-
1885
1402
  //#endregion
1886
1403
  //#region src/plugins/vue/transform/scriptTemplateMeta.ts
1887
1404
  function injectTemplateComponentMeta(ast, templateComponentMeta) {
@@ -1925,7 +1442,6 @@ function injectTemplateComponentMeta(ast, templateComponentMeta) {
1925
1442
  }
1926
1443
  return changed;
1927
1444
  }
1928
-
1929
1445
  //#endregion
1930
1446
  //#region src/plugins/vue/transform/scriptVueSfcTransform.ts
1931
1447
  /**
@@ -1966,7 +1482,6 @@ function vueSfcTransformPlugin() {
1966
1482
  }
1967
1483
  };
1968
1484
  }
1969
-
1970
1485
  //#endregion
1971
1486
  //#region src/plugins/vue/transform/scriptComponent.ts
1972
1487
  function isDefineComponentCall(node, aliases) {
@@ -2025,7 +1540,6 @@ function resolveComponentOptionsObject(componentExpr) {
2025
1540
  if (t.isCallExpression(normalized)) return resolveObjectExpressionFromAssignCall(normalized);
2026
1541
  return null;
2027
1542
  }
2028
-
2029
1543
  //#endregion
2030
1544
  //#region src/plugins/vue/transform/transformScript/collect.ts
2031
1545
  function createCollectVisitors(state) {
@@ -2045,11 +1559,9 @@ function createCollectVisitors(state) {
2045
1559
  }
2046
1560
  };
2047
1561
  }
2048
-
2049
1562
  //#endregion
2050
1563
  //#region src/plugins/vue/transform/constants.ts
2051
1564
  const RUNTIME_IMPORT_PATH = WE_VU_MODULE_ID;
2052
-
2053
1565
  //#endregion
2054
1566
  //#region src/plugins/vue/transform/scriptRuntimeImport.ts
2055
1567
  function ensureRuntimeImport(program, importedName, localName = importedName) {
@@ -2065,7 +1577,6 @@ function ensureRuntimeImport(program, importedName, localName = importedName) {
2065
1577
  return t.isIdentifier(spec.local, { name: localName });
2066
1578
  })) targetImport.specifiers.push(t.importSpecifier(t.identifier(localName), t.identifier(importedName)));
2067
1579
  }
2068
-
2069
1580
  //#endregion
2070
1581
  //#region src/plugins/vue/transform/transformScript/imports.ts
2071
1582
  function createImportVisitors(program, state) {
@@ -2126,7 +1637,6 @@ function createImportVisitors(program, state) {
2126
1637
  }
2127
1638
  } };
2128
1639
  }
2129
-
2130
1640
  //#endregion
2131
1641
  //#region src/plugins/vue/transform/transformScript/macros/setupExpose.ts
2132
1642
  function createSetupExposeVisitors(state) {
@@ -2148,7 +1658,6 @@ function createSetupExposeVisitors(state) {
2148
1658
  }
2149
1659
  } };
2150
1660
  }
2151
-
2152
1661
  //#endregion
2153
1662
  //#region src/plugins/vue/transform/transformScript/macros/optional.ts
2154
1663
  function isOptionalPatternNode(node) {
@@ -2186,7 +1695,6 @@ function stripOptionalFromPattern(pattern) {
2186
1695
  }
2187
1696
  return changed;
2188
1697
  }
2189
-
2190
1698
  //#endregion
2191
1699
  //#region src/plugins/vue/transform/transformScript/macros/stripTypes.ts
2192
1700
  function createStripTypesVisitors(state) {
@@ -2321,7 +1829,6 @@ function createStripTypesVisitors(state) {
2321
1829
  }
2322
1830
  };
2323
1831
  }
2324
-
2325
1832
  //#endregion
2326
1833
  //#region src/plugins/vue/transform/transformScript/macros/index.ts
2327
1834
  function createMacroVisitors(state) {
@@ -2330,9 +1837,8 @@ function createMacroVisitors(state) {
2330
1837
  ...createStripTypesVisitors(state)
2331
1838
  };
2332
1839
  }
2333
-
2334
1840
  //#endregion
2335
- //#region src/plugins/vue/transform/classStyleComputed.ts
1841
+ //#region src/plugins/vue/transform/classStyleComputedBuilders.ts
2336
1842
  function createStaticObjectKey$1(key) {
2337
1843
  return t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
2338
1844
  }
@@ -2346,9 +1852,10 @@ function buildNormalizedExpression(binding, helpers) {
2346
1852
  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
1853
  }
2348
1854
  const normalizeHelper = binding.type === "class" ? helpers.normalizeClass : helpers.normalizeStyle;
1855
+ const errorFallback = binding.errorFallback ?? "";
2349
1856
  const exp = binding.expAst ? t.cloneNode(binding.expAst, true) : t.stringLiteral("");
2350
1857
  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)])), []);
1858
+ 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)])), []);
2352
1859
  }
2353
1860
  function buildArrayMapExpression(binding, forStack, level, listId, helpers) {
2354
1861
  const itemParam = createValidIdentifier(forStack[level].item, `__wv_item_${level}`);
@@ -2413,6 +1920,8 @@ function buildComputedFunctionBody(binding, helpers) {
2413
1920
  const expr = buildForExpression(binding, binding.forStack ?? [], 0, helpers);
2414
1921
  return t.blockStatement([t.returnStatement(expr)]);
2415
1922
  }
1923
+ //#endregion
1924
+ //#region src/plugins/vue/transform/classStyleComputed.ts
2416
1925
  function buildClassStyleComputedEntries(bindings, helpers) {
2417
1926
  const entries = [];
2418
1927
  for (const binding of bindings) {
@@ -2440,7 +1949,6 @@ function buildClassStyleComputedCode(bindings, helpers) {
2440
1949
  const { code } = generate(obj, { compact: true });
2441
1950
  return code;
2442
1951
  }
2443
-
2444
1952
  //#endregion
2445
1953
  //#region src/plugins/vue/transform/transformScript/utils.ts
2446
1954
  function isPlainRecord(value) {
@@ -2463,7 +1971,6 @@ function getObjectPropertyByKey$1(node, key) {
2463
1971
  function createStaticObjectKey(key) {
2464
1972
  return t.isValidIdentifier(key) ? t.identifier(key) : t.stringLiteral(key);
2465
1973
  }
2466
-
2467
1974
  //#endregion
2468
1975
  //#region src/plugins/vue/transform/transformScript/rewrite/classStyle.ts
2469
1976
  function injectClassStyleComputed(optionsObject, bindings, warn) {
@@ -2496,7 +2003,6 @@ function ensureClassStyleRuntimeImports(program) {
2496
2003
  ensureRuntimeImport(program, "normalizeStyle", "__wevuNormalizeStyle");
2497
2004
  ensureRuntimeImport(program, "unref", "__wevuUnref");
2498
2005
  }
2499
-
2500
2006
  //#endregion
2501
2007
  //#region src/plugins/vue/transform/transformScript/rewrite/defaults.ts
2502
2008
  function mergePlainDefaultsIntoObjectExpression(target, defaults) {
@@ -2571,7 +2077,7 @@ function stripVirtualHostFromDefaults(defaults) {
2571
2077
  const next = { ...defaults };
2572
2078
  const options = next.options;
2573
2079
  if (!isPlainRecord(options)) return next;
2574
- if (!Object.prototype.hasOwnProperty.call(options, "virtualHost")) return next;
2080
+ if (!Object.hasOwn(options, "virtualHost")) return next;
2575
2081
  const copiedOptions = { ...options };
2576
2082
  delete copiedOptions.virtualHost;
2577
2083
  if (Object.keys(copiedOptions).length > 0) next.options = copiedOptions;
@@ -2624,7 +2130,6 @@ function injectWevuDefaultsForApp(params) {
2624
2130
  }
2625
2131
  return changed;
2626
2132
  }
2627
-
2628
2133
  //#endregion
2629
2134
  //#region src/plugins/vue/transform/transformScript/rewrite/export.ts
2630
2135
  function rewriteComponentExport(params) {
@@ -2644,33 +2149,83 @@ function rewriteComponentExport(params) {
2644
2149
  exportPath.insertAfter(t.expressionStatement(t.callExpression(t.identifier(WE_VU_RUNTIME_APIS.createWevuComponent), [t.identifier(DEFAULT_OPTIONS_IDENTIFIER)])));
2645
2150
  return true;
2646
2151
  }
2647
-
2648
2152
  //#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));
2663
- }
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));
2672
- }
2673
- const entryObj = t.objectExpression(entryObjProps);
2153
+ //#region src/plugins/vue/compiler/template/expression/parse.ts
2154
+ const babelExpressionCache = new LRUCache({ max: 1024 });
2155
+ new LRUCache({ max: 1024 });
2156
+ const BABEL_GENERATE_MINI_PROGRAM_OPTIONS = {
2157
+ compact: true,
2158
+ jsescOption: {
2159
+ quotes: "single",
2160
+ minimal: true
2161
+ }
2162
+ };
2163
+ function generateExpression(node) {
2164
+ const { code } = generate(node, BABEL_GENERATE_MINI_PROGRAM_OPTIONS);
2165
+ return code;
2166
+ }
2167
+ function parseBabelExpression(exp) {
2168
+ const cached = babelExpressionCache.get(exp);
2169
+ if (cached !== void 0) return cached === false ? null : cached;
2170
+ try {
2171
+ const stmt = parse$2(`(${exp})`, {
2172
+ sourceType: "module",
2173
+ plugins: ["typescript"]
2174
+ }).program.body[0];
2175
+ if (!stmt || !("expression" in stmt)) {
2176
+ babelExpressionCache.set(exp, false);
2177
+ return null;
2178
+ }
2179
+ const expression = stmt.expression;
2180
+ babelExpressionCache.set(exp, expression);
2181
+ return expression;
2182
+ } catch {
2183
+ babelExpressionCache.set(exp, false);
2184
+ return null;
2185
+ }
2186
+ }
2187
+ function parseBabelExpressionFile(exp) {
2188
+ try {
2189
+ const ast = parse$2(`(${exp})`, {
2190
+ sourceType: "module",
2191
+ plugins: ["typescript"]
2192
+ });
2193
+ const stmt = ast.program.body[0];
2194
+ if (!stmt || !("expression" in stmt)) return null;
2195
+ return {
2196
+ ast,
2197
+ expression: stmt.expression
2198
+ };
2199
+ } catch {
2200
+ return null;
2201
+ }
2202
+ }
2203
+ //#endregion
2204
+ //#region src/plugins/vue/transform/transformScript/rewrite/inlineExpressions.ts
2205
+ function buildInlineMapExpression(inlineExpressions) {
2206
+ const entries = inlineExpressions.map((entry) => {
2207
+ const keysExpr = t.arrayExpression(entry.scopeKeys.map((key) => t.stringLiteral(key)));
2208
+ const exprAst = parseBabelExpression(entry.expression) ?? t.identifier("undefined");
2209
+ const fnExpr = t.arrowFunctionExpression([
2210
+ t.identifier("ctx"),
2211
+ t.identifier("scope"),
2212
+ t.identifier("$event")
2213
+ ], exprAst);
2214
+ const entryObjProps = [t.objectProperty(t.identifier("keys"), keysExpr), t.objectProperty(t.identifier("fn"), fnExpr)];
2215
+ if (entry.indexBindings?.length) {
2216
+ const indexKeysExpr = t.arrayExpression(entry.indexBindings.map((binding) => t.stringLiteral(binding.key)));
2217
+ entryObjProps.push(t.objectProperty(t.identifier("indexKeys"), indexKeysExpr));
2218
+ }
2219
+ if (entry.scopeResolvers?.length) {
2220
+ const resolverMap = new Map(entry.scopeResolvers.map((item) => [item.key, item.expression]));
2221
+ const resolverExpr = t.arrayExpression(entry.scopeKeys.map((key) => {
2222
+ const source = resolverMap.get(key);
2223
+ if (!source) return t.identifier("undefined");
2224
+ return parseBabelExpression(source) ?? t.identifier("undefined");
2225
+ }));
2226
+ entryObjProps.push(t.objectProperty(t.identifier("scopeResolvers"), resolverExpr));
2227
+ }
2228
+ const entryObj = t.objectExpression(entryObjProps);
2674
2229
  return t.objectProperty(t.stringLiteral(entry.id), entryObj);
2675
2230
  });
2676
2231
  return t.objectExpression(entries);
@@ -2714,7 +2269,110 @@ function injectInlineExpressions(componentExpr, inlineExpressions) {
2714
2269
  }
2715
2270
  return false;
2716
2271
  }
2717
-
2272
+ //#endregion
2273
+ //#region src/plugins/vue/transform/transformScript/rewrite/setupInitialData.ts
2274
+ function unwrapExpression(node) {
2275
+ if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTypeCastExpression(node) || t.isParenthesizedExpression(node)) return unwrapExpression(node.expression);
2276
+ return node;
2277
+ }
2278
+ function resolveSetupFunction(componentOptionsObject) {
2279
+ for (const prop of componentOptionsObject.properties) {
2280
+ if (t.isObjectMethod(prop) && !prop.computed && isStaticObjectKeyMatch(prop.key, "setup")) return prop;
2281
+ if (!t.isObjectProperty(prop) || prop.computed || !isStaticObjectKeyMatch(prop.key, "setup")) continue;
2282
+ const value = unwrapExpression(prop.value);
2283
+ if (t.isFunctionExpression(value) || t.isArrowFunctionExpression(value)) return value;
2284
+ }
2285
+ return null;
2286
+ }
2287
+ function isComponentMetaObject(node) {
2288
+ return node.properties.some((prop) => {
2289
+ return t.isObjectProperty(prop) && !prop.computed && isStaticObjectKeyMatch(prop.key, "__weappViteUsingComponent") && t.isBooleanLiteral(prop.value, { value: true });
2290
+ });
2291
+ }
2292
+ function isSerializableSeed(node) {
2293
+ const normalized = unwrapExpression(node);
2294
+ if (t.isStringLiteral(normalized) || t.isNumericLiteral(normalized) || t.isBooleanLiteral(normalized) || t.isNullLiteral(normalized)) return true;
2295
+ if (t.isTemplateLiteral(normalized)) return normalized.expressions.length === 0;
2296
+ if (t.isArrayExpression(normalized)) return normalized.elements.every((element) => !!element && !t.isSpreadElement(element) && isSerializableSeed(element));
2297
+ if (t.isObjectExpression(normalized)) {
2298
+ if (isComponentMetaObject(normalized)) return false;
2299
+ return normalized.properties.every((prop) => {
2300
+ return t.isObjectProperty(prop) && !prop.computed && !t.isPatternLike(prop.value) && isSerializableSeed(prop.value);
2301
+ });
2302
+ }
2303
+ return false;
2304
+ }
2305
+ function extractSeedExpression(node) {
2306
+ const normalized = unwrapExpression(node);
2307
+ if (t.isCallExpression(normalized) && t.isIdentifier(normalized.callee) && [
2308
+ "ref",
2309
+ "shallowRef",
2310
+ "reactive"
2311
+ ].includes(normalized.callee.name)) {
2312
+ const firstArg = normalized.arguments[0];
2313
+ if (firstArg && !t.isSpreadElement(firstArg) && t.isExpression(firstArg) && isSerializableSeed(firstArg)) return t.cloneNode(unwrapExpression(firstArg), true);
2314
+ return null;
2315
+ }
2316
+ if (!isSerializableSeed(normalized)) return null;
2317
+ return t.cloneNode(normalized, true);
2318
+ }
2319
+ function collectSetupInitializers(setupBody) {
2320
+ const initializers = /* @__PURE__ */ new Map();
2321
+ for (const statement of setupBody.body) {
2322
+ if (!t.isVariableDeclaration(statement)) continue;
2323
+ for (const declarator of statement.declarations) {
2324
+ if (!t.isIdentifier(declarator.id) || !declarator.init || !t.isExpression(declarator.init)) continue;
2325
+ initializers.set(declarator.id.name, declarator.init);
2326
+ }
2327
+ }
2328
+ return initializers;
2329
+ }
2330
+ function resolveReturnedObjectExpression(setupBody, initializers) {
2331
+ for (let index = setupBody.body.length - 1; index >= 0; index -= 1) {
2332
+ const statement = setupBody.body[index];
2333
+ if (!t.isReturnStatement(statement) || !statement.argument || !t.isExpression(statement.argument)) continue;
2334
+ const returned = unwrapExpression(statement.argument);
2335
+ if (t.isObjectExpression(returned)) return returned;
2336
+ if (t.isIdentifier(returned)) {
2337
+ const initializer = initializers.get(returned.name);
2338
+ if (initializer) {
2339
+ const normalized = unwrapExpression(initializer);
2340
+ if (t.isObjectExpression(normalized)) return normalized;
2341
+ }
2342
+ }
2343
+ }
2344
+ return null;
2345
+ }
2346
+ function resolvePropertyName(node) {
2347
+ if (t.isIdentifier(node.key) && !node.computed) return node.key.name;
2348
+ if (t.isStringLiteral(node.key) && !node.computed) return node.key.value;
2349
+ return null;
2350
+ }
2351
+ function injectSetupInitialData(componentOptionsObject) {
2352
+ if (getObjectPropertyByKey$1(componentOptionsObject, "data")) return false;
2353
+ const setupFn = resolveSetupFunction(componentOptionsObject);
2354
+ if (!setupFn || !t.isBlockStatement(setupFn.body)) return false;
2355
+ const initializers = collectSetupInitializers(setupFn.body);
2356
+ const returnedObject = resolveReturnedObjectExpression(setupFn.body, initializers);
2357
+ if (!returnedObject) return false;
2358
+ const seedProperties = [];
2359
+ for (const prop of returnedObject.properties) {
2360
+ if (!t.isObjectProperty(prop) || prop.computed) continue;
2361
+ const propertyName = resolvePropertyName(prop);
2362
+ if (!propertyName) continue;
2363
+ let sourceExpression = null;
2364
+ if (prop.shorthand && t.isIdentifier(prop.value)) sourceExpression = initializers.get(prop.value.name) ?? null;
2365
+ else if (t.isIdentifier(prop.value)) sourceExpression = initializers.get(prop.value.name) ?? prop.value;
2366
+ else if (t.isExpression(prop.value)) sourceExpression = prop.value;
2367
+ if (!sourceExpression) continue;
2368
+ const seedExpression = extractSeedExpression(sourceExpression);
2369
+ if (!seedExpression) continue;
2370
+ seedProperties.push(t.objectProperty(createStaticObjectKey(propertyName), seedExpression));
2371
+ }
2372
+ if (!seedProperties.length) return false;
2373
+ componentOptionsObject.properties.unshift(t.objectMethod("method", createStaticObjectKey("data"), [], t.blockStatement([t.returnStatement(t.objectExpression(seedProperties))])));
2374
+ return true;
2375
+ }
2718
2376
  //#endregion
2719
2377
  //#region src/plugins/vue/transform/transformScript/rewrite/templateRefs.ts
2720
2378
  function buildTemplateRefEntry(binding) {
@@ -2749,7 +2407,6 @@ function injectTemplateRefs(optionsObject, bindings, warn) {
2749
2407
  warnHandler("无法自动注入 template ref 元数据,请手动合并 __wevuTemplateRefs。");
2750
2408
  return false;
2751
2409
  }
2752
-
2753
2410
  //#endregion
2754
2411
  //#region src/plugins/vue/transform/transformScript/rewrite/index.ts
2755
2412
  function hasStaticProperty(target, keyName) {
@@ -2779,7 +2436,7 @@ function resolveObjectExpressionFromProgram(program, name) {
2779
2436
  const normalized = unwrapTypeLikeExpression(declarator.init);
2780
2437
  if (t.isObjectExpression(normalized)) return normalized;
2781
2438
  if (t.isCallExpression(normalized) && isObjectAssignCall(normalized)) {
2782
- const lastArg = normalized.arguments[normalized.arguments.length - 1];
2439
+ const lastArg = normalized.arguments.at(-1);
2783
2440
  if (lastArg && !t.isSpreadElement(lastArg) && t.isExpression(lastArg)) {
2784
2441
  const lastNormalized = unwrapTypeLikeExpression(lastArg);
2785
2442
  if (t.isObjectExpression(lastNormalized)) return lastNormalized;
@@ -2835,6 +2492,7 @@ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializ
2835
2492
  parsedWevuDefaults,
2836
2493
  options
2837
2494
  }) || transformed;
2495
+ if (componentOptionsObject) transformed = injectSetupInitialData(componentOptionsObject) || transformed;
2838
2496
  const classStyleBindings = options?.classStyleBindings ?? [];
2839
2497
  if (classStyleBindings.length) if (componentOptionsObject) {
2840
2498
  ensureClassStyleRuntimeImports(ast.program);
@@ -2865,7 +2523,6 @@ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializ
2865
2523
  }
2866
2524
  return transformed;
2867
2525
  }
2868
-
2869
2526
  //#endregion
2870
2527
  //#region src/plugins/vue/transform/transformScript/index.ts
2871
2528
  /**
@@ -2896,252 +2553,817 @@ function transformScript(source, options) {
2896
2553
  transformed: false
2897
2554
  };
2898
2555
  return {
2899
- code: generate(ast, { retainLines: true }).code,
2900
- transformed: state.transformed
2556
+ code: generate(ast, { retainLines: true }).code,
2557
+ transformed: state.transformed
2558
+ };
2559
+ }
2560
+ //#endregion
2561
+ //#region src/plugins/vue/compiler/template/expression/wxml.ts
2562
+ function templateLiteralToConcat(node) {
2563
+ const segments = [];
2564
+ node.quasis.forEach((quasi, index) => {
2565
+ const cooked = quasi.value.cooked ?? quasi.value.raw ?? "";
2566
+ if (cooked) segments.push(t.stringLiteral(cooked));
2567
+ if (index < node.expressions.length) {
2568
+ let inner = node.expressions[index];
2569
+ if (t.isTemplateLiteral(inner)) inner = templateLiteralToConcat(inner);
2570
+ segments.push(inner);
2571
+ }
2572
+ });
2573
+ if (segments.length === 0) return t.stringLiteral("");
2574
+ if (segments.length === 1) return segments[0];
2575
+ return segments.reduce((acc, cur) => t.binaryExpression("+", acc, cur));
2576
+ }
2577
+ function isOptionalChainNode(node) {
2578
+ return Boolean(node && (t.isOptionalMemberExpression(node) || t.isOptionalCallExpression(node)));
2579
+ }
2580
+ function collectOptionalChain(node) {
2581
+ const operations = [];
2582
+ let current = node;
2583
+ while (isOptionalChainNode(current)) {
2584
+ if (t.isOptionalMemberExpression(current)) {
2585
+ operations.push({
2586
+ type: "member",
2587
+ optional: current.optional === true,
2588
+ computed: current.computed,
2589
+ property: t.cloneNode(current.property)
2590
+ });
2591
+ current = current.object;
2592
+ continue;
2593
+ }
2594
+ operations.push({
2595
+ type: "call",
2596
+ optional: current.optional === true,
2597
+ args: current.arguments.map((arg) => t.cloneNode(arg))
2598
+ });
2599
+ current = current.callee;
2600
+ }
2601
+ if (!t.isExpression(current)) return null;
2602
+ return {
2603
+ base: t.cloneNode(current),
2604
+ operations: operations.reverse()
2605
+ };
2606
+ }
2607
+ function applyOptionalChainOperation(base, operation) {
2608
+ if (operation.type === "member") return t.memberExpression(base, t.cloneNode(operation.property), operation.computed);
2609
+ return t.callExpression(base, operation.args.map((arg) => t.cloneNode(arg)));
2610
+ }
2611
+ function lowerOptionalChain(node) {
2612
+ const chain = collectOptionalChain(node);
2613
+ if (!chain) return t.cloneNode(node);
2614
+ const segments = [chain.base];
2615
+ for (const operation of chain.operations) {
2616
+ const currentBase = t.cloneNode(segments.at(-1));
2617
+ segments.push(applyOptionalChainOperation(currentBase, operation));
2618
+ }
2619
+ let lowered = t.cloneNode(segments.at(-1));
2620
+ for (let index = chain.operations.length - 1; index >= 0; index--) {
2621
+ if (!chain.operations[index].optional) continue;
2622
+ lowered = t.conditionalExpression(t.binaryExpression("==", t.cloneNode(segments[index]), t.nullLiteral()), t.identifier("undefined"), lowered);
2623
+ }
2624
+ return lowered;
2625
+ }
2626
+ const TEMPLATE_INTERPOLATION_RE = /\$\{([^}]+)\}/g;
2627
+ const EMPTY_STRING_CONCAT_LEFT_RE = /'\s*\+\s*''/g;
2628
+ const EMPTY_STRING_CONCAT_RIGHT_RE = /''\s*\+\s*'/g;
2629
+ const LEADING_EMPTY_CONCAT_RE = /^\s*''\s*\+\s*/g;
2630
+ const TRAILING_EMPTY_CONCAT_RE = /\s*\+\s*''\s*$/g;
2631
+ function normalizeWxmlExpression(exp) {
2632
+ if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.")) return exp;
2633
+ try {
2634
+ const ast = parse$2(`(${exp})`, {
2635
+ sourceType: "module",
2636
+ plugins: ["typescript"]
2637
+ });
2638
+ const stmt = ast.program.body[0];
2639
+ if (!stmt || !("expression" in stmt)) return exp;
2640
+ traverse(ast, {
2641
+ OptionalMemberExpression: { exit(path) {
2642
+ if (isOptionalChainNode(path.parentPath.node)) return;
2643
+ path.replaceWith(lowerOptionalChain(path.node));
2644
+ path.skip();
2645
+ } },
2646
+ OptionalCallExpression: { exit(path) {
2647
+ if (isOptionalChainNode(path.parentPath.node)) return;
2648
+ path.replaceWith(lowerOptionalChain(path.node));
2649
+ path.skip();
2650
+ } },
2651
+ LogicalExpression(path) {
2652
+ if (path.node.operator !== "??") return;
2653
+ const left = path.node.left;
2654
+ const right = path.node.right;
2655
+ const test = t.binaryExpression("!=", t.cloneNode(left), t.nullLiteral());
2656
+ path.replaceWith(t.conditionalExpression(test, t.cloneNode(left), t.cloneNode(right)));
2657
+ path.skip();
2658
+ },
2659
+ TemplateLiteral(path) {
2660
+ if (t.isTaggedTemplateExpression(path.parent)) return;
2661
+ path.replaceWith(templateLiteralToConcat(path.node));
2662
+ }
2663
+ });
2664
+ const normalized = stmt.expression;
2665
+ return generateExpression(normalized);
2666
+ } catch {
2667
+ if (exp.startsWith("`") && exp.endsWith("`")) {
2668
+ let rewritten = `'${exp.slice(1, -1).replace(TEMPLATE_INTERPOLATION_RE, "' + ($1) + '")}'`;
2669
+ rewritten = rewritten.replace(EMPTY_STRING_CONCAT_LEFT_RE, "'").replace(EMPTY_STRING_CONCAT_RIGHT_RE, "'");
2670
+ rewritten = rewritten.replace(LEADING_EMPTY_CONCAT_RE, "").replace(TRAILING_EMPTY_CONCAT_RE, "");
2671
+ return rewritten;
2672
+ }
2673
+ return exp;
2674
+ }
2675
+ }
2676
+ //#endregion
2677
+ //#region src/plugins/jsx/compileJsx/ast.ts
2678
+ const ESCAPED_TEXT_RE = /[&<>]/g;
2679
+ const ESCAPED_ATTR_RE = /[&"<>]/g;
2680
+ const ESCAPED_TEXT_MAP = {
2681
+ "&": "&amp;",
2682
+ "<": "&lt;",
2683
+ ">": "&gt;"
2684
+ };
2685
+ const ESCAPED_ATTR_MAP = {
2686
+ "&": "&amp;",
2687
+ "\"": "&quot;",
2688
+ "<": "&lt;",
2689
+ ">": "&gt;"
2690
+ };
2691
+ function escapeText(value) {
2692
+ return value.replace(ESCAPED_TEXT_RE, (ch) => ESCAPED_TEXT_MAP[ch] || ch);
2693
+ }
2694
+ function escapeAttr(value) {
2695
+ return value.replace(ESCAPED_ATTR_RE, (ch) => ESCAPED_ATTR_MAP[ch] || ch);
2696
+ }
2697
+ const WHITESPACE_RE = /\s+/g;
2698
+ function normalizeJsxText(value) {
2699
+ return value.replace(WHITESPACE_RE, " ");
2700
+ }
2701
+ function printExpression(exp) {
2702
+ return generate(exp).code;
2703
+ }
2704
+ function unwrapTsExpression$2(exp) {
2705
+ let current = exp;
2706
+ while (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current) || t.isParenthesizedExpression(current) || t.isTSInstantiationExpression(current)) {
2707
+ if (t.isTSAsExpression(current) || t.isTSTypeAssertion(current) || t.isTSNonNullExpression(current)) {
2708
+ current = current.expression;
2709
+ continue;
2710
+ }
2711
+ if (t.isParenthesizedExpression(current)) {
2712
+ current = current.expression;
2713
+ continue;
2714
+ }
2715
+ if (t.isTSInstantiationExpression(current)) current = current.expression;
2716
+ }
2717
+ return current;
2718
+ }
2719
+ function normalizeInterpolationExpression(exp) {
2720
+ return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
2721
+ }
2722
+ function renderMustache$1(expression, context) {
2723
+ return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
2724
+ }
2725
+ function pushScope$1(context, names) {
2726
+ for (const name of names) {
2727
+ if (!name) continue;
2728
+ context.scopeStack.push(name);
2729
+ }
2730
+ }
2731
+ function popScope$1(context, count) {
2732
+ for (let i = 0; i < count; i += 1) context.scopeStack.pop();
2733
+ }
2734
+ function collectExpressionScopeBindings(exp, context) {
2735
+ const localSet = new Set(context.scopeStack);
2736
+ if (!localSet.size) return [];
2737
+ const used = [];
2738
+ const usedSet = /* @__PURE__ */ new Set();
2739
+ traverse(t.file(t.program([t.expressionStatement(t.cloneNode(exp, true))])), { Identifier(path) {
2740
+ if (!path.isReferencedIdentifier()) return;
2741
+ const name = path.node.name;
2742
+ if (!localSet.has(name)) return;
2743
+ if (path.scope.hasBinding(name)) return;
2744
+ if (usedSet.has(name)) return;
2745
+ usedSet.add(name);
2746
+ used.push(name);
2747
+ } });
2748
+ return used;
2749
+ }
2750
+ function registerInlineExpression$1(exp, context) {
2751
+ const scopeKeys = collectExpressionScopeBindings(exp, context);
2752
+ const id = `__wv_inline_${context.inlineExpressionSeed++}`;
2753
+ context.inlineExpressions.push({
2754
+ id,
2755
+ expression: printExpression(exp),
2756
+ scopeKeys
2757
+ });
2758
+ return {
2759
+ id,
2760
+ scopeKeys
2761
+ };
2762
+ }
2763
+ function toStaticObjectKey(key) {
2764
+ if (t.isIdentifier(key)) return key.name;
2765
+ if (t.isStringLiteral(key)) return key.value;
2766
+ return null;
2767
+ }
2768
+ function getObjectPropertyByKey(node, key) {
2769
+ for (const prop of node.properties) {
2770
+ if (t.isObjectMethod(prop)) {
2771
+ if (toStaticObjectKey(prop.key) === key) return prop;
2772
+ continue;
2773
+ }
2774
+ if (!t.isObjectProperty(prop) || prop.computed) continue;
2775
+ if (toStaticObjectKey(prop.key) === key) return prop;
2776
+ }
2777
+ return null;
2778
+ }
2779
+ function toJsxTagName(name, context) {
2780
+ if (t.isJSXIdentifier(name)) return name.name;
2781
+ if (t.isJSXNamespacedName(name)) return `${name.namespace.name}:${name.name.name}`;
2782
+ context.warnings.push("暂不支持 JSX 成员标签(如 <Foo.Bar />),已回退为 <view />。");
2783
+ return "view";
2784
+ }
2785
+ function resolveRenderableExpression(node) {
2786
+ if (t.isObjectMethod(node)) {
2787
+ for (const statement of node.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2788
+ return null;
2789
+ }
2790
+ if (!node.value) return null;
2791
+ const value = node.value;
2792
+ if (t.isArrowFunctionExpression(value)) {
2793
+ if (t.isBlockStatement(value.body)) {
2794
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2795
+ return null;
2796
+ }
2797
+ return unwrapTsExpression$2(value.body);
2798
+ }
2799
+ if (t.isFunctionExpression(value)) {
2800
+ for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
2801
+ }
2802
+ return null;
2803
+ }
2804
+ //#endregion
2805
+ //#region src/plugins/jsx/compileJsx/script.ts
2806
+ function removeRenderOptionFromObjectExpression(node) {
2807
+ const nextProps = node.properties.filter((prop) => {
2808
+ if (t.isObjectMethod(prop)) return toStaticObjectKey(prop.key) !== "render";
2809
+ if (t.isObjectProperty(prop) && !prop.computed) return toStaticObjectKey(prop.key) !== "render";
2810
+ return true;
2811
+ });
2812
+ const removed = nextProps.length !== node.properties.length;
2813
+ if (removed) node.properties = nextProps;
2814
+ return removed;
2815
+ }
2816
+ function stripRenderOptionFromScript(source, filename, warn) {
2817
+ let ast;
2818
+ try {
2819
+ ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
2820
+ } catch {
2821
+ return source;
2822
+ }
2823
+ const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
2824
+ const defineComponentDecls = /* @__PURE__ */ new Map();
2825
+ let removedRender = false;
2826
+ let removedJsonMacroImport = false;
2827
+ traverse(ast, {
2828
+ ImportDeclaration(path) {
2829
+ const importSource = path.node.source.value;
2830
+ if (importSource === "wevu" || importSource === "vue") for (const specifier of path.node.specifiers) {
2831
+ if (!t.isImportSpecifier(specifier)) continue;
2832
+ if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
2833
+ defineComponentAliases.add(specifier.local.name);
2834
+ }
2835
+ if (importSource !== "weapp-vite") return;
2836
+ const retained = path.node.specifiers.filter((specifier) => {
2837
+ if (!t.isImportSpecifier(specifier)) return true;
2838
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : "";
2839
+ return !JSON_MACROS.has(importedName);
2840
+ });
2841
+ if (retained.length === path.node.specifiers.length) return;
2842
+ removedJsonMacroImport = true;
2843
+ if (retained.length === 0) path.remove();
2844
+ else path.node.specifiers = retained;
2845
+ },
2846
+ VariableDeclarator(path) {
2847
+ if (!t.isIdentifier(path.node.id) || !path.node.init) return;
2848
+ if (t.isObjectExpression(path.node.init)) {
2849
+ defineComponentDecls.set(path.node.id.name, path.node.init);
2850
+ return;
2851
+ }
2852
+ if (!t.isCallExpression(path.node.init)) return;
2853
+ const callee = path.node.init.callee;
2854
+ if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
2855
+ const first = path.node.init.arguments[0];
2856
+ if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, first);
2857
+ },
2858
+ ExportDefaultDeclaration(path) {
2859
+ const declaration = path.node.declaration;
2860
+ if (t.isDeclaration(declaration)) return;
2861
+ if (t.isObjectExpression(declaration)) {
2862
+ removedRender = removeRenderOptionFromObjectExpression(declaration) || removedRender;
2863
+ return;
2864
+ }
2865
+ if (t.isCallExpression(declaration)) {
2866
+ const callee = declaration.callee;
2867
+ if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
2868
+ const first = declaration.arguments[0];
2869
+ if (t.isObjectExpression(first)) removedRender = removeRenderOptionFromObjectExpression(first) || removedRender;
2870
+ return;
2871
+ }
2872
+ if (t.isIdentifier(declaration)) {
2873
+ const target = defineComponentDecls.get(declaration.name);
2874
+ if (target) removedRender = removeRenderOptionFromObjectExpression(target) || removedRender;
2875
+ }
2876
+ }
2877
+ });
2878
+ if (!removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
2879
+ if (!removedRender && !removedJsonMacroImport) return source;
2880
+ return generate(ast).code;
2881
+ }
2882
+ //#endregion
2883
+ //#region src/plugins/vue/compiler/template/platforms/alipay.ts
2884
+ const eventMap$3 = {
2885
+ click: "tap",
2886
+ dblclick: "tap",
2887
+ mousedown: "touchstart",
2888
+ mouseup: "touchend",
2889
+ tap: "tap",
2890
+ input: "input",
2891
+ change: "change",
2892
+ submit: "submit",
2893
+ focus: "focus",
2894
+ blur: "blur",
2895
+ confirm: "confirm",
2896
+ cancel: "cancel",
2897
+ load: "load",
2898
+ error: "error",
2899
+ scroll: "scroll",
2900
+ scrolltoupper: "scrolltoupper",
2901
+ scrolltolower: "scrolltolower",
2902
+ touchcancel: "touchcancel",
2903
+ longtap: "longtap",
2904
+ longpress: "longpress"
2905
+ };
2906
+ function toOnEventName(eventName) {
2907
+ if (!eventName) return "on";
2908
+ return `on${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
2909
+ }
2910
+ const EVENT_BINDING_PREFIX_RE$3 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2911
+ function parseEventBinding$3(eventName) {
2912
+ const prefixed = EVENT_BINDING_PREFIX_RE$3.exec(eventName);
2913
+ if (prefixed) return {
2914
+ prefix: prefixed[1],
2915
+ name: prefixed[2]
2916
+ };
2917
+ return {
2918
+ prefix: "bind",
2919
+ name: eventName
2920
+ };
2921
+ }
2922
+ function toAlipayDirectiveEvent(prefix, eventName) {
2923
+ if (!eventName) return "on";
2924
+ const pascalEvent = `${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
2925
+ switch (prefix) {
2926
+ case "catch": return `catch${pascalEvent}`;
2927
+ case "capture-bind": return `capture${pascalEvent}`;
2928
+ case "capture-catch": return `captureCatch${pascalEvent}`;
2929
+ default: return toOnEventName(eventName);
2930
+ }
2931
+ }
2932
+ /**
2933
+ * 支付宝小程序平台适配器。
2934
+ */
2935
+ const alipayPlatform = {
2936
+ name: "alipay",
2937
+ wrapIf: (exp, content, renderMustache) => `<block a:if="${renderMustache(exp)}">${content}</block>`,
2938
+ wrapElseIf: (exp, content, renderMustache) => `<block a:elif="${renderMustache(exp)}">${content}</block>`,
2939
+ wrapElse: (content) => `<block a:else>${content}</block>`,
2940
+ forAttrs: (listExp, renderMustache, item, index) => {
2941
+ const attrs = [`a:for="${renderMustache(listExp)}"`];
2942
+ if (item) attrs.push(`a:for-item="${item}"`);
2943
+ if (index) attrs.push(`a:for-index="${index}"`);
2944
+ return attrs;
2945
+ },
2946
+ keyThisValue: "*this",
2947
+ keyAttr: (value) => `a:key="${value}"`,
2948
+ mapEventName: (eventName) => eventMap$3[eventName] || eventName,
2949
+ eventBindingAttr: (eventName) => {
2950
+ const { prefix, name } = parseEventBinding$3(eventName);
2951
+ if (name.includes(":")) return `on:${name}`;
2952
+ return toAlipayDirectiveEvent(prefix, name);
2953
+ }
2954
+ };
2955
+ //#endregion
2956
+ //#region src/plugins/vue/compiler/template/platforms/swan.ts
2957
+ const eventMap$2 = {
2958
+ click: "tap",
2959
+ dblclick: "tap",
2960
+ mousedown: "touchstart",
2961
+ mouseup: "touchend",
2962
+ tap: "tap",
2963
+ input: "input",
2964
+ change: "change",
2965
+ submit: "submit",
2966
+ focus: "focus",
2967
+ blur: "blur",
2968
+ confirm: "confirm",
2969
+ cancel: "cancel",
2970
+ load: "load",
2971
+ error: "error",
2972
+ scroll: "scroll",
2973
+ scrolltoupper: "scrolltoupper",
2974
+ scrolltolower: "scrolltolower",
2975
+ touchcancel: "touchcancel",
2976
+ longtap: "longtap",
2977
+ longpress: "longpress"
2978
+ };
2979
+ const EVENT_BINDING_PREFIX_RE$2 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2980
+ function parseEventBinding$2(eventName) {
2981
+ const prefixed = EVENT_BINDING_PREFIX_RE$2.exec(eventName);
2982
+ if (prefixed) return {
2983
+ prefix: prefixed[1],
2984
+ name: prefixed[2]
2985
+ };
2986
+ return {
2987
+ prefix: "bind",
2988
+ name: eventName
2901
2989
  };
2902
2990
  }
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;"
2912
- };
2913
- const ESCAPED_ATTR_MAP = {
2914
- "&": "&amp;",
2915
- "\"": "&quot;",
2916
- "<": "&lt;",
2917
- ">": "&gt;"
2918
- };
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, " ");
2927
- }
2928
- function printExpression(exp) {
2929
- return generate(exp).code;
2991
+ function shouldUseColonEventBinding$2(name) {
2992
+ return name.includes(":") || name.includes("-");
2930
2993
  }
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;
2994
+ /**
2995
+ * 百度智能小程序平台适配器。
2996
+ */
2997
+ const swanPlatform = {
2998
+ name: "swan",
2999
+ wrapIf: (exp, content, renderMustache) => `<block s-if="${renderMustache(exp)}">${content}</block>`,
3000
+ wrapElseIf: (exp, content, renderMustache) => `<block s-elif="${renderMustache(exp)}">${content}</block>`,
3001
+ wrapElse: (content) => `<block s-else>${content}</block>`,
3002
+ forAttrs: (listExp, renderMustache, item, index) => {
3003
+ const attrs = [`s-for="${renderMustache(listExp)}"`];
3004
+ if (item) attrs.push(`s-for-item="${item}"`);
3005
+ if (index) attrs.push(`s-for-index="${index}"`);
3006
+ return attrs;
3007
+ },
3008
+ keyThisValue: "*this",
3009
+ keyAttr: (value) => `s-key="${value}"`,
3010
+ mapEventName: (eventName) => eventMap$2[eventName] || eventName,
3011
+ eventBindingAttr: (eventName) => {
3012
+ const { prefix, name } = parseEventBinding$2(eventName);
3013
+ switch (prefix) {
3014
+ case "catch": return shouldUseColonEventBinding$2(name) ? `catch:${name}` : `catch${name}`;
3015
+ case "capture-bind": return `capture-bind:${name}`;
3016
+ case "capture-catch": return `capture-catch:${name}`;
3017
+ case "mut-bind": return `mut-bind:${name}`;
3018
+ default: return shouldUseColonEventBinding$2(name) ? `bind:${name}` : `bind${name}`;
2941
3019
  }
2942
- if (t.isTSInstantiationExpression(current)) current = current.expression;
2943
3020
  }
2944
- return current;
2945
- }
2946
- function normalizeInterpolationExpression(exp) {
2947
- return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
3021
+ };
3022
+ //#endregion
3023
+ //#region src/plugins/vue/compiler/template/platforms/tt.ts
3024
+ const eventMap$1 = {
3025
+ click: "tap",
3026
+ dblclick: "tap",
3027
+ mousedown: "touchstart",
3028
+ mouseup: "touchend",
3029
+ tap: "tap",
3030
+ input: "input",
3031
+ change: "change",
3032
+ submit: "submit",
3033
+ focus: "focus",
3034
+ blur: "blur",
3035
+ confirm: "confirm",
3036
+ cancel: "cancel",
3037
+ load: "load",
3038
+ error: "error",
3039
+ scroll: "scroll",
3040
+ scrolltoupper: "scrolltoupper",
3041
+ scrolltolower: "scrolltolower",
3042
+ touchcancel: "touchcancel",
3043
+ longtap: "longtap",
3044
+ longpress: "longpress"
3045
+ };
3046
+ const EVENT_BINDING_PREFIX_RE$1 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
3047
+ function parseEventBinding$1(eventName) {
3048
+ const prefixed = EVENT_BINDING_PREFIX_RE$1.exec(eventName);
3049
+ if (prefixed) return {
3050
+ prefix: prefixed[1],
3051
+ name: prefixed[2]
3052
+ };
3053
+ return {
3054
+ prefix: "bind",
3055
+ name: eventName
3056
+ };
2948
3057
  }
2949
- function renderMustache$1(expression, context) {
2950
- return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
3058
+ function shouldUseColonEventBinding$1(name) {
3059
+ return name.includes(":") || name.includes("-");
2951
3060
  }
2952
- function pushScope$1(context, names) {
2953
- for (const name of names) {
2954
- if (!name) continue;
2955
- context.scopeStack.push(name);
3061
+ /**
3062
+ * 抖音小程序平台适配器。
3063
+ */
3064
+ const ttPlatform = {
3065
+ name: "tt",
3066
+ wrapIf: (exp, content, renderMustache) => `<block tt:if="${renderMustache(exp)}">${content}</block>`,
3067
+ wrapElseIf: (exp, content, renderMustache) => `<block tt:elif="${renderMustache(exp)}">${content}</block>`,
3068
+ wrapElse: (content) => `<block tt:else>${content}</block>`,
3069
+ forAttrs: (listExp, renderMustache, item, index) => {
3070
+ const attrs = [`tt:for="${renderMustache(listExp)}"`];
3071
+ if (item) attrs.push(`tt:for-item="${item}"`);
3072
+ if (index) attrs.push(`tt:for-index="${index}"`);
3073
+ return attrs;
3074
+ },
3075
+ keyThisValue: "*this",
3076
+ keyAttr: (value) => `tt:key="${value}"`,
3077
+ mapEventName: (eventName) => eventMap$1[eventName] || eventName,
3078
+ eventBindingAttr: (eventName) => {
3079
+ const { prefix, name } = parseEventBinding$1(eventName);
3080
+ switch (prefix) {
3081
+ case "catch": return shouldUseColonEventBinding$1(name) ? `catch:${name}` : `catch${name}`;
3082
+ case "capture-bind": return `capture-bind:${name}`;
3083
+ case "capture-catch": return `capture-catch:${name}`;
3084
+ case "mut-bind": return `mut-bind:${name}`;
3085
+ default: return shouldUseColonEventBinding$1(name) ? `bind:${name}` : `bind${name}`;
3086
+ }
2956
3087
  }
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
- });
3088
+ };
3089
+ //#endregion
3090
+ //#region src/plugins/vue/compiler/template/platforms/wechat.ts
3091
+ const eventMap = {
3092
+ click: "tap",
3093
+ dblclick: "tap",
3094
+ mousedown: "touchstart",
3095
+ mouseup: "touchend",
3096
+ tap: "tap",
3097
+ input: "input",
3098
+ change: "change",
3099
+ submit: "submit",
3100
+ focus: "focus",
3101
+ blur: "blur",
3102
+ confirm: "confirm",
3103
+ cancel: "cancel",
3104
+ load: "load",
3105
+ error: "error",
3106
+ scroll: "scroll",
3107
+ scrolltoupper: "scrolltoupper",
3108
+ scrolltolower: "scrolltolower",
3109
+ touchcancel: "touchcancel",
3110
+ longtap: "longtap",
3111
+ longpress: "longpress"
3112
+ };
3113
+ const EVENT_BINDING_PREFIX_RE = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
3114
+ function parseEventBinding(eventName) {
3115
+ const prefixed = EVENT_BINDING_PREFIX_RE.exec(eventName);
3116
+ if (prefixed) return {
3117
+ prefix: prefixed[1],
3118
+ name: prefixed[2]
3119
+ };
2985
3120
  return {
2986
- id,
2987
- scopeKeys
3121
+ prefix: "bind",
3122
+ name: eventName
2988
3123
  };
2989
3124
  }
2990
- function toStaticObjectKey(key) {
2991
- if (t.isIdentifier(key)) return key.name;
2992
- if (t.isStringLiteral(key)) return key.value;
2993
- return null;
3125
+ function shouldUseColonEventBinding(name) {
3126
+ return name.includes(":") || name.includes("-");
2994
3127
  }
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;
3128
+ /**
3129
+ * 微信小程序平台适配器。
3130
+ */
3131
+ const wechatPlatform = {
3132
+ name: "wechat",
3133
+ wrapIf: (exp, content, renderMustache) => `<block wx:if="${renderMustache(exp)}">${content}</block>`,
3134
+ wrapElseIf: (exp, content, renderMustache) => `<block wx:elif="${renderMustache(exp)}">${content}</block>`,
3135
+ wrapElse: (content) => `<block wx:else>${content}</block>`,
3136
+ forAttrs: (listExp, renderMustache, item, index) => {
3137
+ const attrs = [`wx:for="${renderMustache(listExp)}"`];
3138
+ if (item) attrs.push(`wx:for-item="${item}"`);
3139
+ if (index) attrs.push(`wx:for-index="${index}"`);
3140
+ return attrs;
3141
+ },
3142
+ keyThisValue: "*this",
3143
+ keyAttr: (value) => `wx:key="${value}"`,
3144
+ mapEventName: (eventName) => eventMap[eventName] || eventName,
3145
+ eventBindingAttr: (eventName) => {
3146
+ const { prefix, name } = parseEventBinding(eventName);
3147
+ switch (prefix) {
3148
+ case "catch": return shouldUseColonEventBinding(name) ? `catch:${name}` : `catch${name}`;
3149
+ case "capture-bind": return `capture-bind:${name}`;
3150
+ case "capture-catch": return `capture-catch:${name}`;
3151
+ case "mut-bind": return `mut-bind:${name}`;
3152
+ default: return shouldUseColonEventBinding(name) ? `bind:${name}` : `bind${name}`;
3000
3153
  }
3001
- if (!t.isObjectProperty(prop) || prop.computed) continue;
3002
- if (toStaticObjectKey(prop.key) === key) return prop;
3003
3154
  }
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";
3155
+ };
3156
+ //#endregion
3157
+ //#region src/plugins/vue/compiler/template/platforms/index.ts
3158
+ const TEMPLATE_PLATFORMS = {
3159
+ weapp: wechatPlatform,
3160
+ alipay: alipayPlatform,
3161
+ tt: ttPlatform,
3162
+ swan: swanPlatform,
3163
+ jd: wechatPlatform,
3164
+ xhs: wechatPlatform
3165
+ };
3166
+ /**
3167
+ * 获取指定平台的模板适配器,默认回退到 wechat。
3168
+ */
3169
+ function getMiniProgramTemplatePlatform(platform) {
3170
+ if (!platform) return wechatPlatform;
3171
+ return TEMPLATE_PLATFORMS[platform] ?? wechatPlatform;
3011
3172
  }
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);
3173
+ //#endregion
3174
+ //#region src/plugins/jsx/compileJsx/analysis.ts
3175
+ function resolveRenderExpression(componentExpr, context) {
3176
+ if (!t.isObjectExpression(componentExpr)) {
3177
+ context.warnings.push("JSX 编译仅支持对象字面量组件选项。");
3015
3178
  return null;
3016
3179
  }
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);
3180
+ const renderNode = getObjectPropertyByKey(componentExpr, "render");
3181
+ if (!renderNode) {
3182
+ context.warnings.push("未找到 render(),请在默认导出组件中声明 render 函数。");
3183
+ return null;
3025
3184
  }
3026
- if (t.isFunctionExpression(value)) {
3027
- for (const statement of value.body.body) if (t.isReturnStatement(statement) && statement.argument) return unwrapTsExpression$2(statement.argument);
3185
+ if (!t.isObjectMethod(renderNode) && !t.isObjectProperty(renderNode)) {
3186
+ context.warnings.push("render 不是可执行函数。");
3187
+ return null;
3028
3188
  }
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;
3189
+ return resolveRenderableExpression(renderNode);
3040
3190
  }
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
- }
3191
+ /**
3192
+ * 单次遍历同时收集导入组件信息和默认导出表达式,避免多次 traverse 开销。
3193
+ */
3194
+ function collectImportsAndExportDefault(ast) {
3048
3195
  const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
3049
3196
  const defineComponentDecls = /* @__PURE__ */ new Map();
3050
- let removedRender = false;
3051
- let removedJsonMacroImport = false;
3197
+ const imports = /* @__PURE__ */ new Map();
3198
+ let exportDefaultExpression = null;
3052
3199
  traverse(ast, {
3053
3200
  ImportDeclaration(path) {
3054
- const importSource = path.node.source.value;
3055
- if (importSource === "wevu" || importSource === "vue") for (const specifier of path.node.specifiers) {
3201
+ const source = path.node.source.value;
3202
+ if (source === "wevu" || source === "vue") for (const specifier of path.node.specifiers) {
3056
3203
  if (!t.isImportSpecifier(specifier)) continue;
3057
3204
  if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
3058
3205
  defineComponentAliases.add(specifier.local.name);
3059
3206
  }
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;
3207
+ if (path.node.importKind === "type") return;
3208
+ if (!t.isStringLiteral(path.node.source)) return;
3209
+ const importSource = path.node.source.value;
3210
+ for (const specifier of path.node.specifiers) {
3211
+ if ("importKind" in specifier && specifier.importKind === "type") continue;
3212
+ if (!("local" in specifier) || !t.isIdentifier(specifier.local)) continue;
3213
+ const localName = specifier.local.name;
3214
+ if (t.isImportDefaultSpecifier(specifier)) {
3215
+ imports.set(localName, {
3216
+ localName,
3217
+ importSource,
3218
+ importedName: "default",
3219
+ kind: "default"
3220
+ });
3221
+ continue;
3222
+ }
3223
+ if (!t.isImportSpecifier(specifier)) continue;
3224
+ const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : void 0;
3225
+ imports.set(localName, {
3226
+ localName,
3227
+ importSource,
3228
+ importedName,
3229
+ kind: "named"
3230
+ });
3231
+ }
3070
3232
  },
3071
3233
  VariableDeclarator(path) {
3072
3234
  if (!t.isIdentifier(path.node.id) || !path.node.init) return;
3073
3235
  if (t.isObjectExpression(path.node.init)) {
3074
- defineComponentDecls.set(path.node.id.name, path.node.init);
3236
+ defineComponentDecls.set(path.node.id.name, t.cloneNode(path.node.init, true));
3075
3237
  return;
3076
3238
  }
3077
3239
  if (!t.isCallExpression(path.node.init)) return;
3078
3240
  const callee = path.node.init.callee;
3079
3241
  if (!t.isIdentifier(callee) || !defineComponentAliases.has(callee.name)) return;
3080
3242
  const first = path.node.init.arguments[0];
3081
- if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, first);
3243
+ if (t.isObjectExpression(first)) defineComponentDecls.set(path.node.id.name, t.cloneNode(first, true));
3082
3244
  },
3083
3245
  ExportDefaultDeclaration(path) {
3084
3246
  const declaration = path.node.declaration;
3085
3247
  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;
3100
- }
3248
+ exportDefaultExpression = resolveComponentExpression(declaration, defineComponentDecls, defineComponentAliases);
3101
3249
  }
3102
3250
  });
3103
- if (!removedRender) warn?.(`[JSX 编译] 未在 ${filename} 中移除 render 选项,输出脚本可能包含 JSX。`);
3104
- if (!removedRender && !removedJsonMacroImport) return source;
3105
- return generate(ast).code;
3251
+ return {
3252
+ importedComponents: [...imports.values()],
3253
+ exportDefaultExpression
3254
+ };
3106
3255
  }
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;
3256
+ function isCollectableJsxTemplateTag(tag) {
3257
+ if (!tag) return false;
3258
+ if (RESERVED_VUE_COMPONENT_TAGS.has(tag)) return false;
3259
+ return !isBuiltinComponent(tag);
3260
+ }
3261
+ /**
3262
+ * 递归收集 JSX 表达式中的自定义组件标签名。
3263
+ * 直接遍历 AST 节点,无需 cloneNode 和 Babel traverse。
3264
+ */
3265
+ function collectJsxTemplateTags(renderExpression) {
3266
+ const tags = /* @__PURE__ */ new Set();
3267
+ function walk(node) {
3268
+ if (t.isJSXElement(node)) {
3269
+ const { name } = node.openingElement;
3270
+ if (!t.isJSXMemberExpression(name)) {
3271
+ let tag = null;
3272
+ if (t.isJSXIdentifier(name)) tag = name.name;
3273
+ else if (t.isJSXNamespacedName(name)) tag = `${name.namespace.name}:${name.name.name}`;
3274
+ if (tag && isCollectableJsxTemplateTag(tag)) tags.add(tag);
3275
+ }
3276
+ for (const child of node.children) walk(child);
3277
+ return;
3278
+ }
3279
+ if (t.isJSXFragment(node)) {
3280
+ for (const child of node.children) walk(child);
3281
+ return;
3282
+ }
3283
+ if (t.isJSXExpressionContainer(node) && !t.isJSXEmptyExpression(node.expression)) {
3284
+ walk(node.expression);
3285
+ return;
3286
+ }
3287
+ if (t.isConditionalExpression(node)) {
3288
+ walk(node.consequent);
3289
+ walk(node.alternate);
3290
+ return;
3291
+ }
3292
+ if (t.isLogicalExpression(node)) {
3293
+ walk(node.left);
3294
+ walk(node.right);
3295
+ return;
3296
+ }
3297
+ if (t.isCallExpression(node)) {
3298
+ for (const arg of node.arguments) if (t.isExpression(arg)) walk(arg);
3299
+ return;
3300
+ }
3301
+ if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {
3302
+ if (t.isBlockStatement(node.body)) {
3303
+ for (const stmt of node.body.body) if (t.isReturnStatement(stmt) && stmt.argument) walk(stmt.argument);
3304
+ } else walk(node.body);
3305
+ return;
3306
+ }
3307
+ if (t.isArrayExpression(node)) {
3308
+ for (const element of node.elements) if (element && t.isExpression(element)) walk(element);
3309
+ return;
3310
+ }
3311
+ if (t.isParenthesizedExpression(node) || t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node)) walk(node.expression);
3116
3312
  }
3117
- if (!t.isObjectMethod(renderNode) && !t.isObjectProperty(renderNode)) {
3118
- context.warnings.push("render 不是可执行函数。");
3119
- return null;
3313
+ walk(renderExpression);
3314
+ return tags;
3315
+ }
3316
+ /**
3317
+ * 从已解析的 AST 中一次性提取 render 表达式和自动组件上下文。
3318
+ * 内部只调用一次 collectImportsAndExportDefault,避免重复遍历。
3319
+ */
3320
+ function analyzeJsxAst(ast, context) {
3321
+ const { importedComponents, exportDefaultExpression } = collectImportsAndExportDefault(ast);
3322
+ let renderExpression = null;
3323
+ let templateTags = /* @__PURE__ */ new Set();
3324
+ if (exportDefaultExpression) {
3325
+ renderExpression = resolveRenderExpression(exportDefaultExpression, context);
3326
+ if (renderExpression) templateTags = collectJsxTemplateTags(renderExpression);
3120
3327
  }
3121
- return resolveRenderableExpression(renderNode);
3328
+ return {
3329
+ renderExpression,
3330
+ autoComponentContext: {
3331
+ templateTags,
3332
+ importedComponents
3333
+ }
3334
+ };
3122
3335
  }
3336
+ //#endregion
3337
+ //#region src/plugins/jsx/compileJsx/attributes.ts
3338
+ const ON_EVENT_RE = /^on[A-Z]/;
3339
+ const CATCH_EVENT_RE = /^catch[A-Z]/;
3340
+ const CAPTURE_BIND_EVENT_RE = /^captureBind[A-Z]/;
3341
+ const CAPTURE_CATCH_EVENT_RE = /^captureCatch[A-Z]/;
3342
+ const MUT_BIND_EVENT_RE = /^mutBind[A-Z]/;
3123
3343
  function isEventBinding(name) {
3124
- 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);
3344
+ return ON_EVENT_RE.test(name) || CATCH_EVENT_RE.test(name) || CAPTURE_BIND_EVENT_RE.test(name) || CAPTURE_CATCH_EVENT_RE.test(name) || MUT_BIND_EVENT_RE.test(name);
3125
3345
  }
3346
+ const LEADING_UPPER_RE = /^[A-Z]/;
3347
+ const UPPER_CHAR_RE = /[A-Z]/g;
3126
3348
  function lowerEventName(name) {
3127
3349
  if (!name) return name;
3128
- return name.replace(/^[A-Z]/, (s) => s.toLowerCase()).replace(/[A-Z]/g, (s) => s.toLowerCase());
3350
+ return name.replace(LEADING_UPPER_RE, (s) => s.toLowerCase()).replace(UPPER_CHAR_RE, (s) => s.toLowerCase());
3129
3351
  }
3130
3352
  function toEventBindingName(rawName, context) {
3131
3353
  const resolveEvent = (name) => context.platform.mapEventName(lowerEventName(name));
3132
- if (/^captureBind[A-Z]/.test(rawName)) {
3354
+ if (CAPTURE_BIND_EVENT_RE.test(rawName)) {
3133
3355
  const eventName = resolveEvent(rawName.slice(11));
3134
3356
  return context.platform.eventBindingAttr(`capture-bind:${eventName}`);
3135
3357
  }
3136
- if (/^captureCatch[A-Z]/.test(rawName)) {
3358
+ if (CAPTURE_CATCH_EVENT_RE.test(rawName)) {
3137
3359
  const eventName = resolveEvent(rawName.slice(12));
3138
3360
  return context.platform.eventBindingAttr(`capture-catch:${eventName}`);
3139
3361
  }
3140
- if (/^mutBind[A-Z]/.test(rawName)) {
3362
+ if (MUT_BIND_EVENT_RE.test(rawName)) {
3141
3363
  const eventName = resolveEvent(rawName.slice(7));
3142
3364
  return context.platform.eventBindingAttr(`mut-bind:${eventName}`);
3143
3365
  }
3144
- if (/^catch[A-Z]/.test(rawName)) {
3366
+ if (CATCH_EVENT_RE.test(rawName)) {
3145
3367
  const eventName = resolveEvent(rawName.slice(5));
3146
3368
  return context.platform.eventBindingAttr(`catch:${eventName}`);
3147
3369
  }
@@ -3210,6 +3432,8 @@ function compileJsxAttributes(attributes, context) {
3210
3432
  }
3211
3433
  return output;
3212
3434
  }
3435
+ //#endregion
3436
+ //#region src/plugins/jsx/compileJsx/render.ts
3213
3437
  function compileListExpression(exp) {
3214
3438
  return normalizeInterpolationExpression(exp);
3215
3439
  }
@@ -3327,129 +3551,10 @@ function compileJsxElement(node, context) {
3327
3551
  if (node.openingElement.selfClosing) return `<${tag}${attrsSegment} />`;
3328
3552
  return `<${tag}${attrsSegment}>${compileJsxChildren(node.children, context)}</${tag}>`;
3329
3553
  }
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
- };
3554
+ //#endregion
3555
+ //#region src/plugins/jsx/compileJsx/template.ts
3556
+ function createJsxCompileContext(options) {
3445
3557
  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
3558
  platform: options?.template?.platform ?? wechatPlatform,
3454
3559
  mustacheInterpolation: options?.template?.mustacheInterpolation ?? "compact",
3455
3560
  warnings: [],
@@ -3457,27 +3562,28 @@ function compileJsxTemplate(source, filename, options) {
3457
3562
  inlineExpressionSeed: 0,
3458
3563
  scopeStack: []
3459
3564
  };
3460
- const componentExpr = findExportDefaultExpression(ast);
3461
- if (!componentExpr) {
3462
- context.warnings.push(`未在 ${filename} 中识别到默认导出组件。`);
3463
- return {
3464
- template: void 0,
3465
- warnings: context.warnings,
3466
- inlineExpressions: context.inlineExpressions
3467
- };
3468
- }
3469
- const renderExpression = resolveRenderExpression(componentExpr, context);
3470
- if (!renderExpression) return {
3471
- template: void 0,
3472
- warnings: context.warnings,
3473
- inlineExpressions: context.inlineExpressions
3474
- };
3565
+ }
3566
+ /**
3567
+ * 单次解析同时编译模板和收集自动组件上下文,避免重复 babelParse 和 traverse。
3568
+ */
3569
+ function compileJsxTemplateAndCollectComponents(source, filename, options) {
3570
+ const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3571
+ const context = createJsxCompileContext(options);
3572
+ const { renderExpression, autoComponentContext } = analyzeJsxAst(ast, context);
3573
+ let template;
3574
+ if (renderExpression) template = compileRenderableExpression(renderExpression, context);
3575
+ else context.warnings = context.warnings.map((message) => message === "未识别到默认导出组件。" ? `未在 ${filename} 中识别到默认导出组件。` : message);
3475
3576
  return {
3476
- template: compileRenderableExpression(renderExpression, context),
3577
+ template,
3477
3578
  warnings: context.warnings,
3478
- inlineExpressions: context.inlineExpressions
3579
+ inlineExpressions: context.inlineExpressions,
3580
+ autoComponentContext
3479
3581
  };
3480
3582
  }
3583
+ //#endregion
3584
+ //#region src/plugins/jsx/compileJsxFile.ts
3585
+ const LEADING_DOT_RE = /^\./;
3586
+ const SETUP_CALL_RE$1 = /\bsetup\s*\(/;
3481
3587
  /**
3482
3588
  * 编译 JSX/TSX 文件,输出 wevu 脚本与 WXML 模板。
3483
3589
  */
@@ -3491,7 +3597,7 @@ async function compileJsxFile(source, filename, options) {
3491
3597
  let scriptSource = source;
3492
3598
  let scriptMacroConfig;
3493
3599
  let scriptMacroHash;
3494
- const scriptLang = path.extname(filename).replace(/^\./, "") || void 0;
3600
+ const scriptLang = path.extname(filename).replace(LEADING_DOT_RE, "") || void 0;
3495
3601
  try {
3496
3602
  const extracted = await extractJsonMacroFromScriptSetup(source, filename, scriptLang, { merge: (target, incoming) => mergeJson(target, incoming, "macro") });
3497
3603
  scriptSource = extracted.stripped;
@@ -3501,8 +3607,7 @@ async function compileJsxFile(source, filename, options) {
3501
3607
  const message = error instanceof Error ? error.message : String(error);
3502
3608
  throw new Error(`解析 ${filename} 失败:${message}`);
3503
3609
  }
3504
- const compiledTemplate = compileJsxTemplate(source, filename, options);
3505
- const autoComponentContext = collectJsxAutoComponentContext(source, filename, options?.warn);
3610
+ const { template: compiledTemplateStr, warnings: templateWarnings, inlineExpressions, autoComponentContext } = compileJsxTemplateAndCollectComponents(source, filename, options);
3506
3611
  const autoUsingComponentsMap = {};
3507
3612
  if (options?.autoUsingComponents?.resolveUsingComponentPath && autoComponentContext.templateTags.size > 0) for (const imported of autoComponentContext.importedComponents) {
3508
3613
  if (!autoComponentContext.templateTags.has(imported.localName)) continue;
@@ -3534,9 +3639,9 @@ async function compileJsxFile(source, filename, options) {
3534
3639
  isPage: options?.isPage,
3535
3640
  warn: options?.warn,
3536
3641
  wevuDefaults: options?.wevuDefaults,
3537
- inlineExpressions: compiledTemplate.inlineExpressions
3642
+ inlineExpressions
3538
3643
  });
3539
- if (compiledTemplate.warnings.length && options?.warn) compiledTemplate.warnings.forEach((message) => options.warn?.(`[JSX 编译] ${message}`));
3644
+ if (templateWarnings.length && options?.warn) templateWarnings.forEach((message) => options.warn?.(`[JSX 编译] ${message}`));
3540
3645
  let configObj;
3541
3646
  if (Object.keys(autoUsingComponentsMap).length > 0 || Object.keys(autoImportTagsMap).length > 0) {
3542
3647
  const existingRaw = configObj?.usingComponents;
@@ -3555,26 +3660,25 @@ async function compileJsxFile(source, filename, options) {
3555
3660
  if (scriptMacroConfig && Object.keys(scriptMacroConfig).length > 0) configObj = mergeJson(configObj ?? {}, scriptMacroConfig, "macro");
3556
3661
  return {
3557
3662
  script: transformedScript.code,
3558
- template: compiledTemplate.template,
3663
+ template: compiledTemplateStr,
3559
3664
  config: configObj && Object.keys(configObj).length > 0 ? JSON.stringify(configObj, null, 2) : void 0,
3560
3665
  meta: {
3561
3666
  hasScriptSetup: false,
3562
- hasSetupOption: /\bsetup\s*\(/.test(normalizedScriptSource),
3667
+ hasSetupOption: SETUP_CALL_RE$1.test(normalizedScriptSource),
3563
3668
  jsonMacroHash: scriptMacroHash
3564
3669
  }
3565
3670
  };
3566
3671
  }
3567
-
3568
3672
  //#endregion
3569
3673
  //#region src/utils/text.ts
3674
+ const CRLF_RE = /\r\n?/g;
3570
3675
  /**
3571
3676
  * 统一文本换行符为 LF,消除不同系统(CRLF/CR/LF)差异。
3572
3677
  */
3573
3678
  function normalizeLineEndings(source) {
3574
3679
  if (!source.includes("\r")) return source;
3575
- return source.replace(/\r\n?/g, "\n");
3680
+ return source.replace(CRLF_RE, "\n");
3576
3681
  }
3577
-
3578
3682
  //#endregion
3579
3683
  //#region src/plugins/utils/cache.ts
3580
3684
  const mtimeCache = /* @__PURE__ */ new Map();
@@ -3652,7 +3756,6 @@ function clearFileCaches() {
3652
3756
  loadCache.clear();
3653
3757
  pathExistsCache.clear();
3654
3758
  }
3655
-
3656
3759
  //#endregion
3657
3760
  //#region src/utils/cachePolicy.ts
3658
3761
  /**
@@ -3661,11 +3764,10 @@ function clearFileCaches() {
3661
3764
  function getReadFileCheckMtime(config) {
3662
3765
  return Boolean(config?.isDev);
3663
3766
  }
3664
-
3665
3767
  //#endregion
3666
3768
  //#region src/utils/viteId.ts
3667
3769
  const VUE_VIRTUAL_MODULE_PREFIX = "\0vue:";
3668
- const BACKSLASH_RE = /\\/g;
3770
+ const BACKSLASH_RE$3 = /\\/g;
3669
3771
  function normalizeViteId(id, options) {
3670
3772
  const stripQuery = options?.stripQuery !== false;
3671
3773
  const fileProtocolToPathEnabled = options?.fileProtocolToPath !== false;
@@ -3674,7 +3776,7 @@ function normalizeViteId(id, options) {
3674
3776
  const stripLeadingNullByte = options?.stripLeadingNullByte === true;
3675
3777
  let clean = id;
3676
3778
  if (stripVueVirtualPrefix && clean.startsWith(VUE_VIRTUAL_MODULE_PREFIX)) clean = clean.slice(5);
3677
- if (clean.includes("\\")) clean = clean.replace(BACKSLASH_RE, "/");
3779
+ if (clean.includes("\\")) clean = clean.replace(BACKSLASH_RE$3, "/");
3678
3780
  if (stripQuery) clean = clean.split("?", 1)[0];
3679
3781
  if (fileProtocolToPathEnabled && clean.startsWith("file://")) try {
3680
3782
  clean = fileURLToPath(clean);
@@ -3683,7 +3785,6 @@ function normalizeViteId(id, options) {
3683
3785
  if (stripLeadingNullByte && clean.startsWith("\0")) clean = clean.slice(1);
3684
3786
  return clean;
3685
3787
  }
3686
-
3687
3788
  //#endregion
3688
3789
  //#region src/utils/resolvedId.ts
3689
3790
  function isSkippableResolvedId(id) {
@@ -3707,13 +3808,8 @@ function normalizeFsResolvedId(id, options) {
3707
3808
  if (options?.stripLeadingNullByte) normalizeOptions.stripLeadingNullByte = true;
3708
3809
  return normalizeViteId(id, normalizeOptions);
3709
3810
  }
3710
-
3711
3811
  //#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;
3812
+ //#region src/plugins/utils/vueSfcBlockSrc.ts
3717
3813
  const SCRIPT_LANG_EXT = new Map([
3718
3814
  [".ts", "ts"],
3719
3815
  [".tsx", "tsx"],
@@ -3747,46 +3843,6 @@ function getBlockLabel(kind) {
3747
3843
  if (kind === "script setup") return "script setup";
3748
3844
  return kind;
3749
3845
  }
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];
3779
- }
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];
3789
- }
3790
3846
  async function resolveBlockSrcPath(src, filename, options) {
3791
3847
  const normalizedSrc = normalizeFsResolvedId(src);
3792
3848
  if (normalizedSrc && isSkippableResolvedId(normalizedSrc)) throw new Error(`解析 ${filename} 失败:不支持 <src> 引用虚拟模块 ${src}`);
@@ -3848,9 +3904,58 @@ async function resolveSfcBlockSrc(descriptor, filename, options) {
3848
3904
  if (nextDescriptor.styles.length) nextDescriptor.styles = await Promise.all(nextDescriptor.styles.map((style) => resolveBlock(style, "style")));
3849
3905
  return {
3850
3906
  descriptor: nextDescriptor,
3851
- deps: Array.from(deps)
3907
+ deps: [...deps]
3852
3908
  };
3853
3909
  }
3910
+ //#endregion
3911
+ //#region src/plugins/utils/vueSfc.ts
3912
+ const sfcParseCache = new LRUCache({ max: 512 });
3913
+ const SCRIPT_SETUP_SRC_ATTR = "data-weapp-vite-src";
3914
+ const SCRIPT_SRC_ATTR = "data-weapp-vite-script-src";
3915
+ const SCRIPT_SETUP_TAG_RE = /<script\b([^>]*)>/gi;
3916
+ const SETUP_WORD_RE = /\bsetup\b/i;
3917
+ const SRC_WORD_RE = /\bsrc\b/i;
3918
+ const SRC_ATTR_RE = /\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i;
3919
+ /**
3920
+ * 预处理 `<script setup src>`,避免编译器丢失 src。
3921
+ */
3922
+ function preprocessScriptSetupSrc(source) {
3923
+ if (!source.includes("<script") || !source.includes("setup") || !source.includes("src")) return source;
3924
+ return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3925
+ if (!SETUP_WORD_RE.test(attrs) || !SRC_WORD_RE.test(attrs)) return full;
3926
+ return `<script${attrs.replace(SRC_ATTR_RE, `${SCRIPT_SETUP_SRC_ATTR}$1`)}>`;
3927
+ });
3928
+ }
3929
+ /**
3930
+ * 预处理普通 `<script src>`,避免编译器丢失 src。
3931
+ */
3932
+ function preprocessScriptSrc(source) {
3933
+ if (!source.includes("<script") || !source.includes("src")) return source;
3934
+ return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3935
+ if (SETUP_WORD_RE.test(attrs) || !SRC_WORD_RE.test(attrs)) return full;
3936
+ return `<script${attrs.replace(SRC_ATTR_RE, `${SCRIPT_SRC_ATTR}$1`)}>`;
3937
+ });
3938
+ }
3939
+ /**
3940
+ * 将预处理的 `<script setup src>` 恢复为真实 src。
3941
+ */
3942
+ function restoreScriptSetupSrc(descriptor) {
3943
+ const scriptSetup = descriptor.scriptSetup;
3944
+ if (!scriptSetup?.attrs || !(SCRIPT_SETUP_SRC_ATTR in scriptSetup.attrs)) return;
3945
+ const raw = scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3946
+ if (typeof raw === "string") scriptSetup.src = raw;
3947
+ delete scriptSetup.attrs[SCRIPT_SETUP_SRC_ATTR];
3948
+ }
3949
+ /**
3950
+ * 将预处理的 `<script src>` 恢复为真实 src。
3951
+ */
3952
+ function restoreScriptSrc(descriptor) {
3953
+ const script = descriptor.script;
3954
+ if (!script?.attrs || !(SCRIPT_SRC_ATTR in script.attrs)) return;
3955
+ const raw = script.attrs[SCRIPT_SRC_ATTR];
3956
+ if (typeof raw === "string") script.src = raw;
3957
+ delete script.attrs[SCRIPT_SRC_ATTR];
3958
+ }
3854
3959
  /**
3855
3960
  * 读取并解析 SFC,支持缓存与 src 解析。
3856
3961
  */
@@ -3907,9 +4012,10 @@ async function readAndParseSfc(filename, options) {
3907
4012
  function getSfcCheckMtime(config) {
3908
4013
  return getReadFileCheckMtime(config);
3909
4014
  }
3910
-
3911
4015
  //#endregion
3912
4016
  //#region src/plugins/vue/compiler/style.ts
4017
+ const CSS_RULE_RE = /([^{]+)(\{[^}]*\})/g;
4018
+ const CSS_CLASS_RE = /\.([a-z_][\w-]*)(?:\[[^\]]+\])?\s*\{/gi;
3913
4019
  /**
3914
4020
  * 将 Vue SFC 的 style 块转换为 WXSS
3915
4021
  */
@@ -3933,7 +4039,7 @@ function compileVueStyleToWxss(styleBlock, options) {
3933
4039
  */
3934
4040
  function transformScopedCss(source, id) {
3935
4041
  const scopedId = `data-v-${id}`;
3936
- return source.replace(/([^{]+)(\{[^}]*\})/g, (match, selector, rules) => {
4042
+ return source.replace(CSS_RULE_RE, (match, selector, rules) => {
3937
4043
  const trimmedSelector = selector.trim();
3938
4044
  if (!trimmedSelector) return match;
3939
4045
  if (trimmedSelector.includes("[") || trimmedSelector.includes(":deep(") || trimmedSelector.includes(":slotted(")) return match;
@@ -3949,7 +4055,7 @@ function transformScopedCss(source, id) {
3949
4055
  function transformCssModules(source, id) {
3950
4056
  const classes = {};
3951
4057
  const hash = generateHash(id);
3952
- const classRegex = /\.([a-z_][\w-]*)(?:\[[^\]]+\])?\s*\{/gi;
4058
+ const classRegex = new RegExp(CSS_CLASS_RE.source, CSS_CLASS_RE.flags);
3953
4059
  const foundClasses = [];
3954
4060
  let result = classRegex.exec(source);
3955
4061
  while (result !== null) {
@@ -3983,7 +4089,6 @@ function generateHash(str) {
3983
4089
  }
3984
4090
  return Math.abs(hash).toString(36) + str.length.toString(36);
3985
4091
  }
3986
-
3987
4092
  //#endregion
3988
4093
  //#region src/plugins/vue/compiler/template/classStyleRuntime.ts
3989
4094
  /**
@@ -4002,7 +4107,7 @@ function resolveScriptModuleTag(extension) {
4002
4107
  */
4003
4108
  function buildClassStyleWxsTag(extension, src) {
4004
4109
  const normalized = extension.startsWith(".") ? extension.slice(1) : extension;
4005
- const resolvedSrc = src ?? `./${CLASS_STYLE_WXS_FILE}.${normalized}`;
4110
+ const resolvedSrc = src ?? `./__weapp_vite_class_style.${normalized}`;
4006
4111
  return `<${resolveScriptModuleTag(normalized)} module="${CLASS_STYLE_WXS_MODULE}" src="${resolvedSrc}"/>`;
4007
4112
  }
4008
4113
  /**
@@ -4242,106 +4347,12 @@ function getClassStyleWxsSource(options = {}) {
4242
4347
  ""
4243
4348
  ].join("\n");
4244
4349
  }
4245
-
4246
4350
  //#endregion
4247
- //#region src/plugins/vue/compiler/template/elements/helpers.ts
4248
- const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
4351
+ //#region src/plugins/vue/compiler/template/elements/forExpression.ts
4352
+ const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
4249
4353
  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
4354
  function isIdentifier(value) {
4344
- return IDENTIFIER_RE$1.test(value);
4355
+ return IDENTIFIER_RE$4.test(value);
4345
4356
  }
4346
4357
  function splitTopLevelByComma(input) {
4347
4358
  const out = [];
@@ -4513,46 +4524,145 @@ function collectPatternAliases(node, base, aliases) {
4513
4524
  collectPatternAliases(property.value, nextBase, aliases);
4514
4525
  });
4515
4526
  }
4516
- function parseItemAliases(pattern) {
4527
+ function parseItemAliases(pattern) {
4528
+ try {
4529
+ const stmt = parseJsLike(`(${pattern}) => {}`).program.body[0];
4530
+ if (!stmt || stmt.type !== "ExpressionStatement") return {};
4531
+ const exp = stmt.expression;
4532
+ if (!t.isArrowFunctionExpression(exp) || exp.params.length !== 1) return {};
4533
+ const aliases = {};
4534
+ collectPatternAliases(exp.params[0], FOR_ITEM_ALIAS_PLACEHOLDER, aliases);
4535
+ return aliases;
4536
+ } catch {
4537
+ return {};
4538
+ }
4539
+ }
4540
+ function parseForExpression(exp) {
4541
+ const split = splitForExpression(exp.trim());
4542
+ if (!split) return {};
4543
+ const segments = splitTopLevelByComma(stripOuterParentheses(split.source));
4544
+ if (!segments.length || segments.length > 3) return { listExp: split.list };
4545
+ const result = { listExp: split.list };
4546
+ const rawItem = segments[0]?.trim();
4547
+ if (rawItem) if (isIdentifier(rawItem)) result.item = rawItem;
4548
+ else {
4549
+ const aliases = parseItemAliases(rawItem);
4550
+ if (Object.keys(aliases).length) {
4551
+ result.item = FOR_ITEM_ALIAS_PLACEHOLDER;
4552
+ result.itemAliases = aliases;
4553
+ }
4554
+ }
4555
+ if (segments.length === 2) {
4556
+ const rawIndex = segments[1]?.trim();
4557
+ if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4558
+ } else if (segments.length === 3) {
4559
+ const rawKey = segments[1]?.trim();
4560
+ const rawIndex = segments[2]?.trim();
4561
+ if (rawKey && isIdentifier(rawKey)) result.key = rawKey;
4562
+ if (rawIndex && isIdentifier(rawIndex)) result.index = rawIndex;
4563
+ }
4564
+ return result;
4565
+ }
4566
+ //#endregion
4567
+ //#region src/plugins/vue/compiler/template/elements/helpers.ts
4568
+ function isStructuralDirective(node) {
4569
+ for (const prop of node.props) if (prop.type === NodeTypes.DIRECTIVE) {
4570
+ if (prop.name === "if" || prop.name === "else-if" || prop.name === "else") return {
4571
+ type: "if",
4572
+ directive: prop
4573
+ };
4574
+ if (prop.name === "for") return {
4575
+ type: "for",
4576
+ directive: prop
4577
+ };
4578
+ }
4579
+ return {
4580
+ type: null,
4581
+ directive: void 0
4582
+ };
4583
+ }
4584
+ function pushScope(context, names) {
4585
+ if (!names.length) return;
4586
+ context.scopeStack.push(new Set(names));
4587
+ }
4588
+ function popScope(context) {
4589
+ if (context.scopeStack.length) context.scopeStack.pop();
4590
+ }
4591
+ function pushForScope(context, info) {
4592
+ if (!info.listExp) return;
4593
+ context.forStack.push({ ...info });
4594
+ }
4595
+ function popForScope(context) {
4596
+ if (context.forStack.length) context.forStack.pop();
4597
+ }
4598
+ function withForScope(context, info, fn) {
4599
+ pushForScope(context, info);
4600
+ try {
4601
+ return fn();
4602
+ } finally {
4603
+ popForScope(context);
4604
+ }
4605
+ }
4606
+ function pushSlotProps(context, mapping) {
4607
+ if (!Object.keys(mapping).length) return;
4608
+ context.slotPropStack.push(mapping);
4609
+ }
4610
+ function popSlotProps(context) {
4611
+ if (context.slotPropStack.length) context.slotPropStack.pop();
4612
+ }
4613
+ function withScope(context, names, fn) {
4614
+ pushScope(context, names);
4517
4615
  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 {};
4616
+ return fn();
4617
+ } finally {
4618
+ popScope(context);
4527
4619
  }
4528
4620
  }
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
- }
4621
+ function withSlotProps(context, mapping, fn) {
4622
+ pushSlotProps(context, mapping);
4623
+ try {
4624
+ return fn();
4625
+ } finally {
4626
+ popSlotProps(context);
4543
4627
  }
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;
4628
+ }
4629
+ const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
4630
+ const BACKSLASH_RE$2 = /\\/g;
4631
+ const SINGLE_QUOTE_RE$2 = /'/g;
4632
+ const CR_RE$1 = /\r/g;
4633
+ const LF_RE$1 = /\n/g;
4634
+ function collectScopePropMapping(context) {
4635
+ const mapping = {};
4636
+ if (!context.slotMultipleInstance) return mapping;
4637
+ for (const scope of context.scopeStack) for (const name of scope) {
4638
+ if (!IDENTIFIER_RE$3.test(name)) continue;
4639
+ if (!Object.hasOwn(mapping, name)) mapping[name] = name;
4552
4640
  }
4553
- return result;
4641
+ return mapping;
4642
+ }
4643
+ function buildScopePropsExpression(context) {
4644
+ const mapping = collectScopePropMapping(context);
4645
+ const keys = Object.keys(mapping);
4646
+ if (!keys.length) return null;
4647
+ return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${key}`).join(",")}]`;
4648
+ }
4649
+ function toWxmlStringLiteral$1(value) {
4650
+ return `'${value.replace(BACKSLASH_RE$2, "\\\\").replace(SINGLE_QUOTE_RE$2, "\\'").replace(CR_RE$1, "\\r").replace(LF_RE$1, "\\n")}'`;
4651
+ }
4652
+ function hashString(input) {
4653
+ let hash = 0;
4654
+ for (let i = 0; i < input.length; i++) {
4655
+ hash = (hash << 5) - hash + input.charCodeAt(i);
4656
+ hash |= 0;
4657
+ }
4658
+ return Math.abs(hash).toString(36);
4659
+ }
4660
+ function isScopedSlotsDisabled(context) {
4661
+ return context.scopedSlotsCompiler === "off";
4662
+ }
4663
+ function findSlotDirective(node) {
4664
+ return node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "slot");
4554
4665
  }
4555
-
4556
4666
  //#endregion
4557
4667
  //#region src/plugins/vue/compiler/template/expression/scopedSlot.ts
4558
4668
  const SCOPED_SLOT_GLOBALS = new Set([
@@ -4614,6 +4724,7 @@ function replaceIdentifierWithExpression(path, replacement) {
4614
4724
  }
4615
4725
  path.replaceWith(replacement);
4616
4726
  }
4727
+ const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
4617
4728
  function rewriteScopedSlotExpression(exp, context) {
4618
4729
  const normalized = normalizeWxmlExpression(exp);
4619
4730
  const parsed = parseBabelExpressionFile(normalized);
@@ -4624,7 +4735,7 @@ function rewriteScopedSlotExpression(exp, context) {
4624
4735
  const forAliases = collectForAliasMapping$2(context);
4625
4736
  const createMemberAccess = (target, prop) => {
4626
4737
  if (!prop) return t.identifier(target);
4627
- if (/^[A-Z_$][\w$]*$/i.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
4738
+ if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
4628
4739
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
4629
4740
  };
4630
4741
  traverse(ast, { Identifier(path) {
@@ -4632,7 +4743,7 @@ function rewriteScopedSlotExpression(exp, context) {
4632
4743
  const name = path.node.name;
4633
4744
  if (SCOPED_SLOT_GLOBALS.has(name)) return;
4634
4745
  if (path.scope.hasBinding(name)) return;
4635
- if (Object.prototype.hasOwnProperty.call(forAliases, name)) {
4746
+ if (Object.hasOwn(forAliases, name)) {
4636
4747
  const aliasExp = parseBabelExpression(forAliases[name]);
4637
4748
  if (aliasExp) {
4638
4749
  replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
@@ -4640,7 +4751,7 @@ function rewriteScopedSlotExpression(exp, context) {
4640
4751
  }
4641
4752
  }
4642
4753
  if (locals.has(name)) return;
4643
- if (Object.prototype.hasOwnProperty.call(slotProps, name)) {
4754
+ if (Object.hasOwn(slotProps, name)) {
4644
4755
  replaceIdentifierWithExpression(path, createMemberAccess("__wvSlotPropsData", slotProps[name]));
4645
4756
  return;
4646
4757
  }
@@ -4661,7 +4772,7 @@ function rewriteForAliasExpression(exp, context) {
4661
4772
  if (!path.isReferencedIdentifier()) return;
4662
4773
  const name = path.node.name;
4663
4774
  if (path.scope.hasBinding(name)) return;
4664
- if (!Object.prototype.hasOwnProperty.call(forAliases, name)) return;
4775
+ if (!Object.hasOwn(forAliases, name)) return;
4665
4776
  const aliasExp = parseBabelExpression(forAliases[name]);
4666
4777
  if (!aliasExp) return;
4667
4778
  replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
@@ -4675,7 +4786,6 @@ function normalizeWxmlExpressionWithContext(exp, context) {
4675
4786
  if (!context.rewriteScopedSlot) return rewriteForAliasExpression(exp, context);
4676
4787
  return rewriteScopedSlotExpression(exp, context);
4677
4788
  }
4678
-
4679
4789
  //#endregion
4680
4790
  //#region src/plugins/vue/compiler/template/expression/bindings.ts
4681
4791
  function normalizeClassBindingExpression(exp, context) {
@@ -4775,7 +4885,6 @@ function normalizeStyleBindingExpression(exp, context) {
4775
4885
  if (!out.length) return [normalizeWxmlExpressionWithContext(exp, context)];
4776
4886
  return out;
4777
4887
  }
4778
-
4779
4888
  //#endregion
4780
4889
  //#region src/plugins/vue/compiler/template/expression/inline.ts
4781
4890
  const INLINE_GLOBALS = new Set([
@@ -4824,14 +4933,14 @@ const INLINE_GLOBALS = new Set([
4824
4933
  "ctx",
4825
4934
  "scope"
4826
4935
  ]);
4827
- const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
4936
+ const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
4828
4937
  const SIMPLE_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
4829
4938
  function createMemberAccess$1(target, prop) {
4830
- if (IDENTIFIER_RE.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
4939
+ if (IDENTIFIER_RE$1.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
4831
4940
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
4832
4941
  }
4833
4942
  function resolveSlotPropBinding(slotProps, name) {
4834
- if (!Object.prototype.hasOwnProperty.call(slotProps, name)) return null;
4943
+ if (!Object.hasOwn(slotProps, name)) return null;
4835
4944
  const prop = slotProps[name];
4836
4945
  if (!prop) return "__wvSlotPropsData";
4837
4946
  return generateExpression(createMemberAccess$1("__wvSlotPropsData", prop));
@@ -4948,7 +5057,6 @@ function registerInlineExpression(exp, context) {
4948
5057
  indexBindings: scopeResolvers.length ? indexBindings.map((binding) => binding.binding) : []
4949
5058
  };
4950
5059
  }
4951
-
4952
5060
  //#endregion
4953
5061
  //#region src/plugins/vue/compiler/template/expression/js.ts
4954
5062
  const JS_RUNTIME_GLOBALS = new Set([
@@ -5062,7 +5170,7 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5062
5170
  const name = path.node.name;
5063
5171
  if (JS_RUNTIME_GLOBALS.has(name)) return;
5064
5172
  if (path.scope.hasBinding(name)) return;
5065
- if (Object.prototype.hasOwnProperty.call(forAliases, name)) {
5173
+ if (Object.hasOwn(forAliases, name)) {
5066
5174
  const aliasExp = parseBabelExpression(forAliases[name]);
5067
5175
  if (aliasExp) {
5068
5176
  const replacement = t.cloneNode(aliasExp, true);
@@ -5078,7 +5186,7 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5078
5186
  }
5079
5187
  if (locals.has(name)) return;
5080
5188
  let replacement;
5081
- if (context.rewriteScopedSlot) if (Object.prototype.hasOwnProperty.call(slotProps, name)) {
5189
+ if (context.rewriteScopedSlot) if (Object.hasOwn(slotProps, name)) {
5082
5190
  const prop = slotProps[name];
5083
5191
  const base = createThisMemberAccess("__wvSlotPropsData");
5084
5192
  replacement = createUnrefCall(prop ? createMemberAccess(base, prop) : base);
@@ -5096,7 +5204,6 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5096
5204
  const stmt = ast.program.body[0];
5097
5205
  return (stmt && "expression" in stmt ? stmt.expression : null) || null;
5098
5206
  }
5099
-
5100
5207
  //#endregion
5101
5208
  //#region src/plugins/vue/compiler/template/expression/runtimeBinding.ts
5102
5209
  function buildForIndexAccess$1(context) {
@@ -5140,17 +5247,19 @@ function registerRuntimeBindingExpression(exp, context, options) {
5140
5247
  context.classStyleBindings.push(binding);
5141
5248
  return `${binding.name}${buildForIndexAccess$1(context)}`;
5142
5249
  }
5143
-
5144
5250
  //#endregion
5145
5251
  //#region src/plugins/vue/compiler/template/mustache.ts
5146
5252
  function renderMustache(expression, context) {
5147
5253
  return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
5148
5254
  }
5149
-
5150
5255
  //#endregion
5151
5256
  //#region src/plugins/vue/compiler/template/attributes.ts
5257
+ const BACKSLASH_RE$1 = /\\/g;
5258
+ const SINGLE_QUOTE_RE$1 = /'/g;
5259
+ const CR_RE = /\r/g;
5260
+ const LF_RE = /\n/g;
5152
5261
  function toWxmlStringLiteral(value) {
5153
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n")}'`;
5262
+ return `'${value.replace(BACKSLASH_RE$1, "\\\\").replace(SINGLE_QUOTE_RE$1, "\\'").replace(CR_RE, "\\r").replace(LF_RE, "\\n")}'`;
5154
5263
  }
5155
5264
  function cloneForStack(context) {
5156
5265
  return context.forStack.map((info) => ({ ...info }));
@@ -5163,6 +5272,16 @@ function generateExpressionCode(exp) {
5163
5272
  const { code } = generate(exp, { compact: true });
5164
5273
  return code;
5165
5274
  }
5275
+ const TRAILING_SEMICOLONS_RE = /;+\s*$/;
5276
+ function normalizeStyleFallbackValue(value) {
5277
+ return value.trim().replace(TRAILING_SEMICOLONS_RE, "");
5278
+ }
5279
+ function buildStyleErrorFallback(staticValue, shouldHideByDefault) {
5280
+ const segments = [];
5281
+ if (staticValue?.trim()) segments.push(normalizeStyleFallbackValue(staticValue));
5282
+ if (shouldHideByDefault) segments.push("display: none");
5283
+ return segments.join(";");
5284
+ }
5166
5285
  function mergeJsExpressionParts(parts) {
5167
5286
  if (!parts.length) return t.stringLiteral("");
5168
5287
  if (parts.length === 1) return parts[0];
@@ -5192,21 +5311,26 @@ function shouldPreferJsClassStyleRuntime(exp) {
5192
5311
  return false;
5193
5312
  }
5194
5313
  if (t.isConditionalExpression(current)) return visit(current.test) || visit(current.consequent) || visit(current.alternate);
5195
- if (t.isLogicalExpression(current) || t.isBinaryExpression(current)) return visit(current.left) || visit(current.right);
5314
+ if (t.isLogicalExpression(current) || t.isBinaryExpression(current)) {
5315
+ if (t.isPrivateName(current.left) || t.isPrivateName(current.right)) return true;
5316
+ return visit(current.left) || visit(current.right);
5317
+ }
5196
5318
  if (t.isUnaryExpression(current)) return visit(current.argument);
5197
5319
  return true;
5198
5320
  };
5199
5321
  return visit(ast);
5200
5322
  }
5201
- function createClassStyleBinding(context, type, exp, expAst) {
5323
+ function createClassStyleBinding(context, type, exp, expAst, errorFallback) {
5202
5324
  const sameTypeCount = context.classStyleBindings.filter((binding) => binding.type === type).length;
5203
- return {
5325
+ const binding = {
5204
5326
  name: type === "class" ? `__wv_cls_${sameTypeCount}` : type === "style" ? `__wv_style_${sameTypeCount}` : `__wv_bind_${sameTypeCount}`,
5205
5327
  type,
5206
5328
  exp,
5207
5329
  expAst,
5208
5330
  forStack: cloneForStack(context)
5209
5331
  };
5332
+ if (errorFallback !== void 0) binding.errorFallback = errorFallback;
5333
+ return binding;
5210
5334
  }
5211
5335
  function renderClassAttribute(staticClass, dynamicClassExp, context) {
5212
5336
  const staticValue = staticClass?.trim();
@@ -5225,7 +5349,7 @@ function renderClassAttribute(staticClass, dynamicClassExp, context) {
5225
5349
  const dynamicAst = normalizeJsExpressionWithContext(dynamicClassExp, context, { hint: "class 绑定" });
5226
5350
  if (dynamicAst) jsParts.push(dynamicAst);
5227
5351
  const expAst = mergeJsExpressionParts(jsParts);
5228
- const binding = createClassStyleBinding(context, "class", generateExpressionCode(expAst), expAst);
5352
+ const binding = createClassStyleBinding(context, "class", generateExpressionCode(expAst), expAst, staticValue ?? "");
5229
5353
  context.classStyleBindings.push(binding);
5230
5354
  const indexAccess = buildForIndexAccess(context);
5231
5355
  return `class="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
@@ -5259,7 +5383,7 @@ function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
5259
5383
  if (showAst) jsParts.push(t.conditionalExpression(showAst, t.stringLiteral(""), t.stringLiteral("display: none")));
5260
5384
  }
5261
5385
  const expAst = mergeJsExpressionParts(jsParts);
5262
- const binding = createClassStyleBinding(context, "style", generateExpressionCode(expAst), expAst);
5386
+ const binding = createClassStyleBinding(context, "style", generateExpressionCode(expAst), expAst, buildStyleErrorFallback(staticValue, Boolean(vShowExp)));
5263
5387
  context.classStyleBindings.push(binding);
5264
5388
  const indexAccess = buildForIndexAccess(context);
5265
5389
  return `style="${renderMustache(`${binding.name}${indexAccess}`, context)}"`;
@@ -5270,7 +5394,6 @@ function transformAttribute(node, _context) {
5270
5394
  if (value.type === NodeTypes.TEXT) return `${name}="${value.content}"`;
5271
5395
  return `${name}=""`;
5272
5396
  }
5273
-
5274
5397
  //#endregion
5275
5398
  //#region src/plugins/vue/compiler/template/directives/bind.ts
5276
5399
  function unwrapTsExpression(node) {
@@ -5292,8 +5415,10 @@ function createInlineObjectLiteralAttr(argValue, rawExpValue, context) {
5292
5415
  if (context.mustacheInterpolation === "spaced") return `${argValue}="${renderMustache(expValue, context)}"`;
5293
5416
  return `${argValue}="{{ ${expValue} }}"`;
5294
5417
  }
5295
- const isSimpleIdentifier = (value) => /^[A-Z_$][\w$]*$/i.test(value);
5296
- const isSimpleMemberPath = (value) => /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i.test(value);
5418
+ const SIMPLE_IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
5419
+ const SIMPLE_MEMBER_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
5420
+ const isSimpleIdentifier = (value) => SIMPLE_IDENTIFIER_RE$1.test(value);
5421
+ const isSimpleMemberPath = (value) => SIMPLE_MEMBER_PATH_RE.test(value);
5297
5422
  function transformBindDirective(node, context, forInfo) {
5298
5423
  const { exp, arg } = node;
5299
5424
  if (!arg) return null;
@@ -5336,9 +5461,9 @@ function transformBindDirective(node, context, forInfo) {
5336
5461
  }
5337
5462
  return `${argValue}="${renderMustache(normalizeWxmlExpressionWithContext(rawExpValue, context), context)}"`;
5338
5463
  }
5339
-
5340
5464
  //#endregion
5341
5465
  //#region src/plugins/vue/compiler/template/directives/custom.ts
5466
+ const IDENTIFIER_RE = /^[a-z_$][\w$]*$/i;
5342
5467
  function transformCustomDirective(name, exp, arg, context) {
5343
5468
  if (new Set([
5344
5469
  "bind",
@@ -5358,14 +5483,13 @@ function transformCustomDirective(name, exp, arg, context) {
5358
5483
  const dataAttrName = `data-v-${name}`;
5359
5484
  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
5360
5485
  const expValue = normalizeWxmlExpressionWithContext(exp.content, context);
5361
- if (/^[a-z_$][\w$]*$/i.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5486
+ if (IDENTIFIER_RE.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5362
5487
  return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5363
5488
  }
5364
5489
  if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION) return `${dataAttrName}="${arg.content}"`;
5365
5490
  context.warnings.push(`自定义指令 v-${name} 可能需要运行时支持。已生成 data 属性:${dataAttrName}`);
5366
5491
  return dataAttrName;
5367
5492
  }
5368
-
5369
5493
  //#endregion
5370
5494
  //#region src/plugins/vue/compiler/template/directives/model.ts
5371
5495
  function getElementType(element) {
@@ -5375,8 +5499,9 @@ function getElementType(element) {
5375
5499
  }
5376
5500
  return "";
5377
5501
  }
5502
+ const QUOTE_RE$1 = /"/g;
5378
5503
  function transformVModel(element, expValue, context) {
5379
- const escapedModel = expValue.replace(/"/g, "&quot;");
5504
+ const escapedModel = expValue.replace(QUOTE_RE$1, "&quot;");
5380
5505
  const bindModel = (event) => {
5381
5506
  return `${context.platform.eventBindingAttr(event)}="__weapp_vite_model" data-wv-model="${escapedModel}"`;
5382
5507
  };
@@ -5405,24 +5530,27 @@ function transformModelDirective(node, context, elementNode) {
5405
5530
  if (!exp) return null;
5406
5531
  return transformVModel(elementNode, normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context), context);
5407
5532
  }
5408
-
5409
5533
  //#endregion
5410
5534
  //#region src/plugins/vue/compiler/template/directives/on.ts
5411
- const isSimpleHandler = (value) => /^[A-Z_$][\w$]*$/i.test(value);
5535
+ const SIMPLE_IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
5536
+ const isSimpleHandler = (value) => SIMPLE_IDENTIFIER_RE.test(value);
5412
5537
  function shouldUseDetailPayload(options) {
5413
5538
  return options?.isComponent === true;
5414
5539
  }
5540
+ const NON_ALNUM_RE = /[^a-z0-9]+/gi;
5541
+ const LEADING_TRAILING_DASH_RE = /^-+|-+$/g;
5415
5542
  function normalizeEventDatasetSuffix(eventName) {
5416
- return eventName.trim().replace(/[^a-z0-9]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "event";
5543
+ return eventName.trim().replace(NON_ALNUM_RE, "-").replace(LEADING_TRAILING_DASH_RE, "").toLowerCase() || "event";
5417
5544
  }
5545
+ const QUOTE_RE = /"/g;
5418
5546
  function buildInlineScopeAttrs(scopeBindings, context) {
5419
5547
  return scopeBindings.map((binding, index) => {
5420
- return `data-wv-s${index}="${renderMustache(binding.replace(/"/g, "&quot;"), context)}"`;
5548
+ return `data-wv-s${index}="${renderMustache(binding.replace(QUOTE_RE, "&quot;"), context)}"`;
5421
5549
  });
5422
5550
  }
5423
5551
  function buildInlineIndexAttrs(indexBindings, context) {
5424
5552
  return indexBindings.map((binding, index) => {
5425
- return `data-wv-i${index}="${renderMustache(binding.replace(/"/g, "&quot;"), context)}"`;
5553
+ return `data-wv-i${index}="${renderMustache(binding.replace(QUOTE_RE, "&quot;"), context)}"`;
5426
5554
  });
5427
5555
  }
5428
5556
  function resolveEventPrefix(modifiers) {
@@ -5487,12 +5615,11 @@ function transformOnDirective(node, context, options) {
5487
5615
  }
5488
5616
  if (isInlineExpression) return [
5489
5617
  detailAttr,
5490
- `data-wv-inline-${eventSuffix}="${inlineSource.replace(/"/g, "&quot;")}"`,
5618
+ `data-wv-inline-${eventSuffix}="${inlineSource.replace(QUOTE_RE, "&quot;")}"`,
5491
5619
  `${bindAttr}="__weapp_vite_inline"`
5492
5620
  ].filter(Boolean).join(" ");
5493
5621
  return [detailAttr, `${bindAttr}="${expValue}"`].filter(Boolean).join(" ");
5494
5622
  }
5495
-
5496
5623
  //#endregion
5497
5624
  //#region src/plugins/vue/compiler/template/directives/show.ts
5498
5625
  function transformShowDirective(node, context) {
@@ -5500,7 +5627,6 @@ function transformShowDirective(node, context) {
5500
5627
  if (!exp) return null;
5501
5628
  return `style="${renderMustache(`${normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context)} ? '' : 'display: none'`, context)}"`;
5502
5629
  }
5503
-
5504
5630
  //#endregion
5505
5631
  //#region src/plugins/vue/compiler/template/directives/index.ts
5506
5632
  function transformDirective(node, context, elementNode, forInfo, options) {
@@ -5520,7 +5646,6 @@ function transformDirective(node, context, elementNode, forInfo, options) {
5520
5646
  }
5521
5647
  return transformCustomDirective(name, exp, arg, context);
5522
5648
  }
5523
-
5524
5649
  //#endregion
5525
5650
  //#region src/plugins/vue/compiler/template/elements/attrs.ts
5526
5651
  const builtinTagSet = new Set(components.map((tag) => tag.toLowerCase()));
@@ -5611,7 +5736,93 @@ function collectElementAttributes(node, context, options) {
5611
5736
  vTextExp
5612
5737
  };
5613
5738
  }
5614
-
5739
+ //#endregion
5740
+ //#region src/plugins/vue/compiler/template/elements/slotProps.ts
5741
+ const BACKSLASH_RE = /\\/g;
5742
+ const SINGLE_QUOTE_RE = /'/g;
5743
+ function parseSlotPropsExpression(exp, context) {
5744
+ const trimmed = exp.trim();
5745
+ if (!trimmed) return {};
5746
+ try {
5747
+ const stmt = parse$2(`(${trimmed}) => {}`, {
5748
+ sourceType: "module",
5749
+ plugins: ["typescript"]
5750
+ }).program.body[0];
5751
+ if (!stmt || !("expression" in stmt)) return {};
5752
+ const expression = stmt.expression;
5753
+ if (!t.isArrowFunctionExpression(expression)) return {};
5754
+ const param = expression.params[0];
5755
+ if (!param) return {};
5756
+ if (t.isIdentifier(param)) return { [param.name]: "" };
5757
+ if (t.isObjectPattern(param)) {
5758
+ const mapping = {};
5759
+ for (const prop of param.properties) {
5760
+ if (t.isRestElement(prop)) {
5761
+ context.warnings.push("小程序不支持作用域插槽的剩余解构元素。");
5762
+ continue;
5763
+ }
5764
+ if (!t.isObjectProperty(prop)) continue;
5765
+ const key = prop.key;
5766
+ const propName = t.isIdentifier(key) ? key.name : t.isStringLiteral(key) ? key.value : void 0;
5767
+ if (!propName) {
5768
+ context.warnings.push("小程序不支持作用域插槽的计算属性键。");
5769
+ continue;
5770
+ }
5771
+ const value = prop.value;
5772
+ if (t.isIdentifier(value)) {
5773
+ mapping[value.name] = propName;
5774
+ continue;
5775
+ }
5776
+ if (t.isAssignmentPattern(value) && t.isIdentifier(value.left)) {
5777
+ mapping[value.left.name] = propName;
5778
+ context.warnings.push("不支持作用域插槽参数的默认值,默认值将被忽略。");
5779
+ continue;
5780
+ }
5781
+ context.warnings.push("作用域插槽解构仅支持标识符绑定。");
5782
+ }
5783
+ return mapping;
5784
+ }
5785
+ } catch {
5786
+ context.warnings.push("作用域插槽参数解析失败,已回退为空参数。");
5787
+ }
5788
+ return {};
5789
+ }
5790
+ function collectSlotBindingExpression(node, context) {
5791
+ let bindObjectExp = null;
5792
+ const namedBindings = [];
5793
+ for (const prop of node.props) {
5794
+ if (prop.type === NodeTypes.ATTRIBUTE && prop.name === "name") continue;
5795
+ if (prop.type === NodeTypes.DIRECTIVE && prop.name === "bind") {
5796
+ if (prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION) {
5797
+ const rawExpValue = prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION ? prop.exp.content : "";
5798
+ if (prop.arg.content === "name") continue;
5799
+ if (rawExpValue) namedBindings.push({
5800
+ key: prop.arg.content,
5801
+ value: normalizeWxmlExpressionWithContext(rawExpValue, context)
5802
+ });
5803
+ continue;
5804
+ }
5805
+ if (prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
5806
+ bindObjectExp = normalizeWxmlExpressionWithContext(prop.exp.content, context);
5807
+ continue;
5808
+ }
5809
+ }
5810
+ if (prop.type === NodeTypes.ATTRIBUTE && prop.name !== "name") {
5811
+ const literal = prop.value?.type === NodeTypes.TEXT ? prop.value.content : "";
5812
+ if (literal) namedBindings.push({
5813
+ key: prop.name,
5814
+ value: `'${literal.replace(BACKSLASH_RE, "\\\\").replace(SINGLE_QUOTE_RE, "\\'")}'`
5815
+ });
5816
+ }
5817
+ }
5818
+ if (bindObjectExp && namedBindings.length) {
5819
+ context.warnings.push("作用域插槽参数使用 v-bind 对象时,将忽略额外的命名绑定。");
5820
+ namedBindings.length = 0;
5821
+ }
5822
+ if (bindObjectExp) return bindObjectExp;
5823
+ if (!namedBindings.length) return null;
5824
+ return `[${namedBindings.map((entry) => `${toWxmlStringLiteral$1(entry.key)},${entry.value}`).join(",")}]`;
5825
+ }
5615
5826
  //#endregion
5616
5827
  //#region src/plugins/vue/compiler/template/elements/tag-slot.ts
5617
5828
  function renderSlotNameAttribute(info, context, attrName) {
@@ -5663,53 +5874,6 @@ function stringifySlotName(info, context) {
5663
5874
  if (info.type === "static") return info.value === "default" ? "'default'" : `'${info.value}'`;
5664
5875
  return normalizeWxmlExpressionWithContext(info.exp, context);
5665
5876
  }
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
5877
  function buildSlotDeclaration(name, propsExp, children, context) {
5714
5878
  return {
5715
5879
  name,
@@ -5767,39 +5931,7 @@ function renderSlotFallback(decl, context, transformNode) {
5767
5931
  function transformSlotElement(node, context, transformNode) {
5768
5932
  if (isScopedSlotsDisabled(context)) return transformSlotElementPlain(node, context, transformNode);
5769
5933
  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(",")}]`;
5934
+ let slotPropsExp = collectSlotBindingExpression(node, context);
5803
5935
  let fallbackContent = "";
5804
5936
  if (node.children.length > 0) fallbackContent = node.children.map((child) => transformNode(child, context)).join("");
5805
5937
  if (slotPropsExp && fallbackContent) {
@@ -5814,8 +5946,8 @@ function transformSlotElement(node, context, transformNode) {
5814
5946
  if (context.scopedSlotsRequireProps && !slotPropsExp) return slotTag;
5815
5947
  const genericKey = `scoped-slots-${resolveSlotKey(context, slotNameInfo)}`;
5816
5948
  context.componentGenerics[genericKey] = true;
5817
- const resolvedSlotPropsExp = slotPropsExp ?? "[]";
5818
- const scopedAttrs = [`__wv-owner-id="${renderMustache("__wvSlotOwnerId", context)}"`, `__wv-slot-props="${renderMustache(resolvedSlotPropsExp, context)}"`];
5949
+ slotPropsExp = slotPropsExp ?? "[]";
5950
+ const scopedAttrs = [`__wv-owner-id="${renderMustache("__wvSlotOwnerId", context)}"`, `__wv-slot-props="${renderMustache(slotPropsExp, context)}"`];
5819
5951
  if (context.slotMultipleInstance) scopedAttrs.push(`__wv-slot-scope="${renderMustache("__wvSlotScope", context)}"`);
5820
5952
  return `${slotTag}${`<${genericKey}${scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : ""} />`}`;
5821
5953
  }
@@ -5832,7 +5964,6 @@ function transformSlotElementPlain(node, context, transformNode) {
5832
5964
  const slotAttrString = slotAttrs.length ? ` ${slotAttrs.join(" ")}` : "";
5833
5965
  return fallbackContent ? `<slot${slotAttrString}>${fallbackContent}</slot>` : `<slot${slotAttrString} />`;
5834
5966
  }
5835
-
5836
5967
  //#endregion
5837
5968
  //#region src/plugins/vue/compiler/template/elements/tag-component.ts
5838
5969
  function transformComponentWithSlots(node, context, transformNode, options) {
@@ -5985,7 +6116,6 @@ function transformComponentElement(node, context, transformNode) {
5985
6116
  context.warnings.push("动态组件使用 data-is 属性,可能需要小程序运行时支持。");
5986
6117
  return `<component data-is="${renderMustache(componentVar, context)}"${attrString}>${children}</component>`;
5987
6118
  }
5988
-
5989
6119
  //#endregion
5990
6120
  //#region src/plugins/vue/compiler/template/elements/tag-normal.ts
5991
6121
  function transformNormalElement(node, context, transformNode) {
@@ -6000,9 +6130,9 @@ function transformNormalElement(node, context, transformNode) {
6000
6130
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6001
6131
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6002
6132
  }
6003
-
6004
6133
  //#endregion
6005
6134
  //#region src/plugins/vue/compiler/template/elements/tag-structural.ts
6135
+ const REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
6006
6136
  function resolveConditionExpression$1(rawExpValue, context, hint) {
6007
6137
  return (shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
6008
6138
  }
@@ -6035,11 +6165,11 @@ function transformForElement(node, context, transformNode) {
6035
6165
  const forDirective = node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "for");
6036
6166
  if (!forDirective || !forDirective.exp) return transformNormalElement(node, context, transformNode);
6037
6167
  const forInfo = parseForExpression(forDirective.exp.type === NodeTypes.SIMPLE_EXPRESSION ? forDirective.exp.content : "");
6038
- if (forInfo.item === FOR_ITEM_ALIAS_PLACEHOLDER) {
6168
+ if (forInfo.item === "__wv_for_item__") {
6039
6169
  const generatedItem = `__wv_item_${context.forIndexSeed++}`;
6040
6170
  forInfo.item = generatedItem;
6041
6171
  if (forInfo.itemAliases) {
6042
- const escaped = FOR_ITEM_ALIAS_PLACEHOLDER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6172
+ const escaped = FOR_ITEM_ALIAS_PLACEHOLDER.replace(REGEX_SPECIAL_CHARS_RE, "\\$&");
6043
6173
  const placeholderRE = new RegExp(`\\b${escaped}\\b`, "g");
6044
6174
  forInfo.itemAliases = Object.fromEntries(Object.entries(forInfo.itemAliases).map(([alias, expression]) => {
6045
6175
  return [alias, expression.replace(placeholderRE, generatedItem)];
@@ -6088,9 +6218,10 @@ function transformForElement(node, context, transformNode) {
6088
6218
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6089
6219
  }));
6090
6220
  }
6091
-
6092
6221
  //#endregion
6093
6222
  //#region src/plugins/vue/compiler/template/elements/tag-builtin.ts
6223
+ const TEMPLATE_OPEN_RE = /<template/g;
6224
+ const TEMPLATE_CLOSE_RE = /<\/template>/g;
6094
6225
  function resolveConditionExpression(rawExpValue, context, hint) {
6095
6226
  return (shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
6096
6227
  }
@@ -6149,7 +6280,7 @@ function transformTemplateElement(node, context, transformNode) {
6149
6280
  if (dir.name === "else") return context.platform.wrapElse(children);
6150
6281
  return transformIfElement(fakeNode, context, transformNode);
6151
6282
  }
6152
- if (hasOtherDirective) return transformNormalElement(node, context, transformNode).replace(/<template/g, "<block").replace(/<\/template>/g, "</block>");
6283
+ if (hasOtherDirective) return transformNormalElement(node, context, transformNode).replace(TEMPLATE_OPEN_RE, "<block").replace(TEMPLATE_CLOSE_RE, "</block>");
6153
6284
  return children;
6154
6285
  }
6155
6286
  const attrs = [];
@@ -6158,7 +6289,6 @@ function transformTemplateElement(node, context, transformNode) {
6158
6289
  if (dataAttr) attrs.push(`data="${dataAttr}"`);
6159
6290
  return `<template${attrs.length ? ` ${attrs.join(" ")}` : ""}>${children}</template>`;
6160
6291
  }
6161
-
6162
6292
  //#endregion
6163
6293
  //#region src/plugins/vue/compiler/template/elements/index.ts
6164
6294
  function transformElement(node, context, transformNode) {
@@ -6173,12 +6303,14 @@ function transformElement(node, context, transformNode) {
6173
6303
  if (type === "for") return transformForElement(node, context, transformNode);
6174
6304
  return transformNormalElement(node, context, transformNode);
6175
6305
  }
6176
-
6177
6306
  //#endregion
6178
6307
  //#region src/plugins/vue/compiler/template/nodes.ts
6308
+ const AMP_RE = /&/g;
6309
+ const LT_RE = /</g;
6310
+ const GT_RE = />/g;
6179
6311
  function escapeWxmlText(value) {
6180
6312
  if (!value) return "";
6181
- return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
6313
+ return value.replace(AMP_RE, "&amp;").replace(LT_RE, "&lt;").replace(GT_RE, "&gt;");
6182
6314
  }
6183
6315
  function transformText(node, _context) {
6184
6316
  return escapeWxmlText(node.content);
@@ -6203,9 +6335,24 @@ function transformNode(node, context) {
6203
6335
  return "";
6204
6336
  }
6205
6337
  }
6206
-
6207
6338
  //#endregion
6208
6339
  //#region src/plugins/vue/compiler/template.ts
6340
+ const HTML_VOID_TAGS = new Set([
6341
+ "area",
6342
+ "base",
6343
+ "br",
6344
+ "col",
6345
+ "embed",
6346
+ "hr",
6347
+ "img",
6348
+ "input",
6349
+ "link",
6350
+ "meta",
6351
+ "param",
6352
+ "source",
6353
+ "track",
6354
+ "wbr"
6355
+ ]);
6209
6356
  /**
6210
6357
  * 将 Vue 模板编译为 WXML。
6211
6358
  */
@@ -6216,9 +6363,12 @@ function compileVueTemplateToWxml(template, filename, options) {
6216
6363
  const wxsExtension = options?.wxsExtension;
6217
6364
  const scopedSlotsRequireProps = options?.scopedSlotsRequireProps ?? options?.scopedSlotsCompiler !== "augmented";
6218
6365
  try {
6219
- const ast = baseParse(template, { onError: (error) => {
6220
- warnings.push(`模板解析失败:${error.message}`);
6221
- } });
6366
+ const ast = baseParse(template, {
6367
+ isVoidTag: (tag) => HTML_VOID_TAGS.has(tag),
6368
+ onError: (error) => {
6369
+ warnings.push(`模板解析失败:${error.message}`);
6370
+ }
6371
+ });
6222
6372
  const context = {
6223
6373
  source: template,
6224
6374
  filename,
@@ -6270,7 +6420,6 @@ function compileVueTemplateToWxml(template, filename, options) {
6270
6420
  };
6271
6421
  }
6272
6422
  }
6273
-
6274
6423
  //#endregion
6275
6424
  //#region src/plugins/vue/transform/config.ts
6276
6425
  /**
@@ -6361,7 +6510,6 @@ async function compileConfigBlocks(blocks, filename, options) {
6361
6510
  if (Reflect.has(accumulator, "$schema")) delete accumulator.$schema;
6362
6511
  return JSON.stringify(accumulator, null, 2);
6363
6512
  }
6364
-
6365
6513
  //#endregion
6366
6514
  //#region src/plugins/vue/transform/compileVueFile/config.ts
6367
6515
  function collectTemplateAutoImportTags(template, filename, warn) {
@@ -6421,7 +6569,6 @@ async function compileConfigPhase(params) {
6421
6569
  if (scriptSetupMacroConfig && Object.keys(scriptSetupMacroConfig).length > 0) configObj = mergeJson(configObj ?? {}, scriptSetupMacroConfig, "macro");
6422
6570
  if (configObj && Object.keys(configObj).length > 0) result.config = JSON.stringify(configObj, null, 2);
6423
6571
  }
6424
-
6425
6572
  //#endregion
6426
6573
  //#region src/plugins/vue/transform/compileVueFile/finalize.ts
6427
6574
  function finalizeResult(result, options) {
@@ -6429,9 +6576,17 @@ function finalizeResult(result, options) {
6429
6576
  if (result.meta && options.scriptSetupMacroHash) result.meta.jsonMacroHash = options.scriptSetupMacroHash;
6430
6577
  if (result.meta && options.defineOptionsHash) result.meta.defineOptionsHash = options.defineOptionsHash;
6431
6578
  }
6432
-
6433
6579
  //#endregion
6434
- //#region src/plugins/vue/transform/defineOptions/inline.ts
6580
+ //#region src/plugins/vue/transform/defineOptions/serialize.ts
6581
+ function getErrorMessage(error) {
6582
+ if (error instanceof Error) return error.message;
6583
+ return typeof error === "string" ? error : "";
6584
+ }
6585
+ const BEHAVIOR_NOT_DEFINED_RE = /\bBehavior is not defined\b/;
6586
+ function shouldFallbackToRawDefineOptions(error) {
6587
+ const message = getErrorMessage(error);
6588
+ return BEHAVIOR_NOT_DEFINED_RE.test(message);
6589
+ }
6435
6590
  function normalizeScriptSetupLang(lang) {
6436
6591
  if (!lang) return "ts";
6437
6592
  const lower = lang.toLowerCase();
@@ -6443,8 +6598,9 @@ function resolveScriptSetupExtension(lang) {
6443
6598
  if (normalized === "ts" || normalized === "tsx" || normalized === "cts" || normalized === "mts") return "ts";
6444
6599
  return "js";
6445
6600
  }
6601
+ const IDENTIFIER_LIKE_KEY_RE = /^[A-Z_$][\w$]*$/i;
6446
6602
  function isIdentifierLikeKey(key) {
6447
- return /^[A-Z_$][\w$]*$/i.test(key);
6603
+ return IDENTIFIER_LIKE_KEY_RE.test(key);
6448
6604
  }
6449
6605
  const SERIALIZABLE_NATIVE_FUNCTIONS = new Map([
6450
6606
  [String, "String"],
@@ -6528,6 +6684,8 @@ function serializeStaticValueToExpression(value, seen = /* @__PURE__ */ new Weak
6528
6684
  }
6529
6685
  throw new Error(`defineOptions 的参数中包含不支持的值类型:${valueType}`);
6530
6686
  }
6687
+ //#endregion
6688
+ //#region src/plugins/vue/transform/defineOptions/inline.ts
6531
6689
  function collectDefineOptionsStatements(content, filename) {
6532
6690
  const ast = parse$2(content, BABEL_TS_MODULE_PARSER_OPTIONS);
6533
6691
  const statements = [];
@@ -6623,12 +6781,24 @@ async function inlineScriptSetupDefineOptionsArgs(content, filename, lang) {
6623
6781
  code: content,
6624
6782
  dependencies: []
6625
6783
  };
6626
- const { values, dependencies } = await evaluateDefineOptionsValues({
6627
- content,
6628
- filename,
6629
- lang,
6630
- statements
6631
- });
6784
+ let values = [];
6785
+ let dependencies = [];
6786
+ try {
6787
+ const evaluated = await evaluateDefineOptionsValues({
6788
+ content,
6789
+ filename,
6790
+ lang,
6791
+ statements
6792
+ });
6793
+ values = evaluated.values;
6794
+ dependencies = evaluated.dependencies;
6795
+ } catch (error) {
6796
+ if (shouldFallbackToRawDefineOptions(error)) return {
6797
+ code: content,
6798
+ dependencies: []
6799
+ };
6800
+ throw error;
6801
+ }
6632
6802
  const ms = new MagicString(content);
6633
6803
  for (let index = 0; index < statements.length; index += 1) {
6634
6804
  const argNode = statements[index].argPath?.node;
@@ -6641,9 +6811,11 @@ async function inlineScriptSetupDefineOptionsArgs(content, filename, lang) {
6641
6811
  dependencies: dependencies.filter(Boolean)
6642
6812
  };
6643
6813
  }
6644
-
6645
6814
  //#endregion
6646
6815
  //#region src/plugins/vue/transform/compileVueFile/parse.ts
6816
+ const SETUP_CALL_RE = /\bsetup\s*\(/;
6817
+ const DEFINE_OPTIONS_CALL_RE = /\bdefineOptions\s*\(/;
6818
+ const APP_VUE_FILE_RE = /[\\/]app\.vue$/;
6647
6819
  function extractDefineOptionsHash(content) {
6648
6820
  let ast;
6649
6821
  try {
@@ -6686,7 +6858,7 @@ async function parseVueFile(source, filename, options) {
6686
6858
  let descriptorForCompile = resolvedDescriptor;
6687
6859
  const meta = {
6688
6860
  hasScriptSetup: !!resolvedDescriptor.scriptSetup,
6689
- hasSetupOption: !!resolvedDescriptor.script && /\bsetup\s*\(/.test(resolvedDescriptor.script.content),
6861
+ hasSetupOption: !!resolvedDescriptor.script && SETUP_CALL_RE.test(resolvedDescriptor.script.content),
6690
6862
  sfcSrcDeps
6691
6863
  };
6692
6864
  let scriptSetupMacroConfig;
@@ -6727,8 +6899,7 @@ async function parseVueFile(source, filename, options) {
6727
6899
  const resolvedNext = await resolveSfcBlockSrc(nextDescriptor, filename, options.sfcSrc);
6728
6900
  descriptorForCompile = resolvedNext.descriptor;
6729
6901
  if (resolvedNext.deps.length) {
6730
- const deps = new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps]);
6731
- sfcSrcDeps = Array.from(deps);
6902
+ sfcSrcDeps = [...new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps])];
6732
6903
  meta.sfcSrcDeps = sfcSrcDeps;
6733
6904
  }
6734
6905
  } else descriptorForCompile = nextDescriptor;
@@ -6739,7 +6910,7 @@ async function parseVueFile(source, filename, options) {
6739
6910
  defineOptionsHash = extractDefineOptionsHash(scriptSetup.content);
6740
6911
  }
6741
6912
  const compileScriptSetup = descriptorForCompile.scriptSetup;
6742
- if (compileScriptSetup?.content && /\bdefineOptions\s*\(/.test(compileScriptSetup.content)) {
6913
+ if (compileScriptSetup?.content && DEFINE_OPTIONS_CALL_RE.test(compileScriptSetup.content)) {
6743
6914
  const inlined = await inlineScriptSetupDefineOptionsArgs(compileScriptSetup.content, filename, compileScriptSetup.lang);
6744
6915
  if (inlined.code !== compileScriptSetup.content) if (compileScriptSetup.src) descriptorForCompile = {
6745
6916
  ...descriptorForCompile,
@@ -6767,15 +6938,14 @@ async function parseVueFile(source, filename, options) {
6767
6938
  const resolvedNext = await resolveSfcBlockSrc(nextDescriptor, filename, options.sfcSrc);
6768
6939
  descriptorForCompile = resolvedNext.descriptor;
6769
6940
  if (resolvedNext.deps.length) {
6770
- const deps = new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps]);
6771
- sfcSrcDeps = Array.from(deps);
6941
+ sfcSrcDeps = [...new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps])];
6772
6942
  meta.sfcSrcDeps = sfcSrcDeps;
6773
6943
  }
6774
6944
  } else descriptorForCompile = nextDescriptor;
6775
6945
  descriptorForCompileSource = nextSource;
6776
6946
  }
6777
6947
  }
6778
- const isAppFile = /[\\/]app\.vue$/.test(filename);
6948
+ const isAppFile = APP_VUE_FILE_RE.test(filename);
6779
6949
  return {
6780
6950
  descriptor: resolvedDescriptor,
6781
6951
  descriptorForCompile,
@@ -6789,7 +6959,6 @@ async function parseVueFile(source, filename, options) {
6789
6959
  isAppFile
6790
6960
  };
6791
6961
  }
6792
-
6793
6962
  //#endregion
6794
6963
  //#region src/plugins/vue/transform/compileVueFile/script.ts
6795
6964
  function collectTemplateComponentNames(template, filename, warn) {
@@ -6882,7 +7051,6 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
6882
7051
  autoComponentMeta
6883
7052
  };
6884
7053
  }
6885
-
6886
7054
  //#endregion
6887
7055
  //#region src/plugins/vue/transform/scopedId.ts
6888
7056
  /**
@@ -6894,7 +7062,6 @@ function generateScopedId(filename) {
6894
7062
  }, 0);
6895
7063
  return Math.abs(hash).toString(36);
6896
7064
  }
6897
-
6898
7065
  //#endregion
6899
7066
  //#region src/plugins/vue/transform/compileVueFile/style.ts
6900
7067
  function compileStylePhase(descriptor, filename, result) {
@@ -6920,7 +7087,6 @@ const __cssModules = ${JSON.stringify(modulesMap, null, 2)}
6920
7087
  ${result.script}
6921
7088
  `;
6922
7089
  }
6923
-
6924
7090
  //#endregion
6925
7091
  //#region src/plugins/vue/transform/compileVueFile/template.ts
6926
7092
  function compileTemplatePhase(descriptor, filename, options, result) {
@@ -6932,7 +7098,6 @@ function compileTemplatePhase(descriptor, filename, options, result) {
6932
7098
  if (templateCompiled.classStyleWxs) result.classStyleWxs = true;
6933
7099
  return templateCompiled;
6934
7100
  }
6935
-
6936
7101
  //#endregion
6937
7102
  //#region src/plugins/vue/transform/compileVueFile/index.ts
6938
7103
  /**
@@ -6965,6 +7130,5 @@ async function compileVueFile(source, filename, options) {
6965
7130
  });
6966
7131
  return result;
6967
7132
  }
6968
-
6969
7133
  //#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 };
7134
+ 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 };