@wevu/compiler 6.21.0 → 6.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +30 -5
- package/dist/index.mjs +578 -292
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_FUNCTION_PROP_PATHS_KEY, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_JSX_ISLAND_DATA_KEY, WEVU_JSX_ISLAND_HANDLER, WEVU_JSX_ISLAND_TEMPLATE_NAME, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_ALIASES_KEY, WEVU_PROPS_DERIVED_KEYS_KEY, WEVU_PROPS_KEY, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_FUNCTION_TOKEN, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_OWNER_PROXY_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, WEVU_TEMPLATE_REF_CLASS_PREFIX } from "@weapp-core/constants";
|
|
3
|
-
import { getMiniProgramRuntimeGlobalKeys, getMiniProgramTemplatePreset, removeExtensionDeep } from "@weapp-core/shared";
|
|
2
|
+
import { WEAPP_I18N_RUNTIME_MARKER, WEAPP_VITE_RUNTIME_REACTIVITY_VIRTUAL_ID, WEAPP_VITE_RUNTIME_TEMPLATE_VIRTUAL_ID, WEAPP_VITE_RUNTIME_VIRTUAL_ID, WEVU_CLASS_STYLE_RUNTIME_FILE, WEVU_CLASS_STYLE_RUNTIME_MODULE, WEVU_CSS_MODULES_KEY, WEVU_CSS_VARS_STYLE_KEY, WEVU_EXPRESSION_ERROR_IDENTIFIER, WEVU_FUNCTION_PROP_PATHS_KEY, WEVU_INLINE_HANDLER, WEVU_INLINE_MAP_KEY, WEVU_IS_PAGE_KEY, WEVU_JSX_ISLAND_DATA_KEY, WEVU_JSX_ISLAND_HANDLER, WEVU_JSX_ISLAND_TEMPLATE_NAME, WEVU_LAYOUT_HOSTS_KEY, WEVU_LAYOUT_HOST_ID_PREFIX, WEVU_LAYOUT_HOST_REF_PREFIX, WEVU_MODEL_HANDLER, WEVU_OWNER_HANDLER, WEVU_PROPS_ALIASES_KEY, WEVU_PROPS_DERIVED_KEYS_KEY, WEVU_PROPS_KEY, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_BASE, WEVU_SLOT_FALLBACK_VIRTUAL_HOST_TAG_NAME, WEVU_SLOT_FUNCTION_TOKEN, WEVU_SLOT_NAMES_ATTR, WEVU_SLOT_NAMES_PROP, WEVU_SLOT_OWNER_ID_ATTR, WEVU_SLOT_OWNER_ID_KEY, WEVU_SLOT_OWNER_ID_PROP, WEVU_SLOT_OWNER_KEY, WEVU_SLOT_OWNER_PROXY_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, WEVU_TEMPLATE_REF_CLASS_PREFIX } from "@weapp-core/constants";
|
|
3
|
+
import { escapeWxmlAttribute, escapeWxmlText, getMiniProgramRuntimeGlobalKeys, getMiniProgramTemplatePreset, removeExtensionDeep } from "@weapp-core/shared";
|
|
4
4
|
import path from "pathe";
|
|
5
5
|
import { NodeTypes, baseParse } from "@vue/compiler-core";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
@@ -18,7 +18,7 @@ import { LRUCache } from "lru-cache";
|
|
|
18
18
|
import { collectJsxImportedComponentsAndDefaultExportFromBabelAst, collectJsxTemplateTagsFromBabelExpression, getObjectPropertyByKey, getRenderPropertyFromComponentOptions, parseJsLikeWithEngine, resolveRenderExpressionFromComponentOptions, toStaticObjectKey, unwrapTypeScriptExpression } from "@weapp-vite/ast";
|
|
19
19
|
import vueJsxPlugin from "@vue/babel-plugin-jsx";
|
|
20
20
|
import { transformSync } from "@weapp-vite/ast/babelCore";
|
|
21
|
-
import { compileScript, parse } from "vue/compiler-sfc";
|
|
21
|
+
import { compileScript, compileStyleAsync, parse } from "vue/compiler-sfc";
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
23
|
import postcss from "postcss";
|
|
24
24
|
import selectorParser from "postcss-selector-parser";
|
|
@@ -2523,6 +2523,8 @@ const INTERNAL_RUNTIME_VALUE_EXPORTS = /* @__PURE__ */ new Set([
|
|
|
2523
2523
|
"triggerRef",
|
|
2524
2524
|
"unref",
|
|
2525
2525
|
"useAttrs",
|
|
2526
|
+
"useCssModule",
|
|
2527
|
+
"useCssVars",
|
|
2526
2528
|
"useAsyncPullDownRefresh",
|
|
2527
2529
|
"useBindModel",
|
|
2528
2530
|
"useBoundingClientRect",
|
|
@@ -2605,6 +2607,8 @@ function createImportVisitors(program, state) {
|
|
|
2605
2607
|
"resolveComponent",
|
|
2606
2608
|
"resolveDirective",
|
|
2607
2609
|
"useAttrs",
|
|
2610
|
+
"useCssModule",
|
|
2611
|
+
"useCssVars",
|
|
2608
2612
|
"useSlots",
|
|
2609
2613
|
"useModel",
|
|
2610
2614
|
"mergeModels",
|
|
@@ -3060,7 +3064,8 @@ function buildForExpression(binding, forStack, level, helpers) {
|
|
|
3060
3064
|
if (level >= forStack.length) return buildNormalizedExpression(binding, helpers);
|
|
3061
3065
|
const info = forStack[level];
|
|
3062
3066
|
const listId = t.identifier(`__wv_list_${level}`);
|
|
3063
|
-
const
|
|
3067
|
+
const listExpAst = !binding.exp.startsWith("v-for :key ") && info.projectedListExpAst ? info.projectedListExpAst : info.listExpAst;
|
|
3068
|
+
const listExp = listExpAst ? t.cloneNode(listExpAst, true) : t.arrayExpression([]);
|
|
3064
3069
|
const unrefHelper = helpers.unref ? t.cloneNode(helpers.unref) : t.identifier("unref");
|
|
3065
3070
|
const listUnrefExp = t.callExpression(unrefHelper, [listExp]);
|
|
3066
3071
|
const listDecl = t.variableDeclaration("let", [t.variableDeclarator(listId, t.arrayExpression([]))]);
|
|
@@ -3673,6 +3678,14 @@ function injectFunctionPropPaths(componentOptionsObject, paths) {
|
|
|
3673
3678
|
componentOptionsObject.properties.push(t.objectProperty(t.identifier(WEVU_FUNCTION_PROP_PATHS_KEY), t.arrayExpression(uniquePaths.map((path) => t.stringLiteral(path)))));
|
|
3674
3679
|
return true;
|
|
3675
3680
|
}
|
|
3681
|
+
function createObjectLiteral(value) {
|
|
3682
|
+
return t.objectExpression(Object.entries(value).map(([key, item]) => t.objectProperty(t.stringLiteral(key), item && typeof item === "object" && !Array.isArray(item) ? createObjectLiteral(item) : t.valueToNode(item))));
|
|
3683
|
+
}
|
|
3684
|
+
function injectCssModules(componentOptionsObject, modules) {
|
|
3685
|
+
if (hasStaticProperty(componentOptionsObject, WEVU_CSS_MODULES_KEY)) return false;
|
|
3686
|
+
componentOptionsObject.properties.push(t.objectProperty(t.stringLiteral(WEVU_CSS_MODULES_KEY), createObjectLiteral(modules)));
|
|
3687
|
+
return true;
|
|
3688
|
+
}
|
|
3676
3689
|
function createScopedSlotHostPropertyDefinition(typeName, value) {
|
|
3677
3690
|
return t.objectExpression([t.objectProperty(t.identifier("type"), typeName === "String" ? t.identifier("String") : t.nullLiteral()), t.objectProperty(t.identifier("value"), value === null ? t.nullLiteral() : t.stringLiteral(value))]);
|
|
3678
3691
|
}
|
|
@@ -3806,6 +3819,7 @@ function rewriteDefaultExport(ast, state, options, enabledPageFeatures, serializ
|
|
|
3806
3819
|
if (componentOptionsObject) transformed = injectSetupInitialData(componentOptionsObject) || transformed;
|
|
3807
3820
|
if (componentOptionsObject && options?.relaxStructuredTypeOnlyProps) transformed = relaxStructuredTypeOnlyProps(componentOptionsObject) || transformed;
|
|
3808
3821
|
if (componentOptionsObject && options?.scopedSlotHostProperties) transformed = injectScopedSlotHostProperties(componentOptionsObject) || transformed;
|
|
3822
|
+
if (componentOptionsObject && options?.cssModules && Object.keys(options.cssModules).length) transformed = injectCssModules(componentOptionsObject, options.cssModules) || transformed;
|
|
3809
3823
|
if (componentOptionsObject) {
|
|
3810
3824
|
transformed = injectPropsAliases(componentOptionsObject, options?.propsAliases) || transformed;
|
|
3811
3825
|
transformed = injectPropsDerivedKeys(componentOptionsObject, options?.propsDerivedKeys) || transformed;
|
|
@@ -3928,6 +3942,31 @@ function createInlineExpressionId(seed) {
|
|
|
3928
3942
|
return `i${seed.toString(36)}`;
|
|
3929
3943
|
}
|
|
3930
3944
|
//#endregion
|
|
3945
|
+
//#region src/plugins/vue/compiler/template/expression/numeric.ts
|
|
3946
|
+
const DIGIT_NUMERIC_SEPARATOR_RE = /\d_\d/;
|
|
3947
|
+
const NON_DECIMAL_NUMERIC_LITERAL_RE = /\b0[bxo][\da-f_]/i;
|
|
3948
|
+
const DECIMAL_BIGINT_LITERAL_RE = /\b\d[\d_]*n\b/;
|
|
3949
|
+
const NON_DECIMAL_NUMERIC_RAW_RE = /^0[bxo]/i;
|
|
3950
|
+
function hasExtendedNumericLiteralSyntax(exp) {
|
|
3951
|
+
return DIGIT_NUMERIC_SEPARATOR_RE.test(exp) || NON_DECIMAL_NUMERIC_LITERAL_RE.test(exp) || DECIMAL_BIGINT_LITERAL_RE.test(exp);
|
|
3952
|
+
}
|
|
3953
|
+
function serializeBigIntForWxml(value) {
|
|
3954
|
+
const asNumber = Number(value);
|
|
3955
|
+
if (!Number.isSafeInteger(asNumber)) return t.stringLiteral(value.toString());
|
|
3956
|
+
return asNumber < 0 ? t.unaryExpression("-", t.numericLiteral(Math.abs(asNumber))) : t.numericLiteral(asNumber);
|
|
3957
|
+
}
|
|
3958
|
+
function normalizeTopLevelBigInt(expression) {
|
|
3959
|
+
if (t.isBigIntLiteral(expression)) return serializeBigIntForWxml(BigInt(expression.value));
|
|
3960
|
+
if (t.isUnaryExpression(expression, { operator: "-" }) && t.isBigIntLiteral(expression.argument)) return serializeBigIntForWxml(-BigInt(expression.argument.value));
|
|
3961
|
+
return expression;
|
|
3962
|
+
}
|
|
3963
|
+
function canonicalizeNumericLiteral(node) {
|
|
3964
|
+
const raw = node.extra?.raw;
|
|
3965
|
+
if (typeof raw !== "string" || !raw.includes("_") && !NON_DECIMAL_NUMERIC_RAW_RE.test(raw)) return;
|
|
3966
|
+
delete node.extra?.raw;
|
|
3967
|
+
delete node.extra?.rawValue;
|
|
3968
|
+
}
|
|
3969
|
+
//#endregion
|
|
3931
3970
|
//#region src/plugins/vue/compiler/template/expression/wxml.ts
|
|
3932
3971
|
function templateLiteralToConcat(node) {
|
|
3933
3972
|
const segments = [];
|
|
@@ -4027,7 +4066,8 @@ function normalizeWxmlExpression(exp) {
|
|
|
4027
4066
|
const hasTypeScriptSyntax = /\s(?:as|satisfies)\s/.test(exp) || /[\w$)\]]!(?=[.[\s,);:?]|$)/.test(exp) || /^\s*<[^>]+>/.test(exp);
|
|
4028
4067
|
const needsVueSlotsRewrite = exp.includes("$slots");
|
|
4029
4068
|
const needsThisRewrite = /\bthis\./.test(exp);
|
|
4030
|
-
|
|
4069
|
+
const needsNumericLiteralRewrite = hasExtendedNumericLiteralSyntax(exp);
|
|
4070
|
+
if (!exp.includes("`") && !exp.includes("??") && !exp.includes("?.") && !hasTypeScriptSyntax && !needsVueSlotsRewrite && !needsThisRewrite && !needsNumericLiteralRewrite) return exp;
|
|
4031
4071
|
try {
|
|
4032
4072
|
const ast = parse$3(`(${exp})`, {
|
|
4033
4073
|
sourceType: "module",
|
|
@@ -4036,6 +4076,8 @@ function normalizeWxmlExpression(exp) {
|
|
|
4036
4076
|
const stmt = ast.program.body[0];
|
|
4037
4077
|
if (!stmt || !("expression" in stmt)) return exp;
|
|
4038
4078
|
if (needsVueSlotsRewrite) rewriteVueSlotsExpression(ast);
|
|
4079
|
+
const expressionStatement = stmt;
|
|
4080
|
+
expressionStatement.expression = normalizeTopLevelBigInt(expressionStatement.expression);
|
|
4039
4081
|
traverse(ast, {
|
|
4040
4082
|
MemberExpression: { exit(path) {
|
|
4041
4083
|
const node = path.node;
|
|
@@ -4052,6 +4094,9 @@ function normalizeWxmlExpression(exp) {
|
|
|
4052
4094
|
TSTypeAssertion(path) {
|
|
4053
4095
|
path.replaceWith(path.node.expression);
|
|
4054
4096
|
},
|
|
4097
|
+
NumericLiteral(path) {
|
|
4098
|
+
canonicalizeNumericLiteral(path.node);
|
|
4099
|
+
},
|
|
4055
4100
|
OptionalMemberExpression: { exit(path) {
|
|
4056
4101
|
if (isOptionalChainNode(path.parentPath.node)) return;
|
|
4057
4102
|
path.replaceWith(lowerOptionalChain(path.node));
|
|
@@ -4089,8 +4134,6 @@ function normalizeWxmlExpression(exp) {
|
|
|
4089
4134
|
}
|
|
4090
4135
|
//#endregion
|
|
4091
4136
|
//#region src/plugins/jsx/compileJsx/ast.ts
|
|
4092
|
-
const ESCAPED_TEXT_RE = /[&<>]/g;
|
|
4093
|
-
const ESCAPED_ATTR_RE = /[&"<>]/g;
|
|
4094
4137
|
const WXML_EXPRESSION_GENERATE_OPTIONS = {
|
|
4095
4138
|
compact: true,
|
|
4096
4139
|
jsescOption: {
|
|
@@ -4098,23 +4141,8 @@ const WXML_EXPRESSION_GENERATE_OPTIONS = {
|
|
|
4098
4141
|
minimal: true
|
|
4099
4142
|
}
|
|
4100
4143
|
};
|
|
4101
|
-
const
|
|
4102
|
-
|
|
4103
|
-
"<": "<",
|
|
4104
|
-
">": ">"
|
|
4105
|
-
};
|
|
4106
|
-
const ESCAPED_ATTR_MAP = {
|
|
4107
|
-
"&": "&",
|
|
4108
|
-
"\"": """,
|
|
4109
|
-
"<": "<",
|
|
4110
|
-
">": ">"
|
|
4111
|
-
};
|
|
4112
|
-
function escapeText(value) {
|
|
4113
|
-
return value.replace(ESCAPED_TEXT_RE, (ch) => ESCAPED_TEXT_MAP[ch] || ch);
|
|
4114
|
-
}
|
|
4115
|
-
function escapeAttr(value) {
|
|
4116
|
-
return value.replace(ESCAPED_ATTR_RE, (ch) => ESCAPED_ATTR_MAP[ch] || ch);
|
|
4117
|
-
}
|
|
4144
|
+
const escapeText = escapeWxmlText;
|
|
4145
|
+
const escapeAttr = escapeWxmlAttribute;
|
|
4118
4146
|
const WHITESPACE_RE = /\s+/g;
|
|
4119
4147
|
function normalizeJsxText(value) {
|
|
4120
4148
|
return value.replace(WHITESPACE_RE, " ");
|
|
@@ -6609,106 +6637,69 @@ function transformNestedWxssVars(source) {
|
|
|
6609
6637
|
}
|
|
6610
6638
|
//#endregion
|
|
6611
6639
|
//#region src/plugins/vue/compiler/style.ts
|
|
6612
|
-
|
|
6613
|
-
|
|
6640
|
+
function normalizeStyleError(error) {
|
|
6641
|
+
return error instanceof Error ? error.message : String(error);
|
|
6642
|
+
}
|
|
6643
|
+
function hasSlottedScopeSelector(source, slottedScopeId) {
|
|
6644
|
+
let found = false;
|
|
6645
|
+
const processor = selectorParser((selectors) => {
|
|
6646
|
+
selectors.walkAttributes((attribute) => {
|
|
6647
|
+
if (attribute.attribute === slottedScopeId) found = true;
|
|
6648
|
+
});
|
|
6649
|
+
});
|
|
6650
|
+
postcss.parse(source).walkRules((rule) => {
|
|
6651
|
+
if (!found) processor.processSync(rule.selector);
|
|
6652
|
+
});
|
|
6653
|
+
return found;
|
|
6654
|
+
}
|
|
6655
|
+
/**
|
|
6656
|
+
* compiler-sfc 已在 scoped 插件中处理 deep 选择器,此函数保留为兼容入口。
|
|
6657
|
+
*/
|
|
6614
6658
|
function transformVueDeepSelectors(source) {
|
|
6615
|
-
if (!source.includes(":deep") && !source.includes("::v-deep")) return source;
|
|
6616
6659
|
const root = postcss.parse(source);
|
|
6617
6660
|
const processor = selectorParser((selectors) => {
|
|
6618
6661
|
selectors.walkTags((tag) => {
|
|
6619
|
-
const
|
|
6620
|
-
if (
|
|
6662
|
+
const mapped = DEFAULT_HTML_TO_WXML_TAG_MAP[tag.value.toLowerCase()];
|
|
6663
|
+
if (mapped && mapped !== tag.value.toLowerCase()) tag.replaceWith(selectorParser.className({ value: tag.value.toLowerCase() }));
|
|
6621
6664
|
});
|
|
6622
6665
|
selectors.walkPseudos((pseudo) => {
|
|
6623
|
-
if (
|
|
6666
|
+
if (![":deep", "::v-deep"].includes(pseudo.value)) return;
|
|
6624
6667
|
const replacement = pseudo.nodes?.[0]?.nodes.map((node) => node.clone()) ?? [];
|
|
6625
|
-
|
|
6626
|
-
else {
|
|
6627
|
-
const previous = pseudo.prev();
|
|
6628
|
-
const next = pseudo.next();
|
|
6629
|
-
if (next?.type === "combinator" && (!previous || previous.type === "combinator")) next.remove();
|
|
6630
|
-
pseudo.remove();
|
|
6631
|
-
}
|
|
6668
|
+
replacement.length ? pseudo.replaceWith(...replacement) : pseudo.remove();
|
|
6632
6669
|
});
|
|
6633
6670
|
});
|
|
6634
6671
|
root.walkRules((rule) => {
|
|
6635
|
-
|
|
6672
|
+
rule.selector = processor.processSync(rule.selector).replace(/\s{2,}/g, " ").trim();
|
|
6636
6673
|
});
|
|
6637
6674
|
return root.toString();
|
|
6638
6675
|
}
|
|
6639
6676
|
/**
|
|
6640
|
-
*
|
|
6641
|
-
* 为每个选择器添加特定的 scoped 属性
|
|
6677
|
+
* 将 Vue SFC style 块编译为可交给 Vite CSS 管线的内容。
|
|
6642
6678
|
*/
|
|
6643
|
-
function
|
|
6644
|
-
const
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6679
|
+
async function compileVueStyleToWxss(styleBlock, options) {
|
|
6680
|
+
const filename = options.filename ?? `style-${options.id}.${styleBlock.lang || "css"}`;
|
|
6681
|
+
const moduleName = typeof styleBlock.module === "string" ? styleBlock.module : typeof options.modules === "string" ? options.modules : "$style";
|
|
6682
|
+
const modules = Boolean(options.modules || styleBlock.module);
|
|
6683
|
+
const result = await compileStyleAsync({
|
|
6684
|
+
filename,
|
|
6685
|
+
id: `data-v-${options.id}`,
|
|
6686
|
+
source: styleBlock.content,
|
|
6687
|
+
scoped: options.transformScoped !== false && Boolean(options.scoped || styleBlock.scoped),
|
|
6688
|
+
modules,
|
|
6689
|
+
modulesOptions: modules ? { generateScopedName: (name) => `${name}_${options.id}` } : void 0,
|
|
6690
|
+
preprocessLang: styleBlock.lang,
|
|
6691
|
+
preprocessOptions: options.preprocessOptions
|
|
6653
6692
|
});
|
|
6654
|
-
}
|
|
6655
|
-
/**
|
|
6656
|
-
* 样式转换:CSS → WXSS
|
|
6657
|
-
* 处理小程序不支持的 CSS 特性
|
|
6658
|
-
*/
|
|
6659
|
-
/**
|
|
6660
|
-
* 生成简单的 hash
|
|
6661
|
-
*/
|
|
6662
|
-
function generateHash(str) {
|
|
6663
|
-
let hash = 0;
|
|
6664
|
-
for (let i = 0; i < str.length; i++) {
|
|
6665
|
-
const char = str.charCodeAt(i);
|
|
6666
|
-
hash = (hash << 5) - hash + char;
|
|
6667
|
-
hash = hash & hash;
|
|
6668
|
-
}
|
|
6669
|
-
return Math.abs(hash).toString(36) + str.length.toString(36);
|
|
6670
|
-
}
|
|
6671
|
-
/**
|
|
6672
|
-
* 转换 CSS Modules
|
|
6673
|
-
*/
|
|
6674
|
-
function transformCssModules(source, id) {
|
|
6675
|
-
const classes = {};
|
|
6676
|
-
const hash = generateHash(id);
|
|
6677
|
-
const classRegex = new RegExp(CSS_CLASS_RE.source, CSS_CLASS_RE.flags);
|
|
6678
|
-
const foundClasses = [];
|
|
6679
|
-
let result = classRegex.exec(source);
|
|
6680
|
-
while (result !== null) {
|
|
6681
|
-
foundClasses.push(result[1]);
|
|
6682
|
-
result = classRegex.exec(source);
|
|
6683
|
-
}
|
|
6684
|
-
for (const className of foundClasses) classes[className] = `${className}_${hash}`;
|
|
6685
|
-
let code = source;
|
|
6686
|
-
for (const [original, scoped] of Object.entries(classes)) {
|
|
6687
|
-
const regex = new RegExp(`\\.${original}\\b`, "g");
|
|
6688
|
-
code = code.replace(regex, `.${scoped}`);
|
|
6689
|
-
}
|
|
6693
|
+
if (result.errors.length) throw new Error(`SFC 样式编译失败(${filename}):${result.errors.map(normalizeStyleError).join("; ")}`);
|
|
6690
6694
|
return {
|
|
6691
|
-
code,
|
|
6692
|
-
|
|
6695
|
+
code: options.preserveDeepSelectors ? result.code : transformVueDeepSelectors(result.code),
|
|
6696
|
+
map: result.map ? JSON.stringify(result.map) : void 0,
|
|
6697
|
+
scopedId: options.scoped || styleBlock.scoped ? `data-v-${options.id}` : void 0,
|
|
6698
|
+
usesSlotted: hasSlottedScopeSelector(result.code, `data-v-${options.id}-s`),
|
|
6699
|
+
modules: result.modules ? { [moduleName]: result.modules } : void 0,
|
|
6700
|
+
dependencies: [...result.dependencies]
|
|
6693
6701
|
};
|
|
6694
6702
|
}
|
|
6695
|
-
/**
|
|
6696
|
-
* 将 Vue SFC 的 style 块转换为 WXSS
|
|
6697
|
-
*/
|
|
6698
|
-
function compileVueStyleToWxss(styleBlock, options) {
|
|
6699
|
-
const { id, scoped, modules, preserveDeepSelectors, transformScoped = true } = options;
|
|
6700
|
-
let code = styleBlock.content;
|
|
6701
|
-
if (transformScoped && (scoped || styleBlock.scoped)) code = transformScopedCss(code, id);
|
|
6702
|
-
if (modules || styleBlock.module) {
|
|
6703
|
-
const moduleName = typeof styleBlock.module === "string" ? styleBlock.module : "$style";
|
|
6704
|
-
const moduleResult = transformCssModules(code, id);
|
|
6705
|
-
return {
|
|
6706
|
-
code: preserveDeepSelectors ? moduleResult.code : transformVueDeepSelectors(moduleResult.code),
|
|
6707
|
-
modules: { [moduleName]: moduleResult.classes }
|
|
6708
|
-
};
|
|
6709
|
-
}
|
|
6710
|
-
return { code: preserveDeepSelectors ? code : transformVueDeepSelectors(code) };
|
|
6711
|
-
}
|
|
6712
6703
|
//#endregion
|
|
6713
6704
|
//#region src/plugins/vue/compiler/template/classStyleRuntime.ts
|
|
6714
6705
|
/**
|
|
@@ -6968,11 +6959,93 @@ function getClassStyleWxsSource(options = {}) {
|
|
|
6968
6959
|
].join("\n");
|
|
6969
6960
|
}
|
|
6970
6961
|
//#endregion
|
|
6971
|
-
//#region src/plugins/vue/compiler/template/
|
|
6962
|
+
//#region src/plugins/vue/compiler/template/expression/inlineShared.ts
|
|
6972
6963
|
const IDENTIFIER_RE$5 = /^[A-Z_$][\w$]*$/i;
|
|
6964
|
+
const INLINE_GLOBALS = /* @__PURE__ */ new Set([
|
|
6965
|
+
"Math",
|
|
6966
|
+
"Number",
|
|
6967
|
+
"Date",
|
|
6968
|
+
"Array",
|
|
6969
|
+
"Object",
|
|
6970
|
+
"Boolean",
|
|
6971
|
+
"String",
|
|
6972
|
+
"RegExp",
|
|
6973
|
+
"Map",
|
|
6974
|
+
"Set",
|
|
6975
|
+
"JSON",
|
|
6976
|
+
"Intl",
|
|
6977
|
+
"Promise",
|
|
6978
|
+
"console",
|
|
6979
|
+
"Infinity",
|
|
6980
|
+
"undefined",
|
|
6981
|
+
"NaN",
|
|
6982
|
+
"isFinite",
|
|
6983
|
+
"isNaN",
|
|
6984
|
+
"parseFloat",
|
|
6985
|
+
"parseInt",
|
|
6986
|
+
"decodeURI",
|
|
6987
|
+
"decodeURIComponent",
|
|
6988
|
+
"encodeURI",
|
|
6989
|
+
"encodeURIComponent",
|
|
6990
|
+
"require",
|
|
6991
|
+
"arguments",
|
|
6992
|
+
WEVU_CLASS_STYLE_RUNTIME_MODULE,
|
|
6993
|
+
"__wevuUnref",
|
|
6994
|
+
"globalThis",
|
|
6995
|
+
"setTimeout",
|
|
6996
|
+
"clearTimeout",
|
|
6997
|
+
"setInterval",
|
|
6998
|
+
"clearInterval",
|
|
6999
|
+
"Page",
|
|
7000
|
+
"App",
|
|
7001
|
+
"Component",
|
|
7002
|
+
"requirePlugin",
|
|
7003
|
+
"getApp",
|
|
7004
|
+
"getCurrentPages",
|
|
7005
|
+
"ctx",
|
|
7006
|
+
"scope",
|
|
7007
|
+
...getMiniProgramRuntimeGlobalKeys()
|
|
7008
|
+
]);
|
|
7009
|
+
function createMemberAccess$1(target, prop) {
|
|
7010
|
+
if (IDENTIFIER_RE$5.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
|
|
7011
|
+
return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
|
|
7012
|
+
}
|
|
7013
|
+
function replaceIdentifierWithExpression$1(path, replacement) {
|
|
7014
|
+
const parent = path.parentPath;
|
|
7015
|
+
if (parent.isObjectProperty() && parent.node.shorthand && parent.node.key === path.node) {
|
|
7016
|
+
parent.node.shorthand = false;
|
|
7017
|
+
parent.node.value = replacement;
|
|
7018
|
+
return;
|
|
7019
|
+
}
|
|
7020
|
+
path.replaceWith(replacement);
|
|
7021
|
+
}
|
|
7022
|
+
//#endregion
|
|
7023
|
+
//#region src/plugins/vue/compiler/template/expression/forItemAccess.ts
|
|
7024
|
+
function getForItemAccess(context, name) {
|
|
7025
|
+
for (let index = context.forStack.length - 1; index >= 0; index -= 1) {
|
|
7026
|
+
const forInfo = context.forStack[index];
|
|
7027
|
+
if (forInfo?.item === name && forInfo.itemAccess) return forInfo.itemAccess;
|
|
7028
|
+
}
|
|
7029
|
+
return name;
|
|
7030
|
+
}
|
|
7031
|
+
function rewriteForItemAccess(ast, context) {
|
|
7032
|
+
const itemAccesses = /* @__PURE__ */ new Map();
|
|
7033
|
+
for (const forInfo of context.forStack) if (forInfo.item && forInfo.itemAccess) itemAccesses.set(forInfo.item, forInfo.itemAccess);
|
|
7034
|
+
if (!itemAccesses.size) return;
|
|
7035
|
+
traverse(ast, { Identifier(path) {
|
|
7036
|
+
if (!path.isReferencedIdentifier() || path.scope.hasBinding(path.node.name)) return;
|
|
7037
|
+
const replacement = itemAccesses.get(path.node.name);
|
|
7038
|
+
if (!replacement) return;
|
|
7039
|
+
replaceIdentifierWithExpression$1(path, replacement.split(".").slice(1).reduce((target, property) => t.memberExpression(target, t.identifier(property)), t.identifier(path.node.name)));
|
|
7040
|
+
path.skip();
|
|
7041
|
+
} });
|
|
7042
|
+
}
|
|
7043
|
+
//#endregion
|
|
7044
|
+
//#region src/plugins/vue/compiler/template/elements/forExpression.ts
|
|
7045
|
+
const IDENTIFIER_RE$4 = /^[A-Z_$][\w$]*$/i;
|
|
6973
7046
|
const FOR_ITEM_ALIAS_PLACEHOLDER = "__wv_for_item__";
|
|
6974
7047
|
function isIdentifier(value) {
|
|
6975
|
-
return IDENTIFIER_RE$
|
|
7048
|
+
return IDENTIFIER_RE$4.test(value);
|
|
6976
7049
|
}
|
|
6977
7050
|
function splitTopLevelByComma(input) {
|
|
6978
7051
|
const out = [];
|
|
@@ -7248,7 +7321,7 @@ function withSlotProps(context, mapping, fn) {
|
|
|
7248
7321
|
popSlotProps(context);
|
|
7249
7322
|
}
|
|
7250
7323
|
}
|
|
7251
|
-
const IDENTIFIER_RE$
|
|
7324
|
+
const IDENTIFIER_RE$3 = /^[A-Z_$][\w$]*$/i;
|
|
7252
7325
|
const BIND_SHORTHAND_ARG_RE = /^[A-Z_$][\w$]*(?:-[A-Z_$][\w$]*)*$/i;
|
|
7253
7326
|
const BACKSLASH_RE$2 = /\\/g;
|
|
7254
7327
|
const SINGLE_QUOTE_RE$2 = /'/g;
|
|
@@ -7269,7 +7342,7 @@ function collectScopePropMapping(context) {
|
|
|
7269
7342
|
const mapping = {};
|
|
7270
7343
|
if (!context.slotMultipleInstance) return mapping;
|
|
7271
7344
|
for (const scope of context.scopeStack) for (const name of scope) {
|
|
7272
|
-
if (!IDENTIFIER_RE$
|
|
7345
|
+
if (!IDENTIFIER_RE$3.test(name)) continue;
|
|
7273
7346
|
if (!hasOwn(mapping, name)) mapping[name] = name;
|
|
7274
7347
|
}
|
|
7275
7348
|
return mapping;
|
|
@@ -7281,7 +7354,7 @@ function buildScopePropsExpression(context) {
|
|
|
7281
7354
|
const mapping = collectScopePropMapping(context);
|
|
7282
7355
|
const keys = Object.keys(mapping);
|
|
7283
7356
|
if (!keys.length) return null;
|
|
7284
|
-
return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${key}`).join(",")}]`;
|
|
7357
|
+
return `[${keys.map((key) => `${toWxmlStringLiteral$1(key)},${getForItemAccess(context, key)}`).join(",")}]`;
|
|
7285
7358
|
}
|
|
7286
7359
|
function hashString(input) {
|
|
7287
7360
|
let hash = 0;
|
|
@@ -7350,7 +7423,7 @@ function collectForAliasMapping$2(context) {
|
|
|
7350
7423
|
}
|
|
7351
7424
|
return mapping;
|
|
7352
7425
|
}
|
|
7353
|
-
function replaceIdentifierWithExpression
|
|
7426
|
+
function replaceIdentifierWithExpression(path, replacement) {
|
|
7354
7427
|
const parent = path.parentPath;
|
|
7355
7428
|
if (parent.isObjectProperty() && parent.node.shorthand && parent.node.key === path.node) {
|
|
7356
7429
|
parent.node.shorthand = false;
|
|
@@ -7359,7 +7432,7 @@ function replaceIdentifierWithExpression$1(path, replacement) {
|
|
|
7359
7432
|
}
|
|
7360
7433
|
path.replaceWith(replacement);
|
|
7361
7434
|
}
|
|
7362
|
-
const IDENTIFIER_RE$
|
|
7435
|
+
const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
|
|
7363
7436
|
function rewriteScopedSlotExpression(exp, context) {
|
|
7364
7437
|
const normalized = normalizeWxmlExpression(exp);
|
|
7365
7438
|
const parsed = parseBabelExpressionFile(normalized);
|
|
@@ -7370,7 +7443,7 @@ function rewriteScopedSlotExpression(exp, context) {
|
|
|
7370
7443
|
const forAliases = collectForAliasMapping$2(context);
|
|
7371
7444
|
const createMemberAccess = (target, prop) => {
|
|
7372
7445
|
if (!prop) return t.identifier(target);
|
|
7373
|
-
if (IDENTIFIER_RE$
|
|
7446
|
+
if (IDENTIFIER_RE$2.test(prop)) return t.memberExpression(t.identifier(target), t.identifier(prop));
|
|
7374
7447
|
return t.memberExpression(t.identifier(target), t.stringLiteral(prop), true);
|
|
7375
7448
|
};
|
|
7376
7449
|
traverse(ast, { Identifier(path) {
|
|
@@ -7381,17 +7454,18 @@ function rewriteScopedSlotExpression(exp, context) {
|
|
|
7381
7454
|
if (hasOwn(forAliases, name)) {
|
|
7382
7455
|
const aliasExp = parseBabelExpression(forAliases[name]);
|
|
7383
7456
|
if (aliasExp) {
|
|
7384
|
-
replaceIdentifierWithExpression
|
|
7457
|
+
replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
|
|
7385
7458
|
return;
|
|
7386
7459
|
}
|
|
7387
7460
|
}
|
|
7388
7461
|
if (locals.has(name)) return;
|
|
7389
7462
|
if (hasOwn(slotProps, name)) {
|
|
7390
|
-
replaceIdentifierWithExpression
|
|
7463
|
+
replaceIdentifierWithExpression(path, createMemberAccess(WEVU_SLOT_PROPS_DATA_KEY, slotProps[name]));
|
|
7391
7464
|
return;
|
|
7392
7465
|
}
|
|
7393
|
-
replaceIdentifierWithExpression
|
|
7466
|
+
replaceIdentifierWithExpression(path, createMemberAccess(WEVU_SLOT_OWNER_KEY, name));
|
|
7394
7467
|
} });
|
|
7468
|
+
rewriteForItemAccess(ast, context);
|
|
7395
7469
|
const stmt = ast.program.body[0];
|
|
7396
7470
|
const updatedExpression = stmt && "expression" in stmt ? stmt.expression : null;
|
|
7397
7471
|
return updatedExpression ? generateExpression(updatedExpression) : normalized;
|
|
@@ -7399,7 +7473,7 @@ function rewriteScopedSlotExpression(exp, context) {
|
|
|
7399
7473
|
function rewriteForAliasExpression(exp, context) {
|
|
7400
7474
|
const normalized = normalizeWxmlExpression(exp);
|
|
7401
7475
|
const forAliases = collectForAliasMapping$2(context);
|
|
7402
|
-
if (!Object.keys(forAliases).length) return normalized;
|
|
7476
|
+
if (!Object.keys(forAliases).length && !context.forStack.some((forInfo) => forInfo.itemAccess)) return normalized;
|
|
7403
7477
|
const parsed = parseBabelExpressionFile(normalized);
|
|
7404
7478
|
if (!parsed) return normalized;
|
|
7405
7479
|
const { ast } = parsed;
|
|
@@ -7409,9 +7483,10 @@ function rewriteForAliasExpression(exp, context) {
|
|
|
7409
7483
|
if (path.scope.hasBinding(name)) return;
|
|
7410
7484
|
if (hasOwn(forAliases, name)) {
|
|
7411
7485
|
const aliasExp = parseBabelExpression(forAliases[name]);
|
|
7412
|
-
if (aliasExp) replaceIdentifierWithExpression
|
|
7486
|
+
if (aliasExp) replaceIdentifierWithExpression(path, t.cloneNode(aliasExp, true));
|
|
7413
7487
|
}
|
|
7414
7488
|
} });
|
|
7489
|
+
rewriteForItemAccess(ast, context);
|
|
7415
7490
|
const stmt = ast.program.body[0];
|
|
7416
7491
|
const updatedExpression = stmt && "expression" in stmt ? stmt.expression : null;
|
|
7417
7492
|
return updatedExpression ? generateExpression(updatedExpression) : normalized;
|
|
@@ -7521,68 +7596,89 @@ function normalizeStyleBindingExpression(exp, context) {
|
|
|
7521
7596
|
return out;
|
|
7522
7597
|
}
|
|
7523
7598
|
//#endregion
|
|
7524
|
-
//#region src/plugins/vue/compiler/template/expression/
|
|
7525
|
-
const INLINE_GLOBALS = /* @__PURE__ */ new Set([
|
|
7526
|
-
"Math",
|
|
7527
|
-
"Number",
|
|
7528
|
-
"Date",
|
|
7529
|
-
"Array",
|
|
7530
|
-
"Object",
|
|
7531
|
-
"Boolean",
|
|
7532
|
-
"String",
|
|
7533
|
-
"RegExp",
|
|
7534
|
-
"Map",
|
|
7535
|
-
"Set",
|
|
7536
|
-
"JSON",
|
|
7537
|
-
"Intl",
|
|
7538
|
-
"Promise",
|
|
7539
|
-
"console",
|
|
7540
|
-
"Infinity",
|
|
7541
|
-
"undefined",
|
|
7542
|
-
"NaN",
|
|
7543
|
-
"isFinite",
|
|
7544
|
-
"isNaN",
|
|
7545
|
-
"parseFloat",
|
|
7546
|
-
"parseInt",
|
|
7547
|
-
"decodeURI",
|
|
7548
|
-
"decodeURIComponent",
|
|
7549
|
-
"encodeURI",
|
|
7550
|
-
"encodeURIComponent",
|
|
7551
|
-
"require",
|
|
7552
|
-
"arguments",
|
|
7553
|
-
WEVU_CLASS_STYLE_RUNTIME_MODULE,
|
|
7554
|
-
"__wevuUnref",
|
|
7555
|
-
"globalThis",
|
|
7556
|
-
"setTimeout",
|
|
7557
|
-
"clearTimeout",
|
|
7558
|
-
"setInterval",
|
|
7559
|
-
"clearInterval",
|
|
7560
|
-
"Page",
|
|
7561
|
-
"App",
|
|
7562
|
-
"Component",
|
|
7563
|
-
"requirePlugin",
|
|
7564
|
-
"getApp",
|
|
7565
|
-
"getCurrentPages",
|
|
7566
|
-
"ctx",
|
|
7567
|
-
"scope",
|
|
7568
|
-
...getMiniProgramRuntimeGlobalKeys()
|
|
7569
|
-
]);
|
|
7570
|
-
const IDENTIFIER_RE$2 = /^[A-Z_$][\w$]*$/i;
|
|
7599
|
+
//#region src/plugins/vue/compiler/template/expression/forItemResolver.ts
|
|
7571
7600
|
const SIMPLE_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
if (
|
|
7575
|
-
|
|
7601
|
+
function rewriteForItemResolverExpression(rawExp, resolvedLocals, resolvedIndexes) {
|
|
7602
|
+
const parsed = parseBabelExpressionFile(rawExp);
|
|
7603
|
+
if (!parsed) return null;
|
|
7604
|
+
traverse(parsed.ast, {
|
|
7605
|
+
Identifier(path) {
|
|
7606
|
+
if (!path.isReferencedIdentifier() || path.scope.hasBinding(path.node.name)) return;
|
|
7607
|
+
const name = path.node.name;
|
|
7608
|
+
const localExpression = resolvedLocals.get(name) ?? resolvedIndexes.get(name);
|
|
7609
|
+
if (localExpression) {
|
|
7610
|
+
replaceIdentifierWithExpression$1(path, t.cloneNode(localExpression, true));
|
|
7611
|
+
path.skip();
|
|
7612
|
+
return;
|
|
7613
|
+
}
|
|
7614
|
+
if (INLINE_GLOBALS.has(name)) return;
|
|
7615
|
+
replaceIdentifierWithExpression$1(path, createMemberAccess$1("ctx", name));
|
|
7616
|
+
path.skip();
|
|
7617
|
+
},
|
|
7618
|
+
ThisExpression(path) {
|
|
7619
|
+
path.replaceWith(t.identifier("ctx"));
|
|
7620
|
+
}
|
|
7621
|
+
});
|
|
7622
|
+
const statement = parsed.ast.program.body[0];
|
|
7623
|
+
return statement && t.isExpressionStatement(statement) ? statement.expression : null;
|
|
7576
7624
|
}
|
|
7577
|
-
function
|
|
7578
|
-
const
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7625
|
+
function buildNestedForItemResolverExpression(targetKey, targetLevel, context, slotProps, indexBindings) {
|
|
7626
|
+
const resolvedLocals = /* @__PURE__ */ new Map();
|
|
7627
|
+
const resolvedIndexes = /* @__PURE__ */ new Map();
|
|
7628
|
+
for (let level = 0; level <= targetLevel; level += 1) {
|
|
7629
|
+
const forInfo = context.forStack[level];
|
|
7630
|
+
const listExp = forInfo?.listExp?.trim() ?? "";
|
|
7631
|
+
const indexBinding = indexBindings[level];
|
|
7632
|
+
if (!forInfo || !listExp || !indexBinding) return null;
|
|
7633
|
+
const root = SIMPLE_PATH_RE.test(listExp) ? listExp.split(".")[0] : "";
|
|
7634
|
+
if (root && hasOwn(slotProps, root) && !resolvedLocals.has(root)) return null;
|
|
7635
|
+
const listExpression = rewriteForItemResolverExpression(listExp, resolvedLocals, resolvedIndexes);
|
|
7636
|
+
if (!listExpression) return null;
|
|
7637
|
+
const indexExpression = createMemberAccess$1("scope", indexBinding.key);
|
|
7638
|
+
const itemExpression = t.memberExpression(listExpression, t.cloneNode(indexExpression), true);
|
|
7639
|
+
if (forInfo.item) resolvedLocals.set(forInfo.item, itemExpression);
|
|
7640
|
+
for (const [alias, aliasExp] of Object.entries(forInfo.itemAliases ?? {})) {
|
|
7641
|
+
const resolvedAlias = rewriteForItemResolverExpression(aliasExp, resolvedLocals, resolvedIndexes);
|
|
7642
|
+
if (resolvedAlias) resolvedLocals.set(alias, resolvedAlias);
|
|
7643
|
+
}
|
|
7644
|
+
const targetExpression = resolvedLocals.get(targetKey);
|
|
7645
|
+
if (level === targetLevel && targetExpression) return generateExpression(t.arrowFunctionExpression([t.identifier("ctx"), t.identifier("scope")], t.cloneNode(targetExpression, true)));
|
|
7646
|
+
resolvedIndexes.set(forInfo.index?.trim() || "index", indexExpression);
|
|
7647
|
+
if (forInfo.key) resolvedIndexes.set(forInfo.key, indexExpression);
|
|
7583
7648
|
}
|
|
7584
|
-
|
|
7649
|
+
return null;
|
|
7585
7650
|
}
|
|
7651
|
+
function buildForItemResolverExpression(targetKey, context, slotProps, indexBindings) {
|
|
7652
|
+
let targetLevel = -1;
|
|
7653
|
+
for (let level = context.forStack.length - 1; level >= 0; level -= 1) {
|
|
7654
|
+
const forInfo = context.forStack[level];
|
|
7655
|
+
if (forInfo?.item === targetKey || hasOwn(forInfo?.itemAliases ?? {}, targetKey)) {
|
|
7656
|
+
targetLevel = level;
|
|
7657
|
+
break;
|
|
7658
|
+
}
|
|
7659
|
+
}
|
|
7660
|
+
if (targetLevel < 0) return null;
|
|
7661
|
+
const forInfo = context.forStack[targetLevel];
|
|
7662
|
+
const listExp = forInfo?.listExp?.trim() ?? "";
|
|
7663
|
+
const indexBinding = indexBindings[targetLevel];
|
|
7664
|
+
if (!listExp || !indexBinding) return null;
|
|
7665
|
+
if (forInfo?.item === targetKey && SIMPLE_PATH_RE.test(listExp)) {
|
|
7666
|
+
const root = listExp.split(".")[0];
|
|
7667
|
+
const localRoots = new Set(Object.keys(slotProps));
|
|
7668
|
+
for (let level = 0; level <= targetLevel; level += 1) {
|
|
7669
|
+
const item = context.forStack[level]?.item?.trim();
|
|
7670
|
+
const index = context.forStack[level]?.index?.trim();
|
|
7671
|
+
if (item) localRoots.add(item);
|
|
7672
|
+
if (index) localRoots.add(index);
|
|
7673
|
+
localRoots.add("index");
|
|
7674
|
+
}
|
|
7675
|
+
if (!localRoots.has(root)) return `({type:'for-item',path:${JSON.stringify(listExp)},indexKey:${JSON.stringify(indexBinding.key)}})`;
|
|
7676
|
+
}
|
|
7677
|
+
return buildNestedForItemResolverExpression(targetKey, targetLevel, context, slotProps, indexBindings);
|
|
7678
|
+
}
|
|
7679
|
+
//#endregion
|
|
7680
|
+
//#region src/plugins/vue/compiler/template/expression/inline.ts
|
|
7681
|
+
const SCRIPT_SETUP_REF_BINDINGS = /* @__PURE__ */ new Set(["setup-ref", "setup-maybe-ref"]);
|
|
7586
7682
|
function resolveSlotPropBinding(slotProps, name) {
|
|
7587
7683
|
if (!hasOwn(slotProps, name)) return null;
|
|
7588
7684
|
const prop = slotProps[name];
|
|
@@ -7599,11 +7695,11 @@ function rewriteExpressionAst(ast, locals, options) {
|
|
|
7599
7695
|
if (path.scope.getBinding(name)) return;
|
|
7600
7696
|
if (locals.has(name)) {
|
|
7601
7697
|
options?.markLocal?.(name);
|
|
7602
|
-
replaceIdentifierWithExpression(path, createMemberAccess$1("scope", name));
|
|
7698
|
+
replaceIdentifierWithExpression$1(path, createMemberAccess$1("scope", name));
|
|
7603
7699
|
return;
|
|
7604
7700
|
}
|
|
7605
7701
|
if (INLINE_GLOBALS.has(name)) return;
|
|
7606
|
-
replaceIdentifierWithExpression(path, createMemberAccess$1("ctx", name));
|
|
7702
|
+
replaceIdentifierWithExpression$1(path, createMemberAccess$1("ctx", name));
|
|
7607
7703
|
},
|
|
7608
7704
|
ThisExpression(path) {
|
|
7609
7705
|
path.replaceWith(t.identifier("ctx"));
|
|
@@ -7617,28 +7713,6 @@ function buildInlineIndexBindings(context) {
|
|
|
7617
7713
|
binding: forInfo.index?.trim() || "index"
|
|
7618
7714
|
}));
|
|
7619
7715
|
}
|
|
7620
|
-
function buildForItemResolverExpression(targetKey, context, slotProps, indexBindings) {
|
|
7621
|
-
let targetLevel = -1;
|
|
7622
|
-
for (let level = context.forStack.length - 1; level >= 0; level -= 1) if (context.forStack[level]?.item === targetKey) {
|
|
7623
|
-
targetLevel = level;
|
|
7624
|
-
break;
|
|
7625
|
-
}
|
|
7626
|
-
if (targetLevel < 0) return null;
|
|
7627
|
-
const listExp = context.forStack[targetLevel]?.listExp?.trim() ?? "";
|
|
7628
|
-
const indexBinding = indexBindings[targetLevel];
|
|
7629
|
-
if (!listExp || !indexBinding || !SIMPLE_PATH_RE.test(listExp)) return null;
|
|
7630
|
-
const root = listExp.split(".")[0];
|
|
7631
|
-
const localRoots = new Set(Object.keys(slotProps));
|
|
7632
|
-
for (let level = 0; level <= targetLevel; level += 1) {
|
|
7633
|
-
const item = context.forStack[level]?.item?.trim();
|
|
7634
|
-
const index = context.forStack[level]?.index?.trim();
|
|
7635
|
-
if (item) localRoots.add(item);
|
|
7636
|
-
if (index) localRoots.add(index);
|
|
7637
|
-
localRoots.add("index");
|
|
7638
|
-
}
|
|
7639
|
-
if (localRoots.has(root)) return null;
|
|
7640
|
-
return `({type:'for-item',path:${JSON.stringify(listExp)},indexKey:${JSON.stringify(indexBinding.key)}})`;
|
|
7641
|
-
}
|
|
7642
7716
|
function buildScopeResolvers(usedLocals, context, slotProps, indexBindings) {
|
|
7643
7717
|
const resolvers = [];
|
|
7644
7718
|
for (const key of usedLocals) {
|
|
@@ -7800,7 +7874,7 @@ function createThisMemberAccess(prop) {
|
|
|
7800
7874
|
function createUnrefCall(exp) {
|
|
7801
7875
|
return t.callExpression(t.identifier("__wevuUnref"), [exp]);
|
|
7802
7876
|
}
|
|
7803
|
-
function createHasOwnPropertyCall(target, key) {
|
|
7877
|
+
function createHasOwnPropertyCall$1(target, key) {
|
|
7804
7878
|
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)]);
|
|
7805
7879
|
}
|
|
7806
7880
|
function createResolvePropValueCall(name, fallback, preferProps = false) {
|
|
@@ -7816,7 +7890,7 @@ function createPropsKeyAccessFallback(name, fallback) {
|
|
|
7816
7890
|
const propsObject = createThisMemberAccess(WEVU_PROPS_KEY);
|
|
7817
7891
|
const propsAccess = createMemberAccess(propsObject, name);
|
|
7818
7892
|
const hasPropsObject = t.binaryExpression("!=", propsObject, t.nullLiteral());
|
|
7819
|
-
const hasPropsValue = t.logicalExpression("&&", hasPropsObject, t.logicalExpression("||", t.binaryExpression("!==", propsAccess, t.identifier("undefined")), createHasOwnPropertyCall(propsObject, name)));
|
|
7893
|
+
const hasPropsValue = t.logicalExpression("&&", hasPropsObject, t.logicalExpression("||", t.binaryExpression("!==", propsAccess, t.identifier("undefined")), createHasOwnPropertyCall$1(propsObject, name)));
|
|
7820
7894
|
return t.conditionalExpression(hasPropsValue, propsAccess, fallback);
|
|
7821
7895
|
}
|
|
7822
7896
|
function createIdentifierAccessWithPropsFallback(name, context, useRuntimePropHelper = false) {
|
|
@@ -7838,10 +7912,10 @@ function createIdentifierAccessWithPropsFallback(name, context, useRuntimePropHe
|
|
|
7838
7912
|
const stateObject = createThisMemberAccess("$state");
|
|
7839
7913
|
const hasPropsObject = t.binaryExpression("!=", propsObject, t.nullLiteral());
|
|
7840
7914
|
const hasDefinedPropsValue = t.binaryExpression("!==", propsAccess, t.identifier("undefined"));
|
|
7841
|
-
const hasPropsKey = createHasOwnPropertyCall(propsObject, name);
|
|
7915
|
+
const hasPropsKey = createHasOwnPropertyCall$1(propsObject, name);
|
|
7842
7916
|
const hasUsablePropsValue = t.logicalExpression("&&", hasPropsObject, t.logicalExpression("||", hasDefinedPropsValue, hasPropsKey));
|
|
7843
7917
|
const hasStateObject = t.binaryExpression("!=", stateObject, t.nullLiteral());
|
|
7844
|
-
const hasStateKey = createHasOwnPropertyCall(stateObject, name);
|
|
7918
|
+
const hasStateKey = createHasOwnPropertyCall$1(stateObject, name);
|
|
7845
7919
|
const shouldUseStateAccess = Boolean(context.propsDerivedKeys?.includes(name)) ? t.booleanLiteral(false) : t.logicalExpression("&&", hasStateObject, hasStateKey);
|
|
7846
7920
|
return t.conditionalExpression(shouldUseStateAccess, thisAccess, t.conditionalExpression(hasUsablePropsValue, propsAccess, thisAccess));
|
|
7847
7921
|
}
|
|
@@ -7905,6 +7979,9 @@ function normalizeJsExpressionWithContext(exp, context, options) {
|
|
|
7905
7979
|
}
|
|
7906
7980
|
}
|
|
7907
7981
|
if (locals.has(name)) return;
|
|
7982
|
+
if (options?.preserveForItems && context.forStack.some((forInfo) => {
|
|
7983
|
+
return forInfo.item === name || forInfo.index === name || forInfo.key === name;
|
|
7984
|
+
})) return;
|
|
7908
7985
|
let replacement;
|
|
7909
7986
|
if (context.rewriteScopedSlot) {
|
|
7910
7987
|
if (hasOwn(slotProps, name)) {
|
|
@@ -7927,6 +8004,7 @@ function normalizeJsExpressionWithContext(exp, context, options) {
|
|
|
7927
8004
|
path.replaceWith(replacement);
|
|
7928
8005
|
path.skip();
|
|
7929
8006
|
} });
|
|
8007
|
+
rewriteForItemAccess(ast, context);
|
|
7930
8008
|
if (options?.unrefMemberAccess) traverse(ast, { MemberExpression: { exit(path) {
|
|
7931
8009
|
if (!shouldUnrefMemberAccess(path.node, path.parentPath?.node)) return;
|
|
7932
8010
|
path.replaceWith(createUnrefCall(t.cloneNode(path.node, true)));
|
|
@@ -7944,7 +8022,7 @@ function buildForIndexAccess$1(context) {
|
|
|
7944
8022
|
/**
|
|
7945
8023
|
* 检测表达式是否包含小程序模板不稳定的调用语义。
|
|
7946
8024
|
*/
|
|
7947
|
-
function shouldFallbackToRuntimeBinding(exp) {
|
|
8025
|
+
function shouldFallbackToRuntimeBinding(exp, templateSafeCallNames = /* @__PURE__ */ new Set()) {
|
|
7948
8026
|
const trimmed = exp.trim();
|
|
7949
8027
|
if (!trimmed) return false;
|
|
7950
8028
|
const parsed = parseBabelExpressionFile(normalizeWxmlExpression(trimmed));
|
|
@@ -7952,6 +8030,7 @@ function shouldFallbackToRuntimeBinding(exp) {
|
|
|
7952
8030
|
let shouldFallback = false;
|
|
7953
8031
|
traverse(parsed.ast, {
|
|
7954
8032
|
CallExpression(path) {
|
|
8033
|
+
if (path.node.callee.type === "Identifier" && templateSafeCallNames.has(path.node.callee.name)) return;
|
|
7955
8034
|
shouldFallback = true;
|
|
7956
8035
|
path.stop();
|
|
7957
8036
|
},
|
|
@@ -7963,6 +8042,10 @@ function shouldFallbackToRuntimeBinding(exp) {
|
|
|
7963
8042
|
if (path.node.operator !== "typeof") return;
|
|
7964
8043
|
shouldFallback = true;
|
|
7965
8044
|
path.stop();
|
|
8045
|
+
},
|
|
8046
|
+
BigIntLiteral(path) {
|
|
8047
|
+
shouldFallback = true;
|
|
8048
|
+
path.stop();
|
|
7966
8049
|
}
|
|
7967
8050
|
});
|
|
7968
8051
|
return shouldFallback;
|
|
@@ -8140,10 +8223,161 @@ function renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context) {
|
|
|
8140
8223
|
function transformAttribute(node, _context) {
|
|
8141
8224
|
const { name, value } = node;
|
|
8142
8225
|
if (!value) return name;
|
|
8143
|
-
if (value.type === NodeTypes.TEXT) return `${name}="${value.content}"`;
|
|
8226
|
+
if (value.type === NodeTypes.TEXT) return `${name}="${escapeWxmlAttribute(value.content)}"`;
|
|
8144
8227
|
return `${name}=""`;
|
|
8145
8228
|
}
|
|
8146
8229
|
//#endregion
|
|
8230
|
+
//#region src/plugins/vue/compiler/template/directives/forKey/projection.ts
|
|
8231
|
+
function createConsoleErrorGuard(message, errorId) {
|
|
8232
|
+
return t.ifStatement(t.logicalExpression("&&", t.binaryExpression("!==", t.unaryExpression("typeof", t.identifier("console")), t.stringLiteral("undefined")), t.binaryExpression("===", t.unaryExpression("typeof", t.memberExpression(t.identifier("console"), t.identifier("error"))), t.stringLiteral("function"))), t.blockStatement([t.expressionStatement(t.callExpression(t.memberExpression(t.identifier("console"), t.identifier("error")), [t.stringLiteral(message), t.cloneNode(errorId)]))]));
|
|
8233
|
+
}
|
|
8234
|
+
function createConsoleWarnGuard(message, item) {
|
|
8235
|
+
return t.ifStatement(t.logicalExpression("&&", t.binaryExpression("!==", t.unaryExpression("typeof", t.identifier("console")), t.stringLiteral("undefined")), t.binaryExpression("===", t.unaryExpression("typeof", t.memberExpression(t.identifier("console"), t.identifier("warn"))), t.stringLiteral("function"))), t.blockStatement([t.expressionStatement(t.callExpression(t.memberExpression(t.identifier("console"), t.identifier("warn")), [t.stringLiteral(message), t.cloneNode(item)]))]));
|
|
8236
|
+
}
|
|
8237
|
+
function createHasOwnPropertyCall(item, field) {
|
|
8238
|
+
return t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier("Object"), t.identifier("prototype")), t.identifier("hasOwnProperty")), t.identifier("call")), [t.cloneNode(item), t.stringLiteral(field)]);
|
|
8239
|
+
}
|
|
8240
|
+
function createSafeKeyExpression(exp, rawExp, seed, item) {
|
|
8241
|
+
const errorId = t.identifier(`__wv_for_key_error_${seed}`);
|
|
8242
|
+
const shouldReportError = item ? t.binaryExpression("!=", t.cloneNode(item), t.nullLiteral()) : t.booleanLiteral(true);
|
|
8243
|
+
return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.tryStatement(t.blockStatement([t.returnStatement(t.cloneNode(exp, true))]), t.catchClause(errorId, t.blockStatement([t.ifStatement(shouldReportError, t.blockStatement([createConsoleErrorGuard(`[wevu] v-for :key 表达式执行失败: ${rawExp}`, errorId)])), t.returnStatement(t.identifier("undefined"))])), null)])), []);
|
|
8244
|
+
}
|
|
8245
|
+
function createProjectedItemExpression(item, keyExp, rawKeyExp, keyField, valueField, seed) {
|
|
8246
|
+
const isObject = t.logicalExpression("&&", t.binaryExpression("!=", t.cloneNode(item), t.nullLiteral()), t.binaryExpression("===", t.unaryExpression("typeof", t.cloneNode(item)), t.stringLiteral("object")));
|
|
8247
|
+
const projected = t.callExpression(t.arrowFunctionExpression([], t.blockStatement([t.ifStatement(t.logicalExpression("||", createHasOwnPropertyCall(item, keyField), createHasOwnPropertyCall(item, valueField)), t.blockStatement([createConsoleWarnGuard(`[wevu] v-for :key 内部字段冲突,投影将使用保留字段 ${keyField} / ${valueField}`, item)])), t.returnStatement(t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("assign")), [
|
|
8248
|
+
t.objectExpression([]),
|
|
8249
|
+
t.cloneNode(item),
|
|
8250
|
+
t.objectExpression([t.objectProperty(t.stringLiteral(valueField), t.cloneNode(item)), t.objectProperty(t.stringLiteral(keyField), createSafeKeyExpression(keyExp, rawKeyExp, seed, item))])
|
|
8251
|
+
]))])), []);
|
|
8252
|
+
const primitiveProjected = t.objectExpression([t.objectProperty(t.stringLiteral(valueField), t.cloneNode(item)), t.objectProperty(t.stringLiteral(keyField), createSafeKeyExpression(keyExp, rawKeyExp, seed, item))]);
|
|
8253
|
+
return t.conditionalExpression(isObject, projected, primitiveProjected);
|
|
8254
|
+
}
|
|
8255
|
+
function createArrayProjection(sourceId, keyExp, rawKeyExp, keyField, valueField, forInfo, seed) {
|
|
8256
|
+
const itemId = forInfo.item && t.isValidIdentifier(forInfo.item) ? t.identifier(forInfo.item) : t.identifier(`__wv_for_key_item_${seed}`);
|
|
8257
|
+
const indexId = forInfo.index && t.isValidIdentifier(forInfo.index) ? t.identifier(forInfo.index) : t.identifier(`__wv_for_key_index_${seed}`);
|
|
8258
|
+
const body = [];
|
|
8259
|
+
if (forInfo.key && t.isValidIdentifier(forInfo.key) && forInfo.key !== indexId.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(forInfo.key), t.cloneNode(indexId))]));
|
|
8260
|
+
body.push(t.returnStatement(createProjectedItemExpression(itemId, keyExp, rawKeyExp, keyField, valueField, seed)));
|
|
8261
|
+
return t.callExpression(t.memberExpression(t.cloneNode(sourceId), t.identifier("map")), [t.arrowFunctionExpression([itemId, indexId], t.blockStatement(body))]);
|
|
8262
|
+
}
|
|
8263
|
+
function createObjectProjection(sourceId, keyExp, rawKeyExp, keyField, valueField, forInfo, seed) {
|
|
8264
|
+
const resultId = t.identifier(`__wv_for_key_result_${seed}`);
|
|
8265
|
+
const keysId = t.identifier(`__wv_for_key_keys_${seed}`);
|
|
8266
|
+
const loopIndexId = t.identifier(`__wv_for_key_loop_index_${seed}`);
|
|
8267
|
+
const sourceKeyId = t.identifier(`__wv_for_key_source_key_${seed}`);
|
|
8268
|
+
const sourceItemId = t.identifier(`__wv_for_key_source_item_${seed}`);
|
|
8269
|
+
const body = [t.variableDeclaration("const", [t.variableDeclarator(sourceKeyId, t.memberExpression(keysId, loopIndexId, true))]), t.variableDeclaration("const", [t.variableDeclarator(sourceItemId, t.memberExpression(sourceId, sourceKeyId, true))])];
|
|
8270
|
+
if (forInfo.item && t.isValidIdentifier(forInfo.item) && forInfo.item !== sourceItemId.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(forInfo.item), t.cloneNode(sourceItemId))]));
|
|
8271
|
+
if (forInfo.key && t.isValidIdentifier(forInfo.key) && forInfo.key !== sourceKeyId.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(forInfo.key), t.cloneNode(sourceKeyId))]));
|
|
8272
|
+
if (forInfo.index && t.isValidIdentifier(forInfo.index)) {
|
|
8273
|
+
const source = forInfo.key ? loopIndexId : sourceKeyId;
|
|
8274
|
+
if (forInfo.index !== source.name) body.push(t.variableDeclaration("const", [t.variableDeclarator(t.identifier(forInfo.index), t.cloneNode(source))]));
|
|
8275
|
+
}
|
|
8276
|
+
body.push(t.expressionStatement(t.assignmentExpression("=", t.memberExpression(resultId, sourceKeyId, true), createProjectedItemExpression(sourceItemId, keyExp, rawKeyExp, keyField, valueField, seed))));
|
|
8277
|
+
return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([
|
|
8278
|
+
t.variableDeclaration("const", [t.variableDeclarator(resultId, t.objectExpression([]))]),
|
|
8279
|
+
t.variableDeclaration("const", [t.variableDeclarator(keysId, t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("keys")), [t.cloneNode(sourceId)]))]),
|
|
8280
|
+
t.forStatement(t.variableDeclaration("let", [t.variableDeclarator(loopIndexId, t.numericLiteral(0))]), t.binaryExpression("<", loopIndexId, t.memberExpression(keysId, t.identifier("length"))), t.updateExpression("++", loopIndexId), t.blockStatement(body)),
|
|
8281
|
+
t.returnStatement(resultId)
|
|
8282
|
+
])), []);
|
|
8283
|
+
}
|
|
8284
|
+
function createForKeyProjectionExpression(sourceExp, keyExp, rawKeyExp, keyField, valueField, forInfo, seed) {
|
|
8285
|
+
const sourceId = t.identifier(`__wv_for_key_source_${seed}`);
|
|
8286
|
+
const objectCheck = t.logicalExpression("&&", t.binaryExpression("!=", t.cloneNode(sourceId), t.nullLiteral()), t.binaryExpression("===", t.unaryExpression("typeof", t.cloneNode(sourceId)), t.stringLiteral("object")));
|
|
8287
|
+
return t.callExpression(t.arrowFunctionExpression([], t.blockStatement([
|
|
8288
|
+
t.variableDeclaration("const", [t.variableDeclarator(sourceId, t.cloneNode(sourceExp, true))]),
|
|
8289
|
+
t.ifStatement(t.callExpression(t.memberExpression(t.identifier("Array"), t.identifier("isArray")), [t.cloneNode(sourceId)]), t.blockStatement([t.returnStatement(createArrayProjection(sourceId, keyExp, rawKeyExp, keyField, valueField, forInfo, seed))])),
|
|
8290
|
+
t.ifStatement(objectCheck, t.blockStatement([t.returnStatement(createObjectProjection(sourceId, keyExp, rawKeyExp, keyField, valueField, forInfo, seed))])),
|
|
8291
|
+
t.returnStatement(t.cloneNode(sourceId))
|
|
8292
|
+
])), []);
|
|
8293
|
+
}
|
|
8294
|
+
//#endregion
|
|
8295
|
+
//#region src/plugins/vue/compiler/template/directives/forKey/index.ts
|
|
8296
|
+
const SIMPLE_IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
|
|
8297
|
+
const SIMPLE_MEMBER_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
|
|
8298
|
+
const RUNTIME_BINDING_REF_RE = /^__wv_bind_\d+(?:\[[A-Z_$][\w$]*\])*$/i;
|
|
8299
|
+
function createSourceContext(context) {
|
|
8300
|
+
return {
|
|
8301
|
+
...context,
|
|
8302
|
+
forStack: context.forStack.map((forInfo) => ({
|
|
8303
|
+
...forInfo,
|
|
8304
|
+
itemAccess: void 0
|
|
8305
|
+
}))
|
|
8306
|
+
};
|
|
8307
|
+
}
|
|
8308
|
+
function hasKnownPrimitiveItems(exp) {
|
|
8309
|
+
if (t.isStringLiteral(exp) || t.isNumericLiteral(exp) || t.isBooleanLiteral(exp) || t.isNullLiteral(exp)) return true;
|
|
8310
|
+
if (!t.isArrayExpression(exp)) return false;
|
|
8311
|
+
return exp.elements.every((element) => {
|
|
8312
|
+
return element == null || t.isStringLiteral(element) || t.isNumericLiteral(element) || t.isBooleanLiteral(element) || t.isNullLiteral(element);
|
|
8313
|
+
});
|
|
8314
|
+
}
|
|
8315
|
+
function resolveItemAliasKeyField(trimmed, forInfo) {
|
|
8316
|
+
const aliasExp = forInfo.itemAliases?.[trimmed]?.trim();
|
|
8317
|
+
if (!aliasExp || !forInfo.item || !aliasExp.startsWith(`${forInfo.item}.`)) return null;
|
|
8318
|
+
const remainder = aliasExp.slice(forInfo.item.length + 1);
|
|
8319
|
+
return SIMPLE_MEMBER_PATH_RE.test(remainder) && !remainder.includes(".") ? remainder : null;
|
|
8320
|
+
}
|
|
8321
|
+
function resolveNativeForKeyValue(exp, forInfo, keyThisValue) {
|
|
8322
|
+
const trimmed = exp.trim();
|
|
8323
|
+
if (!forInfo) return null;
|
|
8324
|
+
if (forInfo.item && trimmed === forInfo.item || forInfo.key && trimmed === forInfo.key) return keyThisValue;
|
|
8325
|
+
if (forInfo.item && trimmed.startsWith(`${forInfo.item}.`)) {
|
|
8326
|
+
const remainder = trimmed.slice(forInfo.item.length + 1);
|
|
8327
|
+
if (SIMPLE_MEMBER_PATH_RE.test(remainder) && !remainder.includes(".")) return remainder;
|
|
8328
|
+
return null;
|
|
8329
|
+
}
|
|
8330
|
+
if (SIMPLE_IDENTIFIER_RE$1.test(trimmed)) {
|
|
8331
|
+
if (forInfo.index === trimmed) return trimmed;
|
|
8332
|
+
return resolveItemAliasKeyField(trimmed, forInfo);
|
|
8333
|
+
}
|
|
8334
|
+
return null;
|
|
8335
|
+
}
|
|
8336
|
+
function createForKeyProjection(node, forInfo, context) {
|
|
8337
|
+
const rawKeyExp = getBindDirectiveExpression(node).trim();
|
|
8338
|
+
if (!rawKeyExp || !forInfo.listExp || resolveNativeForKeyValue(rawKeyExp, forInfo, context.platform.keyThisValue)) return null;
|
|
8339
|
+
const listExp = forInfo.listExp?.trim() ?? "";
|
|
8340
|
+
const rawListExp = forInfo.rawListExp?.trim() || listExp;
|
|
8341
|
+
const projectionListExp = RUNTIME_BINDING_REF_RE.test(listExp) ? listExp : rawListExp;
|
|
8342
|
+
const sourceContext = createSourceContext(context);
|
|
8343
|
+
const projectionSourceAst = RUNTIME_BINDING_REF_RE.test(projectionListExp) ? normalizeJsExpressionWithContext(projectionListExp, sourceContext, {
|
|
8344
|
+
hint: "v-for :key 数据源",
|
|
8345
|
+
runtimePropAccess: "helper",
|
|
8346
|
+
unrefMemberAccess: true,
|
|
8347
|
+
preserveForItems: true
|
|
8348
|
+
}) : normalizeJsExpressionWithContext(projectionListExp, sourceContext, {
|
|
8349
|
+
hint: "v-for :key 数据源",
|
|
8350
|
+
preserveForItems: true
|
|
8351
|
+
});
|
|
8352
|
+
if (!projectionSourceAst) return null;
|
|
8353
|
+
if (hasKnownPrimitiveItems(projectionSourceAst)) return null;
|
|
8354
|
+
const keyExpAst = normalizeJsExpressionWithContext(rawKeyExp, sourceContext, {
|
|
8355
|
+
hint: "v-for :key",
|
|
8356
|
+
runtimePropAccess: "helper",
|
|
8357
|
+
unrefMemberAccess: true,
|
|
8358
|
+
preserveForItems: true
|
|
8359
|
+
});
|
|
8360
|
+
if (!keyExpAst) return null;
|
|
8361
|
+
const bindingSeed = context.classStyleBindings.filter((binding) => binding.type === "bind").length;
|
|
8362
|
+
const bindingName = `__wv_bind_${bindingSeed}`;
|
|
8363
|
+
const keyField = `__wv_key_${bindingSeed}`;
|
|
8364
|
+
const valueField = `__wv_value_${bindingSeed}`;
|
|
8365
|
+
const outerForStack = context.forStack.slice(0, -1).map((info) => ({ ...info }));
|
|
8366
|
+
context.classStyleBindings.push({
|
|
8367
|
+
name: bindingName,
|
|
8368
|
+
type: "bind",
|
|
8369
|
+
exp: `v-for :key ${rawKeyExp}`,
|
|
8370
|
+
expAst: createForKeyProjectionExpression(projectionSourceAst, keyExpAst, rawKeyExp, keyField, valueField, forInfo, bindingSeed),
|
|
8371
|
+
forStack: outerForStack
|
|
8372
|
+
});
|
|
8373
|
+
const indexAccess = outerForStack.map((info) => `[${info.index ?? "index"}]`).join("");
|
|
8374
|
+
return {
|
|
8375
|
+
keyAttr: context.platform.keyAttr(keyField),
|
|
8376
|
+
listExp: `${bindingName}${indexAccess}`,
|
|
8377
|
+
itemAccess: `${forInfo.item}.${valueField}`
|
|
8378
|
+
};
|
|
8379
|
+
}
|
|
8380
|
+
//#endregion
|
|
8147
8381
|
//#region src/plugins/vue/compiler/template/directives/bind.ts
|
|
8148
8382
|
function unwrapTsExpression(node) {
|
|
8149
8383
|
if (node.type === "TSAsExpression" || node.type === "TSNonNullExpression" || node.type === "TSTypeAssertion") return unwrapTsExpression(node.expression);
|
|
@@ -8190,10 +8424,6 @@ function createInlineObjectLiteralAttr(argValue, rawExpValue, context) {
|
|
|
8190
8424
|
if (context.mustacheInterpolation === "spaced") return `${argValue}="${renderMustache(expValue, context)}"`;
|
|
8191
8425
|
return `${argValue}="{{ ${expValue} }}"`;
|
|
8192
8426
|
}
|
|
8193
|
-
const SIMPLE_IDENTIFIER_RE$1 = /^[A-Z_$][\w$]*$/i;
|
|
8194
|
-
const SIMPLE_MEMBER_PATH_RE = /^[A-Z_$][\w$]*(?:\.[A-Z_$][\w$]*)*$/i;
|
|
8195
|
-
const isSimpleIdentifier = (value) => SIMPLE_IDENTIFIER_RE$1.test(value);
|
|
8196
|
-
const isSimpleMemberPath = (value) => SIMPLE_MEMBER_PATH_RE.test(value);
|
|
8197
8427
|
const COMPONENT_NON_PROP_BINDINGS = /* @__PURE__ */ new Set([
|
|
8198
8428
|
"class",
|
|
8199
8429
|
"style",
|
|
@@ -8265,24 +8495,10 @@ function transformBindDirective(node, context, forInfo, options) {
|
|
|
8265
8495
|
if (argValue === "key") {
|
|
8266
8496
|
const expValue = normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
8267
8497
|
const trimmed = expValue.trim();
|
|
8268
|
-
const
|
|
8269
|
-
|
|
8270
|
-
context.warnings.push(`v-for :key "${trimmed}" ${reason},已降级为 ${context.platform.keyAttr(context.platform.keyThisValue)}。建议使用稳定的基础类型 key(例如 item.id)。`);
|
|
8271
|
-
};
|
|
8272
|
-
if (forInfo?.item && trimmed === forInfo.item) return context.platform.keyAttr(context.platform.keyThisValue);
|
|
8273
|
-
if (forInfo?.key && trimmed === forInfo.key) return context.platform.keyAttr(context.platform.keyThisValue);
|
|
8274
|
-
if (forInfo?.item && trimmed.startsWith(`${forInfo.item}.`)) {
|
|
8275
|
-
const remainder = trimmed.slice(forInfo.item.length + 1);
|
|
8276
|
-
if (isSimpleMemberPath(remainder)) {
|
|
8277
|
-
const firstSegment = remainder.split(".")[0] || remainder;
|
|
8278
|
-
return context.platform.keyAttr(firstSegment);
|
|
8279
|
-
}
|
|
8280
|
-
warnKeyFallback("不是简单的成员路径");
|
|
8281
|
-
return context.platform.keyAttr(context.platform.keyThisValue);
|
|
8282
|
-
}
|
|
8283
|
-
if (isSimpleIdentifier(trimmed)) return context.platform.keyAttr(trimmed);
|
|
8498
|
+
const nativeKeyValue = resolveNativeForKeyValue(trimmed, forInfo, context.platform.keyThisValue);
|
|
8499
|
+
if (nativeKeyValue) return context.platform.keyAttr(nativeKeyValue);
|
|
8284
8500
|
if (forInfo) {
|
|
8285
|
-
|
|
8501
|
+
context.warnings.push(`v-for :key "${trimmed}" 无法生成运行时 key 投影,已降级为 ${context.platform.keyAttr(context.platform.keyThisValue)}。建议使用稳定的基础类型 key。`);
|
|
8286
8502
|
return context.platform.keyAttr(context.platform.keyThisValue);
|
|
8287
8503
|
}
|
|
8288
8504
|
return context.platform.keyAttr(expValue);
|
|
@@ -8291,7 +8507,7 @@ function transformBindDirective(node, context, forInfo, options) {
|
|
|
8291
8507
|
if (context.objectLiteralBindMode === "inline" || isStaticObjectLiteral(rawExpValue)) return createInlineObjectLiteralAttr(argValue, rawExpValue, context);
|
|
8292
8508
|
return createBindRuntimeAttr(argValue, rawExpValue, context);
|
|
8293
8509
|
}
|
|
8294
|
-
if (shouldFallbackToRuntimeBinding(rawExpValue)) {
|
|
8510
|
+
if (shouldFallbackToRuntimeBinding(rawExpValue, context.templateSafeCallNames)) {
|
|
8295
8511
|
const runtimeAttr = createBindRuntimeAttr(argValue, rawExpValue, context);
|
|
8296
8512
|
if (runtimeAttr) return runtimeAttr;
|
|
8297
8513
|
}
|
|
@@ -8335,7 +8551,6 @@ function getElementType(element) {
|
|
|
8335
8551
|
}
|
|
8336
8552
|
return "";
|
|
8337
8553
|
}
|
|
8338
|
-
const QUOTE_RE$1 = /"/g;
|
|
8339
8554
|
const CAMELIZE_RE = /-([a-z0-9])/gi;
|
|
8340
8555
|
const IDENTIFIER_RE = /^[A-Z_$][\w$]*$/i;
|
|
8341
8556
|
const NATIVE_MODEL_TAGS = /* @__PURE__ */ new Set([
|
|
@@ -8359,7 +8574,7 @@ function isNativeModelElement(element) {
|
|
|
8359
8574
|
return NATIVE_MODEL_TAGS.has(element.tag);
|
|
8360
8575
|
}
|
|
8361
8576
|
function transformVModel(element, expValue, context) {
|
|
8362
|
-
const escapedModel = expValue
|
|
8577
|
+
const escapedModel = escapeWxmlAttribute(expValue);
|
|
8363
8578
|
const bindModel = (event) => {
|
|
8364
8579
|
return `${context.platform.eventBindingAttr(event)}="${WEVU_MODEL_HANDLER}" data-wv-model="${escapedModel}"`;
|
|
8365
8580
|
};
|
|
@@ -8437,15 +8652,14 @@ function isScriptSetupHandlerBinding(value, context) {
|
|
|
8437
8652
|
function shouldUseDetailPayload(options) {
|
|
8438
8653
|
return options?.isComponent === true;
|
|
8439
8654
|
}
|
|
8440
|
-
const QUOTE_RE = /"/g;
|
|
8441
8655
|
function buildInlineScopeAttrs(scopeBindings, context) {
|
|
8442
8656
|
return scopeBindings.map((binding, index) => {
|
|
8443
|
-
return `data-wv-s${index}="${renderMustache(binding
|
|
8657
|
+
return `data-wv-s${index}="${renderMustache(escapeWxmlAttribute(binding), context)}"`;
|
|
8444
8658
|
});
|
|
8445
8659
|
}
|
|
8446
8660
|
function buildInlineIndexAttrs(indexBindings, context) {
|
|
8447
8661
|
return indexBindings.map((binding, index) => {
|
|
8448
|
-
return `data-wv-i${index}="${renderMustache(binding
|
|
8662
|
+
return `data-wv-i${index}="${renderMustache(escapeWxmlAttribute(binding), context)}"`;
|
|
8449
8663
|
});
|
|
8450
8664
|
}
|
|
8451
8665
|
function resolveEventPrefix(modifiers) {
|
|
@@ -8510,7 +8724,7 @@ function transformOnDirective(node, context, options) {
|
|
|
8510
8724
|
}
|
|
8511
8725
|
if (isInlineExpression) return [
|
|
8512
8726
|
detailAttr,
|
|
8513
|
-
`data-wv-inline-${eventSuffix}="${inlineSource
|
|
8727
|
+
`data-wv-inline-${eventSuffix}="${escapeWxmlAttribute(inlineSource)}"`,
|
|
8514
8728
|
`${bindAttr}="${WEVU_INLINE_HANDLER}"`
|
|
8515
8729
|
].filter(Boolean).join(" ");
|
|
8516
8730
|
return [detailAttr, `${bindAttr}="${expValue}"`].filter(Boolean).join(" ");
|
|
@@ -8557,6 +8771,7 @@ function collectElementAttributes(node, context, options) {
|
|
|
8557
8771
|
const resolvedTag = options?.resolvedTag ?? resolveTemplateTagName(node.tag, context);
|
|
8558
8772
|
const isComponentElement = options?.isComponent ?? !isBuiltinTag(resolvedTag);
|
|
8559
8773
|
const attrs = options?.extraAttrs ? [...options.extraAttrs] : [];
|
|
8774
|
+
if (context.scopeId) attrs.push(`${context.scopeId}=""`);
|
|
8560
8775
|
const mappedTagClass = resolveMappedHtmlTagClassName(node.tag, context, resolvedTag);
|
|
8561
8776
|
let staticClass;
|
|
8562
8777
|
let staticId;
|
|
@@ -8636,7 +8851,7 @@ function collectElementAttributes(node, context, options) {
|
|
|
8636
8851
|
}
|
|
8637
8852
|
if (prop.name === "text" && prop.exp?.type === NodeTypes.SIMPLE_EXPRESSION) {
|
|
8638
8853
|
const rawExp = prop.exp.content;
|
|
8639
|
-
vTextExp = (shouldFallbackToRuntimeBinding(rawExp) ? registerRuntimeBindingExpression(rawExp, context, { hint: "v-text" }) : null) ?? normalizeWxmlExpressionWithContext(rawExp, context);
|
|
8854
|
+
vTextExp = (shouldFallbackToRuntimeBinding(rawExp, context.templateSafeCallNames) ? registerRuntimeBindingExpression(rawExp, context, { hint: "v-text" }) : null) ?? normalizeWxmlExpressionWithContext(rawExp, context);
|
|
8640
8855
|
continue;
|
|
8641
8856
|
}
|
|
8642
8857
|
const dir = transformDirective(prop, context, node, options?.forInfo, { isComponent: isComponentElement });
|
|
@@ -8680,7 +8895,7 @@ function collectElementAttributes(node, context, options) {
|
|
|
8680
8895
|
if (staticId) attrs.unshift(`id="${staticId}"`);
|
|
8681
8896
|
const classAttr = renderClassAttribute(staticClass, dynamicClassExp, context);
|
|
8682
8897
|
if (classAttr) attrs.unshift(classAttr);
|
|
8683
|
-
const styleAttr = renderStyleAttribute(staticStyle, dynamicStyleExp, vShowExp, context);
|
|
8898
|
+
const styleAttr = renderStyleAttribute(staticStyle, context.cssVars ? dynamicStyleExp ? `[${dynamicStyleExp}, ${WEVU_CSS_VARS_STYLE_KEY}]` : WEVU_CSS_VARS_STYLE_KEY : dynamicStyleExp, vShowExp, context);
|
|
8684
8899
|
if (styleAttr) attrs.unshift(styleAttr);
|
|
8685
8900
|
return {
|
|
8686
8901
|
attrs,
|
|
@@ -9039,6 +9254,7 @@ function renderPlainSlotOutlet(node, context, transformNode) {
|
|
|
9039
9254
|
if (hasScopeBindings) context.warnings.push("已禁用作用域插槽参数,插槽绑定将被忽略。");
|
|
9040
9255
|
const fallbackContent = node.children.map((child) => transformNode(child, context)).join("");
|
|
9041
9256
|
const slotAttrs = [];
|
|
9257
|
+
if (context.slottedScopeId) slotAttrs.push(`${context.slottedScopeId}=""`);
|
|
9042
9258
|
const nameAttr = renderSlotNameAttribute(slotNameInfo, context, "name");
|
|
9043
9259
|
if (nameAttr) slotAttrs.push(nameAttr);
|
|
9044
9260
|
const slotAttrString = slotAttrs.length ? ` ${slotAttrs.join(" ")}` : "";
|
|
@@ -9103,6 +9319,7 @@ function transformSlotElement(node, context, transformNode) {
|
|
|
9103
9319
|
let fallbackContent = "";
|
|
9104
9320
|
if (node.children.length > 0) fallbackContent = node.children.map((child) => transformNode(child, context)).join("");
|
|
9105
9321
|
const slotAttrs = [];
|
|
9322
|
+
if (context.slottedScopeId) slotAttrs.push(`${context.slottedScopeId}=""`);
|
|
9106
9323
|
const nameAttr = renderSlotNameAttribute(slotNameInfo, context, "name");
|
|
9107
9324
|
if (nameAttr) slotAttrs.push(nameAttr);
|
|
9108
9325
|
const slotAttrString = slotAttrs.length ? ` ${slotAttrs.join(" ")}` : "";
|
|
@@ -9122,6 +9339,7 @@ function transformSlotElement(node, context, transformNode) {
|
|
|
9122
9339
|
`${WEVU_SLOT_OWNER_ID_ATTR}="${renderMustache(WEVU_SLOT_OWNER_ID_PROP, context)}"`,
|
|
9123
9340
|
`${WEVU_SLOT_PROPS_ATTR}="${renderMustache(slotPropsExp, context)}"`
|
|
9124
9341
|
];
|
|
9342
|
+
if (context.slottedScopeId) scopedAttrs.push(`${context.slottedScopeId}=""`);
|
|
9125
9343
|
if (context.slotMultipleInstance) scopedAttrs.push(`${WEVU_SLOT_SCOPE_ATTR}="${renderMustache(WEVU_SLOT_SCOPE_KEY, context)}"`);
|
|
9126
9344
|
const scopedTag = `<${genericKey}${scopedAttrs.length ? ` ${scopedAttrs.join(" ")}` : ""} />`;
|
|
9127
9345
|
const nativeFallbackTag = context.forStack.length > 0 ? "" : context.platform.wrapIf(`!${WEVU_SLOT_OWNER_ID_PROP}`, slotTag, (exp) => renderMustache(exp, context));
|
|
@@ -9598,10 +9816,26 @@ function transformNormalElement(node, context, transformNode) {
|
|
|
9598
9816
|
//#region src/plugins/vue/compiler/template/elements/tag-structural.ts
|
|
9599
9817
|
const REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
|
|
9600
9818
|
function resolveConditionExpression$1(rawExpValue, context, hint) {
|
|
9601
|
-
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9819
|
+
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue, context.templateSafeCallNames) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9602
9820
|
}
|
|
9603
9821
|
function resolveListExpression(rawExpValue, context, hint) {
|
|
9604
|
-
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9822
|
+
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue, context.templateSafeCallNames) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9823
|
+
}
|
|
9824
|
+
function requiresRuntimeForKeyProjection(node, context) {
|
|
9825
|
+
const forDirective = node.props.find((prop) => {
|
|
9826
|
+
return prop.type === NodeTypes.DIRECTIVE && prop.name === "for";
|
|
9827
|
+
});
|
|
9828
|
+
const keyDirective = node.props.find((prop) => {
|
|
9829
|
+
return prop.type === NodeTypes.DIRECTIVE && prop.name === "bind" && prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION && prop.arg.content === "key";
|
|
9830
|
+
});
|
|
9831
|
+
if (forDirective?.exp?.type === NodeTypes.SIMPLE_EXPRESSION && keyDirective) {
|
|
9832
|
+
const forInfo = parseForExpression(forDirective.exp.content);
|
|
9833
|
+
const rawKeyExp = getBindDirectiveExpression(keyDirective).trim();
|
|
9834
|
+
if (rawKeyExp && !resolveNativeForKeyValue(rawKeyExp, forInfo, context.platform.keyThisValue)) return true;
|
|
9835
|
+
}
|
|
9836
|
+
return node.children.some((child) => {
|
|
9837
|
+
return child.type === NodeTypes.ELEMENT && requiresRuntimeForKeyProjection(child, context);
|
|
9838
|
+
});
|
|
9605
9839
|
}
|
|
9606
9840
|
function transformIfElement(node, context, transformNode) {
|
|
9607
9841
|
const renderTemplateMustache = (exp) => renderMustache(exp, context);
|
|
@@ -9643,15 +9877,18 @@ function transformForElement(node, context, transformNode) {
|
|
|
9643
9877
|
}));
|
|
9644
9878
|
}
|
|
9645
9879
|
}
|
|
9646
|
-
if (context.classStyleRuntime === "js" && !forInfo.index) forInfo.index = `__wv_index_${context.forIndexSeed++}`;
|
|
9880
|
+
if ((context.classStyleRuntime === "js" || requiresRuntimeForKeyProjection(node, context)) && !forInfo.index) forInfo.index = `__wv_index_${context.forIndexSeed++}`;
|
|
9881
|
+
const rawListExp = forInfo.listExp?.trim();
|
|
9647
9882
|
const listExp = forInfo.listExp ? resolveListExpression(forInfo.listExp, context, "v-for 列表") : void 0;
|
|
9648
9883
|
const listExpAst = forInfo.listExp ? normalizeJsExpressionWithContext(forInfo.listExp, context, { hint: "v-for 列表" }) : void 0;
|
|
9649
9884
|
const scopedForInfo = listExp ? {
|
|
9650
9885
|
...forInfo,
|
|
9651
9886
|
listExp,
|
|
9887
|
+
rawListExp,
|
|
9652
9888
|
listExpAst: listExpAst ?? void 0
|
|
9653
9889
|
} : {
|
|
9654
9890
|
...forInfo,
|
|
9891
|
+
rawListExp,
|
|
9655
9892
|
listExpAst: listExpAst ?? void 0
|
|
9656
9893
|
};
|
|
9657
9894
|
const scopeNames = [
|
|
@@ -9666,34 +9903,64 @@ function transformForElement(node, context, transformNode) {
|
|
|
9666
9903
|
...node,
|
|
9667
9904
|
props: otherProps
|
|
9668
9905
|
};
|
|
9669
|
-
const
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9906
|
+
const keyDirective = otherProps.find((prop) => {
|
|
9907
|
+
return prop.type === NodeTypes.DIRECTIVE && prop.name === "bind" && prop.arg?.type === NodeTypes.SIMPLE_EXPRESSION && prop.arg.content === "key";
|
|
9908
|
+
});
|
|
9909
|
+
const keyProjection = keyDirective ? createForKeyProjection(keyDirective, scopedForInfo, context) : null;
|
|
9910
|
+
if (keyProjection) {
|
|
9911
|
+
scopedForInfo.itemAccess = keyProjection.itemAccess;
|
|
9912
|
+
const projectionContext = {
|
|
9913
|
+
...context,
|
|
9914
|
+
forStack: context.forStack.map((forInfo) => ({
|
|
9915
|
+
...forInfo,
|
|
9916
|
+
itemAccess: void 0
|
|
9917
|
+
}))
|
|
9918
|
+
};
|
|
9919
|
+
const projectedListExpAst = normalizeJsExpressionWithContext(keyProjection.listExp, projectionContext, {
|
|
9920
|
+
hint: "v-for 投影列表",
|
|
9921
|
+
runtimePropAccess: "helper",
|
|
9922
|
+
unrefMemberAccess: true,
|
|
9923
|
+
preserveForItems: true
|
|
9673
9924
|
});
|
|
9925
|
+
scopedForInfo.projectedListExp = keyProjection.listExp;
|
|
9926
|
+
scopedForInfo.projectedListExpAst = projectedListExpAst ?? scopedForInfo.projectedListExpAst;
|
|
9927
|
+
const currentForInfo = context.forStack[context.forStack.length - 1];
|
|
9928
|
+
if (currentForInfo) {
|
|
9929
|
+
currentForInfo.itemAccess = keyProjection.itemAccess;
|
|
9930
|
+
currentForInfo.projectedListExp = scopedForInfo.projectedListExp;
|
|
9931
|
+
currentForInfo.projectedListExpAst = scopedForInfo.projectedListExpAst;
|
|
9932
|
+
}
|
|
9933
|
+
}
|
|
9934
|
+
const renderElement = keyProjection ? {
|
|
9935
|
+
...elementWithoutFor,
|
|
9936
|
+
props: otherProps.filter((prop) => prop !== keyDirective)
|
|
9937
|
+
} : elementWithoutFor;
|
|
9938
|
+
const templateListExp = keyProjection?.listExp ?? listExp;
|
|
9939
|
+
const extraAttrs = templateListExp ? context.platform.forAttrs(templateListExp, renderTemplateMustache, forInfo.item, forInfo.index) : [];
|
|
9940
|
+
if (keyProjection) extraAttrs.push(keyProjection.keyAttr);
|
|
9941
|
+
if (renderElement.tag === "slot") {
|
|
9942
|
+
const slotKeyDirective = keyProjection ? void 0 : keyDirective;
|
|
9674
9943
|
const content = transformSlotElement({
|
|
9675
|
-
...
|
|
9676
|
-
props:
|
|
9677
|
-
return prop !== keyDirective;
|
|
9678
|
-
})
|
|
9944
|
+
...renderElement,
|
|
9945
|
+
props: renderElement.props.filter((prop) => prop !== slotKeyDirective)
|
|
9679
9946
|
}, context, transformNode);
|
|
9680
|
-
const keyAttr =
|
|
9947
|
+
const keyAttr = slotKeyDirective ? transformBindDirective(slotKeyDirective, context, scopedForInfo) : null;
|
|
9681
9948
|
if (keyAttr) extraAttrs.push(keyAttr);
|
|
9682
9949
|
const attrString = extraAttrs.length ? ` ${extraAttrs.join(" ")}` : "";
|
|
9683
9950
|
return attrString ? `<block${attrString}>${content}</block>` : content;
|
|
9684
9951
|
}
|
|
9685
|
-
const resolvedTag = resolveTemplateTagName(
|
|
9686
|
-
if (shouldTransformAsComponentWithSlots(
|
|
9952
|
+
const resolvedTag = resolveTemplateTagName(renderElement.tag, context);
|
|
9953
|
+
if (shouldTransformAsComponentWithSlots(renderElement, context, resolvedTag)) return transformComponentWithSlots(renderElement, context, transformNode, {
|
|
9687
9954
|
extraAttrs,
|
|
9688
|
-
forInfo
|
|
9955
|
+
forInfo: scopedForInfo
|
|
9689
9956
|
});
|
|
9690
|
-
const { attrs, vTextExp } = collectElementAttributes(
|
|
9691
|
-
forInfo,
|
|
9957
|
+
const { attrs, vTextExp } = collectElementAttributes(renderElement, context, {
|
|
9958
|
+
forInfo: scopedForInfo,
|
|
9692
9959
|
extraAttrs,
|
|
9693
9960
|
resolvedTag
|
|
9694
9961
|
});
|
|
9695
9962
|
let children = "";
|
|
9696
|
-
if (
|
|
9963
|
+
if (renderElement.children.length > 0) children = renderElement.children.map((child) => transformNode(child, context)).join("");
|
|
9697
9964
|
if (vTextExp !== void 0) children = renderMustache(vTextExp, context);
|
|
9698
9965
|
const tag = resolvedTag;
|
|
9699
9966
|
const attrString = attrs.length ? ` ${attrs.join(" ")}` : "";
|
|
@@ -9705,7 +9972,7 @@ function transformForElement(node, context, transformNode) {
|
|
|
9705
9972
|
const TEMPLATE_OPEN_RE = /<template/g;
|
|
9706
9973
|
const TEMPLATE_CLOSE_RE = /<\/template>/g;
|
|
9707
9974
|
function resolveConditionExpression(rawExpValue, context, hint) {
|
|
9708
|
-
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9975
|
+
return (context.rewriteScopedSlot || shouldFallbackToRuntimeBinding(rawExpValue, context.templateSafeCallNames) ? registerRuntimeBindingExpression(rawExpValue, context, { hint }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context);
|
|
9709
9976
|
}
|
|
9710
9977
|
function transformTransitionElement(node, context, transformNode) {
|
|
9711
9978
|
context.warnings.push("<transition> 组件:过渡效果需要动画库或运行时支持,仅渲染子节点。");
|
|
@@ -9792,13 +10059,6 @@ function transformElement(node, context, transformNode) {
|
|
|
9792
10059
|
}
|
|
9793
10060
|
//#endregion
|
|
9794
10061
|
//#region src/plugins/vue/compiler/template/nodes.ts
|
|
9795
|
-
const AMP_RE = /&/g;
|
|
9796
|
-
const LT_RE = /</g;
|
|
9797
|
-
const GT_RE = />/g;
|
|
9798
|
-
function escapeWxmlText(value) {
|
|
9799
|
-
if (!value) return "";
|
|
9800
|
-
return value.replace(AMP_RE, "&").replace(LT_RE, "<").replace(GT_RE, ">");
|
|
9801
|
-
}
|
|
9802
10062
|
function transformText(node, _context) {
|
|
9803
10063
|
return escapeWxmlText(node.content);
|
|
9804
10064
|
}
|
|
@@ -9806,7 +10066,7 @@ function transformInterpolation(node, context) {
|
|
|
9806
10066
|
const { content } = node;
|
|
9807
10067
|
if (content.type === NodeTypes.SIMPLE_EXPRESSION) {
|
|
9808
10068
|
const rawExpValue = content.content;
|
|
9809
|
-
return renderMustache((shouldFallbackToRuntimeBinding(rawExpValue) ? registerRuntimeBindingExpression(rawExpValue, context, { hint: "插值表达式" }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context), context);
|
|
10069
|
+
return renderMustache((shouldFallbackToRuntimeBinding(rawExpValue, context.templateSafeCallNames) ? registerRuntimeBindingExpression(rawExpValue, context, { hint: "插值表达式" }) : null) ?? normalizeWxmlExpressionWithContext(rawExpValue, context), context);
|
|
9810
10070
|
}
|
|
9811
10071
|
/* istanbul ignore next */
|
|
9812
10072
|
return renderMustache("", context);
|
|
@@ -9929,8 +10189,12 @@ function compileVueTemplateToWxml(template, filename, options) {
|
|
|
9929
10189
|
inlineExpressionSeed: 0,
|
|
9930
10190
|
functionPropPaths: /* @__PURE__ */ new Set(),
|
|
9931
10191
|
functionPropNames: Array.from(options?.functionPropNames ?? []),
|
|
10192
|
+
templateSafeCallNames: new Set(options?.templateSafeCallNames ?? []),
|
|
9932
10193
|
wevuComponentTags: options?.wevuComponentTags ? new Set(options.wevuComponentTags) : void 0,
|
|
9933
|
-
miniProgramComponentTags: options?.miniProgramComponentTags ? new Set(options.miniProgramComponentTags) : void 0
|
|
10194
|
+
miniProgramComponentTags: options?.miniProgramComponentTags ? new Set(options.miniProgramComponentTags) : void 0,
|
|
10195
|
+
scopeId: options?.scopeId,
|
|
10196
|
+
slottedScopeId: options?.slottedScopeId,
|
|
10197
|
+
cssVars: options?.cssVars
|
|
9934
10198
|
};
|
|
9935
10199
|
let wxml = ast.children.map((child) => transformNode(child, context)).join("");
|
|
9936
10200
|
if (context.classStyleWxs) wxml = `${buildClassStyleWxsTag(context.classStyleWxsExtension || "wxs", context.classStyleWxsSrc)}\n${wxml}`;
|
|
@@ -9961,6 +10225,25 @@ function compileVueTemplateToWxml(template, filename, options) {
|
|
|
9961
10225
|
}
|
|
9962
10226
|
}
|
|
9963
10227
|
//#endregion
|
|
10228
|
+
//#region src/plugins/vue/transform/scopedId.ts
|
|
10229
|
+
const SOURCE_ROOT_RE = /(?:^|\/)src\/(.+)$/;
|
|
10230
|
+
function normalizeScopedIdInput(filename) {
|
|
10231
|
+
const normalized = filename.replace(/\\/g, "/");
|
|
10232
|
+
return normalized.match(SOURCE_ROOT_RE)?.[1] ?? normalized.replace(/^.*?\/(pages|components|layouts)\//, "$1/");
|
|
10233
|
+
}
|
|
10234
|
+
/**
|
|
10235
|
+
* 根据项目内相对路径生成跨机器稳定的 scoped ID。
|
|
10236
|
+
*/
|
|
10237
|
+
function generateScopedId(filename) {
|
|
10238
|
+
const input = normalizeScopedIdInput(filename);
|
|
10239
|
+
let hash = 2166136261;
|
|
10240
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
10241
|
+
hash ^= input.charCodeAt(index);
|
|
10242
|
+
hash = Math.imul(hash, 16777619);
|
|
10243
|
+
}
|
|
10244
|
+
return (hash >>> 0).toString(36);
|
|
10245
|
+
}
|
|
10246
|
+
//#endregion
|
|
9964
10247
|
//#region src/ast/native.ts
|
|
9965
10248
|
const require = createRequire(import.meta.url);
|
|
9966
10249
|
let binding;
|
|
@@ -10568,6 +10851,10 @@ const OBJECT_TO_STRING = Object.prototype.toString;
|
|
|
10568
10851
|
function isIdentifierLikeKey(key) {
|
|
10569
10852
|
return IDENTIFIER_LIKE_KEY_RE.test(key);
|
|
10570
10853
|
}
|
|
10854
|
+
function resolveRuntimeMarkerIdentifier(value, scopeValues) {
|
|
10855
|
+
if (value[WEAPP_I18N_RUNTIME_MARKER] !== true) return;
|
|
10856
|
+
return Object.entries(scopeValues).find(([name, scopeValue]) => isIdentifierLikeKey(name) && scopeValue === value)?.[0];
|
|
10857
|
+
}
|
|
10571
10858
|
function getObjectTag(value) {
|
|
10572
10859
|
return OBJECT_TO_STRING.call(value);
|
|
10573
10860
|
}
|
|
@@ -10665,6 +10952,8 @@ function serializeStaticValueToExpression(value, seen = /* @__PURE__ */ new Weak
|
|
|
10665
10952
|
if (getObjectTag(value) === "[object RegExp]") return value.toString();
|
|
10666
10953
|
if (Array.isArray(value)) return `[${value.map((item) => serializeStaticValueToExpression(item, seen, scopeValues)).join(", ")}]`;
|
|
10667
10954
|
if (value && typeof value === "object") {
|
|
10955
|
+
const runtimeIdentifier = resolveRuntimeMarkerIdentifier(value, scopeValues);
|
|
10956
|
+
if (runtimeIdentifier) return runtimeIdentifier;
|
|
10668
10957
|
if (seen.has(value)) throw new Error("defineOptions 的参数中不支持循环引用。");
|
|
10669
10958
|
seen.add(value);
|
|
10670
10959
|
const proto = Object.getPrototypeOf(value);
|
|
@@ -11311,7 +11600,7 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
|
|
|
11311
11600
|
let propsDerivedKeys;
|
|
11312
11601
|
if (descriptor.script || descriptor.scriptSetup) {
|
|
11313
11602
|
const scriptCompiled = precompiledScript ?? compileScript(descriptorForCompile, {
|
|
11314
|
-
id: filename,
|
|
11603
|
+
id: generateScopedId(filename),
|
|
11315
11604
|
isProd: false
|
|
11316
11605
|
});
|
|
11317
11606
|
warnReservedScriptSetupProps(descriptorForCompile.scriptSetup?.content, options?.warn, {
|
|
@@ -11356,6 +11645,7 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
|
|
|
11356
11645
|
functionPropPaths: templateCompiled?.functionPropPaths,
|
|
11357
11646
|
propsAliases,
|
|
11358
11647
|
propsDerivedKeys,
|
|
11648
|
+
cssModules: precomputedScriptPhaseInfo?.cssModules,
|
|
11359
11649
|
relaxStructuredTypeOnlyProps,
|
|
11360
11650
|
scopedSlotHostProperties: Boolean(templateCompiled?.componentGenerics && Object.keys(templateCompiled.componentGenerics).length > 0)
|
|
11361
11651
|
});
|
|
@@ -11376,42 +11666,29 @@ async function compileScriptPhase(descriptor, descriptorForCompile, filename, op
|
|
|
11376
11666
|
};
|
|
11377
11667
|
}
|
|
11378
11668
|
//#endregion
|
|
11379
|
-
//#region src/plugins/vue/transform/scopedId.ts
|
|
11380
|
-
/**
|
|
11381
|
-
* 生成 scoped ID
|
|
11382
|
-
*/
|
|
11383
|
-
function generateScopedId(filename) {
|
|
11384
|
-
const hash = filename.split("").reduce((acc, char) => {
|
|
11385
|
-
return (acc << 5) - acc + char.charCodeAt(0);
|
|
11386
|
-
}, 0);
|
|
11387
|
-
return Math.abs(hash).toString(36);
|
|
11388
|
-
}
|
|
11389
|
-
//#endregion
|
|
11390
11669
|
//#region src/plugins/vue/transform/compileVueFile/style.ts
|
|
11391
|
-
function compileStylePhase(descriptor, filename, result, options) {
|
|
11392
|
-
if (descriptor.styles.length === 0) return;
|
|
11670
|
+
async function compileStylePhase(descriptor, filename, result, options) {
|
|
11671
|
+
if (descriptor.styles.length === 0) return { usesSlotted: false };
|
|
11393
11672
|
const scopedId = generateScopedId(filename);
|
|
11394
|
-
const compiledStyles = descriptor.styles.map((styleBlock) => {
|
|
11395
|
-
return compileVueStyleToWxss(styleBlock, {
|
|
11673
|
+
const compiledStyles = await Promise.all(descriptor.styles.map(async (styleBlock) => {
|
|
11674
|
+
return await compileVueStyleToWxss(styleBlock, {
|
|
11396
11675
|
id: scopedId,
|
|
11676
|
+
filename,
|
|
11397
11677
|
scoped: styleBlock.scoped,
|
|
11398
11678
|
modules: styleBlock.module,
|
|
11679
|
+
preprocessOptions: options?.preprocessOptions?.[styleBlock.lang || "css"],
|
|
11399
11680
|
preserveDeepSelectors: options?.preserveDeepSelectors,
|
|
11400
11681
|
transformScoped: options?.transformScoped
|
|
11401
11682
|
});
|
|
11402
|
-
});
|
|
11683
|
+
}));
|
|
11403
11684
|
result.style = compiledStyles.map((s) => s.code.trim()).filter(Boolean).join("\n\n");
|
|
11404
|
-
if (!compiledStyles.some((s) => s.modules)) return;
|
|
11685
|
+
if (!compiledStyles.some((s) => s.modules)) return { usesSlotted: compiledStyles.some((style) => style.usesSlotted) };
|
|
11405
11686
|
const modulesMap = {};
|
|
11406
11687
|
compiledStyles.forEach((compiled) => {
|
|
11407
11688
|
if (compiled.modules) Object.assign(modulesMap, compiled.modules);
|
|
11408
11689
|
});
|
|
11409
11690
|
result.cssModules = modulesMap;
|
|
11410
|
-
|
|
11411
|
-
// 模块化样式(CSS Modules)
|
|
11412
|
-
const __cssModules = ${JSON.stringify(modulesMap, null, 2)}
|
|
11413
|
-
${result.script}
|
|
11414
|
-
`;
|
|
11691
|
+
return { usesSlotted: compiledStyles.some((style) => style.usesSlotted) };
|
|
11415
11692
|
}
|
|
11416
11693
|
//#endregion
|
|
11417
11694
|
//#region src/plugins/vue/transform/compileVueFile/template.ts
|
|
@@ -11471,6 +11748,7 @@ async function refreshVueFileJsonConfig(source, filename, cachedResult, options)
|
|
|
11471
11748
|
*/
|
|
11472
11749
|
async function compileVueFile(source, filename, options) {
|
|
11473
11750
|
const parsed = await parseVueFile(source, filename, options);
|
|
11751
|
+
const sfcId = generateScopedId(filename);
|
|
11474
11752
|
const result = { meta: {
|
|
11475
11753
|
...parsed.meta,
|
|
11476
11754
|
styleBlocks: parsed.descriptor.styles
|
|
@@ -11486,24 +11764,32 @@ async function compileVueFile(source, filename, options) {
|
|
|
11486
11764
|
autoImportTags
|
|
11487
11765
|
});
|
|
11488
11766
|
const scriptCompiled = parsed.descriptor.script || parsed.descriptor.scriptSetup ? compileScript(parsed.descriptorForCompile, {
|
|
11489
|
-
id:
|
|
11767
|
+
id: sfcId,
|
|
11490
11768
|
isProd: false
|
|
11491
11769
|
}) : void 0;
|
|
11492
11770
|
const propsAliases = scriptCompiled ? resolveScriptSetupPropsAliases(scriptCompiled.bindings) : void 0;
|
|
11493
11771
|
const propsDerivedKeys = scriptCompiled ? resolveEffectivePropsDerivedKeys(scriptCompiled.bindings, scriptCompiled.content) : void 0;
|
|
11772
|
+
const styleCompiled = await compileStylePhase(parsed.descriptor, filename, result, options?.style);
|
|
11773
|
+
const scopedId = parsed.descriptor.styles.some((style) => style.scoped) ? `data-v-${sfcId}` : void 0;
|
|
11494
11774
|
const baseTemplateOptions = parsed.isAppFile ? {
|
|
11495
11775
|
...options?.template,
|
|
11496
11776
|
isPage: options?.isPage,
|
|
11497
11777
|
propsAliases,
|
|
11498
11778
|
propsDerivedKeys,
|
|
11499
11779
|
scriptSetupBindings: scriptCompiled?.bindings,
|
|
11500
|
-
scopedSlotsRequireProps: true
|
|
11780
|
+
scopedSlotsRequireProps: true,
|
|
11781
|
+
scopeId: scopedId,
|
|
11782
|
+
slottedScopeId: scopedId && styleCompiled.usesSlotted ? `${scopedId}-s` : void 0,
|
|
11783
|
+
cssVars: parsed.descriptor.cssVars.length > 0
|
|
11501
11784
|
} : {
|
|
11502
11785
|
...options?.template,
|
|
11503
11786
|
isPage: options?.isPage,
|
|
11504
11787
|
propsAliases,
|
|
11505
11788
|
propsDerivedKeys,
|
|
11506
|
-
scriptSetupBindings: scriptCompiled?.bindings
|
|
11789
|
+
scriptSetupBindings: scriptCompiled?.bindings,
|
|
11790
|
+
scopeId: scopedId,
|
|
11791
|
+
slottedScopeId: scopedId && styleCompiled.usesSlotted ? `${scopedId}-s` : void 0,
|
|
11792
|
+
cssVars: parsed.descriptor.cssVars.length > 0
|
|
11507
11793
|
};
|
|
11508
11794
|
const templateOptions = componentSourceInfo.wevuComponentTags.size ? {
|
|
11509
11795
|
...baseTemplateOptions,
|
|
@@ -11519,12 +11805,12 @@ async function compileVueFile(source, filename, options) {
|
|
|
11519
11805
|
const templateCompiled = compileTemplatePhase(parsed.descriptor, filename, templateOptions, result);
|
|
11520
11806
|
const scriptPhase = await compileScriptPhase(parsed.descriptor, parsed.descriptorForCompile, filename, options, autoUsingComponents, templateCompiled, parsed.isAppFile, componentSourceInfo, scriptCompiled, {
|
|
11521
11807
|
propsAliases,
|
|
11522
|
-
propsDerivedKeys
|
|
11808
|
+
propsDerivedKeys,
|
|
11809
|
+
cssModules: result.cssModules
|
|
11523
11810
|
});
|
|
11524
11811
|
result.script = scriptPhase.script;
|
|
11525
11812
|
result.scriptMap = scriptPhase.scriptMap;
|
|
11526
11813
|
if (scriptPhase.template) result.template = scriptPhase.template;
|
|
11527
|
-
compileStylePhase(parsed.descriptor, filename, result, options?.style);
|
|
11528
11814
|
await compileConfigPhase({
|
|
11529
11815
|
descriptor: parsed.descriptor,
|
|
11530
11816
|
filename,
|