@wevu/compiler 6.16.7 → 6.16.8

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.
package/dist/index.d.mts CHANGED
@@ -217,6 +217,8 @@ interface ScopedSlotComponentAsset {
217
217
  classStyleBindings?: ClassStyleBinding[];
218
218
  classStyleWxs?: boolean;
219
219
  inlineExpressions?: InlineExpressionAsset[];
220
+ ownerKeys?: string[];
221
+ ownerPropsExpression?: string;
220
222
  }
221
223
  /**
222
224
  * 内联表达式资源描述。
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import os from "node:os";
13
13
  import process from "node:process";
14
14
  import { collectFeatureFlagsFromCode, collectJsxImportedComponentsAndDefaultExportFromBabelAst, collectJsxTemplateTagsFromBabelExpression, getRenderPropertyFromComponentOptions, parseJsLikeWithEngine, resolveRenderExpressionFromComponentOptions, toStaticObjectKey, unwrapTypeScriptExpression } from "@weapp-vite/ast";
15
15
  import { LRUCache } from "lru-cache";
16
- import { WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_KEY, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ATTR, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_PROPS_ATTR, WEVU_SLOT_PROPS_DATA_KEY, WEVU_SLOT_PROPS_KEY, WEVU_SLOT_SCOPE_ATTR, WEVU_SLOT_SCOPE_KEY, WEVU_TEMPLATE_REFS_KEY } from "@weapp-core/constants";
16
+ import { WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_GENERIC_SLOT_OWNER_DATA_KEY, WEVU_GENERIC_SLOT_OWNER_ID_ATTR, WEVU_GENERIC_SLOT_OWNER_PROPS_ATTR, WEVU_GENERIC_SLOT_PROPS_ATTR, WEVU_GENERIC_SLOT_PROPS_DATA_ATTR, WEVU_GENERIC_SLOT_PROPS_DATA_KEY, WEVU_GENERIC_SLOT_SCOPE_ATTR, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_KEY, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_OWNER_PROXY_KEY, WEVU_SLOT_PROPS_DATA_KEY, WEVU_SLOT_PROPS_KEY, WEVU_SLOT_SCOPE_KEY, WEVU_TEMPLATE_REFS_KEY } from "@weapp-core/constants";
17
17
  import { compileScript, parse } from "vue/compiler-sfc";
18
18
  import { fileURLToPath } from "node:url";
19
19
  import { parse as parse$1 } from "@vue/compiler-dom";
@@ -3145,11 +3145,11 @@ function normalizeJsxText(value) {
3145
3145
  function printExpression(exp) {
3146
3146
  return generate(exp).code;
3147
3147
  }
3148
- function unwrapTsExpression$2(exp) {
3148
+ function unwrapTsExpression$3(exp) {
3149
3149
  return unwrapTypeScriptExpression(exp);
3150
3150
  }
3151
3151
  function normalizeInterpolationExpression(exp) {
3152
- return normalizeWxmlExpression(printExpression(unwrapTsExpression$2(exp)));
3152
+ return normalizeWxmlExpression(printExpression(unwrapTsExpression$3(exp)));
3153
3153
  }
3154
3154
  function renderMustache$1(expression, context) {
3155
3155
  return context.mustacheInterpolation === "spaced" ? `{{ ${expression} }}` : `{{${expression}}}`;
@@ -3701,7 +3701,7 @@ function readJsxAttributeExpression(value) {
3701
3701
  if (t.isStringLiteral(value)) return value;
3702
3702
  if (!t.isJSXExpressionContainer(value)) return null;
3703
3703
  if (t.isJSXEmptyExpression(value.expression)) return null;
3704
- return unwrapTsExpression$2(value.expression);
3704
+ return unwrapTsExpression$3(value.expression);
3705
3705
  }
3706
3706
  function extractJsxKeyExpression(node) {
3707
3707
  for (const attr of node.openingElement.attributes) {
@@ -3783,10 +3783,10 @@ function compileMapExpression(exp, context) {
3783
3783
  let bodyExp = null;
3784
3784
  if (t.isBlockStatement(callback.body)) {
3785
3785
  for (const statement of callback.body.body) if (t.isReturnStatement(statement) && statement.argument) {
3786
- bodyExp = unwrapTsExpression$2(statement.argument);
3786
+ bodyExp = unwrapTsExpression$3(statement.argument);
3787
3787
  break;
3788
3788
  }
3789
- } else bodyExp = unwrapTsExpression$2(callback.body);
3789
+ } else bodyExp = unwrapTsExpression$3(callback.body);
3790
3790
  const body = bodyExp ? compileRenderableExpression(bodyExp, context) : "";
3791
3791
  popScope$1(context, addedScope.length);
3792
3792
  if (!body) return "";
@@ -3821,7 +3821,7 @@ function compileLogicalExpression(exp, context) {
3821
3821
  return renderMustache$1(normalizeInterpolationExpression(exp), context);
3822
3822
  }
3823
3823
  function compileRenderableExpression(exp, context) {
3824
- const node = unwrapTsExpression$2(exp);
3824
+ const node = unwrapTsExpression$3(exp);
3825
3825
  if (t.isJSXElement(node)) return compileJsxElement(node, context);
3826
3826
  if (t.isJSXFragment(node)) return compileJsxFragment(node, context);
3827
3827
  if (t.isConditionalExpression(node)) return compileConditionalExpression(node, context);
@@ -4756,10 +4756,10 @@ function resolveMappedHtmlTagClassName(tag, context, resolvedTag) {
4756
4756
  }
4757
4757
  //#endregion
4758
4758
  //#region src/plugins/vue/compiler/template/elements/forExpression.ts
4759
- const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
4759
+ const IDENTIFIER_RE$5 = /^[A-Z_$][\w$]*$/i;
4760
4760
  const FOR_ITEM_ALIAS_PLACEHOLDER = "__wv_for_item__";
4761
4761
  function isIdentifier(value) {
4762
- return IDENTIFIER_RE$4.test(value);
4762
+ return IDENTIFIER_RE$5.test(value);
4763
4763
  }
4764
4764
  function splitTopLevelByComma(input) {
4765
4765
  const out = [];
@@ -5033,7 +5033,7 @@ function withSlotProps(context, mapping, fn) {
5033
5033
  popSlotProps(context);
5034
5034
  }
5035
5035
  }
5036
- const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
5036
+ const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
5037
5037
  const BIND_SHORTHAND_ARG_RE = /^[A-Z_$][\w$]*(?:-[A-Z_$][\w$]*)*$/i;
5038
5038
  const BACKSLASH_RE$2 = /\\/g;
5039
5039
  const SINGLE_QUOTE_RE$2 = /'/g;
@@ -5054,7 +5054,7 @@ function collectScopePropMapping(context) {
5054
5054
  const mapping = {};
5055
5055
  if (!context.slotMultipleInstance) return mapping;
5056
5056
  for (const scope of context.scopeStack) for (const name of scope) {
5057
- if (!IDENTIFIER_RE$3.test(name)) continue;
5057
+ if (!IDENTIFIER_RE$4.test(name)) continue;
5058
5058
  if (!hasOwn(mapping, name)) mapping[name] = name;
5059
5059
  }
5060
5060
  return mapping;
@@ -5112,8 +5112,10 @@ const SCOPED_SLOT_GLOBALS = new Set([
5112
5112
  "require",
5113
5113
  "arguments",
5114
5114
  WEVU_SLOT_OWNER_KEY,
5115
+ WEVU_GENERIC_SLOT_OWNER_DATA_KEY,
5115
5116
  WEVU_SLOT_PROPS_KEY,
5116
5117
  WEVU_SLOT_PROPS_DATA_KEY,
5118
+ WEVU_GENERIC_SLOT_PROPS_DATA_KEY,
5117
5119
  WEVU_CLASS_STYLE_RUNTIME_MODULE
5118
5120
  ]);
5119
5121
  function collectScopedSlotLocals(context) {
@@ -5143,7 +5145,11 @@ function replaceIdentifierWithExpression(path, replacement) {
5143
5145
  }
5144
5146
  path.replaceWith(replacement);
5145
5147
  }
5146
- const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
5148
+ const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
5149
+ function unwrapTsExpression$2(node) {
5150
+ if (t.isTSAsExpression(node) || t.isTSNonNullExpression(node) || t.isTSTypeAssertion(node) || t.isTSSatisfiesExpression(node)) return unwrapTsExpression$2(node.expression);
5151
+ return node;
5152
+ }
5147
5153
  function rewriteScopedSlotExpression(exp, context) {
5148
5154
  const normalized = normalizeWxmlExpression(exp);
5149
5155
  const parsed = parseBabelExpressionFile(normalized);
@@ -5154,28 +5160,43 @@ function rewriteScopedSlotExpression(exp, context) {
5154
5160
  const forAliases = collectForAliasMapping$2(context);
5155
5161
  const createMemberAccess = (target, prop) => {
5156
5162
  if (!prop) return t.identifier(target);
5157
- if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5163
+ if (IDENTIFIER_RE$3.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5158
5164
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
5159
5165
  };
5160
- traverse(ast, { Identifier(path) {
5161
- if (!path.isReferencedIdentifier()) return;
5162
- const name = path.node.name;
5163
- if (SCOPED_SLOT_GLOBALS.has(name)) return;
5164
- if (path.scope.hasBinding(name)) return;
5165
- if (hasOwn(forAliases, name)) {
5166
- const aliasExp = parseBabelExpression(forAliases[name]);
5167
- if (aliasExp) {
5168
- replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
5166
+ traverse(ast, {
5167
+ TSAsExpression(path) {
5168
+ path.replaceWith(unwrapTsExpression$2(path.node));
5169
+ },
5170
+ TSSatisfiesExpression(path) {
5171
+ path.replaceWith(unwrapTsExpression$2(path.node));
5172
+ },
5173
+ TSTypeAssertion(path) {
5174
+ path.replaceWith(unwrapTsExpression$2(path.node));
5175
+ },
5176
+ TSNonNullExpression(path) {
5177
+ path.replaceWith(unwrapTsExpression$2(path.node));
5178
+ },
5179
+ Identifier(path) {
5180
+ if (!path.isReferencedIdentifier()) return;
5181
+ const name = path.node.name;
5182
+ if (SCOPED_SLOT_GLOBALS.has(name)) return;
5183
+ if (path.scope.hasBinding(name)) return;
5184
+ if (hasOwn(forAliases, name)) {
5185
+ const aliasExp = parseBabelExpression(forAliases[name]);
5186
+ if (aliasExp) {
5187
+ replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
5188
+ return;
5189
+ }
5190
+ }
5191
+ if (locals.has(name)) return;
5192
+ if (hasOwn(slotProps, name)) {
5193
+ const prop = slotProps[name];
5194
+ replaceIdentifierWithExpression(path, createMemberAccess(WEVU_GENERIC_SLOT_PROPS_DATA_KEY, prop));
5169
5195
  return;
5170
5196
  }
5197
+ replaceIdentifierWithExpression(path, createMemberAccess(WEVU_GENERIC_SLOT_PROPS_DATA_KEY, name));
5171
5198
  }
5172
- if (locals.has(name)) return;
5173
- if (hasOwn(slotProps, name)) {
5174
- replaceIdentifierWithExpression(path, createMemberAccess(WEVU_SLOT_PROPS_DATA_KEY, slotProps[name]));
5175
- return;
5176
- }
5177
- replaceIdentifierWithExpression(path, createMemberAccess(WEVU_SLOT_OWNER_KEY, name));
5178
- } });
5199
+ });
5179
5200
  const stmt = ast.program.body[0];
5180
5201
  const updatedExpression = stmt && "expression" in stmt ? stmt.expression : null;
5181
5202
  return updatedExpression ? generateExpression(updatedExpression) : normalized;
@@ -5351,10 +5372,10 @@ const INLINE_GLOBALS = new Set([
5351
5372
  "scope",
5352
5373
  ...getMiniProgramRuntimeGlobalKeys()
5353
5374
  ]);
5354
- const IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
5375
+ const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
5355
5376
  const SIMPLE_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
5356
5377
  function createMemberAccess$1(target, prop) {
5357
- if (IDENTIFIER_RE$1.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5378
+ if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
5358
5379
  return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
5359
5380
  }
5360
5381
  function resolveSlotPropBinding(slotProps, name) {
@@ -5536,9 +5557,22 @@ function createMemberAccess(target, prop) {
5536
5557
  function createThisMemberAccess(prop) {
5537
5558
  return createMemberAccess(t.thisExpression(), prop);
5538
5559
  }
5560
+ function createScopedSlotOwnerRuntimeAccess() {
5561
+ return t.logicalExpression("||", createThisMemberAccess(WEVU_SLOT_OWNER_PROXY_KEY), createThisMemberAccess(WEVU_SLOT_OWNER_KEY));
5562
+ }
5539
5563
  function createUnrefCall(exp) {
5540
5564
  return t.callExpression(t.identifier("__wevuUnref"), [exp]);
5541
5565
  }
5566
+ function isCallCalleeIdentifier(path) {
5567
+ const parent = path.parentPath;
5568
+ if (parent.isCallExpression() && parent.node.callee === path.node) return true;
5569
+ if (parent.isOptionalCallExpression() && parent.node.callee === path.node) return true;
5570
+ if (!parent.isMemberExpression()) return false;
5571
+ const grandParent = parent.parentPath;
5572
+ if (grandParent.isCallExpression() && grandParent.node.callee === parent.node) return true;
5573
+ if (grandParent.isOptionalCallExpression() && grandParent.node.callee === parent.node) return true;
5574
+ return false;
5575
+ }
5542
5576
  function createHasOwnPropertyCall(target, key) {
5543
5577
  return t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier("Object"), t.identifier("prototype")), t.identifier("hasOwnProperty")), t.identifier("call")), [target, t.stringLiteral(key)]);
5544
5578
  }
@@ -5609,7 +5643,10 @@ function normalizeJsExpressionWithContext(exp, context, options) {
5609
5643
  const base = createThisMemberAccess(WEVU_SLOT_PROPS_DATA_KEY);
5610
5644
  replacement = createUnrefCall(prop ? createMemberAccess(base, prop) : base);
5611
5645
  } else if (name === WEVU_SLOT_OWNER_KEY || name === WEVU_SLOT_PROPS_DATA_KEY || name === WEVU_SLOT_PROPS_KEY || name === WEVU_SLOT_SCOPE_KEY) replacement = createUnrefCall(createThisMemberAccess(name));
5612
- else replacement = createUnrefCall(createMemberAccess(createThisMemberAccess(WEVU_SLOT_OWNER_KEY), name));
5646
+ else {
5647
+ const ownerAccess = createMemberAccess(createScopedSlotOwnerRuntimeAccess(), name);
5648
+ replacement = isCallCalleeIdentifier(path) ? ownerAccess : createUnrefCall(ownerAccess);
5649
+ }
5613
5650
  else replacement = createUnrefCall(createIdentifierAccessWithPropsFallback(name));
5614
5651
  const parent = path.parentPath;
5615
5652
  if (parent.isObjectProperty() && parent.node.shorthand && parent.node.key === path.node) {
@@ -5653,17 +5690,26 @@ function shouldFallbackToRuntimeBinding(exp) {
5653
5690
  * 将复杂表达式注册为 JS 运行时计算绑定,返回可用于模板 mustache 的绑定引用。
5654
5691
  */
5655
5692
  function registerRuntimeBindingExpression(exp, context, options) {
5656
- const expAst = normalizeJsExpressionWithContext(exp, context, options);
5693
+ const forIndexAccess = buildForIndexAccess$1(context);
5694
+ const bindingContext = context.rewriteScopedSlot && context.scopedSlotOwnerRuntimeBindingTarget ? context.scopedSlotOwnerRuntimeBindingTarget : context;
5695
+ const cacheKey = context.rewriteScopedSlot && !forIndexAccess ? `${options?.prefix ?? ""}:${exp.trim()}` : void 0;
5696
+ if (cacheKey) {
5697
+ const cached = context.runtimeBindingCache?.get(cacheKey);
5698
+ if (cached) return cached;
5699
+ }
5700
+ const expAst = normalizeJsExpressionWithContext(exp, bindingContext, options);
5657
5701
  if (!expAst) return null;
5658
5702
  const binding = {
5659
- name: `__wv_bind_${context.classStyleBindings.filter((item) => item.type === "bind").length}`,
5703
+ name: `${options?.prefix ?? context.runtimeBindingPrefix ?? "__wv_bind_"}${bindingContext.classStyleBindings.filter((item) => item.type === "bind").length}`,
5660
5704
  type: "bind",
5661
5705
  exp,
5662
5706
  expAst,
5663
- forStack: context.forStack.map((info) => ({ ...info }))
5707
+ forStack: bindingContext.forStack.map((info) => ({ ...info }))
5664
5708
  };
5665
- context.classStyleBindings.push(binding);
5666
- return `${binding.name}${buildForIndexAccess$1(context)}`;
5709
+ bindingContext.classStyleBindings.push(binding);
5710
+ const bindingRef = context.rewriteScopedSlot ? `${WEVU_GENERIC_SLOT_PROPS_DATA_KEY}.${binding.name}${forIndexAccess}` : `${binding.name}${forIndexAccess}`;
5711
+ if (cacheKey) context.runtimeBindingCache?.set(cacheKey, bindingRef);
5712
+ return bindingRef;
5667
5713
  }
5668
5714
  //#endregion
5669
5715
  //#region src/plugins/vue/compiler/template/mustache.ts
@@ -5880,7 +5926,7 @@ function transformBindDirective(node, context, forInfo) {
5880
5926
  }
5881
5927
  //#endregion
5882
5928
  //#region src/plugins/vue/compiler/template/directives/custom.ts
5883
- const IDENTIFIER_RE = /^[a-z_$][\w$]*$/i;
5929
+ const IDENTIFIER_RE$1 = /^[a-z_$][\w$]*$/i;
5884
5930
  function transformCustomDirective(name, exp, arg, context) {
5885
5931
  if (new Set([
5886
5932
  "bind",
@@ -5900,7 +5946,7 @@ function transformCustomDirective(name, exp, arg, context) {
5900
5946
  const dataAttrName = `data-v-${name}`;
5901
5947
  if (exp && exp.type === NodeTypes.SIMPLE_EXPRESSION) {
5902
5948
  const expValue = normalizeWxmlExpressionWithContext(exp.content, context);
5903
- if (IDENTIFIER_RE.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5949
+ if (IDENTIFIER_RE$1.test(expValue)) return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5904
5950
  return `${dataAttrName}="${renderMustache(expValue, context)}"`;
5905
5951
  }
5906
5952
  if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION) return `${dataAttrName}="${arg.content}"`;
@@ -5917,6 +5963,28 @@ function getElementType(element) {
5917
5963
  return "";
5918
5964
  }
5919
5965
  const QUOTE_RE$1 = /"/g;
5966
+ const CAMELIZE_RE = /-([a-z0-9])/gi;
5967
+ const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
5968
+ const NATIVE_MODEL_TAGS = new Set([
5969
+ "input",
5970
+ "textarea",
5971
+ "select",
5972
+ "switch",
5973
+ "checkbox",
5974
+ "slider",
5975
+ "picker"
5976
+ ]);
5977
+ function camelize(value) {
5978
+ return value.replace(CAMELIZE_RE, (_, char) => char.toUpperCase());
5979
+ }
5980
+ function buildModelAssignmentExpression(rawExpValue) {
5981
+ if (IDENTIFIER_RE.test(rawExpValue)) return `ctx.${rawExpValue} = $event`;
5982
+ return `${rawExpValue} = $event`;
5983
+ }
5984
+ function isNativeModelElement(element) {
5985
+ if (!element || element.tag !== element.tag.toLowerCase()) return false;
5986
+ return NATIVE_MODEL_TAGS.has(element.tag);
5987
+ }
5920
5988
  function transformVModel(element, expValue, context) {
5921
5989
  const escapedModel = expValue.replace(QUOTE_RE$1, """);
5922
5990
  const bindModel = (event) => {
@@ -5942,9 +6010,48 @@ function transformVModel(element, expValue, context) {
5942
6010
  return `value="${renderMustache(expValue, context)}" ${bindModel("input")}`;
5943
6011
  }
5944
6012
  }
5945
- function transformModelDirective(node, context, elementNode) {
6013
+ function transformComponentModelDirective(node, context) {
6014
+ const rawExpValue = getBindDirectiveExpression(node).trim();
6015
+ if (!rawExpValue) return null;
6016
+ const rawModelName = node.arg?.type === NodeTypes.SIMPLE_EXPRESSION ? node.arg.content.trim() : "";
6017
+ if (node.arg?.type === NodeTypes.SIMPLE_EXPRESSION && !node.arg.isStatic) {
6018
+ context.warnings.push("暂不支持动态 v-model 参数,已忽略该 v-model。");
6019
+ return null;
6020
+ }
6021
+ const modelProp = rawModelName || "modelValue";
6022
+ if (!modelProp) return null;
6023
+ const updateEvent = `update:${camelize(modelProp)}`;
6024
+ const eventSuffix = normalizeEventDatasetSuffix(updateEvent);
6025
+ const bindAttr = context.platform.eventBindingAttr(updateEvent);
6026
+ const inlineExpression = registerInlineExpression(buildModelAssignmentExpression(rawExpValue), context);
6027
+ if (!inlineExpression) {
6028
+ context.warnings.push(`v-model="${rawExpValue}" 需要是可赋值的成员表达式。`);
6029
+ return null;
6030
+ }
6031
+ const modelAttr = modelProp === "modelValue" ? `modelValue="${renderMustache(normalizeWxmlExpressionWithContext(rawExpValue, context), context)}"` : transformBindDirective(node, context);
6032
+ const updateAttr = [
6033
+ `data-wd-${eventSuffix}="1"`,
6034
+ `data-wi-${eventSuffix}="${inlineExpression.id}"`,
6035
+ `${bindAttr}="${WEVU_INLINE_HANDLER}"`
6036
+ ].filter(Boolean).join(" ");
6037
+ const modifierNames = node.modifiers.map((modifier) => modifier.content.trim()).filter(Boolean);
6038
+ const modifierProperties = modifierNames.map((name) => `${JSON.stringify(name)}:true`).join(",");
6039
+ const modifiersProp = modelProp === "modelValue" ? "modelModifiers" : `${modelProp}Modifiers`;
6040
+ const modifiersRef = modifierNames.length ? registerRuntimeBindingExpression(`{${modifierProperties}}`, context, { hint: "v-model modifiers" }) : null;
6041
+ return [
6042
+ modelAttr,
6043
+ updateAttr,
6044
+ modifiersRef ? `${modifiersProp}="${renderMustache(modifiersRef, context)}"` : null
6045
+ ].filter(Boolean).join(" ");
6046
+ }
6047
+ function transformModelDirective(node, context, elementNode, options) {
5946
6048
  const { exp } = node;
5947
6049
  if (!exp) return null;
6050
+ if (options?.isComponent === true && !isNativeModelElement(elementNode)) return transformComponentModelDirective(node, context);
6051
+ if (node.arg) {
6052
+ context.warnings.push("原生小程序元素不支持 v-model 参数,已忽略该 v-model。");
6053
+ return null;
6054
+ }
5948
6055
  return transformVModel(elementNode, normalizeWxmlExpressionWithContext(exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : "", context), context);
5949
6056
  }
5950
6057
  //#endregion
@@ -6045,7 +6152,7 @@ function transformDirective(node, context, elementNode, forInfo, options) {
6045
6152
  const { name, exp, arg } = node;
6046
6153
  if (name === "bind") return transformBindDirective(node, context, forInfo);
6047
6154
  if (name === "on") return transformOnDirective(node, context, options);
6048
- if (name === "model") return transformModelDirective(node, context, elementNode);
6155
+ if (name === "model") return transformModelDirective(node, context, elementNode, options);
6049
6156
  if (name === "show") return transformShowDirective(node, context);
6050
6157
  if (name === "html") {
6051
6158
  context.warnings.push("小程序不支持 v-html,请使用 rich-text 组件替代。");
@@ -6147,6 +6254,17 @@ function collectElementAttributes(node, context, options) {
6147
6254
  }
6148
6255
  if (prop.name === "text" && prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
6149
6256
  const rawExp = prop.exp.content;
6257
+ if (context.nativeSlotScopeRuntime) {
6258
+ const runtimeExp = registerRuntimeBindingExpression(rawExp, context.nativeSlotScopeRuntime.owner, {
6259
+ hint: "v-text",
6260
+ prefix: context.nativeSlotScopeRuntime.runtimeBindingPrefix
6261
+ });
6262
+ if (runtimeExp) {
6263
+ context.nativeSlotScopeRuntime.bindings.set(runtimeExp, runtimeExp);
6264
+ vTextExp = runtimeExp;
6265
+ continue;
6266
+ }
6267
+ }
6150
6268
  vTextExp = (shouldFallbackToRuntimeBinding(rawExp) ? registerRuntimeBindingExpression(rawExp, context, { hint: "v-text" }) : null) ?? normalizeWxmlExpressionWithContext(rawExp, context);
6151
6269
  continue;
6152
6270
  }
@@ -6246,7 +6364,10 @@ function parseSlotPropsExpression(exp, context) {
6246
6364
  }
6247
6365
  return {};
6248
6366
  }
6249
- function collectSlotBindingExpression(node, context) {
6367
+ function renderObjectBindingKey(key) {
6368
+ return /^[A-Z_$][\w$]*$/i.test(key) ? key : toWxmlStringLiteral$1(key);
6369
+ }
6370
+ function collectSlotBindingExpressions(node, context) {
6250
6371
  let bindObjectExp = null;
6251
6372
  const namedBindings = [];
6252
6373
  for (const prop of node.props) {
@@ -6278,9 +6399,18 @@ function collectSlotBindingExpression(node, context) {
6278
6399
  context.warnings.push("作用域插槽参数使用 v-bind 对象时,将忽略额外的命名绑定。");
6279
6400
  namedBindings.length = 0;
6280
6401
  }
6281
- if (bindObjectExp) return bindObjectExp;
6282
- if (!namedBindings.length) return null;
6283
- return `[${namedBindings.map((entry) => `${toWxmlStringLiteral$1(entry.key)},${entry.value}`).join(",")}]`;
6402
+ if (bindObjectExp) return {
6403
+ data: bindObjectExp,
6404
+ props: bindObjectExp
6405
+ };
6406
+ if (!namedBindings.length) return {
6407
+ data: null,
6408
+ props: null
6409
+ };
6410
+ return {
6411
+ data: `{${namedBindings.map((entry) => `${renderObjectBindingKey(entry.key)}:${entry.value}`).join(",")}}`,
6412
+ props: `[${namedBindings.map((entry) => `${toWxmlStringLiteral$1(entry.key)},${entry.value}`).join(",")}]`
6413
+ };
6284
6414
  }
6285
6415
  //#endregion
6286
6416
  //#region src/plugins/vue/compiler/template/elements/tag-slot.ts
@@ -6338,6 +6468,12 @@ function resolveSlotStaticName(info) {
6338
6468
  if (info.type === "static") return info.value || "default";
6339
6469
  }
6340
6470
  const SLOT_PRESENCE_IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
6471
+ const SLOT_OWNER_KEY_RE = /\bwvslotowner(?:\.([A-Z_$][\w$]*)|\[['"]([^'"]+)['"]\])/gi;
6472
+ const SLOT_OWNER_PROP_PREFIX_RE = /\bwvslotownerprop([A-Z_$][\w$]*)\b/gi;
6473
+ const SLOT_PROPS_DATA_KEY_RE = /\bwvslotpropsdata(?:\.([A-Z_$][\w$]*)|\[['"]([^'"]+)['"]\])/gi;
6474
+ function renderOwnerPropSourceExpression(key) {
6475
+ return SLOT_PRESENCE_IDENTIFIER_RE.test(key) ? key : `${WEVU_SLOT_OWNER_ID_KEY}['${key.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}']`;
6476
+ }
6341
6477
  function createSlotPresenceExpression(info) {
6342
6478
  const slotName = resolveSlotStaticName(info);
6343
6479
  if (!slotName) return;
@@ -6352,6 +6488,66 @@ function buildSlotDeclaration(name, propsExp, children, context, options) {
6352
6488
  condition: options?.condition
6353
6489
  };
6354
6490
  }
6491
+ function collectOwnerMemberKey(node, ownerKeys, slotPropKeys) {
6492
+ const object = node.object;
6493
+ if (object.type !== "Identifier" || object.name !== "wvslotowner" && object.name !== "wvslotpropsdata") return;
6494
+ const property = node.property;
6495
+ if (!node.computed && property.type === "Identifier") {
6496
+ if (object.name === "wvslotpropsdata" && slotPropKeys.has(property.name)) return;
6497
+ ownerKeys.add(property.name);
6498
+ } else if (node.computed && property.type === "StringLiteral") {
6499
+ if (object.name === "wvslotpropsdata" && slotPropKeys.has(property.value)) return;
6500
+ ownerKeys.add(property.value);
6501
+ }
6502
+ }
6503
+ function collectScopedSlotOwnerKeys(template, slotPropKeys) {
6504
+ const ownerKeys = /* @__PURE__ */ new Set();
6505
+ let match = SLOT_OWNER_KEY_RE.exec(template);
6506
+ while (match) {
6507
+ const key = match[1] ?? match[2];
6508
+ if (key) ownerKeys.add(key);
6509
+ match = SLOT_OWNER_KEY_RE.exec(template);
6510
+ }
6511
+ SLOT_OWNER_KEY_RE.lastIndex = 0;
6512
+ match = SLOT_OWNER_PROP_PREFIX_RE.exec(template);
6513
+ while (match) {
6514
+ const key = match[1];
6515
+ if (key) ownerKeys.add(key);
6516
+ match = SLOT_OWNER_PROP_PREFIX_RE.exec(template);
6517
+ }
6518
+ SLOT_OWNER_PROP_PREFIX_RE.lastIndex = 0;
6519
+ const computedExpressions = template.match(/\{\{([\s\S]*?)\}\}/g) ?? [];
6520
+ for (const raw of computedExpressions) {
6521
+ const parsed = parseBabelExpressionFile(raw.slice(2, -2).trim());
6522
+ if (!parsed) continue;
6523
+ traverse(parsed.ast, {
6524
+ MemberExpression(path) {
6525
+ collectOwnerMemberKey(path.node, ownerKeys, slotPropKeys);
6526
+ },
6527
+ OptionalMemberExpression(path) {
6528
+ collectOwnerMemberKey(path.node, ownerKeys, slotPropKeys);
6529
+ }
6530
+ });
6531
+ }
6532
+ return ownerKeys.size ? [...ownerKeys].sort((a, b) => a.localeCompare(b)) : void 0;
6533
+ }
6534
+ function collectScopedSlotPropsDataKeys(template) {
6535
+ const keys = /* @__PURE__ */ new Set();
6536
+ let match = SLOT_PROPS_DATA_KEY_RE.exec(template);
6537
+ while (match) {
6538
+ const key = match[1] ?? match[2];
6539
+ if (key) keys.add(key);
6540
+ match = SLOT_PROPS_DATA_KEY_RE.exec(template);
6541
+ }
6542
+ SLOT_PROPS_DATA_KEY_RE.lastIndex = 0;
6543
+ return [...keys].sort((a, b) => a.localeCompare(b));
6544
+ }
6545
+ function renderScopedSlotPropsDataReadyGuard(keys) {
6546
+ if (!keys.length) return;
6547
+ return keys.map((key) => {
6548
+ return `${SLOT_PRESENCE_IDENTIFIER_RE.test(key) ? `${WEVU_GENERIC_SLOT_PROPS_DATA_KEY}.${key}` : `${WEVU_GENERIC_SLOT_PROPS_DATA_KEY}[${toWxmlStringLiteral$1(key)}]`}!==undefined`;
6549
+ }).join("&&");
6550
+ }
6355
6551
  function createScopedSlotComponent(context, slotKey, props, children, transformNode) {
6356
6552
  const ownerHash = hashString(context.filename);
6357
6553
  const index = context.scopedSlotComponents.length;
@@ -6372,27 +6568,36 @@ function createScopedSlotComponent(context, slotKey, props, children, transformN
6372
6568
  slotPropStack: [],
6373
6569
  rewriteScopedSlot: true,
6374
6570
  classStyleBindings: [],
6571
+ runtimeBindingCache: /* @__PURE__ */ new Map(),
6572
+ runtimeBindingPrefix: "wvslotbind",
6375
6573
  classStyleWxs: false,
6376
6574
  forStack: [],
6377
6575
  forIndexSeed: 0,
6378
6576
  inlineExpressions: [],
6379
- inlineExpressionSeed: 0
6577
+ inlineExpressionSeed: 0,
6578
+ scopedSlotOwnerRuntimeBindingTarget: context
6380
6579
  };
6381
- let template = withSlotProps(scopedContext, {
6580
+ const slotMapping = {
6382
6581
  ...collectScopePropMapping(context),
6383
6582
  ...props
6384
- }, () => {
6583
+ };
6584
+ let template = withSlotProps(scopedContext, slotMapping, () => {
6385
6585
  return children.map((child) => transformNode(child, scopedContext)).join("");
6386
6586
  });
6587
+ const slotPropsDataReadyGuard = renderScopedSlotPropsDataReadyGuard(collectScopedSlotPropsDataKeys(template));
6588
+ if (slotPropsDataReadyGuard) template = scopedContext.platform.wrapIf(slotPropsDataReadyGuard, template, (exp) => renderMustache(exp, scopedContext));
6387
6589
  if (scopedContext.classStyleWxs) template = `${buildClassStyleWxsTag(scopedContext.classStyleWxsExtension || "wxs", scopedContext.classStyleWxsSrc)}\n${template}`;
6388
6590
  asset.template = template;
6389
6591
  asset.componentGenerics = Object.keys(scopedContext.componentGenerics).length ? scopedContext.componentGenerics : void 0;
6390
6592
  asset.classStyleBindings = scopedContext.classStyleBindings.length ? scopedContext.classStyleBindings : void 0;
6391
6593
  asset.classStyleWxs = scopedContext.classStyleWxs || void 0;
6392
6594
  asset.inlineExpressions = scopedContext.inlineExpressions.length ? scopedContext.inlineExpressions : void 0;
6595
+ asset.ownerKeys = collectScopedSlotOwnerKeys(template, new Set(Object.values(slotMapping)));
6596
+ if (asset.ownerKeys?.length) asset.ownerPropsExpression = `[${asset.ownerKeys.map((key) => `'${key}',${renderOwnerPropSourceExpression(key)}`).join(",")}]`;
6393
6597
  return {
6394
6598
  componentName,
6395
- slotKey
6599
+ slotKey,
6600
+ asset
6396
6601
  };
6397
6602
  }
6398
6603
  function injectAttributeIntoOpeningTag(source, attr) {
@@ -6406,29 +6611,79 @@ function injectAttributeIntoOpeningTag(source, attr) {
6406
6611
  if (tagNameEnd <= 1) return null;
6407
6612
  return `${source.slice(0, tagNameEnd)} ${attr}${source.slice(tagNameEnd)}`;
6408
6613
  }
6614
+ function createSlotAttributeNode(sourceNode, attr) {
6615
+ const match = /^slot="([\s\S]*)"$/.exec(attr);
6616
+ if (!match) return null;
6617
+ return {
6618
+ type: NodeTypes.ATTRIBUTE,
6619
+ name: "slot",
6620
+ nameLoc: sourceNode.loc,
6621
+ value: {
6622
+ type: NodeTypes.TEXT,
6623
+ content: match[1],
6624
+ loc: sourceNode.loc
6625
+ },
6626
+ loc: sourceNode.loc
6627
+ };
6628
+ }
6629
+ function injectSlotAttributeIntoStructuralElementNode(child, slotAttr, transformNode, context) {
6630
+ if (child.type !== NodeTypes.ELEMENT || child.tag === "template") return null;
6631
+ const sourceNode = child;
6632
+ const structural = isStructuralDirective(sourceNode);
6633
+ if (structural.type !== "if" || structural.directive?.name !== "if" || !structural.directive.exp) return null;
6634
+ const slotAttribute = createSlotAttributeNode(sourceNode, slotAttr);
6635
+ if (!slotAttribute) return null;
6636
+ const elementWithoutIf = {
6637
+ ...sourceNode,
6638
+ props: [slotAttribute, ...sourceNode.props.filter((prop) => prop !== structural.directive)]
6639
+ };
6640
+ const expValue = normalizeWxmlExpressionWithContext(structural.directive.exp.type === NodeTypes.SIMPLE_EXPRESSION ? structural.directive.exp.content : "", context);
6641
+ const tag = sourceNode.tag;
6642
+ const { attrs, vTextExp } = collectElementAttributes(elementWithoutIf, context, { skipSlotDirective: true });
6643
+ let children = "";
6644
+ if (sourceNode.children.length > 0) children = sourceNode.children.map((childNode) => transformNode(childNode, context)).join("");
6645
+ if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6646
+ const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6647
+ return (children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`).replace(/^<([^\s>/]+)/, `<$1 ${context.platform.directives.ifAttr}="${renderMustache(expValue, context)}"`);
6648
+ }
6649
+ function isRenderableFallbackChild(child) {
6650
+ if (child.type === NodeTypes.COMMENT) return false;
6651
+ if (child.type === NodeTypes.TEXT) return child.content.trim().length > 0;
6652
+ return true;
6653
+ }
6409
6654
  function renderSlotFallback(decl, context, transformNode) {
6410
- const rawRenderedChildren = decl.children.map((child) => ({ code: transformNode(child, context) }));
6411
- const rawContent = rawRenderedChildren.map((item) => item.code).join("");
6412
- if (!rawContent) return "";
6413
6655
  const slotAttr = renderSlotNameAttribute(decl.name, context, "slot");
6414
6656
  const wrapCondition = (content) => {
6415
6657
  return decl.condition ? context.platform.wrapIf(decl.condition, content, (exp) => renderMustache(exp, context)) : content;
6416
6658
  };
6417
- if (!slotAttr) return wrapCondition(rawContent);
6418
- if (!context.slotSingleRootNoWrapper) return wrapCondition(`<view ${slotAttr}>${rawContent}</view>`);
6419
- const renderedChildren = rawRenderedChildren.filter((item) => item.code.trim().length > 0);
6420
- if (!renderedChildren.length) return "";
6421
- const content = renderedChildren.map((item) => item.code).join("");
6422
- if (renderedChildren.length === 1) {
6423
- const projected = injectAttributeIntoOpeningTag(renderedChildren[0].code, slotAttr);
6659
+ if (!slotAttr) {
6660
+ const rawContent = decl.children.map((child) => transformNode(child, context)).join("");
6661
+ if (!rawContent) return "";
6662
+ return wrapCondition(rawContent);
6663
+ }
6664
+ const renderableChildren = decl.children.filter(isRenderableFallbackChild);
6665
+ if (!renderableChildren.length) return "";
6666
+ if (!context.slotSingleRootNoWrapper) {
6667
+ const rawContent = decl.children.map((child) => transformNode(child, context)).join("");
6668
+ if (!rawContent) return "";
6669
+ return wrapCondition(`<view ${slotAttr}>${rawContent}</view>`);
6670
+ }
6671
+ if (renderableChildren.length === 1) {
6672
+ const child = renderableChildren[0];
6673
+ if (child.type === NodeTypes.ELEMENT && isStructuralDirective(child).type) {
6674
+ const projected = injectSlotAttributeIntoStructuralElementNode(child, slotAttr, transformNode, context);
6675
+ if (projected) return wrapCondition(projected);
6676
+ }
6677
+ const projected = injectAttributeIntoOpeningTag(transformNode(child, context), slotAttr);
6424
6678
  if (projected) return wrapCondition(projected);
6425
6679
  }
6426
- return wrapCondition(`<view ${slotAttr}>${content}</view>`);
6680
+ return wrapCondition(`<view ${slotAttr}>${renderableChildren.map((child) => transformNode(child, context)).join("")}</view>`);
6427
6681
  }
6428
6682
  function transformSlotElement(node, context, transformNode) {
6429
6683
  if (isScopedSlotsDisabled(context)) return transformSlotElementPlain(node, context, transformNode);
6430
6684
  const slotNameInfo = resolveSlotNameFromSlotElement(node);
6431
- let slotPropsExp = collectSlotBindingExpression(node, context);
6685
+ const slotBindingExps = collectSlotBindingExpressions(node, context);
6686
+ const slotPropsExp = slotBindingExps.props;
6432
6687
  let fallbackContent = "";
6433
6688
  if (node.children.length > 0) fallbackContent = node.children.map((child) => transformNode(child, context)).join("");
6434
6689
  const slotAttrs = [];
@@ -6437,22 +6692,28 @@ function transformSlotElement(node, context, transformNode) {
6437
6692
  const slotAttrString = slotAttrs.length ? ` ${slotAttrs.join(" ")}` : "";
6438
6693
  let slotTag = `<slot${slotAttrString} />`;
6439
6694
  const slotPresentExp = fallbackContent ? createSlotPresenceExpression(slotNameInfo) : void 0;
6440
- if (fallbackContent) {
6441
- if (!slotPropsExp && slotPresentExp) slotTag = `${context.platform.wrapIf(slotPresentExp, slotTag, (exp) => renderMustache(exp, context))}${context.platform.wrapElse(fallbackContent)}`;
6442
- else if (!slotPropsExp) slotTag = `<slot${slotAttrString}>${fallbackContent}</slot>`;
6695
+ if (fallbackContent && !slotPropsExp && !slotPresentExp) slotTag = `<slot${slotAttrString}>${fallbackContent}</slot>`;
6696
+ if (!slotPropsExp && context.scopedSlotsRequireProps) {
6697
+ if (fallbackContent && slotPresentExp) return `${context.platform.wrapIf(slotPresentExp, slotTag, (exp) => renderMustache(exp, context))}${context.platform.wrapElse(fallbackContent)}`;
6698
+ return slotTag;
6443
6699
  }
6444
- if (!slotPropsExp && (context.scopedSlotsRequireProps || slotNameInfo.type !== "default")) return slotTag;
6445
6700
  const genericKey = `scoped-slots-${resolveSlotKey(context, slotNameInfo)}`;
6446
6701
  context.componentGenerics[genericKey] = true;
6447
- slotPropsExp = slotPropsExp ?? "[]";
6702
+ const slotPropsFallbackExp = slotPropsExp ?? WEVU_GENERIC_SLOT_OWNER_PROPS_ATTR;
6703
+ const slotPropsDataExp = slotPropsExp && slotBindingExps.data ? registerRuntimeBindingExpression(slotBindingExps.data, context, {
6704
+ hint: "scoped slot props data",
6705
+ prefix: `${WEVU_GENERIC_SLOT_PROPS_DATA_ATTR}_`
6706
+ }) ?? slotPropsFallbackExp : WEVU_GENERIC_SLOT_PROPS_DATA_KEY;
6448
6707
  const scopedAttrs = [
6449
- `${context.platform.directives.ifAttr}="${renderMustache(WEVU_SLOT_OWNER_ID_PROP, context)}"`,
6450
- `${WEVU_SLOT_OWNER_ATTR}="${renderMustache(WEVU_SLOT_OWNER_ID_PROP, context)}"`,
6451
- `${WEVU_SLOT_PROPS_ATTR}="${renderMustache(slotPropsExp, context)}"`
6708
+ `${WEVU_GENERIC_SLOT_OWNER_ID_ATTR}="${renderMustache(WEVU_GENERIC_SLOT_OWNER_ID_ATTR, context)}"`,
6709
+ `${WEVU_GENERIC_SLOT_PROPS_ATTR}="${renderMustache(slotPropsFallbackExp, context)}"`,
6710
+ `${WEVU_GENERIC_SLOT_PROPS_DATA_ATTR}="${renderMustache(slotPropsDataExp, context)}"`
6452
6711
  ];
6453
- if (context.slotMultipleInstance) scopedAttrs.push(`${WEVU_SLOT_SCOPE_ATTR}="${renderMustache(WEVU_SLOT_SCOPE_KEY, context)}"`);
6454
- const scopedTag = `<${genericKey}${scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : ""} />`;
6455
- const projectedContent = `${slotTag}${scopedTag}`;
6712
+ if (context.slotMultipleInstance) scopedAttrs.push(`${WEVU_GENERIC_SLOT_SCOPE_ATTR}="${renderMustache(WEVU_SLOT_SCOPE_KEY, context)}"`);
6713
+ scopedAttrs.push(`${WEVU_GENERIC_SLOT_OWNER_PROPS_ATTR}="${renderMustache(WEVU_GENERIC_SLOT_OWNER_PROPS_ATTR, context)}"`);
6714
+ const scopedAttrString = scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : "";
6715
+ const scopedTag = context.platform.wrapIf(WEVU_GENERIC_SLOT_OWNER_ID_ATTR, `<${genericKey}${scopedAttrString} />`, (exp) => renderMustache(exp, context));
6716
+ const projectedContent = slotPropsExp ? scopedTag : `${slotTag}${scopedTag}`;
6456
6717
  if (fallbackContent && slotPresentExp) return `${context.platform.wrapIf(slotPresentExp, projectedContent, (exp) => renderMustache(exp, context))}${context.platform.wrapElse(fallbackContent)}`;
6457
6718
  return projectedContent;
6458
6719
  }
@@ -6471,6 +6732,18 @@ function transformSlotElementPlain(node, context, transformNode) {
6471
6732
  }
6472
6733
  //#endregion
6473
6734
  //#region src/plugins/vue/compiler/template/elements/tag-component.ts
6735
+ function createNativeSlotContext(context) {
6736
+ return {
6737
+ ...context,
6738
+ classStyleBindings: context.classStyleBindings,
6739
+ runtimeBindingCache: context.runtimeBindingCache,
6740
+ nativeSlotScopeRuntime: {
6741
+ owner: context,
6742
+ bindings: /* @__PURE__ */ new Map(),
6743
+ runtimeBindingPrefix: "wvslotbind"
6744
+ }
6745
+ };
6746
+ }
6474
6747
  function hasLegacySlotAttribute(children) {
6475
6748
  return children.some((child) => {
6476
6749
  if (child.type !== NodeTypes.ELEMENT) return false;
@@ -6491,10 +6764,52 @@ function hasDirectComponentSlotChild(children, context) {
6491
6764
  return /^[A-Z]/.test(child.tag);
6492
6765
  });
6493
6766
  }
6494
- function shouldAugmentPlainDefaultSlot(decl, context) {
6495
- if (context.scopedSlotsRequireProps || !decl.implicitDefault) return false;
6496
- if (context.scopedSlotsCompiler === "augmented") return true;
6497
- return hasDirectComponentSlotChild(decl.children, context);
6767
+ function hasComponentSlotDescendant(children, context) {
6768
+ return children.some((child) => {
6769
+ if (child.type !== NodeTypes.ELEMENT) return false;
6770
+ if (child.tag === "template") return false;
6771
+ if (child.tag === "component") return true;
6772
+ return !isBuiltinTag(resolveTemplateTagName(child.tag, context)) || /^[A-Z]/.test(child.tag) || hasComponentSlotDescendant(child.children, context);
6773
+ });
6774
+ }
6775
+ function hasStructuralSlotRoot(children) {
6776
+ return children.some((child) => {
6777
+ if (child.type !== NodeTypes.ELEMENT) return false;
6778
+ return Boolean(isStructuralDirective(child).type);
6779
+ });
6780
+ }
6781
+ function hasParentExpressionSlotContent(children) {
6782
+ return children.some((child) => {
6783
+ if (child.type === NodeTypes.INTERPOLATION) return true;
6784
+ if (child.type !== NodeTypes.ELEMENT) return false;
6785
+ const element = child;
6786
+ if (element.props.some((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name !== "slot")) return true;
6787
+ return hasParentExpressionSlotContent(element.children);
6788
+ });
6789
+ }
6790
+ function hasRuntimeOnlySlotExpression(children) {
6791
+ return children.some((child) => {
6792
+ if (child.type === NodeTypes.INTERPOLATION) {
6793
+ const content = child.content;
6794
+ return shouldFallbackToRuntimeBinding(content?.type === NodeTypes.SIMPLE_EXPRESSION ? content.content : "");
6795
+ }
6796
+ if (child.type !== NodeTypes.ELEMENT) return false;
6797
+ const element = child;
6798
+ if (element.props.some((prop) => {
6799
+ if (prop.type !== NodeTypes.DIRECTIVE || prop.name === "slot") return false;
6800
+ return shouldFallbackToRuntimeBinding(prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION ? prop.exp.content : "");
6801
+ })) return true;
6802
+ return hasRuntimeOnlySlotExpression(element.children);
6803
+ });
6804
+ }
6805
+ function shouldAugmentPlainSlot(decl, context) {
6806
+ if (context.scopedSlotsRequireProps) return false;
6807
+ if (hasParentExpressionSlotContent(decl.children)) return hasComponentSlotDescendant(decl.children, context) || context.scopedSlotsCompiler === "augmented" && (hasStructuralSlotRoot(decl.children) || hasRuntimeOnlySlotExpression(decl.children));
6808
+ if (context.scopedSlotsCompiler === "augmented" && !decl.implicitDefault && (!context.slotSingleRootNoWrapper || hasStructuralSlotRoot(decl.children))) return true;
6809
+ if (context.scopedSlotsCompiler === "augmented" && decl.implicitDefault && hasComponentSlotDescendant(decl.children, context)) return true;
6810
+ if (hasDirectComponentSlotChild(decl.children, context)) return true;
6811
+ if (!decl.implicitDefault) return false;
6812
+ return context.scopedSlotsCompiler === "augmented" && (hasStructuralSlotRoot(decl.children) || hasRuntimeOnlySlotExpression(decl.children));
6498
6813
  }
6499
6814
  function resolveTemplateSlotCondition(node, context) {
6500
6815
  const ifDirective = node.props.find((prop) => prop.type === NodeTypes.DIRECTIVE && prop.name === "if" && prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION);
@@ -6535,8 +6850,19 @@ function shouldExposePlainSlotPresence(node) {
6535
6850
  function isWevuComponentTag(node, context) {
6536
6851
  return context.wevuComponentTags ? context.wevuComponentTags.has(node.tag) : /^[A-Z]/.test(node.tag);
6537
6852
  }
6853
+ function buildScopedSlotOwnerIdExpression(context) {
6854
+ return context.rewriteScopedSlot ? `${WEVU_GENERIC_SLOT_OWNER_ID_ATTR} || ${WEVU_SLOT_OWNER_ID_KEY} || ''` : `${WEVU_SLOT_OWNER_ID_KEY} || ''`;
6855
+ }
6856
+ function shouldTransformAsComponentWithSlots(node, context, resolvedTag = resolveTemplateTagName(node.tag, context)) {
6857
+ const slotDirective = findSlotDirective(node);
6858
+ const templateSlotChildren = node.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6859
+ const shouldUseAugmentedDefaultSlot = node.children.length > 0 && !context.scopedSlotsRequireProps && !isBuiltinTag(resolvedTag);
6860
+ const shouldUseSlotPresenceMetadata = node.children.length > 0 && isWevuComponentTag(node, context);
6861
+ return slotDirective || templateSlotChildren.length > 0 || shouldUseAugmentedDefaultSlot || shouldUseSlotPresenceMetadata;
6862
+ }
6538
6863
  function transformComponentWithSlots(node, context, transformNode, options) {
6539
6864
  if (isScopedSlotsDisabled(context)) return transformComponentWithSlotsFallback(node, context, transformNode, options);
6865
+ if (node.tag !== "component" && context.wevuComponentTags && !isWevuComponentTag(node, context)) return transformComponentWithSlotsFallback(node, context, transformNode, options);
6540
6866
  const extraAttrs = options?.extraAttrs ?? [];
6541
6867
  const slotDeclarations = [];
6542
6868
  const slotDirective = findSlotDirective(node);
@@ -6569,24 +6895,32 @@ function transformComponentWithSlots(node, context, transformNode, options) {
6569
6895
  let children = node.children.map((child) => transformNode(child, context)).join("");
6570
6896
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6571
6897
  if (children && defaultSlotChildren.length && !hasLegacySlotAttribute(defaultSlotChildren) && isWevuComponentTag(node, context)) pushSlotNamesAttr(attrs, [{ name: "'default'" }], context);
6572
- const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6898
+ const mergedAttrs = [...extraAttrs, ...attrs];
6899
+ const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6573
6900
  const { tag } = node;
6574
6901
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6575
6902
  }
6576
6903
  const scopedSlotDeclarations = [];
6577
6904
  const plainSlotDeclarations = [];
6578
- for (const decl of slotDeclarations) if (Object.keys(decl.props).length > 0 || shouldAugmentPlainDefaultSlot(decl, context)) scopedSlotDeclarations.push(decl);
6905
+ for (const decl of slotDeclarations) if (Object.keys(decl.props).length > 0 || shouldAugmentPlainSlot(decl, context)) scopedSlotDeclarations.push(decl);
6579
6906
  else plainSlotDeclarations.push(decl);
6580
6907
  const slotNames = [];
6581
6908
  const slotGenericAttrs = [];
6582
6909
  for (const decl of scopedSlotDeclarations) {
6583
6910
  const slotKey = resolveSlotKey(context, decl.name);
6584
- const { componentName } = createScopedSlotComponent(context, slotKey, decl.props, decl.children, transformNode);
6911
+ const { componentName, asset } = createScopedSlotComponent(context, slotKey, decl.props, decl.children, transformNode);
6585
6912
  slotNames.push({
6586
6913
  name: stringifySlotName(decl.name, context),
6587
6914
  condition: decl.condition
6588
6915
  });
6589
6916
  slotGenericAttrs.push(`generic:scoped-slots-${slotKey}="${componentName}"`);
6917
+ if (asset.ownerPropsExpression) {
6918
+ const ownerPropsRef = registerRuntimeBindingExpression(asset.ownerPropsExpression, context, {
6919
+ hint: "scoped slot owner props",
6920
+ prefix: "wvslotownerprops"
6921
+ });
6922
+ slotGenericAttrs.push(`${WEVU_GENERIC_SLOT_OWNER_PROPS_ATTR}="${renderMustache(ownerPropsRef ?? asset.ownerPropsExpression, context)}"`);
6923
+ }
6590
6924
  }
6591
6925
  if (shouldExposePlainSlotPresence(node) || isWevuComponentTag(node, context)) for (const decl of plainSlotDeclarations) slotNames.push({
6592
6926
  name: stringifySlotName(decl.name, context),
@@ -6605,12 +6939,22 @@ function transformComponentWithSlots(node, context, transformNode, options) {
6605
6939
  pushSlotNamesAttr(mergedAttrs, slotNames, context);
6606
6940
  if (scopedSlotDeclarations.length) {
6607
6941
  const scopePropsExp = buildScopePropsExpression(context);
6608
- if (scopePropsExp) mergedAttrs.push(`${WEVU_SLOT_SCOPE_ATTR}="${renderMustache(scopePropsExp, context)}"`);
6609
- mergedAttrs.push(`${WEVU_SLOT_OWNER_ID_ATTR}="${renderMustache(`${WEVU_SLOT_OWNER_ID_KEY} || ''`, context)}"`);
6942
+ if (scopePropsExp) mergedAttrs.push(`${WEVU_GENERIC_SLOT_SCOPE_ATTR}="${renderMustache(scopePropsExp, context)}"`);
6943
+ const ownerIdExp = renderMustache(buildScopedSlotOwnerIdExpression(context), context);
6944
+ mergedAttrs.push(`${WEVU_GENERIC_SLOT_OWNER_ID_ATTR}="${ownerIdExp}"`);
6610
6945
  }
6611
- const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6612
6946
  const { tag } = node;
6613
- const plainSlotContent = plainSlotDeclarations.map((decl) => renderSlotFallback(decl, context, transformNode)).join("");
6947
+ const nativeSlotContext = plainSlotDeclarations.length ? createNativeSlotContext(context) : context;
6948
+ const plainSlotContent = plainSlotDeclarations.map((decl) => renderSlotFallback(decl, nativeSlotContext, transformNode)).join("");
6949
+ const nativeSlotBindings = nativeSlotContext.nativeSlotScopeRuntime?.bindings;
6950
+ if (nativeSlotBindings?.size) {
6951
+ const bindingEntries = Array.from(nativeSlotBindings);
6952
+ const scopeExp = `[${bindingEntries.map(([key, value]) => `'${key}',${value}`).join(",")}]`;
6953
+ mergedAttrs.push(`${WEVU_GENERIC_SLOT_SCOPE_ATTR}="${renderMustache(scopeExp, context)}"`);
6954
+ const readyExp = bindingEntries.map(([key]) => `${key}!==undefined`).join("&&");
6955
+ if (readyExp) mergedAttrs.push(`${context.platform.directives.ifAttr}="${renderMustache(readyExp, context)}"`);
6956
+ }
6957
+ const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6614
6958
  return plainSlotContent ? `<${tag}${attrString}>${plainSlotContent}</${tag}>` : `<${tag}${attrString} />`;
6615
6959
  }
6616
6960
  function transformComponentWithSlotsFallback(node, context, transformNode, options) {
@@ -6645,7 +6989,8 @@ function transformComponentWithSlotsFallback(node, context, transformNode, optio
6645
6989
  let children = node.children.map((child) => transformNode(child, context)).join("");
6646
6990
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6647
6991
  if (children && defaultSlotChildren.length && !hasLegacySlotAttribute(defaultSlotChildren) && isWevuComponentTag(node, context)) pushSlotNamesAttr(attrs, [{ name: "'default'" }], context);
6648
- const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6992
+ const mergedAttrs = [...extraAttrs, ...attrs];
6993
+ const attrString = mergedAttrs.length ? ` ${mergedAttrs.join(" ")}` : "";
6649
6994
  const { tag } = node;
6650
6995
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6651
6996
  }
@@ -6707,11 +7052,7 @@ function transformComponentElement(node, context, transformNode) {
6707
7052
  //#region src/plugins/vue/compiler/template/elements/tag-normal.ts
6708
7053
  function transformNormalElement(node, context, transformNode) {
6709
7054
  const tag = resolveTemplateTagName(node.tag, context);
6710
- const slotDirective = findSlotDirective(node);
6711
- const templateSlotChildren = node.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6712
- const shouldUseAugmentedDefaultSlot = node.children.length > 0 && !context.scopedSlotsRequireProps && !isBuiltinTag(tag);
6713
- const shouldUseSlotPresenceMetadata = node.children.length > 0 && (context.wevuComponentTags ? context.wevuComponentTags.has(node.tag) : /^[A-Z]/.test(node.tag));
6714
- if (slotDirective || templateSlotChildren.length > 0 || shouldUseAugmentedDefaultSlot || shouldUseSlotPresenceMetadata) return transformComponentWithSlots(node, context, transformNode);
7055
+ if (shouldTransformAsComponentWithSlots(node, context, tag)) return transformComponentWithSlots(node, context, transformNode);
6715
7056
  const { attrs, vTextExp } = collectElementAttributes(node, context, { resolvedTag: tag });
6716
7057
  let children = "";
6717
7058
  if (node.children.length > 0) children = node.children.map((child) => transformNode(child, context)).join("");
@@ -6723,6 +7064,16 @@ function transformNormalElement(node, context, transformNode) {
6723
7064
  //#region src/plugins/vue/compiler/template/elements/tag-structural.ts
6724
7065
  const REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
6725
7066
  function resolveConditionExpression$1(rawExpValue, context, hint) {
7067
+ if (context.nativeSlotScopeRuntime) {
7068
+ const runtimeExp = registerRuntimeBindingExpression(rawExpValue, context.nativeSlotScopeRuntime.owner, {
7069
+ hint,
7070
+ prefix: context.nativeSlotScopeRuntime.runtimeBindingPrefix
7071
+ });
7072
+ if (runtimeExp) {
7073
+ context.nativeSlotScopeRuntime.bindings.set(runtimeExp, runtimeExp);
7074
+ return runtimeExp;
7075
+ }
7076
+ }
6726
7077
  return (shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
6727
7078
  }
6728
7079
  function transformIfElement(node, context, transformNode) {
@@ -6789,21 +7140,20 @@ function transformForElement(node, context, transformNode) {
6789
7140
  props: otherProps
6790
7141
  };
6791
7142
  const extraAttrs = listExp ? context.platform.forAttrs(listExp, renderTemplateMustache, forInfo.item, forInfo.index) : [];
6792
- const slotDirective = findSlotDirective(elementWithoutFor);
6793
- const templateSlotChildren = elementWithoutFor.children.filter((child) => child.type === NodeTypes.ELEMENT && child.tag === "template" && findSlotDirective(child));
6794
- if (slotDirective || templateSlotChildren.length > 0) return transformComponentWithSlots(elementWithoutFor, context, transformNode, {
7143
+ const resolvedTag = resolveTemplateTagName(elementWithoutFor.tag, context);
7144
+ if (shouldTransformAsComponentWithSlots(elementWithoutFor, context, resolvedTag)) return transformComponentWithSlots(elementWithoutFor, context, transformNode, {
6795
7145
  extraAttrs,
6796
7146
  forInfo
6797
7147
  });
6798
7148
  const { attrs, vTextExp } = collectElementAttributes(elementWithoutFor, context, {
6799
7149
  forInfo,
6800
7150
  extraAttrs,
6801
- resolvedTag: resolveTemplateTagName(elementWithoutFor.tag, context)
7151
+ resolvedTag
6802
7152
  });
6803
7153
  let children = "";
6804
7154
  if (elementWithoutFor.children.length > 0) children = elementWithoutFor.children.map((child) => transformNode(child, context)).join("");
6805
7155
  if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
6806
- const tag = resolveTemplateTagName(elementWithoutFor.tag, context);
7156
+ const tag = resolvedTag;
6807
7157
  const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
6808
7158
  return children ? `<${tag}${attrString}>${children}</${tag}>` : `<${tag}${attrString} />`;
6809
7159
  }));
@@ -6913,6 +7263,16 @@ function transformInterpolation(node, context) {
6913
7263
  const { content } = node;
6914
7264
  if (content.type === NodeTypes.SIMPLE_EXPRESSION) {
6915
7265
  const rawExpValue = content.content;
7266
+ if (context.nativeSlotScopeRuntime) {
7267
+ const runtimeExp = registerRuntimeBindingExpression(rawExpValue, context.nativeSlotScopeRuntime.owner, {
7268
+ hint: "插值表达式",
7269
+ prefix: context.nativeSlotScopeRuntime.runtimeBindingPrefix
7270
+ });
7271
+ if (runtimeExp) {
7272
+ context.nativeSlotScopeRuntime.bindings.set(runtimeExp, runtimeExp);
7273
+ return renderMustache(runtimeExp, context);
7274
+ }
7275
+ }
6916
7276
  return renderMustache((shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint: "插值表达式" }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context), context);
6917
7277
  }
6918
7278
  /* istanbul ignore next */
@@ -6985,6 +7345,8 @@ function compileVueTemplateToWxml(template, filename, options) {
6985
7345
  objectLiteralBindMode: options?.objectLiteralBindMode ?? "runtime",
6986
7346
  mustacheInterpolation: options?.mustacheInterpolation ?? "compact",
6987
7347
  classStyleBindings: [],
7348
+ runtimeBindingCache: /* @__PURE__ */ new Map(),
7349
+ runtimeBindingPrefix: "__wv_bind_",
6988
7350
  classStyleWxs: false,
6989
7351
  classStyleWxsExtension: wxsExtension,
6990
7352
  classStyleWxsSrc: options?.classStyleWxsSrc,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/compiler",
3
3
  "type": "module",
4
- "version": "6.16.7",
4
+ "version": "6.16.8",
5
5
  "description": "wevu 编译器基础包,面向小程序模板的编译与转换",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -50,9 +50,9 @@
50
50
  "merge": "^2.1.1",
51
51
  "pathe": "^2.0.3",
52
52
  "vue": "^3.5.34",
53
- "@weapp-core/constants": "^0.1.4",
53
+ "@weapp-core/constants": "^0.1.5",
54
54
  "@weapp-core/shared": "3.0.4",
55
- "@weapp-vite/ast": "6.16.7",
55
+ "@weapp-vite/ast": "6.16.8",
56
56
  "rolldown-require": "2.0.15"
57
57
  },
58
58
  "publishConfig": {