uni-ticket-system/node_modules/@dcloudio/uni-mp-compiler/dist/transforms/vFor.js
2023-12-05 10:11:10 +08:00

304 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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;