@wevu/compiler 6.7.4 → 6.7.6

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 (2) hide show
  1. package/dist/index.mjs +357 -175
  2. package/package.json +4 -3
package/dist/index.mjs CHANGED
@@ -159,11 +159,12 @@ const RESERVED_VUE_COMPONENT_TAGS = new Set([
159
159
  "suspense"
160
160
  ]);
161
161
  const VUE_COMPONENT_TAG_RE = /^[A-Z_$][\w$]*$/i;
162
+ const PASCAL_CASE_TAG_RE = /^[A-Z][\w$]*$/;
162
163
  /**
163
164
  * 判断模板标签是否可能需要自动导入。
164
165
  */
165
166
  function isAutoImportCandidateTag(tag) {
166
- return tag.includes("-") || /^[A-Z][\w$]*$/.test(tag);
167
+ return tag.includes("-") || PASCAL_CASE_TAG_RE.test(tag);
167
168
  }
168
169
  /**
169
170
  * 收集 Vue 模板中的自定义组件标签。
@@ -365,12 +366,12 @@ function parseJsLike(source) {
365
366
  }
366
367
  //#endregion
367
368
  //#region src/utils/path.ts
368
- const BACKSLASH_RE$1 = /\\/g;
369
+ const BACKSLASH_RE$4 = /\\/g;
369
370
  const LEADING_SLASH_RE = /^[\\/]+/;
370
371
  const DUPLICATE_SLASH_RE = /\/{2,}/g;
371
372
  const TRIM_SLASH_RE = /^\/+|\/+$/g;
372
373
  function toPosixPath(value) {
373
- return value.replace(BACKSLASH_RE$1, "/");
374
+ return value.replace(BACKSLASH_RE$4, "/");
374
375
  }
375
376
  function stripLeadingSlashes(value) {
376
377
  return value.replace(LEADING_SLASH_RE, "");
@@ -513,7 +514,7 @@ const __weapp_defineThemeJson = (config) => (__weapp_json_macro_values.push(conf
513
514
  if (typeof next === "function") next = next();
514
515
  if (next && typeof next.then === "function") next = await next;
515
516
  if (!next || typeof next !== "object" || Array.isArray(next)) throw new Error("宏的返回值必须解析为对象。");
516
- if (Object.prototype.hasOwnProperty.call(next, "$schema")) delete next.$schema;
517
+ if (Object.hasOwn(next, "$schema")) delete next.$schema;
517
518
  if (options?.merge) {
518
519
  const merged = options.merge(accumulator, next);
519
520
  if (merged && typeof merged === "object" && !Array.isArray(merged)) accumulator = merged;
@@ -568,7 +569,7 @@ function collectMacroCallPaths(ast, filename) {
568
569
  };
569
570
  }
570
571
  function assertSingleMacro(macroNames, filename) {
571
- 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})。`);
572
573
  return macroNames.values().next().value;
573
574
  }
574
575
  function findProgramPath(ast) {
@@ -734,7 +735,7 @@ function getObjectPropertyByKey$2(node, key) {
734
735
  return null;
735
736
  }
736
737
  function buildInjectedFeaturesObject(enabled) {
737
- return t.objectExpression(Array.from(enabled).map((key) => {
738
+ return t.objectExpression(Array.from(enabled, (key) => {
738
739
  return t.objectProperty(t.identifier(key), t.booleanLiteral(true));
739
740
  }));
740
741
  }
@@ -808,7 +809,7 @@ function collectWevuPageFeatureFlags(ast) {
808
809
  */
809
810
  function injectWevuPageFeatureFlagsIntoOptionsObject(optionsObject, enabled) {
810
811
  if (!enabled.size) return false;
811
- const expectedKeys = Array.from(enabled);
812
+ const expectedKeys = [...enabled];
812
813
  const existingFeaturesProp = getObjectPropertyByKey$2(optionsObject, "features");
813
814
  let changed = false;
814
815
  if (!existingFeaturesProp) {
@@ -2076,7 +2077,7 @@ function stripVirtualHostFromDefaults(defaults) {
2076
2077
  const next = { ...defaults };
2077
2078
  const options = next.options;
2078
2079
  if (!isPlainRecord(options)) return next;
2079
- if (!Object.prototype.hasOwnProperty.call(options, "virtualHost")) return next;
2080
+ if (!Object.hasOwn(options, "virtualHost")) return next;
2080
2081
  const copiedOptions = { ...options };
2081
2082
  delete copiedOptions.virtualHost;
2082
2083
  if (Object.keys(copiedOptions).length > 0) next.options = copiedOptions;
@@ -2269,6 +2270,110 @@ function injectInlineExpressions(componentExpr, inlineExpressions) {
2269
2270
  return false;
2270
2271
  }
2271
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
+ }
2376
+ //#endregion
2272
2377
  //#region src/plugins/vue/transform/transformScript/rewrite/templateRefs.ts
2273
2378
  function buildTemplateRefEntry(binding) {
2274
2379
  const props = [t.objectProperty(t.identifier("selector"), t.stringLiteral(binding.selector)), t.objectProperty(t.identifier("inFor"), t.booleanLiteral(binding.inFor))];
@@ -2331,7 +2436,7 @@ function resolveObjectExpressionFromProgram(program, name) {
2331
2436
  const normalized = unwrapTypeLikeExpression(declarator.init);
2332
2437
  if (t.isObjectExpression(normalized)) return normalized;
2333
2438
  if (t.isCallExpression(normalized) && isObjectAssignCall(normalized)) {
2334
- const lastArg = normalized.arguments[normalized.arguments.length - 1];
2439
+ const lastArg = normalized.arguments.at(-1);
2335
2440
  if (lastArg && !t.isSpreadElement(lastArg) && t.isExpression(lastArg)) {
2336
2441
  const lastNormalized = unwrapTypeLikeExpression(lastArg);
2337
2442
  if (t.isObjectExpression(lastNormalized)) return lastNormalized;
@@ -2387,6 +2492,7 @@ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializ
2387
2492
  parsedWevuDefaults,
2388
2493
  options
2389
2494
  }) || transformed;
2495
+ if (componentOptionsObject) transformed = injectSetupInitialData(componentOptionsObject) || transformed;
2390
2496
  const classStyleBindings = options?.classStyleBindings ?? [];
2391
2497
  if (classStyleBindings.length) if (componentOptionsObject) {
2392
2498
  ensureClassStyleRuntimeImports(ast.program);
@@ -2507,16 +2613,21 @@ function lowerOptionalChain(node) {
2507
2613
  if (!chain) return t.cloneNode(node);
2508
2614
  const segments = [chain.base];
2509
2615
  for (const operation of chain.operations) {
2510
- const currentBase = t.cloneNode(segments[segments.length - 1]);
2616
+ const currentBase = t.cloneNode(segments.at(-1));
2511
2617
  segments.push(applyOptionalChainOperation(currentBase, operation));
2512
2618
  }
2513
- let lowered = t.cloneNode(segments[segments.length - 1]);
2619
+ let lowered = t.cloneNode(segments.at(-1));
2514
2620
  for (let index = chain.operations.length - 1; index >= 0; index--) {
2515
2621
  if (!chain.operations[index].optional) continue;
2516
2622
  lowered = t.conditionalExpression(t.binaryExpression("==", t.cloneNode(segments[index]), t.nullLiteral()), t.identifier("undefined"), lowered);
2517
2623
  }
2518
2624
  return lowered;
2519
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;
2520
2631
  function normalizeWxmlExpression(exp) {
2521
2632
  if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.")) return exp;
2522
2633
  try {
@@ -2554,9 +2665,9 @@ function normalizeWxmlExpression(exp) {
2554
2665
  return generateExpression(normalized);
2555
2666
  } catch {
2556
2667
  if (exp.startsWith("`") && exp.endsWith("`")) {
2557
- let rewritten = `'${exp.slice(1, -1).replace(/\$\{([^}]+)\}/g, "' + ($1) + '")}'`;
2558
- rewritten = rewritten.replace(/'\s*\+\s*''/g, "'").replace(/''\s*\+\s*'/g, "'");
2559
- rewritten = rewritten.replace(/^\s*''\s*\+\s*/g, "").replace(/\s*\+\s*''\s*$/g, "");
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, "");
2560
2671
  return rewritten;
2561
2672
  }
2562
2673
  return exp;
@@ -2583,8 +2694,9 @@ function escapeText(value) {
2583
2694
  function escapeAttr(value) {
2584
2695
  return value.replace(ESCAPED_ATTR_RE, (ch) => ESCAPED_ATTR_MAP[ch] || ch);
2585
2696
  }
2697
+ const WHITESPACE_RE = /\s+/g;
2586
2698
  function normalizeJsxText(value) {
2587
- return value.replace(/\s+/g, " ");
2699
+ return value.replace(WHITESPACE_RE, " ");
2588
2700
  }
2589
2701
  function printExpression(exp) {
2590
2702
  return generate(exp).code;
@@ -2795,8 +2907,9 @@ function toOnEventName(eventName) {
2795
2907
  if (!eventName) return "on";
2796
2908
  return `on${(eventName[0] ?? "").toUpperCase()}${eventName.slice(1)}`;
2797
2909
  }
2910
+ const EVENT_BINDING_PREFIX_RE$3 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2798
2911
  function parseEventBinding$3(eventName) {
2799
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
2912
+ const prefixed = EVENT_BINDING_PREFIX_RE$3.exec(eventName);
2800
2913
  if (prefixed) return {
2801
2914
  prefix: prefixed[1],
2802
2915
  name: prefixed[2]
@@ -2863,8 +2976,9 @@ const eventMap$2 = {
2863
2976
  longtap: "longtap",
2864
2977
  longpress: "longpress"
2865
2978
  };
2979
+ const EVENT_BINDING_PREFIX_RE$2 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2866
2980
  function parseEventBinding$2(eventName) {
2867
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
2981
+ const prefixed = EVENT_BINDING_PREFIX_RE$2.exec(eventName);
2868
2982
  if (prefixed) return {
2869
2983
  prefix: prefixed[1],
2870
2984
  name: prefixed[2]
@@ -2929,8 +3043,9 @@ const eventMap$1 = {
2929
3043
  longtap: "longtap",
2930
3044
  longpress: "longpress"
2931
3045
  };
3046
+ const EVENT_BINDING_PREFIX_RE$1 = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2932
3047
  function parseEventBinding$1(eventName) {
2933
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
3048
+ const prefixed = EVENT_BINDING_PREFIX_RE$1.exec(eventName);
2934
3049
  if (prefixed) return {
2935
3050
  prefix: prefixed[1],
2936
3051
  name: prefixed[2]
@@ -2995,8 +3110,9 @@ const eventMap = {
2995
3110
  longtap: "longtap",
2996
3111
  longpress: "longpress"
2997
3112
  };
3113
+ const EVENT_BINDING_PREFIX_RE = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/;
2998
3114
  function parseEventBinding(eventName) {
2999
- const prefixed = /^(bind|catch|capture-bind|capture-catch|mut-bind):(.+)$/.exec(eventName);
3115
+ const prefixed = EVENT_BINDING_PREFIX_RE.exec(eventName);
3000
3116
  if (prefixed) return {
3001
3117
  prefix: prefixed[1],
3002
3118
  name: prefixed[2]
@@ -3072,19 +3188,47 @@ function resolveRenderExpression(componentExpr, context) {
3072
3188
  }
3073
3189
  return resolveRenderableExpression(renderNode);
3074
3190
  }
3075
- function findExportDefaultExpression(ast) {
3191
+ /**
3192
+ * 单次遍历同时收集导入组件信息和默认导出表达式,避免多次 traverse 开销。
3193
+ */
3194
+ function collectImportsAndExportDefault(ast) {
3076
3195
  const defineComponentAliases = new Set(["defineComponent", "_defineComponent"]);
3077
3196
  const defineComponentDecls = /* @__PURE__ */ new Map();
3197
+ const imports = /* @__PURE__ */ new Map();
3078
3198
  let exportDefaultExpression = null;
3079
3199
  traverse(ast, {
3080
3200
  ImportDeclaration(path) {
3081
3201
  const source = path.node.source.value;
3082
- if (source !== "wevu" && source !== "vue") return;
3083
- for (const specifier of path.node.specifiers) {
3202
+ if (source === "wevu" || source === "vue") for (const specifier of path.node.specifiers) {
3084
3203
  if (!t.isImportSpecifier(specifier)) continue;
3085
3204
  if (!t.isIdentifier(specifier.imported, { name: "defineComponent" })) continue;
3086
3205
  defineComponentAliases.add(specifier.local.name);
3087
3206
  }
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
+ }
3088
3232
  },
3089
3233
  VariableDeclarator(path) {
3090
3234
  if (!t.isIdentifier(path.node.id) || !path.node.init) return;
@@ -3104,120 +3248,122 @@ function findExportDefaultExpression(ast) {
3104
3248
  exportDefaultExpression = resolveComponentExpression(declaration, defineComponentDecls, defineComponentAliases);
3105
3249
  }
3106
3250
  });
3107
- return exportDefaultExpression;
3251
+ return {
3252
+ importedComponents: [...imports.values()],
3253
+ exportDefaultExpression
3254
+ };
3108
3255
  }
3109
3256
  function isCollectableJsxTemplateTag(tag) {
3110
3257
  if (!tag) return false;
3111
3258
  if (RESERVED_VUE_COMPONENT_TAGS.has(tag)) return false;
3112
3259
  return !isBuiltinComponent(tag);
3113
3260
  }
3261
+ /**
3262
+ * 递归收集 JSX 表达式中的自定义组件标签名。
3263
+ * 直接遍历 AST 节点,无需 cloneNode 和 Babel traverse。
3264
+ */
3114
3265
  function collectJsxTemplateTags(renderExpression) {
3115
3266
  const tags = /* @__PURE__ */ new Set();
3116
- traverse(t.file(t.program([t.expressionStatement(t.cloneNode(renderExpression, true))])), { JSXOpeningElement(path) {
3117
- const { name } = path.node;
3118
- if (t.isJSXMemberExpression(name)) return;
3119
- let tag = null;
3120
- if (t.isJSXIdentifier(name)) tag = name.name;
3121
- else if (t.isJSXNamespacedName(name)) tag = `${name.namespace.name}:${name.name.name}`;
3122
- if (!tag || !isCollectableJsxTemplateTag(tag)) return;
3123
- tags.add(tag);
3124
- } });
3125
- return tags;
3126
- }
3127
- function collectImportedComponents(ast) {
3128
- const imports = /* @__PURE__ */ new Map();
3129
- traverse(ast, { ImportDeclaration(path) {
3130
- if (path.node.importKind === "type") return;
3131
- if (!t.isStringLiteral(path.node.source)) return;
3132
- const importSource = path.node.source.value;
3133
- for (const specifier of path.node.specifiers) {
3134
- if ("importKind" in specifier && specifier.importKind === "type") continue;
3135
- if (!("local" in specifier) || !t.isIdentifier(specifier.local)) continue;
3136
- const localName = specifier.local.name;
3137
- if (t.isImportDefaultSpecifier(specifier)) {
3138
- imports.set(localName, {
3139
- localName,
3140
- importSource,
3141
- importedName: "default",
3142
- kind: "default"
3143
- });
3144
- continue;
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);
3145
3275
  }
3146
- if (!t.isImportSpecifier(specifier)) continue;
3147
- const importedName = t.isIdentifier(specifier.imported) ? specifier.imported.name : t.isStringLiteral(specifier.imported) ? specifier.imported.value : void 0;
3148
- imports.set(localName, {
3149
- localName,
3150
- importSource,
3151
- importedName,
3152
- kind: "named"
3153
- });
3276
+ for (const child of node.children) walk(child);
3277
+ return;
3154
3278
  }
3155
- } });
3156
- return Array.from(imports.values());
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);
3312
+ }
3313
+ walk(renderExpression);
3314
+ return tags;
3157
3315
  }
3158
- function collectJsxAutoComponentContext(source, filename, context, warn) {
3159
- const empty = {
3160
- templateTags: /* @__PURE__ */ new Set(),
3161
- importedComponents: []
3162
- };
3163
- let ast;
3164
- try {
3165
- ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3166
- } catch (error) {
3167
- const message = error instanceof Error ? error.message : String(error);
3168
- warn?.(`[JSX 编译] 解析 ${filename} 失败,已跳过自动 usingComponents 推导:${message}`);
3169
- return empty;
3170
- }
3171
- const importedComponents = collectImportedComponents(ast);
3172
- const componentExpr = findExportDefaultExpression(ast);
3173
- if (!componentExpr) return {
3174
- templateTags: /* @__PURE__ */ new Set(),
3175
- importedComponents
3176
- };
3177
- const renderExpression = resolveRenderExpression(componentExpr, context);
3178
- if (!renderExpression) return {
3179
- templateTags: /* @__PURE__ */ new Set(),
3180
- importedComponents
3181
- };
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);
3327
+ }
3182
3328
  return {
3183
- templateTags: collectJsxTemplateTags(renderExpression),
3184
- importedComponents
3329
+ renderExpression,
3330
+ autoComponentContext: {
3331
+ templateTags,
3332
+ importedComponents
3333
+ }
3185
3334
  };
3186
3335
  }
3187
- function findJsxRenderExpression(ast, context) {
3188
- const componentExpr = findExportDefaultExpression(ast);
3189
- if (!componentExpr) {
3190
- context.warnings.push("未识别到默认导出组件。");
3191
- return null;
3192
- }
3193
- const renderExpression = resolveRenderExpression(componentExpr, context);
3194
- if (!renderExpression) return null;
3195
- return renderExpression;
3196
- }
3197
3336
  //#endregion
3198
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]/;
3199
3343
  function isEventBinding(name) {
3200
- return /^on[A-Z]/.test(name) || /^catch[A-Z]/.test(name) || /^captureBind[A-Z]/.test(name) || /^captureCatch[A-Z]/.test(name) || /^mutBind[A-Z]/.test(name);
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);
3201
3345
  }
3346
+ const LEADING_UPPER_RE = /^[A-Z]/;
3347
+ const UPPER_CHAR_RE = /[A-Z]/g;
3202
3348
  function lowerEventName(name) {
3203
3349
  if (!name) return name;
3204
- 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());
3205
3351
  }
3206
3352
  function toEventBindingName(rawName, context) {
3207
3353
  const resolveEvent = (name) => context.platform.mapEventName(lowerEventName(name));
3208
- if (/^captureBind[A-Z]/.test(rawName)) {
3354
+ if (CAPTURE_BIND_EVENT_RE.test(rawName)) {
3209
3355
  const eventName = resolveEvent(rawName.slice(11));
3210
3356
  return context.platform.eventBindingAttr(`capture-bind:${eventName}`);
3211
3357
  }
3212
- if (/^captureCatch[A-Z]/.test(rawName)) {
3358
+ if (CAPTURE_CATCH_EVENT_RE.test(rawName)) {
3213
3359
  const eventName = resolveEvent(rawName.slice(12));
3214
3360
  return context.platform.eventBindingAttr(`capture-catch:${eventName}`);
3215
3361
  }
3216
- if (/^mutBind[A-Z]/.test(rawName)) {
3362
+ if (MUT_BIND_EVENT_RE.test(rawName)) {
3217
3363
  const eventName = resolveEvent(rawName.slice(7));
3218
3364
  return context.platform.eventBindingAttr(`mut-bind:${eventName}`);
3219
3365
  }
3220
- if (/^catch[A-Z]/.test(rawName)) {
3366
+ if (CATCH_EVENT_RE.test(rawName)) {
3221
3367
  const eventName = resolveEvent(rawName.slice(5));
3222
3368
  return context.platform.eventBindingAttr(`catch:${eventName}`);
3223
3369
  }
@@ -3417,29 +3563,27 @@ function createJsxCompileContext(options) {
3417
3563
  scopeStack: []
3418
3564
  };
3419
3565
  }
3420
- function compileJsxTemplate(source, filename, options) {
3566
+ /**
3567
+ * 单次解析同时编译模板和收集自动组件上下文,避免重复 babelParse 和 traverse。
3568
+ */
3569
+ function compileJsxTemplateAndCollectComponents(source, filename, options) {
3421
3570
  const ast = parse$2(source, BABEL_TS_MODULE_PARSER_OPTIONS);
3422
3571
  const context = createJsxCompileContext(options);
3423
- const renderExpression = findJsxRenderExpression(ast, context);
3424
- if (!renderExpression) {
3425
- context.warnings = context.warnings.map((message) => message === "未识别到默认导出组件。" ? `未在 ${filename} 中识别到默认导出组件。` : message);
3426
- return {
3427
- template: void 0,
3428
- warnings: context.warnings,
3429
- inlineExpressions: context.inlineExpressions
3430
- };
3431
- }
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);
3432
3576
  return {
3433
- template: compileRenderableExpression(renderExpression, context),
3577
+ template,
3434
3578
  warnings: context.warnings,
3435
- inlineExpressions: context.inlineExpressions
3579
+ inlineExpressions: context.inlineExpressions,
3580
+ autoComponentContext
3436
3581
  };
3437
3582
  }
3438
- function collectJsxAutoComponents(source, filename, options) {
3439
- return collectJsxAutoComponentContext(source, filename, createJsxCompileContext(options), options?.warn);
3440
- }
3441
3583
  //#endregion
3442
3584
  //#region src/plugins/jsx/compileJsxFile.ts
3585
+ const LEADING_DOT_RE = /^\./;
3586
+ const SETUP_CALL_RE$1 = /\bsetup\s*\(/;
3443
3587
  /**
3444
3588
  * 编译 JSX/TSX 文件,输出 wevu 脚本与 WXML 模板。
3445
3589
  */
@@ -3453,7 +3597,7 @@ async function compileJsxFile(source, filename, options) {
3453
3597
  let scriptSource = source;
3454
3598
  let scriptMacroConfig;
3455
3599
  let scriptMacroHash;
3456
- const scriptLang = path.extname(filename).replace(/^\./, "") || void 0;
3600
+ const scriptLang = path.extname(filename).replace(LEADING_DOT_RE, "") || void 0;
3457
3601
  try {
3458
3602
  const extracted = await extractJsonMacroFromScriptSetup(source, filename, scriptLang, { merge: (target, incoming) => mergeJson(target, incoming, "macro") });
3459
3603
  scriptSource = extracted.stripped;
@@ -3463,8 +3607,7 @@ async function compileJsxFile(source, filename, options) {
3463
3607
  const message = error instanceof Error ? error.message : String(error);
3464
3608
  throw new Error(`解析 ${filename} 失败:${message}`);
3465
3609
  }
3466
- const compiledTemplate = compileJsxTemplate(source, filename, options);
3467
- const autoComponentContext = collectJsxAutoComponents(source, filename, options);
3610
+ const { template: compiledTemplateStr, warnings: templateWarnings, inlineExpressions, autoComponentContext } = compileJsxTemplateAndCollectComponents(source, filename, options);
3468
3611
  const autoUsingComponentsMap = {};
3469
3612
  if (options?.autoUsingComponents?.resolveUsingComponentPath && autoComponentContext.templateTags.size > 0) for (const imported of autoComponentContext.importedComponents) {
3470
3613
  if (!autoComponentContext.templateTags.has(imported.localName)) continue;
@@ -3496,9 +3639,9 @@ async function compileJsxFile(source, filename, options) {
3496
3639
  isPage: options?.isPage,
3497
3640
  warn: options?.warn,
3498
3641
  wevuDefaults: options?.wevuDefaults,
3499
- inlineExpressions: compiledTemplate.inlineExpressions
3642
+ inlineExpressions
3500
3643
  });
3501
- 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}`));
3502
3645
  let configObj;
3503
3646
  if (Object.keys(autoUsingComponentsMap).length > 0 || Object.keys(autoImportTagsMap).length > 0) {
3504
3647
  const existingRaw = configObj?.usingComponents;
@@ -3517,23 +3660,24 @@ async function compileJsxFile(source, filename, options) {
3517
3660
  if (scriptMacroConfig && Object.keys(scriptMacroConfig).length > 0) configObj = mergeJson(configObj ?? {}, scriptMacroConfig, "macro");
3518
3661
  return {
3519
3662
  script: transformedScript.code,
3520
- template: compiledTemplate.template,
3663
+ template: compiledTemplateStr,
3521
3664
  config: configObj && Object.keys(configObj).length > 0 ? JSON.stringify(configObj, null, 2) : void 0,
3522
3665
  meta: {
3523
3666
  hasScriptSetup: false,
3524
- hasSetupOption: /\bsetup\s*\(/.test(normalizedScriptSource),
3667
+ hasSetupOption: SETUP_CALL_RE$1.test(normalizedScriptSource),
3525
3668
  jsonMacroHash: scriptMacroHash
3526
3669
  }
3527
3670
  };
3528
3671
  }
3529
3672
  //#endregion
3530
3673
  //#region src/utils/text.ts
3674
+ const CRLF_RE = /\r\n?/g;
3531
3675
  /**
3532
3676
  * 统一文本换行符为 LF,消除不同系统(CRLF/CR/LF)差异。
3533
3677
  */
3534
3678
  function normalizeLineEndings(source) {
3535
3679
  if (!source.includes("\r")) return source;
3536
- return source.replace(/\r\n?/g, "\n");
3680
+ return source.replace(CRLF_RE, "\n");
3537
3681
  }
3538
3682
  //#endregion
3539
3683
  //#region src/plugins/utils/cache.ts
@@ -3623,7 +3767,7 @@ function getReadFileCheckMtime(config) {
3623
3767
  //#endregion
3624
3768
  //#region src/utils/viteId.ts
3625
3769
  const VUE_VIRTUAL_MODULE_PREFIX = "\0vue:";
3626
- const BACKSLASH_RE = /\\/g;
3770
+ const BACKSLASH_RE$3 = /\\/g;
3627
3771
  function normalizeViteId(id, options) {
3628
3772
  const stripQuery = options?.stripQuery !== false;
3629
3773
  const fileProtocolToPathEnabled = options?.fileProtocolToPath !== false;
@@ -3632,7 +3776,7 @@ function normalizeViteId(id, options) {
3632
3776
  const stripLeadingNullByte = options?.stripLeadingNullByte === true;
3633
3777
  let clean = id;
3634
3778
  if (stripVueVirtualPrefix && clean.startsWith(VUE_VIRTUAL_MODULE_PREFIX)) clean = clean.slice(5);
3635
- if (clean.includes("\\")) clean = clean.replace(BACKSLASH_RE, "/");
3779
+ if (clean.includes("\\")) clean = clean.replace(BACKSLASH_RE$3, "/");
3636
3780
  if (stripQuery) clean = clean.split("?", 1)[0];
3637
3781
  if (fileProtocolToPathEnabled && clean.startsWith("file://")) try {
3638
3782
  clean = fileURLToPath(clean);
@@ -3760,7 +3904,7 @@ async function resolveSfcBlockSrc(descriptor, filename, options) {
3760
3904
  if (nextDescriptor.styles.length) nextDescriptor.styles = await Promise.all(nextDescriptor.styles.map((style) => resolveBlock(style, "style")));
3761
3905
  return {
3762
3906
  descriptor: nextDescriptor,
3763
- deps: Array.from(deps)
3907
+ deps: [...deps]
3764
3908
  };
3765
3909
  }
3766
3910
  //#endregion
@@ -3769,14 +3913,17 @@ const sfcParseCache = new LRUCache({ max: 512 });
3769
3913
  const SCRIPT_SETUP_SRC_ATTR = "data-weapp-vite-src";
3770
3914
  const SCRIPT_SRC_ATTR = "data-weapp-vite-script-src";
3771
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;
3772
3919
  /**
3773
3920
  * 预处理 `<script setup src>`,避免编译器丢失 src。
3774
3921
  */
3775
3922
  function preprocessScriptSetupSrc(source) {
3776
3923
  if (!source.includes("<script") || !source.includes("setup") || !source.includes("src")) return source;
3777
3924
  return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3778
- if (!/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3779
- return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SETUP_SRC_ATTR}$1`)}>`;
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`)}>`;
3780
3927
  });
3781
3928
  }
3782
3929
  /**
@@ -3785,8 +3932,8 @@ function preprocessScriptSetupSrc(source) {
3785
3932
  function preprocessScriptSrc(source) {
3786
3933
  if (!source.includes("<script") || !source.includes("src")) return source;
3787
3934
  return source.replace(SCRIPT_SETUP_TAG_RE, (full, attrs) => {
3788
- if (/\bsetup\b/i.test(attrs) || !/\bsrc\b/i.test(attrs)) return full;
3789
- return `<script${attrs.replace(/\bsrc(\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))/i, `${SCRIPT_SRC_ATTR}$1`)}>`;
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`)}>`;
3790
3937
  });
3791
3938
  }
3792
3939
  /**
@@ -3867,6 +4014,8 @@ function getSfcCheckMtime(config) {
3867
4014
  }
3868
4015
  //#endregion
3869
4016
  //#region src/plugins/vue/compiler/style.ts
4017
+ const CSS_RULE_RE = /([^{]+)(\{[^}]*\})/g;
4018
+ const CSS_CLASS_RE = /\.([a-z_][\w-]*)(?:\[[^\]]+\])?\s*\{/gi;
3870
4019
  /**
3871
4020
  * 将 Vue SFC 的 style 块转换为 WXSS
3872
4021
  */
@@ -3890,7 +4039,7 @@ function compileVueStyleToWxss(styleBlock, options) {
3890
4039
  */
3891
4040
  function transformScopedCss(source, id) {
3892
4041
  const scopedId = `data-v-${id}`;
3893
- return source.replace(/([^{]+)(\{[^}]*\})/g, (match, selector, rules) => {
4042
+ return source.replace(CSS_RULE_RE, (match, selector, rules) => {
3894
4043
  const trimmedSelector = selector.trim();
3895
4044
  if (!trimmedSelector) return match;
3896
4045
  if (trimmedSelector.includes("[") || trimmedSelector.includes(":deep(") || trimmedSelector.includes(":slotted(")) return match;
@@ -3906,7 +4055,7 @@ function transformScopedCss(source, id) {
3906
4055
  function transformCssModules(source, id) {
3907
4056
  const classes = {};
3908
4057
  const hash = generateHash(id);
3909
- const classRegex = /\.([a-z_][\w-]*)(?:\[[^\]]+\])?\s*\{/gi;
4058
+ const classRegex = new RegExp(CSS_CLASS_RE.source, CSS_CLASS_RE.flags);
3910
4059
  const foundClasses = [];
3911
4060
  let result = classRegex.exec(source);
3912
4061
  while (result !== null) {
@@ -4200,10 +4349,10 @@ function getClassStyleWxsSource(options = {}) {
4200
4349
  }
4201
4350
  //#endregion
4202
4351
  //#region src/plugins/vue/compiler/template/elements/forExpression.ts
4203
- const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
4352
+ const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
4204
4353
  const FOR_ITEM_ALIAS_PLACEHOLDER = "__wv_for_item__";
4205
4354
  function isIdentifier(value) {
4206
- return IDENTIFIER_RE$1.test(value);
4355
+ return IDENTIFIER_RE$4.test(value);
4207
4356
  }
4208
4357
  function splitTopLevelByComma(input) {
4209
4358
  const out = [];
@@ -4477,12 +4626,17 @@ function withSlotProps(context, mapping, fn) {
4477
4626
  popSlotProps(context);
4478
4627
  }
4479
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;
4480
4634
  function collectScopePropMapping(context) {
4481
4635
  const mapping = {};
4482
4636
  if (!context.slotMultipleInstance) return mapping;
4483
4637
  for (const scope of context.scopeStack) for (const name of scope) {
4484
- if (!/^[A-Z_$][\w$]*$/i.test(name)) continue;
4485
- if (!Object.prototype.hasOwnProperty.call(mapping, name)) mapping[name] = name;
4638
+ if (!IDENTIFIER_RE$3.test(name)) continue;
4639
+ if (!Object.hasOwn(mapping, name)) mapping[name] = name;
4486
4640
  }
4487
4641
  return mapping;
4488
4642
  }
@@ -4493,7 +4647,7 @@ function buildScopePropsExpression(context) {
4493
4647
  return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${key}`).join(",")}]`;
4494
4648
  }
4495
4649
  function toWxmlStringLiteral$1(value) {
4496
- return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n")}'`;
4650
+ return `'${value.replace(BACKSLASH_RE$2, "\\\\").replace(SINGLE_QUOTE_RE$2, "\\'").replace(CR_RE$1, "\\r").replace(LF_RE$1, "\\n")}'`;
4497
4651
  }
4498
4652
  function hashString(input) {
4499
4653
  let hash = 0;
@@ -4570,6 +4724,7 @@ function replaceIdentifierWithExpression(path, replacement) {
4570
4724
  }
4571
4725
  path.replaceWith(replacement);
4572
4726
  }
4727
+ const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
4573
4728
  function rewriteScopedSlotExpression(exp, context) {
4574
4729
  const normalized = normalizeWxmlExpression(exp);
4575
4730
  const parsed = parseBabelExpressionFile(normalized);
@@ -4580,7 +4735,7 @@ function rewriteScopedSlotExpression(exp, context) {
4580
4735
  const forAliases = collectForAliasMapping$2(context);
4581
4736
  const createMemberAccess = (target, prop) => {
4582
4737
  if (!prop) return t.identifier(target);
4583
- 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));
4584
4739
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
4585
4740
  };
4586
4741
  traverse(ast, { Identifier(path) {
@@ -4588,7 +4743,7 @@ function rewriteScopedSlotExpression(exp, context) {
4588
4743
  const name = path.node.name;
4589
4744
  if (SCOPED_SLOT_GLOBALS.has(name)) return;
4590
4745
  if (path.scope.hasBinding(name)) return;
4591
- if (Object.prototype.hasOwnProperty.call(forAliases, name)) {
4746
+ if (Object.hasOwn(forAliases, name)) {
4592
4747
  const aliasExp = parseBabelExpression(forAliases[name]);
4593
4748
  if (aliasExp) {
4594
4749
  replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
@@ -4596,7 +4751,7 @@ function rewriteScopedSlotExpression(exp, context) {
4596
4751
  }
4597
4752
  }
4598
4753
  if (locals.has(name)) return;
4599
- if (Object.prototype.hasOwnProperty.call(slotProps, name)) {
4754
+ if (Object.hasOwn(slotProps, name)) {
4600
4755
  replaceIdentifierWithExpression(path, createMemberAccess("__wvSlotPropsData", slotProps[name]));
4601
4756
  return;
4602
4757
  }
@@ -4617,7 +4772,7 @@ function rewriteForAliasExpression(exp, context) {
4617
4772
  if (!path.isReferencedIdentifier()) return;
4618
4773
  const name = path.node.name;
4619
4774
  if (path.scope.hasBinding(name)) return;
4620
- if (!Object.prototype.hasOwnProperty.call(forAliases, name)) return;
4775
+ if (!Object.hasOwn(forAliases, name)) return;
4621
4776
  const aliasExp = parseBabelExpression(forAliases[name]);
4622
4777
  if (!aliasExp) return;
4623
4778
  replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
@@ -4778,14 +4933,14 @@ const INLINE_GLOBALS = new Set([
4778
4933
  "ctx",
4779
4934
  "scope"
4780
4935
  ]);
4781
- const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
4936
+ const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
4782
4937
  const SIMPLE_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
4783
4938
  function createMemberAccess$1(target, prop) {
4784
- 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));
4785
4940
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
4786
4941
  }
4787
4942
  function resolveSlotPropBinding(slotProps, name) {
4788
- if (!Object.prototype.hasOwnProperty.call(slotProps, name)) return null;
4943
+ if (!Object.hasOwn(slotProps, name)) return null;
4789
4944
  const prop = slotProps[name];
4790
4945
  if (!prop) return "__wvSlotPropsData";
4791
4946
  return generateExpression(createMemberAccess$1("__wvSlotPropsData", prop));
@@ -5015,7 +5170,7 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5015
5170
  const name = path.node.name;
5016
5171
  if (JS_RUNTIME_GLOBALS.has(name)) return;
5017
5172
  if (path.scope.hasBinding(name)) return;
5018
- if (Object.prototype.hasOwnProperty.call(forAliases, name)) {
5173
+ if (Object.hasOwn(forAliases, name)) {
5019
5174
  const aliasExp = parseBabelExpression(forAliases[name]);
5020
5175
  if (aliasExp) {
5021
5176
  const replacement = t.cloneNode(aliasExp, true);
@@ -5031,7 +5186,7 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5031
5186
  }
5032
5187
  if (locals.has(name)) return;
5033
5188
  let replacement;
5034
- if (context.rewriteScopedSlot) if (Object.prototype.hasOwnProperty.call(slotProps, name)) {
5189
+ if (context.rewriteScopedSlot) if (Object.hasOwn(slotProps, name)) {
5035
5190
  const prop = slotProps[name];
5036
5191
  const base = createThisMemberAccess("__wvSlotPropsData");
5037
5192
  replacement = createUnrefCall(prop ? createMemberAccess(base, prop) : base);
@@ -5099,8 +5254,12 @@ function renderMustache(expression, context) {
5099
5254
  }
5100
5255
  //#endregion
5101
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;
5102
5261
  function toWxmlStringLiteral(value) {
5103
- 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")}'`;
5104
5263
  }
5105
5264
  function cloneForStack(context) {
5106
5265
  return context.forStack.map((info) => ({ ...info }));
@@ -5113,8 +5272,9 @@ function generateExpressionCode(exp) {
5113
5272
  const { code } = generate(exp, { compact: true });
5114
5273
  return code;
5115
5274
  }
5275
+ const TRAILING_SEMICOLONS_RE = /;+\s*$/;
5116
5276
  function normalizeStyleFallbackValue(value) {
5117
- return value.trim().replace(/;+\s*$/, "");
5277
+ return value.trim().replace(TRAILING_SEMICOLONS_RE, "");
5118
5278
  }
5119
5279
  function buildStyleErrorFallback(staticValue, shouldHideByDefault) {
5120
5280
  const segments = [];
@@ -5151,7 +5311,10 @@ function shouldPreferJsClassStyleRuntime(exp) {
5151
5311
  return false;
5152
5312
  }
5153
5313
  if (t.isConditionalExpression(current)) return visit(current.test) || visit(current.consequent) || visit(current.alternate);
5154
- 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
+ }
5155
5318
  if (t.isUnaryExpression(current)) return visit(current.argument);
5156
5319
  return true;
5157
5320
  };
@@ -5252,8 +5415,10 @@ function createInlineObjectLiteralAttr(argValue, rawExpValue, context) {
5252
5415
  if (context.mustacheInterpolation === "spaced") return `${argValue}="${renderMustache(expValue, context)}"`;
5253
5416
  return `${argValue}="{{ ${expValue} }}"`;
5254
5417
  }
5255
- const isSimpleIdentifier = (value) => /^[A-Z_$][\w$]*$/i.test(value);
5256
- 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);
5257
5422
  function transformBindDirective(node, context, forInfo) {
5258
5423
  const { exp, arg } = node;
5259
5424
  if (!arg) return null;
@@ -5298,6 +5463,7 @@ function transformBindDirective(node, context, forInfo) {
5298
5463
  }
5299
5464
  //#endregion
5300
5465
  //#region src/plugins/vue/compiler/template/directives/custom.ts
5466
+ const IDENTIFIER_RE = /^[a-z_$][\w$]*$/i;
5301
5467
  function transformCustomDirective(name, exp, arg, context) {
5302
5468
  if (new Set([
5303
5469
  "bind",
@@ -5317,7 +5483,7 @@ function transformCustomDirective(name, exp, arg, context) {
5317
5483
  const dataAttrName = `data-v-${name}`;
5318
5484
  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
5319
5485
  const expValue = normalizeWxmlExpressionWithContext(exp.content, context);
5320
- if (/^[a-z_$][\w$]*$/i.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5486
+ if (IDENTIFIER_RE.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5321
5487
  return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5322
5488
  }
5323
5489
  if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION) return `${dataAttrName}="${arg.content}"`;
@@ -5333,8 +5499,9 @@ function getElementType(element) {
5333
5499
  }
5334
5500
  return "";
5335
5501
  }
5502
+ const QUOTE_RE$1 = /"/g;
5336
5503
  function transformVModel(element, expValue, context) {
5337
- const escapedModel = expValue.replace(/"/g, "&quot;");
5504
+ const escapedModel = expValue.replace(QUOTE_RE$1, "&quot;");
5338
5505
  const bindModel = (event) => {
5339
5506
  return `${context.platform.eventBindingAttr(event)}="__weapp_vite_model" data-wv-model="${escapedModel}"`;
5340
5507
  };
@@ -5365,21 +5532,25 @@ function transformModelDirective(node, context, elementNode) {
5365
5532
  }
5366
5533
  //#endregion
5367
5534
  //#region src/plugins/vue/compiler/template/directives/on.ts
5368
- 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);
5369
5537
  function shouldUseDetailPayload(options) {
5370
5538
  return options?.isComponent === true;
5371
5539
  }
5540
+ const NON_ALNUM_RE = /[^a-z0-9]+/gi;
5541
+ const LEADING_TRAILING_DASH_RE = /^-+|-+$/g;
5372
5542
  function normalizeEventDatasetSuffix(eventName) {
5373
- 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";
5374
5544
  }
5545
+ const QUOTE_RE = /"/g;
5375
5546
  function buildInlineScopeAttrs(scopeBindings, context) {
5376
5547
  return scopeBindings.map((binding, index) => {
5377
- return `data-wv-s${index}="${renderMustache(binding.replace(/"/g, "&quot;"), context)}"`;
5548
+ return `data-wv-s${index}="${renderMustache(binding.replace(QUOTE_RE, "&quot;"), context)}"`;
5378
5549
  });
5379
5550
  }
5380
5551
  function buildInlineIndexAttrs(indexBindings, context) {
5381
5552
  return indexBindings.map((binding, index) => {
5382
- return `data-wv-i${index}="${renderMustache(binding.replace(/"/g, "&quot;"), context)}"`;
5553
+ return `data-wv-i${index}="${renderMustache(binding.replace(QUOTE_RE, "&quot;"), context)}"`;
5383
5554
  });
5384
5555
  }
5385
5556
  function resolveEventPrefix(modifiers) {
@@ -5444,7 +5615,7 @@ function transformOnDirective(node, context, options) {
5444
5615
  }
5445
5616
  if (isInlineExpression) return [
5446
5617
  detailAttr,
5447
- `data-wv-inline-${eventSuffix}="${inlineSource.replace(/"/g, "&quot;")}"`,
5618
+ `data-wv-inline-${eventSuffix}="${inlineSource.replace(QUOTE_RE, "&quot;")}"`,
5448
5619
  `${bindAttr}="__weapp_vite_inline"`
5449
5620
  ].filter(Boolean).join(" ");
5450
5621
  return [detailAttr, `${bindAttr}="${expValue}"`].filter(Boolean).join(" ");
@@ -5567,6 +5738,8 @@ function collectElementAttributes(node, context, options) {
5567
5738
  }
5568
5739
  //#endregion
5569
5740
  //#region src/plugins/vue/compiler/template/elements/slotProps.ts
5741
+ const BACKSLASH_RE = /\\/g;
5742
+ const SINGLE_QUOTE_RE = /'/g;
5570
5743
  function parseSlotPropsExpression(exp, context) {
5571
5744
  const trimmed = exp.trim();
5572
5745
  if (!trimmed) return {};
@@ -5638,7 +5811,7 @@ function collectSlotBindingExpression(node, context) {
5638
5811
  const literal = prop.value?.type === NodeTypes.TEXT ? prop.value.content : "";
5639
5812
  if (literal) namedBindings.push({
5640
5813
  key: prop.name,
5641
- value: `'${literal.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`
5814
+ value: `'${literal.replace(BACKSLASH_RE, "\\\\").replace(SINGLE_QUOTE_RE, "\\'")}'`
5642
5815
  });
5643
5816
  }
5644
5817
  }
@@ -5959,6 +6132,7 @@ function transformNormalElement(node, context, transformNode) {
5959
6132
  }
5960
6133
  //#endregion
5961
6134
  //#region src/plugins/vue/compiler/template/elements/tag-structural.ts
6135
+ const REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
5962
6136
  function resolveConditionExpression$1(rawExpValue, context, hint) {
5963
6137
  return (shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
5964
6138
  }
@@ -5995,7 +6169,7 @@ function transformForElement(node, context, transformNode) {
5995
6169
  const generatedItem = `__wv_item_${context.forIndexSeed++}`;
5996
6170
  forInfo.item = generatedItem;
5997
6171
  if (forInfo.itemAliases) {
5998
- const escaped = FOR_ITEM_ALIAS_PLACEHOLDER.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6172
+ const escaped = FOR_ITEM_ALIAS_PLACEHOLDER.replace(REGEX_SPECIAL_CHARS_RE, "\\$&");
5999
6173
  const placeholderRE = new RegExp(`\\b${escaped}\\b`, "g");
6000
6174
  forInfo.itemAliases = Object.fromEntries(Object.entries(forInfo.itemAliases).map(([alias, expression]) => {
6001
6175
  return [alias, expression.replace(placeholderRE, generatedItem)];
@@ -6046,6 +6220,8 @@ function transformForElement(node, context, transformNode) {
6046
6220
  }
6047
6221
  //#endregion
6048
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;
6049
6225
  function resolveConditionExpression(rawExpValue, context, hint) {
6050
6226
  return (shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
6051
6227
  }
@@ -6104,7 +6280,7 @@ function transformTemplateElement(node, context, transformNode) {
6104
6280
  if (dir.name === "else") return context.platform.wrapElse(children);
6105
6281
  return transformIfElement(fakeNode, context, transformNode);
6106
6282
  }
6107
- 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>");
6108
6284
  return children;
6109
6285
  }
6110
6286
  const attrs = [];
@@ -6129,9 +6305,12 @@ function transformElement(node, context, transformNode) {
6129
6305
  }
6130
6306
  //#endregion
6131
6307
  //#region src/plugins/vue/compiler/template/nodes.ts
6308
+ const AMP_RE = /&/g;
6309
+ const LT_RE = /</g;
6310
+ const GT_RE = />/g;
6132
6311
  function escapeWxmlText(value) {
6133
6312
  if (!value) return "";
6134
- 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;");
6135
6314
  }
6136
6315
  function transformText(node, _context) {
6137
6316
  return escapeWxmlText(node.content);
@@ -6403,9 +6582,10 @@ function getErrorMessage(error) {
6403
6582
  if (error instanceof Error) return error.message;
6404
6583
  return typeof error === "string" ? error : "";
6405
6584
  }
6585
+ const BEHAVIOR_NOT_DEFINED_RE = /\bBehavior is not defined\b/;
6406
6586
  function shouldFallbackToRawDefineOptions(error) {
6407
6587
  const message = getErrorMessage(error);
6408
- return /\bBehavior is not defined\b/.test(message);
6588
+ return BEHAVIOR_NOT_DEFINED_RE.test(message);
6409
6589
  }
6410
6590
  function normalizeScriptSetupLang(lang) {
6411
6591
  if (!lang) return "ts";
@@ -6418,8 +6598,9 @@ function resolveScriptSetupExtension(lang) {
6418
6598
  if (normalized === "ts" || normalized === "tsx" || normalized === "cts" || normalized === "mts") return "ts";
6419
6599
  return "js";
6420
6600
  }
6601
+ const IDENTIFIER_LIKE_KEY_RE = /^[A-Z_$][\w$]*$/i;
6421
6602
  function isIdentifierLikeKey(key) {
6422
- return /^[A-Z_$][\w$]*$/i.test(key);
6603
+ return IDENTIFIER_LIKE_KEY_RE.test(key);
6423
6604
  }
6424
6605
  const SERIALIZABLE_NATIVE_FUNCTIONS = new Map([
6425
6606
  [String, "String"],
@@ -6632,6 +6813,9 @@ async function inlineScriptSetupDefineOptionsArgs(content, filename, lang) {
6632
6813
  }
6633
6814
  //#endregion
6634
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$/;
6635
6819
  function extractDefineOptionsHash(content) {
6636
6820
  let ast;
6637
6821
  try {
@@ -6674,7 +6858,7 @@ async function parseVueFile(source, filename, options) {
6674
6858
  let descriptorForCompile = resolvedDescriptor;
6675
6859
  const meta = {
6676
6860
  hasScriptSetup: !!resolvedDescriptor.scriptSetup,
6677
- hasSetupOption: !!resolvedDescriptor.script && /\bsetup\s*\(/.test(resolvedDescriptor.script.content),
6861
+ hasSetupOption: !!resolvedDescriptor.script && SETUP_CALL_RE.test(resolvedDescriptor.script.content),
6678
6862
  sfcSrcDeps
6679
6863
  };
6680
6864
  let scriptSetupMacroConfig;
@@ -6715,8 +6899,7 @@ async function parseVueFile(source, filename, options) {
6715
6899
  const resolvedNext = await resolveSfcBlockSrc(nextDescriptor, filename, options.sfcSrc);
6716
6900
  descriptorForCompile = resolvedNext.descriptor;
6717
6901
  if (resolvedNext.deps.length) {
6718
- const deps = new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps]);
6719
- sfcSrcDeps = Array.from(deps);
6902
+ sfcSrcDeps = [...new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps])];
6720
6903
  meta.sfcSrcDeps = sfcSrcDeps;
6721
6904
  }
6722
6905
  } else descriptorForCompile = nextDescriptor;
@@ -6727,7 +6910,7 @@ async function parseVueFile(source, filename, options) {
6727
6910
  defineOptionsHash = extractDefineOptionsHash(scriptSetup.content);
6728
6911
  }
6729
6912
  const compileScriptSetup = descriptorForCompile.scriptSetup;
6730
- if (compileScriptSetup?.content && /\bdefineOptions\s*\(/.test(compileScriptSetup.content)) {
6913
+ if (compileScriptSetup?.content && DEFINE_OPTIONS_CALL_RE.test(compileScriptSetup.content)) {
6731
6914
  const inlined = await inlineScriptSetupDefineOptionsArgs(compileScriptSetup.content, filename, compileScriptSetup.lang);
6732
6915
  if (inlined.code !== compileScriptSetup.content) if (compileScriptSetup.src) descriptorForCompile = {
6733
6916
  ...descriptorForCompile,
@@ -6755,15 +6938,14 @@ async function parseVueFile(source, filename, options) {
6755
6938
  const resolvedNext = await resolveSfcBlockSrc(nextDescriptor, filename, options.sfcSrc);
6756
6939
  descriptorForCompile = resolvedNext.descriptor;
6757
6940
  if (resolvedNext.deps.length) {
6758
- const deps = new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps]);
6759
- sfcSrcDeps = Array.from(deps);
6941
+ sfcSrcDeps = [...new Set([...sfcSrcDeps ?? [], ...resolvedNext.deps])];
6760
6942
  meta.sfcSrcDeps = sfcSrcDeps;
6761
6943
  }
6762
6944
  } else descriptorForCompile = nextDescriptor;
6763
6945
  descriptorForCompileSource = nextSource;
6764
6946
  }
6765
6947
  }
6766
- const isAppFile = /[\\/]app\.vue$/.test(filename);
6948
+ const isAppFile = APP_VUE_FILE_RE.test(filename);
6767
6949
  return {
6768
6950
  descriptor: resolvedDescriptor,
6769
6951
  descriptorForCompile,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/compiler",
3
3
  "type": "module",
4
- "version": "6.7.4",
4
+ "version": "6.7.6",
5
5
  "description": "wevu 编译器基础包,面向小程序模板的编译与转换",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -45,14 +45,14 @@
45
45
  "@babel/parser": "^7.29.0",
46
46
  "@babel/traverse": "^7.29.0",
47
47
  "@babel/types": "^7.29.0",
48
- "@vue/compiler-core": "^3.5.29",
48
+ "@vue/compiler-core": "^3.5.30",
49
49
  "comment-json": "^4.6.2",
50
50
  "fs-extra": "^11.3.4",
51
51
  "lru-cache": "^11.2.6",
52
52
  "magic-string": "^0.30.21",
53
53
  "merge": "^2.1.1",
54
54
  "pathe": "^2.0.3",
55
- "vue": "^3.5.29",
55
+ "vue": "^3.5.30",
56
56
  "@weapp-core/shared": "3.0.1",
57
57
  "rolldown-require": "2.0.6"
58
58
  },
@@ -65,6 +65,7 @@
65
65
  "build": "tsdown",
66
66
  "test": "vitest run",
67
67
  "test:dev": "vitest",
68
+ "typecheck": "tsc --noEmit",
68
69
  "release": "pnpm publish",
69
70
  "lint": "eslint .",
70
71
  "lint:fix": "eslint . --fix"