uni-ticket-system/node_modules/@dcloudio/uni-mp-compiler/dist/transforms/vFor.js

304 lines
11 KiB
JavaScript
Raw Normal View History

2023-12-05 02:11:10 +00:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createVForArrowFunctionExpression = exports.createForLoopParams = exports.parseForExpression = exports.parseVForScope = exports.transformFor = exports.isForElementNode = void 0;
const shared_1 = require("@vue/shared");
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
const compiler_core_1 = require("@vue/compiler-core");
const ast_1 = require("../ast");
const transform_1 = require("../transform");
const transformExpression_1 = require("./transformExpression");
const codegen_1 = require("../codegen");
const types_1 = require("@babel/types");
const utils_1 = require("./utils");
const runtimeHelpers_1 = require("../runtimeHelpers");
const vSlot_1 = require("./vSlot");
function isForElementNode(node) {
return !!node.vFor;
}
exports.isForElementNode = isForElementNode;
exports.transformFor = (0, transform_1.createStructuralDirectiveTransform)('for', (node, dir, context) => {
if (!dir.exp) {
context.onError((0, compiler_core_1.createCompilerError)(31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */, dir.loc));
return;
}
const parseResult = parseForExpression(dir.exp, context);
if (!parseResult) {
context.onError((0, compiler_core_1.createCompilerError)(32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));
return;
}
parseResult.tagType = node.tagType;
const { addIdentifiers, removeIdentifiers } = context;
const { source, value, key, index } = parseResult;
if (context.prefixIdentifiers) {
addIdentifiers(value);
addIdentifiers(key);
addIdentifiers(index);
}
const { currentScope: parentScope, scopes, popScope } = context;
const sourceExpr = (0, ast_1.parseExpr)(source, context);
const valueCode = (0, codegen_1.genExpr)(value);
const valueExpr = (0, ast_1.parseParam)(valueCode, context, value);
const valueAlias = parseAlias(valueExpr, valueCode, 'v' + scopes.vFor);
const keyCode = (0, codegen_1.genExpr)(key);
const keyExpr = (0, ast_1.parseParam)(keyCode, context, key);
const keyAlias = parseAlias(keyExpr, keyCode, 'k' + scopes.vFor);
const indexCode = (0, codegen_1.genExpr)(index);
const indexExpr = (0, ast_1.parseParam)(indexCode, context, index);
const indexAlias = parseAlias(indexExpr, indexCode, 'i' + scopes.vFor);
// 先占位 vFor后续更新 cloneSourceExpr 为 CallExpression
const cloneSourceExpr = (0, types_1.cloneNode)(sourceExpr, false);
const sourceAliasReferencedScope = (0, utils_1.findReferencedScope)(cloneSourceExpr, context.currentScope,
// vFor 嵌套时始终保持嵌套关系issues/3263
false);
// 寻找子节点中 if 指令作用域
const vIfReferencedScope = findVIfReferencedScope(node, context.currentScope, context);
// 取最近的作用域
const referencedScope = vIfReferencedScope &&
context.getScopeIndex(vIfReferencedScope) >
context.getScopeIndex(sourceAliasReferencedScope)
? vIfReferencedScope
: sourceAliasReferencedScope;
const sourceAlias = (0, utils_1.rewriteExpression)(source, context, cloneSourceExpr, parentScope,
// 强制 rewrite因为即使是字符串数字也要走 vFor 函数
{
property: true,
ignoreLiteral: true,
referencedScope,
}).content;
const sourceCode = `{{${sourceAlias}}}`;
const vForData = {
source,
sourceExpr,
sourceAlias,
sourceCode,
value,
valueCode,
valueExpr,
valueAlias,
key,
keyCode,
keyExpr,
keyAlias,
index,
indexCode,
indexExpr,
indexAlias,
node,
};
const vForScope = context.addVForScope({
...vForData,
locals: findVForLocals(parseResult),
});
const vFor = {
...vForData,
};
const isScopedSlot = (0, transform_1.isScopedSlotVFor)(vForScope);
node.vFor = vFor;
scopes.vFor++;
return () => {
scopes.vFor--;
if ((0, compiler_core_1.isTemplateNode)(node)) {
node.children.some((c) => {
if (c.type === 1 /* NodeTypes.ELEMENT */ && !isForElementNode(c)) {
const key = (0, compiler_core_1.findProp)(c, 'key');
if (key) {
context.onError((0, compiler_core_1.createCompilerError)(33 /* ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));
return true;
}
}
});
}
if (context.prefixIdentifiers) {
value && removeIdentifiers(value);
key && removeIdentifiers(key);
index && removeIdentifiers(index);
}
(0, shared_1.extend)(clearExpr(cloneSourceExpr), isScopedSlot
? (0, vSlot_1.createVSlotCallExpression)(node
.slotComponent, vForScope, context)
: createVForCallExpression(vForScope, context));
popScope();
};
});
function clearExpr(expr) {
Object.keys(expr).forEach((key) => {
delete expr[key];
});
return expr;
}
function parseAlias(babelExpr, exprCode, fallback) {
if ((0, types_1.isIdentifier)(babelExpr)) {
return exprCode;
}
return fallback;
}
function parseVForScope(currentScope) {
while (currentScope) {
if ((0, transform_1.isVForScope)(currentScope) && !(0, transform_1.isScopedSlotVFor)(currentScope)) {
return currentScope;
}
currentScope = currentScope.parent;
}
}
exports.parseVForScope = parseVForScope;
function findVIfReferencedScope(node, currentScope, context) {
if (!currentScope) {
return;
}
const vForScope = parseVForScope(currentScope);
if (!vForScope) {
return;
}
if (!node.children.find((item) => checkVIfReferenced(item, vForScope, context))) {
return findVIfReferencedScope(node, currentScope.parent, context);
}
return vForScope;
}
function checkVIfReferenced(node, vForScope, context) {
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
return false;
}
// 嵌套 for 不查找
if ((0, compiler_core_1.findDir)(node, 'for')) {
return false;
}
const ifDir = (0, compiler_core_1.findDir)(node, 'if');
if (ifDir) {
return checkDirReferenced(ifDir.exp, vForScope, context);
}
const elseIfDir = (0, compiler_core_1.findDir)(node, 'else-if');
if (elseIfDir) {
return checkDirReferenced(elseIfDir.exp, vForScope, context);
}
return !!node.children.find((item) => checkVIfReferenced(item, vForScope, context));
}
function checkDirReferenced(node, vForScope, context) {
if (node) {
const babelNode = (0, ast_1.parseExpr)(node, context);
if (babelNode && (0, utils_1.isReferencedByIds)(babelNode, vForScope.locals)) {
return true;
}
}
return false;
}
function findVForLocals({ value, key, index }) {
const ids = [];
if (value) {
findIds(value, ids);
}
if (key) {
findIds(key, ids);
}
if (index) {
findIds(index, ids);
}
return ids;
}
function findIds(exp, ids) {
if ((0, shared_1.isString)(exp)) {
ids.push(exp);
}
else if (exp.identifiers) {
exp.identifiers.forEach((id) => ids.push(id));
}
else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
ids.push(exp.content);
}
}
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
const stripParensRE = /^\(|\)$/g;
function parseForExpression(input, context) {
const loc = input.loc;
const exp = input.content;
const inMatch = exp.match(forAliasRE);
if (!inMatch)
return;
const [, LHS, RHS] = inMatch;
const result = {
source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),
value: (0, compiler_core_1.createSimpleExpression)('v' + context.scopes.vFor),
key: (0, compiler_core_1.createSimpleExpression)('k' + context.scopes.vFor),
index: (0, compiler_core_1.createSimpleExpression)('i' + context.scopes.vFor),
tagType: 0 /* ElementTypes.ELEMENT */,
};
if (context.prefixIdentifiers) {
result.source = (0, transformExpression_1.processExpression)(result.source, context);
}
let valueContent = LHS.trim().replace(stripParensRE, '').trim();
const trimmedOffset = LHS.indexOf(valueContent);
const iteratorMatch = valueContent.match(forIteratorRE);
if (iteratorMatch) {
valueContent = valueContent.replace(forIteratorRE, '').trim();
const keyContent = iteratorMatch[1].trim();
let keyOffset;
if (keyContent) {
keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);
result.key = createAliasExpression(loc, keyContent, keyOffset);
if (context.prefixIdentifiers) {
result.key = (0, transformExpression_1.processExpression)(result.key, context, true);
}
}
if (iteratorMatch[2]) {
const indexContent = iteratorMatch[2].trim();
if (indexContent) {
result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key
? keyOffset + keyContent.length
: trimmedOffset + valueContent.length));
if (context.prefixIdentifiers) {
result.index = (0, transformExpression_1.processExpression)(result.index, context, true);
}
}
}
}
if (valueContent) {
result.value = createAliasExpression(loc, valueContent, trimmedOffset);
if (context.prefixIdentifiers) {
result.value = (0, transformExpression_1.processExpression)(result.value, context, true);
}
}
return result;
}
exports.parseForExpression = parseForExpression;
function createAliasExpression(range, content, offset) {
return (0, compiler_core_1.createSimpleExpression)(content, false, (0, compiler_core_1.getInnerRange)(range, offset, content.length));
}
function createForLoopParams({ value, key, index }, memoArgs = []) {
return createParamsList([value, key, index, ...memoArgs]);
}
exports.createForLoopParams = createForLoopParams;
function createParamsList(args) {
let i = args.length;
while (i--) {
if (args[i])
break;
}
return args
.slice(0, i + 1)
.map((arg, i) => arg || (0, compiler_core_1.createSimpleExpression)(`_`.repeat(i + 1), false));
}
function createVForCallExpression(vForScope, context) {
// let sourceExpr: Expression = vForScope.sourceExpr!
// if (isNumericLiteral(sourceExpr)) {
// sourceExpr = numericLiteralToArrayExpr((sourceExpr as NumericLiteral).value)
// }
return (0, types_1.callExpression)((0, types_1.identifier)(context.helperString(runtimeHelpers_1.V_FOR)), [
vForScope.sourceExpr,
createVForArrowFunctionExpression(vForScope),
]);
}
function createVForArrowFunctionExpression({ valueExpr, keyExpr, indexExpr, properties, }) {
const params = [];
if (valueExpr) {
params.push(valueExpr);
}
if (keyExpr) {
params.push(keyExpr);
}
if (indexExpr) {
params.push(indexExpr);
}
return (0, types_1.arrowFunctionExpression)(params, (0, types_1.blockStatement)([(0, types_1.returnStatement)((0, types_1.objectExpression)(properties))]));
}
exports.createVForArrowFunctionExpression = createVForArrowFunctionExpression;