How to use checkCompatEnabled method in Playwright Internal

Best JavaScript code snippet using playwright-internal

vendor-node_modules_r.js

Source:vendor-node_modules_r.js Github

copy

Full Screen

...803 // in v3 mode, only enable if explicitly set to true804 // otherwise enable for any non-false value805 return mode === 3 ? value === true : value !== false;806}807function checkCompatEnabled(key, context, loc, ...args) {808 const enabled = isCompatEnabled(key, context);809 if (( true) && enabled) {810 warnDeprecation(key, context, loc, ...args);811 }812 return enabled;813}814function warnDeprecation(key, context, loc, ...args) {815 const val = getCompatValue(key, context);816 if (val === 'suppress-warning') {817 return;818 }819 const { message, link } = deprecationData[key];820 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;821 const err = new SyntaxError(msg);822 err.code = key;823 if (loc)824 err.loc = loc;825 context.onWarn(err);826}827// The default decoder only provides escapes for characters reserved as part of828// the template syntax, and is only used if the custom renderer did not provide829// a platform-specific decoder.830const decodeRE = /&(gt|lt|amp|apos|quot);/g;831const decodeMap = {832 gt: '>',833 lt: '<',834 amp: '&',835 apos: "'",836 quot: '"'837};838const defaultParserOptions = {839 delimiters: [`{{`, `}}`],840 getNamespace: () => 0 /* HTML */,841 getTextMode: () => 0 /* DATA */,842 isVoidTag: _vue_shared__WEBPACK_IMPORTED_MODULE_0__.NO,843 isPreTag: _vue_shared__WEBPACK_IMPORTED_MODULE_0__.NO,844 isCustomElement: _vue_shared__WEBPACK_IMPORTED_MODULE_0__.NO,845 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),846 onError: defaultOnError,847 onWarn: defaultOnWarn,848 comments: false849};850function baseParse(content, options = {}) {851 const context = createParserContext(content, options);852 const start = getCursor(context);853 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));854}855function createParserContext(content, rawOptions) {856 const options = (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.extend)({}, defaultParserOptions);857 for (const key in rawOptions) {858 // @ts-ignore859 options[key] = rawOptions[key] || defaultParserOptions[key];860 }861 return {862 options,863 column: 1,864 line: 1,865 offset: 0,866 originalSource: content,867 source: content,868 inPre: false,869 inVPre: false,870 onWarn: options.onWarn871 };872}873function parseChildren(context, mode, ancestors) {874 const parent = last(ancestors);875 const ns = parent ? parent.ns : 0 /* HTML */;876 const nodes = [];877 while (!isEnd(context, mode, ancestors)) {878 const s = context.source;879 let node = undefined;880 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {881 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {882 // '{{'883 node = parseInterpolation(context, mode);884 }885 else if (mode === 0 /* DATA */ && s[0] === '<') {886 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state887 if (s.length === 1) {888 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);889 }890 else if (s[1] === '!') {891 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state892 if (startsWith(s, '<!--')) {893 node = parseComment(context);894 }895 else if (startsWith(s, '<!DOCTYPE')) {896 // Ignore DOCTYPE by a limitation.897 node = parseBogusComment(context);898 }899 else if (startsWith(s, '<![CDATA[')) {900 if (ns !== 0 /* HTML */) {901 node = parseCDATA(context, ancestors);902 }903 else {904 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);905 node = parseBogusComment(context);906 }907 }908 else {909 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);910 node = parseBogusComment(context);911 }912 }913 else if (s[1] === '/') {914 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state915 if (s.length === 2) {916 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);917 }918 else if (s[2] === '>') {919 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);920 advanceBy(context, 3);921 continue;922 }923 else if (/[a-z]/i.test(s[2])) {924 emitError(context, 23 /* X_INVALID_END_TAG */);925 parseTag(context, 1 /* End */, parent);926 continue;927 }928 else {929 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);930 node = parseBogusComment(context);931 }932 }933 else if (/[a-z]/i.test(s[1])) {934 node = parseElement(context, ancestors);935 // 2.x <template> with no directive compat936 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&937 node &&938 node.tag === 'template' &&939 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&940 isSpecialTemplateDirective(p.name))) {941 ( true) &&942 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);943 node = node.children;944 }945 }946 else if (s[1] === '?') {947 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);948 node = parseBogusComment(context);949 }950 else {951 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);952 }953 }954 }955 if (!node) {956 node = parseText(context, mode);957 }958 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(node)) {959 for (let i = 0; i < node.length; i++) {960 pushNode(nodes, node[i]);961 }962 }963 else {964 pushNode(nodes, node);965 }966 }967 // Whitespace handling strategy like v2968 let removedWhitespace = false;969 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {970 const preserve = context.options.whitespace === 'preserve';971 for (let i = 0; i < nodes.length; i++) {972 const node = nodes[i];973 if (!context.inPre && node.type === 2 /* TEXT */) {974 if (!/[^\t\r\n\f ]/.test(node.content)) {975 const prev = nodes[i - 1];976 const next = nodes[i + 1];977 // Remove if:978 // - the whitespace is the first or last node, or:979 // - (condense mode) the whitespace is adjacent to a comment, or:980 // - (condense mode) the whitespace is between two elements AND contains newline981 if (!prev ||982 !next ||983 (!preserve &&984 (prev.type === 3 /* COMMENT */ ||985 next.type === 3 /* COMMENT */ ||986 (prev.type === 1 /* ELEMENT */ &&987 next.type === 1 /* ELEMENT */ &&988 /[\r\n]/.test(node.content))))) {989 removedWhitespace = true;990 nodes[i] = null;991 }992 else {993 // Otherwise, the whitespace is condensed into a single space994 node.content = ' ';995 }996 }997 else if (!preserve) {998 // in condense mode, consecutive whitespaces in text are condensed999 // down to a single space.1000 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');1001 }1002 }1003 // also remove comment nodes in prod by default1004 if (false) {}1005 }1006 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {1007 // remove leading newline per html spec1008 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element1009 const first = nodes[0];1010 if (first && first.type === 2 /* TEXT */) {1011 first.content = first.content.replace(/^\r?\n/, '');1012 }1013 }1014 }1015 return removedWhitespace ? nodes.filter(Boolean) : nodes;1016}1017function pushNode(nodes, node) {1018 if (node.type === 2 /* TEXT */) {1019 const prev = last(nodes);1020 // Merge if both this and the previous node are text and those are1021 // consecutive. This happens for cases like "a < b".1022 if (prev &&1023 prev.type === 2 /* TEXT */ &&1024 prev.loc.end.offset === node.loc.start.offset) {1025 prev.content += node.content;1026 prev.loc.end = node.loc.end;1027 prev.loc.source += node.loc.source;1028 return;1029 }1030 }1031 nodes.push(node);1032}1033function parseCDATA(context, ancestors) {1034 advanceBy(context, 9);1035 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1036 if (context.source.length === 0) {1037 emitError(context, 6 /* EOF_IN_CDATA */);1038 }1039 else {1040 advanceBy(context, 3);1041 }1042 return nodes;1043}1044function parseComment(context) {1045 const start = getCursor(context);1046 let content;1047 // Regular comment.1048 const match = /--(\!)?>/.exec(context.source);1049 if (!match) {1050 content = context.source.slice(4);1051 advanceBy(context, context.source.length);1052 emitError(context, 7 /* EOF_IN_COMMENT */);1053 }1054 else {1055 if (match.index <= 3) {1056 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1057 }1058 if (match[1]) {1059 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1060 }1061 content = context.source.slice(4, match.index);1062 // Advancing with reporting nested comments.1063 const s = context.source.slice(0, match.index);1064 let prevIndex = 1, nestedIndex = 0;1065 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1066 advanceBy(context, nestedIndex - prevIndex + 1);1067 if (nestedIndex + 4 < s.length) {1068 emitError(context, 16 /* NESTED_COMMENT */);1069 }1070 prevIndex = nestedIndex + 1;1071 }1072 advanceBy(context, match.index + match[0].length - prevIndex + 1);1073 }1074 return {1075 type: 3 /* COMMENT */,1076 content,1077 loc: getSelection(context, start)1078 };1079}1080function parseBogusComment(context) {1081 const start = getCursor(context);1082 const contentStart = context.source[1] === '?' ? 1 : 2;1083 let content;1084 const closeIndex = context.source.indexOf('>');1085 if (closeIndex === -1) {1086 content = context.source.slice(contentStart);1087 advanceBy(context, context.source.length);1088 }1089 else {1090 content = context.source.slice(contentStart, closeIndex);1091 advanceBy(context, closeIndex + 1);1092 }1093 return {1094 type: 3 /* COMMENT */,1095 content,1096 loc: getSelection(context, start)1097 };1098}1099function parseElement(context, ancestors) {1100 // Start tag.1101 const wasInPre = context.inPre;1102 const wasInVPre = context.inVPre;1103 const parent = last(ancestors);1104 const element = parseTag(context, 0 /* Start */, parent);1105 const isPreBoundary = context.inPre && !wasInPre;1106 const isVPreBoundary = context.inVPre && !wasInVPre;1107 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1108 // #4030 self-closing <pre> tag1109 if (context.options.isPreTag(element.tag)) {1110 context.inPre = false;1111 }1112 return element;1113 }1114 // Children.1115 ancestors.push(element);1116 const mode = context.options.getTextMode(element, parent);1117 const children = parseChildren(context, mode, ancestors);1118 ancestors.pop();1119 // 2.x inline-template compat1120 {1121 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1122 if (inlineTemplateProp &&1123 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1124 const loc = getSelection(context, element.loc.end);1125 inlineTemplateProp.value = {1126 type: 2 /* TEXT */,1127 content: loc.source,1128 loc1129 };1130 }1131 }1132 element.children = children;1133 // End tag.1134 if (startsWithEndTagOpen(context.source, element.tag)) {1135 parseTag(context, 1 /* End */, parent);1136 }1137 else {1138 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1139 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1140 const first = children[0];1141 if (first && startsWith(first.loc.source, '<!--')) {1142 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1143 }1144 }1145 }1146 element.loc = getSelection(context, element.loc.start);1147 if (isPreBoundary) {1148 context.inPre = false;1149 }1150 if (isVPreBoundary) {1151 context.inVPre = false;1152 }1153 return element;1154}1155const isSpecialTemplateDirective = /*#__PURE__*/ (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.makeMap)(`if,else,else-if,for,slot`);1156function parseTag(context, type, parent) {1157 // Tag open.1158 const start = getCursor(context);1159 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1160 const tag = match[1];1161 const ns = context.options.getNamespace(tag, parent);1162 advanceBy(context, match[0].length);1163 advanceSpaces(context);1164 // save current state in case we need to re-parse attributes with v-pre1165 const cursor = getCursor(context);1166 const currentSource = context.source;1167 // check <pre> tag1168 const isPreTag = context.options.isPreTag(tag);1169 if (isPreTag) {1170 context.inPre = true;1171 }1172 // Attributes.1173 let props = parseAttributes(context, type);1174 // check v-pre1175 if (type === 0 /* Start */ &&1176 !context.inVPre &&1177 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1178 context.inVPre = true;1179 // reset context1180 (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.extend)(context, cursor);1181 context.source = currentSource;1182 // re-parse attrs and filter out v-pre itself1183 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1184 }1185 // Tag close.1186 let isSelfClosing = false;1187 if (context.source.length === 0) {1188 emitError(context, 9 /* EOF_IN_TAG */);1189 }1190 else {1191 isSelfClosing = startsWith(context.source, '/>');1192 if (type === 1 /* End */ && isSelfClosing) {1193 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1194 }1195 advanceBy(context, isSelfClosing ? 2 : 1);1196 }1197 if (type === 1 /* End */) {1198 return;1199 }1200 // 2.x deprecation checks1201 if (( true) &&1202 isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1203 let hasIf = false;1204 let hasFor = false;1205 for (let i = 0; i < props.length; i++) {1206 const p = props[i];1207 if (p.type === 7 /* DIRECTIVE */) {1208 if (p.name === 'if') {1209 hasIf = true;1210 }1211 else if (p.name === 'for') {1212 hasFor = true;1213 }1214 }1215 if (hasIf && hasFor) {1216 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1217 }1218 }1219 }1220 let tagType = 0 /* ELEMENT */;1221 if (!context.inVPre) {1222 if (tag === 'slot') {1223 tagType = 2 /* SLOT */;1224 }1225 else if (tag === 'template') {1226 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1227 tagType = 3 /* TEMPLATE */;1228 }1229 }1230 else if (isComponent(tag, props, context)) {1231 tagType = 1 /* COMPONENT */;1232 }1233 }1234 return {1235 type: 1 /* ELEMENT */,1236 ns,1237 tag,1238 tagType,1239 props,1240 isSelfClosing,1241 children: [],1242 loc: getSelection(context, start),1243 codegenNode: undefined // to be created during transform phase1244 };1245}1246function isComponent(tag, props, context) {1247 const options = context.options;1248 if (options.isCustomElement(tag)) {1249 return false;1250 }1251 if (tag === 'component' ||1252 /^[A-Z]/.test(tag) ||1253 isCoreComponent(tag) ||1254 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1255 (options.isNativeTag && !options.isNativeTag(tag))) {1256 return true;1257 }1258 // at this point the tag should be a native tag, but check for potential "is"1259 // casting1260 for (let i = 0; i < props.length; i++) {1261 const p = props[i];1262 if (p.type === 6 /* ATTRIBUTE */) {1263 if (p.name === 'is' && p.value) {1264 if (p.value.content.startsWith('vue:')) {1265 return true;1266 }1267 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1268 return true;1269 }1270 }1271 }1272 else {1273 // directive1274 // v-is (TODO Deprecate)1275 if (p.name === 'is') {1276 return true;1277 }1278 else if (1279 // :is on plain element - only treat as component in compat mode1280 p.name === 'bind' &&1281 isBindKey(p.arg, 'is') &&1282 true &&1283 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1284 return true;1285 }1286 }1287 }1288}1289function parseAttributes(context, type) {1290 const props = [];1291 const attributeNames = new Set();1292 while (context.source.length > 0 &&1293 !startsWith(context.source, '>') &&1294 !startsWith(context.source, '/>')) {1295 if (startsWith(context.source, '/')) {1296 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1297 advanceBy(context, 1);1298 advanceSpaces(context);1299 continue;1300 }1301 if (type === 1 /* End */) {1302 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1303 }1304 const attr = parseAttribute(context, attributeNames);1305 if (type === 0 /* Start */) {1306 props.push(attr);1307 }1308 if (/^[^\t\r\n\f />]/.test(context.source)) {1309 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1310 }1311 advanceSpaces(context);1312 }1313 return props;1314}1315function parseAttribute(context, nameSet) {1316 // Name.1317 const start = getCursor(context);1318 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1319 const name = match[0];1320 if (nameSet.has(name)) {1321 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1322 }1323 nameSet.add(name);1324 if (name[0] === '=') {1325 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1326 }1327 {1328 const pattern = /["'<]/g;1329 let m;1330 while ((m = pattern.exec(name))) {1331 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1332 }1333 }1334 advanceBy(context, name.length);1335 // Value1336 let value = undefined;1337 if (/^[\t\r\n\f ]*=/.test(context.source)) {1338 advanceSpaces(context);1339 advanceBy(context, 1);1340 advanceSpaces(context);1341 value = parseAttributeValue(context);1342 if (!value) {1343 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1344 }1345 }1346 const loc = getSelection(context, start);1347 if (!context.inVPre && /^(v-|:|@|#)/.test(name)) {1348 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1349 let dirName = match[1] ||1350 (startsWith(name, ':') ? 'bind' : startsWith(name, '@') ? 'on' : 'slot');1351 let arg;1352 if (match[2]) {1353 const isSlot = dirName === 'slot';1354 const startOffset = name.lastIndexOf(match[2]);1355 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));1356 let content = match[2];1357 let isStatic = true;1358 if (content.startsWith('[')) {1359 isStatic = false;1360 if (!content.endsWith(']')) {1361 emitError(context, 26 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1362 }1363 content = content.substr(1, content.length - 2);1364 }1365 else if (isSlot) {1366 // #1241 special case for v-slot: vuetify relies extensively on slot1367 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x1368 // supports such usage so we are keeping it consistent with 2.x.1369 content += match[3] || '';1370 }1371 arg = {1372 type: 4 /* SIMPLE_EXPRESSION */,1373 content,1374 isStatic,1375 constType: isStatic1376 ? 3 /* CAN_STRINGIFY */1377 : 0 /* NOT_CONSTANT */,1378 loc1379 };1380 }1381 if (value && value.isQuoted) {1382 const valueLoc = value.loc;1383 valueLoc.start.offset++;1384 valueLoc.start.column++;1385 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1386 valueLoc.source = valueLoc.source.slice(1, -1);1387 }1388 const modifiers = match[3] ? match[3].substr(1).split('.') : [];1389 // 2.x compat v-bind:foo.sync -> v-model:foo1390 if (dirName === 'bind' && arg) {1391 if (modifiers.includes('sync') &&1392 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {1393 dirName = 'model';1394 modifiers.splice(modifiers.indexOf('sync'), 1);1395 }1396 if (( true) && modifiers.includes('prop')) {1397 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);1398 }1399 }1400 return {1401 type: 7 /* DIRECTIVE */,1402 name: dirName,1403 exp: value && {1404 type: 4 /* SIMPLE_EXPRESSION */,1405 content: value.content,1406 isStatic: false,1407 // Treat as non-constant by default. This can be potentially set to1408 // other values by `transformExpression` to make it eligible for hoisting.1409 constType: 0 /* NOT_CONSTANT */,1410 loc: value.loc1411 },1412 arg,1413 modifiers,1414 loc1415 };1416 }1417 return {1418 type: 6 /* ATTRIBUTE */,1419 name,1420 value: value && {1421 type: 2 /* TEXT */,1422 content: value.content,1423 loc: value.loc1424 },1425 loc1426 };1427}1428function parseAttributeValue(context) {1429 const start = getCursor(context);1430 let content;1431 const quote = context.source[0];1432 const isQuoted = quote === `"` || quote === `'`;1433 if (isQuoted) {1434 // Quoted value.1435 advanceBy(context, 1);1436 const endIndex = context.source.indexOf(quote);1437 if (endIndex === -1) {1438 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1439 }1440 else {1441 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1442 advanceBy(context, 1);1443 }1444 }1445 else {1446 // Unquoted1447 const match = /^[^\t\r\n\f >]+/.exec(context.source);1448 if (!match) {1449 return undefined;1450 }1451 const unexpectedChars = /["'<=`]/g;1452 let m;1453 while ((m = unexpectedChars.exec(match[0]))) {1454 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1455 }1456 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1457 }1458 return { content, isQuoted, loc: getSelection(context, start) };1459}1460function parseInterpolation(context, mode) {1461 const [open, close] = context.options.delimiters;1462 const closeIndex = context.source.indexOf(close, open.length);1463 if (closeIndex === -1) {1464 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);1465 return undefined;1466 }1467 const start = getCursor(context);1468 advanceBy(context, open.length);1469 const innerStart = getCursor(context);1470 const innerEnd = getCursor(context);1471 const rawContentLength = closeIndex - open.length;1472 const rawContent = context.source.slice(0, rawContentLength);1473 const preTrimContent = parseTextData(context, rawContentLength, mode);1474 const content = preTrimContent.trim();1475 const startOffset = preTrimContent.indexOf(content);1476 if (startOffset > 0) {1477 advancePositionWithMutation(innerStart, rawContent, startOffset);1478 }1479 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1480 advancePositionWithMutation(innerEnd, rawContent, endOffset);1481 advanceBy(context, close.length);1482 return {1483 type: 5 /* INTERPOLATION */,1484 content: {1485 type: 4 /* SIMPLE_EXPRESSION */,1486 isStatic: false,1487 // Set `isConstant` to false by default and will decide in transformExpression1488 constType: 0 /* NOT_CONSTANT */,1489 content,1490 loc: getSelection(context, innerStart, innerEnd)1491 },1492 loc: getSelection(context, start)1493 };1494}1495function parseText(context, mode) {1496 const endTokens = ['<', context.options.delimiters[0]];1497 if (mode === 3 /* CDATA */) {1498 endTokens.push(']]>');1499 }1500 let endIndex = context.source.length;1501 for (let i = 0; i < endTokens.length; i++) {1502 const index = context.source.indexOf(endTokens[i], 1);1503 if (index !== -1 && endIndex > index) {1504 endIndex = index;1505 }1506 }1507 const start = getCursor(context);1508 const content = parseTextData(context, endIndex, mode);1509 return {1510 type: 2 /* TEXT */,1511 content,1512 loc: getSelection(context, start)1513 };1514}1515/**1516 * Get text data with a given length from the current location.1517 * This translates HTML entities in the text data.1518 */1519function parseTextData(context, length, mode) {1520 const rawText = context.source.slice(0, length);1521 advanceBy(context, length);1522 if (mode === 2 /* RAWTEXT */ ||1523 mode === 3 /* CDATA */ ||1524 rawText.indexOf('&') === -1) {1525 return rawText;1526 }1527 else {1528 // DATA or RCDATA containing "&"". Entity decoding required.1529 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);1530 }1531}1532function getCursor(context) {1533 const { column, line, offset } = context;1534 return { column, line, offset };1535}1536function getSelection(context, start, end) {1537 end = end || getCursor(context);1538 return {1539 start,1540 end,1541 source: context.originalSource.slice(start.offset, end.offset)1542 };1543}1544function last(xs) {1545 return xs[xs.length - 1];1546}1547function startsWith(source, searchString) {1548 return source.startsWith(searchString);1549}1550function advanceBy(context, numberOfCharacters) {1551 const { source } = context;1552 advancePositionWithMutation(context, source, numberOfCharacters);1553 context.source = source.slice(numberOfCharacters);1554}1555function advanceSpaces(context) {1556 const match = /^[\t\r\n\f ]+/.exec(context.source);1557 if (match) {1558 advanceBy(context, match[0].length);1559 }1560}1561function getNewPosition(context, start, numberOfCharacters) {1562 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1563}1564function emitError(context, code, offset, loc = getCursor(context)) {1565 if (offset) {1566 loc.offset += offset;1567 loc.column += offset;1568 }1569 context.options.onError(createCompilerError(code, {1570 start: loc,1571 end: loc,1572 source: ''1573 }));1574}1575function isEnd(context, mode, ancestors) {1576 const s = context.source;1577 switch (mode) {1578 case 0 /* DATA */:1579 if (startsWith(s, '</')) {1580 // TODO: probably bad performance1581 for (let i = ancestors.length - 1; i >= 0; --i) {1582 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1583 return true;1584 }1585 }1586 }1587 break;1588 case 1 /* RCDATA */:1589 case 2 /* RAWTEXT */: {1590 const parent = last(ancestors);1591 if (parent && startsWithEndTagOpen(s, parent.tag)) {1592 return true;1593 }1594 break;1595 }1596 case 3 /* CDATA */:1597 if (startsWith(s, ']]>')) {1598 return true;1599 }1600 break;1601 }1602 return !s;1603}1604function startsWithEndTagOpen(source, tag) {1605 return (startsWith(source, '</') &&1606 source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&1607 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));1608}1609function hoistStatic(root, context) {1610 walk(root, context, 1611 // Root node is unfortunately non-hoistable due to potential parent1612 // fallthrough attributes.1613 isSingleElementRoot(root, root.children[0]));1614}1615function isSingleElementRoot(root, child) {1616 const { children } = root;1617 return (children.length === 1 &&1618 child.type === 1 /* ELEMENT */ &&1619 !isSlotOutlet(child));1620}1621function walk(node, context, doNotHoistNode = false) {1622 let hasHoistedNode = false;1623 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1624 // static bindings with expressions. These expressions are guaranteed to be1625 // constant so they are still eligible for hoisting, but they are only1626 // available at runtime and therefore cannot be evaluated ahead of time.1627 // This is only a concern for pre-stringification (via transformHoist by1628 // @vue/compiler-dom), but doing it here allows us to perform only one full1629 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1630 // stringficiation threshold is met.1631 let canStringify = true;1632 const { children } = node;1633 for (let i = 0; i < children.length; i++) {1634 const child = children[i];1635 // only plain elements & text calls are eligible for hoisting.1636 if (child.type === 1 /* ELEMENT */ &&1637 child.tagType === 0 /* ELEMENT */) {1638 const constantType = doNotHoistNode1639 ? 0 /* NOT_CONSTANT */1640 : getConstantType(child, context);1641 if (constantType > 0 /* NOT_CONSTANT */) {1642 if (constantType < 3 /* CAN_STRINGIFY */) {1643 canStringify = false;1644 }1645 if (constantType >= 2 /* CAN_HOIST */) {1646 child.codegenNode.patchFlag =1647 -1 /* HOISTED */ + (( true) ? ` /* HOISTED */` : 0);1648 child.codegenNode = context.hoist(child.codegenNode);1649 hasHoistedNode = true;1650 continue;1651 }1652 }1653 else {1654 // node may contain dynamic children, but its props may be eligible for1655 // hoisting.1656 const codegenNode = child.codegenNode;1657 if (codegenNode.type === 13 /* VNODE_CALL */) {1658 const flag = getPatchFlag(codegenNode);1659 if ((!flag ||1660 flag === 512 /* NEED_PATCH */ ||1661 flag === 1 /* TEXT */) &&1662 getGeneratedPropsConstantType(child, context) >=1663 2 /* CAN_HOIST */) {1664 const props = getNodeProps(child);1665 if (props) {1666 codegenNode.props = context.hoist(props);1667 }1668 }1669 }1670 }1671 }1672 else if (child.type === 12 /* TEXT_CALL */) {1673 const contentType = getConstantType(child.content, context);1674 if (contentType > 0) {1675 if (contentType < 3 /* CAN_STRINGIFY */) {1676 canStringify = false;1677 }1678 if (contentType >= 2 /* CAN_HOIST */) {1679 child.codegenNode = context.hoist(child.codegenNode);1680 hasHoistedNode = true;1681 }1682 }1683 }1684 // walk further1685 if (child.type === 1 /* ELEMENT */) {1686 const isComponent = child.tagType === 1 /* COMPONENT */;1687 if (isComponent) {1688 context.scopes.vSlot++;1689 }1690 walk(child, context);1691 if (isComponent) {1692 context.scopes.vSlot--;1693 }1694 }1695 else if (child.type === 11 /* FOR */) {1696 // Do not hoist v-for single child because it has to be a block1697 walk(child, context, child.children.length === 1);1698 }1699 else if (child.type === 9 /* IF */) {1700 for (let i = 0; i < child.branches.length; i++) {1701 // Do not hoist v-if single child because it has to be a block1702 walk(child.branches[i], context, child.branches[i].children.length === 1);1703 }1704 }1705 }1706 if (canStringify && hasHoistedNode && context.transformHoist) {1707 context.transformHoist(children, context, node);1708 }1709}1710function getConstantType(node, context) {1711 const { constantCache } = context;1712 switch (node.type) {1713 case 1 /* ELEMENT */:1714 if (node.tagType !== 0 /* ELEMENT */) {1715 return 0 /* NOT_CONSTANT */;1716 }1717 const cached = constantCache.get(node);1718 if (cached !== undefined) {1719 return cached;1720 }1721 const codegenNode = node.codegenNode;1722 if (codegenNode.type !== 13 /* VNODE_CALL */) {1723 return 0 /* NOT_CONSTANT */;1724 }1725 const flag = getPatchFlag(codegenNode);1726 if (!flag) {1727 let returnType = 3 /* CAN_STRINGIFY */;1728 // Element itself has no patch flag. However we still need to check:1729 // 1. Even for a node with no patch flag, it is possible for it to contain1730 // non-hoistable expressions that refers to scope variables, e.g. compiler1731 // injected keys or cached event handlers. Therefore we need to always1732 // check the codegenNode's props to be sure.1733 const generatedPropsType = getGeneratedPropsConstantType(node, context);1734 if (generatedPropsType === 0 /* NOT_CONSTANT */) {1735 constantCache.set(node, 0 /* NOT_CONSTANT */);1736 return 0 /* NOT_CONSTANT */;1737 }1738 if (generatedPropsType < returnType) {1739 returnType = generatedPropsType;1740 }1741 // 2. its children.1742 for (let i = 0; i < node.children.length; i++) {1743 const childType = getConstantType(node.children[i], context);1744 if (childType === 0 /* NOT_CONSTANT */) {1745 constantCache.set(node, 0 /* NOT_CONSTANT */);1746 return 0 /* NOT_CONSTANT */;1747 }1748 if (childType < returnType) {1749 returnType = childType;1750 }1751 }1752 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-01753 // type, check if any of the props can cause the type to be lowered1754 // we can skip can_patch because it's guaranteed by the absence of a1755 // patchFlag.1756 if (returnType > 1 /* CAN_SKIP_PATCH */) {1757 for (let i = 0; i < node.props.length; i++) {1758 const p = node.props[i];1759 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {1760 const expType = getConstantType(p.exp, context);1761 if (expType === 0 /* NOT_CONSTANT */) {1762 constantCache.set(node, 0 /* NOT_CONSTANT */);1763 return 0 /* NOT_CONSTANT */;1764 }1765 if (expType < returnType) {1766 returnType = expType;1767 }1768 }1769 }1770 }1771 // only svg/foreignObject could be block here, however if they are1772 // static then they don't need to be blocks since there will be no1773 // nested updates.1774 if (codegenNode.isBlock) {1775 context.removeHelper(OPEN_BLOCK);1776 context.removeHelper(CREATE_BLOCK);1777 codegenNode.isBlock = false;1778 context.helper(CREATE_VNODE);1779 }1780 constantCache.set(node, returnType);1781 return returnType;1782 }1783 else {1784 constantCache.set(node, 0 /* NOT_CONSTANT */);1785 return 0 /* NOT_CONSTANT */;1786 }1787 case 2 /* TEXT */:1788 case 3 /* COMMENT */:1789 return 3 /* CAN_STRINGIFY */;1790 case 9 /* IF */:1791 case 11 /* FOR */:1792 case 10 /* IF_BRANCH */:1793 return 0 /* NOT_CONSTANT */;1794 case 5 /* INTERPOLATION */:1795 case 12 /* TEXT_CALL */:1796 return getConstantType(node.content, context);1797 case 4 /* SIMPLE_EXPRESSION */:1798 return node.constType;1799 case 8 /* COMPOUND_EXPRESSION */:1800 let returnType = 3 /* CAN_STRINGIFY */;1801 for (let i = 0; i < node.children.length; i++) {1802 const child = node.children[i];1803 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(child) || (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isSymbol)(child)) {1804 continue;1805 }1806 const childType = getConstantType(child, context);1807 if (childType === 0 /* NOT_CONSTANT */) {1808 return 0 /* NOT_CONSTANT */;1809 }1810 else if (childType < returnType) {1811 returnType = childType;1812 }1813 }1814 return returnType;1815 default:1816 if ((true)) ;1817 return 0 /* NOT_CONSTANT */;1818 }1819}1820function getGeneratedPropsConstantType(node, context) {1821 let returnType = 3 /* CAN_STRINGIFY */;1822 const props = getNodeProps(node);1823 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {1824 const { properties } = props;1825 for (let i = 0; i < properties.length; i++) {1826 const { key, value } = properties[i];1827 const keyType = getConstantType(key, context);1828 if (keyType === 0 /* NOT_CONSTANT */) {1829 return keyType;1830 }1831 if (keyType < returnType) {1832 returnType = keyType;1833 }1834 if (value.type !== 4 /* SIMPLE_EXPRESSION */) {1835 return 0 /* NOT_CONSTANT */;1836 }1837 const valueType = getConstantType(value, context);1838 if (valueType === 0 /* NOT_CONSTANT */) {1839 return valueType;1840 }1841 if (valueType < returnType) {1842 returnType = valueType;1843 }1844 }1845 }1846 return returnType;1847}1848function getNodeProps(node) {1849 const codegenNode = node.codegenNode;1850 if (codegenNode.type === 13 /* VNODE_CALL */) {1851 return codegenNode.props;1852 }1853}1854function getPatchFlag(node) {1855 const flag = node.patchFlag;1856 return flag ? parseInt(flag, 10) : undefined;1857}1858function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = _vue_shared__WEBPACK_IMPORTED_MODULE_0__.NOOP, isCustomElement = _vue_shared__WEBPACK_IMPORTED_MODULE_0__.NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, ssrCssVars = ``, bindingMetadata = _vue_shared__WEBPACK_IMPORTED_MODULE_0__.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {1859 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);1860 const context = {1861 // options1862 selfName: nameMatch && (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.capitalize)((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.camelize)(nameMatch[1])),1863 prefixIdentifiers,1864 hoistStatic,1865 cacheHandlers,1866 nodeTransforms,1867 directiveTransforms,1868 transformHoist,1869 isBuiltInComponent,1870 isCustomElement,1871 expressionPlugins,1872 scopeId,1873 slotted,1874 ssr,1875 ssrCssVars,1876 bindingMetadata,1877 inline,1878 isTS,1879 onError,1880 onWarn,1881 compatConfig,1882 // state1883 root,1884 helpers: new Map(),1885 components: new Set(),1886 directives: new Set(),1887 hoists: [],1888 imports: [],1889 constantCache: new Map(),1890 temps: 0,1891 cached: 0,1892 identifiers: Object.create(null),1893 scopes: {1894 vFor: 0,1895 vSlot: 0,1896 vPre: 0,1897 vOnce: 01898 },1899 parent: null,1900 currentNode: root,1901 childIndex: 0,1902 // methods1903 helper(name) {1904 const count = context.helpers.get(name) || 0;1905 context.helpers.set(name, count + 1);1906 return name;1907 },1908 removeHelper(name) {1909 const count = context.helpers.get(name);1910 if (count) {1911 const currentCount = count - 1;1912 if (!currentCount) {1913 context.helpers.delete(name);1914 }1915 else {1916 context.helpers.set(name, currentCount);1917 }1918 }1919 },1920 helperString(name) {1921 return `_${helperNameMap[context.helper(name)]}`;1922 },1923 replaceNode(node) {1924 /* istanbul ignore if */1925 if ((true)) {1926 if (!context.currentNode) {1927 throw new Error(`Node being replaced is already removed.`);1928 }1929 if (!context.parent) {1930 throw new Error(`Cannot replace root node.`);1931 }1932 }1933 context.parent.children[context.childIndex] = context.currentNode = node;1934 },1935 removeNode(node) {1936 if (( true) && !context.parent) {1937 throw new Error(`Cannot remove root node.`);1938 }1939 const list = context.parent.children;1940 const removalIndex = node1941 ? list.indexOf(node)1942 : context.currentNode1943 ? context.childIndex1944 : -1;1945 /* istanbul ignore if */1946 if (( true) && removalIndex < 0) {1947 throw new Error(`node being removed is not a child of current parent`);1948 }1949 if (!node || node === context.currentNode) {1950 // current node removed1951 context.currentNode = null;1952 context.onNodeRemoved();1953 }1954 else {1955 // sibling node removed1956 if (context.childIndex > removalIndex) {1957 context.childIndex--;1958 context.onNodeRemoved();1959 }1960 }1961 context.parent.children.splice(removalIndex, 1);1962 },1963 onNodeRemoved: () => { },1964 addIdentifiers(exp) {1965 },1966 removeIdentifiers(exp) {1967 },1968 hoist(exp) {1969 context.hoists.push(exp);1970 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);1971 identifier.hoisted = exp;1972 return identifier;1973 },1974 cache(exp, isVNode = false) {1975 return createCacheExpression(++context.cached, exp, isVNode);1976 }1977 };1978 {1979 context.filters = new Set();1980 }1981 return context;1982}1983function transform(root, options) {1984 const context = createTransformContext(root, options);1985 traverseNode(root, context);1986 if (options.hoistStatic) {1987 hoistStatic(root, context);1988 }1989 if (!options.ssr) {1990 createRootCodegen(root, context);1991 }1992 // finalize meta information1993 root.helpers = [...context.helpers.keys()];1994 root.components = [...context.components];1995 root.directives = [...context.directives];1996 root.imports = context.imports;1997 root.hoists = context.hoists;1998 root.temps = context.temps;1999 root.cached = context.cached;2000 {2001 root.filters = [...context.filters];2002 }2003}2004function createRootCodegen(root, context) {2005 const { helper, removeHelper } = context;2006 const { children } = root;2007 if (children.length === 1) {2008 const child = children[0];2009 // if the single child is an element, turn it into a block.2010 if (isSingleElementRoot(root, child) && child.codegenNode) {2011 // single element root is never hoisted so codegenNode will never be2012 // SimpleExpressionNode2013 const codegenNode = child.codegenNode;2014 if (codegenNode.type === 13 /* VNODE_CALL */) {2015 if (!codegenNode.isBlock) {2016 removeHelper(CREATE_VNODE);2017 codegenNode.isBlock = true;2018 helper(OPEN_BLOCK);2019 helper(CREATE_BLOCK);2020 }2021 }2022 root.codegenNode = codegenNode;2023 }2024 else {2025 // - single <slot/>, IfNode, ForNode: already blocks.2026 // - single text node: always patched.2027 // root codegen falls through via genNode()2028 root.codegenNode = child;2029 }2030 }2031 else if (children.length > 1) {2032 // root has multiple nodes - return a fragment block.2033 let patchFlag = 64 /* STABLE_FRAGMENT */;2034 let patchFlagText = _vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[64];2035 // check if the fragment actually contains a single valid child with2036 // the rest being comments2037 if (( true) &&2038 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2039 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2040 patchFlagText += `, ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[2048]}`;2041 }2042 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + (( true) ? ` /* ${patchFlagText} */` : 0), undefined, undefined, true);2043 }2044 else ;2045}2046function traverseChildren(parent, context) {2047 let i = 0;2048 const nodeRemoved = () => {2049 i--;2050 };2051 for (; i < parent.children.length; i++) {2052 const child = parent.children[i];2053 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(child))2054 continue;2055 context.parent = parent;2056 context.childIndex = i;2057 context.onNodeRemoved = nodeRemoved;2058 traverseNode(child, context);2059 }2060}2061function traverseNode(node, context) {2062 context.currentNode = node;2063 // apply transform plugins2064 const { nodeTransforms } = context;2065 const exitFns = [];2066 for (let i = 0; i < nodeTransforms.length; i++) {2067 const onExit = nodeTransforms[i](node, context);2068 if (onExit) {2069 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(onExit)) {2070 exitFns.push(...onExit);2071 }2072 else {2073 exitFns.push(onExit);2074 }2075 }2076 if (!context.currentNode) {2077 // node was removed2078 return;2079 }2080 else {2081 // node may have been replaced2082 node = context.currentNode;2083 }2084 }2085 switch (node.type) {2086 case 3 /* COMMENT */:2087 if (!context.ssr) {2088 // inject import for the Comment symbol, which is needed for creating2089 // comment nodes with `createVNode`2090 context.helper(CREATE_COMMENT);2091 }2092 break;2093 case 5 /* INTERPOLATION */:2094 // no need to traverse, but we need to inject toString helper2095 if (!context.ssr) {2096 context.helper(TO_DISPLAY_STRING);2097 }2098 break;2099 // for container types, further traverse downwards2100 case 9 /* IF */:2101 for (let i = 0; i < node.branches.length; i++) {2102 traverseNode(node.branches[i], context);2103 }2104 break;2105 case 10 /* IF_BRANCH */:2106 case 11 /* FOR */:2107 case 1 /* ELEMENT */:2108 case 0 /* ROOT */:2109 traverseChildren(node, context);2110 break;2111 }2112 // exit transforms2113 context.currentNode = node;2114 let i = exitFns.length;2115 while (i--) {2116 exitFns[i]();2117 }2118}2119function createStructuralDirectiveTransform(name, fn) {2120 const matches = (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(name)2121 ? (n) => n === name2122 : (n) => name.test(n);2123 return (node, context) => {2124 if (node.type === 1 /* ELEMENT */) {2125 const { props } = node;2126 // structural directive transforms are not concerned with slots2127 // as they are handled separately in vSlot.ts2128 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2129 return;2130 }2131 const exitFns = [];2132 for (let i = 0; i < props.length; i++) {2133 const prop = props[i];2134 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2135 // structural directives are removed to avoid infinite recursion2136 // also we remove them *before* applying so that it can further2137 // traverse itself in case it moves the node around2138 props.splice(i, 1);2139 i--;2140 const onExit = fn(node, prop, context);2141 if (onExit)2142 exitFns.push(onExit);2143 }2144 }2145 return exitFns;2146 }2147 };2148}2149const PURE_ANNOTATION = `/*#__PURE__*/`;2150function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false, isTS = false }) {2151 const context = {2152 mode,2153 prefixIdentifiers,2154 sourceMap,2155 filename,2156 scopeId,2157 optimizeImports,2158 runtimeGlobalName,2159 runtimeModuleName,2160 ssr,2161 isTS,2162 source: ast.loc.source,2163 code: ``,2164 column: 1,2165 line: 1,2166 offset: 0,2167 indentLevel: 0,2168 pure: false,2169 map: undefined,2170 helper(key) {2171 return `_${helperNameMap[key]}`;2172 },2173 push(code, node) {2174 context.code += code;2175 },2176 indent() {2177 newline(++context.indentLevel);2178 },2179 deindent(withoutNewLine = false) {2180 if (withoutNewLine) {2181 --context.indentLevel;2182 }2183 else {2184 newline(--context.indentLevel);2185 }2186 },2187 newline() {2188 newline(context.indentLevel);2189 }2190 };2191 function newline(n) {2192 context.push('\n' + ` `.repeat(n));2193 }2194 return context;2195}2196function generate(ast, options = {}) {2197 const context = createCodegenContext(ast, options);2198 if (options.onContextCreated)2199 options.onContextCreated(context);2200 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2201 const hasHelpers = ast.helpers.length > 0;2202 const useWithBlock = !prefixIdentifiers && mode !== 'module';2203 // preambles2204 // in setup() inline mode, the preamble is generated in a sub context2205 // and returned separately.2206 const preambleContext = context;2207 {2208 genFunctionPreamble(ast, preambleContext);2209 }2210 // enter render function2211 const functionName = ssr ? `ssrRender` : `render`;2212 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2213 const signature = args.join(', ');2214 {2215 push(`function ${functionName}(${signature}) {`);2216 }2217 indent();2218 if (useWithBlock) {2219 push(`with (_ctx) {`);2220 indent();2221 // function mode const declarations should be inside with block2222 // also they should be renamed to avoid collision with user properties2223 if (hasHelpers) {2224 push(`const { ${ast.helpers2225 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2226 .join(', ')} } = _Vue`);2227 push(`\n`);2228 newline();2229 }2230 }2231 // generate asset resolution statements2232 if (ast.components.length) {2233 genAssets(ast.components, 'component', context);2234 if (ast.directives.length || ast.temps > 0) {2235 newline();2236 }2237 }2238 if (ast.directives.length) {2239 genAssets(ast.directives, 'directive', context);2240 if (ast.temps > 0) {2241 newline();2242 }2243 }2244 if (ast.filters && ast.filters.length) {2245 newline();2246 genAssets(ast.filters, 'filter', context);2247 newline();2248 }2249 if (ast.temps > 0) {2250 push(`let `);2251 for (let i = 0; i < ast.temps; i++) {2252 push(`${i > 0 ? `, ` : ``}_temp${i}`);2253 }2254 }2255 if (ast.components.length || ast.directives.length || ast.temps) {2256 push(`\n`);2257 newline();2258 }2259 // generate the VNode tree expression2260 if (!ssr) {2261 push(`return `);2262 }2263 if (ast.codegenNode) {2264 genNode(ast.codegenNode, context);2265 }2266 else {2267 push(`null`);2268 }2269 if (useWithBlock) {2270 deindent();2271 push(`}`);2272 }2273 deindent();2274 push(`}`);2275 return {2276 ast,2277 code: context.code,2278 preamble: ``,2279 // SourceMapGenerator does have toJSON() method but it's not in the types2280 map: context.map ? context.map.toJSON() : undefined2281 };2282}2283function genFunctionPreamble(ast, context) {2284 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName } = context;2285 const VueBinding = runtimeGlobalName;2286 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2287 // Generate const declaration for helpers2288 // In prefix mode, we place the const declaration at top so it's done2289 // only once; But if we not prefixing, we place the declaration inside the2290 // with block so it doesn't incur the `in` check cost for every helper access.2291 if (ast.helpers.length > 0) {2292 {2293 // "with" mode.2294 // save Vue in a separate variable to avoid collision2295 push(`const _Vue = ${VueBinding}\n`);2296 // in "with" mode, helpers are declared inside the with block to avoid2297 // has check cost, but hoists are lifted out of the function - we need2298 // to provide the helper here.2299 if (ast.hoists.length) {2300 const staticHelpers = [2301 CREATE_VNODE,2302 CREATE_COMMENT,2303 CREATE_TEXT,2304 CREATE_STATIC2305 ]2306 .filter(helper => ast.helpers.includes(helper))2307 .map(aliasHelper)2308 .join(', ');2309 push(`const { ${staticHelpers} } = _Vue\n`);2310 }2311 }2312 }2313 genHoists(ast.hoists, context);2314 newline();2315 push(`return `);2316}2317function genAssets(assets, type, { helper, push, newline, isTS }) {2318 const resolver = helper(type === 'filter'2319 ? RESOLVE_FILTER2320 : type === 'component'2321 ? RESOLVE_COMPONENT2322 : RESOLVE_DIRECTIVE);2323 for (let i = 0; i < assets.length; i++) {2324 let id = assets[i];2325 // potential component implicit self-reference inferred from SFC filename2326 const maybeSelfReference = id.endsWith('__self');2327 if (maybeSelfReference) {2328 id = id.slice(0, -6);2329 }2330 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);2331 if (i < assets.length - 1) {2332 newline();2333 }2334 }2335}2336function genHoists(hoists, context) {2337 if (!hoists.length) {2338 return;2339 }2340 context.pure = true;2341 const { push, newline, helper, scopeId, mode } = context;2342 newline();2343 hoists.forEach((exp, i) => {2344 if (exp) {2345 push(`const _hoisted_${i + 1} = `);2346 genNode(exp, context);2347 newline();2348 }2349 });2350 context.pure = false;2351}2352function isText$1(n) {2353 return ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(n) ||2354 n.type === 4 /* SIMPLE_EXPRESSION */ ||2355 n.type === 2 /* TEXT */ ||2356 n.type === 5 /* INTERPOLATION */ ||2357 n.type === 8 /* COMPOUND_EXPRESSION */);2358}2359function genNodeListAsArray(nodes, context) {2360 const multilines = nodes.length > 3 ||2361 ((( true)) && nodes.some(n => (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(n) || !isText$1(n)));2362 context.push(`[`);2363 multilines && context.indent();2364 genNodeList(nodes, context, multilines);2365 multilines && context.deindent();2366 context.push(`]`);2367}2368function genNodeList(nodes, context, multilines = false, comma = true) {2369 const { push, newline } = context;2370 for (let i = 0; i < nodes.length; i++) {2371 const node = nodes[i];2372 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(node)) {2373 push(node);2374 }2375 else if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(node)) {2376 genNodeListAsArray(node, context);2377 }2378 else {2379 genNode(node, context);2380 }2381 if (i < nodes.length - 1) {2382 if (multilines) {2383 comma && push(',');2384 newline();2385 }2386 else {2387 comma && push(', ');2388 }2389 }2390 }2391}2392function genNode(node, context) {2393 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(node)) {2394 context.push(node);2395 return;2396 }2397 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isSymbol)(node)) {2398 context.push(context.helper(node));2399 return;2400 }2401 switch (node.type) {2402 case 1 /* ELEMENT */:2403 case 9 /* IF */:2404 case 11 /* FOR */:2405 ( true) &&2406 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2407 `Apply appropriate transforms first.`);2408 genNode(node.codegenNode, context);2409 break;2410 case 2 /* TEXT */:2411 genText(node, context);2412 break;2413 case 4 /* SIMPLE_EXPRESSION */:2414 genExpression(node, context);2415 break;2416 case 5 /* INTERPOLATION */:2417 genInterpolation(node, context);2418 break;2419 case 12 /* TEXT_CALL */:2420 genNode(node.codegenNode, context);2421 break;2422 case 8 /* COMPOUND_EXPRESSION */:2423 genCompoundExpression(node, context);2424 break;2425 case 3 /* COMMENT */:2426 genComment(node, context);2427 break;2428 case 13 /* VNODE_CALL */:2429 genVNodeCall(node, context);2430 break;2431 case 14 /* JS_CALL_EXPRESSION */:2432 genCallExpression(node, context);2433 break;2434 case 15 /* JS_OBJECT_EXPRESSION */:2435 genObjectExpression(node, context);2436 break;2437 case 17 /* JS_ARRAY_EXPRESSION */:2438 genArrayExpression(node, context);2439 break;2440 case 18 /* JS_FUNCTION_EXPRESSION */:2441 genFunctionExpression(node, context);2442 break;2443 case 19 /* JS_CONDITIONAL_EXPRESSION */:2444 genConditionalExpression(node, context);2445 break;2446 case 20 /* JS_CACHE_EXPRESSION */:2447 genCacheExpression(node, context);2448 break;2449 // SSR only types2450 case 21 /* JS_BLOCK_STATEMENT */:2451 break;2452 case 22 /* JS_TEMPLATE_LITERAL */:2453 break;2454 case 23 /* JS_IF_STATEMENT */:2455 break;2456 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2457 break;2458 case 25 /* JS_SEQUENCE_EXPRESSION */:2459 break;2460 case 26 /* JS_RETURN_STATEMENT */:2461 break;2462 /* istanbul ignore next */2463 case 10 /* IF_BRANCH */:2464 // noop2465 break;2466 default:2467 if ((true)) {2468 assert(false, `unhandled codegen node type: ${node.type}`);2469 // make sure we exhaust all possible types2470 const exhaustiveCheck = node;2471 return exhaustiveCheck;2472 }2473 }2474}2475function genText(node, context) {2476 context.push(JSON.stringify(node.content), node);2477}2478function genExpression(node, context) {2479 const { content, isStatic } = node;2480 context.push(isStatic ? JSON.stringify(content) : content, node);2481}2482function genInterpolation(node, context) {2483 const { push, helper, pure } = context;2484 if (pure)2485 push(PURE_ANNOTATION);2486 push(`${helper(TO_DISPLAY_STRING)}(`);2487 genNode(node.content, context);2488 push(`)`);2489}2490function genCompoundExpression(node, context) {2491 for (let i = 0; i < node.children.length; i++) {2492 const child = node.children[i];2493 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(child)) {2494 context.push(child);2495 }2496 else {2497 genNode(child, context);2498 }2499 }2500}2501function genExpressionAsPropertyKey(node, context) {2502 const { push } = context;2503 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2504 push(`[`);2505 genCompoundExpression(node, context);2506 push(`]`);2507 }2508 else if (node.isStatic) {2509 // only quote keys if necessary2510 const text = isSimpleIdentifier(node.content)2511 ? node.content2512 : JSON.stringify(node.content);2513 push(text, node);2514 }2515 else {2516 push(`[${node.content}]`, node);2517 }2518}2519function genComment(node, context) {2520 const { push, helper, pure } = context;2521 if (pure) {2522 push(PURE_ANNOTATION);2523 }2524 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2525}2526function genVNodeCall(node, context) {2527 const { push, helper, pure } = context;2528 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking } = node;2529 if (directives) {2530 push(helper(WITH_DIRECTIVES) + `(`);2531 }2532 if (isBlock) {2533 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);2534 }2535 if (pure) {2536 push(PURE_ANNOTATION);2537 }2538 push(helper(isBlock ? CREATE_BLOCK : CREATE_VNODE) + `(`, node);2539 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2540 push(`)`);2541 if (isBlock) {2542 push(`)`);2543 }2544 if (directives) {2545 push(`, `);2546 genNode(directives, context);2547 push(`)`);2548 }2549}2550function genNullableArgs(args) {2551 let i = args.length;2552 while (i--) {2553 if (args[i] != null)2554 break;2555 }2556 return args.slice(0, i + 1).map(arg => arg || `null`);2557}2558// JavaScript2559function genCallExpression(node, context) {2560 const { push, helper, pure } = context;2561 const callee = (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isString)(node.callee) ? node.callee : helper(node.callee);2562 if (pure) {2563 push(PURE_ANNOTATION);2564 }2565 push(callee + `(`, node);2566 genNodeList(node.arguments, context);2567 push(`)`);2568}2569function genObjectExpression(node, context) {2570 const { push, indent, deindent, newline } = context;2571 const { properties } = node;2572 if (!properties.length) {2573 push(`{}`, node);2574 return;2575 }2576 const multilines = properties.length > 1 ||2577 ((( true)) &&2578 properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2579 push(multilines ? `{` : `{ `);2580 multilines && indent();2581 for (let i = 0; i < properties.length; i++) {2582 const { key, value } = properties[i];2583 // key2584 genExpressionAsPropertyKey(key, context);2585 push(`: `);2586 // value2587 genNode(value, context);2588 if (i < properties.length - 1) {2589 // will only reach this if it's multilines2590 push(`,`);2591 newline();2592 }2593 }2594 multilines && deindent();2595 push(multilines ? `}` : ` }`);2596}2597function genArrayExpression(node, context) {2598 genNodeListAsArray(node.elements, context);2599}2600function genFunctionExpression(node, context) {2601 const { push, indent, deindent, scopeId, mode } = context;2602 const { params, returns, body, newline, isSlot } = node;2603 if (isSlot) {2604 // wrap slot functions with owner context2605 push(`_${helperNameMap[WITH_CTX]}(`);2606 }2607 push(`(`, node);2608 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(params)) {2609 genNodeList(params, context);2610 }2611 else if (params) {2612 genNode(params, context);2613 }2614 push(`) => `);2615 if (newline || body) {2616 push(`{`);2617 indent();2618 }2619 if (returns) {2620 if (newline) {2621 push(`return `);2622 }2623 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isArray)(returns)) {2624 genNodeListAsArray(returns, context);2625 }2626 else {2627 genNode(returns, context);2628 }2629 }2630 else if (body) {2631 genNode(body, context);2632 }2633 if (newline || body) {2634 deindent();2635 push(`}`);2636 }2637 if (isSlot) {2638 if (node.isNonScopedSlot) {2639 push(`, undefined, true`);2640 }2641 push(`)`);2642 }2643}2644function genConditionalExpression(node, context) {2645 const { test, consequent, alternate, newline: needNewline } = node;2646 const { push, indent, deindent, newline } = context;2647 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2648 const needsParens = !isSimpleIdentifier(test.content);2649 needsParens && push(`(`);2650 genExpression(test, context);2651 needsParens && push(`)`);2652 }2653 else {2654 push(`(`);2655 genNode(test, context);2656 push(`)`);2657 }2658 needNewline && indent();2659 context.indentLevel++;2660 needNewline || push(` `);2661 push(`? `);2662 genNode(consequent, context);2663 context.indentLevel--;2664 needNewline && newline();2665 needNewline || push(` `);2666 push(`: `);2667 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2668 if (!isNested) {2669 context.indentLevel++;2670 }2671 genNode(alternate, context);2672 if (!isNested) {2673 context.indentLevel--;2674 }2675 needNewline && deindent(true /* without newline */);2676}2677function genCacheExpression(node, context) {2678 const { push, helper, indent, deindent, newline } = context;2679 push(`_cache[${node.index}] || (`);2680 if (node.isVNode) {2681 indent();2682 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2683 newline();2684 }2685 push(`_cache[${node.index}] = `);2686 genNode(node.value, context);2687 if (node.isVNode) {2688 push(`,`);2689 newline();2690 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2691 newline();2692 push(`_cache[${node.index}]`);2693 deindent();2694 }2695 push(`)`);2696}2697// these keywords should not appear inside expressions, but operators like2698// typeof, instanceof and in are allowed2699const prohibitedKeywordRE = new RegExp('\\b' +2700 ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +2701 'super,throw,while,yield,delete,export,import,return,switch,default,' +2702 'extends,finally,continue,debugger,function,arguments,typeof,void')2703 .split(',')2704 .join('\\b|\\b') +2705 '\\b');2706// strip strings in expressions2707const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;2708/**2709 * Validate a non-prefixed expression.2710 * This is only called when using the in-browser runtime compiler since it2711 * doesn't prefix expressions.2712 */2713function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) {2714 const exp = node.content;2715 // empty expressions are validated per-directive since some directives2716 // do allow empty expressions.2717 if (!exp.trim()) {2718 return;2719 }2720 try {2721 new Function(asRawStatements2722 ? ` ${exp} `2723 : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`);2724 }2725 catch (e) {2726 let message = e.message;2727 const keywordMatch = exp2728 .replace(stripStringRE, '')2729 .match(prohibitedKeywordRE);2730 if (keywordMatch) {2731 message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`;2732 }2733 context.onError(createCompilerError(43 /* X_INVALID_EXPRESSION */, node.loc, undefined, message));2734 }2735}2736const transformExpression = (node, context) => {2737 if (node.type === 5 /* INTERPOLATION */) {2738 node.content = processExpression(node.content, context);2739 }2740 else if (node.type === 1 /* ELEMENT */) {2741 // handle directives on element2742 for (let i = 0; i < node.props.length; i++) {2743 const dir = node.props[i];2744 // do not process for v-on & v-for since they are special handled2745 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {2746 const exp = dir.exp;2747 const arg = dir.arg;2748 // do not process exp if this is v-on:arg - we need special handling2749 // for wrapping inline statements.2750 if (exp &&2751 exp.type === 4 /* SIMPLE_EXPRESSION */ &&2752 !(dir.name === 'on' && arg)) {2753 dir.exp = processExpression(exp, context, 2754 // slot args must be processed as function params2755 dir.name === 'slot');2756 }2757 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {2758 dir.arg = processExpression(arg, context);2759 }2760 }2761 }2762 }2763};2764// Important: since this function uses Node.js only dependencies, it should2765// always be used with a leading !true check so that it can be2766// tree-shaken from the browser build.2767function processExpression(node, context, 2768// some expressions like v-slot props & v-for aliases should be parsed as2769// function params2770asParams = false, 2771// v-on handler values may contain multiple statements2772asRawStatements = false) {2773 {2774 if ((true)) {2775 // simple in-browser validation (same logic in 2.x)2776 validateBrowserExpression(node, context, asParams, asRawStatements);2777 }2778 return node;2779 }2780}2781const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {2782 return processIf(node, dir, context, (ifNode, branch, isRoot) => {2783 // #1587: We need to dynamically increment the key based on the current2784 // node's sibling nodes, since chained v-if/else branches are2785 // rendered at the same depth2786 const siblings = context.parent.children;2787 let i = siblings.indexOf(ifNode);2788 let key = 0;2789 while (i-- >= 0) {2790 const sibling = siblings[i];2791 if (sibling && sibling.type === 9 /* IF */) {2792 key += sibling.branches.length;2793 }2794 }2795 // Exit callback. Complete the codegenNode when all children have been2796 // transformed.2797 return () => {2798 if (isRoot) {2799 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);2800 }2801 else {2802 // attach this branch's codegen node to the v-if root.2803 const parentCondition = getParentCondition(ifNode.codegenNode);2804 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);2805 }2806 };2807 });2808});2809// target-agnostic transform used for both Client and SSR2810function processIf(node, dir, context, processCodegen) {2811 if (dir.name !== 'else' &&2812 (!dir.exp || !dir.exp.content.trim())) {2813 const loc = dir.exp ? dir.exp.loc : node.loc;2814 context.onError(createCompilerError(27 /* X_V_IF_NO_EXPRESSION */, dir.loc));2815 dir.exp = createSimpleExpression(`true`, false, loc);2816 }2817 if ( true && dir.exp) {2818 validateBrowserExpression(dir.exp, context);2819 }2820 if (dir.name === 'if') {2821 const branch = createIfBranch(node, dir);2822 const ifNode = {2823 type: 9 /* IF */,2824 loc: node.loc,2825 branches: [branch]2826 };2827 context.replaceNode(ifNode);2828 if (processCodegen) {2829 return processCodegen(ifNode, branch, true);2830 }2831 }2832 else {2833 // locate the adjacent v-if2834 const siblings = context.parent.children;2835 const comments = [];2836 let i = siblings.indexOf(node);2837 while (i-- >= -1) {2838 const sibling = siblings[i];2839 if (( true) && sibling && sibling.type === 3 /* COMMENT */) {2840 context.removeNode(sibling);2841 comments.unshift(sibling);2842 continue;2843 }2844 if (sibling &&2845 sibling.type === 2 /* TEXT */ &&2846 !sibling.content.trim().length) {2847 context.removeNode(sibling);2848 continue;2849 }2850 if (sibling && sibling.type === 9 /* IF */) {2851 // move the node to the if node's branches2852 context.removeNode();2853 const branch = createIfBranch(node, dir);2854 if (( true) &&2855 comments.length &&2856 // #3619 ignore comments if the v-if is direct child of <transition>2857 !(context.parent &&2858 context.parent.type === 1 /* ELEMENT */ &&2859 isBuiltInType(context.parent.tag, 'transition'))) {2860 branch.children = [...comments, ...branch.children];2861 }2862 // check if user is forcing same key on different branches2863 if (true) {2864 const key = branch.userKey;2865 if (key) {2866 sibling.branches.forEach(({ userKey }) => {2867 if (isSameKey(userKey, key)) {2868 context.onError(createCompilerError(28 /* X_V_IF_SAME_KEY */, branch.userKey.loc));2869 }2870 });2871 }2872 }2873 sibling.branches.push(branch);2874 const onExit = processCodegen && processCodegen(sibling, branch, false);2875 // since the branch was removed, it will not be traversed.2876 // make sure to traverse here.2877 traverseNode(branch, context);2878 // call on exit2879 if (onExit)2880 onExit();2881 // make sure to reset currentNode after traversal to indicate this2882 // node has been removed.2883 context.currentNode = null;2884 }2885 else {2886 context.onError(createCompilerError(29 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));2887 }2888 break;2889 }2890 }2891}2892function createIfBranch(node, dir) {2893 return {2894 type: 10 /* IF_BRANCH */,2895 loc: node.loc,2896 condition: dir.name === 'else' ? undefined : dir.exp,2897 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')2898 ? node.children2899 : [node],2900 userKey: findProp(node, `key`)2901 };2902}2903function createCodegenNodeForBranch(branch, keyIndex, context) {2904 if (branch.condition) {2905 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 2906 // make sure to pass in asBlock: true so that the comment node call2907 // closes the current block.2908 createCallExpression(context.helper(CREATE_COMMENT), [2909 ( true) ? '"v-if"' : 0,2910 'true'2911 ]));2912 }2913 else {2914 return createChildrenCodegenNode(branch, keyIndex, context);2915 }2916}2917function createChildrenCodegenNode(branch, keyIndex, context) {2918 const { helper, removeHelper } = context;2919 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));2920 const { children } = branch;2921 const firstChild = children[0];2922 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;2923 if (needFragmentWrapper) {2924 if (children.length === 1 && firstChild.type === 11 /* FOR */) {2925 // optimize away nested fragments when child is a ForNode2926 const vnodeCall = firstChild.codegenNode;2927 injectProp(vnodeCall, keyProperty, context);2928 return vnodeCall;2929 }2930 else {2931 let patchFlag = 64 /* STABLE_FRAGMENT */;2932 let patchFlagText = _vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[64];2933 // check if the fragment actually contains a single valid child with2934 // the rest being comments2935 if (( true) &&2936 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2937 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2938 patchFlagText += `, ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[2048]}`;2939 }2940 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (( true) ? ` /* ${patchFlagText} */` : 0), undefined, undefined, true, false, branch.loc);2941 }2942 }2943 else {2944 const vnodeCall = firstChild2945 .codegenNode;2946 // Change createVNode to createBlock.2947 if (vnodeCall.type === 13 /* VNODE_CALL */ && !vnodeCall.isBlock) {2948 removeHelper(CREATE_VNODE);2949 vnodeCall.isBlock = true;2950 helper(OPEN_BLOCK);2951 helper(CREATE_BLOCK);2952 }2953 // inject branch key2954 injectProp(vnodeCall, keyProperty, context);2955 return vnodeCall;2956 }2957}2958function isSameKey(a, b) {2959 if (!a || a.type !== b.type) {2960 return false;2961 }2962 if (a.type === 6 /* ATTRIBUTE */) {2963 if (a.value.content !== b.value.content) {2964 return false;2965 }2966 }2967 else {2968 // directive2969 const exp = a.exp;2970 const branchExp = b.exp;2971 if (exp.type !== branchExp.type) {2972 return false;2973 }2974 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||2975 (exp.isStatic !== branchExp.isStatic ||2976 exp.content !== branchExp.content)) {2977 return false;2978 }2979 }2980 return true;2981}2982function getParentCondition(node) {2983 while (true) {2984 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {2985 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {2986 node = node.alternate;2987 }2988 else {2989 return node;2990 }2991 }2992 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {2993 node = node.value;2994 }2995 }2996}2997const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {2998 const { helper, removeHelper } = context;2999 return processFor(node, dir, context, forNode => {3000 // create the loop render function expression now, and add the3001 // iterator on exit after all children have been traversed3002 const renderExp = createCallExpression(helper(RENDER_LIST), [3003 forNode.source3004 ]);3005 const keyProp = findProp(node, `key`);3006 const keyProperty = keyProp3007 ? createObjectProperty(`key`, keyProp.type === 6 /* ATTRIBUTE */3008 ? createSimpleExpression(keyProp.value.content, true)3009 : keyProp.exp)3010 : null;3011 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3012 forNode.source.constType > 0 /* NOT_CONSTANT */;3013 const fragmentFlag = isStableFragment3014 ? 64 /* STABLE_FRAGMENT */3015 : keyProp3016 ? 128 /* KEYED_FRAGMENT */3017 : 256 /* UNKEYED_FRAGMENT */;3018 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3019 (( true) ? ` /* ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[fragmentFlag]} */` : 0), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, node.loc);3020 return () => {3021 // finish the codegen now that all children have been traversed3022 let childBlock;3023 const isTemplate = isTemplateNode(node);3024 const { children } = forNode;3025 // check <template v-for> key placement3026 if (( true) && isTemplate) {3027 node.children.some(c => {3028 if (c.type === 1 /* ELEMENT */) {3029 const key = findProp(c, 'key');3030 if (key) {3031 context.onError(createCompilerError(32 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3032 return true;3033 }3034 }3035 });3036 }3037 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3038 const slotOutlet = isSlotOutlet(node)3039 ? node3040 : isTemplate &&3041 node.children.length === 1 &&3042 isSlotOutlet(node.children[0])3043 ? node.children[0] // api-extractor somehow fails to infer this3044 : null;3045 if (slotOutlet) {3046 // <slot v-for="..."> or <template v-for="..."><slot/></template>3047 childBlock = slotOutlet.codegenNode;3048 if (isTemplate && keyProperty) {3049 // <template v-for="..." :key="..."><slot/></template>3050 // we need to inject the key to the renderSlot() call.3051 // the props for renderSlot is passed as the 3rd argument.3052 injectProp(childBlock, keyProperty, context);3053 }3054 }3055 else if (needFragmentWrapper) {3056 // <template v-for="..."> with text or multi-elements3057 // should generate a fragment block for each loop3058 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3059 (( true)3060 ? ` /* ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[64]} */`3061 : 0), undefined, undefined, true);3062 }3063 else {3064 // Normal element v-for. Directly use the child's codegenNode3065 // but mark it as a block.3066 childBlock = children[0]3067 .codegenNode;3068 if (isTemplate && keyProperty) {3069 injectProp(childBlock, keyProperty, context);3070 }3071 if (childBlock.isBlock !== !isStableFragment) {3072 if (childBlock.isBlock) {3073 // switch from block to vnode3074 removeHelper(OPEN_BLOCK);3075 removeHelper(CREATE_BLOCK);3076 }3077 else {3078 // switch from vnode to block3079 removeHelper(CREATE_VNODE);3080 }3081 }3082 childBlock.isBlock = !isStableFragment;3083 if (childBlock.isBlock) {3084 helper(OPEN_BLOCK);3085 helper(CREATE_BLOCK);3086 }3087 else {3088 helper(CREATE_VNODE);3089 }3090 }3091 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3092 };3093 });3094});3095// target-agnostic transform used for both Client and SSR3096function processFor(node, dir, context, processCodegen) {3097 if (!dir.exp) {3098 context.onError(createCompilerError(30 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3099 return;3100 }3101 const parseResult = parseForExpression(3102 // can only be simple expression because vFor transform is applied3103 // before expression transform.3104 dir.exp, context);3105 if (!parseResult) {3106 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3107 return;3108 }3109 const { addIdentifiers, removeIdentifiers, scopes } = context;3110 const { source, value, key, index } = parseResult;3111 const forNode = {3112 type: 11 /* FOR */,3113 loc: dir.loc,3114 source,3115 valueAlias: value,3116 keyAlias: key,3117 objectIndexAlias: index,3118 parseResult,3119 children: isTemplateNode(node) ? node.children : [node]3120 };3121 context.replaceNode(forNode);3122 // bookkeeping3123 scopes.vFor++;3124 const onExit = processCodegen && processCodegen(forNode);3125 return () => {3126 scopes.vFor--;3127 if (onExit)3128 onExit();3129 };3130}3131const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3132// This regex doesn't cover the case if key or index aliases have destructuring,3133// but those do not make sense in the first place, so this works in practice.3134const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3135const stripParensRE = /^\(|\)$/g;3136function parseForExpression(input, context) {3137 const loc = input.loc;3138 const exp = input.content;3139 const inMatch = exp.match(forAliasRE);3140 if (!inMatch)3141 return;3142 const [, LHS, RHS] = inMatch;3143 const result = {3144 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3145 value: undefined,3146 key: undefined,3147 index: undefined3148 };3149 if (true) {3150 validateBrowserExpression(result.source, context);3151 }3152 let valueContent = LHS.trim()3153 .replace(stripParensRE, '')3154 .trim();3155 const trimmedOffset = LHS.indexOf(valueContent);3156 const iteratorMatch = valueContent.match(forIteratorRE);3157 if (iteratorMatch) {3158 valueContent = valueContent.replace(forIteratorRE, '').trim();3159 const keyContent = iteratorMatch[1].trim();3160 let keyOffset;3161 if (keyContent) {3162 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3163 result.key = createAliasExpression(loc, keyContent, keyOffset);3164 if (true) {3165 validateBrowserExpression(result.key, context, true);3166 }3167 }3168 if (iteratorMatch[2]) {3169 const indexContent = iteratorMatch[2].trim();3170 if (indexContent) {3171 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3172 ? keyOffset + keyContent.length3173 : trimmedOffset + valueContent.length));3174 if (true) {3175 validateBrowserExpression(result.index, context, true);3176 }3177 }3178 }3179 }3180 if (valueContent) {3181 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3182 if (true) {3183 validateBrowserExpression(result.value, context, true);3184 }3185 }3186 return result;3187}3188function createAliasExpression(range, content, offset) {3189 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3190}3191function createForLoopParams({ value, key, index }) {3192 const params = [];3193 if (value) {3194 params.push(value);3195 }3196 if (key) {3197 if (!value) {3198 params.push(createSimpleExpression(`_`, false));3199 }3200 params.push(key);3201 }3202 if (index) {3203 if (!key) {3204 if (!value) {3205 params.push(createSimpleExpression(`_`, false));3206 }3207 params.push(createSimpleExpression(`__`, false));3208 }3209 params.push(index);3210 }3211 return params;3212}3213const defaultFallback = createSimpleExpression(`undefined`, false);3214// A NodeTransform that:3215// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3216// by transformExpression. This is only applied in non-browser builds with3217// { prefixIdentifiers: true }.3218// 2. Track v-slot depths so that we know a slot is inside another slot.3219// Note the exit callback is executed before buildSlots() on the same node,3220// so only nested slots see positive numbers.3221const trackSlotScopes = (node, context) => {3222 if (node.type === 1 /* ELEMENT */ &&3223 (node.tagType === 1 /* COMPONENT */ ||3224 node.tagType === 3 /* TEMPLATE */)) {3225 // We are only checking non-empty v-slot here3226 // since we only care about slots that introduce scope variables.3227 const vSlot = findDir(node, 'slot');3228 if (vSlot) {3229 vSlot.exp;3230 context.scopes.vSlot++;3231 return () => {3232 context.scopes.vSlot--;3233 };3234 }3235 }3236};3237// A NodeTransform that tracks scope identifiers for scoped slots with v-for.3238// This transform is only applied in non-browser builds with { prefixIdentifiers: true }3239const trackVForSlotScopes = (node, context) => {3240 let vFor;3241 if (isTemplateNode(node) &&3242 node.props.some(isVSlot) &&3243 (vFor = findDir(node, 'for'))) {3244 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3245 if (result) {3246 const { value, key, index } = result;3247 const { addIdentifiers, removeIdentifiers } = context;3248 value && addIdentifiers(value);3249 key && addIdentifiers(key);3250 index && addIdentifiers(index);3251 return () => {3252 value && removeIdentifiers(value);3253 key && removeIdentifiers(key);3254 index && removeIdentifiers(index);3255 };3256 }3257 }3258};3259const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3260// Instead of being a DirectiveTransform, v-slot processing is called during3261// transformElement to build the slots object for a component.3262function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3263 context.helper(WITH_CTX);3264 const { children, loc } = node;3265 const slotsProperties = [];3266 const dynamicSlots = [];3267 // If the slot is inside a v-for or another v-slot, force it to be dynamic3268 // since it likely uses a scope variable.3269 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3270 // 1. Check for slot with slotProps on component itself.3271 // <Comp v-slot="{ prop }"/>3272 const onComponentSlot = findDir(node, 'slot', true);3273 if (onComponentSlot) {3274 const { arg, exp } = onComponentSlot;3275 if (arg && !isStaticExp(arg)) {3276 hasDynamicSlots = true;3277 }3278 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));3279 }3280 // 2. Iterate through children and check for template slots3281 // <template v-slot:foo="{ prop }">3282 let hasTemplateSlots = false;3283 let hasNamedDefaultSlot = false;3284 const implicitDefaultChildren = [];3285 const seenSlotNames = new Set();3286 for (let i = 0; i < children.length; i++) {3287 const slotElement = children[i];3288 let slotDir;3289 if (!isTemplateNode(slotElement) ||3290 !(slotDir = findDir(slotElement, 'slot', true))) {3291 // not a <template v-slot>, skip.3292 if (slotElement.type !== 3 /* COMMENT */) {3293 implicitDefaultChildren.push(slotElement);3294 }3295 continue;3296 }3297 if (onComponentSlot) {3298 // already has on-component slot - this is incorrect usage.3299 context.onError(createCompilerError(36 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3300 break;3301 }3302 hasTemplateSlots = true;3303 const { children: slotChildren, loc: slotLoc } = slotElement;3304 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3305 // check if name is dynamic.3306 let staticSlotName;3307 if (isStaticExp(slotName)) {3308 staticSlotName = slotName ? slotName.content : `default`;3309 }3310 else {3311 hasDynamicSlots = true;3312 }3313 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3314 // check if this slot is conditional (v-if/v-for)3315 let vIf;3316 let vElse;3317 let vFor;3318 if ((vIf = findDir(slotElement, 'if'))) {3319 hasDynamicSlots = true;3320 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3321 }3322 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3323 // find adjacent v-if3324 let j = i;3325 let prev;3326 while (j--) {3327 prev = children[j];3328 if (prev.type !== 3 /* COMMENT */) {3329 break;3330 }3331 }3332 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3333 // remove node3334 children.splice(i, 1);3335 i--;3336 // attach this slot to previous conditional3337 let conditional = dynamicSlots[dynamicSlots.length - 1];3338 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3339 conditional = conditional.alternate;3340 }3341 conditional.alternate = vElse.exp3342 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3343 : buildDynamicSlot(slotName, slotFunction);3344 }3345 else {3346 context.onError(createCompilerError(29 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3347 }3348 }3349 else if ((vFor = findDir(slotElement, 'for'))) {3350 hasDynamicSlots = true;3351 const parseResult = vFor.parseResult ||3352 parseForExpression(vFor.exp, context);3353 if (parseResult) {3354 // Render the dynamic slots as an array and add it to the createSlot()3355 // args. The runtime knows how to handle it appropriately.3356 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3357 parseResult.source,3358 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3359 ]));3360 }3361 else {3362 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3363 }3364 }3365 else {3366 // check duplicate static names3367 if (staticSlotName) {3368 if (seenSlotNames.has(staticSlotName)) {3369 context.onError(createCompilerError(37 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3370 continue;3371 }3372 seenSlotNames.add(staticSlotName);3373 if (staticSlotName === 'default') {3374 hasNamedDefaultSlot = true;3375 }3376 }3377 slotsProperties.push(createObjectProperty(slotName, slotFunction));3378 }3379 }3380 if (!onComponentSlot) {3381 const buildDefaultSlotProperty = (props, children) => {3382 const fn = buildSlotFn(props, children, loc);3383 if (context.compatConfig) {3384 fn.isNonScopedSlot = true;3385 }3386 return createObjectProperty(`default`, fn);3387 };3388 if (!hasTemplateSlots) {3389 // implicit default slot (on component)3390 slotsProperties.push(buildDefaultSlotProperty(undefined, children));3391 }3392 else if (implicitDefaultChildren.length &&3393 // #37663394 // with whitespace: 'preserve', whitespaces between slots will end up in3395 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.3396 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {3397 // implicit default slot (mixed with named slots)3398 if (hasNamedDefaultSlot) {3399 context.onError(createCompilerError(38 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));3400 }3401 else {3402 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));3403 }3404 }3405 }3406 const slotFlag = hasDynamicSlots3407 ? 2 /* DYNAMIC */3408 : hasForwardedSlots(node.children)3409 ? 3 /* FORWARDED */3410 : 1 /* STABLE */;3411 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 3412 // 2 = compiled but dynamic = can skip normalization, but must run diff3413 // 1 = compiled and static = can skip normalization AND diff as optimized3414 createSimpleExpression(slotFlag + (( true) ? ` /* ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.slotFlagsText[slotFlag]} */` : 0), false))), loc);3415 if (dynamicSlots.length) {3416 slots = createCallExpression(context.helper(CREATE_SLOTS), [3417 slots,3418 createArrayExpression(dynamicSlots)3419 ]);3420 }3421 return {3422 slots,3423 hasDynamicSlots3424 };3425}3426function buildDynamicSlot(name, fn) {3427 return createObjectExpression([3428 createObjectProperty(`name`, name),3429 createObjectProperty(`fn`, fn)3430 ]);3431}3432function hasForwardedSlots(children) {3433 for (let i = 0; i < children.length; i++) {3434 const child = children[i];3435 switch (child.type) {3436 case 1 /* ELEMENT */:3437 if (child.tagType === 2 /* SLOT */ ||3438 ((child.tagType === 0 /* ELEMENT */ ||3439 child.tagType === 3 /* TEMPLATE */) &&3440 hasForwardedSlots(child.children))) {3441 return true;3442 }3443 break;3444 case 9 /* IF */:3445 if (hasForwardedSlots(child.branches))3446 return true;3447 break;3448 case 10 /* IF_BRANCH */:3449 case 11 /* FOR */:3450 if (hasForwardedSlots(child.children))3451 return true;3452 break;3453 }3454 }3455 return false;3456}3457function isNonWhitespaceContent(node) {3458 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)3459 return true;3460 return node.type === 2 /* TEXT */3461 ? !!node.content.trim()3462 : isNonWhitespaceContent(node.content);3463}3464// some directive transforms (e.g. v-model) may return a symbol for runtime3465// import, which should be used instead of a resolveDirective call.3466const directiveImportMap = new WeakMap();3467// generate a JavaScript AST for this element's codegen3468const transformElement = (node, context) => {3469 // perform the work on exit, after all child expressions have been3470 // processed and merged.3471 return function postTransformElement() {3472 node = context.currentNode;3473 if (!(node.type === 1 /* ELEMENT */ &&3474 (node.tagType === 0 /* ELEMENT */ ||3475 node.tagType === 1 /* COMPONENT */))) {3476 return;3477 }3478 const { tag, props } = node;3479 const isComponent = node.tagType === 1 /* COMPONENT */;3480 // The goal of the transform is to create a codegenNode implementing the3481 // VNodeCall interface.3482 let vnodeTag = isComponent3483 ? resolveComponentType(node, context)3484 : `"${tag}"`;3485 const isDynamicComponent = (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isObject)(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;3486 let vnodeProps;3487 let vnodeChildren;3488 let vnodePatchFlag;3489 let patchFlag = 0;3490 let vnodeDynamicProps;3491 let dynamicPropNames;3492 let vnodeDirectives;3493 let shouldUseBlock = 3494 // dynamic component may resolve to plain elements3495 isDynamicComponent ||3496 vnodeTag === TELEPORT ||3497 vnodeTag === SUSPENSE ||3498 (!isComponent &&3499 // <svg> and <foreignObject> must be forced into blocks so that block3500 // updates inside get proper isSVG flag at runtime. (#639, #643)3501 // This is technically web-specific, but splitting the logic out of core3502 // leads to too much unnecessary complexity.3503 (tag === 'svg' ||3504 tag === 'foreignObject' ||3505 // #938: elements with dynamic keys should be forced into blocks3506 findProp(node, 'key', true)));3507 // props3508 if (props.length > 0) {3509 const propsBuildResult = buildProps(node, context);3510 vnodeProps = propsBuildResult.props;3511 patchFlag = propsBuildResult.patchFlag;3512 dynamicPropNames = propsBuildResult.dynamicPropNames;3513 const directives = propsBuildResult.directives;3514 vnodeDirectives =3515 directives && directives.length3516 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))3517 : undefined;3518 }3519 // children3520 if (node.children.length > 0) {3521 if (vnodeTag === KEEP_ALIVE) {3522 // Although a built-in component, we compile KeepAlive with raw children3523 // instead of slot functions so that it can be used inside Transition3524 // or other Transition-wrapping HOCs.3525 // To ensure correct updates with block optimizations, we need to:3526 // 1. Force keep-alive into a block. This avoids its children being3527 // collected by a parent block.3528 shouldUseBlock = true;3529 // 2. Force keep-alive to always be updated, since it uses raw children.3530 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3531 if (( true) && node.children.length > 1) {3532 context.onError(createCompilerError(44 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {3533 start: node.children[0].loc.start,3534 end: node.children[node.children.length - 1].loc.end,3535 source: ''3536 }));3537 }3538 }3539 const shouldBuildAsSlots = isComponent &&3540 // Teleport is not a real component and has dedicated runtime handling3541 vnodeTag !== TELEPORT &&3542 // explained above.3543 vnodeTag !== KEEP_ALIVE;3544 if (shouldBuildAsSlots) {3545 const { slots, hasDynamicSlots } = buildSlots(node, context);3546 vnodeChildren = slots;3547 if (hasDynamicSlots) {3548 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3549 }3550 }3551 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {3552 const child = node.children[0];3553 const type = child.type;3554 // check for dynamic text children3555 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||3556 type === 8 /* COMPOUND_EXPRESSION */;3557 if (hasDynamicTextChild &&3558 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {3559 patchFlag |= 1 /* TEXT */;3560 }3561 // pass directly if the only child is a text node3562 // (plain / interpolation / expression)3563 if (hasDynamicTextChild || type === 2 /* TEXT */) {3564 vnodeChildren = child;3565 }3566 else {3567 vnodeChildren = node.children;3568 }3569 }3570 else {3571 vnodeChildren = node.children;3572 }3573 }3574 // patchFlag & dynamicPropNames3575 if (patchFlag !== 0) {3576 if ((true)) {3577 if (patchFlag < 0) {3578 // special flags (negative and mutually exclusive)3579 vnodePatchFlag = patchFlag + ` /* ${_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[patchFlag]} */`;3580 }3581 else {3582 // bitwise flags3583 const flagNames = Object.keys(_vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames)3584 .map(Number)3585 .filter(n => n > 0 && patchFlag & n)3586 .map(n => _vue_shared__WEBPACK_IMPORTED_MODULE_0__.PatchFlagNames[n])3587 .join(`, `);3588 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;3589 }3590 }3591 else {}3592 if (dynamicPropNames && dynamicPropNames.length) {3593 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);3594 }3595 }3596 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, node.loc);3597 };3598};3599function resolveComponentType(node, context, ssr = false) {3600 let { tag } = node;3601 // 1. dynamic component3602 const isExplicitDynamic = isComponentTag(tag);3603 const isProp = findProp(node, 'is');3604 if (isProp) {3605 if (isExplicitDynamic ||3606 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {3607 const exp = isProp.type === 6 /* ATTRIBUTE */3608 ? isProp.value && createSimpleExpression(isProp.value.content, true)3609 : isProp.exp;3610 if (exp) {3611 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3612 exp3613 ]);3614 }3615 }3616 else if (isProp.type === 6 /* ATTRIBUTE */ &&3617 isProp.value.content.startsWith('vue:')) {3618 // <button is="vue:xxx">3619 // if not <component>, only is value that starts with "vue:" will be3620 // treated as component by the parse phase and reach here, unless it's3621 // compat mode where all is values are considered components3622 tag = isProp.value.content.slice(4);3623 }3624 }3625 // 1.5 v-is (TODO: Deprecate)3626 const isDir = !isExplicitDynamic && findDir(node, 'is');3627 if (isDir && isDir.exp) {3628 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3629 isDir.exp3630 ]);3631 }3632 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)3633 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);3634 if (builtIn) {3635 // built-ins are simply fallthroughs / have special handling during ssr3636 // so we don't need to import their runtime equivalents3637 if (!ssr)3638 context.helper(builtIn);3639 return builtIn;3640 }3641 // 5. user component (resolve)3642 context.helper(RESOLVE_COMPONENT);3643 context.components.add(tag);3644 return toValidAssetId(tag, `component`);3645}3646function buildProps(node, context, props = node.props, ssr = false) {3647 const { tag, loc: elementLoc } = node;3648 const isComponent = node.tagType === 1 /* COMPONENT */;3649 let properties = [];3650 const mergeArgs = [];3651 const runtimeDirectives = [];3652 // patchFlag analysis3653 let patchFlag = 0;3654 let hasRef = false;3655 let hasClassBinding = false;3656 let hasStyleBinding = false;3657 let hasHydrationEventBinding = false;3658 let hasDynamicKeys = false;3659 let hasVnodeHook = false;3660 const dynamicPropNames = [];3661 const analyzePatchFlag = ({ key, value }) => {3662 if (isStaticExp(key)) {3663 const name = key.content;3664 const isEventHandler = (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isOn)(name);3665 if (!isComponent &&3666 isEventHandler &&3667 // omit the flag for click handlers because hydration gives click3668 // dedicated fast path.3669 name.toLowerCase() !== 'onclick' &&3670 // omit v-model handlers3671 name !== 'onUpdate:modelValue' &&3672 // omit onVnodeXXX hooks3673 !(0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isReservedProp)(name)) {3674 hasHydrationEventBinding = true;3675 }3676 if (isEventHandler && (0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isReservedProp)(name)) {3677 hasVnodeHook = true;3678 }3679 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||3680 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||3681 value.type === 8 /* COMPOUND_EXPRESSION */) &&3682 getConstantType(value, context) > 0)) {3683 // skip if the prop is a cached handler or has constant value3684 return;3685 }3686 if (name === 'ref') {3687 hasRef = true;3688 }3689 else if (name === 'class' && !isComponent) {3690 hasClassBinding = true;3691 }3692 else if (name === 'style' && !isComponent) {3693 hasStyleBinding = true;3694 }3695 else if (name !== 'key' && !dynamicPropNames.includes(name)) {3696 dynamicPropNames.push(name);3697 }3698 }3699 else {3700 hasDynamicKeys = true;3701 }3702 };3703 for (let i = 0; i < props.length; i++) {3704 // static attribute3705 const prop = props[i];3706 if (prop.type === 6 /* ATTRIBUTE */) {3707 const { loc, name, value } = prop;3708 let isStatic = true;3709 if (name === 'ref') {3710 hasRef = true;3711 }3712 // skip is on <component>, or is="vue:xxx"3713 if (name === 'is' &&3714 (isComponentTag(tag) ||3715 (value && value.content.startsWith('vue:')) ||3716 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {3717 continue;3718 }3719 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));3720 }3721 else {3722 // directives3723 const { name, arg, exp, loc } = prop;3724 const isVBind = name === 'bind';3725 const isVOn = name === 'on';3726 // skip v-slot - it is handled by its dedicated transform.3727 if (name === 'slot') {3728 if (!isComponent) {3729 context.onError(createCompilerError(39 /* X_V_SLOT_MISPLACED */, loc));3730 }3731 continue;3732 }3733 // skip v-once - it is handled by its dedicated transform.3734 if (name === 'once') {3735 continue;3736 }3737 // skip v-is and :is on <component>3738 if (name === 'is' ||3739 (isVBind &&3740 isBindKey(arg, 'is') &&3741 (isComponentTag(tag) ||3742 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {3743 continue;3744 }3745 // skip v-on in SSR compilation3746 if (isVOn && ssr) {3747 continue;3748 }3749 // special case for v-bind and v-on with no argument3750 if (!arg && (isVBind || isVOn)) {3751 hasDynamicKeys = true;3752 if (exp) {3753 if (properties.length) {3754 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));3755 properties = [];3756 }3757 if (isVBind) {3758 {3759 // 2.x v-bind object order compat3760 if ((true)) {3761 const hasOverridableKeys = mergeArgs.some(arg => {3762 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {3763 return arg.properties.some(({ key }) => {3764 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||3765 !key.isStatic) {3766 return true;3767 }3768 return (key.content !== 'class' &&3769 key.content !== 'style' &&3770 !(0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isOn)(key.content));3771 });3772 }3773 else {3774 // dynamic expression3775 return true;3776 }3777 });3778 if (hasOverridableKeys) {3779 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);3780 }3781 }3782 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {3783 mergeArgs.unshift(exp);3784 continue;3785 }3786 }3787 mergeArgs.push(exp);3788 }3789 else {3790 // v-on="obj" -> toHandlers(obj)3791 mergeArgs.push({3792 type: 14 /* JS_CALL_EXPRESSION */,3793 loc,3794 callee: context.helper(TO_HANDLERS),3795 arguments: [exp]3796 });3797 }3798 }3799 else {3800 context.onError(createCompilerError(isVBind3801 ? 33 /* X_V_BIND_NO_EXPRESSION */3802 : 34 /* X_V_ON_NO_EXPRESSION */, loc));3803 }3804 continue;3805 }3806 const directiveTransform = context.directiveTransforms[name];3807 if (directiveTransform) {3808 // has built-in directive transform.3809 const { props, needRuntime } = directiveTransform(prop, node, context);3810 !ssr && props.forEach(analyzePatchFlag);3811 properties.push(...props);3812 if (needRuntime) {3813 runtimeDirectives.push(prop);3814 if ((0,_vue_shared__WEBPACK_IMPORTED_MODULE_0__.isSymbol)(needRuntime)) {3815 directiveImportMap.set(prop, needRuntime);3816 }3817 }3818 }3819 else {3820 // no built-in transform, this is a user custom directive.3821 runtimeDirectives.push(prop);3822 }3823 }3824 if (prop.type === 6 /* ATTRIBUTE */ &&3825 prop.name === 'ref' &&3826 context.scopes.vFor > 0 &&3827 checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {3828 properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));3829 }3830 }3831 let propsExpression = undefined;3832 // has v-bind="object" or v-on="object", wrap with mergeProps3833 if (mergeArgs.length) {3834 if (properties.length) {3835 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));3836 }3837 if (mergeArgs.length > 1) {3838 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);3839 }3840 else {3841 // single v-bind with nothing else - no need for a mergeProps call...

Full Screen

Full Screen

dep-56143c31.js

Source:dep-56143c31.js Github

copy

Full Screen

...1426 // in v3 mode, only enable if explicitly set to true1427 // otherwise enable for any non-false value1428 return mode === 3 ? value === true : value !== false;1429}1430function checkCompatEnabled(key, context, loc, ...args) {1431 const enabled = isCompatEnabled(key, context);1432 if ((process.env.NODE_ENV !== 'production') && enabled) {1433 warnDeprecation(key, context, loc, ...args);1434 }1435 return enabled;1436}1437function warnDeprecation(key, context, loc, ...args) {1438 const val = getCompatValue(key, context);1439 if (val === 'suppress-warning') {1440 return;1441 }1442 const { message, link } = deprecationData[key];1443 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;1444 const err = new SyntaxError(msg);1445 err.code = key;1446 if (loc)1447 err.loc = loc;1448 context.onWarn(err);1449}1450// The default decoder only provides escapes for characters reserved as part of1451// the template syntax, and is only used if the custom renderer did not provide1452// a platform-specific decoder.1453const decodeRE = /&(gt|lt|amp|apos|quot);/g;1454const decodeMap = {1455 gt: '>',1456 lt: '<',1457 amp: '&',1458 apos: "'",1459 quot: '"'1460};1461const defaultParserOptions = {1462 delimiters: [`{{`, `}}`],1463 getNamespace: () => 0 /* HTML */,1464 getTextMode: () => 0 /* DATA */,1465 isVoidTag: NO,1466 isPreTag: NO,1467 isCustomElement: NO,1468 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),1469 onError: defaultOnError,1470 onWarn: defaultOnWarn,1471 comments: (process.env.NODE_ENV !== 'production')1472};1473function baseParse(content, options = {}) {1474 const context = createParserContext(content, options);1475 const start = getCursor(context);1476 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));1477}1478function createParserContext(content, rawOptions) {1479 const options = extend({}, defaultParserOptions);1480 let key;1481 for (key in rawOptions) {1482 // @ts-ignore1483 options[key] =1484 rawOptions[key] === undefined1485 ? defaultParserOptions[key]1486 : rawOptions[key];1487 }1488 return {1489 options,1490 column: 1,1491 line: 1,1492 offset: 0,1493 originalSource: content,1494 source: content,1495 inPre: false,1496 inVPre: false,1497 onWarn: options.onWarn1498 };1499}1500function parseChildren(context, mode, ancestors) {1501 const parent = last(ancestors);1502 const ns = parent ? parent.ns : 0 /* HTML */;1503 const nodes = [];1504 while (!isEnd(context, mode, ancestors)) {1505 const s = context.source;1506 let node = undefined;1507 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {1508 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {1509 // '{{'1510 node = parseInterpolation(context, mode);1511 }1512 else if (mode === 0 /* DATA */ && s[0] === '<') {1513 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state1514 if (s.length === 1) {1515 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);1516 }1517 else if (s[1] === '!') {1518 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state1519 if (startsWith(s, '<!--')) {1520 node = parseComment(context);1521 }1522 else if (startsWith(s, '<!DOCTYPE')) {1523 // Ignore DOCTYPE by a limitation.1524 node = parseBogusComment(context);1525 }1526 else if (startsWith(s, '<![CDATA[')) {1527 if (ns !== 0 /* HTML */) {1528 node = parseCDATA(context, ancestors);1529 }1530 else {1531 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);1532 node = parseBogusComment(context);1533 }1534 }1535 else {1536 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);1537 node = parseBogusComment(context);1538 }1539 }1540 else if (s[1] === '/') {1541 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state1542 if (s.length === 2) {1543 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);1544 }1545 else if (s[2] === '>') {1546 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);1547 advanceBy(context, 3);1548 continue;1549 }1550 else if (/[a-z]/i.test(s[2])) {1551 emitError(context, 23 /* X_INVALID_END_TAG */);1552 parseTag(context, 1 /* End */, parent);1553 continue;1554 }1555 else {1556 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);1557 node = parseBogusComment(context);1558 }1559 }1560 else if (/[a-z]/i.test(s[1])) {1561 node = parseElement(context, ancestors);1562 // 2.x <template> with no directive compat1563 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&1564 node &&1565 node.tag === 'template' &&1566 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&1567 isSpecialTemplateDirective(p.name))) {1568 (process.env.NODE_ENV !== 'production') &&1569 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);1570 node = node.children;1571 }1572 }1573 else if (s[1] === '?') {1574 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);1575 node = parseBogusComment(context);1576 }1577 else {1578 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);1579 }1580 }1581 }1582 if (!node) {1583 node = parseText(context, mode);1584 }1585 if (isArray(node)) {1586 for (let i = 0; i < node.length; i++) {1587 pushNode(nodes, node[i]);1588 }1589 }1590 else {1591 pushNode(nodes, node);1592 }1593 }1594 // Whitespace handling strategy like v21595 let removedWhitespace = false;1596 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {1597 const shouldCondense = context.options.whitespace !== 'preserve';1598 for (let i = 0; i < nodes.length; i++) {1599 const node = nodes[i];1600 if (!context.inPre && node.type === 2 /* TEXT */) {1601 if (!/[^\t\r\n\f ]/.test(node.content)) {1602 const prev = nodes[i - 1];1603 const next = nodes[i + 1];1604 // Remove if:1605 // - the whitespace is the first or last node, or:1606 // - (condense mode) the whitespace is adjacent to a comment, or:1607 // - (condense mode) the whitespace is between two elements AND contains newline1608 if (!prev ||1609 !next ||1610 (shouldCondense &&1611 (prev.type === 3 /* COMMENT */ ||1612 next.type === 3 /* COMMENT */ ||1613 (prev.type === 1 /* ELEMENT */ &&1614 next.type === 1 /* ELEMENT */ &&1615 /[\r\n]/.test(node.content))))) {1616 removedWhitespace = true;1617 nodes[i] = null;1618 }1619 else {1620 // Otherwise, the whitespace is condensed into a single space1621 node.content = ' ';1622 }1623 }1624 else if (shouldCondense) {1625 // in condense mode, consecutive whitespaces in text are condensed1626 // down to a single space.1627 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');1628 }1629 }1630 // Remove comment nodes if desired by configuration.1631 else if (node.type === 3 /* COMMENT */ && !context.options.comments) {1632 removedWhitespace = true;1633 nodes[i] = null;1634 }1635 }1636 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {1637 // remove leading newline per html spec1638 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element1639 const first = nodes[0];1640 if (first && first.type === 2 /* TEXT */) {1641 first.content = first.content.replace(/^\r?\n/, '');1642 }1643 }1644 }1645 return removedWhitespace ? nodes.filter(Boolean) : nodes;1646}1647function pushNode(nodes, node) {1648 if (node.type === 2 /* TEXT */) {1649 const prev = last(nodes);1650 // Merge if both this and the previous node are text and those are1651 // consecutive. This happens for cases like "a < b".1652 if (prev &&1653 prev.type === 2 /* TEXT */ &&1654 prev.loc.end.offset === node.loc.start.offset) {1655 prev.content += node.content;1656 prev.loc.end = node.loc.end;1657 prev.loc.source += node.loc.source;1658 return;1659 }1660 }1661 nodes.push(node);1662}1663function parseCDATA(context, ancestors) {1664 advanceBy(context, 9);1665 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1666 if (context.source.length === 0) {1667 emitError(context, 6 /* EOF_IN_CDATA */);1668 }1669 else {1670 advanceBy(context, 3);1671 }1672 return nodes;1673}1674function parseComment(context) {1675 const start = getCursor(context);1676 let content;1677 // Regular comment.1678 const match = /--(\!)?>/.exec(context.source);1679 if (!match) {1680 content = context.source.slice(4);1681 advanceBy(context, context.source.length);1682 emitError(context, 7 /* EOF_IN_COMMENT */);1683 }1684 else {1685 if (match.index <= 3) {1686 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1687 }1688 if (match[1]) {1689 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1690 }1691 content = context.source.slice(4, match.index);1692 // Advancing with reporting nested comments.1693 const s = context.source.slice(0, match.index);1694 let prevIndex = 1, nestedIndex = 0;1695 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1696 advanceBy(context, nestedIndex - prevIndex + 1);1697 if (nestedIndex + 4 < s.length) {1698 emitError(context, 16 /* NESTED_COMMENT */);1699 }1700 prevIndex = nestedIndex + 1;1701 }1702 advanceBy(context, match.index + match[0].length - prevIndex + 1);1703 }1704 return {1705 type: 3 /* COMMENT */,1706 content,1707 loc: getSelection(context, start)1708 };1709}1710function parseBogusComment(context) {1711 const start = getCursor(context);1712 const contentStart = context.source[1] === '?' ? 1 : 2;1713 let content;1714 const closeIndex = context.source.indexOf('>');1715 if (closeIndex === -1) {1716 content = context.source.slice(contentStart);1717 advanceBy(context, context.source.length);1718 }1719 else {1720 content = context.source.slice(contentStart, closeIndex);1721 advanceBy(context, closeIndex + 1);1722 }1723 return {1724 type: 3 /* COMMENT */,1725 content,1726 loc: getSelection(context, start)1727 };1728}1729function parseElement(context, ancestors) {1730 // Start tag.1731 const wasInPre = context.inPre;1732 const wasInVPre = context.inVPre;1733 const parent = last(ancestors);1734 const element = parseTag(context, 0 /* Start */, parent);1735 const isPreBoundary = context.inPre && !wasInPre;1736 const isVPreBoundary = context.inVPre && !wasInVPre;1737 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1738 // #4030 self-closing <pre> tag1739 if (isPreBoundary) {1740 context.inPre = false;1741 }1742 if (isVPreBoundary) {1743 context.inVPre = false;1744 }1745 return element;1746 }1747 // Children.1748 ancestors.push(element);1749 const mode = context.options.getTextMode(element, parent);1750 const children = parseChildren(context, mode, ancestors);1751 ancestors.pop();1752 // 2.x inline-template compat1753 {1754 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1755 if (inlineTemplateProp &&1756 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1757 const loc = getSelection(context, element.loc.end);1758 inlineTemplateProp.value = {1759 type: 2 /* TEXT */,1760 content: loc.source,1761 loc1762 };1763 }1764 }1765 element.children = children;1766 // End tag.1767 if (startsWithEndTagOpen(context.source, element.tag)) {1768 parseTag(context, 1 /* End */, parent);1769 }1770 else {1771 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1772 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1773 const first = children[0];1774 if (first && startsWith(first.loc.source, '<!--')) {1775 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1776 }1777 }1778 }1779 element.loc = getSelection(context, element.loc.start);1780 if (isPreBoundary) {1781 context.inPre = false;1782 }1783 if (isVPreBoundary) {1784 context.inVPre = false;1785 }1786 return element;1787}1788const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`);1789function parseTag(context, type, parent) {1790 // Tag open.1791 const start = getCursor(context);1792 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1793 const tag = match[1];1794 const ns = context.options.getNamespace(tag, parent);1795 advanceBy(context, match[0].length);1796 advanceSpaces(context);1797 // save current state in case we need to re-parse attributes with v-pre1798 const cursor = getCursor(context);1799 const currentSource = context.source;1800 // check <pre> tag1801 if (context.options.isPreTag(tag)) {1802 context.inPre = true;1803 }1804 // Attributes.1805 let props = parseAttributes(context, type);1806 // check v-pre1807 if (type === 0 /* Start */ &&1808 !context.inVPre &&1809 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1810 context.inVPre = true;1811 // reset context1812 extend(context, cursor);1813 context.source = currentSource;1814 // re-parse attrs and filter out v-pre itself1815 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1816 }1817 // Tag close.1818 let isSelfClosing = false;1819 if (context.source.length === 0) {1820 emitError(context, 9 /* EOF_IN_TAG */);1821 }1822 else {1823 isSelfClosing = startsWith(context.source, '/>');1824 if (type === 1 /* End */ && isSelfClosing) {1825 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1826 }1827 advanceBy(context, isSelfClosing ? 2 : 1);1828 }1829 if (type === 1 /* End */) {1830 return;1831 }1832 // 2.x deprecation checks1833 if ((process.env.NODE_ENV !== 'production') &&1834 isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1835 let hasIf = false;1836 let hasFor = false;1837 for (let i = 0; i < props.length; i++) {1838 const p = props[i];1839 if (p.type === 7 /* DIRECTIVE */) {1840 if (p.name === 'if') {1841 hasIf = true;1842 }1843 else if (p.name === 'for') {1844 hasFor = true;1845 }1846 }1847 if (hasIf && hasFor) {1848 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1849 break;1850 }1851 }1852 }1853 let tagType = 0 /* ELEMENT */;1854 if (!context.inVPre) {1855 if (tag === 'slot') {1856 tagType = 2 /* SLOT */;1857 }1858 else if (tag === 'template') {1859 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1860 tagType = 3 /* TEMPLATE */;1861 }1862 }1863 else if (isComponent(tag, props, context)) {1864 tagType = 1 /* COMPONENT */;1865 }1866 }1867 return {1868 type: 1 /* ELEMENT */,1869 ns,1870 tag,1871 tagType,1872 props,1873 isSelfClosing,1874 children: [],1875 loc: getSelection(context, start),1876 codegenNode: undefined // to be created during transform phase1877 };1878}1879function isComponent(tag, props, context) {1880 const options = context.options;1881 if (options.isCustomElement(tag)) {1882 return false;1883 }1884 if (tag === 'component' ||1885 /^[A-Z]/.test(tag) ||1886 isCoreComponent(tag) ||1887 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1888 (options.isNativeTag && !options.isNativeTag(tag))) {1889 return true;1890 }1891 // at this point the tag should be a native tag, but check for potential "is"1892 // casting1893 for (let i = 0; i < props.length; i++) {1894 const p = props[i];1895 if (p.type === 6 /* ATTRIBUTE */) {1896 if (p.name === 'is' && p.value) {1897 if (p.value.content.startsWith('vue:')) {1898 return true;1899 }1900 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1901 return true;1902 }1903 }1904 }1905 else {1906 // directive1907 // v-is (TODO Deprecate)1908 if (p.name === 'is') {1909 return true;1910 }1911 else if (1912 // :is on plain element - only treat as component in compat mode1913 p.name === 'bind' &&1914 isStaticArgOf(p.arg, 'is') &&1915 true &&1916 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1917 return true;1918 }1919 }1920 }1921}1922function parseAttributes(context, type) {1923 const props = [];1924 const attributeNames = new Set();1925 while (context.source.length > 0 &&1926 !startsWith(context.source, '>') &&1927 !startsWith(context.source, '/>')) {1928 if (startsWith(context.source, '/')) {1929 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1930 advanceBy(context, 1);1931 advanceSpaces(context);1932 continue;1933 }1934 if (type === 1 /* End */) {1935 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1936 }1937 const attr = parseAttribute(context, attributeNames);1938 // Trim whitespace between class1939 // https://github.com/vuejs/core/issues/42511940 if (attr.type === 6 /* ATTRIBUTE */ &&1941 attr.value &&1942 attr.name === 'class') {1943 attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();1944 }1945 if (type === 0 /* Start */) {1946 props.push(attr);1947 }1948 if (/^[^\t\r\n\f />]/.test(context.source)) {1949 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1950 }1951 advanceSpaces(context);1952 }1953 return props;1954}1955function parseAttribute(context, nameSet) {1956 // Name.1957 const start = getCursor(context);1958 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1959 const name = match[0];1960 if (nameSet.has(name)) {1961 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1962 }1963 nameSet.add(name);1964 if (name[0] === '=') {1965 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1966 }1967 {1968 const pattern = /["'<]/g;1969 let m;1970 while ((m = pattern.exec(name))) {1971 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1972 }1973 }1974 advanceBy(context, name.length);1975 // Value1976 let value = undefined;1977 if (/^[\t\r\n\f ]*=/.test(context.source)) {1978 advanceSpaces(context);1979 advanceBy(context, 1);1980 advanceSpaces(context);1981 value = parseAttributeValue(context);1982 if (!value) {1983 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1984 }1985 }1986 const loc = getSelection(context, start);1987 if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {1988 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1989 let isPropShorthand = startsWith(name, '.');1990 let dirName = match[1] ||1991 (isPropShorthand || startsWith(name, ':')1992 ? 'bind'1993 : startsWith(name, '@')1994 ? 'on'1995 : 'slot');1996 let arg;1997 if (match[2]) {1998 const isSlot = dirName === 'slot';1999 const startOffset = name.lastIndexOf(match[2]);2000 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));2001 let content = match[2];2002 let isStatic = true;2003 if (content.startsWith('[')) {2004 isStatic = false;2005 if (!content.endsWith(']')) {2006 emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);2007 content = content.slice(1);2008 }2009 else {2010 content = content.slice(1, content.length - 1);2011 }2012 }2013 else if (isSlot) {2014 // #1241 special case for v-slot: vuetify relies extensively on slot2015 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x2016 // supports such usage so we are keeping it consistent with 2.x.2017 content += match[3] || '';2018 }2019 arg = {2020 type: 4 /* SIMPLE_EXPRESSION */,2021 content,2022 isStatic,2023 constType: isStatic2024 ? 3 /* CAN_STRINGIFY */2025 : 0 /* NOT_CONSTANT */,2026 loc2027 };2028 }2029 if (value && value.isQuoted) {2030 const valueLoc = value.loc;2031 valueLoc.start.offset++;2032 valueLoc.start.column++;2033 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);2034 valueLoc.source = valueLoc.source.slice(1, -1);2035 }2036 const modifiers = match[3] ? match[3].slice(1).split('.') : [];2037 if (isPropShorthand)2038 modifiers.push('prop');2039 // 2.x compat v-bind:foo.sync -> v-model:foo2040 if (dirName === 'bind' && arg) {2041 if (modifiers.includes('sync') &&2042 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {2043 dirName = 'model';2044 modifiers.splice(modifiers.indexOf('sync'), 1);2045 }2046 if ((process.env.NODE_ENV !== 'production') && modifiers.includes('prop')) {2047 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);2048 }2049 }2050 return {2051 type: 7 /* DIRECTIVE */,2052 name: dirName,2053 exp: value && {2054 type: 4 /* SIMPLE_EXPRESSION */,2055 content: value.content,2056 isStatic: false,2057 // Treat as non-constant by default. This can be potentially set to2058 // other values by `transformExpression` to make it eligible for hoisting.2059 constType: 0 /* NOT_CONSTANT */,2060 loc: value.loc2061 },2062 arg,2063 modifiers,2064 loc2065 };2066 }2067 // missing directive name or illegal directive name2068 if (!context.inVPre && startsWith(name, 'v-')) {2069 emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */);2070 }2071 return {2072 type: 6 /* ATTRIBUTE */,2073 name,2074 value: value && {2075 type: 2 /* TEXT */,2076 content: value.content,2077 loc: value.loc2078 },2079 loc2080 };2081}2082function parseAttributeValue(context) {2083 const start = getCursor(context);2084 let content;2085 const quote = context.source[0];2086 const isQuoted = quote === `"` || quote === `'`;2087 if (isQuoted) {2088 // Quoted value.2089 advanceBy(context, 1);2090 const endIndex = context.source.indexOf(quote);2091 if (endIndex === -1) {2092 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);2093 }2094 else {2095 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);2096 advanceBy(context, 1);2097 }2098 }2099 else {2100 // Unquoted2101 const match = /^[^\t\r\n\f >]+/.exec(context.source);2102 if (!match) {2103 return undefined;2104 }2105 const unexpectedChars = /["'<=`]/g;2106 let m;2107 while ((m = unexpectedChars.exec(match[0]))) {2108 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);2109 }2110 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);2111 }2112 return { content, isQuoted, loc: getSelection(context, start) };2113}2114function parseInterpolation(context, mode) {2115 const [open, close] = context.options.delimiters;2116 const closeIndex = context.source.indexOf(close, open.length);2117 if (closeIndex === -1) {2118 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);2119 return undefined;2120 }2121 const start = getCursor(context);2122 advanceBy(context, open.length);2123 const innerStart = getCursor(context);2124 const innerEnd = getCursor(context);2125 const rawContentLength = closeIndex - open.length;2126 const rawContent = context.source.slice(0, rawContentLength);2127 const preTrimContent = parseTextData(context, rawContentLength, mode);2128 const content = preTrimContent.trim();2129 const startOffset = preTrimContent.indexOf(content);2130 if (startOffset > 0) {2131 advancePositionWithMutation(innerStart, rawContent, startOffset);2132 }2133 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);2134 advancePositionWithMutation(innerEnd, rawContent, endOffset);2135 advanceBy(context, close.length);2136 return {2137 type: 5 /* INTERPOLATION */,2138 content: {2139 type: 4 /* SIMPLE_EXPRESSION */,2140 isStatic: false,2141 // Set `isConstant` to false by default and will decide in transformExpression2142 constType: 0 /* NOT_CONSTANT */,2143 content,2144 loc: getSelection(context, innerStart, innerEnd)2145 },2146 loc: getSelection(context, start)2147 };2148}2149function parseText(context, mode) {2150 const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];2151 let endIndex = context.source.length;2152 for (let i = 0; i < endTokens.length; i++) {2153 const index = context.source.indexOf(endTokens[i], 1);2154 if (index !== -1 && endIndex > index) {2155 endIndex = index;2156 }2157 }2158 const start = getCursor(context);2159 const content = parseTextData(context, endIndex, mode);2160 return {2161 type: 2 /* TEXT */,2162 content,2163 loc: getSelection(context, start)2164 };2165}2166/**2167 * Get text data with a given length from the current location.2168 * This translates HTML entities in the text data.2169 */2170function parseTextData(context, length, mode) {2171 const rawText = context.source.slice(0, length);2172 advanceBy(context, length);2173 if (mode === 2 /* RAWTEXT */ ||2174 mode === 3 /* CDATA */ ||2175 !rawText.includes('&')) {2176 return rawText;2177 }2178 else {2179 // DATA or RCDATA containing "&"". Entity decoding required.2180 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);2181 }2182}2183function getCursor(context) {2184 const { column, line, offset } = context;2185 return { column, line, offset };2186}2187function getSelection(context, start, end) {2188 end = end || getCursor(context);2189 return {2190 start,2191 end,2192 source: context.originalSource.slice(start.offset, end.offset)2193 };2194}2195function last(xs) {2196 return xs[xs.length - 1];2197}2198function startsWith(source, searchString) {2199 return source.startsWith(searchString);2200}2201function advanceBy(context, numberOfCharacters) {2202 const { source } = context;2203 advancePositionWithMutation(context, source, numberOfCharacters);2204 context.source = source.slice(numberOfCharacters);2205}2206function advanceSpaces(context) {2207 const match = /^[\t\r\n\f ]+/.exec(context.source);2208 if (match) {2209 advanceBy(context, match[0].length);2210 }2211}2212function getNewPosition(context, start, numberOfCharacters) {2213 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);2214}2215function emitError(context, code, offset, loc = getCursor(context)) {2216 if (offset) {2217 loc.offset += offset;2218 loc.column += offset;2219 }2220 context.options.onError(createCompilerError(code, {2221 start: loc,2222 end: loc,2223 source: ''2224 }));2225}2226function isEnd(context, mode, ancestors) {2227 const s = context.source;2228 switch (mode) {2229 case 0 /* DATA */:2230 if (startsWith(s, '</')) {2231 // TODO: probably bad performance2232 for (let i = ancestors.length - 1; i >= 0; --i) {2233 if (startsWithEndTagOpen(s, ancestors[i].tag)) {2234 return true;2235 }2236 }2237 }2238 break;2239 case 1 /* RCDATA */:2240 case 2 /* RAWTEXT */: {2241 const parent = last(ancestors);2242 if (parent && startsWithEndTagOpen(s, parent.tag)) {2243 return true;2244 }2245 break;2246 }2247 case 3 /* CDATA */:2248 if (startsWith(s, ']]>')) {2249 return true;2250 }2251 break;2252 }2253 return !s;2254}2255function startsWithEndTagOpen(source, tag) {2256 return (startsWith(source, '</') &&2257 source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&2258 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));2259}2260function hoistStatic(root, context) {2261 walk(root, context, 2262 // Root node is unfortunately non-hoistable due to potential parent2263 // fallthrough attributes.2264 isSingleElementRoot(root, root.children[0]));2265}2266function isSingleElementRoot(root, child) {2267 const { children } = root;2268 return (children.length === 1 &&2269 child.type === 1 /* ELEMENT */ &&2270 !isSlotOutlet(child));2271}2272function walk(node, context, doNotHoistNode = false) {2273 const { children } = node;2274 const originalCount = children.length;2275 let hoistedCount = 0;2276 for (let i = 0; i < children.length; i++) {2277 const child = children[i];2278 // only plain elements & text calls are eligible for hoisting.2279 if (child.type === 1 /* ELEMENT */ &&2280 child.tagType === 0 /* ELEMENT */) {2281 const constantType = doNotHoistNode2282 ? 0 /* NOT_CONSTANT */2283 : getConstantType(child, context);2284 if (constantType > 0 /* NOT_CONSTANT */) {2285 if (constantType >= 2 /* CAN_HOIST */) {2286 child.codegenNode.patchFlag =2287 -1 /* HOISTED */ + ((process.env.NODE_ENV !== 'production') ? ` /* HOISTED */` : ``);2288 child.codegenNode = context.hoist(child.codegenNode);2289 hoistedCount++;2290 continue;2291 }2292 }2293 else {2294 // node may contain dynamic children, but its props may be eligible for2295 // hoisting.2296 const codegenNode = child.codegenNode;2297 if (codegenNode.type === 13 /* VNODE_CALL */) {2298 const flag = getPatchFlag(codegenNode);2299 if ((!flag ||2300 flag === 512 /* NEED_PATCH */ ||2301 flag === 1 /* TEXT */) &&2302 getGeneratedPropsConstantType(child, context) >=2303 2 /* CAN_HOIST */) {2304 const props = getNodeProps(child);2305 if (props) {2306 codegenNode.props = context.hoist(props);2307 }2308 }2309 if (codegenNode.dynamicProps) {2310 codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);2311 }2312 }2313 }2314 }2315 else if (child.type === 12 /* TEXT_CALL */ &&2316 getConstantType(child.content, context) >= 2 /* CAN_HOIST */) {2317 child.codegenNode = context.hoist(child.codegenNode);2318 hoistedCount++;2319 }2320 // walk further2321 if (child.type === 1 /* ELEMENT */) {2322 const isComponent = child.tagType === 1 /* COMPONENT */;2323 if (isComponent) {2324 context.scopes.vSlot++;2325 }2326 walk(child, context);2327 if (isComponent) {2328 context.scopes.vSlot--;2329 }2330 }2331 else if (child.type === 11 /* FOR */) {2332 // Do not hoist v-for single child because it has to be a block2333 walk(child, context, child.children.length === 1);2334 }2335 else if (child.type === 9 /* IF */) {2336 for (let i = 0; i < child.branches.length; i++) {2337 // Do not hoist v-if single child because it has to be a block2338 walk(child.branches[i], context, child.branches[i].children.length === 1);2339 }2340 }2341 }2342 if (hoistedCount && context.transformHoist) {2343 context.transformHoist(children, context, node);2344 }2345 // all children were hoisted - the entire children array is hoistable.2346 if (hoistedCount &&2347 hoistedCount === originalCount &&2348 node.type === 1 /* ELEMENT */ &&2349 node.tagType === 0 /* ELEMENT */ &&2350 node.codegenNode &&2351 node.codegenNode.type === 13 /* VNODE_CALL */ &&2352 isArray(node.codegenNode.children)) {2353 node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));2354 }2355}2356function getConstantType(node, context) {2357 const { constantCache } = context;2358 switch (node.type) {2359 case 1 /* ELEMENT */:2360 if (node.tagType !== 0 /* ELEMENT */) {2361 return 0 /* NOT_CONSTANT */;2362 }2363 const cached = constantCache.get(node);2364 if (cached !== undefined) {2365 return cached;2366 }2367 const codegenNode = node.codegenNode;2368 if (codegenNode.type !== 13 /* VNODE_CALL */) {2369 return 0 /* NOT_CONSTANT */;2370 }2371 if (codegenNode.isBlock &&2372 node.tag !== 'svg' &&2373 node.tag !== 'foreignObject') {2374 return 0 /* NOT_CONSTANT */;2375 }2376 const flag = getPatchFlag(codegenNode);2377 if (!flag) {2378 let returnType = 3 /* CAN_STRINGIFY */;2379 // Element itself has no patch flag. However we still need to check:2380 // 1. Even for a node with no patch flag, it is possible for it to contain2381 // non-hoistable expressions that refers to scope variables, e.g. compiler2382 // injected keys or cached event handlers. Therefore we need to always2383 // check the codegenNode's props to be sure.2384 const generatedPropsType = getGeneratedPropsConstantType(node, context);2385 if (generatedPropsType === 0 /* NOT_CONSTANT */) {2386 constantCache.set(node, 0 /* NOT_CONSTANT */);2387 return 0 /* NOT_CONSTANT */;2388 }2389 if (generatedPropsType < returnType) {2390 returnType = generatedPropsType;2391 }2392 // 2. its children.2393 for (let i = 0; i < node.children.length; i++) {2394 const childType = getConstantType(node.children[i], context);2395 if (childType === 0 /* NOT_CONSTANT */) {2396 constantCache.set(node, 0 /* NOT_CONSTANT */);2397 return 0 /* NOT_CONSTANT */;2398 }2399 if (childType < returnType) {2400 returnType = childType;2401 }2402 }2403 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-02404 // type, check if any of the props can cause the type to be lowered2405 // we can skip can_patch because it's guaranteed by the absence of a2406 // patchFlag.2407 if (returnType > 1 /* CAN_SKIP_PATCH */) {2408 for (let i = 0; i < node.props.length; i++) {2409 const p = node.props[i];2410 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {2411 const expType = getConstantType(p.exp, context);2412 if (expType === 0 /* NOT_CONSTANT */) {2413 constantCache.set(node, 0 /* NOT_CONSTANT */);2414 return 0 /* NOT_CONSTANT */;2415 }2416 if (expType < returnType) {2417 returnType = expType;2418 }2419 }2420 }2421 }2422 // only svg/foreignObject could be block here, however if they are2423 // static then they don't need to be blocks since there will be no2424 // nested updates.2425 if (codegenNode.isBlock) {2426 context.removeHelper(OPEN_BLOCK);2427 context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));2428 codegenNode.isBlock = false;2429 context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));2430 }2431 constantCache.set(node, returnType);2432 return returnType;2433 }2434 else {2435 constantCache.set(node, 0 /* NOT_CONSTANT */);2436 return 0 /* NOT_CONSTANT */;2437 }2438 case 2 /* TEXT */:2439 case 3 /* COMMENT */:2440 return 3 /* CAN_STRINGIFY */;2441 case 9 /* IF */:2442 case 11 /* FOR */:2443 case 10 /* IF_BRANCH */:2444 return 0 /* NOT_CONSTANT */;2445 case 5 /* INTERPOLATION */:2446 case 12 /* TEXT_CALL */:2447 return getConstantType(node.content, context);2448 case 4 /* SIMPLE_EXPRESSION */:2449 return node.constType;2450 case 8 /* COMPOUND_EXPRESSION */:2451 let returnType = 3 /* CAN_STRINGIFY */;2452 for (let i = 0; i < node.children.length; i++) {2453 const child = node.children[i];2454 if (isString(child) || isSymbol(child)) {2455 continue;2456 }2457 const childType = getConstantType(child, context);2458 if (childType === 0 /* NOT_CONSTANT */) {2459 return 0 /* NOT_CONSTANT */;2460 }2461 else if (childType < returnType) {2462 returnType = childType;2463 }2464 }2465 return returnType;2466 default:2467 if ((process.env.NODE_ENV !== 'production')) ;2468 return 0 /* NOT_CONSTANT */;2469 }2470}2471const allowHoistedHelperSet = new Set([2472 NORMALIZE_CLASS,2473 NORMALIZE_STYLE,2474 NORMALIZE_PROPS,2475 GUARD_REACTIVE_PROPS2476]);2477function getConstantTypeOfHelperCall(value, context) {2478 if (value.type === 14 /* JS_CALL_EXPRESSION */ &&2479 !isString(value.callee) &&2480 allowHoistedHelperSet.has(value.callee)) {2481 const arg = value.arguments[0];2482 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {2483 return getConstantType(arg, context);2484 }2485 else if (arg.type === 14 /* JS_CALL_EXPRESSION */) {2486 // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`2487 return getConstantTypeOfHelperCall(arg, context);2488 }2489 }2490 return 0 /* NOT_CONSTANT */;2491}2492function getGeneratedPropsConstantType(node, context) {2493 let returnType = 3 /* CAN_STRINGIFY */;2494 const props = getNodeProps(node);2495 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {2496 const { properties } = props;2497 for (let i = 0; i < properties.length; i++) {2498 const { key, value } = properties[i];2499 const keyType = getConstantType(key, context);2500 if (keyType === 0 /* NOT_CONSTANT */) {2501 return keyType;2502 }2503 if (keyType < returnType) {2504 returnType = keyType;2505 }2506 let valueType;2507 if (value.type === 4 /* SIMPLE_EXPRESSION */) {2508 valueType = getConstantType(value, context);2509 }2510 else if (value.type === 14 /* JS_CALL_EXPRESSION */) {2511 // some helper calls can be hoisted,2512 // such as the `normalizeProps` generated by the compiler for pre-normalize class,2513 // in this case we need to respect the ConstantType of the helper's arguments2514 valueType = getConstantTypeOfHelperCall(value, context);2515 }2516 else {2517 valueType = 0 /* NOT_CONSTANT */;2518 }2519 if (valueType === 0 /* NOT_CONSTANT */) {2520 return valueType;2521 }2522 if (valueType < returnType) {2523 returnType = valueType;2524 }2525 }2526 }2527 return returnType;2528}2529function getNodeProps(node) {2530 const codegenNode = node.codegenNode;2531 if (codegenNode.type === 13 /* VNODE_CALL */) {2532 return codegenNode.props;2533 }2534}2535function getPatchFlag(node) {2536 const flag = node.patchFlag;2537 return flag ? parseInt(flag, 10) : undefined;2538}2539function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {2540 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);2541 const context = {2542 // options2543 selfName: nameMatch && capitalize(camelize$1(nameMatch[1])),2544 prefixIdentifiers,2545 hoistStatic,2546 cacheHandlers,2547 nodeTransforms,2548 directiveTransforms,2549 transformHoist,2550 isBuiltInComponent,2551 isCustomElement,2552 expressionPlugins,2553 scopeId,2554 slotted,2555 ssr,2556 inSSR,2557 ssrCssVars,2558 bindingMetadata,2559 inline,2560 isTS,2561 onError,2562 onWarn,2563 compatConfig,2564 // state2565 root,2566 helpers: new Map(),2567 components: new Set(),2568 directives: new Set(),2569 hoists: [],2570 imports: [],2571 constantCache: new Map(),2572 temps: 0,2573 cached: 0,2574 identifiers: Object.create(null),2575 scopes: {2576 vFor: 0,2577 vSlot: 0,2578 vPre: 0,2579 vOnce: 02580 },2581 parent: null,2582 currentNode: root,2583 childIndex: 0,2584 inVOnce: false,2585 // methods2586 helper(name) {2587 const count = context.helpers.get(name) || 0;2588 context.helpers.set(name, count + 1);2589 return name;2590 },2591 removeHelper(name) {2592 const count = context.helpers.get(name);2593 if (count) {2594 const currentCount = count - 1;2595 if (!currentCount) {2596 context.helpers.delete(name);2597 }2598 else {2599 context.helpers.set(name, currentCount);2600 }2601 }2602 },2603 helperString(name) {2604 return `_${helperNameMap[context.helper(name)]}`;2605 },2606 replaceNode(node) {2607 /* istanbul ignore if */2608 if ((process.env.NODE_ENV !== 'production')) {2609 if (!context.currentNode) {2610 throw new Error(`Node being replaced is already removed.`);2611 }2612 if (!context.parent) {2613 throw new Error(`Cannot replace root node.`);2614 }2615 }2616 context.parent.children[context.childIndex] = context.currentNode = node;2617 },2618 removeNode(node) {2619 if ((process.env.NODE_ENV !== 'production') && !context.parent) {2620 throw new Error(`Cannot remove root node.`);2621 }2622 const list = context.parent.children;2623 const removalIndex = node2624 ? list.indexOf(node)2625 : context.currentNode2626 ? context.childIndex2627 : -1;2628 /* istanbul ignore if */2629 if ((process.env.NODE_ENV !== 'production') && removalIndex < 0) {2630 throw new Error(`node being removed is not a child of current parent`);2631 }2632 if (!node || node === context.currentNode) {2633 // current node removed2634 context.currentNode = null;2635 context.onNodeRemoved();2636 }2637 else {2638 // sibling node removed2639 if (context.childIndex > removalIndex) {2640 context.childIndex--;2641 context.onNodeRemoved();2642 }2643 }2644 context.parent.children.splice(removalIndex, 1);2645 },2646 onNodeRemoved: () => { },2647 addIdentifiers(exp) {2648 },2649 removeIdentifiers(exp) {2650 },2651 hoist(exp) {2652 if (isString(exp))2653 exp = createSimpleExpression(exp);2654 context.hoists.push(exp);2655 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);2656 identifier.hoisted = exp;2657 return identifier;2658 },2659 cache(exp, isVNode = false) {2660 return createCacheExpression(context.cached++, exp, isVNode);2661 }2662 };2663 {2664 context.filters = new Set();2665 }2666 return context;2667}2668function transform(root, options) {2669 const context = createTransformContext(root, options);2670 traverseNode(root, context);2671 if (options.hoistStatic) {2672 hoistStatic(root, context);2673 }2674 if (!options.ssr) {2675 createRootCodegen(root, context);2676 }2677 // finalize meta information2678 root.helpers = [...context.helpers.keys()];2679 root.components = [...context.components];2680 root.directives = [...context.directives];2681 root.imports = context.imports;2682 root.hoists = context.hoists;2683 root.temps = context.temps;2684 root.cached = context.cached;2685 {2686 root.filters = [...context.filters];2687 }2688}2689function createRootCodegen(root, context) {2690 const { helper } = context;2691 const { children } = root;2692 if (children.length === 1) {2693 const child = children[0];2694 // if the single child is an element, turn it into a block.2695 if (isSingleElementRoot(root, child) && child.codegenNode) {2696 // single element root is never hoisted so codegenNode will never be2697 // SimpleExpressionNode2698 const codegenNode = child.codegenNode;2699 if (codegenNode.type === 13 /* VNODE_CALL */) {2700 makeBlock(codegenNode, context);2701 }2702 root.codegenNode = codegenNode;2703 }2704 else {2705 // - single <slot/>, IfNode, ForNode: already blocks.2706 // - single text node: always patched.2707 // root codegen falls through via genNode()2708 root.codegenNode = child;2709 }2710 }2711 else if (children.length > 1) {2712 // root has multiple nodes - return a fragment block.2713 let patchFlag = 64 /* STABLE_FRAGMENT */;2714 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];2715 // check if the fragment actually contains a single valid child with2716 // the rest being comments2717 if ((process.env.NODE_ENV !== 'production') &&2718 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2719 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2720 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;2721 }2722 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, undefined, false /* isComponent */);2723 }2724 else ;2725}2726function traverseChildren(parent, context) {2727 let i = 0;2728 const nodeRemoved = () => {2729 i--;2730 };2731 for (; i < parent.children.length; i++) {2732 const child = parent.children[i];2733 if (isString(child))2734 continue;2735 context.parent = parent;2736 context.childIndex = i;2737 context.onNodeRemoved = nodeRemoved;2738 traverseNode(child, context);2739 }2740}2741function traverseNode(node, context) {2742 context.currentNode = node;2743 // apply transform plugins2744 const { nodeTransforms } = context;2745 const exitFns = [];2746 for (let i = 0; i < nodeTransforms.length; i++) {2747 const onExit = nodeTransforms[i](node, context);2748 if (onExit) {2749 if (isArray(onExit)) {2750 exitFns.push(...onExit);2751 }2752 else {2753 exitFns.push(onExit);2754 }2755 }2756 if (!context.currentNode) {2757 // node was removed2758 return;2759 }2760 else {2761 // node may have been replaced2762 node = context.currentNode;2763 }2764 }2765 switch (node.type) {2766 case 3 /* COMMENT */:2767 if (!context.ssr) {2768 // inject import for the Comment symbol, which is needed for creating2769 // comment nodes with `createVNode`2770 context.helper(CREATE_COMMENT);2771 }2772 break;2773 case 5 /* INTERPOLATION */:2774 // no need to traverse, but we need to inject toString helper2775 if (!context.ssr) {2776 context.helper(TO_DISPLAY_STRING);2777 }2778 break;2779 // for container types, further traverse downwards2780 case 9 /* IF */:2781 for (let i = 0; i < node.branches.length; i++) {2782 traverseNode(node.branches[i], context);2783 }2784 break;2785 case 10 /* IF_BRANCH */:2786 case 11 /* FOR */:2787 case 1 /* ELEMENT */:2788 case 0 /* ROOT */:2789 traverseChildren(node, context);2790 break;2791 }2792 // exit transforms2793 context.currentNode = node;2794 let i = exitFns.length;2795 while (i--) {2796 exitFns[i]();2797 }2798}2799function createStructuralDirectiveTransform(name, fn) {2800 const matches = isString(name)2801 ? (n) => n === name2802 : (n) => name.test(n);2803 return (node, context) => {2804 if (node.type === 1 /* ELEMENT */) {2805 const { props } = node;2806 // structural directive transforms are not concerned with slots2807 // as they are handled separately in vSlot.ts2808 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2809 return;2810 }2811 const exitFns = [];2812 for (let i = 0; i < props.length; i++) {2813 const prop = props[i];2814 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2815 // structural directives are removed to avoid infinite recursion2816 // also we remove them *before* applying so that it can further2817 // traverse itself in case it moves the node around2818 props.splice(i, 1);2819 i--;2820 const onExit = fn(node, prop, context);2821 if (onExit)2822 exitFns.push(onExit);2823 }2824 }2825 return exitFns;2826 }2827 };2828}2829const PURE_ANNOTATION = `/*#__PURE__*/`;2830function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {2831 const context = {2832 mode,2833 prefixIdentifiers,2834 sourceMap,2835 filename,2836 scopeId,2837 optimizeImports,2838 runtimeGlobalName,2839 runtimeModuleName,2840 ssrRuntimeModuleName,2841 ssr,2842 isTS,2843 inSSR,2844 source: ast.loc.source,2845 code: ``,2846 column: 1,2847 line: 1,2848 offset: 0,2849 indentLevel: 0,2850 pure: false,2851 map: undefined,2852 helper(key) {2853 return `_${helperNameMap[key]}`;2854 },2855 push(code, node) {2856 context.code += code;2857 },2858 indent() {2859 newline(++context.indentLevel);2860 },2861 deindent(withoutNewLine = false) {2862 if (withoutNewLine) {2863 --context.indentLevel;2864 }2865 else {2866 newline(--context.indentLevel);2867 }2868 },2869 newline() {2870 newline(context.indentLevel);2871 }2872 };2873 function newline(n) {2874 context.push('\n' + ` `.repeat(n));2875 }2876 return context;2877}2878function generate(ast, options = {}) {2879 const context = createCodegenContext(ast, options);2880 if (options.onContextCreated)2881 options.onContextCreated(context);2882 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2883 const hasHelpers = ast.helpers.length > 0;2884 const useWithBlock = !prefixIdentifiers && mode !== 'module';2885 // preambles2886 // in setup() inline mode, the preamble is generated in a sub context2887 // and returned separately.2888 const preambleContext = context;2889 {2890 genFunctionPreamble(ast, preambleContext);2891 }2892 // enter render function2893 const functionName = ssr ? `ssrRender` : `render`;2894 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2895 const signature = args.join(', ');2896 {2897 push(`function ${functionName}(${signature}) {`);2898 }2899 indent();2900 if (useWithBlock) {2901 push(`with (_ctx) {`);2902 indent();2903 // function mode const declarations should be inside with block2904 // also they should be renamed to avoid collision with user properties2905 if (hasHelpers) {2906 push(`const { ${ast.helpers2907 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2908 .join(', ')} } = _Vue`);2909 push(`\n`);2910 newline();2911 }2912 }2913 // generate asset resolution statements2914 if (ast.components.length) {2915 genAssets(ast.components, 'component', context);2916 if (ast.directives.length || ast.temps > 0) {2917 newline();2918 }2919 }2920 if (ast.directives.length) {2921 genAssets(ast.directives, 'directive', context);2922 if (ast.temps > 0) {2923 newline();2924 }2925 }2926 if (ast.filters && ast.filters.length) {2927 newline();2928 genAssets(ast.filters, 'filter', context);2929 newline();2930 }2931 if (ast.temps > 0) {2932 push(`let `);2933 for (let i = 0; i < ast.temps; i++) {2934 push(`${i > 0 ? `, ` : ``}_temp${i}`);2935 }2936 }2937 if (ast.components.length || ast.directives.length || ast.temps) {2938 push(`\n`);2939 newline();2940 }2941 // generate the VNode tree expression2942 if (!ssr) {2943 push(`return `);2944 }2945 if (ast.codegenNode) {2946 genNode(ast.codegenNode, context);2947 }2948 else {2949 push(`null`);2950 }2951 if (useWithBlock) {2952 deindent();2953 push(`}`);2954 }2955 deindent();2956 push(`}`);2957 return {2958 ast,2959 code: context.code,2960 preamble: ``,2961 // SourceMapGenerator does have toJSON() method but it's not in the types2962 map: context.map ? context.map.toJSON() : undefined2963 };2964}2965function genFunctionPreamble(ast, context) {2966 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;2967 const VueBinding = runtimeGlobalName;2968 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2969 // Generate const declaration for helpers2970 // In prefix mode, we place the const declaration at top so it's done2971 // only once; But if we not prefixing, we place the declaration inside the2972 // with block so it doesn't incur the `in` check cost for every helper access.2973 if (ast.helpers.length > 0) {2974 {2975 // "with" mode.2976 // save Vue in a separate variable to avoid collision2977 push(`const _Vue = ${VueBinding}\n`);2978 // in "with" mode, helpers are declared inside the with block to avoid2979 // has check cost, but hoists are lifted out of the function - we need2980 // to provide the helper here.2981 if (ast.hoists.length) {2982 const staticHelpers = [2983 CREATE_VNODE,2984 CREATE_ELEMENT_VNODE,2985 CREATE_COMMENT,2986 CREATE_TEXT,2987 CREATE_STATIC2988 ]2989 .filter(helper => ast.helpers.includes(helper))2990 .map(aliasHelper)2991 .join(', ');2992 push(`const { ${staticHelpers} } = _Vue\n`);2993 }2994 }2995 }2996 genHoists(ast.hoists, context);2997 newline();2998 push(`return `);2999}3000function genAssets(assets, type, { helper, push, newline, isTS }) {3001 const resolver = helper(type === 'filter'3002 ? RESOLVE_FILTER3003 : type === 'component'3004 ? RESOLVE_COMPONENT3005 : RESOLVE_DIRECTIVE);3006 for (let i = 0; i < assets.length; i++) {3007 let id = assets[i];3008 // potential component implicit self-reference inferred from SFC filename3009 const maybeSelfReference = id.endsWith('__self');3010 if (maybeSelfReference) {3011 id = id.slice(0, -6);3012 }3013 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);3014 if (i < assets.length - 1) {3015 newline();3016 }3017 }3018}3019function genHoists(hoists, context) {3020 if (!hoists.length) {3021 return;3022 }3023 context.pure = true;3024 const { push, newline, helper, scopeId, mode } = context;3025 newline();3026 for (let i = 0; i < hoists.length; i++) {3027 const exp = hoists[i];3028 if (exp) {3029 push(`const _hoisted_${i + 1} = ${``}`);3030 genNode(exp, context);3031 newline();3032 }3033 }3034 context.pure = false;3035}3036function isText$1(n) {3037 return (isString(n) ||3038 n.type === 4 /* SIMPLE_EXPRESSION */ ||3039 n.type === 2 /* TEXT */ ||3040 n.type === 5 /* INTERPOLATION */ ||3041 n.type === 8 /* COMPOUND_EXPRESSION */);3042}3043function genNodeListAsArray(nodes, context) {3044 const multilines = nodes.length > 3 ||3045 (((process.env.NODE_ENV !== 'production')) && nodes.some(n => isArray(n) || !isText$1(n)));3046 context.push(`[`);3047 multilines && context.indent();3048 genNodeList(nodes, context, multilines);3049 multilines && context.deindent();3050 context.push(`]`);3051}3052function genNodeList(nodes, context, multilines = false, comma = true) {3053 const { push, newline } = context;3054 for (let i = 0; i < nodes.length; i++) {3055 const node = nodes[i];3056 if (isString(node)) {3057 push(node);3058 }3059 else if (isArray(node)) {3060 genNodeListAsArray(node, context);3061 }3062 else {3063 genNode(node, context);3064 }3065 if (i < nodes.length - 1) {3066 if (multilines) {3067 comma && push(',');3068 newline();3069 }3070 else {3071 comma && push(', ');3072 }3073 }3074 }3075}3076function genNode(node, context) {3077 if (isString(node)) {3078 context.push(node);3079 return;3080 }3081 if (isSymbol(node)) {3082 context.push(context.helper(node));3083 return;3084 }3085 switch (node.type) {3086 case 1 /* ELEMENT */:3087 case 9 /* IF */:3088 case 11 /* FOR */:3089 (process.env.NODE_ENV !== 'production') &&3090 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +3091 `Apply appropriate transforms first.`);3092 genNode(node.codegenNode, context);3093 break;3094 case 2 /* TEXT */:3095 genText(node, context);3096 break;3097 case 4 /* SIMPLE_EXPRESSION */:3098 genExpression(node, context);3099 break;3100 case 5 /* INTERPOLATION */:3101 genInterpolation(node, context);3102 break;3103 case 12 /* TEXT_CALL */:3104 genNode(node.codegenNode, context);3105 break;3106 case 8 /* COMPOUND_EXPRESSION */:3107 genCompoundExpression(node, context);3108 break;3109 case 3 /* COMMENT */:3110 genComment(node, context);3111 break;3112 case 13 /* VNODE_CALL */:3113 genVNodeCall(node, context);3114 break;3115 case 14 /* JS_CALL_EXPRESSION */:3116 genCallExpression(node, context);3117 break;3118 case 15 /* JS_OBJECT_EXPRESSION */:3119 genObjectExpression(node, context);3120 break;3121 case 17 /* JS_ARRAY_EXPRESSION */:3122 genArrayExpression(node, context);3123 break;3124 case 18 /* JS_FUNCTION_EXPRESSION */:3125 genFunctionExpression(node, context);3126 break;3127 case 19 /* JS_CONDITIONAL_EXPRESSION */:3128 genConditionalExpression(node, context);3129 break;3130 case 20 /* JS_CACHE_EXPRESSION */:3131 genCacheExpression(node, context);3132 break;3133 case 21 /* JS_BLOCK_STATEMENT */:3134 genNodeList(node.body, context, true, false);3135 break;3136 // SSR only types3137 case 22 /* JS_TEMPLATE_LITERAL */:3138 break;3139 case 23 /* JS_IF_STATEMENT */:3140 break;3141 case 24 /* JS_ASSIGNMENT_EXPRESSION */:3142 break;3143 case 25 /* JS_SEQUENCE_EXPRESSION */:3144 break;3145 case 26 /* JS_RETURN_STATEMENT */:3146 break;3147 /* istanbul ignore next */3148 case 10 /* IF_BRANCH */:3149 // noop3150 break;3151 default:3152 if ((process.env.NODE_ENV !== 'production')) {3153 assert(false, `unhandled codegen node type: ${node.type}`);3154 // make sure we exhaust all possible types3155 const exhaustiveCheck = node;3156 return exhaustiveCheck;3157 }3158 }3159}3160function genText(node, context) {3161 context.push(JSON.stringify(node.content), node);3162}3163function genExpression(node, context) {3164 const { content, isStatic } = node;3165 context.push(isStatic ? JSON.stringify(content) : content, node);3166}3167function genInterpolation(node, context) {3168 const { push, helper, pure } = context;3169 if (pure)3170 push(PURE_ANNOTATION);3171 push(`${helper(TO_DISPLAY_STRING)}(`);3172 genNode(node.content, context);3173 push(`)`);3174}3175function genCompoundExpression(node, context) {3176 for (let i = 0; i < node.children.length; i++) {3177 const child = node.children[i];3178 if (isString(child)) {3179 context.push(child);3180 }3181 else {3182 genNode(child, context);3183 }3184 }3185}3186function genExpressionAsPropertyKey(node, context) {3187 const { push } = context;3188 if (node.type === 8 /* COMPOUND_EXPRESSION */) {3189 push(`[`);3190 genCompoundExpression(node, context);3191 push(`]`);3192 }3193 else if (node.isStatic) {3194 // only quote keys if necessary3195 const text = isSimpleIdentifier(node.content)3196 ? node.content3197 : JSON.stringify(node.content);3198 push(text, node);3199 }3200 else {3201 push(`[${node.content}]`, node);3202 }3203}3204function genComment(node, context) {3205 const { push, helper, pure } = context;3206 if (pure) {3207 push(PURE_ANNOTATION);3208 }3209 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);3210}3211function genVNodeCall(node, context) {3212 const { push, helper, pure } = context;3213 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;3214 if (directives) {3215 push(helper(WITH_DIRECTIVES) + `(`);3216 }3217 if (isBlock) {3218 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);3219 }3220 if (pure) {3221 push(PURE_ANNOTATION);3222 }3223 const callHelper = isBlock3224 ? getVNodeBlockHelper(context.inSSR, isComponent)3225 : getVNodeHelper(context.inSSR, isComponent);3226 push(helper(callHelper) + `(`, node);3227 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);3228 push(`)`);3229 if (isBlock) {3230 push(`)`);3231 }3232 if (directives) {3233 push(`, `);3234 genNode(directives, context);3235 push(`)`);3236 }3237}3238function genNullableArgs(args) {3239 let i = args.length;3240 while (i--) {3241 if (args[i] != null)3242 break;3243 }3244 return args.slice(0, i + 1).map(arg => arg || `null`);3245}3246// JavaScript3247function genCallExpression(node, context) {3248 const { push, helper, pure } = context;3249 const callee = isString(node.callee) ? node.callee : helper(node.callee);3250 if (pure) {3251 push(PURE_ANNOTATION);3252 }3253 push(callee + `(`, node);3254 genNodeList(node.arguments, context);3255 push(`)`);3256}3257function genObjectExpression(node, context) {3258 const { push, indent, deindent, newline } = context;3259 const { properties } = node;3260 if (!properties.length) {3261 push(`{}`, node);3262 return;3263 }3264 const multilines = properties.length > 1 ||3265 (((process.env.NODE_ENV !== 'production')) &&3266 properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));3267 push(multilines ? `{` : `{ `);3268 multilines && indent();3269 for (let i = 0; i < properties.length; i++) {3270 const { key, value } = properties[i];3271 // key3272 genExpressionAsPropertyKey(key, context);3273 push(`: `);3274 // value3275 genNode(value, context);3276 if (i < properties.length - 1) {3277 // will only reach this if it's multilines3278 push(`,`);3279 newline();3280 }3281 }3282 multilines && deindent();3283 push(multilines ? `}` : ` }`);3284}3285function genArrayExpression(node, context) {3286 genNodeListAsArray(node.elements, context);3287}3288function genFunctionExpression(node, context) {3289 const { push, indent, deindent } = context;3290 const { params, returns, body, newline, isSlot } = node;3291 if (isSlot) {3292 // wrap slot functions with owner context3293 push(`_${helperNameMap[WITH_CTX]}(`);3294 }3295 push(`(`, node);3296 if (isArray(params)) {3297 genNodeList(params, context);3298 }3299 else if (params) {3300 genNode(params, context);3301 }3302 push(`) => `);3303 if (newline || body) {3304 push(`{`);3305 indent();3306 }3307 if (returns) {3308 if (newline) {3309 push(`return `);3310 }3311 if (isArray(returns)) {3312 genNodeListAsArray(returns, context);3313 }3314 else {3315 genNode(returns, context);3316 }3317 }3318 else if (body) {3319 genNode(body, context);3320 }3321 if (newline || body) {3322 deindent();3323 push(`}`);3324 }3325 if (isSlot) {3326 if (node.isNonScopedSlot) {3327 push(`, undefined, true`);3328 }3329 push(`)`);3330 }3331}3332function genConditionalExpression(node, context) {3333 const { test, consequent, alternate, newline: needNewline } = node;3334 const { push, indent, deindent, newline } = context;3335 if (test.type === 4 /* SIMPLE_EXPRESSION */) {3336 const needsParens = !isSimpleIdentifier(test.content);3337 needsParens && push(`(`);3338 genExpression(test, context);3339 needsParens && push(`)`);3340 }3341 else {3342 push(`(`);3343 genNode(test, context);3344 push(`)`);3345 }3346 needNewline && indent();3347 context.indentLevel++;3348 needNewline || push(` `);3349 push(`? `);3350 genNode(consequent, context);3351 context.indentLevel--;3352 needNewline && newline();3353 needNewline || push(` `);3354 push(`: `);3355 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;3356 if (!isNested) {3357 context.indentLevel++;3358 }3359 genNode(alternate, context);3360 if (!isNested) {3361 context.indentLevel--;3362 }3363 needNewline && deindent(true /* without newline */);3364}3365function genCacheExpression(node, context) {3366 const { push, helper, indent, deindent, newline } = context;3367 push(`_cache[${node.index}] || (`);3368 if (node.isVNode) {3369 indent();3370 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);3371 newline();3372 }3373 push(`_cache[${node.index}] = `);3374 genNode(node.value, context);3375 if (node.isVNode) {3376 push(`,`);3377 newline();3378 push(`${helper(SET_BLOCK_TRACKING)}(1),`);3379 newline();3380 push(`_cache[${node.index}]`);3381 deindent();3382 }3383 push(`)`);3384}3385function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {3386 {3387 return;3388 }3389}3390function isReferencedIdentifier(id, parent, parentStack) {3391 {3392 return false;3393 }3394}3395function isInDestructureAssignment(parent, parentStack) {3396 if (parent &&3397 (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {3398 let i = parentStack.length;3399 while (i--) {3400 const p = parentStack[i];3401 if (p.type === 'AssignmentExpression') {3402 return true;3403 }3404 else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {3405 break;3406 }3407 }3408 }3409 return false;3410}3411function walkFunctionParams(node, onIdent) {3412 for (const p of node.params) {3413 for (const id of extractIdentifiers(p)) {3414 onIdent(id);3415 }3416 }3417}3418function walkBlockDeclarations(block, onIdent) {3419 for (const stmt of block.body) {3420 if (stmt.type === 'VariableDeclaration') {3421 if (stmt.declare)3422 continue;3423 for (const decl of stmt.declarations) {3424 for (const id of extractIdentifiers(decl.id)) {3425 onIdent(id);3426 }3427 }3428 }3429 else if (stmt.type === 'FunctionDeclaration' ||3430 stmt.type === 'ClassDeclaration') {3431 if (stmt.declare || !stmt.id)3432 continue;3433 onIdent(stmt.id);3434 }3435 }3436}3437function extractIdentifiers(param, nodes = []) {3438 switch (param.type) {3439 case 'Identifier':3440 nodes.push(param);3441 break;3442 case 'MemberExpression':3443 let object = param;3444 while (object.type === 'MemberExpression') {3445 object = object.object;3446 }3447 nodes.push(object);3448 break;3449 case 'ObjectPattern':3450 for (const prop of param.properties) {3451 if (prop.type === 'RestElement') {3452 extractIdentifiers(prop.argument, nodes);3453 }3454 else {3455 extractIdentifiers(prop.value, nodes);3456 }3457 }3458 break;3459 case 'ArrayPattern':3460 param.elements.forEach(element => {3461 if (element)3462 extractIdentifiers(element, nodes);3463 });3464 break;3465 case 'RestElement':3466 extractIdentifiers(param.argument, nodes);3467 break;3468 case 'AssignmentPattern':3469 extractIdentifiers(param.left, nodes);3470 break;3471 }3472 return nodes;3473}3474const isFunctionType = (node) => {3475 return /Function(?:Expression|Declaration)$|Method$/.test(node.type);3476};3477const isStaticProperty = (node) => node &&3478 (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&3479 !node.computed;3480const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;3481// these keywords should not appear inside expressions, but operators like3482// typeof, instanceof and in are allowed3483const prohibitedKeywordRE = new RegExp('\\b' +3484 ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +3485 'super,throw,while,yield,delete,export,import,return,switch,default,' +3486 'extends,finally,continue,debugger,function,arguments,typeof,void')3487 .split(',')3488 .join('\\b|\\b') +3489 '\\b');3490// strip strings in expressions3491const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;3492/**3493 * Validate a non-prefixed expression.3494 * This is only called when using the in-browser runtime compiler since it3495 * doesn't prefix expressions.3496 */3497function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) {3498 const exp = node.content;3499 // empty expressions are validated per-directive since some directives3500 // do allow empty expressions.3501 if (!exp.trim()) {3502 return;3503 }3504 try {3505 new Function(asRawStatements3506 ? ` ${exp} `3507 : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`);3508 }3509 catch (e) {3510 let message = e.message;3511 const keywordMatch = exp3512 .replace(stripStringRE, '')3513 .match(prohibitedKeywordRE);3514 if (keywordMatch) {3515 message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`;3516 }3517 context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message));3518 }3519}3520const transformExpression = (node, context) => {3521 if (node.type === 5 /* INTERPOLATION */) {3522 node.content = processExpression(node.content, context);3523 }3524 else if (node.type === 1 /* ELEMENT */) {3525 // handle directives on element3526 for (let i = 0; i < node.props.length; i++) {3527 const dir = node.props[i];3528 // do not process for v-on & v-for since they are special handled3529 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {3530 const exp = dir.exp;3531 const arg = dir.arg;3532 // do not process exp if this is v-on:arg - we need special handling3533 // for wrapping inline statements.3534 if (exp &&3535 exp.type === 4 /* SIMPLE_EXPRESSION */ &&3536 !(dir.name === 'on' && arg)) {3537 dir.exp = processExpression(exp, context, 3538 // slot args must be processed as function params3539 dir.name === 'slot');3540 }3541 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {3542 dir.arg = processExpression(arg, context);3543 }3544 }3545 }3546 }3547};3548// Important: since this function uses Node.js only dependencies, it should3549// always be used with a leading !true check so that it can be3550// tree-shaken from the browser build.3551function processExpression(node, context, 3552// some expressions like v-slot props & v-for aliases should be parsed as3553// function params3554asParams = false, 3555// v-on handler values may contain multiple statements3556asRawStatements = false, localVars = Object.create(context.identifiers)) {3557 {3558 if ((process.env.NODE_ENV !== 'production')) {3559 // simple in-browser validation (same logic in 2.x)3560 validateBrowserExpression(node, context, asParams, asRawStatements);3561 }3562 return node;3563 }3564}3565const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {3566 return processIf(node, dir, context, (ifNode, branch, isRoot) => {3567 // #1587: We need to dynamically increment the key based on the current3568 // node's sibling nodes, since chained v-if/else branches are3569 // rendered at the same depth3570 const siblings = context.parent.children;3571 let i = siblings.indexOf(ifNode);3572 let key = 0;3573 while (i-- >= 0) {3574 const sibling = siblings[i];3575 if (sibling && sibling.type === 9 /* IF */) {3576 key += sibling.branches.length;3577 }3578 }3579 // Exit callback. Complete the codegenNode when all children have been3580 // transformed.3581 return () => {3582 if (isRoot) {3583 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);3584 }3585 else {3586 // attach this branch's codegen node to the v-if root.3587 const parentCondition = getParentCondition(ifNode.codegenNode);3588 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);3589 }3590 };3591 });3592});3593// target-agnostic transform used for both Client and SSR3594function processIf(node, dir, context, processCodegen) {3595 if (dir.name !== 'else' &&3596 (!dir.exp || !dir.exp.content.trim())) {3597 const loc = dir.exp ? dir.exp.loc : node.loc;3598 context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc));3599 dir.exp = createSimpleExpression(`true`, false, loc);3600 }3601 if ((process.env.NODE_ENV !== 'production') && true && dir.exp) {3602 validateBrowserExpression(dir.exp, context);3603 }3604 if (dir.name === 'if') {3605 const branch = createIfBranch(node, dir);3606 const ifNode = {3607 type: 9 /* IF */,3608 loc: node.loc,3609 branches: [branch]3610 };3611 context.replaceNode(ifNode);3612 if (processCodegen) {3613 return processCodegen(ifNode, branch, true);3614 }3615 }3616 else {3617 // locate the adjacent v-if3618 const siblings = context.parent.children;3619 const comments = [];3620 let i = siblings.indexOf(node);3621 while (i-- >= -1) {3622 const sibling = siblings[i];3623 if ((process.env.NODE_ENV !== 'production') && sibling && sibling.type === 3 /* COMMENT */) {3624 context.removeNode(sibling);3625 comments.unshift(sibling);3626 continue;3627 }3628 if (sibling &&3629 sibling.type === 2 /* TEXT */ &&3630 !sibling.content.trim().length) {3631 context.removeNode(sibling);3632 continue;3633 }3634 if (sibling && sibling.type === 9 /* IF */) {3635 // Check if v-else was followed by v-else-if3636 if (dir.name === 'else-if' &&3637 sibling.branches[sibling.branches.length - 1].condition === undefined) {3638 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3639 }3640 // move the node to the if node's branches3641 context.removeNode();3642 const branch = createIfBranch(node, dir);3643 if ((process.env.NODE_ENV !== 'production') &&3644 comments.length &&3645 // #3619 ignore comments if the v-if is direct child of <transition>3646 !(context.parent &&3647 context.parent.type === 1 /* ELEMENT */ &&3648 isBuiltInType(context.parent.tag, 'transition'))) {3649 branch.children = [...comments, ...branch.children];3650 }3651 // check if user is forcing same key on different branches3652 if ((process.env.NODE_ENV !== 'production') || !true) {3653 const key = branch.userKey;3654 if (key) {3655 sibling.branches.forEach(({ userKey }) => {3656 if (isSameKey(userKey, key)) {3657 context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc));3658 }3659 });3660 }3661 }3662 sibling.branches.push(branch);3663 const onExit = processCodegen && processCodegen(sibling, branch, false);3664 // since the branch was removed, it will not be traversed.3665 // make sure to traverse here.3666 traverseNode(branch, context);3667 // call on exit3668 if (onExit)3669 onExit();3670 // make sure to reset currentNode after traversal to indicate this3671 // node has been removed.3672 context.currentNode = null;3673 }3674 else {3675 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3676 }3677 break;3678 }3679 }3680}3681function createIfBranch(node, dir) {3682 return {3683 type: 10 /* IF_BRANCH */,3684 loc: node.loc,3685 condition: dir.name === 'else' ? undefined : dir.exp,3686 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')3687 ? node.children3688 : [node],3689 userKey: findProp(node, `key`)3690 };3691}3692function createCodegenNodeForBranch(branch, keyIndex, context) {3693 if (branch.condition) {3694 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 3695 // make sure to pass in asBlock: true so that the comment node call3696 // closes the current block.3697 createCallExpression(context.helper(CREATE_COMMENT), [3698 (process.env.NODE_ENV !== 'production') ? '"v-if"' : '""',3699 'true'3700 ]));3701 }3702 else {3703 return createChildrenCodegenNode(branch, keyIndex, context);3704 }3705}3706function createChildrenCodegenNode(branch, keyIndex, context) {3707 const { helper } = context;3708 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));3709 const { children } = branch;3710 const firstChild = children[0];3711 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;3712 if (needFragmentWrapper) {3713 if (children.length === 1 && firstChild.type === 11 /* FOR */) {3714 // optimize away nested fragments when child is a ForNode3715 const vnodeCall = firstChild.codegenNode;3716 injectProp(vnodeCall, keyProperty, context);3717 return vnodeCall;3718 }3719 else {3720 let patchFlag = 64 /* STABLE_FRAGMENT */;3721 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];3722 // check if the fragment actually contains a single valid child with3723 // the rest being comments3724 if ((process.env.NODE_ENV !== 'production') &&3725 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {3726 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;3727 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;3728 }3729 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, false, false /* isComponent */, branch.loc);3730 }3731 }3732 else {3733 const ret = firstChild.codegenNode;3734 const vnodeCall = getMemoedVNodeCall(ret);3735 // Change createVNode to createBlock.3736 if (vnodeCall.type === 13 /* VNODE_CALL */) {3737 makeBlock(vnodeCall, context);3738 }3739 // inject branch key3740 injectProp(vnodeCall, keyProperty, context);3741 return ret;3742 }3743}3744function isSameKey(a, b) {3745 if (!a || a.type !== b.type) {3746 return false;3747 }3748 if (a.type === 6 /* ATTRIBUTE */) {3749 if (a.value.content !== b.value.content) {3750 return false;3751 }3752 }3753 else {3754 // directive3755 const exp = a.exp;3756 const branchExp = b.exp;3757 if (exp.type !== branchExp.type) {3758 return false;3759 }3760 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||3761 exp.isStatic !== branchExp.isStatic ||3762 exp.content !== branchExp.content) {3763 return false;3764 }3765 }3766 return true;3767}3768function getParentCondition(node) {3769 while (true) {3770 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3771 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3772 node = node.alternate;3773 }3774 else {3775 return node;3776 }3777 }3778 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {3779 node = node.value;3780 }3781 }3782}3783const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {3784 const { helper, removeHelper } = context;3785 return processFor(node, dir, context, forNode => {3786 // create the loop render function expression now, and add the3787 // iterator on exit after all children have been traversed3788 const renderExp = createCallExpression(helper(RENDER_LIST), [3789 forNode.source3790 ]);3791 const isTemplate = isTemplateNode(node);3792 const memo = findDir(node, 'memo');3793 const keyProp = findProp(node, `key`);3794 const keyExp = keyProp &&3795 (keyProp.type === 6 /* ATTRIBUTE */3796 ? createSimpleExpression(keyProp.value.content, true)3797 : keyProp.exp);3798 const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;3799 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3800 forNode.source.constType > 0 /* NOT_CONSTANT */;3801 const fragmentFlag = isStableFragment3802 ? 64 /* STABLE_FRAGMENT */3803 : keyProp3804 ? 128 /* KEYED_FRAGMENT */3805 : 256 /* UNKEYED_FRAGMENT */;3806 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3807 ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);3808 return () => {3809 // finish the codegen now that all children have been traversed3810 let childBlock;3811 const { children } = forNode;3812 // check <template v-for> key placement3813 if (((process.env.NODE_ENV !== 'production') || !true) && isTemplate) {3814 node.children.some(c => {3815 if (c.type === 1 /* ELEMENT */) {3816 const key = findProp(c, 'key');3817 if (key) {3818 context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3819 return true;3820 }3821 }3822 });3823 }3824 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3825 const slotOutlet = isSlotOutlet(node)3826 ? node3827 : isTemplate &&3828 node.children.length === 1 &&3829 isSlotOutlet(node.children[0])3830 ? node.children[0] // api-extractor somehow fails to infer this3831 : null;3832 if (slotOutlet) {3833 // <slot v-for="..."> or <template v-for="..."><slot/></template>3834 childBlock = slotOutlet.codegenNode;3835 if (isTemplate && keyProperty) {3836 // <template v-for="..." :key="..."><slot/></template>3837 // we need to inject the key to the renderSlot() call.3838 // the props for renderSlot is passed as the 3rd argument.3839 injectProp(childBlock, keyProperty, context);3840 }3841 }3842 else if (needFragmentWrapper) {3843 // <template v-for="..."> with text or multi-elements3844 // should generate a fragment block for each loop3845 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3846 ((process.env.NODE_ENV !== 'production')3847 ? ` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`3848 : ``), undefined, undefined, true, undefined, false /* isComponent */);3849 }3850 else {3851 // Normal element v-for. Directly use the child's codegenNode3852 // but mark it as a block.3853 childBlock = children[0]3854 .codegenNode;3855 if (isTemplate && keyProperty) {3856 injectProp(childBlock, keyProperty, context);3857 }3858 if (childBlock.isBlock !== !isStableFragment) {3859 if (childBlock.isBlock) {3860 // switch from block to vnode3861 removeHelper(OPEN_BLOCK);3862 removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3863 }3864 else {3865 // switch from vnode to block3866 removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));3867 }3868 }3869 childBlock.isBlock = !isStableFragment;3870 if (childBlock.isBlock) {3871 helper(OPEN_BLOCK);3872 helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3873 }3874 else {3875 helper(getVNodeHelper(context.inSSR, childBlock.isComponent));3876 }3877 }3878 if (memo) {3879 const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [3880 createSimpleExpression(`_cached`)3881 ]));3882 loop.body = createBlockStatement([3883 createCompoundExpression([`const _memo = (`, memo.exp, `)`]),3884 createCompoundExpression([3885 `if (_cached`,3886 ...(keyExp ? [` && _cached.key === `, keyExp] : []),3887 ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`3888 ]),3889 createCompoundExpression([`const _item = `, childBlock]),3890 createSimpleExpression(`_item.memo = _memo`),3891 createSimpleExpression(`return _item`)3892 ]);3893 renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));3894 }3895 else {3896 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3897 }3898 };3899 });3900});3901// target-agnostic transform used for both Client and SSR3902function processFor(node, dir, context, processCodegen) {3903 if (!dir.exp) {3904 context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3905 return;3906 }3907 const parseResult = parseForExpression(3908 // can only be simple expression because vFor transform is applied3909 // before expression transform.3910 dir.exp, context);3911 if (!parseResult) {3912 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3913 return;3914 }3915 const { addIdentifiers, removeIdentifiers, scopes } = context;3916 const { source, value, key, index } = parseResult;3917 const forNode = {3918 type: 11 /* FOR */,3919 loc: dir.loc,3920 source,3921 valueAlias: value,3922 keyAlias: key,3923 objectIndexAlias: index,3924 parseResult,3925 children: isTemplateNode(node) ? node.children : [node]3926 };3927 context.replaceNode(forNode);3928 // bookkeeping3929 scopes.vFor++;3930 const onExit = processCodegen && processCodegen(forNode);3931 return () => {3932 scopes.vFor--;3933 if (onExit)3934 onExit();3935 };3936}3937const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3938// This regex doesn't cover the case if key or index aliases have destructuring,3939// but those do not make sense in the first place, so this works in practice.3940const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3941const stripParensRE = /^\(|\)$/g;3942function parseForExpression(input, context) {3943 const loc = input.loc;3944 const exp = input.content;3945 const inMatch = exp.match(forAliasRE);3946 if (!inMatch)3947 return;3948 const [, LHS, RHS] = inMatch;3949 const result = {3950 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3951 value: undefined,3952 key: undefined,3953 index: undefined3954 };3955 if ((process.env.NODE_ENV !== 'production') && true) {3956 validateBrowserExpression(result.source, context);3957 }3958 let valueContent = LHS.trim().replace(stripParensRE, '').trim();3959 const trimmedOffset = LHS.indexOf(valueContent);3960 const iteratorMatch = valueContent.match(forIteratorRE);3961 if (iteratorMatch) {3962 valueContent = valueContent.replace(forIteratorRE, '').trim();3963 const keyContent = iteratorMatch[1].trim();3964 let keyOffset;3965 if (keyContent) {3966 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3967 result.key = createAliasExpression(loc, keyContent, keyOffset);3968 if ((process.env.NODE_ENV !== 'production') && true) {3969 validateBrowserExpression(result.key, context, true);3970 }3971 }3972 if (iteratorMatch[2]) {3973 const indexContent = iteratorMatch[2].trim();3974 if (indexContent) {3975 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3976 ? keyOffset + keyContent.length3977 : trimmedOffset + valueContent.length));3978 if ((process.env.NODE_ENV !== 'production') && true) {3979 validateBrowserExpression(result.index, context, true);3980 }3981 }3982 }3983 }3984 if (valueContent) {3985 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3986 if ((process.env.NODE_ENV !== 'production') && true) {3987 validateBrowserExpression(result.value, context, true);3988 }3989 }3990 return result;3991}3992function createAliasExpression(range, content, offset) {3993 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3994}3995function createForLoopParams({ value, key, index }, memoArgs = []) {3996 return createParamsList([value, key, index, ...memoArgs]);3997}3998function createParamsList(args) {3999 let i = args.length;4000 while (i--) {4001 if (args[i])4002 break;4003 }4004 return args4005 .slice(0, i + 1)4006 .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));4007}4008const defaultFallback = createSimpleExpression(`undefined`, false);4009// A NodeTransform that:4010// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed4011// by transformExpression. This is only applied in non-browser builds with4012// { prefixIdentifiers: true }.4013// 2. Track v-slot depths so that we know a slot is inside another slot.4014// Note the exit callback is executed before buildSlots() on the same node,4015// so only nested slots see positive numbers.4016const trackSlotScopes = (node, context) => {4017 if (node.type === 1 /* ELEMENT */ &&4018 (node.tagType === 1 /* COMPONENT */ ||4019 node.tagType === 3 /* TEMPLATE */)) {4020 // We are only checking non-empty v-slot here4021 // since we only care about slots that introduce scope variables.4022 const vSlot = findDir(node, 'slot');4023 if (vSlot) {4024 context.scopes.vSlot++;4025 return () => {4026 context.scopes.vSlot--;4027 };4028 }4029 }4030};4031// A NodeTransform that tracks scope identifiers for scoped slots with v-for.4032// This transform is only applied in non-browser builds with { prefixIdentifiers: true }4033const trackVForSlotScopes = (node, context) => {4034 let vFor;4035 if (isTemplateNode(node) &&4036 node.props.some(isVSlot) &&4037 (vFor = findDir(node, 'for'))) {4038 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));4039 if (result) {4040 const { value, key, index } = result;4041 const { addIdentifiers, removeIdentifiers } = context;4042 value && addIdentifiers(value);4043 key && addIdentifiers(key);4044 index && addIdentifiers(index);4045 return () => {4046 value && removeIdentifiers(value);4047 key && removeIdentifiers(key);4048 index && removeIdentifiers(index);4049 };4050 }4051 }4052};4053const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);4054// Instead of being a DirectiveTransform, v-slot processing is called during4055// transformElement to build the slots object for a component.4056function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {4057 context.helper(WITH_CTX);4058 const { children, loc } = node;4059 const slotsProperties = [];4060 const dynamicSlots = [];4061 // If the slot is inside a v-for or another v-slot, force it to be dynamic4062 // since it likely uses a scope variable.4063 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;4064 // 1. Check for slot with slotProps on component itself.4065 // <Comp v-slot="{ prop }"/>4066 const onComponentSlot = findDir(node, 'slot', true);4067 if (onComponentSlot) {4068 const { arg, exp } = onComponentSlot;4069 if (arg && !isStaticExp(arg)) {4070 hasDynamicSlots = true;4071 }4072 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));4073 }4074 // 2. Iterate through children and check for template slots4075 // <template v-slot:foo="{ prop }">4076 let hasTemplateSlots = false;4077 let hasNamedDefaultSlot = false;4078 const implicitDefaultChildren = [];4079 const seenSlotNames = new Set();4080 for (let i = 0; i < children.length; i++) {4081 const slotElement = children[i];4082 let slotDir;4083 if (!isTemplateNode(slotElement) ||4084 !(slotDir = findDir(slotElement, 'slot', true))) {4085 // not a <template v-slot>, skip.4086 if (slotElement.type !== 3 /* COMMENT */) {4087 implicitDefaultChildren.push(slotElement);4088 }4089 continue;4090 }4091 if (onComponentSlot) {4092 // already has on-component slot - this is incorrect usage.4093 context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));4094 break;4095 }4096 hasTemplateSlots = true;4097 const { children: slotChildren, loc: slotLoc } = slotElement;4098 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;4099 // check if name is dynamic.4100 let staticSlotName;4101 if (isStaticExp(slotName)) {4102 staticSlotName = slotName ? slotName.content : `default`;4103 }4104 else {4105 hasDynamicSlots = true;4106 }4107 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);4108 // check if this slot is conditional (v-if/v-for)4109 let vIf;4110 let vElse;4111 let vFor;4112 if ((vIf = findDir(slotElement, 'if'))) {4113 hasDynamicSlots = true;4114 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));4115 }4116 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {4117 // find adjacent v-if4118 let j = i;4119 let prev;4120 while (j--) {4121 prev = children[j];4122 if (prev.type !== 3 /* COMMENT */) {4123 break;4124 }4125 }4126 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {4127 // remove node4128 children.splice(i, 1);4129 i--;4130 // attach this slot to previous conditional4131 let conditional = dynamicSlots[dynamicSlots.length - 1];4132 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {4133 conditional = conditional.alternate;4134 }4135 conditional.alternate = vElse.exp4136 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)4137 : buildDynamicSlot(slotName, slotFunction);4138 }4139 else {4140 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));4141 }4142 }4143 else if ((vFor = findDir(slotElement, 'for'))) {4144 hasDynamicSlots = true;4145 const parseResult = vFor.parseResult ||4146 parseForExpression(vFor.exp, context);4147 if (parseResult) {4148 // Render the dynamic slots as an array and add it to the createSlot()4149 // args. The runtime knows how to handle it appropriately.4150 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [4151 parseResult.source,4152 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)4153 ]));4154 }4155 else {4156 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));4157 }4158 }4159 else {4160 // check duplicate static names4161 if (staticSlotName) {4162 if (seenSlotNames.has(staticSlotName)) {4163 context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));4164 continue;4165 }4166 seenSlotNames.add(staticSlotName);4167 if (staticSlotName === 'default') {4168 hasNamedDefaultSlot = true;4169 }4170 }4171 slotsProperties.push(createObjectProperty(slotName, slotFunction));4172 }4173 }4174 if (!onComponentSlot) {4175 const buildDefaultSlotProperty = (props, children) => {4176 const fn = buildSlotFn(props, children, loc);4177 if (context.compatConfig) {4178 fn.isNonScopedSlot = true;4179 }4180 return createObjectProperty(`default`, fn);4181 };4182 if (!hasTemplateSlots) {4183 // implicit default slot (on component)4184 slotsProperties.push(buildDefaultSlotProperty(undefined, children));4185 }4186 else if (implicitDefaultChildren.length &&4187 // #37664188 // with whitespace: 'preserve', whitespaces between slots will end up in4189 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.4190 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {4191 // implicit default slot (mixed with named slots)4192 if (hasNamedDefaultSlot) {4193 context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));4194 }4195 else {4196 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));4197 }4198 }4199 }4200 const slotFlag = hasDynamicSlots4201 ? 2 /* DYNAMIC */4202 : hasForwardedSlots(node.children)4203 ? 3 /* FORWARDED */4204 : 1 /* STABLE */;4205 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 4206 // 2 = compiled but dynamic = can skip normalization, but must run diff4207 // 1 = compiled and static = can skip normalization AND diff as optimized4208 createSimpleExpression(slotFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${slotFlagsText[slotFlag]} */` : ``), false))), loc);4209 if (dynamicSlots.length) {4210 slots = createCallExpression(context.helper(CREATE_SLOTS), [4211 slots,4212 createArrayExpression(dynamicSlots)4213 ]);4214 }4215 return {4216 slots,4217 hasDynamicSlots4218 };4219}4220function buildDynamicSlot(name, fn) {4221 return createObjectExpression([4222 createObjectProperty(`name`, name),4223 createObjectProperty(`fn`, fn)4224 ]);4225}4226function hasForwardedSlots(children) {4227 for (let i = 0; i < children.length; i++) {4228 const child = children[i];4229 switch (child.type) {4230 case 1 /* ELEMENT */:4231 if (child.tagType === 2 /* SLOT */ ||4232 hasForwardedSlots(child.children)) {4233 return true;4234 }4235 break;4236 case 9 /* IF */:4237 if (hasForwardedSlots(child.branches))4238 return true;4239 break;4240 case 10 /* IF_BRANCH */:4241 case 11 /* FOR */:4242 if (hasForwardedSlots(child.children))4243 return true;4244 break;4245 }4246 }4247 return false;4248}4249function isNonWhitespaceContent(node) {4250 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)4251 return true;4252 return node.type === 2 /* TEXT */4253 ? !!node.content.trim()4254 : isNonWhitespaceContent(node.content);4255}4256// some directive transforms (e.g. v-model) may return a symbol for runtime4257// import, which should be used instead of a resolveDirective call.4258const directiveImportMap = new WeakMap();4259// generate a JavaScript AST for this element's codegen4260const transformElement = (node, context) => {4261 // perform the work on exit, after all child expressions have been4262 // processed and merged.4263 return function postTransformElement() {4264 node = context.currentNode;4265 if (!(node.type === 1 /* ELEMENT */ &&4266 (node.tagType === 0 /* ELEMENT */ ||4267 node.tagType === 1 /* COMPONENT */))) {4268 return;4269 }4270 const { tag, props } = node;4271 const isComponent = node.tagType === 1 /* COMPONENT */;4272 // The goal of the transform is to create a codegenNode implementing the4273 // VNodeCall interface.4274 let vnodeTag = isComponent4275 ? resolveComponentType(node, context)4276 : `"${tag}"`;4277 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;4278 let vnodeProps;4279 let vnodeChildren;4280 let vnodePatchFlag;4281 let patchFlag = 0;4282 let vnodeDynamicProps;4283 let dynamicPropNames;4284 let vnodeDirectives;4285 let shouldUseBlock = 4286 // dynamic component may resolve to plain elements4287 isDynamicComponent ||4288 vnodeTag === TELEPORT ||4289 vnodeTag === SUSPENSE ||4290 (!isComponent &&4291 // <svg> and <foreignObject> must be forced into blocks so that block4292 // updates inside get proper isSVG flag at runtime. (#639, #643)4293 // This is technically web-specific, but splitting the logic out of core4294 // leads to too much unnecessary complexity.4295 (tag === 'svg' || tag === 'foreignObject'));4296 // props4297 if (props.length > 0) {4298 const propsBuildResult = buildProps(node, context);4299 vnodeProps = propsBuildResult.props;4300 patchFlag = propsBuildResult.patchFlag;4301 dynamicPropNames = propsBuildResult.dynamicPropNames;4302 const directives = propsBuildResult.directives;4303 vnodeDirectives =4304 directives && directives.length4305 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))4306 : undefined;4307 if (propsBuildResult.shouldUseBlock) {4308 shouldUseBlock = true;4309 }4310 }4311 // children4312 if (node.children.length > 0) {4313 if (vnodeTag === KEEP_ALIVE) {4314 // Although a built-in component, we compile KeepAlive with raw children4315 // instead of slot functions so that it can be used inside Transition4316 // or other Transition-wrapping HOCs.4317 // To ensure correct updates with block optimizations, we need to:4318 // 1. Force keep-alive into a block. This avoids its children being4319 // collected by a parent block.4320 shouldUseBlock = true;4321 // 2. Force keep-alive to always be updated, since it uses raw children.4322 patchFlag |= 1024 /* DYNAMIC_SLOTS */;4323 if ((process.env.NODE_ENV !== 'production') && node.children.length > 1) {4324 context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {4325 start: node.children[0].loc.start,4326 end: node.children[node.children.length - 1].loc.end,4327 source: ''4328 }));4329 }4330 }4331 const shouldBuildAsSlots = isComponent &&4332 // Teleport is not a real component and has dedicated runtime handling4333 vnodeTag !== TELEPORT &&4334 // explained above.4335 vnodeTag !== KEEP_ALIVE;4336 if (shouldBuildAsSlots) {4337 const { slots, hasDynamicSlots } = buildSlots(node, context);4338 vnodeChildren = slots;4339 if (hasDynamicSlots) {4340 patchFlag |= 1024 /* DYNAMIC_SLOTS */;4341 }4342 }4343 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {4344 const child = node.children[0];4345 const type = child.type;4346 // check for dynamic text children4347 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||4348 type === 8 /* COMPOUND_EXPRESSION */;4349 if (hasDynamicTextChild &&4350 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {4351 patchFlag |= 1 /* TEXT */;4352 }4353 // pass directly if the only child is a text node4354 // (plain / interpolation / expression)4355 if (hasDynamicTextChild || type === 2 /* TEXT */) {4356 vnodeChildren = child;4357 }4358 else {4359 vnodeChildren = node.children;4360 }4361 }4362 else {4363 vnodeChildren = node.children;4364 }4365 }4366 // patchFlag & dynamicPropNames4367 if (patchFlag !== 0) {4368 if ((process.env.NODE_ENV !== 'production')) {4369 if (patchFlag < 0) {4370 // special flags (negative and mutually exclusive)4371 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;4372 }4373 else {4374 // bitwise flags4375 const flagNames = Object.keys(PatchFlagNames)4376 .map(Number)4377 .filter(n => n > 0 && patchFlag & n)4378 .map(n => PatchFlagNames[n])4379 .join(`, `);4380 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;4381 }4382 }4383 else {4384 vnodePatchFlag = String(patchFlag);4385 }4386 if (dynamicPropNames && dynamicPropNames.length) {4387 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);4388 }4389 }4390 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);4391 };4392};4393function resolveComponentType(node, context, ssr = false) {4394 let { tag } = node;4395 // 1. dynamic component4396 const isExplicitDynamic = isComponentTag(tag);4397 const isProp = findProp(node, 'is');4398 if (isProp) {4399 if (isExplicitDynamic ||4400 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {4401 const exp = isProp.type === 6 /* ATTRIBUTE */4402 ? isProp.value && createSimpleExpression(isProp.value.content, true)4403 : isProp.exp;4404 if (exp) {4405 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [4406 exp4407 ]);4408 }4409 }4410 else if (isProp.type === 6 /* ATTRIBUTE */ &&4411 isProp.value.content.startsWith('vue:')) {4412 // <button is="vue:xxx">4413 // if not <component>, only is value that starts with "vue:" will be4414 // treated as component by the parse phase and reach here, unless it's4415 // compat mode where all is values are considered components4416 tag = isProp.value.content.slice(4);4417 }4418 }4419 // 1.5 v-is (TODO: Deprecate)4420 const isDir = !isExplicitDynamic && findDir(node, 'is');4421 if (isDir && isDir.exp) {4422 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [4423 isDir.exp4424 ]);4425 }4426 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)4427 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);4428 if (builtIn) {4429 // built-ins are simply fallthroughs / have special handling during ssr4430 // so we don't need to import their runtime equivalents4431 if (!ssr)4432 context.helper(builtIn);4433 return builtIn;4434 }4435 // 5. user component (resolve)4436 context.helper(RESOLVE_COMPONENT);4437 context.components.add(tag);4438 return toValidAssetId(tag, `component`);4439}4440function buildProps(node, context, props = node.props, ssr = false) {4441 const { tag, loc: elementLoc, children } = node;4442 const isComponent = node.tagType === 1 /* COMPONENT */;4443 let properties = [];4444 const mergeArgs = [];4445 const runtimeDirectives = [];4446 const hasChildren = children.length > 0;4447 let shouldUseBlock = false;4448 // patchFlag analysis4449 let patchFlag = 0;4450 let hasRef = false;4451 let hasClassBinding = false;4452 let hasStyleBinding = false;4453 let hasHydrationEventBinding = false;4454 let hasDynamicKeys = false;4455 let hasVnodeHook = false;4456 const dynamicPropNames = [];4457 const analyzePatchFlag = ({ key, value }) => {4458 if (isStaticExp(key)) {4459 const name = key.content;4460 const isEventHandler = isOn(name);4461 if (!isComponent &&4462 isEventHandler &&4463 // omit the flag for click handlers because hydration gives click4464 // dedicated fast path.4465 name.toLowerCase() !== 'onclick' &&4466 // omit v-model handlers4467 name !== 'onUpdate:modelValue' &&4468 // omit onVnodeXXX hooks4469 !isReservedProp(name)) {4470 hasHydrationEventBinding = true;4471 }4472 if (isEventHandler && isReservedProp(name)) {4473 hasVnodeHook = true;4474 }4475 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||4476 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||4477 value.type === 8 /* COMPOUND_EXPRESSION */) &&4478 getConstantType(value, context) > 0)) {4479 // skip if the prop is a cached handler or has constant value4480 return;4481 }4482 if (name === 'ref') {4483 hasRef = true;4484 }4485 else if (name === 'class') {4486 hasClassBinding = true;4487 }4488 else if (name === 'style') {4489 hasStyleBinding = true;4490 }4491 else if (name !== 'key' && !dynamicPropNames.includes(name)) {4492 dynamicPropNames.push(name);4493 }4494 // treat the dynamic class and style binding of the component as dynamic props4495 if (isComponent &&4496 (name === 'class' || name === 'style') &&4497 !dynamicPropNames.includes(name)) {4498 dynamicPropNames.push(name);4499 }4500 }4501 else {4502 hasDynamicKeys = true;4503 }4504 };4505 for (let i = 0; i < props.length; i++) {4506 // static attribute4507 const prop = props[i];4508 if (prop.type === 6 /* ATTRIBUTE */) {4509 const { loc, name, value } = prop;4510 let isStatic = true;4511 if (name === 'ref') {4512 hasRef = true;4513 if (context.scopes.vFor > 0) {4514 properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));4515 }4516 }4517 // skip is on <component>, or is="vue:xxx"4518 if (name === 'is' &&4519 (isComponentTag(tag) ||4520 (value && value.content.startsWith('vue:')) ||4521 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {4522 continue;4523 }4524 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));4525 }4526 else {4527 // directives4528 const { name, arg, exp, loc } = prop;4529 const isVBind = name === 'bind';4530 const isVOn = name === 'on';4531 // skip v-slot - it is handled by its dedicated transform.4532 if (name === 'slot') {4533 if (!isComponent) {4534 context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc));4535 }4536 continue;4537 }4538 // skip v-once/v-memo - they are handled by dedicated transforms.4539 if (name === 'once' || name === 'memo') {4540 continue;4541 }4542 // skip v-is and :is on <component>4543 if (name === 'is' ||4544 (isVBind &&4545 isStaticArgOf(arg, 'is') &&4546 (isComponentTag(tag) ||4547 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {4548 continue;4549 }4550 // skip v-on in SSR compilation4551 if (isVOn && ssr) {4552 continue;4553 }4554 if (4555 // #938: elements with dynamic keys should be forced into blocks4556 (isVBind && isStaticArgOf(arg, 'key')) ||4557 // inline before-update hooks need to force block so that it is invoked4558 // before children4559 (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) {4560 shouldUseBlock = true;4561 }4562 if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {4563 properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));4564 }4565 // special case for v-bind and v-on with no argument4566 if (!arg && (isVBind || isVOn)) {4567 hasDynamicKeys = true;4568 if (exp) {4569 if (properties.length) {4570 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4571 properties = [];4572 }4573 if (isVBind) {4574 {4575 // 2.x v-bind object order compat4576 if ((process.env.NODE_ENV !== 'production')) {4577 const hasOverridableKeys = mergeArgs.some(arg => {4578 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {4579 return arg.properties.some(({ key }) => {4580 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||4581 !key.isStatic) {4582 return true;4583 }4584 return (key.content !== 'class' &&4585 key.content !== 'style' &&4586 !isOn(key.content));4587 });4588 }4589 else {4590 // dynamic expression4591 return true;4592 }4593 });4594 if (hasOverridableKeys) {4595 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);4596 }4597 }4598 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {4599 mergeArgs.unshift(exp);4600 continue;4601 }4602 }4603 mergeArgs.push(exp);4604 }4605 else {4606 // v-on="obj" -> toHandlers(obj)4607 mergeArgs.push({4608 type: 14 /* JS_CALL_EXPRESSION */,4609 loc,4610 callee: context.helper(TO_HANDLERS),4611 arguments: [exp]4612 });4613 }4614 }4615 else {4616 context.onError(createCompilerError(isVBind4617 ? 34 /* X_V_BIND_NO_EXPRESSION */4618 : 35 /* X_V_ON_NO_EXPRESSION */, loc));4619 }4620 continue;4621 }4622 const directiveTransform = context.directiveTransforms[name];4623 if (directiveTransform) {4624 // has built-in directive transform.4625 const { props, needRuntime } = directiveTransform(prop, node, context);4626 !ssr && props.forEach(analyzePatchFlag);4627 properties.push(...props);4628 if (needRuntime) {4629 runtimeDirectives.push(prop);4630 if (isSymbol(needRuntime)) {4631 directiveImportMap.set(prop, needRuntime);4632 }4633 }4634 }4635 else if (!isBuiltInDirective(name)) {4636 // no built-in transform, this is a user custom directive.4637 runtimeDirectives.push(prop);4638 // custom dirs may use beforeUpdate so they need to force blocks4639 // to ensure before-update gets called before children update4640 if (hasChildren) {4641 shouldUseBlock = true;4642 }4643 }4644 }4645 }4646 let propsExpression = undefined;4647 // has v-bind="object" or v-on="object", wrap with mergeProps4648 if (mergeArgs.length) {4649 if (properties.length) {4650 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4651 }4652 if (mergeArgs.length > 1) {4653 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);4654 }4655 else {4656 // single v-bind with nothing else - no need for a mergeProps call4657 propsExpression = mergeArgs[0];4658 }4659 }4660 else if (properties.length) {4661 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);4662 }4663 // patchFlag analysis4664 if (hasDynamicKeys) {4665 patchFlag |= 16 /* FULL_PROPS */;4666 }4667 else {4668 if (hasClassBinding && !isComponent) {4669 patchFlag |= 2 /* CLASS */;4670 }4671 if (hasStyleBinding && !isComponent) {4672 patchFlag |= 4 /* STYLE */;4673 }4674 if (dynamicPropNames.length) {4675 patchFlag |= 8 /* PROPS */;4676 }4677 if (hasHydrationEventBinding) {4678 patchFlag |= 32 /* HYDRATE_EVENTS */;4679 }4680 }4681 if (!shouldUseBlock &&4682 (patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&4683 (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {4684 patchFlag |= 512 /* NEED_PATCH */;4685 }4686 // pre-normalize props, SSR is skipped for now4687 if (!context.inSSR && propsExpression) {4688 switch (propsExpression.type) {4689 case 15 /* JS_OBJECT_EXPRESSION */:4690 // means that there is no v-bind,4691 // but still need to deal with dynamic key binding4692 let classKeyIndex = -1;4693 let styleKeyIndex = -1;4694 let hasDynamicKey = false;4695 for (let i = 0; i < propsExpression.properties.length; i++) {4696 const key = propsExpression.properties[i].key;4697 if (isStaticExp(key)) {4698 if (key.content === 'class') {4699 classKeyIndex = i;4700 }4701 else if (key.content === 'style') {4702 styleKeyIndex = i;4703 }4704 }4705 else if (!key.isHandlerKey) {4706 hasDynamicKey = true;4707 }4708 }4709 const classProp = propsExpression.properties[classKeyIndex];4710 const styleProp = propsExpression.properties[styleKeyIndex];4711 // no dynamic key4712 if (!hasDynamicKey) {4713 if (classProp && !isStaticExp(classProp.value)) {4714 classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]);4715 }4716 if (styleProp &&4717 !isStaticExp(styleProp.value) &&4718 // the static style is compiled into an object,4719 // so use `hasStyleBinding` to ensure that it is a dynamic style binding4720 (hasStyleBinding ||4721 // v-bind:style and style both exist,4722 // v-bind:style with static literal object4723 styleProp.value.type === 17 /* JS_ARRAY_EXPRESSION */)) {4724 styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]);4725 }4726 }4727 else {4728 // dynamic key binding, wrap with `normalizeProps`4729 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]);4730 }4731 break;4732 case 14 /* JS_CALL_EXPRESSION */:4733 // mergeProps call, do nothing4734 break;4735 default:4736 // single v-bind4737 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [4738 createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [4739 propsExpression4740 ])4741 ]);4742 break;4743 }4744 }4745 return {4746 props: propsExpression,4747 directives: runtimeDirectives,4748 patchFlag,4749 dynamicPropNames,4750 shouldUseBlock4751 };4752}4753// Dedupe props in an object literal.4754// Literal duplicated attributes would have been warned during the parse phase,4755// however, it's possible to encounter duplicated `onXXX` handlers with different4756// modifiers. We also need to merge static and dynamic class / style attributes.4757// - onXXX handlers / style: merge into array4758// - class: merge into single expression with concatenation4759function dedupeProperties(properties) {4760 const knownProps = new Map();4761 const deduped = [];4762 for (let i = 0; i < properties.length; i++) {4763 const prop = properties[i];4764 // dynamic keys are always allowed4765 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) {4766 deduped.push(prop);4767 continue;4768 }4769 const name = prop.key.content;4770 const existing = knownProps.get(name);4771 if (existing) {4772 if (name === 'style' || name === 'class' || isOn(name)) {4773 mergeAsArray(existing, prop);4774 }4775 // unexpected duplicate, should have emitted error during parse4776 }4777 else {4778 knownProps.set(name, prop);4779 deduped.push(prop);4780 }4781 }4782 return deduped;4783}4784function mergeAsArray(existing, incoming) {4785 if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) {4786 existing.value.elements.push(incoming.value);4787 }4788 else {4789 existing.value = createArrayExpression([existing.value, incoming.value], existing.loc);4790 }4791}4792function buildDirectiveArgs(dir, context) {4793 const dirArgs = [];4794 const runtime = directiveImportMap.get(dir);4795 if (runtime) {4796 // built-in directive with runtime4797 dirArgs.push(context.helperString(runtime));4798 }4799 else {4800 {4801 // inject statement for resolving directive4802 context.helper(RESOLVE_DIRECTIVE);4803 context.directives.add(dir.name);4804 dirArgs.push(toValidAssetId(dir.name, `directive`));4805 }4806 }4807 const { loc } = dir;4808 if (dir.exp)4809 dirArgs.push(dir.exp);4810 if (dir.arg) {4811 if (!dir.exp) {4812 dirArgs.push(`void 0`);4813 }4814 dirArgs.push(dir.arg);4815 }4816 if (Object.keys(dir.modifiers).length) {4817 if (!dir.arg) {4818 if (!dir.exp) {4819 dirArgs.push(`void 0`);4820 }4821 dirArgs.push(`void 0`);4822 }4823 const trueExpression = createSimpleExpression(`true`, false, loc);4824 dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc));4825 }4826 return createArrayExpression(dirArgs, dir.loc);4827}4828function stringifyDynamicPropNames(props) {4829 let propsNamesString = `[`;4830 for (let i = 0, l = props.length; i < l; i++) {4831 propsNamesString += JSON.stringify(props[i]);4832 if (i < l - 1)4833 propsNamesString += ', ';4834 }4835 return propsNamesString + `]`;4836}4837function isComponentTag(tag) {4838 return tag === 'component' || tag === 'Component';4839}4840(process.env.NODE_ENV !== 'production')4841 ? Object.freeze({})4842 : {};4843(process.env.NODE_ENV !== 'production') ? Object.freeze([]) : [];4844const cacheStringFunction = (fn) => {4845 const cache = Object.create(null);4846 return ((str) => {4847 const hit = cache[str];4848 return hit || (cache[str] = fn(str));4849 });4850};4851const camelizeRE = /-(\w)/g;4852/**4853 * @private4854 */4855const camelize = cacheStringFunction((str) => {4856 return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));4857});4858const transformSlotOutlet = (node, context) => {4859 if (isSlotOutlet(node)) {4860 const { children, loc } = node;4861 const { slotName, slotProps } = processSlotOutlet(node, context);4862 const slotArgs = [4863 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,4864 slotName,4865 '{}',4866 'undefined',4867 'true'4868 ];4869 let expectedLen = 2;4870 if (slotProps) {4871 slotArgs[2] = slotProps;4872 expectedLen = 3;4873 }4874 if (children.length) {4875 slotArgs[3] = createFunctionExpression([], children, false, false, loc);4876 expectedLen = 4;4877 }4878 if (context.scopeId && !context.slotted) {4879 expectedLen = 5;4880 }4881 slotArgs.splice(expectedLen); // remove unused arguments4882 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);4883 }4884};4885function processSlotOutlet(node, context) {4886 let slotName = `"default"`;4887 let slotProps = undefined;4888 const nonNameProps = [];4889 for (let i = 0; i < node.props.length; i++) {4890 const p = node.props[i];4891 if (p.type === 6 /* ATTRIBUTE */) {4892 if (p.value) {4893 if (p.name === 'name') {4894 slotName = JSON.stringify(p.value.content);4895 }4896 else {4897 p.name = camelize(p.name);4898 nonNameProps.push(p);4899 }4900 }4901 }4902 else {4903 if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {4904 if (p.exp)4905 slotName = p.exp;4906 }4907 else {4908 if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) {4909 p.arg.content = camelize(p.arg.content);4910 }4911 nonNameProps.push(p);4912 }4913 }4914 }4915 if (nonNameProps.length > 0) {4916 const { props, directives } = buildProps(node, context, nonNameProps);4917 slotProps = props;4918 if (directives.length) {4919 context.onError(createCompilerError(36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));4920 }4921 }4922 return {4923 slotName,4924 slotProps4925 };4926}4927const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;4928const transformOn = (dir, node, context, augmentor) => {4929 const { loc, modifiers, arg } = dir;4930 if (!dir.exp && !modifiers.length) {4931 context.onError(createCompilerError(35 /* X_V_ON_NO_EXPRESSION */, loc));4932 }4933 let eventName;4934 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4935 if (arg.isStatic) {4936 let rawName = arg.content;4937 // TODO deprecate @vnodeXXX usage4938 if (rawName.startsWith('vue:')) {4939 rawName = `vnode-${rawName.slice(4)}`;4940 }4941 // for all event listeners, auto convert it to camelCase. See issue #22494942 eventName = createSimpleExpression(toHandlerKey(camelize$1(rawName)), true, arg.loc);4943 }4944 else {4945 // #23884946 eventName = createCompoundExpression([4947 `${context.helperString(TO_HANDLER_KEY)}(`,4948 arg,4949 `)`4950 ]);4951 }4952 }4953 else {4954 // already a compound expression.4955 eventName = arg;4956 eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`);4957 eventName.children.push(`)`);4958 }4959 // handler processing4960 let exp = dir.exp;4961 if (exp && !exp.content.trim()) {4962 exp = undefined;4963 }4964 let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;4965 if (exp) {4966 const isMemberExp = isMemberExpression(exp.content);4967 const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));4968 const hasMultipleStatements = exp.content.includes(`;`);4969 if ((process.env.NODE_ENV !== 'production') && true) {4970 validateBrowserExpression(exp, context, false, hasMultipleStatements);4971 }4972 if (isInlineStatement || (shouldCache && isMemberExp)) {4973 // wrap inline statement in a function expression4974 exp = createCompoundExpression([4975 `${isInlineStatement4976 ? `$event`4977 : `${``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,4978 exp,4979 hasMultipleStatements ? `}` : `)`4980 ]);4981 }4982 }4983 let ret = {4984 props: [4985 createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))4986 ]4987 };4988 // apply extended compiler augmentor4989 if (augmentor) {4990 ret = augmentor(ret);4991 }4992 if (shouldCache) {4993 // cache handlers so that it's always the same handler being passed down.4994 // this avoids unnecessary re-renders when users use inline handlers on4995 // components.4996 ret.props[0].value = context.cache(ret.props[0].value);4997 }4998 // mark the key as handler for props normalization check4999 ret.props.forEach(p => (p.key.isHandlerKey = true));5000 return ret;5001};5002// v-bind without arg is handled directly in ./transformElements.ts due to it affecting5003// codegen for the entire props object. This transform here is only for v-bind5004// *with* args.5005const transformBind = (dir, _node, context) => {5006 const { exp, modifiers, loc } = dir;5007 const arg = dir.arg;5008 if (arg.type !== 4 /* SIMPLE_EXPRESSION */) {5009 arg.children.unshift(`(`);5010 arg.children.push(`) || ""`);5011 }5012 else if (!arg.isStatic) {5013 arg.content = `${arg.content} || ""`;5014 }5015 // .sync is replaced by v-model:arg5016 if (modifiers.includes('camel')) {5017 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {5018 if (arg.isStatic) {5019 arg.content = camelize$1(arg.content);5020 }5021 else {5022 arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;5023 }5024 }5025 else {5026 arg.children.unshift(`${context.helperString(CAMELIZE)}(`);5027 arg.children.push(`)`);5028 }5029 }5030 if (!context.inSSR) {5031 if (modifiers.includes('prop')) {5032 injectPrefix(arg, '.');5033 }5034 if (modifiers.includes('attr')) {5035 injectPrefix(arg, '^');5036 }5037 }5038 if (!exp ||5039 (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) {5040 context.onError(createCompilerError(34 /* X_V_BIND_NO_EXPRESSION */, loc));5041 return {5042 props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]5043 };5044 }5045 return {5046 props: [createObjectProperty(arg, exp)]5047 };5048};5049const injectPrefix = (arg, prefix) => {5050 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {5051 if (arg.isStatic) {5052 arg.content = prefix + arg.content;5053 }5054 else {5055 arg.content = `\`${prefix}\${${arg.content}}\``;5056 }5057 }5058 else {5059 arg.children.unshift(`'${prefix}' + (`);5060 arg.children.push(`)`);5061 }5062};5063// Merge adjacent text nodes and expressions into a single expression5064// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.5065const transformText = (node, context) => {5066 if (node.type === 0 /* ROOT */ ||5067 node.type === 1 /* ELEMENT */ ||5068 node.type === 11 /* FOR */ ||5069 node.type === 10 /* IF_BRANCH */) {5070 // perform the transform on node exit so that all expressions have already5071 // been processed.5072 return () => {5073 const children = node.children;5074 let currentContainer = undefined;5075 let hasText = false;5076 for (let i = 0; i < children.length; i++) {5077 const child = children[i];5078 if (isText(child)) {5079 hasText = true;5080 for (let j = i + 1; j < children.length; j++) {5081 const next = children[j];5082 if (isText(next)) {5083 if (!currentContainer) {5084 currentContainer = children[i] = {5085 type: 8 /* COMPOUND_EXPRESSION */,5086 loc: child.loc,5087 children: [child]5088 };5089 }5090 // merge adjacent text node into current5091 currentContainer.children.push(` + `, next);5092 children.splice(j, 1);5093 j--;5094 }5095 else {5096 currentContainer = undefined;5097 break;5098 }5099 }5100 }5101 }5102 if (!hasText ||5103 // if this is a plain element with a single text child, leave it5104 // as-is since the runtime has dedicated fast path for this by directly5105 // setting textContent of the element.5106 // for component root it's always normalized anyway.5107 (children.length === 1 &&5108 (node.type === 0 /* ROOT */ ||5109 (node.type === 1 /* ELEMENT */ &&5110 node.tagType === 0 /* ELEMENT */ &&5111 // #37565112 // custom directives can potentially add DOM elements arbitrarily,5113 // we need to avoid setting textContent of the element at runtime5114 // to avoid accidentally overwriting the DOM elements added5115 // by the user through custom directives.5116 !node.props.find(p => p.type === 7 /* DIRECTIVE */ &&5117 !context.directiveTransforms[p.name]) &&5118 // in compat mode, <template> tags with no special directives5119 // will be rendered as a fragment so its children must be5120 // converted into vnodes.5121 !(node.tag === 'template'))))) {5122 return;5123 }5124 // pre-convert text nodes into createTextVNode(text) calls to avoid5125 // runtime normalization.5126 for (let i = 0; i < children.length; i++) {5127 const child = children[i];5128 if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) {5129 const callArgs = [];5130 // createTextVNode defaults to single whitespace, so if it is a5131 // single space the code could be an empty call to save bytes.5132 if (child.type !== 2 /* TEXT */ || child.content !== ' ') {5133 callArgs.push(child);5134 }5135 // mark dynamic text with flag so it gets patched inside a block5136 if (!context.ssr &&5137 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {5138 callArgs.push(1 /* TEXT */ +5139 ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[1 /* TEXT */]} */` : ``));5140 }5141 children[i] = {5142 type: 12 /* TEXT_CALL */,5143 content: child,5144 loc: child.loc,5145 codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)5146 };5147 }5148 }5149 };5150 }5151};5152const seen = new WeakSet();5153const transformOnce = (node, context) => {5154 if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) {5155 if (seen.has(node) || context.inVOnce) {5156 return;5157 }5158 seen.add(node);5159 context.inVOnce = true;5160 context.helper(SET_BLOCK_TRACKING);5161 return () => {5162 context.inVOnce = false;5163 const cur = context.currentNode;5164 if (cur.codegenNode) {5165 cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */);5166 }5167 };5168 }5169};5170const transformModel = (dir, node, context) => {5171 const { exp, arg } = dir;5172 if (!exp) {5173 context.onError(createCompilerError(41 /* X_V_MODEL_NO_EXPRESSION */, dir.loc));5174 return createTransformProps();5175 }5176 const rawExp = exp.loc.source;5177 const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : rawExp;5178 const maybeRef = !true /* SETUP_CONST */;5179 if (!expString.trim() ||5180 (!isMemberExpression(expString) && !maybeRef)) {5181 context.onError(createCompilerError(42 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));5182 return createTransformProps();5183 }5184 const propName = arg ? arg : createSimpleExpression('modelValue', true);5185 const eventName = arg5186 ? isStaticExp(arg)5187 ? `onUpdate:${arg.content}`5188 : createCompoundExpression(['"onUpdate:" + ', arg])5189 : `onUpdate:modelValue`;5190 let assignmentExp;5191 const eventArg = context.isTS ? `($event: any)` : `$event`;5192 {5193 assignmentExp = createCompoundExpression([5194 `${eventArg} => ((`,5195 exp,5196 `) = $event)`5197 ]);5198 }5199 const props = [5200 // modelValue: foo5201 createObjectProperty(propName, dir.exp),5202 // "onUpdate:modelValue": $event => (foo = $event)5203 createObjectProperty(eventName, assignmentExp)5204 ];5205 // modelModifiers: { foo: true, "bar-baz": true }5206 if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) {5207 const modifiers = dir.modifiers5208 .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)5209 .join(`, `);5210 const modifiersKey = arg5211 ? isStaticExp(arg)5212 ? `${arg.content}Modifiers`5213 : createCompoundExpression([arg, ' + "Modifiers"'])5214 : `modelModifiers`;5215 props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* CAN_HOIST */)));5216 }5217 return createTransformProps(props);5218};5219function createTransformProps(props = []) {5220 return { props };5221}5222const validDivisionCharRE = /[\w).+\-_$\]]/;5223const transformFilter = (node, context) => {5224 if (!isCompatEnabled("COMPILER_FILTER" /* COMPILER_FILTERS */, context)) {5225 return;5226 }5227 if (node.type === 5 /* INTERPOLATION */) {5228 // filter rewrite is applied before expression transform so only5229 // simple expressions are possible at this stage5230 rewriteFilter(node.content, context);5231 }5232 if (node.type === 1 /* ELEMENT */) {5233 node.props.forEach((prop) => {5234 if (prop.type === 7 /* DIRECTIVE */ &&5235 prop.name !== 'for' &&5236 prop.exp) {5237 rewriteFilter(prop.exp, context);5238 }5239 });5240 }5241};5242function rewriteFilter(node, context) {5243 if (node.type === 4 /* SIMPLE_EXPRESSION */) {5244 parseFilter(node, context);5245 }5246 else {5247 for (let i = 0; i < node.children.length; i++) {5248 const child = node.children[i];5249 if (typeof child !== 'object')5250 continue;5251 if (child.type === 4 /* SIMPLE_EXPRESSION */) {5252 parseFilter(child, context);5253 }5254 else if (child.type === 8 /* COMPOUND_EXPRESSION */) {5255 rewriteFilter(node, context);5256 }5257 else if (child.type === 5 /* INTERPOLATION */) {5258 rewriteFilter(child.content, context);5259 }5260 }5261 }5262}5263function parseFilter(node, context) {5264 const exp = node.content;5265 let inSingle = false;5266 let inDouble = false;5267 let inTemplateString = false;5268 let inRegex = false;5269 let curly = 0;5270 let square = 0;5271 let paren = 0;5272 let lastFilterIndex = 0;5273 let c, prev, i, expression, filters = [];5274 for (i = 0; i < exp.length; i++) {5275 prev = c;5276 c = exp.charCodeAt(i);5277 if (inSingle) {5278 if (c === 0x27 && prev !== 0x5c)5279 inSingle = false;5280 }5281 else if (inDouble) {5282 if (c === 0x22 && prev !== 0x5c)5283 inDouble = false;5284 }5285 else if (inTemplateString) {5286 if (c === 0x60 && prev !== 0x5c)5287 inTemplateString = false;5288 }5289 else if (inRegex) {5290 if (c === 0x2f && prev !== 0x5c)5291 inRegex = false;5292 }5293 else if (c === 0x7c && // pipe5294 exp.charCodeAt(i + 1) !== 0x7c &&5295 exp.charCodeAt(i - 1) !== 0x7c &&5296 !curly &&5297 !square &&5298 !paren) {5299 if (expression === undefined) {5300 // first filter, end of expression5301 lastFilterIndex = i + 1;5302 expression = exp.slice(0, i).trim();5303 }5304 else {5305 pushFilter();5306 }5307 }5308 else {5309 switch (c) {5310 case 0x22:5311 inDouble = true;5312 break; // "5313 case 0x27:5314 inSingle = true;5315 break; // '5316 case 0x60:5317 inTemplateString = true;5318 break; // `5319 case 0x28:5320 paren++;5321 break; // (5322 case 0x29:5323 paren--;5324 break; // )5325 case 0x5b:5326 square++;5327 break; // [5328 case 0x5d:5329 square--;5330 break; // ]5331 case 0x7b:5332 curly++;5333 break; // {5334 case 0x7d:5335 curly--;5336 break; // }5337 }5338 if (c === 0x2f) {5339 // /5340 let j = i - 1;5341 let p;5342 // find first non-whitespace prev char5343 for (; j >= 0; j--) {5344 p = exp.charAt(j);5345 if (p !== ' ')5346 break;5347 }5348 if (!p || !validDivisionCharRE.test(p)) {5349 inRegex = true;5350 }5351 }5352 }5353 }5354 if (expression === undefined) {5355 expression = exp.slice(0, i).trim();5356 }5357 else if (lastFilterIndex !== 0) {5358 pushFilter();5359 }5360 function pushFilter() {5361 filters.push(exp.slice(lastFilterIndex, i).trim());5362 lastFilterIndex = i + 1;5363 }5364 if (filters.length) {5365 (process.env.NODE_ENV !== 'production') &&5366 warnDeprecation("COMPILER_FILTER" /* COMPILER_FILTERS */, context, node.loc);5367 for (i = 0; i < filters.length; i++) {5368 expression = wrapFilter(expression, filters[i], context);5369 }5370 node.content = expression;5371 }5372}5373function wrapFilter(exp, filter, context) {5374 context.helper(RESOLVE_FILTER);5375 const i = filter.indexOf('(');5376 if (i < 0) {5377 context.filters.add(filter);5378 return `${toValidAssetId(filter, 'filter')}(${exp})`;5379 }5380 else {5381 const name = filter.slice(0, i);5382 const args = filter.slice(i + 1);5383 context.filters.add(name);5384 return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`;5385 }5386}5387const seen$1 = new WeakSet();5388const transformMemo = (node, context) => {5389 if (node.type === 1 /* ELEMENT */) {5390 const dir = findDir(node, 'memo');5391 if (!dir || seen$1.has(node)) {5392 return;5393 }5394 seen$1.add(node);5395 return () => {5396 const codegenNode = node.codegenNode ||5397 context.currentNode.codegenNode;5398 if (codegenNode && codegenNode.type === 13 /* VNODE_CALL */) {5399 // non-component sub tree should be turned into a block5400 if (node.tagType !== 1 /* COMPONENT */) {5401 makeBlock(codegenNode, context);5402 }5403 node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [5404 dir.exp,5405 createFunctionExpression(undefined, codegenNode),5406 `_cache`,5407 String(context.cached++)5408 ]);5409 }5410 };5411 }5412};5413function getBaseTransformPreset(prefixIdentifiers) {5414 return [5415 [5416 transformOnce,5417 transformIf,5418 transformMemo,5419 transformFor,5420 ...([transformFilter] ),5421 ...((process.env.NODE_ENV !== 'production')5422 ? [transformExpression]5423 : []),5424 transformSlotOutlet,5425 transformElement,5426 trackSlotScopes,5427 transformText5428 ],5429 {5430 on: transformOn,5431 bind: transformBind,5432 model: transformModel5433 }5434 ];5435}5436// we name it `baseCompile` so that higher order compilers like5437// @vue/compiler-dom can export `compile` while re-exporting everything else.5438function baseCompile(template, options = {}) {5439 const onError = options.onError || defaultOnError;5440 const isModuleMode = options.mode === 'module';5441 /* istanbul ignore if */5442 {5443 if (options.prefixIdentifiers === true) {5444 onError(createCompilerError(46 /* X_PREFIX_ID_NOT_SUPPORTED */));5445 }5446 else if (isModuleMode) {5447 onError(createCompilerError(47 /* X_MODULE_MODE_NOT_SUPPORTED */));5448 }5449 }5450 const prefixIdentifiers = !true ;5451 if (options.cacheHandlers) {5452 onError(createCompilerError(48 /* X_CACHE_HANDLER_NOT_SUPPORTED */));5453 }5454 if (options.scopeId && !isModuleMode) {5455 onError(createCompilerError(49 /* X_SCOPE_ID_NOT_SUPPORTED */));5456 }5457 const ast = isString(template) ? baseParse(template, options) : template;5458 const [nodeTransforms, directiveTransforms] = getBaseTransformPreset();5459 transform(ast, extend({}, options, {5460 prefixIdentifiers,5461 nodeTransforms: [5462 ...nodeTransforms,5463 ...(options.nodeTransforms || []) // user transforms5464 ],5465 directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms5466 )5467 }));5468 return generate(ast, extend({}, options, {5469 prefixIdentifiers5470 }));5471}5472const noopDirectiveTransform = () => ({ props: [] });5473var compilerCore_esmBundler = {5474 __proto__: null,5475 BASE_TRANSITION: BASE_TRANSITION,5476 CAMELIZE: CAMELIZE,5477 CAPITALIZE: CAPITALIZE,5478 CREATE_BLOCK: CREATE_BLOCK,5479 CREATE_COMMENT: CREATE_COMMENT,5480 CREATE_ELEMENT_BLOCK: CREATE_ELEMENT_BLOCK,5481 CREATE_ELEMENT_VNODE: CREATE_ELEMENT_VNODE,5482 CREATE_SLOTS: CREATE_SLOTS,5483 CREATE_STATIC: CREATE_STATIC,5484 CREATE_TEXT: CREATE_TEXT,5485 CREATE_VNODE: CREATE_VNODE,5486 FRAGMENT: FRAGMENT,5487 GUARD_REACTIVE_PROPS: GUARD_REACTIVE_PROPS,5488 IS_MEMO_SAME: IS_MEMO_SAME,5489 IS_REF: IS_REF,5490 KEEP_ALIVE: KEEP_ALIVE,5491 MERGE_PROPS: MERGE_PROPS,5492 NORMALIZE_CLASS: NORMALIZE_CLASS,5493 NORMALIZE_PROPS: NORMALIZE_PROPS,5494 NORMALIZE_STYLE: NORMALIZE_STYLE,5495 OPEN_BLOCK: OPEN_BLOCK,5496 POP_SCOPE_ID: POP_SCOPE_ID,5497 PUSH_SCOPE_ID: PUSH_SCOPE_ID,5498 RENDER_LIST: RENDER_LIST,5499 RENDER_SLOT: RENDER_SLOT,5500 RESOLVE_COMPONENT: RESOLVE_COMPONENT,5501 RESOLVE_DIRECTIVE: RESOLVE_DIRECTIVE,5502 RESOLVE_DYNAMIC_COMPONENT: RESOLVE_DYNAMIC_COMPONENT,5503 RESOLVE_FILTER: RESOLVE_FILTER,5504 SET_BLOCK_TRACKING: SET_BLOCK_TRACKING,5505 SUSPENSE: SUSPENSE,5506 TELEPORT: TELEPORT,5507 TO_DISPLAY_STRING: TO_DISPLAY_STRING,5508 TO_HANDLERS: TO_HANDLERS,5509 TO_HANDLER_KEY: TO_HANDLER_KEY,5510 UNREF: UNREF,5511 WITH_CTX: WITH_CTX,5512 WITH_DIRECTIVES: WITH_DIRECTIVES,5513 WITH_MEMO: WITH_MEMO,5514 advancePositionWithClone: advancePositionWithClone,5515 advancePositionWithMutation: advancePositionWithMutation,5516 assert: assert,5517 baseCompile: baseCompile,5518 baseParse: baseParse,5519 buildDirectiveArgs: buildDirectiveArgs,5520 buildProps: buildProps,5521 buildSlots: buildSlots,5522 checkCompatEnabled: checkCompatEnabled,5523 createArrayExpression: createArrayExpression,5524 createAssignmentExpression: createAssignmentExpression,5525 createBlockStatement: createBlockStatement,5526 createCacheExpression: createCacheExpression,5527 createCallExpression: createCallExpression,5528 createCompilerError: createCompilerError,5529 createCompoundExpression: createCompoundExpression,5530 createConditionalExpression: createConditionalExpression,5531 createForLoopParams: createForLoopParams,5532 createFunctionExpression: createFunctionExpression,5533 createIfStatement: createIfStatement,5534 createInterpolation: createInterpolation,5535 createObjectExpression: createObjectExpression,5536 createObjectProperty: createObjectProperty,5537 createReturnStatement: createReturnStatement,5538 createRoot: createRoot,5539 createSequenceExpression: createSequenceExpression,5540 createSimpleExpression: createSimpleExpression,5541 createStructuralDirectiveTransform: createStructuralDirectiveTransform,5542 createTemplateLiteral: createTemplateLiteral,5543 createTransformContext: createTransformContext,5544 createVNodeCall: createVNodeCall,5545 extractIdentifiers: extractIdentifiers,5546 findDir: findDir,5547 findProp: findProp,5548 generate: generate,5549 getBaseTransformPreset: getBaseTransformPreset,5550 getInnerRange: getInnerRange,5551 getMemoedVNodeCall: getMemoedVNodeCall,5552 getVNodeBlockHelper: getVNodeBlockHelper,5553 getVNodeHelper: getVNodeHelper,5554 hasDynamicKeyVBind: hasDynamicKeyVBind,5555 hasScopeRef: hasScopeRef,5556 helperNameMap: helperNameMap,5557 injectProp: injectProp,5558 isBuiltInType: isBuiltInType,5559 isCoreComponent: isCoreComponent,5560 isFunctionType: isFunctionType,5561 isInDestructureAssignment: isInDestructureAssignment,5562 isMemberExpression: isMemberExpression,5563 isMemberExpressionBrowser: isMemberExpressionBrowser,5564 isMemberExpressionNode: isMemberExpressionNode,5565 isReferencedIdentifier: isReferencedIdentifier,5566 isSimpleIdentifier: isSimpleIdentifier,5567 isSlotOutlet: isSlotOutlet,5568 isStaticArgOf: isStaticArgOf,5569 isStaticExp: isStaticExp,5570 isStaticProperty: isStaticProperty,5571 isStaticPropertyKey: isStaticPropertyKey,5572 isTemplateNode: isTemplateNode,5573 isText: isText,5574 isVSlot: isVSlot,5575 locStub: locStub,5576 makeBlock: makeBlock,5577 noopDirectiveTransform: noopDirectiveTransform,5578 processExpression: processExpression,5579 processFor: processFor,5580 processIf: processIf,5581 processSlotOutlet: processSlotOutlet,5582 registerRuntimeHelpers: registerRuntimeHelpers,5583 resolveComponentType: resolveComponentType,5584 toValidAssetId: toValidAssetId,5585 trackSlotScopes: trackSlotScopes,5586 trackVForSlotScopes: trackVForSlotScopes,5587 transform: transform,5588 transformBind: transformBind,5589 transformElement: transformElement,5590 transformExpression: transformExpression,5591 transformModel: transformModel,5592 transformOn: transformOn,5593 traverseNode: traverseNode,5594 walkBlockDeclarations: walkBlockDeclarations,5595 walkFunctionParams: walkFunctionParams,5596 walkIdentifiers: walkIdentifiers,5597 warnDeprecation: warnDeprecation,5598 generateCodeFrame: generateCodeFrame5599};5600var require$$0 = /*@__PURE__*/build.getAugmentedNamespace(compilerCore_esmBundler);5601var require$$1 = /*@__PURE__*/build.getAugmentedNamespace(shared_esmBundler);5602(function (exports) {5603Object.defineProperty(exports, '__esModule', { value: true });5604var compilerCore = require$$0;5605var shared = require$$1;5606const V_MODEL_RADIO = Symbol(`vModelRadio` );5607const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` );5608const V_MODEL_TEXT = Symbol(`vModelText` );5609const V_MODEL_SELECT = Symbol(`vModelSelect` );5610const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` );5611const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` );5612const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` );5613const V_SHOW = Symbol(`vShow` );5614const TRANSITION = Symbol(`Transition` );5615const TRANSITION_GROUP = Symbol(`TransitionGroup` );5616compilerCore.registerRuntimeHelpers({5617 [V_MODEL_RADIO]: `vModelRadio`,5618 [V_MODEL_CHECKBOX]: `vModelCheckbox`,5619 [V_MODEL_TEXT]: `vModelText`,5620 [V_MODEL_SELECT]: `vModelSelect`,5621 [V_MODEL_DYNAMIC]: `vModelDynamic`,5622 [V_ON_WITH_MODIFIERS]: `withModifiers`,5623 [V_ON_WITH_KEYS]: `withKeys`,5624 [V_SHOW]: `vShow`,5625 [TRANSITION]: `Transition`,5626 [TRANSITION_GROUP]: `TransitionGroup`5627});5628var namedCharacterReferences = {5629 GT: ">",5630 gt: ">",5631 LT: "<",5632 lt: "<",5633 "ac;": "∾",5634 "af;": "⁡",5635 AMP: "&",5636 amp: "&",5637 "ap;": "≈",5638 "DD;": "ⅅ",5639 "dd;": "ⅆ",5640 deg: "°",5641 "ee;": "ⅇ",5642 "eg;": "⪚",5643 "el;": "⪙",5644 ETH: "Ð",5645 eth: "ð",5646 "gE;": "≧",5647 "ge;": "≥",5648 "Gg;": "⋙",5649 "gg;": "≫",5650 "gl;": "≷",5651 "GT;": ">",5652 "Gt;": "≫",5653 "gt;": ">",5654 "ic;": "⁣",5655 "ii;": "ⅈ",5656 "Im;": "ℑ",5657 "in;": "∈",5658 "it;": "⁢",5659 "lE;": "≦",5660 "le;": "≤",5661 "lg;": "≶",5662 "Ll;": "⋘",5663 "ll;": "≪",5664 "LT;": "<",5665 "Lt;": "≪",5666 "lt;": "<",5667 "mp;": "∓",5668 "Mu;": "Μ",5669 "mu;": "μ",5670 "ne;": "≠",5671 "ni;": "∋",5672 not: "¬",5673 "Nu;": "Ν",5674 "nu;": "ν",5675 "Or;": "⩔",5676 "or;": "∨",5677 "oS;": "Ⓢ",5678 "Pi;": "Π",5679 "pi;": "π",5680 "pm;": "±",5681 "Pr;": "⪻",5682 "pr;": "≺",5683 "Re;": "ℜ",5684 REG: "®",5685 reg: "®",5686 "rx;": "℞",5687 "Sc;": "⪼",5688 "sc;": "≻",5689 shy: "­",5690 uml: "¨",5691 "wp;": "℘",5692 "wr;": "≀",5693 "Xi;": "Ξ",5694 "xi;": "ξ",5695 yen: "¥",5696 "acd;": "∿",5697 "acE;": "∾̳",5698 "Acy;": "А",5699 "acy;": "а",5700 "Afr;": "𝔄",5701 "afr;": "𝔞",5702 "AMP;": "&",5703 "amp;": "&",5704 "And;": "⩓",5705 "and;": "∧",5706 "ang;": "∠",5707 "apE;": "⩰",5708 "ape;": "≊",5709 "ast;": "*",5710 Auml: "Ä",5711 auml: "ä",5712 "Bcy;": "Б",5713 "bcy;": "б",5714 "Bfr;": "𝔅",5715 "bfr;": "𝔟",5716 "bne;": "=⃥",5717 "bot;": "⊥",5718 "Cap;": "⋒",5719 "cap;": "∩",5720 cent: "¢",5721 "Cfr;": "ℭ",5722 "cfr;": "𝔠",5723 "Chi;": "Χ",5724 "chi;": "χ",5725 "cir;": "○",5726 COPY: "©",5727 copy: "©",5728 "Cup;": "⋓",5729 "cup;": "∪",5730 "Dcy;": "Д",5731 "dcy;": "д",5732 "deg;": "°",5733 "Del;": "∇",5734 "Dfr;": "𝔇",5735 "dfr;": "𝔡",5736 "die;": "¨",5737 "div;": "÷",5738 "Dot;": "¨",5739 "dot;": "˙",5740 "Ecy;": "Э",5741 "ecy;": "э",5742 "Efr;": "𝔈",5743 "efr;": "𝔢",5744 "egs;": "⪖",5745 "ell;": "ℓ",5746 "els;": "⪕",5747 "ENG;": "Ŋ",5748 "eng;": "ŋ",5749 "Eta;": "Η",5750 "eta;": "η",5751 "ETH;": "Ð",5752 "eth;": "ð",5753 Euml: "Ë",5754 euml: "ë",5755 "Fcy;": "Ф",5756 "fcy;": "ф",5757 "Ffr;": "𝔉",5758 "ffr;": "𝔣",5759 "gap;": "⪆",5760 "Gcy;": "Г",5761 "gcy;": "г",5762 "gEl;": "⪌",5763 "gel;": "⋛",5764 "geq;": "≥",5765 "ges;": "⩾",5766 "Gfr;": "𝔊",5767 "gfr;": "𝔤",5768 "ggg;": "⋙",5769 "gla;": "⪥",5770 "glE;": "⪒",5771 "glj;": "⪤",5772 "gnE;": "≩",5773 "gne;": "⪈",5774 "Hat;": "^",5775 "Hfr;": "ℌ",5776 "hfr;": "𝔥",5777 "Icy;": "И",5778 "icy;": "и",5779 "iff;": "⇔",5780 "Ifr;": "ℑ",5781 "ifr;": "𝔦",5782 "Int;": "∬",5783 "int;": "∫",5784 Iuml: "Ï",5785 iuml: "ï",5786 "Jcy;": "Й",5787 "jcy;": "й",5788 "Jfr;": "𝔍",5789 "jfr;": "𝔧",5790 "Kcy;": "К",5791 "kcy;": "к",5792 "Kfr;": "𝔎",5793 "kfr;": "𝔨",5794 "lap;": "⪅",5795 "lat;": "⪫",5796 "Lcy;": "Л",5797 "lcy;": "л",5798 "lEg;": "⪋",5799 "leg;": "⋚",5800 "leq;": "≤",5801 "les;": "⩽",5802 "Lfr;": "𝔏",5803 "lfr;": "𝔩",5804 "lgE;": "⪑",5805 "lnE;": "≨",5806 "lne;": "⪇",5807 "loz;": "◊",5808 "lrm;": "‎",5809 "Lsh;": "↰",5810 "lsh;": "↰",5811 macr: "¯",5812 "Map;": "⤅",5813 "map;": "↦",5814 "Mcy;": "М",5815 "mcy;": "м",5816 "Mfr;": "𝔐",5817 "mfr;": "𝔪",5818 "mho;": "℧",5819 "mid;": "∣",5820 "nap;": "≉",5821 nbsp: " ",5822 "Ncy;": "Н",5823 "ncy;": "н",5824 "Nfr;": "𝔑",5825 "nfr;": "𝔫",5826 "ngE;": "≧̸",5827 "nge;": "≱",5828 "nGg;": "⋙̸",5829 "nGt;": "≫⃒",5830 "ngt;": "≯",5831 "nis;": "⋼",5832 "niv;": "∋",5833 "nlE;": "≦̸",5834 "nle;": "≰",5835 "nLl;": "⋘̸",5836 "nLt;": "≪⃒",5837 "nlt;": "≮",5838 "Not;": "⫬",5839 "not;": "¬",5840 "npr;": "⊀",5841 "nsc;": "⊁",5842 "num;": "#",5843 "Ocy;": "О",5844 "ocy;": "о",5845 "Ofr;": "𝔒",5846 "ofr;": "𝔬",5847 "ogt;": "⧁",5848 "ohm;": "Ω",5849 "olt;": "⧀",5850 "ord;": "⩝",5851 ordf: "ª",5852 ordm: "º",5853 "orv;": "⩛",5854 Ouml: "Ö",5855 ouml: "ö",5856 "par;": "∥",5857 para: "¶",5858 "Pcy;": "П",5859 "pcy;": "п",5860 "Pfr;": "𝔓",5861 "pfr;": "𝔭",5862 "Phi;": "Φ",5863 "phi;": "φ",5864 "piv;": "ϖ",5865 "prE;": "⪳",5866 "pre;": "⪯",5867 "Psi;": "Ψ",5868 "psi;": "ψ",5869 "Qfr;": "𝔔",5870 "qfr;": "𝔮",5871 QUOT: "\"",5872 quot: "\"",5873 "Rcy;": "Р",5874 "rcy;": "р",5875 "REG;": "®",5876 "reg;": "®",5877 "Rfr;": "ℜ",5878 "rfr;": "𝔯",5879 "Rho;": "Ρ",5880 "rho;": "ρ",5881 "rlm;": "‏",5882 "Rsh;": "↱",5883 "rsh;": "↱",5884 "scE;": "⪴",5885 "sce;": "⪰",5886 "Scy;": "С",5887 "scy;": "с",5888 sect: "§",5889 "Sfr;": "𝔖",5890 "sfr;": "𝔰",5891 "shy;": "­",5892 "sim;": "∼",5893 "smt;": "⪪",5894 "sol;": "/",5895 "squ;": "□",5896 "Sub;": "⋐",5897 "sub;": "⊂",5898 "Sum;": "∑",5899 "sum;": "∑",5900 "Sup;": "⋑",5901 "sup;": "⊃",5902 sup1: "¹",5903 sup2: "²",5904 sup3: "³",5905 "Tab;": "\t",5906 "Tau;": "Τ",5907 "tau;": "τ",5908 "Tcy;": "Т",5909 "tcy;": "т",5910 "Tfr;": "𝔗",5911 "tfr;": "𝔱",5912 "top;": "⊤",5913 "Ucy;": "У",5914 "ucy;": "у",5915 "Ufr;": "𝔘",5916 "ufr;": "𝔲",5917 "uml;": "¨",5918 Uuml: "Ü",5919 uuml: "ü",5920 "Vcy;": "В",5921 "vcy;": "в",5922 "Vee;": "⋁",5923 "vee;": "∨",5924 "Vfr;": "𝔙",5925 "vfr;": "𝔳",5926 "Wfr;": "𝔚",5927 "wfr;": "𝔴",5928 "Xfr;": "𝔛",5929 "xfr;": "𝔵",5930 "Ycy;": "Ы",5931 "ycy;": "ы",5932 "yen;": "¥",5933 "Yfr;": "𝔜",5934 "yfr;": "𝔶",5935 yuml: "ÿ",5936 "Zcy;": "З",5937 "zcy;": "з",5938 "Zfr;": "ℨ",5939 "zfr;": "𝔷",5940 "zwj;": "‍",5941 Acirc: "Â",5942 acirc: "â",5943 acute: "´",5944 AElig: "Æ",5945 aelig: "æ",5946 "andd;": "⩜",5947 "andv;": "⩚",5948 "ange;": "⦤",5949 "Aopf;": "𝔸",5950 "aopf;": "𝕒",5951 "apid;": "≋",5952 "apos;": "'",5953 Aring: "Å",5954 aring: "å",5955 "Ascr;": "𝒜",5956 "ascr;": "𝒶",5957 "Auml;": "Ä",5958 "auml;": "ä",5959 "Barv;": "⫧",5960 "bbrk;": "⎵",5961 "Beta;": "Β",5962 "beta;": "β",5963 "beth;": "ℶ",5964 "bNot;": "⫭",5965 "bnot;": "⌐",5966 "Bopf;": "𝔹",5967 "bopf;": "𝕓",5968 "boxH;": "═",5969 "boxh;": "─",5970 "boxV;": "║",5971 "boxv;": "│",5972 "Bscr;": "ℬ",5973 "bscr;": "𝒷",5974 "bsim;": "∽",5975 "bsol;": "\\",5976 "bull;": "•",5977 "bump;": "≎",5978 "caps;": "∩︀",5979 "Cdot;": "Ċ",5980 "cdot;": "ċ",5981 cedil: "¸",5982 "cent;": "¢",5983 "CHcy;": "Ч",5984 "chcy;": "ч",5985 "circ;": "ˆ",5986 "cirE;": "⧃",5987 "cire;": "≗",5988 "comp;": "∁",5989 "cong;": "≅",5990 "Copf;": "ℂ",5991 "copf;": "𝕔",5992 "COPY;": "©",5993 "copy;": "©",5994 "Cscr;": "𝒞",5995 "cscr;": "𝒸",5996 "csub;": "⫏",5997 "csup;": "⫐",5998 "cups;": "∪︀",5999 "Darr;": "↡",6000 "dArr;": "⇓",6001 "darr;": "↓",6002 "dash;": "‐",6003 "dHar;": "⥥",6004 "diam;": "⋄",6005 "DJcy;": "Ђ",6006 "djcy;": "ђ",6007 "Dopf;": "𝔻",6008 "dopf;": "𝕕",6009 "Dscr;": "𝒟",6010 "dscr;": "𝒹",6011 "DScy;": "Ѕ",6012 "dscy;": "ѕ",6013 "dsol;": "⧶",6014 "dtri;": "▿",6015 "DZcy;": "Џ",6016 "dzcy;": "џ",6017 "ecir;": "≖",6018 Ecirc: "Ê",6019 ecirc: "ê",6020 "Edot;": "Ė",6021 "eDot;": "≑",6022 "edot;": "ė",6023 "emsp;": " ",6024 "ensp;": " ",6025 "Eopf;": "𝔼",6026 "eopf;": "𝕖",6027 "epar;": "⋕",6028 "epsi;": "ε",6029 "Escr;": "ℰ",6030 "escr;": "ℯ",6031 "Esim;": "⩳",6032 "esim;": "≂",6033 "Euml;": "Ë",6034 "euml;": "ë",6035 "euro;": "€",6036 "excl;": "!",6037 "flat;": "♭",6038 "fnof;": "ƒ",6039 "Fopf;": "𝔽",6040 "fopf;": "𝕗",6041 "fork;": "⋔",6042 "Fscr;": "ℱ",6043 "fscr;": "𝒻",6044 "Gdot;": "Ġ",6045 "gdot;": "ġ",6046 "geqq;": "≧",6047 "gesl;": "⋛︀",6048 "GJcy;": "Ѓ",6049 "gjcy;": "ѓ",6050 "gnap;": "⪊",6051 "gneq;": "⪈",6052 "Gopf;": "𝔾",6053 "gopf;": "𝕘",6054 "Gscr;": "𝒢",6055 "gscr;": "ℊ",6056 "gsim;": "≳",6057 "gtcc;": "⪧",6058 "gvnE;": "≩︀",6059 "half;": "½",6060 "hArr;": "⇔",6061 "harr;": "↔",6062 "hbar;": "ℏ",6063 "Hopf;": "ℍ",6064 "hopf;": "𝕙",6065 "Hscr;": "ℋ",6066 "hscr;": "𝒽",6067 Icirc: "Î",6068 icirc: "î",6069 "Idot;": "İ",6070 "IEcy;": "Е",6071 "iecy;": "е",6072 iexcl: "¡",6073 "imof;": "⊷",6074 "IOcy;": "Ё",6075 "iocy;": "ё",6076 "Iopf;": "𝕀",6077 "iopf;": "𝕚",6078 "Iota;": "Ι",6079 "iota;": "ι",6080 "Iscr;": "ℐ",6081 "iscr;": "𝒾",6082 "isin;": "∈",6083 "Iuml;": "Ï",6084 "iuml;": "ï",6085 "Jopf;": "𝕁",6086 "jopf;": "𝕛",6087 "Jscr;": "𝒥",6088 "jscr;": "𝒿",6089 "KHcy;": "Х",6090 "khcy;": "х",6091 "KJcy;": "Ќ",6092 "kjcy;": "ќ",6093 "Kopf;": "𝕂",6094 "kopf;": "𝕜",6095 "Kscr;": "𝒦",6096 "kscr;": "𝓀",6097 "Lang;": "⟪",6098 "lang;": "⟨",6099 laquo: "«",6100 "Larr;": "↞",6101 "lArr;": "⇐",6102 "larr;": "←",6103 "late;": "⪭",6104 "lcub;": "{",6105 "ldca;": "⤶",6106 "ldsh;": "↲",6107 "leqq;": "≦",6108 "lesg;": "⋚︀",6109 "lHar;": "⥢",6110 "LJcy;": "Љ",6111 "ljcy;": "љ",6112 "lnap;": "⪉",6113 "lneq;": "⪇",6114 "Lopf;": "𝕃",6115 "lopf;": "𝕝",6116 "lozf;": "⧫",6117 "lpar;": "(",6118 "Lscr;": "ℒ",6119 "lscr;": "𝓁",6120 "lsim;": "≲",6121 "lsqb;": "[",6122 "ltcc;": "⪦",6123 "ltri;": "◃",6124 "lvnE;": "≨︀",6125 "macr;": "¯",6126 "male;": "♂",6127 "malt;": "✠",6128 micro: "µ",6129 "mlcp;": "⫛",6130 "mldr;": "…",6131 "Mopf;": "𝕄",6132 "mopf;": "𝕞",6133 "Mscr;": "ℳ",6134 "mscr;": "𝓂",6135 "nang;": "∠⃒",6136 "napE;": "⩰̸",6137 "nbsp;": " ",6138 "ncap;": "⩃",6139 "ncup;": "⩂",6140 "ngeq;": "≱",6141 "nges;": "⩾̸",6142 "ngtr;": "≯",6143 "nGtv;": "≫̸",6144 "nisd;": "⋺",6145 "NJcy;": "Њ",6146 "njcy;": "њ",6147 "nldr;": "‥",6148 "nleq;": "≰",6149 "nles;": "⩽̸",6150 "nLtv;": "≪̸",6151 "nmid;": "∤",6152 "Nopf;": "ℕ",6153 "nopf;": "𝕟",6154 "npar;": "∦",6155 "npre;": "⪯̸",6156 "nsce;": "⪰̸",6157 "Nscr;": "𝒩",6158 "nscr;": "𝓃",6159 "nsim;": "≁",6160 "nsub;": "⊄",6161 "nsup;": "⊅",6162 "ntgl;": "≹",6163 "ntlg;": "≸",6164 "nvap;": "≍⃒",6165 "nvge;": "≥⃒",6166 "nvgt;": ">⃒",6167 "nvle;": "≤⃒",6168 "nvlt;": "<⃒",6169 "oast;": "⊛",6170 "ocir;": "⊚",6171 Ocirc: "Ô",6172 ocirc: "ô",6173 "odiv;": "⨸",6174 "odot;": "⊙",6175 "ogon;": "˛",6176 "oint;": "∮",6177 "omid;": "⦶",6178 "Oopf;": "𝕆",6179 "oopf;": "𝕠",6180 "opar;": "⦷",6181 "ordf;": "ª",6182 "ordm;": "º",6183 "oror;": "⩖",6184 "Oscr;": "𝒪",6185 "oscr;": "ℴ",6186 "osol;": "⊘",6187 "Ouml;": "Ö",6188 "ouml;": "ö",6189 "para;": "¶",6190 "part;": "∂",6191 "perp;": "⊥",6192 "phiv;": "ϕ",6193 "plus;": "+",6194 "Popf;": "ℙ",6195 "popf;": "𝕡",6196 pound: "£",6197 "prap;": "⪷",6198 "prec;": "≺",6199 "prnE;": "⪵",6200 "prod;": "∏",6201 "prop;": "∝",6202 "Pscr;": "𝒫",6203 "pscr;": "𝓅",6204 "qint;": "⨌",6205 "Qopf;": "ℚ",6206 "qopf;": "𝕢",6207 "Qscr;": "𝒬",6208 "qscr;": "𝓆",6209 "QUOT;": "\"",6210 "quot;": "\"",6211 "race;": "∽̱",6212 "Rang;": "⟫",6213 "rang;": "⟩",6214 raquo: "»",6215 "Rarr;": "↠",6216 "rArr;": "⇒",6217 "rarr;": "→",6218 "rcub;": "}",6219 "rdca;": "⤷",6220 "rdsh;": "↳",6221 "real;": "ℜ",6222 "rect;": "▭",6223 "rHar;": "⥤",6224 "rhov;": "ϱ",6225 "ring;": "˚",6226 "Ropf;": "ℝ",6227 "ropf;": "𝕣",6228 "rpar;": ")",6229 "Rscr;": "ℛ",6230 "rscr;": "𝓇",6231 "rsqb;": "]",6232 "rtri;": "▹",6233 "scap;": "⪸",6234 "scnE;": "⪶",6235 "sdot;": "⋅",6236 "sect;": "§",6237 "semi;": ";",6238 "sext;": "✶",6239 "SHcy;": "Ш",6240 "shcy;": "ш",6241 "sime;": "≃",6242 "simg;": "⪞",6243 "siml;": "⪝",6244 "smid;": "∣",6245 "smte;": "⪬",6246 "solb;": "⧄",6247 "Sopf;": "𝕊",6248 "sopf;": "𝕤",6249 "spar;": "∥",6250 "Sqrt;": "√",6251 "squf;": "▪",6252 "Sscr;": "𝒮",6253 "sscr;": "𝓈",6254 "Star;": "⋆",6255 "star;": "☆",6256 "subE;": "⫅",6257 "sube;": "⊆",6258 "succ;": "≻",6259 "sung;": "♪",6260 "sup1;": "¹",6261 "sup2;": "²",6262 "sup3;": "³",6263 "supE;": "⫆",6264 "supe;": "⊇",6265 szlig: "ß",6266 "tbrk;": "⎴",6267 "tdot;": "⃛",6268 THORN: "Þ",6269 thorn: "þ",6270 times: "×",6271 "tint;": "∭",6272 "toea;": "⤨",6273 "Topf;": "𝕋",6274 "topf;": "𝕥",6275 "tosa;": "⤩",6276 "trie;": "≜",6277 "Tscr;": "𝒯",6278 "tscr;": "𝓉",6279 "TScy;": "Ц",6280 "tscy;": "ц",6281 "Uarr;": "↟",6282 "uArr;": "⇑",6283 "uarr;": "↑",6284 Ucirc: "Û",6285 ucirc: "û",6286 "uHar;": "⥣",6287 "Uopf;": "𝕌",6288 "uopf;": "𝕦",6289 "Upsi;": "ϒ",6290 "upsi;": "υ",6291 "Uscr;": "𝒰",6292 "uscr;": "𝓊",6293 "utri;": "▵",6294 "Uuml;": "Ü",6295 "uuml;": "ü",6296 "vArr;": "⇕",6297 "varr;": "↕",6298 "Vbar;": "⫫",6299 "vBar;": "⫨",6300 "Vert;": "‖",6301 "vert;": "|",6302 "Vopf;": "𝕍",6303 "vopf;": "𝕧",6304 "Vscr;": "𝒱",6305 "vscr;": "𝓋",6306 "Wopf;": "𝕎",6307 "wopf;": "𝕨",6308 "Wscr;": "𝒲",6309 "wscr;": "𝓌",6310 "xcap;": "⋂",6311 "xcup;": "⋃",6312 "xmap;": "⟼",6313 "xnis;": "⋻",6314 "Xopf;": "𝕏",6315 "xopf;": "𝕩",6316 "Xscr;": "𝒳",6317 "xscr;": "𝓍",6318 "xvee;": "⋁",6319 "YAcy;": "Я",6320 "yacy;": "я",6321 "YIcy;": "Ї",6322 "yicy;": "ї",6323 "Yopf;": "𝕐",6324 "yopf;": "𝕪",6325 "Yscr;": "𝒴",6326 "yscr;": "𝓎",6327 "YUcy;": "Ю",6328 "yucy;": "ю",6329 "Yuml;": "Ÿ",6330 "yuml;": "ÿ",6331 "Zdot;": "Ż",6332 "zdot;": "ż",6333 "Zeta;": "Ζ",6334 "zeta;": "ζ",6335 "ZHcy;": "Ж",6336 "zhcy;": "ж",6337 "Zopf;": "ℤ",6338 "zopf;": "𝕫",6339 "Zscr;": "𝒵",6340 "zscr;": "𝓏",6341 "zwnj;": "‌",6342 Aacute: "Á",6343 aacute: "á",6344 "Acirc;": "Â",6345 "acirc;": "â",6346 "acute;": "´",6347 "AElig;": "Æ",6348 "aelig;": "æ",6349 Agrave: "À",6350 agrave: "à",6351 "aleph;": "ℵ",6352 "Alpha;": "Α",6353 "alpha;": "α",6354 "Amacr;": "Ā",6355 "amacr;": "ā",6356 "amalg;": "⨿",6357 "angle;": "∠",6358 "angrt;": "∟",6359 "angst;": "Å",6360 "Aogon;": "Ą",6361 "aogon;": "ą",6362 "Aring;": "Å",6363 "aring;": "å",6364 "asymp;": "≈",6365 Atilde: "Ã",6366 atilde: "ã",6367 "awint;": "⨑",6368 "bcong;": "≌",6369 "bdquo;": "„",6370 "bepsi;": "϶",6371 "blank;": "␣",6372 "blk12;": "▒",6373 "blk14;": "░",6374 "blk34;": "▓",6375 "block;": "█",6376 "boxDL;": "╗",6377 "boxDl;": "╖",6378 "boxdL;": "╕",6379 "boxdl;": "┐",6380 "boxDR;": "╔",6381 "boxDr;": "╓",6382 "boxdR;": "╒",6383 "boxdr;": "┌",6384 "boxHD;": "╦",6385 "boxHd;": "╤",6386 "boxhD;": "╥",6387 "boxhd;": "┬",6388 "boxHU;": "╩",6389 "boxHu;": "╧",6390 "boxhU;": "╨",6391 "boxhu;": "┴",6392 "boxUL;": "╝",6393 "boxUl;": "╜",6394 "boxuL;": "╛",6395 "boxul;": "┘",6396 "boxUR;": "╚",6397 "boxUr;": "╙",6398 "boxuR;": "╘",6399 "boxur;": "└",6400 "boxVH;": "╬",6401 "boxVh;": "╫",6402 "boxvH;": "╪",6403 "boxvh;": "┼",6404 "boxVL;": "╣",6405 "boxVl;": "╢",6406 "boxvL;": "╡",6407 "boxvl;": "┤",6408 "boxVR;": "╠",6409 "boxVr;": "╟",6410 "boxvR;": "╞",6411 "boxvr;": "├",6412 "Breve;": "˘",6413 "breve;": "˘",6414 brvbar: "¦",6415 "bsemi;": "⁏",6416 "bsime;": "⋍",6417 "bsolb;": "⧅",6418 "bumpE;": "⪮",6419 "bumpe;": "≏",6420 "caret;": "⁁",6421 "caron;": "ˇ",6422 "ccaps;": "⩍",6423 Ccedil: "Ç",6424 ccedil: "ç",6425 "Ccirc;": "Ĉ",6426 "ccirc;": "ĉ",6427 "ccups;": "⩌",6428 "cedil;": "¸",6429 "check;": "✓",6430 "clubs;": "♣",6431 "Colon;": "∷",6432 "colon;": ":",6433 "comma;": ",",6434 "crarr;": "↵",6435 "Cross;": "⨯",6436 "cross;": "✗",6437 "csube;": "⫑",6438 "csupe;": "⫒",6439 "ctdot;": "⋯",6440 "cuepr;": "⋞",6441 "cuesc;": "⋟",6442 "cupor;": "⩅",6443 curren: "¤",6444 "cuvee;": "⋎",6445 "cuwed;": "⋏",6446 "cwint;": "∱",6447 "Dashv;": "⫤",6448 "dashv;": "⊣",6449 "dblac;": "˝",6450 "ddarr;": "⇊",6451 "Delta;": "Δ",6452 "delta;": "δ",6453 "dharl;": "⇃",6454 "dharr;": "⇂",6455 "diams;": "♦",6456 "disin;": "⋲",6457 divide: "÷",6458 "doteq;": "≐",6459 "dtdot;": "⋱",6460 "dtrif;": "▾",6461 "duarr;": "⇵",6462 "duhar;": "⥯",6463 Eacute: "É",6464 eacute: "é",6465 "Ecirc;": "Ê",6466 "ecirc;": "ê",6467 "eDDot;": "⩷",6468 "efDot;": "≒",6469 Egrave: "È",6470 egrave: "è",6471 "Emacr;": "Ē",6472 "emacr;": "ē",6473 "empty;": "∅",6474 "Eogon;": "Ę",6475 "eogon;": "ę",6476 "eplus;": "⩱",6477 "epsiv;": "ϵ",6478 "eqsim;": "≂",6479 "Equal;": "⩵",6480 "equiv;": "≡",6481 "erarr;": "⥱",6482 "erDot;": "≓",6483 "esdot;": "≐",6484 "exist;": "∃",6485 "fflig;": "ff",6486 "filig;": "fi",6487 "fjlig;": "fj",6488 "fllig;": "fl",6489 "fltns;": "▱",6490 "forkv;": "⫙",6491 frac12: "½",6492 frac14: "¼",6493 frac34: "¾",6494 "frasl;": "⁄",6495 "frown;": "⌢",6496 "Gamma;": "Γ",6497 "gamma;": "γ",6498 "Gcirc;": "Ĝ",6499 "gcirc;": "ĝ",6500 "gescc;": "⪩",6501 "gimel;": "ℷ",6502 "gneqq;": "≩",6503 "gnsim;": "⋧",6504 "grave;": "`",6505 "gsime;": "⪎",6506 "gsiml;": "⪐",6507 "gtcir;": "⩺",6508 "gtdot;": "⋗",6509 "Hacek;": "ˇ",6510 "harrw;": "↭",6511 "Hcirc;": "Ĥ",6512 "hcirc;": "ĥ",6513 "hoarr;": "⇿",6514 Iacute: "Í",6515 iacute: "í",6516 "Icirc;": "Î",6517 "icirc;": "î",6518 "iexcl;": "¡",6519 Igrave: "Ì",6520 igrave: "ì",6521 "iiint;": "∭",6522 "iiota;": "℩",6523 "IJlig;": "IJ",6524 "ijlig;": "ij",6525 "Imacr;": "Ī",6526 "imacr;": "ī",6527 "image;": "ℑ",6528 "imath;": "ı",6529 "imped;": "Ƶ",6530 "infin;": "∞",6531 "Iogon;": "Į",6532 "iogon;": "į",6533 "iprod;": "⨼",6534 iquest: "¿",6535 "isinE;": "⋹",6536 "isins;": "⋴",6537 "isinv;": "∈",6538 "Iukcy;": "І",6539 "iukcy;": "і",6540 "Jcirc;": "Ĵ",6541 "jcirc;": "ĵ",6542 "jmath;": "ȷ",6543 "Jukcy;": "Є",6544 "jukcy;": "є",6545 "Kappa;": "Κ",6546 "kappa;": "κ",6547 "lAarr;": "⇚",6548 "langd;": "⦑",6549 "laquo;": "«",6550 "larrb;": "⇤",6551 "lates;": "⪭︀",6552 "lBarr;": "⤎",6553 "lbarr;": "⤌",6554 "lbbrk;": "❲",6555 "lbrke;": "⦋",6556 "lceil;": "⌈",6557 "ldquo;": "“",6558 "lescc;": "⪨",6559 "lhard;": "↽",6560 "lharu;": "↼",6561 "lhblk;": "▄",6562 "llarr;": "⇇",6563 "lltri;": "◺",6564 "lneqq;": "≨",6565 "lnsim;": "⋦",6566 "loang;": "⟬",6567 "loarr;": "⇽",6568 "lobrk;": "⟦",6569 "lopar;": "⦅",6570 "lrarr;": "⇆",6571 "lrhar;": "⇋",6572 "lrtri;": "⊿",6573 "lsime;": "⪍",6574 "lsimg;": "⪏",6575 "lsquo;": "‘",6576 "ltcir;": "⩹",6577 "ltdot;": "⋖",6578 "ltrie;": "⊴",6579 "ltrif;": "◂",6580 "mdash;": "—",6581 "mDDot;": "∺",6582 "micro;": "µ",6583 middot: "·",6584 "minus;": "−",6585 "mumap;": "⊸",6586 "nabla;": "∇",6587 "napid;": "≋̸",6588 "napos;": "ʼn",6589 "natur;": "♮",6590 "nbump;": "≎̸",6591 "ncong;": "≇",6592 "ndash;": "–",6593 "neArr;": "⇗",6594 "nearr;": "↗",6595 "nedot;": "≐̸",6596 "nesim;": "≂̸",6597 "ngeqq;": "≧̸",6598 "ngsim;": "≵",6599 "nhArr;": "⇎",6600 "nharr;": "↮",6601 "nhpar;": "⫲",6602 "nlArr;": "⇍",6603 "nlarr;": "↚",6604 "nleqq;": "≦̸",6605 "nless;": "≮",6606 "nlsim;": "≴",6607 "nltri;": "⋪",6608 "notin;": "∉",6609 "notni;": "∌",6610 "npart;": "∂̸",6611 "nprec;": "⊀",6612 "nrArr;": "⇏",6613 "nrarr;": "↛",6614 "nrtri;": "⋫",6615 "nsime;": "≄",6616 "nsmid;": "∤",6617 "nspar;": "∦",6618 "nsubE;": "⫅̸",6619 "nsube;": "⊈",6620 "nsucc;": "⊁",6621 "nsupE;": "⫆̸",6622 "nsupe;": "⊉",6623 Ntilde: "Ñ",6624 ntilde: "ñ",6625 "numsp;": " ",6626 "nvsim;": "∼⃒",6627 "nwArr;": "⇖",6628 "nwarr;": "↖",6629 Oacute: "Ó",6630 oacute: "ó",6631 "Ocirc;": "Ô",6632 "ocirc;": "ô",6633 "odash;": "⊝",6634 "OElig;": "Œ",6635 "oelig;": "œ",6636 "ofcir;": "⦿",6637 Ograve: "Ò",6638 ograve: "ò",6639 "ohbar;": "⦵",6640 "olarr;": "↺",6641 "olcir;": "⦾",6642 "oline;": "‾",6643 "Omacr;": "Ō",6644 "omacr;": "ō",6645 "Omega;": "Ω",6646 "omega;": "ω",6647 "operp;": "⦹",6648 "oplus;": "⊕",6649 "orarr;": "↻",6650 "order;": "ℴ",6651 Oslash: "Ø",6652 oslash: "ø",6653 Otilde: "Õ",6654 otilde: "õ",6655 "ovbar;": "⌽",6656 "parsl;": "⫽",6657 "phone;": "☎",6658 "plusb;": "⊞",6659 "pluse;": "⩲",6660 plusmn: "±",6661 "pound;": "£",6662 "prcue;": "≼",6663 "Prime;": "″",6664 "prime;": "′",6665 "prnap;": "⪹",6666 "prsim;": "≾",6667 "quest;": "?",6668 "rAarr;": "⇛",6669 "radic;": "√",6670 "rangd;": "⦒",6671 "range;": "⦥",6672 "raquo;": "»",6673 "rarrb;": "⇥",6674 "rarrc;": "⤳",6675 "rarrw;": "↝",6676 "ratio;": "∶",6677 "RBarr;": "⤐",6678 "rBarr;": "⤏",6679 "rbarr;": "⤍",6680 "rbbrk;": "❳",6681 "rbrke;": "⦌",6682 "rceil;": "⌉",6683 "rdquo;": "”",6684 "reals;": "ℝ",6685 "rhard;": "⇁",6686 "rharu;": "⇀",6687 "rlarr;": "⇄",6688 "rlhar;": "⇌",6689 "rnmid;": "⫮",6690 "roang;": "⟭",6691 "roarr;": "⇾",6692 "robrk;": "⟧",6693 "ropar;": "⦆",6694 "rrarr;": "⇉",6695 "rsquo;": "’",6696 "rtrie;": "⊵",6697 "rtrif;": "▸",6698 "sbquo;": "‚",6699 "sccue;": "≽",6700 "Scirc;": "Ŝ",6701 "scirc;": "ŝ",6702 "scnap;": "⪺",6703 "scsim;": "≿",6704 "sdotb;": "⊡",6705 "sdote;": "⩦",6706 "seArr;": "⇘",6707 "searr;": "↘",6708 "setmn;": "∖",6709 "sharp;": "♯",6710 "Sigma;": "Σ",6711 "sigma;": "σ",6712 "simeq;": "≃",6713 "simgE;": "⪠",6714 "simlE;": "⪟",6715 "simne;": "≆",6716 "slarr;": "←",6717 "smile;": "⌣",6718 "smtes;": "⪬︀",6719 "sqcap;": "⊓",6720 "sqcup;": "⊔",6721 "sqsub;": "⊏",6722 "sqsup;": "⊐",6723 "srarr;": "→",6724 "starf;": "★",6725 "strns;": "¯",6726 "subnE;": "⫋",6727 "subne;": "⊊",6728 "supnE;": "⫌",6729 "supne;": "⊋",6730 "swArr;": "⇙",6731 "swarr;": "↙",6732 "szlig;": "ß",6733 "Theta;": "Θ",6734 "theta;": "θ",6735 "thkap;": "≈",6736 "THORN;": "Þ",6737 "thorn;": "þ",6738 "Tilde;": "∼",6739 "tilde;": "˜",6740 "times;": "×",6741 "TRADE;": "™",6742 "trade;": "™",6743 "trisb;": "⧍",6744 "TSHcy;": "Ћ",6745 "tshcy;": "ћ",6746 "twixt;": "≬",6747 Uacute: "Ú",6748 uacute: "ú",6749 "Ubrcy;": "Ў",6750 "ubrcy;": "ў",6751 "Ucirc;": "Û",6752 "ucirc;": "û",6753 "udarr;": "⇅",6754 "udhar;": "⥮",6755 Ugrave: "Ù",6756 ugrave: "ù",6757 "uharl;": "↿",6758 "uharr;": "↾",6759 "uhblk;": "▀",6760 "ultri;": "◸",6761 "Umacr;": "Ū",6762 "umacr;": "ū",6763 "Union;": "⋃",6764 "Uogon;": "Ų",6765 "uogon;": "ų",6766 "uplus;": "⊎",6767 "upsih;": "ϒ",6768 "UpTee;": "⊥",6769 "Uring;": "Ů",6770 "uring;": "ů",6771 "urtri;": "◹",6772 "utdot;": "⋰",6773 "utrif;": "▴",6774 "uuarr;": "⇈",6775 "varpi;": "ϖ",6776 "vBarv;": "⫩",6777 "VDash;": "⊫",6778 "Vdash;": "⊩",6779 "vDash;": "⊨",6780 "vdash;": "⊢",6781 "veeeq;": "≚",6782 "vltri;": "⊲",6783 "vnsub;": "⊂⃒",6784 "vnsup;": "⊃⃒",6785 "vprop;": "∝",6786 "vrtri;": "⊳",6787 "Wcirc;": "Ŵ",6788 "wcirc;": "ŵ",6789 "Wedge;": "⋀",6790 "wedge;": "∧",6791 "xcirc;": "◯",6792 "xdtri;": "▽",6793 "xhArr;": "⟺",6794 "xharr;": "⟷",6795 "xlArr;": "⟸",6796 "xlarr;": "⟵",6797 "xodot;": "⨀",6798 "xrArr;": "⟹",6799 "xrarr;": "⟶",6800 "xutri;": "△",6801 Yacute: "Ý",6802 yacute: "ý",6803 "Ycirc;": "Ŷ",6804 "ycirc;": "ŷ",6805 "Aacute;": "Á",6806 "aacute;": "á",6807 "Abreve;": "Ă",6808 "abreve;": "ă",6809 "Agrave;": "À",6810 "agrave;": "à",6811 "andand;": "⩕",6812 "angmsd;": "∡",6813 "angsph;": "∢",6814 "apacir;": "⩯",6815 "approx;": "≈",6816 "Assign;": "≔",6817 "Atilde;": "Ã",6818 "atilde;": "ã",6819 "barvee;": "⊽",6820 "Barwed;": "⌆",6821 "barwed;": "⌅",6822 "becaus;": "∵",6823 "bernou;": "ℬ",6824 "bigcap;": "⋂",6825 "bigcup;": "⋃",6826 "bigvee;": "⋁",6827 "bkarow;": "⤍",6828 "bottom;": "⊥",6829 "bowtie;": "⋈",6830 "boxbox;": "⧉",6831 "bprime;": "‵",6832 "brvbar;": "¦",6833 "bullet;": "•",6834 "Bumpeq;": "≎",6835 "bumpeq;": "≏",6836 "Cacute;": "Ć",6837 "cacute;": "ć",6838 "capand;": "⩄",6839 "capcap;": "⩋",6840 "capcup;": "⩇",6841 "capdot;": "⩀",6842 "Ccaron;": "Č",6843 "ccaron;": "č",6844 "Ccedil;": "Ç",6845 "ccedil;": "ç",6846 "circeq;": "≗",6847 "cirmid;": "⫯",6848 "Colone;": "⩴",6849 "colone;": "≔",6850 "commat;": "@",6851 "compfn;": "∘",6852 "Conint;": "∯",6853 "conint;": "∮",6854 "coprod;": "∐",6855 "copysr;": "℗",6856 "cularr;": "↶",6857 "CupCap;": "≍",6858 "cupcap;": "⩆",6859 "cupcup;": "⩊",6860 "cupdot;": "⊍",6861 "curarr;": "↷",6862 "curren;": "¤",6863 "cylcty;": "⌭",6864 "Dagger;": "‡",6865 "dagger;": "†",6866 "daleth;": "ℸ",6867 "Dcaron;": "Ď",6868 "dcaron;": "ď",6869 "dfisht;": "⥿",6870 "divide;": "÷",6871 "divonx;": "⋇",6872 "dlcorn;": "⌞",6873 "dlcrop;": "⌍",6874 "dollar;": "$",6875 "DotDot;": "⃜",6876 "drcorn;": "⌟",6877 "drcrop;": "⌌",6878 "Dstrok;": "Đ",6879 "dstrok;": "đ",6880 "Eacute;": "É",6881 "eacute;": "é",6882 "easter;": "⩮",6883 "Ecaron;": "Ě",6884 "ecaron;": "ě",6885 "ecolon;": "≕",6886 "Egrave;": "È",6887 "egrave;": "è",6888 "egsdot;": "⪘",6889 "elsdot;": "⪗",6890 "emptyv;": "∅",6891 "emsp13;": " ",6892 "emsp14;": " ",6893 "eparsl;": "⧣",6894 "eqcirc;": "≖",6895 "equals;": "=",6896 "equest;": "≟",6897 "Exists;": "∃",6898 "female;": "♀",6899 "ffilig;": "ffi",6900 "ffllig;": "ffl",6901 "ForAll;": "∀",6902 "forall;": "∀",6903 "frac12;": "½",6904 "frac13;": "⅓",6905 "frac14;": "¼",6906 "frac15;": "⅕",6907 "frac16;": "⅙",6908 "frac18;": "⅛",6909 "frac23;": "⅔",6910 "frac25;": "⅖",6911 "frac34;": "¾",6912 "frac35;": "⅗",6913 "frac38;": "⅜",6914 "frac45;": "⅘",6915 "frac56;": "⅚",6916 "frac58;": "⅝",6917 "frac78;": "⅞",6918 "gacute;": "ǵ",6919 "Gammad;": "Ϝ",6920 "gammad;": "ϝ",6921 "Gbreve;": "Ğ",6922 "gbreve;": "ğ",6923 "Gcedil;": "Ģ",6924 "gesdot;": "⪀",6925 "gesles;": "⪔",6926 "gtlPar;": "⦕",6927 "gtrarr;": "⥸",6928 "gtrdot;": "⋗",6929 "gtrsim;": "≳",6930 "hairsp;": " ",6931 "hamilt;": "ℋ",6932 "HARDcy;": "Ъ",6933 "hardcy;": "ъ",6934 "hearts;": "♥",6935 "hellip;": "…",6936 "hercon;": "⊹",6937 "homtht;": "∻",6938 "horbar;": "―",6939 "hslash;": "ℏ",6940 "Hstrok;": "Ħ",6941 "hstrok;": "ħ",6942 "hybull;": "⁃",6943 "hyphen;": "‐",6944 "Iacute;": "Í",6945 "iacute;": "í",6946 "Igrave;": "Ì",6947 "igrave;": "ì",6948 "iiiint;": "⨌",6949 "iinfin;": "⧜",6950 "incare;": "℅",6951 "inodot;": "ı",6952 "intcal;": "⊺",6953 "iquest;": "¿",6954 "isinsv;": "⋳",6955 "Itilde;": "Ĩ",6956 "itilde;": "ĩ",6957 "Jsercy;": "Ј",6958 "jsercy;": "ј",6959 "kappav;": "ϰ",6960 "Kcedil;": "Ķ",6961 "kcedil;": "ķ",6962 "kgreen;": "ĸ",6963 "Lacute;": "Ĺ",6964 "lacute;": "ĺ",6965 "lagran;": "ℒ",6966 "Lambda;": "Λ",6967 "lambda;": "λ",6968 "langle;": "⟨",6969 "larrfs;": "⤝",6970 "larrhk;": "↩",6971 "larrlp;": "↫",6972 "larrpl;": "⤹",6973 "larrtl;": "↢",6974 "lAtail;": "⤛",6975 "latail;": "⤙",6976 "lbrace;": "{",6977 "lbrack;": "[",6978 "Lcaron;": "Ľ",6979 "lcaron;": "ľ",6980 "Lcedil;": "Ļ",6981 "lcedil;": "ļ",6982 "ldquor;": "„",6983 "lesdot;": "⩿",6984 "lesges;": "⪓",6985 "lfisht;": "⥼",6986 "lfloor;": "⌊",6987 "lharul;": "⥪",6988 "llhard;": "⥫",6989 "Lmidot;": "Ŀ",6990 "lmidot;": "ŀ",6991 "lmoust;": "⎰",6992 "loplus;": "⨭",6993 "lowast;": "∗",6994 "lowbar;": "_",6995 "lparlt;": "⦓",6996 "lrhard;": "⥭",6997 "lsaquo;": "‹",6998 "lsquor;": "‚",6999 "Lstrok;": "Ł",7000 "lstrok;": "ł",7001 "lthree;": "⋋",7002 "ltimes;": "⋉",7003 "ltlarr;": "⥶",7004 "ltrPar;": "⦖",7005 "mapsto;": "↦",7006 "marker;": "▮",7007 "mcomma;": "⨩",7008 "midast;": "*",7009 "midcir;": "⫰",7010 "middot;": "·",7011 "minusb;": "⊟",7012 "minusd;": "∸",7013 "mnplus;": "∓",7014 "models;": "⊧",7015 "mstpos;": "∾",7016 "Nacute;": "Ń",7017 "nacute;": "ń",7018 "nbumpe;": "≏̸",7019 "Ncaron;": "Ň",7020 "ncaron;": "ň",7021 "Ncedil;": "Ņ",7022 "ncedil;": "ņ",7023 "nearhk;": "⤤",7024 "nequiv;": "≢",7025 "nesear;": "⤨",7026 "nexist;": "∄",7027 "nltrie;": "⋬",7028 "notinE;": "⋹̸",7029 "nparsl;": "⫽⃥",7030 "nprcue;": "⋠",7031 "nrarrc;": "⤳̸",7032 "nrarrw;": "↝̸",7033 "nrtrie;": "⋭",7034 "nsccue;": "⋡",7035 "nsimeq;": "≄",7036 "Ntilde;": "Ñ",7037 "ntilde;": "ñ",7038 "numero;": "№",7039 "nVDash;": "⊯",7040 "nVdash;": "⊮",7041 "nvDash;": "⊭",7042 "nvdash;": "⊬",7043 "nvHarr;": "⤄",7044 "nvlArr;": "⤂",7045 "nvrArr;": "⤃",7046 "nwarhk;": "⤣",7047 "nwnear;": "⤧",7048 "Oacute;": "Ó",7049 "oacute;": "ó",7050 "Odblac;": "Ő",7051 "odblac;": "ő",7052 "odsold;": "⦼",7053 "Ograve;": "Ò",7054 "ograve;": "ò",7055 "ominus;": "⊖",7056 "origof;": "⊶",7057 "Oslash;": "Ø",7058 "oslash;": "ø",7059 "Otilde;": "Õ",7060 "otilde;": "õ",7061 "Otimes;": "⨷",7062 "otimes;": "⊗",7063 "parsim;": "⫳",7064 "percnt;": "%",7065 "period;": ".",7066 "permil;": "‰",7067 "phmmat;": "ℳ",7068 "planck;": "ℏ",7069 "plankv;": "ℏ",7070 "plusdo;": "∔",7071 "plusdu;": "⨥",7072 "plusmn;": "±",7073 "preceq;": "⪯",7074 "primes;": "ℙ",7075 "prnsim;": "⋨",7076 "propto;": "∝",7077 "prurel;": "⊰",7078 "puncsp;": " ",7079 "qprime;": "⁗",7080 "Racute;": "Ŕ",7081 "racute;": "ŕ",7082 "rangle;": "⟩",7083 "rarrap;": "⥵",7084 "rarrfs;": "⤞",7085 "rarrhk;": "↪",7086 "rarrlp;": "↬",7087 "rarrpl;": "⥅",7088 "Rarrtl;": "⤖",7089 "rarrtl;": "↣",7090 "rAtail;": "⤜",7091 "ratail;": "⤚",7092 "rbrace;": "}",7093 "rbrack;": "]",7094 "Rcaron;": "Ř",7095 "rcaron;": "ř",7096 "Rcedil;": "Ŗ",7097 "rcedil;": "ŗ",7098 "rdquor;": "”",7099 "rfisht;": "⥽",7100 "rfloor;": "⌋",7101 "rharul;": "⥬",7102 "rmoust;": "⎱",7103 "roplus;": "⨮",7104 "rpargt;": "⦔",7105 "rsaquo;": "›",7106 "rsquor;": "’",7107 "rthree;": "⋌",7108 "rtimes;": "⋊",7109 "Sacute;": "Ś",7110 "sacute;": "ś",7111 "Scaron;": "Š",7112 "scaron;": "š",7113 "Scedil;": "Ş",7114 "scedil;": "ş",7115 "scnsim;": "⋩",7116 "searhk;": "⤥",7117 "seswar;": "⤩",7118 "sfrown;": "⌢",7119 "SHCHcy;": "Щ",7120 "shchcy;": "щ",7121 "sigmaf;": "ς",7122 "sigmav;": "ς",7123 "simdot;": "⩪",7124 "smashp;": "⨳",7125 "SOFTcy;": "Ь",7126 "softcy;": "ь",7127 "solbar;": "⌿",7128 "spades;": "♠",7129 "sqcaps;": "⊓︀",7130 "sqcups;": "⊔︀",7131 "sqsube;": "⊑",7132 "sqsupe;": "⊒",7133 "Square;": "□",7134 "square;": "□",7135 "squarf;": "▪",7136 "ssetmn;": "∖",7137 "ssmile;": "⌣",7138 "sstarf;": "⋆",7139 "subdot;": "⪽",7140 "Subset;": "⋐",7141 "subset;": "⊂",7142 "subsim;": "⫇",7143 "subsub;": "⫕",7144 "subsup;": "⫓",7145 "succeq;": "⪰",7146 "supdot;": "⪾",7147 "Supset;": "⋑",7148 "supset;": "⊃",7149 "supsim;": "⫈",7150 "supsub;": "⫔",7151 "supsup;": "⫖",7152 "swarhk;": "⤦",7153 "swnwar;": "⤪",7154 "target;": "⌖",7155 "Tcaron;": "Ť",7156 "tcaron;": "ť",7157 "Tcedil;": "Ţ",7158 "tcedil;": "ţ",7159 "telrec;": "⌕",7160 "there4;": "∴",7161 "thetav;": "ϑ",7162 "thinsp;": " ",7163 "thksim;": "∼",7164 "timesb;": "⊠",7165 "timesd;": "⨰",7166 "topbot;": "⌶",7167 "topcir;": "⫱",7168 "tprime;": "‴",7169 "tridot;": "◬",7170 "Tstrok;": "Ŧ",7171 "tstrok;": "ŧ",7172 "Uacute;": "Ú",7173 "uacute;": "ú",7174 "Ubreve;": "Ŭ",7175 "ubreve;": "ŭ",7176 "Udblac;": "Ű",7177 "udblac;": "ű",7178 "ufisht;": "⥾",7179 "Ugrave;": "Ù",7180 "ugrave;": "ù",7181 "ulcorn;": "⌜",7182 "ulcrop;": "⌏",7183 "urcorn;": "⌝",7184 "urcrop;": "⌎",7185 "Utilde;": "Ũ",7186 "utilde;": "ũ",7187 "vangrt;": "⦜",7188 "varphi;": "ϕ",7189 "varrho;": "ϱ",7190 "Vdashl;": "⫦",7191 "veebar;": "⊻",7192 "vellip;": "⋮",7193 "Verbar;": "‖",7194 "verbar;": "|",7195 "vsubnE;": "⫋︀",7196 "vsubne;": "⊊︀",7197 "vsupnE;": "⫌︀",7198 "vsupne;": "⊋︀",7199 "Vvdash;": "⊪",7200 "wedbar;": "⩟",7201 "wedgeq;": "≙",7202 "weierp;": "℘",7203 "wreath;": "≀",7204 "xoplus;": "⨁",7205 "xotime;": "⨂",7206 "xsqcup;": "⨆",7207 "xuplus;": "⨄",7208 "xwedge;": "⋀",7209 "Yacute;": "Ý",7210 "yacute;": "ý",7211 "Zacute;": "Ź",7212 "zacute;": "ź",7213 "Zcaron;": "Ž",7214 "zcaron;": "ž",7215 "zeetrf;": "ℨ",7216 "alefsym;": "ℵ",7217 "angrtvb;": "⊾",7218 "angzarr;": "⍼",7219 "asympeq;": "≍",7220 "backsim;": "∽",7221 "Because;": "∵",7222 "because;": "∵",7223 "bemptyv;": "⦰",7224 "between;": "≬",7225 "bigcirc;": "◯",7226 "bigodot;": "⨀",7227 "bigstar;": "★",7228 "bnequiv;": "≡⃥",7229 "boxplus;": "⊞",7230 "Cayleys;": "ℭ",7231 "Cconint;": "∰",7232 "ccupssm;": "⩐",7233 "Cedilla;": "¸",7234 "cemptyv;": "⦲",7235 "cirscir;": "⧂",7236 "coloneq;": "≔",7237 "congdot;": "⩭",7238 "cudarrl;": "⤸",7239 "cudarrr;": "⤵",7240 "cularrp;": "⤽",7241 "curarrm;": "⤼",7242 "dbkarow;": "⤏",7243 "ddagger;": "‡",7244 "ddotseq;": "⩷",7245 "demptyv;": "⦱",7246 "Diamond;": "⋄",7247 "diamond;": "⋄",7248 "digamma;": "ϝ",7249 "dotplus;": "∔",7250 "DownTee;": "⊤",7251 "dwangle;": "⦦",7252 "Element;": "∈",7253 "Epsilon;": "Ε",7254 "epsilon;": "ε",7255 "eqcolon;": "≕",7256 "equivDD;": "⩸",7257 "gesdoto;": "⪂",7258 "gtquest;": "⩼",7259 "gtrless;": "≷",7260 "harrcir;": "⥈",7261 "Implies;": "⇒",7262 "intprod;": "⨼",7263 "isindot;": "⋵",7264 "larrbfs;": "⤟",7265 "larrsim;": "⥳",7266 "lbrksld;": "⦏",7267 "lbrkslu;": "⦍",7268 "ldrdhar;": "⥧",7269 "LeftTee;": "⊣",7270 "lesdoto;": "⪁",7271 "lessdot;": "⋖",7272 "lessgtr;": "≶",7273 "lesssim;": "≲",7274 "lotimes;": "⨴",7275 "lozenge;": "◊",7276 "ltquest;": "⩻",7277 "luruhar;": "⥦",7278 "maltese;": "✠",7279 "minusdu;": "⨪",7280 "napprox;": "≉",7281 "natural;": "♮",7282 "nearrow;": "↗",7283 "NewLine;": "\n",7284 "nexists;": "∄",7285 "NoBreak;": "⁠",7286 "notinva;": "∉",7287 "notinvb;": "⋷",7288 "notinvc;": "⋶",7289 "NotLess;": "≮",7290 "notniva;": "∌",7291 "notnivb;": "⋾",7292 "notnivc;": "⋽",7293 "npolint;": "⨔",7294 "npreceq;": "⪯̸",7295 "nsqsube;": "⋢",7296 "nsqsupe;": "⋣",7297 "nsubset;": "⊂⃒",7298 "nsucceq;": "⪰̸",7299 "nsupset;": "⊃⃒",7300 "nvinfin;": "⧞",7301 "nvltrie;": "⊴⃒",7302 "nvrtrie;": "⊵⃒",7303 "nwarrow;": "↖",7304 "olcross;": "⦻",7305 "Omicron;": "Ο",7306 "omicron;": "ο",7307 "orderof;": "ℴ",7308 "orslope;": "⩗",7309 "OverBar;": "‾",7310 "pertenk;": "‱",7311 "planckh;": "ℎ",7312 "pluscir;": "⨢",7313 "plussim;": "⨦",7314 "plustwo;": "⨧",7315 "precsim;": "≾",7316 "Product;": "∏",7317 "quatint;": "⨖",7318 "questeq;": "≟",7319 "rarrbfs;": "⤠",7320 "rarrsim;": "⥴",7321 "rbrksld;": "⦎",7322 "rbrkslu;": "⦐",7323 "rdldhar;": "⥩",7324 "realine;": "ℛ",7325 "rotimes;": "⨵",7326 "ruluhar;": "⥨",7327 "searrow;": "↘",7328 "simplus;": "⨤",7329 "simrarr;": "⥲",7330 "subedot;": "⫃",7331 "submult;": "⫁",7332 "subplus;": "⪿",7333 "subrarr;": "⥹",7334 "succsim;": "≿",7335 "supdsub;": "⫘",7336 "supedot;": "⫄",7337 "suphsol;": "⟉",7338 "suphsub;": "⫗",7339 "suplarr;": "⥻",7340 "supmult;": "⫂",7341 "supplus;": "⫀",7342 "swarrow;": "↙",7343 "topfork;": "⫚",7344 "triplus;": "⨹",7345 "tritime;": "⨻",7346 "UpArrow;": "↑",7347 "Uparrow;": "⇑",7348 "uparrow;": "↑",7349 "Upsilon;": "Υ",7350 "upsilon;": "υ",7351 "uwangle;": "⦧",7352 "vzigzag;": "⦚",7353 "zigrarr;": "⇝",7354 "andslope;": "⩘",7355 "angmsdaa;": "⦨",7356 "angmsdab;": "⦩",7357 "angmsdac;": "⦪",7358 "angmsdad;": "⦫",7359 "angmsdae;": "⦬",7360 "angmsdaf;": "⦭",7361 "angmsdag;": "⦮",7362 "angmsdah;": "⦯",7363 "angrtvbd;": "⦝",7364 "approxeq;": "≊",7365 "awconint;": "∳",7366 "backcong;": "≌",7367 "barwedge;": "⌅",7368 "bbrktbrk;": "⎶",7369 "bigoplus;": "⨁",7370 "bigsqcup;": "⨆",7371 "biguplus;": "⨄",7372 "bigwedge;": "⋀",7373 "boxminus;": "⊟",7374 "boxtimes;": "⊠",7375 "bsolhsub;": "⟈",7376 "capbrcup;": "⩉",7377 "circledR;": "®",7378 "circledS;": "Ⓢ",7379 "cirfnint;": "⨐",7380 "clubsuit;": "♣",7381 "cupbrcap;": "⩈",7382 "curlyvee;": "⋎",7383 "cwconint;": "∲",7384 "DDotrahd;": "⤑",7385 "doteqdot;": "≑",7386 "DotEqual;": "≐",7387 "dotminus;": "∸",7388 "drbkarow;": "⤐",7389 "dzigrarr;": "⟿",7390 "elinters;": "⏧",7391 "emptyset;": "∅",7392 "eqvparsl;": "⧥",7393 "fpartint;": "⨍",7394 "geqslant;": "⩾",7395 "gesdotol;": "⪄",7396 "gnapprox;": "⪊",7397 "hksearow;": "⤥",7398 "hkswarow;": "⤦",7399 "imagline;": "ℐ",7400 "imagpart;": "ℑ",7401 "infintie;": "⧝",7402 "integers;": "ℤ",7403 "Integral;": "∫",7404 "intercal;": "⊺",7405 "intlarhk;": "⨗",7406 "laemptyv;": "⦴",7407 "ldrushar;": "⥋",7408 "leqslant;": "⩽",7409 "lesdotor;": "⪃",7410 "LessLess;": "⪡",7411 "llcorner;": "⌞",7412 "lnapprox;": "⪉",7413 "lrcorner;": "⌟",7414 "lurdshar;": "⥊",7415 "mapstoup;": "↥",7416 "multimap;": "⊸",7417 "naturals;": "ℕ",7418 "ncongdot;": "⩭̸",7419 "NotEqual;": "≠",7420 "notindot;": "⋵̸",7421 "NotTilde;": "≁",7422 "otimesas;": "⨶",7423 "parallel;": "∥",7424 "PartialD;": "∂",7425 "plusacir;": "⨣",7426 "pointint;": "⨕",7427 "Precedes;": "≺",7428 "precneqq;": "⪵",7429 "precnsim;": "⋨",7430 "profalar;": "⌮",7431 "profline;": "⌒",7432 "profsurf;": "⌓",7433 "raemptyv;": "⦳",7434 "realpart;": "ℜ",7435 "RightTee;": "⊢",7436 "rppolint;": "⨒",7437 "rtriltri;": "⧎",7438 "scpolint;": "⨓",7439 "setminus;": "∖",7440 "shortmid;": "∣",7441 "smeparsl;": "⧤",7442 "sqsubset;": "⊏",7443 "sqsupset;": "⊐",7444 "subseteq;": "⊆",7445 "Succeeds;": "≻",7446 "succneqq;": "⪶",7447 "succnsim;": "⋩",7448 "SuchThat;": "∋",7449 "Superset;": "⊃",7450 "supseteq;": "⊇",7451 "thetasym;": "ϑ",7452 "thicksim;": "∼",7453 "timesbar;": "⨱",7454 "triangle;": "▵",7455 "triminus;": "⨺",7456 "trpezium;": "⏢",7457 "Uarrocir;": "⥉",7458 "ulcorner;": "⌜",7459 "UnderBar;": "_",7460 "urcorner;": "⌝",7461 "varkappa;": "ϰ",7462 "varsigma;": "ς",7463 "vartheta;": "ϑ",7464 "backprime;": "‵",7465 "backsimeq;": "⋍",7466 "Backslash;": "∖",7467 "bigotimes;": "⨂",7468 "CenterDot;": "·",7469 "centerdot;": "·",7470 "checkmark;": "✓",7471 "CircleDot;": "⊙",7472 "complexes;": "ℂ",7473 "Congruent;": "≡",7474 "Coproduct;": "∐",7475 "dotsquare;": "⊡",7476 "DoubleDot;": "¨",7477 "DownArrow;": "↓",7478 "Downarrow;": "⇓",7479 "downarrow;": "↓",7480 "DownBreve;": "̑",7481 "gtrapprox;": "⪆",7482 "gtreqless;": "⋛",7483 "gvertneqq;": "≩︀",7484 "heartsuit;": "♥",7485 "HumpEqual;": "≏",7486 "LeftArrow;": "←",7487 "Leftarrow;": "⇐",7488 "leftarrow;": "←",7489 "LeftFloor;": "⌊",7490 "lesseqgtr;": "⋚",7491 "LessTilde;": "≲",7492 "lvertneqq;": "≨︀",7493 "Mellintrf;": "ℳ",7494 "MinusPlus;": "∓",7495 "ngeqslant;": "⩾̸",7496 "nleqslant;": "⩽̸",7497 "NotCupCap;": "≭",7498 "NotExists;": "∄",7499 "NotSubset;": "⊂⃒",7500 "nparallel;": "∦",7501 "nshortmid;": "∤",7502 "nsubseteq;": "⊈",7503 "nsupseteq;": "⊉",7504 "OverBrace;": "⏞",7505 "pitchfork;": "⋔",7506 "PlusMinus;": "±",7507 "rationals;": "ℚ",7508 "spadesuit;": "♠",7509 "subseteqq;": "⫅",7510 "subsetneq;": "⊊",7511 "supseteqq;": "⫆",7512 "supsetneq;": "⊋",7513 "Therefore;": "∴",7514 "therefore;": "∴",7515 "ThinSpace;": " ",7516 "triangleq;": "≜",7517 "TripleDot;": "⃛",7518 "UnionPlus;": "⊎",7519 "varpropto;": "∝",7520 "Bernoullis;": "ℬ",7521 "circledast;": "⊛",7522 "CirclePlus;": "⊕",7523 "complement;": "∁",7524 "curlywedge;": "⋏",7525 "eqslantgtr;": "⪖",7526 "EqualTilde;": "≂",7527 "Fouriertrf;": "ℱ",7528 "gtreqqless;": "⪌",7529 "ImaginaryI;": "ⅈ",7530 "Laplacetrf;": "ℒ",7531 "LeftVector;": "↼",7532 "lessapprox;": "⪅",7533 "lesseqqgtr;": "⪋",7534 "Lleftarrow;": "⇚",7535 "lmoustache;": "⎰",7536 "longmapsto;": "⟼",7537 "mapstodown;": "↧",7538 "mapstoleft;": "↤",7539 "nLeftarrow;": "⇍",7540 "nleftarrow;": "↚",7541 "NotElement;": "∉",7542 "NotGreater;": "≯",7543 "nsubseteqq;": "⫅̸",7544 "nsupseteqq;": "⫆̸",7545 "precapprox;": "⪷",7546 "Proportion;": "∷",7547 "RightArrow;": "→",7548 "Rightarrow;": "⇒",7549 "rightarrow;": "→",7550 "RightFloor;": "⌋",7551 "rmoustache;": "⎱",7552 "sqsubseteq;": "⊑",7553 "sqsupseteq;": "⊒",7554 "subsetneqq;": "⫋",7555 "succapprox;": "⪸",7556 "supsetneqq;": "⫌",7557 "ThickSpace;": "  ",7558 "TildeEqual;": "≃",7559 "TildeTilde;": "≈",7560 "UnderBrace;": "⏟",7561 "UpArrowBar;": "⤒",7562 "UpTeeArrow;": "↥",7563 "upuparrows;": "⇈",7564 "varepsilon;": "ϵ",7565 "varnothing;": "∅",7566 "backepsilon;": "϶",7567 "blacksquare;": "▪",7568 "circledcirc;": "⊚",7569 "circleddash;": "⊝",7570 "CircleMinus;": "⊖",7571 "CircleTimes;": "⊗",7572 "curlyeqprec;": "⋞",7573 "curlyeqsucc;": "⋟",7574 "diamondsuit;": "♦",7575 "eqslantless;": "⪕",7576 "Equilibrium;": "⇌",7577 "expectation;": "ℰ",7578 "GreaterLess;": "≷",7579 "LeftCeiling;": "⌈",7580 "LessGreater;": "≶",7581 "MediumSpace;": " ",7582 "NotLessLess;": "≪̸",7583 "NotPrecedes;": "⊀",7584 "NotSucceeds;": "⊁",7585 "NotSuperset;": "⊃⃒",7586 "nRightarrow;": "⇏",7587 "nrightarrow;": "↛",7588 "OverBracket;": "⎴",7589 "preccurlyeq;": "≼",7590 "precnapprox;": "⪹",7591 "quaternions;": "ℍ",7592 "RightVector;": "⇀",7593 "Rrightarrow;": "⇛",7594 "RuleDelayed;": "⧴",7595 "SmallCircle;": "∘",7596 "SquareUnion;": "⊔",7597 "straightphi;": "ϕ",7598 "SubsetEqual;": "⊆",7599 "succcurlyeq;": "≽",7600 "succnapprox;": "⪺",7601 "thickapprox;": "≈",7602 "UpDownArrow;": "↕",7603 "Updownarrow;": "⇕",7604 "updownarrow;": "↕",7605 "VerticalBar;": "∣",7606 "blacklozenge;": "⧫",7607 "DownArrowBar;": "⤓",7608 "DownTeeArrow;": "↧",7609 "ExponentialE;": "ⅇ",7610 "exponentiale;": "ⅇ",7611 "GreaterEqual;": "≥",7612 "GreaterTilde;": "≳",7613 "HilbertSpace;": "ℋ",7614 "HumpDownHump;": "≎",7615 "Intersection;": "⋂",7616 "LeftArrowBar;": "⇤",7617 "LeftTeeArrow;": "↤",7618 "LeftTriangle;": "⊲",7619 "LeftUpVector;": "↿",7620 "NotCongruent;": "≢",7621 "NotHumpEqual;": "≏̸",7622 "NotLessEqual;": "≰",7623 "NotLessTilde;": "≴",7624 "Proportional;": "∝",7625 "RightCeiling;": "⌉",7626 "risingdotseq;": "≓",7627 "RoundImplies;": "⥰",7628 "ShortUpArrow;": "↑",7629 "SquareSubset;": "⊏",7630 "triangledown;": "▿",7631 "triangleleft;": "◃",7632 "UnderBracket;": "⎵",7633 "varsubsetneq;": "⊊︀",7634 "varsupsetneq;": "⊋︀",7635 "VerticalLine;": "|",7636 "ApplyFunction;": "⁡",7637 "bigtriangleup;": "△",7638 "blacktriangle;": "▴",7639 "DifferentialD;": "ⅆ",7640 "divideontimes;": "⋇",7641 "DoubleLeftTee;": "⫤",7642 "DoubleUpArrow;": "⇑",7643 "fallingdotseq;": "≒",7644 "hookleftarrow;": "↩",7645 "leftarrowtail;": "↢",7646 "leftharpoonup;": "↼",7647 "LeftTeeVector;": "⥚",7648 "LeftVectorBar;": "⥒",7649 "LessFullEqual;": "≦",7650 "LongLeftArrow;": "⟵",7651 "Longleftarrow;": "⟸",7652 "longleftarrow;": "⟵",7653 "looparrowleft;": "↫",7654 "measuredangle;": "∡",7655 "NotEqualTilde;": "≂̸",7656 "NotTildeEqual;": "≄",7657 "NotTildeTilde;": "≉",7658 "ntriangleleft;": "⋪",7659 "Poincareplane;": "ℌ",7660 "PrecedesEqual;": "⪯",7661 "PrecedesTilde;": "≾",7662 "RightArrowBar;": "⇥",7663 "RightTeeArrow;": "↦",7664 "RightTriangle;": "⊳",7665 "RightUpVector;": "↾",7666 "shortparallel;": "∥",7667 "smallsetminus;": "∖",7668 "SucceedsEqual;": "⪰",7669 "SucceedsTilde;": "≿",7670 "SupersetEqual;": "⊇",7671 "triangleright;": "▹",7672 "UpEquilibrium;": "⥮",7673 "upharpoonleft;": "↿",7674 "varsubsetneqq;": "⫋︀",7675 "varsupsetneqq;": "⫌︀",7676 "VerticalTilde;": "≀",7677 "VeryThinSpace;": " ",7678 "curvearrowleft;": "↶",7679 "DiacriticalDot;": "˙",7680 "doublebarwedge;": "⌆",7681 "DoubleRightTee;": "⊨",7682 "downdownarrows;": "⇊",7683 "DownLeftVector;": "↽",7684 "GreaterGreater;": "⪢",7685 "hookrightarrow;": "↪",7686 "HorizontalLine;": "─",7687 "InvisibleComma;": "⁣",7688 "InvisibleTimes;": "⁢",7689 "LeftDownVector;": "⇃",7690 "leftleftarrows;": "⇇",7691 "LeftRightArrow;": "↔",7692 "Leftrightarrow;": "⇔",7693 "leftrightarrow;": "↔",7694 "leftthreetimes;": "⋋",7695 "LessSlantEqual;": "⩽",7696 "LongRightArrow;": "⟶",7697 "Longrightarrow;": "⟹",7698 "longrightarrow;": "⟶",7699 "looparrowright;": "↬",7700 "LowerLeftArrow;": "↙",7701 "NestedLessLess;": "≪",7702 "NotGreaterLess;": "≹",7703 "NotLessGreater;": "≸",7704 "NotSubsetEqual;": "⊈",7705 "NotVerticalBar;": "∤",7706 "nshortparallel;": "∦",7707 "ntriangleright;": "⋫",7708 "OpenCurlyQuote;": "‘",7709 "ReverseElement;": "∋",7710 "rightarrowtail;": "↣",7711 "rightharpoonup;": "⇀",7712 "RightTeeVector;": "⥛",7713 "RightVectorBar;": "⥓",7714 "ShortDownArrow;": "↓",7715 "ShortLeftArrow;": "←",7716 "SquareSuperset;": "⊐",7717 "TildeFullEqual;": "≅",7718 "trianglelefteq;": "⊴",7719 "upharpoonright;": "↾",7720 "UpperLeftArrow;": "↖",7721 "ZeroWidthSpace;": "​",7722 "bigtriangledown;": "▽",7723 "circlearrowleft;": "↺",7724 "CloseCurlyQuote;": "’",7725 "ContourIntegral;": "∮",7726 "curvearrowright;": "↷",7727 "DoubleDownArrow;": "⇓",7728 "DoubleLeftArrow;": "⇐",7729 "downharpoonleft;": "⇃",7730 "DownRightVector;": "⇁",7731 "leftharpoondown;": "↽",7732 "leftrightarrows;": "⇆",7733 "LeftRightVector;": "⥎",7734 "LeftTriangleBar;": "⧏",7735 "LeftUpTeeVector;": "⥠",7736 "LeftUpVectorBar;": "⥘",7737 "LowerRightArrow;": "↘",7738 "nLeftrightarrow;": "⇎",7739 "nleftrightarrow;": "↮",7740 "NotGreaterEqual;": "≱",7741 "NotGreaterTilde;": "≵",7742 "NotHumpDownHump;": "≎̸",7743 "NotLeftTriangle;": "⋪",7744 "NotSquareSubset;": "⊏̸",7745 "ntrianglelefteq;": "⋬",7746 "OverParenthesis;": "⏜",7747 "RightDownVector;": "⇂",7748 "rightleftarrows;": "⇄",7749 "rightsquigarrow;": "↝",7750 "rightthreetimes;": "⋌",7751 "ShortRightArrow;": "→",7752 "straightepsilon;": "ϵ",7753 "trianglerighteq;": "⊵",7754 "UpperRightArrow;": "↗",7755 "vartriangleleft;": "⊲",7756 "circlearrowright;": "↻",7757 "DiacriticalAcute;": "´",7758 "DiacriticalGrave;": "`",7759 "DiacriticalTilde;": "˜",7760 "DoubleRightArrow;": "⇒",7761 "DownArrowUpArrow;": "⇵",7762 "downharpoonright;": "⇂",7763 "EmptySmallSquare;": "◻",7764 "GreaterEqualLess;": "⋛",7765 "GreaterFullEqual;": "≧",7766 "LeftAngleBracket;": "⟨",7767 "LeftUpDownVector;": "⥑",7768 "LessEqualGreater;": "⋚",7769 "NonBreakingSpace;": " ",7770 "NotPrecedesEqual;": "⪯̸",7771 "NotRightTriangle;": "⋫",7772 "NotSucceedsEqual;": "⪰̸",7773 "NotSucceedsTilde;": "≿̸",7774 "NotSupersetEqual;": "⊉",7775 "ntrianglerighteq;": "⋭",7776 "rightharpoondown;": "⇁",7777 "rightrightarrows;": "⇉",7778 "RightTriangleBar;": "⧐",7779 "RightUpTeeVector;": "⥜",7780 "RightUpVectorBar;": "⥔",7781 "twoheadleftarrow;": "↞",7782 "UnderParenthesis;": "⏝",7783 "UpArrowDownArrow;": "⇅",7784 "vartriangleright;": "⊳",7785 "blacktriangledown;": "▾",7786 "blacktriangleleft;": "◂",7787 "DoubleUpDownArrow;": "⇕",7788 "DoubleVerticalBar;": "∥",7789 "DownLeftTeeVector;": "⥞",7790 "DownLeftVectorBar;": "⥖",7791 "FilledSmallSquare;": "◼",7792 "GreaterSlantEqual;": "⩾",7793 "LeftDoubleBracket;": "⟦",7794 "LeftDownTeeVector;": "⥡",7795 "LeftDownVectorBar;": "⥙",7796 "leftrightharpoons;": "⇋",7797 "LeftTriangleEqual;": "⊴",7798 "NegativeThinSpace;": "​",7799 "NotGreaterGreater;": "≫̸",7800 "NotLessSlantEqual;": "⩽̸",7801 "NotNestedLessLess;": "⪡̸",7802 "NotReverseElement;": "∌",7803 "NotSquareSuperset;": "⊐̸",7804 "NotTildeFullEqual;": "≇",7805 "RightAngleBracket;": "⟩",7806 "rightleftharpoons;": "⇌",7807 "RightUpDownVector;": "⥏",7808 "SquareSubsetEqual;": "⊑",7809 "twoheadrightarrow;": "↠",7810 "VerticalSeparator;": "❘",7811 "blacktriangleright;": "▸",7812 "DownRightTeeVector;": "⥟",7813 "DownRightVectorBar;": "⥗",7814 "LongLeftRightArrow;": "⟷",7815 "Longleftrightarrow;": "⟺",7816 "longleftrightarrow;": "⟷",7817 "NegativeThickSpace;": "​",7818 "NotLeftTriangleBar;": "⧏̸",7819 "PrecedesSlantEqual;": "≼",7820 "ReverseEquilibrium;": "⇋",7821 "RightDoubleBracket;": "⟧",7822 "RightDownTeeVector;": "⥝",7823 "RightDownVectorBar;": "⥕",7824 "RightTriangleEqual;": "⊵",7825 "SquareIntersection;": "⊓",7826 "SucceedsSlantEqual;": "≽",7827 "DoubleLongLeftArrow;": "⟸",7828 "DownLeftRightVector;": "⥐",7829 "LeftArrowRightArrow;": "⇆",7830 "leftrightsquigarrow;": "↭",7831 "NegativeMediumSpace;": "​",7832 "NotGreaterFullEqual;": "≧̸",7833 "NotRightTriangleBar;": "⧐̸",7834 "RightArrowLeftArrow;": "⇄",7835 "SquareSupersetEqual;": "⊒",7836 "CapitalDifferentialD;": "ⅅ",7837 "DoubleLeftRightArrow;": "⇔",7838 "DoubleLongRightArrow;": "⟹",7839 "EmptyVerySmallSquare;": "▫",7840 "NestedGreaterGreater;": "≫",7841 "NotDoubleVerticalBar;": "∦",7842 "NotGreaterSlantEqual;": "⩾̸",7843 "NotLeftTriangleEqual;": "⋬",7844 "NotSquareSubsetEqual;": "⋢",7845 "OpenCurlyDoubleQuote;": "“",7846 "ReverseUpEquilibrium;": "⥯",7847 "CloseCurlyDoubleQuote;": "”",7848 "DoubleContourIntegral;": "∯",7849 "FilledVerySmallSquare;": "▪",7850 "NegativeVeryThinSpace;": "​",7851 "NotPrecedesSlantEqual;": "⋠",7852 "NotRightTriangleEqual;": "⋭",7853 "NotSucceedsSlantEqual;": "⋡",7854 "DiacriticalDoubleAcute;": "˝",7855 "NotSquareSupersetEqual;": "⋣",7856 "NotNestedGreaterGreater;": "⪢̸",7857 "ClockwiseContourIntegral;": "∲",7858 "DoubleLongLeftRightArrow;": "⟺",7859 "CounterClockwiseContourIntegral;": "∳"7860};7861// lazy compute this to make this file tree-shakable for browser7862let maxCRNameLength;7863const decodeHtml = (rawText, asAttr) => {7864 let offset = 0;7865 const end = rawText.length;7866 let decodedText = '';7867 function advance(length) {7868 offset += length;7869 rawText = rawText.slice(length);7870 }7871 while (offset < end) {7872 const head = /&(?:#x?)?/i.exec(rawText);7873 if (!head || offset + head.index >= end) {7874 const remaining = end - offset;7875 decodedText += rawText.slice(0, remaining);7876 advance(remaining);7877 break;7878 }7879 // Advance to the "&".7880 decodedText += rawText.slice(0, head.index);7881 advance(head.index);7882 if (head[0] === '&') {7883 // Named character reference.7884 let name = '';7885 let value = undefined;7886 if (/[0-9a-z]/i.test(rawText[1])) {7887 if (!maxCRNameLength) {7888 maxCRNameLength = Object.keys(namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0);7889 }7890 for (let length = maxCRNameLength; !value && length > 0; --length) {7891 name = rawText.slice(1, 1 + length);7892 value = namedCharacterReferences[name];7893 }7894 if (value) {7895 const semi = name.endsWith(';');7896 if (asAttr &&7897 !semi &&7898 /[=a-z0-9]/i.test(rawText[name.length + 1] || '')) {7899 decodedText += '&' + name;7900 advance(1 + name.length);7901 }7902 else {7903 decodedText += value;7904 advance(1 + name.length);7905 }7906 }7907 else {7908 decodedText += '&' + name;7909 advance(1 + name.length);7910 }7911 }7912 else {7913 decodedText += '&';7914 advance(1);7915 }7916 }7917 else {7918 // Numeric character reference.7919 const hex = head[0] === '&#x';7920 const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;7921 const body = pattern.exec(rawText);7922 if (!body) {7923 decodedText += head[0];7924 advance(head[0].length);7925 }7926 else {7927 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state7928 let cp = Number.parseInt(body[1], hex ? 16 : 10);7929 if (cp === 0) {7930 cp = 0xfffd;7931 }7932 else if (cp > 0x10ffff) {7933 cp = 0xfffd;7934 }7935 else if (cp >= 0xd800 && cp <= 0xdfff) {7936 cp = 0xfffd;7937 }7938 else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) ;7939 else if ((cp >= 0x01 && cp <= 0x08) ||7940 cp === 0x0b ||7941 (cp >= 0x0d && cp <= 0x1f) ||7942 (cp >= 0x7f && cp <= 0x9f)) {7943 cp = CCR_REPLACEMENTS[cp] || cp;7944 }7945 decodedText += String.fromCodePoint(cp);7946 advance(body[0].length);7947 }7948 }7949 }7950 return decodedText;7951};7952// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state7953const CCR_REPLACEMENTS = {7954 0x80: 0x20ac,7955 0x82: 0x201a,7956 0x83: 0x0192,7957 0x84: 0x201e,7958 0x85: 0x2026,7959 0x86: 0x2020,7960 0x87: 0x2021,7961 0x88: 0x02c6,7962 0x89: 0x2030,7963 0x8a: 0x0160,7964 0x8b: 0x2039,7965 0x8c: 0x0152,7966 0x8e: 0x017d,7967 0x91: 0x2018,7968 0x92: 0x2019,7969 0x93: 0x201c,7970 0x94: 0x201d,7971 0x95: 0x2022,7972 0x96: 0x2013,7973 0x97: 0x2014,7974 0x98: 0x02dc,7975 0x99: 0x2122,7976 0x9a: 0x0161,7977 0x9b: 0x203a,7978 0x9c: 0x0153,7979 0x9e: 0x017e,7980 0x9f: 0x01787981};7982const isRawTextContainer = /*#__PURE__*/ shared.makeMap('style,iframe,script,noscript', true);7983const parserOptions = {7984 isVoidTag: shared.isVoidTag,7985 isNativeTag: tag => shared.isHTMLTag(tag) || shared.isSVGTag(tag),7986 isPreTag: tag => tag === 'pre',7987 decodeEntities: decodeHtml,7988 isBuiltInComponent: (tag) => {7989 if (compilerCore.isBuiltInType(tag, `Transition`)) {7990 return TRANSITION;7991 }7992 else if (compilerCore.isBuiltInType(tag, `TransitionGroup`)) {7993 return TRANSITION_GROUP;7994 }7995 },7996 // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher7997 getNamespace(tag, parent) {7998 let ns = parent ? parent.ns : 0 /* HTML */;7999 if (parent && ns === 2 /* MATH_ML */) {8000 if (parent.tag === 'annotation-xml') {8001 if (tag === 'svg') {8002 return 1 /* SVG */;8003 }8004 if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ &&8005 a.name === 'encoding' &&8006 a.value != null &&8007 (a.value.content === 'text/html' ||8008 a.value.content === 'application/xhtml+xml'))) {8009 ns = 0 /* HTML */;8010 }8011 }8012 else if (/^m(?:[ions]|text)$/.test(parent.tag) &&8013 tag !== 'mglyph' &&8014 tag !== 'malignmark') {8015 ns = 0 /* HTML */;8016 }8017 }8018 else if (parent && ns === 1 /* SVG */) {8019 if (parent.tag === 'foreignObject' ||8020 parent.tag === 'desc' ||8021 parent.tag === 'title') {8022 ns = 0 /* HTML */;8023 }8024 }8025 if (ns === 0 /* HTML */) {8026 if (tag === 'svg') {8027 return 1 /* SVG */;8028 }8029 if (tag === 'math') {8030 return 2 /* MATH_ML */;8031 }8032 }8033 return ns;8034 },8035 // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments8036 getTextMode({ tag, ns }) {8037 if (ns === 0 /* HTML */) {8038 if (tag === 'textarea' || tag === 'title') {8039 return 1 /* RCDATA */;8040 }8041 if (isRawTextContainer(tag)) {8042 return 2 /* RAWTEXT */;8043 }8044 }8045 return 0 /* DATA */;8046 }8047};8048// Parse inline CSS strings for static style attributes into an object.8049// This is a NodeTransform since it works on the static `style` attribute and8050// converts it into a dynamic equivalent:8051// style="color: red" -> :style='{ "color": "red" }'8052// It is then processed by `transformElement` and included in the generated8053// props.8054const transformStyle = node => {8055 if (node.type === 1 /* ELEMENT */) {8056 node.props.forEach((p, i) => {8057 if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) {8058 // replace p with an expression node8059 node.props[i] = {8060 type: 7 /* DIRECTIVE */,8061 name: `bind`,8062 arg: compilerCore.createSimpleExpression(`style`, true, p.loc),8063 exp: parseInlineCSS(p.value.content, p.loc),8064 modifiers: [],8065 loc: p.loc8066 };8067 }8068 });8069 }8070};8071const parseInlineCSS = (cssText, loc) => {8072 const normalized = shared.parseStringStyle(cssText);8073 return compilerCore.createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* CAN_STRINGIFY */);8074};8075function createDOMCompilerError(code, loc) {8076 return compilerCore.createCompilerError(code, loc, DOMErrorMessages );8077}8078const DOMErrorMessages = {8079 [50 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,8080 [51 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,8081 [52 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,8082 [53 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,8083 [54 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,8084 [55 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,8085 [56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,8086 [57 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,8087 [58 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,8088 [59 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`,8089 [60 /* X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`8090};8091const transformVHtml = (dir, node, context) => {8092 const { exp, loc } = dir;8093 if (!exp) {8094 context.onError(createDOMCompilerError(50 /* X_V_HTML_NO_EXPRESSION */, loc));8095 }8096 if (node.children.length) {8097 context.onError(createDOMCompilerError(51 /* X_V_HTML_WITH_CHILDREN */, loc));8098 node.children.length = 0;8099 }8100 return {8101 props: [8102 compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`innerHTML`, true, loc), exp || compilerCore.createSimpleExpression('', true))8103 ]8104 };8105};8106const transformVText = (dir, node, context) => {8107 const { exp, loc } = dir;8108 if (!exp) {8109 context.onError(createDOMCompilerError(52 /* X_V_TEXT_NO_EXPRESSION */, loc));8110 }8111 if (node.children.length) {8112 context.onError(createDOMCompilerError(53 /* X_V_TEXT_WITH_CHILDREN */, loc));8113 node.children.length = 0;8114 }8115 return {8116 props: [8117 compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`textContent`, true), exp8118 ? compilerCore.createCallExpression(context.helperString(compilerCore.TO_DISPLAY_STRING), [exp], loc)8119 : compilerCore.createSimpleExpression('', true))8120 ]8121 };8122};8123const transformModel = (dir, node, context) => {8124 const baseResult = compilerCore.transformModel(dir, node, context);8125 // base transform has errors OR component v-model (only need props)8126 if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) {8127 return baseResult;8128 }8129 if (dir.arg) {8130 context.onError(createDOMCompilerError(55 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));8131 }8132 function checkDuplicatedValue() {8133 const value = compilerCore.findProp(node, 'value');8134 if (value) {8135 context.onError(createDOMCompilerError(57 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc));8136 }8137 }8138 const { tag } = node;8139 const isCustomElement = context.isCustomElement(tag);8140 if (tag === 'input' ||8141 tag === 'textarea' ||8142 tag === 'select' ||8143 isCustomElement) {8144 let directiveToUse = V_MODEL_TEXT;8145 let isInvalidType = false;8146 if (tag === 'input' || isCustomElement) {8147 const type = compilerCore.findProp(node, `type`);8148 if (type) {8149 if (type.type === 7 /* DIRECTIVE */) {8150 // :type="foo"8151 directiveToUse = V_MODEL_DYNAMIC;8152 }8153 else if (type.value) {8154 switch (type.value.content) {8155 case 'radio':8156 directiveToUse = V_MODEL_RADIO;8157 break;8158 case 'checkbox':8159 directiveToUse = V_MODEL_CHECKBOX;8160 break;8161 case 'file':8162 isInvalidType = true;8163 context.onError(createDOMCompilerError(56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));8164 break;8165 default:8166 // text type8167 checkDuplicatedValue();8168 break;8169 }8170 }8171 }8172 else if (compilerCore.hasDynamicKeyVBind(node)) {8173 // element has bindings with dynamic keys, which can possibly contain8174 // "type".8175 directiveToUse = V_MODEL_DYNAMIC;8176 }8177 else {8178 // text type8179 checkDuplicatedValue();8180 }8181 }8182 else if (tag === 'select') {8183 directiveToUse = V_MODEL_SELECT;8184 }8185 else {8186 // textarea8187 checkDuplicatedValue();8188 }8189 // inject runtime directive8190 // by returning the helper symbol via needRuntime8191 // the import will replaced a resolveDirective call.8192 if (!isInvalidType) {8193 baseResult.needRuntime = context.helper(directiveToUse);8194 }8195 }8196 else {8197 context.onError(createDOMCompilerError(54 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));8198 }8199 // native vmodel doesn't need the `modelValue` props since they are also8200 // passed to the runtime as `binding.value`. removing it reduces code size.8201 baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* SIMPLE_EXPRESSION */ &&8202 p.key.content === 'modelValue'));8203 return baseResult;8204};8205const isEventOptionModifier = /*#__PURE__*/ shared.makeMap(`passive,once,capture`);8206const isNonKeyModifier = /*#__PURE__*/ shared.makeMap(8207// event propagation management8208`stop,prevent,self,` +8209 // system modifiers + exact8210 `ctrl,shift,alt,meta,exact,` +8211 // mouse8212 `middle`);8213// left & right could be mouse or key modifiers based on event type8214const maybeKeyModifier = /*#__PURE__*/ shared.makeMap('left,right');8215const isKeyboardEvent = /*#__PURE__*/ shared.makeMap(`onkeyup,onkeydown,onkeypress`, true);8216const resolveModifiers = (key, modifiers, context, loc) => {8217 const keyModifiers = [];8218 const nonKeyModifiers = [];8219 const eventOptionModifiers = [];8220 for (let i = 0; i < modifiers.length; i++) {8221 const modifier = modifiers[i];8222 if (modifier === 'native' &&8223 compilerCore.checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) {8224 eventOptionModifiers.push(modifier);8225 }8226 else if (isEventOptionModifier(modifier)) {8227 // eventOptionModifiers: modifiers for addEventListener() options,8228 // e.g. .passive & .capture8229 eventOptionModifiers.push(modifier);8230 }8231 else {8232 // runtimeModifiers: modifiers that needs runtime guards8233 if (maybeKeyModifier(modifier)) {8234 if (compilerCore.isStaticExp(key)) {8235 if (isKeyboardEvent(key.content)) {8236 keyModifiers.push(modifier);8237 }...

Full Screen

Full Screen

compiler-dom.global.js

Source:compiler-dom.global.js Github

copy

Full Screen

...954 // in v3 mode, only enable if explicitly set to true955 // otherwise enable for any non-false value956 return mode === 3 ? value === true : value !== false;957 }958 function checkCompatEnabled(key, context, loc, ...args) {959 const enabled = isCompatEnabled(key, context);960 if (enabled) {961 warnDeprecation(key, context, loc, ...args);962 }963 return enabled;964 }965 function warnDeprecation(key, context, loc, ...args) {966 const val = getCompatValue(key, context);967 if (val === 'suppress-warning') {968 return;969 }970 const { message, link } = deprecationData[key];971 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;972 const err = new SyntaxError(msg);973 err.code = key;974 if (loc)975 err.loc = loc;976 context.onWarn(err);977 }978 // The default decoder only provides escapes for characters reserved as part of979 // the template syntax, and is only used if the custom renderer did not provide980 // a platform-specific decoder.981 const decodeRE = /&(gt|lt|amp|apos|quot);/g;982 const decodeMap = {983 gt: '>',984 lt: '<',985 amp: '&',986 apos: "'",987 quot: '"'988 };989 const defaultParserOptions = {990 delimiters: [`{{`, `}}`],991 getNamespace: () => 0 /* HTML */,992 getTextMode: () => 0 /* DATA */,993 isVoidTag: NO,994 isPreTag: NO,995 isCustomElement: NO,996 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),997 onError: defaultOnError,998 onWarn: defaultOnWarn,999 comments: true1000 };1001 function baseParse(content, options = {}) {1002 const context = createParserContext(content, options);1003 const start = getCursor(context);1004 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));1005 }1006 function createParserContext(content, rawOptions) {1007 const options = extend({}, defaultParserOptions);1008 let key;1009 for (key in rawOptions) {1010 // @ts-ignore1011 options[key] =1012 rawOptions[key] === undefined1013 ? defaultParserOptions[key]1014 : rawOptions[key];1015 }1016 return {1017 options,1018 column: 1,1019 line: 1,1020 offset: 0,1021 originalSource: content,1022 source: content,1023 inPre: false,1024 inVPre: false,1025 onWarn: options.onWarn1026 };1027 }1028 function parseChildren(context, mode, ancestors) {1029 const parent = last(ancestors);1030 const ns = parent ? parent.ns : 0 /* HTML */;1031 const nodes = [];1032 while (!isEnd(context, mode, ancestors)) {1033 const s = context.source;1034 let node = undefined;1035 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {1036 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {1037 // '{{'1038 node = parseInterpolation(context, mode);1039 }1040 else if (mode === 0 /* DATA */ && s[0] === '<') {1041 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state1042 if (s.length === 1) {1043 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);1044 }1045 else if (s[1] === '!') {1046 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state1047 if (startsWith(s, '<!--')) {1048 node = parseComment(context);1049 }1050 else if (startsWith(s, '<!DOCTYPE')) {1051 // Ignore DOCTYPE by a limitation.1052 node = parseBogusComment(context);1053 }1054 else if (startsWith(s, '<![CDATA[')) {1055 if (ns !== 0 /* HTML */) {1056 node = parseCDATA(context, ancestors);1057 }1058 else {1059 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);1060 node = parseBogusComment(context);1061 }1062 }1063 else {1064 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);1065 node = parseBogusComment(context);1066 }1067 }1068 else if (s[1] === '/') {1069 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state1070 if (s.length === 2) {1071 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);1072 }1073 else if (s[2] === '>') {1074 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);1075 advanceBy(context, 3);1076 continue;1077 }1078 else if (/[a-z]/i.test(s[2])) {1079 emitError(context, 23 /* X_INVALID_END_TAG */);1080 parseTag(context, 1 /* End */, parent);1081 continue;1082 }1083 else {1084 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);1085 node = parseBogusComment(context);1086 }1087 }1088 else if (/[a-z]/i.test(s[1])) {1089 node = parseElement(context, ancestors);1090 // 2.x <template> with no directive compat1091 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&1092 node &&1093 node.tag === 'template' &&1094 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&1095 isSpecialTemplateDirective(p.name))) {1096 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);1097 node = node.children;1098 }1099 }1100 else if (s[1] === '?') {1101 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);1102 node = parseBogusComment(context);1103 }1104 else {1105 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);1106 }1107 }1108 }1109 if (!node) {1110 node = parseText(context, mode);1111 }1112 if (isArray(node)) {1113 for (let i = 0; i < node.length; i++) {1114 pushNode(nodes, node[i]);1115 }1116 }1117 else {1118 pushNode(nodes, node);1119 }1120 }1121 // Whitespace handling strategy like v21122 let removedWhitespace = false;1123 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {1124 const shouldCondense = context.options.whitespace !== 'preserve';1125 for (let i = 0; i < nodes.length; i++) {1126 const node = nodes[i];1127 if (!context.inPre && node.type === 2 /* TEXT */) {1128 if (!/[^\t\r\n\f ]/.test(node.content)) {1129 const prev = nodes[i - 1];1130 const next = nodes[i + 1];1131 // Remove if:1132 // - the whitespace is the first or last node, or:1133 // - (condense mode) the whitespace is adjacent to a comment, or:1134 // - (condense mode) the whitespace is between two elements AND contains newline1135 if (!prev ||1136 !next ||1137 (shouldCondense &&1138 (prev.type === 3 /* COMMENT */ ||1139 next.type === 3 /* COMMENT */ ||1140 (prev.type === 1 /* ELEMENT */ &&1141 next.type === 1 /* ELEMENT */ &&1142 /[\r\n]/.test(node.content))))) {1143 removedWhitespace = true;1144 nodes[i] = null;1145 }1146 else {1147 // Otherwise, the whitespace is condensed into a single space1148 node.content = ' ';1149 }1150 }1151 else if (shouldCondense) {1152 // in condense mode, consecutive whitespaces in text are condensed1153 // down to a single space.1154 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');1155 }1156 }1157 // Remove comment nodes if desired by configuration.1158 else if (node.type === 3 /* COMMENT */ && !context.options.comments) {1159 removedWhitespace = true;1160 nodes[i] = null;1161 }1162 }1163 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {1164 // remove leading newline per html spec1165 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element1166 const first = nodes[0];1167 if (first && first.type === 2 /* TEXT */) {1168 first.content = first.content.replace(/^\r?\n/, '');1169 }1170 }1171 }1172 return removedWhitespace ? nodes.filter(Boolean) : nodes;1173 }1174 function pushNode(nodes, node) {1175 if (node.type === 2 /* TEXT */) {1176 const prev = last(nodes);1177 // Merge if both this and the previous node are text and those are1178 // consecutive. This happens for cases like "a < b".1179 if (prev &&1180 prev.type === 2 /* TEXT */ &&1181 prev.loc.end.offset === node.loc.start.offset) {1182 prev.content += node.content;1183 prev.loc.end = node.loc.end;1184 prev.loc.source += node.loc.source;1185 return;1186 }1187 }1188 nodes.push(node);1189 }1190 function parseCDATA(context, ancestors) {1191 advanceBy(context, 9);1192 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1193 if (context.source.length === 0) {1194 emitError(context, 6 /* EOF_IN_CDATA */);1195 }1196 else {1197 advanceBy(context, 3);1198 }1199 return nodes;1200 }1201 function parseComment(context) {1202 const start = getCursor(context);1203 let content;1204 // Regular comment.1205 const match = /--(\!)?>/.exec(context.source);1206 if (!match) {1207 content = context.source.slice(4);1208 advanceBy(context, context.source.length);1209 emitError(context, 7 /* EOF_IN_COMMENT */);1210 }1211 else {1212 if (match.index <= 3) {1213 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1214 }1215 if (match[1]) {1216 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1217 }1218 content = context.source.slice(4, match.index);1219 // Advancing with reporting nested comments.1220 const s = context.source.slice(0, match.index);1221 let prevIndex = 1, nestedIndex = 0;1222 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1223 advanceBy(context, nestedIndex - prevIndex + 1);1224 if (nestedIndex + 4 < s.length) {1225 emitError(context, 16 /* NESTED_COMMENT */);1226 }1227 prevIndex = nestedIndex + 1;1228 }1229 advanceBy(context, match.index + match[0].length - prevIndex + 1);1230 }1231 return {1232 type: 3 /* COMMENT */,1233 content,1234 loc: getSelection(context, start)1235 };1236 }1237 function parseBogusComment(context) {1238 const start = getCursor(context);1239 const contentStart = context.source[1] === '?' ? 1 : 2;1240 let content;1241 const closeIndex = context.source.indexOf('>');1242 if (closeIndex === -1) {1243 content = context.source.slice(contentStart);1244 advanceBy(context, context.source.length);1245 }1246 else {1247 content = context.source.slice(contentStart, closeIndex);1248 advanceBy(context, closeIndex + 1);1249 }1250 return {1251 type: 3 /* COMMENT */,1252 content,1253 loc: getSelection(context, start)1254 };1255 }1256 function parseElement(context, ancestors) {1257 // Start tag.1258 const wasInPre = context.inPre;1259 const wasInVPre = context.inVPre;1260 const parent = last(ancestors);1261 const element = parseTag(context, 0 /* Start */, parent);1262 const isPreBoundary = context.inPre && !wasInPre;1263 const isVPreBoundary = context.inVPre && !wasInVPre;1264 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1265 // #4030 self-closing <pre> tag1266 if (isPreBoundary) {1267 context.inPre = false;1268 }1269 if (isVPreBoundary) {1270 context.inVPre = false;1271 }1272 return element;1273 }1274 // Children.1275 ancestors.push(element);1276 const mode = context.options.getTextMode(element, parent);1277 const children = parseChildren(context, mode, ancestors);1278 ancestors.pop();1279 // 2.x inline-template compat1280 {1281 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1282 if (inlineTemplateProp &&1283 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1284 const loc = getSelection(context, element.loc.end);1285 inlineTemplateProp.value = {1286 type: 2 /* TEXT */,1287 content: loc.source,1288 loc1289 };1290 }1291 }1292 element.children = children;1293 // End tag.1294 if (startsWithEndTagOpen(context.source, element.tag)) {1295 parseTag(context, 1 /* End */, parent);1296 }1297 else {1298 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1299 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1300 const first = children[0];1301 if (first && startsWith(first.loc.source, '<!--')) {1302 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1303 }1304 }1305 }1306 element.loc = getSelection(context, element.loc.start);1307 if (isPreBoundary) {1308 context.inPre = false;1309 }1310 if (isVPreBoundary) {1311 context.inVPre = false;1312 }1313 return element;1314 }1315 const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`);1316 function parseTag(context, type, parent) {1317 // Tag open.1318 const start = getCursor(context);1319 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1320 const tag = match[1];1321 const ns = context.options.getNamespace(tag, parent);1322 advanceBy(context, match[0].length);1323 advanceSpaces(context);1324 // save current state in case we need to re-parse attributes with v-pre1325 const cursor = getCursor(context);1326 const currentSource = context.source;1327 // check <pre> tag1328 if (context.options.isPreTag(tag)) {1329 context.inPre = true;1330 }1331 // Attributes.1332 let props = parseAttributes(context, type);1333 // check v-pre1334 if (type === 0 /* Start */ &&1335 !context.inVPre &&1336 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1337 context.inVPre = true;1338 // reset context1339 extend(context, cursor);1340 context.source = currentSource;1341 // re-parse attrs and filter out v-pre itself1342 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1343 }1344 // Tag close.1345 let isSelfClosing = false;1346 if (context.source.length === 0) {1347 emitError(context, 9 /* EOF_IN_TAG */);1348 }1349 else {1350 isSelfClosing = startsWith(context.source, '/>');1351 if (type === 1 /* End */ && isSelfClosing) {1352 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1353 }1354 advanceBy(context, isSelfClosing ? 2 : 1);1355 }1356 if (type === 1 /* End */) {1357 return;1358 }1359 // 2.x deprecation checks1360 if (isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1361 let hasIf = false;1362 let hasFor = false;1363 for (let i = 0; i < props.length; i++) {1364 const p = props[i];1365 if (p.type === 7 /* DIRECTIVE */) {1366 if (p.name === 'if') {1367 hasIf = true;1368 }1369 else if (p.name === 'for') {1370 hasFor = true;1371 }1372 }1373 if (hasIf && hasFor) {1374 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1375 }1376 }1377 }1378 let tagType = 0 /* ELEMENT */;1379 if (!context.inVPre) {1380 if (tag === 'slot') {1381 tagType = 2 /* SLOT */;1382 }1383 else if (tag === 'template') {1384 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1385 tagType = 3 /* TEMPLATE */;1386 }1387 }1388 else if (isComponent(tag, props, context)) {1389 tagType = 1 /* COMPONENT */;1390 }1391 }1392 return {1393 type: 1 /* ELEMENT */,1394 ns,1395 tag,1396 tagType,1397 props,1398 isSelfClosing,1399 children: [],1400 loc: getSelection(context, start),1401 codegenNode: undefined // to be created during transform phase1402 };1403 }1404 function isComponent(tag, props, context) {1405 const options = context.options;1406 if (options.isCustomElement(tag)) {1407 return false;1408 }1409 if (tag === 'component' ||1410 /^[A-Z]/.test(tag) ||1411 isCoreComponent(tag) ||1412 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1413 (options.isNativeTag && !options.isNativeTag(tag))) {1414 return true;1415 }1416 // at this point the tag should be a native tag, but check for potential "is"1417 // casting1418 for (let i = 0; i < props.length; i++) {1419 const p = props[i];1420 if (p.type === 6 /* ATTRIBUTE */) {1421 if (p.name === 'is' && p.value) {1422 if (p.value.content.startsWith('vue:')) {1423 return true;1424 }1425 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1426 return true;1427 }1428 }1429 }1430 else {1431 // directive1432 // v-is (TODO Deprecate)1433 if (p.name === 'is') {1434 return true;1435 }1436 else if (1437 // :is on plain element - only treat as component in compat mode1438 p.name === 'bind' &&1439 isBindKey(p.arg, 'is') &&1440 true &&1441 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1442 return true;1443 }1444 }1445 }1446 }1447 function parseAttributes(context, type) {1448 const props = [];1449 const attributeNames = new Set();1450 while (context.source.length > 0 &&1451 !startsWith(context.source, '>') &&1452 !startsWith(context.source, '/>')) {1453 if (startsWith(context.source, '/')) {1454 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1455 advanceBy(context, 1);1456 advanceSpaces(context);1457 continue;1458 }1459 if (type === 1 /* End */) {1460 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1461 }1462 const attr = parseAttribute(context, attributeNames);1463 // Trim whitespace between class1464 // https://github.com/vuejs/vue-next/issues/42511465 if (attr.type === 6 /* ATTRIBUTE */ &&1466 attr.value &&1467 attr.name === 'class') {1468 attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();1469 }1470 if (type === 0 /* Start */) {1471 props.push(attr);1472 }1473 if (/^[^\t\r\n\f />]/.test(context.source)) {1474 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1475 }1476 advanceSpaces(context);1477 }1478 return props;1479 }1480 function parseAttribute(context, nameSet) {1481 // Name.1482 const start = getCursor(context);1483 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1484 const name = match[0];1485 if (nameSet.has(name)) {1486 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1487 }1488 nameSet.add(name);1489 if (name[0] === '=') {1490 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1491 }1492 {1493 const pattern = /["'<]/g;1494 let m;1495 while ((m = pattern.exec(name))) {1496 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1497 }1498 }1499 advanceBy(context, name.length);1500 // Value1501 let value = undefined;1502 if (/^[\t\r\n\f ]*=/.test(context.source)) {1503 advanceSpaces(context);1504 advanceBy(context, 1);1505 advanceSpaces(context);1506 value = parseAttributeValue(context);1507 if (!value) {1508 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1509 }1510 }1511 const loc = getSelection(context, start);1512 if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {1513 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1514 let isPropShorthand = startsWith(name, '.');1515 let dirName = match[1] ||1516 (isPropShorthand || startsWith(name, ':')1517 ? 'bind'1518 : startsWith(name, '@')1519 ? 'on'1520 : 'slot');1521 let arg;1522 if (match[2]) {1523 const isSlot = dirName === 'slot';1524 const startOffset = name.lastIndexOf(match[2]);1525 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));1526 let content = match[2];1527 let isStatic = true;1528 if (content.startsWith('[')) {1529 isStatic = false;1530 if (!content.endsWith(']')) {1531 emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1532 content = content.slice(1);1533 }1534 else {1535 content = content.slice(1, content.length - 1);1536 }1537 }1538 else if (isSlot) {1539 // #1241 special case for v-slot: vuetify relies extensively on slot1540 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x1541 // supports such usage so we are keeping it consistent with 2.x.1542 content += match[3] || '';1543 }1544 arg = {1545 type: 4 /* SIMPLE_EXPRESSION */,1546 content,1547 isStatic,1548 constType: isStatic1549 ? 3 /* CAN_STRINGIFY */1550 : 0 /* NOT_CONSTANT */,1551 loc1552 };1553 }1554 if (value && value.isQuoted) {1555 const valueLoc = value.loc;1556 valueLoc.start.offset++;1557 valueLoc.start.column++;1558 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1559 valueLoc.source = valueLoc.source.slice(1, -1);1560 }1561 const modifiers = match[3] ? match[3].slice(1).split('.') : [];1562 if (isPropShorthand)1563 modifiers.push('prop');1564 // 2.x compat v-bind:foo.sync -> v-model:foo1565 if (dirName === 'bind' && arg) {1566 if (modifiers.includes('sync') &&1567 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {1568 dirName = 'model';1569 modifiers.splice(modifiers.indexOf('sync'), 1);1570 }1571 if (modifiers.includes('prop')) {1572 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);1573 }1574 }1575 return {1576 type: 7 /* DIRECTIVE */,1577 name: dirName,1578 exp: value && {1579 type: 4 /* SIMPLE_EXPRESSION */,1580 content: value.content,1581 isStatic: false,1582 // Treat as non-constant by default. This can be potentially set to1583 // other values by `transformExpression` to make it eligible for hoisting.1584 constType: 0 /* NOT_CONSTANT */,1585 loc: value.loc1586 },1587 arg,1588 modifiers,1589 loc1590 };1591 }1592 // missing directive name or illegal directive name1593 if (!context.inVPre && startsWith(name, 'v-')) {1594 emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */);1595 }1596 return {1597 type: 6 /* ATTRIBUTE */,1598 name,1599 value: value && {1600 type: 2 /* TEXT */,1601 content: value.content,1602 loc: value.loc1603 },1604 loc1605 };1606 }1607 function parseAttributeValue(context) {1608 const start = getCursor(context);1609 let content;1610 const quote = context.source[0];1611 const isQuoted = quote === `"` || quote === `'`;1612 if (isQuoted) {1613 // Quoted value.1614 advanceBy(context, 1);1615 const endIndex = context.source.indexOf(quote);1616 if (endIndex === -1) {1617 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1618 }1619 else {1620 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1621 advanceBy(context, 1);1622 }1623 }1624 else {1625 // Unquoted1626 const match = /^[^\t\r\n\f >]+/.exec(context.source);1627 if (!match) {1628 return undefined;1629 }1630 const unexpectedChars = /["'<=`]/g;1631 let m;1632 while ((m = unexpectedChars.exec(match[0]))) {1633 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1634 }1635 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1636 }1637 return { content, isQuoted, loc: getSelection(context, start) };1638 }1639 function parseInterpolation(context, mode) {1640 const [open, close] = context.options.delimiters;1641 const closeIndex = context.source.indexOf(close, open.length);1642 if (closeIndex === -1) {1643 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);1644 return undefined;1645 }1646 const start = getCursor(context);1647 advanceBy(context, open.length);1648 const innerStart = getCursor(context);1649 const innerEnd = getCursor(context);1650 const rawContentLength = closeIndex - open.length;1651 const rawContent = context.source.slice(0, rawContentLength);1652 const preTrimContent = parseTextData(context, rawContentLength, mode);1653 const content = preTrimContent.trim();1654 const startOffset = preTrimContent.indexOf(content);1655 if (startOffset > 0) {1656 advancePositionWithMutation(innerStart, rawContent, startOffset);1657 }1658 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1659 advancePositionWithMutation(innerEnd, rawContent, endOffset);1660 advanceBy(context, close.length);1661 return {1662 type: 5 /* INTERPOLATION */,1663 content: {1664 type: 4 /* SIMPLE_EXPRESSION */,1665 isStatic: false,1666 // Set `isConstant` to false by default and will decide in transformExpression1667 constType: 0 /* NOT_CONSTANT */,1668 content,1669 loc: getSelection(context, innerStart, innerEnd)1670 },1671 loc: getSelection(context, start)1672 };1673 }1674 function parseText(context, mode) {1675 const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];1676 let endIndex = context.source.length;1677 for (let i = 0; i < endTokens.length; i++) {1678 const index = context.source.indexOf(endTokens[i], 1);1679 if (index !== -1 && endIndex > index) {1680 endIndex = index;1681 }1682 }1683 const start = getCursor(context);1684 const content = parseTextData(context, endIndex, mode);1685 return {1686 type: 2 /* TEXT */,1687 content,1688 loc: getSelection(context, start)1689 };1690 }1691 /**1692 * Get text data with a given length from the current location.1693 * This translates HTML entities in the text data.1694 */1695 function parseTextData(context, length, mode) {1696 const rawText = context.source.slice(0, length);1697 advanceBy(context, length);1698 if (mode === 2 /* RAWTEXT */ ||1699 mode === 3 /* CDATA */ ||1700 rawText.indexOf('&') === -1) {1701 return rawText;1702 }1703 else {1704 // DATA or RCDATA containing "&"". Entity decoding required.1705 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);1706 }1707 }1708 function getCursor(context) {1709 const { column, line, offset } = context;1710 return { column, line, offset };1711 }1712 function getSelection(context, start, end) {1713 end = end || getCursor(context);1714 return {1715 start,1716 end,1717 source: context.originalSource.slice(start.offset, end.offset)1718 };1719 }1720 function last(xs) {1721 return xs[xs.length - 1];1722 }1723 function startsWith(source, searchString) {1724 return source.startsWith(searchString);1725 }1726 function advanceBy(context, numberOfCharacters) {1727 const { source } = context;1728 advancePositionWithMutation(context, source, numberOfCharacters);1729 context.source = source.slice(numberOfCharacters);1730 }1731 function advanceSpaces(context) {1732 const match = /^[\t\r\n\f ]+/.exec(context.source);1733 if (match) {1734 advanceBy(context, match[0].length);1735 }1736 }1737 function getNewPosition(context, start, numberOfCharacters) {1738 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1739 }1740 function emitError(context, code, offset, loc = getCursor(context)) {1741 if (offset) {1742 loc.offset += offset;1743 loc.column += offset;1744 }1745 context.options.onError(createCompilerError(code, {1746 start: loc,1747 end: loc,1748 source: ''1749 }));1750 }1751 function isEnd(context, mode, ancestors) {1752 const s = context.source;1753 switch (mode) {1754 case 0 /* DATA */:1755 if (startsWith(s, '</')) {1756 // TODO: probably bad performance1757 for (let i = ancestors.length - 1; i >= 0; --i) {1758 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1759 return true;1760 }1761 }1762 }1763 break;1764 case 1 /* RCDATA */:1765 case 2 /* RAWTEXT */: {1766 const parent = last(ancestors);1767 if (parent && startsWithEndTagOpen(s, parent.tag)) {1768 return true;1769 }1770 break;1771 }1772 case 3 /* CDATA */:1773 if (startsWith(s, ']]>')) {1774 return true;1775 }1776 break;1777 }1778 return !s;1779 }1780 function startsWithEndTagOpen(source, tag) {1781 return (startsWith(source, '</') &&1782 source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&1783 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));1784 }1785 function hoistStatic(root, context) {1786 walk(root, context, 1787 // Root node is unfortunately non-hoistable due to potential parent1788 // fallthrough attributes.1789 isSingleElementRoot(root, root.children[0]));1790 }1791 function isSingleElementRoot(root, child) {1792 const { children } = root;1793 return (children.length === 1 &&1794 child.type === 1 /* ELEMENT */ &&1795 !isSlotOutlet(child));1796 }1797 function walk(node, context, doNotHoistNode = false) {1798 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1799 // static bindings with expressions. These expressions are guaranteed to be1800 // constant so they are still eligible for hoisting, but they are only1801 // available at runtime and therefore cannot be evaluated ahead of time.1802 // This is only a concern for pre-stringification (via transformHoist by1803 // @vue/compiler-dom), but doing it here allows us to perform only one full1804 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1805 // stringification threshold is met.1806 let canStringify = true;1807 const { children } = node;1808 const originalCount = children.length;1809 let hoistedCount = 0;1810 for (let i = 0; i < children.length; i++) {1811 const child = children[i];1812 // only plain elements & text calls are eligible for hoisting.1813 if (child.type === 1 /* ELEMENT */ &&1814 child.tagType === 0 /* ELEMENT */) {1815 const constantType = doNotHoistNode1816 ? 0 /* NOT_CONSTANT */1817 : getConstantType(child, context);1818 if (constantType > 0 /* NOT_CONSTANT */) {1819 if (constantType < 3 /* CAN_STRINGIFY */) {1820 canStringify = false;1821 }1822 if (constantType >= 2 /* CAN_HOIST */) {1823 child.codegenNode.patchFlag =1824 -1 /* HOISTED */ + (` /* HOISTED */` );1825 child.codegenNode = context.hoist(child.codegenNode);1826 hoistedCount++;1827 continue;1828 }1829 }1830 else {1831 // node may contain dynamic children, but its props may be eligible for1832 // hoisting.1833 const codegenNode = child.codegenNode;1834 if (codegenNode.type === 13 /* VNODE_CALL */) {1835 const flag = getPatchFlag(codegenNode);1836 if ((!flag ||1837 flag === 512 /* NEED_PATCH */ ||1838 flag === 1 /* TEXT */) &&1839 getGeneratedPropsConstantType(child, context) >=1840 2 /* CAN_HOIST */) {1841 const props = getNodeProps(child);1842 if (props) {1843 codegenNode.props = context.hoist(props);1844 }1845 }1846 if (codegenNode.dynamicProps) {1847 codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);1848 }1849 }1850 }1851 }1852 else if (child.type === 12 /* TEXT_CALL */) {1853 const contentType = getConstantType(child.content, context);1854 if (contentType > 0) {1855 if (contentType < 3 /* CAN_STRINGIFY */) {1856 canStringify = false;1857 }1858 if (contentType >= 2 /* CAN_HOIST */) {1859 child.codegenNode = context.hoist(child.codegenNode);1860 hoistedCount++;1861 }1862 }1863 }1864 // walk further1865 if (child.type === 1 /* ELEMENT */) {1866 const isComponent = child.tagType === 1 /* COMPONENT */;1867 if (isComponent) {1868 context.scopes.vSlot++;1869 }1870 walk(child, context);1871 if (isComponent) {1872 context.scopes.vSlot--;1873 }1874 }1875 else if (child.type === 11 /* FOR */) {1876 // Do not hoist v-for single child because it has to be a block1877 walk(child, context, child.children.length === 1);1878 }1879 else if (child.type === 9 /* IF */) {1880 for (let i = 0; i < child.branches.length; i++) {1881 // Do not hoist v-if single child because it has to be a block1882 walk(child.branches[i], context, child.branches[i].children.length === 1);1883 }1884 }1885 }1886 if (canStringify && hoistedCount && context.transformHoist) {1887 context.transformHoist(children, context, node);1888 }1889 // all children were hoisted - the entire children array is hoistable.1890 if (hoistedCount &&1891 hoistedCount === originalCount &&1892 node.type === 1 /* ELEMENT */ &&1893 node.tagType === 0 /* ELEMENT */ &&1894 node.codegenNode &&1895 node.codegenNode.type === 13 /* VNODE_CALL */ &&1896 isArray(node.codegenNode.children)) {1897 node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));1898 }1899 }1900 function getConstantType(node, context) {1901 const { constantCache } = context;1902 switch (node.type) {1903 case 1 /* ELEMENT */:1904 if (node.tagType !== 0 /* ELEMENT */) {1905 return 0 /* NOT_CONSTANT */;1906 }1907 const cached = constantCache.get(node);1908 if (cached !== undefined) {1909 return cached;1910 }1911 const codegenNode = node.codegenNode;1912 if (codegenNode.type !== 13 /* VNODE_CALL */) {1913 return 0 /* NOT_CONSTANT */;1914 }1915 const flag = getPatchFlag(codegenNode);1916 if (!flag) {1917 let returnType = 3 /* CAN_STRINGIFY */;1918 // Element itself has no patch flag. However we still need to check:1919 // 1. Even for a node with no patch flag, it is possible for it to contain1920 // non-hoistable expressions that refers to scope variables, e.g. compiler1921 // injected keys or cached event handlers. Therefore we need to always1922 // check the codegenNode's props to be sure.1923 const generatedPropsType = getGeneratedPropsConstantType(node, context);1924 if (generatedPropsType === 0 /* NOT_CONSTANT */) {1925 constantCache.set(node, 0 /* NOT_CONSTANT */);1926 return 0 /* NOT_CONSTANT */;1927 }1928 if (generatedPropsType < returnType) {1929 returnType = generatedPropsType;1930 }1931 // 2. its children.1932 for (let i = 0; i < node.children.length; i++) {1933 const childType = getConstantType(node.children[i], context);1934 if (childType === 0 /* NOT_CONSTANT */) {1935 constantCache.set(node, 0 /* NOT_CONSTANT */);1936 return 0 /* NOT_CONSTANT */;1937 }1938 if (childType < returnType) {1939 returnType = childType;1940 }1941 }1942 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-01943 // type, check if any of the props can cause the type to be lowered1944 // we can skip can_patch because it's guaranteed by the absence of a1945 // patchFlag.1946 if (returnType > 1 /* CAN_SKIP_PATCH */) {1947 for (let i = 0; i < node.props.length; i++) {1948 const p = node.props[i];1949 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {1950 const expType = getConstantType(p.exp, context);1951 if (expType === 0 /* NOT_CONSTANT */) {1952 constantCache.set(node, 0 /* NOT_CONSTANT */);1953 return 0 /* NOT_CONSTANT */;1954 }1955 if (expType < returnType) {1956 returnType = expType;1957 }1958 }1959 }1960 }1961 // only svg/foreignObject could be block here, however if they are1962 // static then they don't need to be blocks since there will be no1963 // nested updates.1964 if (codegenNode.isBlock) {1965 context.removeHelper(OPEN_BLOCK);1966 context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));1967 codegenNode.isBlock = false;1968 context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));1969 }1970 constantCache.set(node, returnType);1971 return returnType;1972 }1973 else {1974 constantCache.set(node, 0 /* NOT_CONSTANT */);1975 return 0 /* NOT_CONSTANT */;1976 }1977 case 2 /* TEXT */:1978 case 3 /* COMMENT */:1979 return 3 /* CAN_STRINGIFY */;1980 case 9 /* IF */:1981 case 11 /* FOR */:1982 case 10 /* IF_BRANCH */:1983 return 0 /* NOT_CONSTANT */;1984 case 5 /* INTERPOLATION */:1985 case 12 /* TEXT_CALL */:1986 return getConstantType(node.content, context);1987 case 4 /* SIMPLE_EXPRESSION */:1988 return node.constType;1989 case 8 /* COMPOUND_EXPRESSION */:1990 let returnType = 3 /* CAN_STRINGIFY */;1991 for (let i = 0; i < node.children.length; i++) {1992 const child = node.children[i];1993 if (isString(child) || isSymbol(child)) {1994 continue;1995 }1996 const childType = getConstantType(child, context);1997 if (childType === 0 /* NOT_CONSTANT */) {1998 return 0 /* NOT_CONSTANT */;1999 }2000 else if (childType < returnType) {2001 returnType = childType;2002 }2003 }2004 return returnType;2005 default:2006 return 0 /* NOT_CONSTANT */;2007 }2008 }2009 const allowHoistedHelperSet = new Set([2010 NORMALIZE_CLASS,2011 NORMALIZE_STYLE,2012 NORMALIZE_PROPS,2013 GUARD_REACTIVE_PROPS2014 ]);2015 function getConstantTypeOfHelperCall(value, context) {2016 if (value.type === 14 /* JS_CALL_EXPRESSION */ &&2017 !isString(value.callee) &&2018 allowHoistedHelperSet.has(value.callee)) {2019 const arg = value.arguments[0];2020 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {2021 return getConstantType(arg, context);2022 }2023 else if (arg.type === 14 /* JS_CALL_EXPRESSION */) {2024 // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`2025 return getConstantTypeOfHelperCall(arg, context);2026 }2027 }2028 return 0 /* NOT_CONSTANT */;2029 }2030 function getGeneratedPropsConstantType(node, context) {2031 let returnType = 3 /* CAN_STRINGIFY */;2032 const props = getNodeProps(node);2033 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {2034 const { properties } = props;2035 for (let i = 0; i < properties.length; i++) {2036 const { key, value } = properties[i];2037 const keyType = getConstantType(key, context);2038 if (keyType === 0 /* NOT_CONSTANT */) {2039 return keyType;2040 }2041 if (keyType < returnType) {2042 returnType = keyType;2043 }2044 let valueType;2045 if (value.type === 4 /* SIMPLE_EXPRESSION */) {2046 valueType = getConstantType(value, context);2047 }2048 else if (value.type === 14 /* JS_CALL_EXPRESSION */) {2049 // some helper calls can be hoisted,2050 // such as the `normalizeProps` generated by the compiler for pre-normalize class,2051 // in this case we need to respect the ConstantType of the helper's argments2052 valueType = getConstantTypeOfHelperCall(value, context);2053 }2054 else {2055 valueType = 0 /* NOT_CONSTANT */;2056 }2057 if (valueType === 0 /* NOT_CONSTANT */) {2058 return valueType;2059 }2060 if (valueType < returnType) {2061 returnType = valueType;2062 }2063 }2064 }2065 return returnType;2066 }2067 function getNodeProps(node) {2068 const codegenNode = node.codegenNode;2069 if (codegenNode.type === 13 /* VNODE_CALL */) {2070 return codegenNode.props;2071 }2072 }2073 function getPatchFlag(node) {2074 const flag = node.patchFlag;2075 return flag ? parseInt(flag, 10) : undefined;2076 }2077 function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {2078 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);2079 const context = {2080 // options2081 selfName: nameMatch && capitalize(camelize(nameMatch[1])),2082 prefixIdentifiers,2083 hoistStatic,2084 cacheHandlers,2085 nodeTransforms,2086 directiveTransforms,2087 transformHoist,2088 isBuiltInComponent,2089 isCustomElement,2090 expressionPlugins,2091 scopeId,2092 slotted,2093 ssr,2094 inSSR,2095 ssrCssVars,2096 bindingMetadata,2097 inline,2098 isTS,2099 onError,2100 onWarn,2101 compatConfig,2102 // state2103 root,2104 helpers: new Map(),2105 components: new Set(),2106 directives: new Set(),2107 hoists: [],2108 imports: [],2109 constantCache: new Map(),2110 temps: 0,2111 cached: 0,2112 identifiers: Object.create(null),2113 scopes: {2114 vFor: 0,2115 vSlot: 0,2116 vPre: 0,2117 vOnce: 02118 },2119 parent: null,2120 currentNode: root,2121 childIndex: 0,2122 inVOnce: false,2123 // methods2124 helper(name) {2125 const count = context.helpers.get(name) || 0;2126 context.helpers.set(name, count + 1);2127 return name;2128 },2129 removeHelper(name) {2130 const count = context.helpers.get(name);2131 if (count) {2132 const currentCount = count - 1;2133 if (!currentCount) {2134 context.helpers.delete(name);2135 }2136 else {2137 context.helpers.set(name, currentCount);2138 }2139 }2140 },2141 helperString(name) {2142 return `_${helperNameMap[context.helper(name)]}`;2143 },2144 replaceNode(node) {2145 /* istanbul ignore if */2146 {2147 if (!context.currentNode) {2148 throw new Error(`Node being replaced is already removed.`);2149 }2150 if (!context.parent) {2151 throw new Error(`Cannot replace root node.`);2152 }2153 }2154 context.parent.children[context.childIndex] = context.currentNode = node;2155 },2156 removeNode(node) {2157 if (!context.parent) {2158 throw new Error(`Cannot remove root node.`);2159 }2160 const list = context.parent.children;2161 const removalIndex = node2162 ? list.indexOf(node)2163 : context.currentNode2164 ? context.childIndex2165 : -1;2166 /* istanbul ignore if */2167 if (removalIndex < 0) {2168 throw new Error(`node being removed is not a child of current parent`);2169 }2170 if (!node || node === context.currentNode) {2171 // current node removed2172 context.currentNode = null;2173 context.onNodeRemoved();2174 }2175 else {2176 // sibling node removed2177 if (context.childIndex > removalIndex) {2178 context.childIndex--;2179 context.onNodeRemoved();2180 }2181 }2182 context.parent.children.splice(removalIndex, 1);2183 },2184 onNodeRemoved: () => { },2185 addIdentifiers(exp) {2186 },2187 removeIdentifiers(exp) {2188 },2189 hoist(exp) {2190 if (isString(exp))2191 exp = createSimpleExpression(exp);2192 context.hoists.push(exp);2193 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);2194 identifier.hoisted = exp;2195 return identifier;2196 },2197 cache(exp, isVNode = false) {2198 return createCacheExpression(context.cached++, exp, isVNode);2199 }2200 };2201 {2202 context.filters = new Set();2203 }2204 return context;2205 }2206 function transform(root, options) {2207 const context = createTransformContext(root, options);2208 traverseNode(root, context);2209 if (options.hoistStatic) {2210 hoistStatic(root, context);2211 }2212 if (!options.ssr) {2213 createRootCodegen(root, context);2214 }2215 // finalize meta information2216 root.helpers = [...context.helpers.keys()];2217 root.components = [...context.components];2218 root.directives = [...context.directives];2219 root.imports = context.imports;2220 root.hoists = context.hoists;2221 root.temps = context.temps;2222 root.cached = context.cached;2223 {2224 root.filters = [...context.filters];2225 }2226 }2227 function createRootCodegen(root, context) {2228 const { helper } = context;2229 const { children } = root;2230 if (children.length === 1) {2231 const child = children[0];2232 // if the single child is an element, turn it into a block.2233 if (isSingleElementRoot(root, child) && child.codegenNode) {2234 // single element root is never hoisted so codegenNode will never be2235 // SimpleExpressionNode2236 const codegenNode = child.codegenNode;2237 if (codegenNode.type === 13 /* VNODE_CALL */) {2238 makeBlock(codegenNode, context);2239 }2240 root.codegenNode = codegenNode;2241 }2242 else {2243 // - single <slot/>, IfNode, ForNode: already blocks.2244 // - single text node: always patched.2245 // root codegen falls through via genNode()2246 root.codegenNode = child;2247 }2248 }2249 else if (children.length > 1) {2250 // root has multiple nodes - return a fragment block.2251 let patchFlag = 64 /* STABLE_FRAGMENT */;2252 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];2253 // check if the fragment actually contains a single valid child with2254 // the rest being comments2255 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2256 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2257 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;2258 }2259 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, undefined, false /* isComponent */);2260 }2261 else ;2262 }2263 function traverseChildren(parent, context) {2264 let i = 0;2265 const nodeRemoved = () => {2266 i--;2267 };2268 for (; i < parent.children.length; i++) {2269 const child = parent.children[i];2270 if (isString(child))2271 continue;2272 context.parent = parent;2273 context.childIndex = i;2274 context.onNodeRemoved = nodeRemoved;2275 traverseNode(child, context);2276 }2277 }2278 function traverseNode(node, context) {2279 context.currentNode = node;2280 // apply transform plugins2281 const { nodeTransforms } = context;2282 const exitFns = [];2283 for (let i = 0; i < nodeTransforms.length; i++) {2284 const onExit = nodeTransforms[i](node, context);2285 if (onExit) {2286 if (isArray(onExit)) {2287 exitFns.push(...onExit);2288 }2289 else {2290 exitFns.push(onExit);2291 }2292 }2293 if (!context.currentNode) {2294 // node was removed2295 return;2296 }2297 else {2298 // node may have been replaced2299 node = context.currentNode;2300 }2301 }2302 switch (node.type) {2303 case 3 /* COMMENT */:2304 if (!context.ssr) {2305 // inject import for the Comment symbol, which is needed for creating2306 // comment nodes with `createVNode`2307 context.helper(CREATE_COMMENT);2308 }2309 break;2310 case 5 /* INTERPOLATION */:2311 // no need to traverse, but we need to inject toString helper2312 if (!context.ssr) {2313 context.helper(TO_DISPLAY_STRING);2314 }2315 break;2316 // for container types, further traverse downwards2317 case 9 /* IF */:2318 for (let i = 0; i < node.branches.length; i++) {2319 traverseNode(node.branches[i], context);2320 }2321 break;2322 case 10 /* IF_BRANCH */:2323 case 11 /* FOR */:2324 case 1 /* ELEMENT */:2325 case 0 /* ROOT */:2326 traverseChildren(node, context);2327 break;2328 }2329 // exit transforms2330 context.currentNode = node;2331 let i = exitFns.length;2332 while (i--) {2333 exitFns[i]();2334 }2335 }2336 function createStructuralDirectiveTransform(name, fn) {2337 const matches = isString(name)2338 ? (n) => n === name2339 : (n) => name.test(n);2340 return (node, context) => {2341 if (node.type === 1 /* ELEMENT */) {2342 const { props } = node;2343 // structural directive transforms are not concerned with slots2344 // as they are handled separately in vSlot.ts2345 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2346 return;2347 }2348 const exitFns = [];2349 for (let i = 0; i < props.length; i++) {2350 const prop = props[i];2351 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2352 // structural directives are removed to avoid infinite recursion2353 // also we remove them *before* applying so that it can further2354 // traverse itself in case it moves the node around2355 props.splice(i, 1);2356 i--;2357 const onExit = fn(node, prop, context);2358 if (onExit)2359 exitFns.push(onExit);2360 }2361 }2362 return exitFns;2363 }2364 };2365 }2366 const PURE_ANNOTATION = `/*#__PURE__*/`;2367 function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {2368 const context = {2369 mode,2370 prefixIdentifiers,2371 sourceMap,2372 filename,2373 scopeId,2374 optimizeImports,2375 runtimeGlobalName,2376 runtimeModuleName,2377 ssrRuntimeModuleName,2378 ssr,2379 isTS,2380 inSSR,2381 source: ast.loc.source,2382 code: ``,2383 column: 1,2384 line: 1,2385 offset: 0,2386 indentLevel: 0,2387 pure: false,2388 map: undefined,2389 helper(key) {2390 return `_${helperNameMap[key]}`;2391 },2392 push(code, node) {2393 context.code += code;2394 },2395 indent() {2396 newline(++context.indentLevel);2397 },2398 deindent(withoutNewLine = false) {2399 if (withoutNewLine) {2400 --context.indentLevel;2401 }2402 else {2403 newline(--context.indentLevel);2404 }2405 },2406 newline() {2407 newline(context.indentLevel);2408 }2409 };2410 function newline(n) {2411 context.push('\n' + ` `.repeat(n));2412 }2413 return context;2414 }2415 function generate(ast, options = {}) {2416 const context = createCodegenContext(ast, options);2417 if (options.onContextCreated)2418 options.onContextCreated(context);2419 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2420 const hasHelpers = ast.helpers.length > 0;2421 const useWithBlock = !prefixIdentifiers && mode !== 'module';2422 // preambles2423 // in setup() inline mode, the preamble is generated in a sub context2424 // and returned separately.2425 const preambleContext = context;2426 {2427 genFunctionPreamble(ast, preambleContext);2428 }2429 // enter render function2430 const functionName = ssr ? `ssrRender` : `render`;2431 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2432 const signature = args.join(', ');2433 {2434 push(`function ${functionName}(${signature}) {`);2435 }2436 indent();2437 if (useWithBlock) {2438 push(`with (_ctx) {`);2439 indent();2440 // function mode const declarations should be inside with block2441 // also they should be renamed to avoid collision with user properties2442 if (hasHelpers) {2443 push(`const { ${ast.helpers2444 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2445 .join(', ')} } = _Vue`);2446 push(`\n`);2447 newline();2448 }2449 }2450 // generate asset resolution statements2451 if (ast.components.length) {2452 genAssets(ast.components, 'component', context);2453 if (ast.directives.length || ast.temps > 0) {2454 newline();2455 }2456 }2457 if (ast.directives.length) {2458 genAssets(ast.directives, 'directive', context);2459 if (ast.temps > 0) {2460 newline();2461 }2462 }2463 if (ast.filters && ast.filters.length) {2464 newline();2465 genAssets(ast.filters, 'filter', context);2466 newline();2467 }2468 if (ast.temps > 0) {2469 push(`let `);2470 for (let i = 0; i < ast.temps; i++) {2471 push(`${i > 0 ? `, ` : ``}_temp${i}`);2472 }2473 }2474 if (ast.components.length || ast.directives.length || ast.temps) {2475 push(`\n`);2476 newline();2477 }2478 // generate the VNode tree expression2479 if (!ssr) {2480 push(`return `);2481 }2482 if (ast.codegenNode) {2483 genNode(ast.codegenNode, context);2484 }2485 else {2486 push(`null`);2487 }2488 if (useWithBlock) {2489 deindent();2490 push(`}`);2491 }2492 deindent();2493 push(`}`);2494 return {2495 ast,2496 code: context.code,2497 preamble: ``,2498 // SourceMapGenerator does have toJSON() method but it's not in the types2499 map: context.map ? context.map.toJSON() : undefined2500 };2501 }2502 function genFunctionPreamble(ast, context) {2503 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;2504 const VueBinding = runtimeGlobalName;2505 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2506 // Generate const declaration for helpers2507 // In prefix mode, we place the const declaration at top so it's done2508 // only once; But if we not prefixing, we place the declaration inside the2509 // with block so it doesn't incur the `in` check cost for every helper access.2510 if (ast.helpers.length > 0) {2511 {2512 // "with" mode.2513 // save Vue in a separate variable to avoid collision2514 push(`const _Vue = ${VueBinding}\n`);2515 // in "with" mode, helpers are declared inside the with block to avoid2516 // has check cost, but hoists are lifted out of the function - we need2517 // to provide the helper here.2518 if (ast.hoists.length) {2519 const staticHelpers = [2520 CREATE_VNODE,2521 CREATE_ELEMENT_VNODE,2522 CREATE_COMMENT,2523 CREATE_TEXT,2524 CREATE_STATIC2525 ]2526 .filter(helper => ast.helpers.includes(helper))2527 .map(aliasHelper)2528 .join(', ');2529 push(`const { ${staticHelpers} } = _Vue\n`);2530 }2531 }2532 }2533 genHoists(ast.hoists, context);2534 newline();2535 push(`return `);2536 }2537 function genAssets(assets, type, { helper, push, newline, isTS }) {2538 const resolver = helper(type === 'filter'2539 ? RESOLVE_FILTER2540 : type === 'component'2541 ? RESOLVE_COMPONENT2542 : RESOLVE_DIRECTIVE);2543 for (let i = 0; i < assets.length; i++) {2544 let id = assets[i];2545 // potential component implicit self-reference inferred from SFC filename2546 const maybeSelfReference = id.endsWith('__self');2547 if (maybeSelfReference) {2548 id = id.slice(0, -6);2549 }2550 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);2551 if (i < assets.length - 1) {2552 newline();2553 }2554 }2555 }2556 function genHoists(hoists, context) {2557 if (!hoists.length) {2558 return;2559 }2560 context.pure = true;2561 const { push, newline, helper, scopeId, mode } = context;2562 newline();2563 for (let i = 0; i < hoists.length; i++) {2564 const exp = hoists[i];2565 if (exp) {2566 push(`const _hoisted_${i + 1} = ${``}`);2567 genNode(exp, context);2568 newline();2569 }2570 }2571 context.pure = false;2572 }2573 function isText$1(n) {2574 return (isString(n) ||2575 n.type === 4 /* SIMPLE_EXPRESSION */ ||2576 n.type === 2 /* TEXT */ ||2577 n.type === 5 /* INTERPOLATION */ ||2578 n.type === 8 /* COMPOUND_EXPRESSION */);2579 }2580 function genNodeListAsArray(nodes, context) {2581 const multilines = nodes.length > 3 ||2582 (nodes.some(n => isArray(n) || !isText$1(n)));2583 context.push(`[`);2584 multilines && context.indent();2585 genNodeList(nodes, context, multilines);2586 multilines && context.deindent();2587 context.push(`]`);2588 }2589 function genNodeList(nodes, context, multilines = false, comma = true) {2590 const { push, newline } = context;2591 for (let i = 0; i < nodes.length; i++) {2592 const node = nodes[i];2593 if (isString(node)) {2594 push(node);2595 }2596 else if (isArray(node)) {2597 genNodeListAsArray(node, context);2598 }2599 else {2600 genNode(node, context);2601 }2602 if (i < nodes.length - 1) {2603 if (multilines) {2604 comma && push(',');2605 newline();2606 }2607 else {2608 comma && push(', ');2609 }2610 }2611 }2612 }2613 function genNode(node, context) {2614 if (isString(node)) {2615 context.push(node);2616 return;2617 }2618 if (isSymbol(node)) {2619 context.push(context.helper(node));2620 return;2621 }2622 switch (node.type) {2623 case 1 /* ELEMENT */:2624 case 9 /* IF */:2625 case 11 /* FOR */:2626 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2627 `Apply appropriate transforms first.`);2628 genNode(node.codegenNode, context);2629 break;2630 case 2 /* TEXT */:2631 genText(node, context);2632 break;2633 case 4 /* SIMPLE_EXPRESSION */:2634 genExpression(node, context);2635 break;2636 case 5 /* INTERPOLATION */:2637 genInterpolation(node, context);2638 break;2639 case 12 /* TEXT_CALL */:2640 genNode(node.codegenNode, context);2641 break;2642 case 8 /* COMPOUND_EXPRESSION */:2643 genCompoundExpression(node, context);2644 break;2645 case 3 /* COMMENT */:2646 genComment(node, context);2647 break;2648 case 13 /* VNODE_CALL */:2649 genVNodeCall(node, context);2650 break;2651 case 14 /* JS_CALL_EXPRESSION */:2652 genCallExpression(node, context);2653 break;2654 case 15 /* JS_OBJECT_EXPRESSION */:2655 genObjectExpression(node, context);2656 break;2657 case 17 /* JS_ARRAY_EXPRESSION */:2658 genArrayExpression(node, context);2659 break;2660 case 18 /* JS_FUNCTION_EXPRESSION */:2661 genFunctionExpression(node, context);2662 break;2663 case 19 /* JS_CONDITIONAL_EXPRESSION */:2664 genConditionalExpression(node, context);2665 break;2666 case 20 /* JS_CACHE_EXPRESSION */:2667 genCacheExpression(node, context);2668 break;2669 case 21 /* JS_BLOCK_STATEMENT */:2670 genNodeList(node.body, context, true, false);2671 break;2672 // SSR only types2673 case 22 /* JS_TEMPLATE_LITERAL */:2674 break;2675 case 23 /* JS_IF_STATEMENT */:2676 break;2677 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2678 break;2679 case 25 /* JS_SEQUENCE_EXPRESSION */:2680 break;2681 case 26 /* JS_RETURN_STATEMENT */:2682 break;2683 /* istanbul ignore next */2684 case 10 /* IF_BRANCH */:2685 // noop2686 break;2687 default:2688 {2689 assert(false, `unhandled codegen node type: ${node.type}`);2690 // make sure we exhaust all possible types2691 const exhaustiveCheck = node;2692 return exhaustiveCheck;2693 }2694 }2695 }2696 function genText(node, context) {2697 context.push(JSON.stringify(node.content), node);2698 }2699 function genExpression(node, context) {2700 const { content, isStatic } = node;2701 context.push(isStatic ? JSON.stringify(content) : content, node);2702 }2703 function genInterpolation(node, context) {2704 const { push, helper, pure } = context;2705 if (pure)2706 push(PURE_ANNOTATION);2707 push(`${helper(TO_DISPLAY_STRING)}(`);2708 genNode(node.content, context);2709 push(`)`);2710 }2711 function genCompoundExpression(node, context) {2712 for (let i = 0; i < node.children.length; i++) {2713 const child = node.children[i];2714 if (isString(child)) {2715 context.push(child);2716 }2717 else {2718 genNode(child, context);2719 }2720 }2721 }2722 function genExpressionAsPropertyKey(node, context) {2723 const { push } = context;2724 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2725 push(`[`);2726 genCompoundExpression(node, context);2727 push(`]`);2728 }2729 else if (node.isStatic) {2730 // only quote keys if necessary2731 const text = isSimpleIdentifier(node.content)2732 ? node.content2733 : JSON.stringify(node.content);2734 push(text, node);2735 }2736 else {2737 push(`[${node.content}]`, node);2738 }2739 }2740 function genComment(node, context) {2741 const { push, helper, pure } = context;2742 if (pure) {2743 push(PURE_ANNOTATION);2744 }2745 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2746 }2747 function genVNodeCall(node, context) {2748 const { push, helper, pure } = context;2749 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;2750 if (directives) {2751 push(helper(WITH_DIRECTIVES) + `(`);2752 }2753 if (isBlock) {2754 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);2755 }2756 if (pure) {2757 push(PURE_ANNOTATION);2758 }2759 const callHelper = isBlock2760 ? getVNodeBlockHelper(context.inSSR, isComponent)2761 : getVNodeHelper(context.inSSR, isComponent);2762 push(helper(callHelper) + `(`, node);2763 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2764 push(`)`);2765 if (isBlock) {2766 push(`)`);2767 }2768 if (directives) {2769 push(`, `);2770 genNode(directives, context);2771 push(`)`);2772 }2773 }2774 function genNullableArgs(args) {2775 let i = args.length;2776 while (i--) {2777 if (args[i] != null)2778 break;2779 }2780 return args.slice(0, i + 1).map(arg => arg || `null`);2781 }2782 // JavaScript2783 function genCallExpression(node, context) {2784 const { push, helper, pure } = context;2785 const callee = isString(node.callee) ? node.callee : helper(node.callee);2786 if (pure) {2787 push(PURE_ANNOTATION);2788 }2789 push(callee + `(`, node);2790 genNodeList(node.arguments, context);2791 push(`)`);2792 }2793 function genObjectExpression(node, context) {2794 const { push, indent, deindent, newline } = context;2795 const { properties } = node;2796 if (!properties.length) {2797 push(`{}`, node);2798 return;2799 }2800 const multilines = properties.length > 1 ||2801 (properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2802 push(multilines ? `{` : `{ `);2803 multilines && indent();2804 for (let i = 0; i < properties.length; i++) {2805 const { key, value } = properties[i];2806 // key2807 genExpressionAsPropertyKey(key, context);2808 push(`: `);2809 // value2810 genNode(value, context);2811 if (i < properties.length - 1) {2812 // will only reach this if it's multilines2813 push(`,`);2814 newline();2815 }2816 }2817 multilines && deindent();2818 push(multilines ? `}` : ` }`);2819 }2820 function genArrayExpression(node, context) {2821 genNodeListAsArray(node.elements, context);2822 }2823 function genFunctionExpression(node, context) {2824 const { push, indent, deindent } = context;2825 const { params, returns, body, newline, isSlot } = node;2826 if (isSlot) {2827 // wrap slot functions with owner context2828 push(`_${helperNameMap[WITH_CTX]}(`);2829 }2830 push(`(`, node);2831 if (isArray(params)) {2832 genNodeList(params, context);2833 }2834 else if (params) {2835 genNode(params, context);2836 }2837 push(`) => `);2838 if (newline || body) {2839 push(`{`);2840 indent();2841 }2842 if (returns) {2843 if (newline) {2844 push(`return `);2845 }2846 if (isArray(returns)) {2847 genNodeListAsArray(returns, context);2848 }2849 else {2850 genNode(returns, context);2851 }2852 }2853 else if (body) {2854 genNode(body, context);2855 }2856 if (newline || body) {2857 deindent();2858 push(`}`);2859 }2860 if (isSlot) {2861 if (node.isNonScopedSlot) {2862 push(`, undefined, true`);2863 }2864 push(`)`);2865 }2866 }2867 function genConditionalExpression(node, context) {2868 const { test, consequent, alternate, newline: needNewline } = node;2869 const { push, indent, deindent, newline } = context;2870 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2871 const needsParens = !isSimpleIdentifier(test.content);2872 needsParens && push(`(`);2873 genExpression(test, context);2874 needsParens && push(`)`);2875 }2876 else {2877 push(`(`);2878 genNode(test, context);2879 push(`)`);2880 }2881 needNewline && indent();2882 context.indentLevel++;2883 needNewline || push(` `);2884 push(`? `);2885 genNode(consequent, context);2886 context.indentLevel--;2887 needNewline && newline();2888 needNewline || push(` `);2889 push(`: `);2890 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2891 if (!isNested) {2892 context.indentLevel++;2893 }2894 genNode(alternate, context);2895 if (!isNested) {2896 context.indentLevel--;2897 }2898 needNewline && deindent(true /* without newline */);2899 }2900 function genCacheExpression(node, context) {2901 const { push, helper, indent, deindent, newline } = context;2902 push(`_cache[${node.index}] || (`);2903 if (node.isVNode) {2904 indent();2905 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2906 newline();2907 }2908 push(`_cache[${node.index}] = `);2909 genNode(node.value, context);2910 if (node.isVNode) {2911 push(`,`);2912 newline();2913 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2914 newline();2915 push(`_cache[${node.index}]`);2916 deindent();2917 }2918 push(`)`);2919 }2920 function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {2921 {2922 return;2923 }2924 }2925 function isReferencedIdentifier(id, parent, parentStack) {2926 {2927 return false;2928 }2929 }2930 function isInDestructureAssignment(parent, parentStack) {2931 if (parent &&2932 (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {2933 let i = parentStack.length;2934 while (i--) {2935 const p = parentStack[i];2936 if (p.type === 'AssignmentExpression') {2937 return true;2938 }2939 else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {2940 break;2941 }2942 }2943 }2944 return false;2945 }2946 function walkFunctionParams(node, onIdent) {2947 for (const p of node.params) {2948 for (const id of extractIdentifiers(p)) {2949 onIdent(id);2950 }2951 }2952 }2953 function walkBlockDeclarations(block, onIdent) {2954 for (const stmt of block.body) {2955 if (stmt.type === 'VariableDeclaration') {2956 if (stmt.declare)2957 continue;2958 for (const decl of stmt.declarations) {2959 for (const id of extractIdentifiers(decl.id)) {2960 onIdent(id);2961 }2962 }2963 }2964 else if (stmt.type === 'FunctionDeclaration' ||2965 stmt.type === 'ClassDeclaration') {2966 if (stmt.declare || !stmt.id)2967 continue;2968 onIdent(stmt.id);2969 }2970 }2971 }2972 function extractIdentifiers(param, nodes = []) {2973 switch (param.type) {2974 case 'Identifier':2975 nodes.push(param);2976 break;2977 case 'MemberExpression':2978 let object = param;2979 while (object.type === 'MemberExpression') {2980 object = object.object;2981 }2982 nodes.push(object);2983 break;2984 case 'ObjectPattern':2985 for (const prop of param.properties) {2986 if (prop.type === 'RestElement') {2987 extractIdentifiers(prop.argument, nodes);2988 }2989 else {2990 extractIdentifiers(prop.value, nodes);2991 }2992 }2993 break;2994 case 'ArrayPattern':2995 param.elements.forEach(element => {2996 if (element)2997 extractIdentifiers(element, nodes);2998 });2999 break;3000 case 'RestElement':3001 extractIdentifiers(param.argument, nodes);3002 break;3003 case 'AssignmentPattern':3004 extractIdentifiers(param.left, nodes);3005 break;3006 }3007 return nodes;3008 }3009 const isFunctionType = (node) => {3010 return /Function(?:Expression|Declaration)$|Method$/.test(node.type);3011 };3012 const isStaticProperty = (node) => node &&3013 (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&3014 !node.computed;3015 const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;3016 // these keywords should not appear inside expressions, but operators like3017 // typeof, instanceof and in are allowed3018 const prohibitedKeywordRE = new RegExp('\\b' +3019 ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +3020 'super,throw,while,yield,delete,export,import,return,switch,default,' +3021 'extends,finally,continue,debugger,function,arguments,typeof,void')3022 .split(',')3023 .join('\\b|\\b') +3024 '\\b');3025 // strip strings in expressions3026 const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;3027 /**3028 * Validate a non-prefixed expression.3029 * This is only called when using the in-browser runtime compiler since it3030 * doesn't prefix expressions.3031 */3032 function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) {3033 const exp = node.content;3034 // empty expressions are validated per-directive since some directives3035 // do allow empty expressions.3036 if (!exp.trim()) {3037 return;3038 }3039 try {3040 new Function(asRawStatements3041 ? ` ${exp} `3042 : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`);3043 }3044 catch (e) {3045 let message = e.message;3046 const keywordMatch = exp3047 .replace(stripStringRE, '')3048 .match(prohibitedKeywordRE);3049 if (keywordMatch) {3050 message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`;3051 }3052 context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message));3053 }3054 }3055 const transformExpression = (node, context) => {3056 if (node.type === 5 /* INTERPOLATION */) {3057 node.content = processExpression(node.content, context);3058 }3059 else if (node.type === 1 /* ELEMENT */) {3060 // handle directives on element3061 for (let i = 0; i < node.props.length; i++) {3062 const dir = node.props[i];3063 // do not process for v-on & v-for since they are special handled3064 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {3065 const exp = dir.exp;3066 const arg = dir.arg;3067 // do not process exp if this is v-on:arg - we need special handling3068 // for wrapping inline statements.3069 if (exp &&3070 exp.type === 4 /* SIMPLE_EXPRESSION */ &&3071 !(dir.name === 'on' && arg)) {3072 dir.exp = processExpression(exp, context, 3073 // slot args must be processed as function params3074 dir.name === 'slot');3075 }3076 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {3077 dir.arg = processExpression(arg, context);3078 }3079 }3080 }3081 }3082 };3083 // Important: since this function uses Node.js only dependencies, it should3084 // always be used with a leading !true check so that it can be3085 // tree-shaken from the browser build.3086 function processExpression(node, context, 3087 // some expressions like v-slot props & v-for aliases should be parsed as3088 // function params3089 asParams = false, 3090 // v-on handler values may contain multiple statements3091 asRawStatements = false, localVars = Object.create(context.identifiers)) {3092 {3093 {3094 // simple in-browser validation (same logic in 2.x)3095 validateBrowserExpression(node, context, asParams, asRawStatements);3096 }3097 return node;3098 }3099 }3100 const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {3101 return processIf(node, dir, context, (ifNode, branch, isRoot) => {3102 // #1587: We need to dynamically increment the key based on the current3103 // node's sibling nodes, since chained v-if/else branches are3104 // rendered at the same depth3105 const siblings = context.parent.children;3106 let i = siblings.indexOf(ifNode);3107 let key = 0;3108 while (i-- >= 0) {3109 const sibling = siblings[i];3110 if (sibling && sibling.type === 9 /* IF */) {3111 key += sibling.branches.length;3112 }3113 }3114 // Exit callback. Complete the codegenNode when all children have been3115 // transformed.3116 return () => {3117 if (isRoot) {3118 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);3119 }3120 else {3121 // attach this branch's codegen node to the v-if root.3122 const parentCondition = getParentCondition(ifNode.codegenNode);3123 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);3124 }3125 };3126 });3127 });3128 // target-agnostic transform used for both Client and SSR3129 function processIf(node, dir, context, processCodegen) {3130 if (dir.name !== 'else' &&3131 (!dir.exp || !dir.exp.content.trim())) {3132 const loc = dir.exp ? dir.exp.loc : node.loc;3133 context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc));3134 dir.exp = createSimpleExpression(`true`, false, loc);3135 }3136 if (dir.exp) {3137 validateBrowserExpression(dir.exp, context);3138 }3139 if (dir.name === 'if') {3140 const branch = createIfBranch(node, dir);3141 const ifNode = {3142 type: 9 /* IF */,3143 loc: node.loc,3144 branches: [branch]3145 };3146 context.replaceNode(ifNode);3147 if (processCodegen) {3148 return processCodegen(ifNode, branch, true);3149 }3150 }3151 else {3152 // locate the adjacent v-if3153 const siblings = context.parent.children;3154 const comments = [];3155 let i = siblings.indexOf(node);3156 while (i-- >= -1) {3157 const sibling = siblings[i];3158 if (sibling && sibling.type === 3 /* COMMENT */) {3159 context.removeNode(sibling);3160 comments.unshift(sibling);3161 continue;3162 }3163 if (sibling &&3164 sibling.type === 2 /* TEXT */ &&3165 !sibling.content.trim().length) {3166 context.removeNode(sibling);3167 continue;3168 }3169 if (sibling && sibling.type === 9 /* IF */) {3170 // Check if v-else was followed by v-else-if3171 if (dir.name === 'else-if' &&3172 sibling.branches[sibling.branches.length - 1].condition === undefined) {3173 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3174 }3175 // move the node to the if node's branches3176 context.removeNode();3177 const branch = createIfBranch(node, dir);3178 if (comments.length &&3179 // #3619 ignore comments if the v-if is direct child of <transition>3180 !(context.parent &&3181 context.parent.type === 1 /* ELEMENT */ &&3182 isBuiltInType(context.parent.tag, 'transition'))) {3183 branch.children = [...comments, ...branch.children];3184 }3185 // check if user is forcing same key on different branches3186 {3187 const key = branch.userKey;3188 if (key) {3189 sibling.branches.forEach(({ userKey }) => {3190 if (isSameKey(userKey, key)) {3191 context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc));3192 }3193 });3194 }3195 }3196 sibling.branches.push(branch);3197 const onExit = processCodegen && processCodegen(sibling, branch, false);3198 // since the branch was removed, it will not be traversed.3199 // make sure to traverse here.3200 traverseNode(branch, context);3201 // call on exit3202 if (onExit)3203 onExit();3204 // make sure to reset currentNode after traversal to indicate this3205 // node has been removed.3206 context.currentNode = null;3207 }3208 else {3209 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3210 }3211 break;3212 }3213 }3214 }3215 function createIfBranch(node, dir) {3216 return {3217 type: 10 /* IF_BRANCH */,3218 loc: node.loc,3219 condition: dir.name === 'else' ? undefined : dir.exp,3220 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')3221 ? node.children3222 : [node],3223 userKey: findProp(node, `key`)3224 };3225 }3226 function createCodegenNodeForBranch(branch, keyIndex, context) {3227 if (branch.condition) {3228 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 3229 // make sure to pass in asBlock: true so that the comment node call3230 // closes the current block.3231 createCallExpression(context.helper(CREATE_COMMENT), [3232 '"v-if"' ,3233 'true'3234 ]));3235 }3236 else {3237 return createChildrenCodegenNode(branch, keyIndex, context);3238 }3239 }3240 function createChildrenCodegenNode(branch, keyIndex, context) {3241 const { helper } = context;3242 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));3243 const { children } = branch;3244 const firstChild = children[0];3245 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;3246 if (needFragmentWrapper) {3247 if (children.length === 1 && firstChild.type === 11 /* FOR */) {3248 // optimize away nested fragments when child is a ForNode3249 const vnodeCall = firstChild.codegenNode;3250 injectProp(vnodeCall, keyProperty, context);3251 return vnodeCall;3252 }3253 else {3254 let patchFlag = 64 /* STABLE_FRAGMENT */;3255 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];3256 // check if the fragment actually contains a single valid child with3257 // the rest being comments3258 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {3259 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;3260 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;3261 }3262 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, false, false /* isComponent */, branch.loc);3263 }3264 }3265 else {3266 const ret = firstChild.codegenNode;3267 const vnodeCall = getMemoedVNodeCall(ret);3268 // Change createVNode to createBlock.3269 if (vnodeCall.type === 13 /* VNODE_CALL */) {3270 makeBlock(vnodeCall, context);3271 }3272 // inject branch key3273 injectProp(vnodeCall, keyProperty, context);3274 return ret;3275 }3276 }3277 function isSameKey(a, b) {3278 if (!a || a.type !== b.type) {3279 return false;3280 }3281 if (a.type === 6 /* ATTRIBUTE */) {3282 if (a.value.content !== b.value.content) {3283 return false;3284 }3285 }3286 else {3287 // directive3288 const exp = a.exp;3289 const branchExp = b.exp;3290 if (exp.type !== branchExp.type) {3291 return false;3292 }3293 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||3294 exp.isStatic !== branchExp.isStatic ||3295 exp.content !== branchExp.content) {3296 return false;3297 }3298 }3299 return true;3300 }3301 function getParentCondition(node) {3302 while (true) {3303 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3304 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3305 node = node.alternate;3306 }3307 else {3308 return node;3309 }3310 }3311 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {3312 node = node.value;3313 }3314 }3315 }3316 const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {3317 const { helper, removeHelper } = context;3318 return processFor(node, dir, context, forNode => {3319 // create the loop render function expression now, and add the3320 // iterator on exit after all children have been traversed3321 const renderExp = createCallExpression(helper(RENDER_LIST), [3322 forNode.source3323 ]);3324 const memo = findDir(node, 'memo');3325 const keyProp = findProp(node, `key`);3326 const keyExp = keyProp &&3327 (keyProp.type === 6 /* ATTRIBUTE */3328 ? createSimpleExpression(keyProp.value.content, true)3329 : keyProp.exp);3330 const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;3331 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3332 forNode.source.constType > 0 /* NOT_CONSTANT */;3333 const fragmentFlag = isStableFragment3334 ? 64 /* STABLE_FRAGMENT */3335 : keyProp3336 ? 128 /* KEYED_FRAGMENT */3337 : 256 /* UNKEYED_FRAGMENT */;3338 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3339 (` /* ${PatchFlagNames[fragmentFlag]} */` ), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);3340 return () => {3341 // finish the codegen now that all children have been traversed3342 let childBlock;3343 const isTemplate = isTemplateNode(node);3344 const { children } = forNode;3345 // check <template v-for> key placement3346 if (isTemplate) {3347 node.children.some(c => {3348 if (c.type === 1 /* ELEMENT */) {3349 const key = findProp(c, 'key');3350 if (key) {3351 context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3352 return true;3353 }3354 }3355 });3356 }3357 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3358 const slotOutlet = isSlotOutlet(node)3359 ? node3360 : isTemplate &&3361 node.children.length === 1 &&3362 isSlotOutlet(node.children[0])3363 ? node.children[0] // api-extractor somehow fails to infer this3364 : null;3365 if (slotOutlet) {3366 // <slot v-for="..."> or <template v-for="..."><slot/></template>3367 childBlock = slotOutlet.codegenNode;3368 if (isTemplate && keyProperty) {3369 // <template v-for="..." :key="..."><slot/></template>3370 // we need to inject the key to the renderSlot() call.3371 // the props for renderSlot is passed as the 3rd argument.3372 injectProp(childBlock, keyProperty, context);3373 }3374 }3375 else if (needFragmentWrapper) {3376 // <template v-for="..."> with text or multi-elements3377 // should generate a fragment block for each loop3378 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3379 (` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`3380 ), undefined, undefined, true, undefined, false /* isComponent */);3381 }3382 else {3383 // Normal element v-for. Directly use the child's codegenNode3384 // but mark it as a block.3385 childBlock = children[0]3386 .codegenNode;3387 if (isTemplate && keyProperty) {3388 injectProp(childBlock, keyProperty, context);3389 }3390 if (childBlock.isBlock !== !isStableFragment) {3391 if (childBlock.isBlock) {3392 // switch from block to vnode3393 removeHelper(OPEN_BLOCK);3394 removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3395 }3396 else {3397 // switch from vnode to block3398 removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));3399 }3400 }3401 childBlock.isBlock = !isStableFragment;3402 if (childBlock.isBlock) {3403 helper(OPEN_BLOCK);3404 helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3405 }3406 else {3407 helper(getVNodeHelper(context.inSSR, childBlock.isComponent));3408 }3409 }3410 if (memo) {3411 const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [3412 createSimpleExpression(`_cached`)3413 ]));3414 loop.body = createBlockStatement([3415 createCompoundExpression([`const _memo = (`, memo.exp, `)`]),3416 createCompoundExpression([3417 `if (_cached`,3418 ...(keyExp ? [` && _cached.key === `, keyExp] : []),3419 ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`3420 ]),3421 createCompoundExpression([`const _item = `, childBlock]),3422 createSimpleExpression(`_item.memo = _memo`),3423 createSimpleExpression(`return _item`)3424 ]);3425 renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));3426 }3427 else {3428 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3429 }3430 };3431 });3432 });3433 // target-agnostic transform used for both Client and SSR3434 function processFor(node, dir, context, processCodegen) {3435 if (!dir.exp) {3436 context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3437 return;3438 }3439 const parseResult = parseForExpression(3440 // can only be simple expression because vFor transform is applied3441 // before expression transform.3442 dir.exp, context);3443 if (!parseResult) {3444 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3445 return;3446 }3447 const { addIdentifiers, removeIdentifiers, scopes } = context;3448 const { source, value, key, index } = parseResult;3449 const forNode = {3450 type: 11 /* FOR */,3451 loc: dir.loc,3452 source,3453 valueAlias: value,3454 keyAlias: key,3455 objectIndexAlias: index,3456 parseResult,3457 children: isTemplateNode(node) ? node.children : [node]3458 };3459 context.replaceNode(forNode);3460 // bookkeeping3461 scopes.vFor++;3462 const onExit = processCodegen && processCodegen(forNode);3463 return () => {3464 scopes.vFor--;3465 if (onExit)3466 onExit();3467 };3468 }3469 const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3470 // This regex doesn't cover the case if key or index aliases have destructuring,3471 // but those do not make sense in the first place, so this works in practice.3472 const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3473 const stripParensRE = /^\(|\)$/g;3474 function parseForExpression(input, context) {3475 const loc = input.loc;3476 const exp = input.content;3477 const inMatch = exp.match(forAliasRE);3478 if (!inMatch)3479 return;3480 const [, LHS, RHS] = inMatch;3481 const result = {3482 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3483 value: undefined,3484 key: undefined,3485 index: undefined3486 };3487 {3488 validateBrowserExpression(result.source, context);3489 }3490 let valueContent = LHS.trim().replace(stripParensRE, '').trim();3491 const trimmedOffset = LHS.indexOf(valueContent);3492 const iteratorMatch = valueContent.match(forIteratorRE);3493 if (iteratorMatch) {3494 valueContent = valueContent.replace(forIteratorRE, '').trim();3495 const keyContent = iteratorMatch[1].trim();3496 let keyOffset;3497 if (keyContent) {3498 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3499 result.key = createAliasExpression(loc, keyContent, keyOffset);3500 {3501 validateBrowserExpression(result.key, context, true);3502 }3503 }3504 if (iteratorMatch[2]) {3505 const indexContent = iteratorMatch[2].trim();3506 if (indexContent) {3507 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3508 ? keyOffset + keyContent.length3509 : trimmedOffset + valueContent.length));3510 {3511 validateBrowserExpression(result.index, context, true);3512 }3513 }3514 }3515 }3516 if (valueContent) {3517 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3518 {3519 validateBrowserExpression(result.value, context, true);3520 }3521 }3522 return result;3523 }3524 function createAliasExpression(range, content, offset) {3525 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3526 }3527 function createForLoopParams({ value, key, index }, memoArgs = []) {3528 return createParamsList([value, key, index, ...memoArgs]);3529 }3530 function createParamsList(args) {3531 let i = args.length;3532 while (i--) {3533 if (args[i])3534 break;3535 }3536 return args3537 .slice(0, i + 1)3538 .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));3539 }3540 const defaultFallback = createSimpleExpression(`undefined`, false);3541 // A NodeTransform that:3542 // 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3543 // by transformExpression. This is only applied in non-browser builds with3544 // { prefixIdentifiers: true }.3545 // 2. Track v-slot depths so that we know a slot is inside another slot.3546 // Note the exit callback is executed before buildSlots() on the same node,3547 // so only nested slots see positive numbers.3548 const trackSlotScopes = (node, context) => {3549 if (node.type === 1 /* ELEMENT */ &&3550 (node.tagType === 1 /* COMPONENT */ ||3551 node.tagType === 3 /* TEMPLATE */)) {3552 // We are only checking non-empty v-slot here3553 // since we only care about slots that introduce scope variables.3554 const vSlot = findDir(node, 'slot');3555 if (vSlot) {3556 vSlot.exp;3557 context.scopes.vSlot++;3558 return () => {3559 context.scopes.vSlot--;3560 };3561 }3562 }3563 };3564 // A NodeTransform that tracks scope identifiers for scoped slots with v-for.3565 // This transform is only applied in non-browser builds with { prefixIdentifiers: true }3566 const trackVForSlotScopes = (node, context) => {3567 let vFor;3568 if (isTemplateNode(node) &&3569 node.props.some(isVSlot) &&3570 (vFor = findDir(node, 'for'))) {3571 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3572 if (result) {3573 const { value, key, index } = result;3574 const { addIdentifiers, removeIdentifiers } = context;3575 value && addIdentifiers(value);3576 key && addIdentifiers(key);3577 index && addIdentifiers(index);3578 return () => {3579 value && removeIdentifiers(value);3580 key && removeIdentifiers(key);3581 index && removeIdentifiers(index);3582 };3583 }3584 }3585 };3586 const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3587 // Instead of being a DirectiveTransform, v-slot processing is called during3588 // transformElement to build the slots object for a component.3589 function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3590 context.helper(WITH_CTX);3591 const { children, loc } = node;3592 const slotsProperties = [];3593 const dynamicSlots = [];3594 // If the slot is inside a v-for or another v-slot, force it to be dynamic3595 // since it likely uses a scope variable.3596 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3597 // 1. Check for slot with slotProps on component itself.3598 // <Comp v-slot="{ prop }"/>3599 const onComponentSlot = findDir(node, 'slot', true);3600 if (onComponentSlot) {3601 const { arg, exp } = onComponentSlot;3602 if (arg && !isStaticExp(arg)) {3603 hasDynamicSlots = true;3604 }3605 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));3606 }3607 // 2. Iterate through children and check for template slots3608 // <template v-slot:foo="{ prop }">3609 let hasTemplateSlots = false;3610 let hasNamedDefaultSlot = false;3611 const implicitDefaultChildren = [];3612 const seenSlotNames = new Set();3613 for (let i = 0; i < children.length; i++) {3614 const slotElement = children[i];3615 let slotDir;3616 if (!isTemplateNode(slotElement) ||3617 !(slotDir = findDir(slotElement, 'slot', true))) {3618 // not a <template v-slot>, skip.3619 if (slotElement.type !== 3 /* COMMENT */) {3620 implicitDefaultChildren.push(slotElement);3621 }3622 continue;3623 }3624 if (onComponentSlot) {3625 // already has on-component slot - this is incorrect usage.3626 context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3627 break;3628 }3629 hasTemplateSlots = true;3630 const { children: slotChildren, loc: slotLoc } = slotElement;3631 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3632 // check if name is dynamic.3633 let staticSlotName;3634 if (isStaticExp(slotName)) {3635 staticSlotName = slotName ? slotName.content : `default`;3636 }3637 else {3638 hasDynamicSlots = true;3639 }3640 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3641 // check if this slot is conditional (v-if/v-for)3642 let vIf;3643 let vElse;3644 let vFor;3645 if ((vIf = findDir(slotElement, 'if'))) {3646 hasDynamicSlots = true;3647 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3648 }3649 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3650 // find adjacent v-if3651 let j = i;3652 let prev;3653 while (j--) {3654 prev = children[j];3655 if (prev.type !== 3 /* COMMENT */) {3656 break;3657 }3658 }3659 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3660 // remove node3661 children.splice(i, 1);3662 i--;3663 // attach this slot to previous conditional3664 let conditional = dynamicSlots[dynamicSlots.length - 1];3665 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3666 conditional = conditional.alternate;3667 }3668 conditional.alternate = vElse.exp3669 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3670 : buildDynamicSlot(slotName, slotFunction);3671 }3672 else {3673 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3674 }3675 }3676 else if ((vFor = findDir(slotElement, 'for'))) {3677 hasDynamicSlots = true;3678 const parseResult = vFor.parseResult ||3679 parseForExpression(vFor.exp, context);3680 if (parseResult) {3681 // Render the dynamic slots as an array and add it to the createSlot()3682 // args. The runtime knows how to handle it appropriately.3683 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3684 parseResult.source,3685 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3686 ]));3687 }3688 else {3689 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3690 }3691 }3692 else {3693 // check duplicate static names3694 if (staticSlotName) {3695 if (seenSlotNames.has(staticSlotName)) {3696 context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3697 continue;3698 }3699 seenSlotNames.add(staticSlotName);3700 if (staticSlotName === 'default') {3701 hasNamedDefaultSlot = true;3702 }3703 }3704 slotsProperties.push(createObjectProperty(slotName, slotFunction));3705 }3706 }3707 if (!onComponentSlot) {3708 const buildDefaultSlotProperty = (props, children) => {3709 const fn = buildSlotFn(props, children, loc);3710 if (context.compatConfig) {3711 fn.isNonScopedSlot = true;3712 }3713 return createObjectProperty(`default`, fn);3714 };3715 if (!hasTemplateSlots) {3716 // implicit default slot (on component)3717 slotsProperties.push(buildDefaultSlotProperty(undefined, children));3718 }3719 else if (implicitDefaultChildren.length &&3720 // #37663721 // with whitespace: 'preserve', whitespaces between slots will end up in3722 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.3723 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {3724 // implicit default slot (mixed with named slots)3725 if (hasNamedDefaultSlot) {3726 context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));3727 }3728 else {3729 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));3730 }3731 }3732 }3733 const slotFlag = hasDynamicSlots3734 ? 2 /* DYNAMIC */3735 : hasForwardedSlots(node.children)3736 ? 3 /* FORWARDED */3737 : 1 /* STABLE */;3738 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 3739 // 2 = compiled but dynamic = can skip normalization, but must run diff3740 // 1 = compiled and static = can skip normalization AND diff as optimized3741 createSimpleExpression(slotFlag + (` /* ${slotFlagsText[slotFlag]} */` ), false))), loc);3742 if (dynamicSlots.length) {3743 slots = createCallExpression(context.helper(CREATE_SLOTS), [3744 slots,3745 createArrayExpression(dynamicSlots)3746 ]);3747 }3748 return {3749 slots,3750 hasDynamicSlots3751 };3752 }3753 function buildDynamicSlot(name, fn) {3754 return createObjectExpression([3755 createObjectProperty(`name`, name),3756 createObjectProperty(`fn`, fn)3757 ]);3758 }3759 function hasForwardedSlots(children) {3760 for (let i = 0; i < children.length; i++) {3761 const child = children[i];3762 switch (child.type) {3763 case 1 /* ELEMENT */:3764 if (child.tagType === 2 /* SLOT */ ||3765 hasForwardedSlots(child.children)) {3766 return true;3767 }3768 break;3769 case 9 /* IF */:3770 if (hasForwardedSlots(child.branches))3771 return true;3772 break;3773 case 10 /* IF_BRANCH */:3774 case 11 /* FOR */:3775 if (hasForwardedSlots(child.children))3776 return true;3777 break;3778 }3779 }3780 return false;3781 }3782 function isNonWhitespaceContent(node) {3783 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)3784 return true;3785 return node.type === 2 /* TEXT */3786 ? !!node.content.trim()3787 : isNonWhitespaceContent(node.content);3788 }3789 // some directive transforms (e.g. v-model) may return a symbol for runtime3790 // import, which should be used instead of a resolveDirective call.3791 const directiveImportMap = new WeakMap();3792 // generate a JavaScript AST for this element's codegen3793 const transformElement = (node, context) => {3794 // perform the work on exit, after all child expressions have been3795 // processed and merged.3796 return function postTransformElement() {3797 node = context.currentNode;3798 if (!(node.type === 1 /* ELEMENT */ &&3799 (node.tagType === 0 /* ELEMENT */ ||3800 node.tagType === 1 /* COMPONENT */))) {3801 return;3802 }3803 const { tag, props } = node;3804 const isComponent = node.tagType === 1 /* COMPONENT */;3805 // The goal of the transform is to create a codegenNode implementing the3806 // VNodeCall interface.3807 let vnodeTag = isComponent3808 ? resolveComponentType(node, context)3809 : `"${tag}"`;3810 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;3811 let vnodeProps;3812 let vnodeChildren;3813 let vnodePatchFlag;3814 let patchFlag = 0;3815 let vnodeDynamicProps;3816 let dynamicPropNames;3817 let vnodeDirectives;3818 let shouldUseBlock = 3819 // dynamic component may resolve to plain elements3820 isDynamicComponent ||3821 vnodeTag === TELEPORT ||3822 vnodeTag === SUSPENSE ||3823 (!isComponent &&3824 // <svg> and <foreignObject> must be forced into blocks so that block3825 // updates inside get proper isSVG flag at runtime. (#639, #643)3826 // This is technically web-specific, but splitting the logic out of core3827 // leads to too much unnecessary complexity.3828 (tag === 'svg' ||3829 tag === 'foreignObject' ||3830 // #938: elements with dynamic keys should be forced into blocks3831 findProp(node, 'key', true)));3832 // props3833 if (props.length > 0) {3834 const propsBuildResult = buildProps(node, context);3835 vnodeProps = propsBuildResult.props;3836 patchFlag = propsBuildResult.patchFlag;3837 dynamicPropNames = propsBuildResult.dynamicPropNames;3838 const directives = propsBuildResult.directives;3839 vnodeDirectives =3840 directives && directives.length3841 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))3842 : undefined;3843 }3844 // children3845 if (node.children.length > 0) {3846 if (vnodeTag === KEEP_ALIVE) {3847 // Although a built-in component, we compile KeepAlive with raw children3848 // instead of slot functions so that it can be used inside Transition3849 // or other Transition-wrapping HOCs.3850 // To ensure correct updates with block optimizations, we need to:3851 // 1. Force keep-alive into a block. This avoids its children being3852 // collected by a parent block.3853 shouldUseBlock = true;3854 // 2. Force keep-alive to always be updated, since it uses raw children.3855 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3856 if (node.children.length > 1) {3857 context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {3858 start: node.children[0].loc.start,3859 end: node.children[node.children.length - 1].loc.end,3860 source: ''3861 }));3862 }3863 }3864 const shouldBuildAsSlots = isComponent &&3865 // Teleport is not a real component and has dedicated runtime handling3866 vnodeTag !== TELEPORT &&3867 // explained above.3868 vnodeTag !== KEEP_ALIVE;3869 if (shouldBuildAsSlots) {3870 const { slots, hasDynamicSlots } = buildSlots(node, context);3871 vnodeChildren = slots;3872 if (hasDynamicSlots) {3873 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3874 }3875 }3876 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {3877 const child = node.children[0];3878 const type = child.type;3879 // check for dynamic text children3880 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||3881 type === 8 /* COMPOUND_EXPRESSION */;3882 if (hasDynamicTextChild &&3883 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {3884 patchFlag |= 1 /* TEXT */;3885 }3886 // pass directly if the only child is a text node3887 // (plain / interpolation / expression)3888 if (hasDynamicTextChild || type === 2 /* TEXT */) {3889 vnodeChildren = child;3890 }3891 else {3892 vnodeChildren = node.children;3893 }3894 }3895 else {3896 vnodeChildren = node.children;3897 }3898 }3899 // patchFlag & dynamicPropNames3900 if (patchFlag !== 0) {3901 {3902 if (patchFlag < 0) {3903 // special flags (negative and mutually exclusive)3904 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;3905 }3906 else {3907 // bitwise flags3908 const flagNames = Object.keys(PatchFlagNames)3909 .map(Number)3910 .filter(n => n > 0 && patchFlag & n)3911 .map(n => PatchFlagNames[n])3912 .join(`, `);3913 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;3914 }3915 }3916 if (dynamicPropNames && dynamicPropNames.length) {3917 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);3918 }3919 }3920 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);3921 };3922 };3923 function resolveComponentType(node, context, ssr = false) {3924 let { tag } = node;3925 // 1. dynamic component3926 const isExplicitDynamic = isComponentTag(tag);3927 const isProp = findProp(node, 'is');3928 if (isProp) {3929 if (isExplicitDynamic ||3930 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {3931 const exp = isProp.type === 6 /* ATTRIBUTE */3932 ? isProp.value && createSimpleExpression(isProp.value.content, true)3933 : isProp.exp;3934 if (exp) {3935 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3936 exp3937 ]);3938 }3939 }3940 else if (isProp.type === 6 /* ATTRIBUTE */ &&3941 isProp.value.content.startsWith('vue:')) {3942 // <button is="vue:xxx">3943 // if not <component>, only is value that starts with "vue:" will be3944 // treated as component by the parse phase and reach here, unless it's3945 // compat mode where all is values are considered components3946 tag = isProp.value.content.slice(4);3947 }3948 }3949 // 1.5 v-is (TODO: Deprecate)3950 const isDir = !isExplicitDynamic && findDir(node, 'is');3951 if (isDir && isDir.exp) {3952 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3953 isDir.exp3954 ]);3955 }3956 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)3957 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);3958 if (builtIn) {3959 // built-ins are simply fallthroughs / have special handling during ssr3960 // so we don't need to import their runtime equivalents3961 if (!ssr)3962 context.helper(builtIn);3963 return builtIn;3964 }3965 // 5. user component (resolve)3966 context.helper(RESOLVE_COMPONENT);3967 context.components.add(tag);3968 return toValidAssetId(tag, `component`);3969 }3970 function buildProps(node, context, props = node.props, ssr = false) {3971 const { tag, loc: elementLoc } = node;3972 const isComponent = node.tagType === 1 /* COMPONENT */;3973 let properties = [];3974 const mergeArgs = [];3975 const runtimeDirectives = [];3976 // patchFlag analysis3977 let patchFlag = 0;3978 let hasRef = false;3979 let hasClassBinding = false;3980 let hasStyleBinding = false;3981 let hasHydrationEventBinding = false;3982 let hasDynamicKeys = false;3983 let hasVnodeHook = false;3984 const dynamicPropNames = [];3985 const analyzePatchFlag = ({ key, value }) => {3986 if (isStaticExp(key)) {3987 const name = key.content;3988 const isEventHandler = isOn(name);3989 if (!isComponent &&3990 isEventHandler &&3991 // omit the flag for click handlers because hydration gives click3992 // dedicated fast path.3993 name.toLowerCase() !== 'onclick' &&3994 // omit v-model handlers3995 name !== 'onUpdate:modelValue' &&3996 // omit onVnodeXXX hooks3997 !isReservedProp(name)) {3998 hasHydrationEventBinding = true;3999 }4000 if (isEventHandler && isReservedProp(name)) {4001 hasVnodeHook = true;4002 }4003 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||4004 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||4005 value.type === 8 /* COMPOUND_EXPRESSION */) &&4006 getConstantType(value, context) > 0)) {4007 // skip if the prop is a cached handler or has constant value4008 return;4009 }4010 if (name === 'ref') {4011 hasRef = true;4012 }4013 else if (name === 'class') {4014 hasClassBinding = true;4015 }4016 else if (name === 'style') {4017 hasStyleBinding = true;4018 }4019 else if (name !== 'key' && !dynamicPropNames.includes(name)) {4020 dynamicPropNames.push(name);4021 }4022 // treat the dynamic class and style binding of the component as dynamic props4023 if (isComponent &&4024 (name === 'class' || name === 'style') &&4025 !dynamicPropNames.includes(name)) {4026 dynamicPropNames.push(name);4027 }4028 }4029 else {4030 hasDynamicKeys = true;4031 }4032 };4033 for (let i = 0; i < props.length; i++) {4034 // static attribute4035 const prop = props[i];4036 if (prop.type === 6 /* ATTRIBUTE */) {4037 const { loc, name, value } = prop;4038 let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);4039 if (name === 'ref') {4040 hasRef = true;4041 }4042 // skip is on <component>, or is="vue:xxx"4043 if (name === 'is' &&4044 (isComponentTag(tag) ||4045 (value && value.content.startsWith('vue:')) ||4046 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {4047 continue;4048 }4049 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));4050 }4051 else {4052 // directives4053 const { name, arg, exp, loc } = prop;4054 const isVBind = name === 'bind';4055 const isVOn = name === 'on';4056 // skip v-slot - it is handled by its dedicated transform.4057 if (name === 'slot') {4058 if (!isComponent) {4059 context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc));4060 }4061 continue;4062 }4063 // skip v-once/v-memo - they are handled by dedicated transforms.4064 if (name === 'once' || name === 'memo') {4065 continue;4066 }4067 // skip v-is and :is on <component>4068 if (name === 'is' ||4069 (isVBind &&4070 isBindKey(arg, 'is') &&4071 (isComponentTag(tag) ||4072 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {4073 continue;4074 }4075 // skip v-on in SSR compilation4076 if (isVOn && ssr) {4077 continue;4078 }4079 // special case for v-bind and v-on with no argument4080 if (!arg && (isVBind || isVOn)) {4081 hasDynamicKeys = true;4082 if (exp) {4083 if (properties.length) {4084 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4085 properties = [];4086 }4087 if (isVBind) {4088 {4089 // 2.x v-bind object order compat4090 {4091 const hasOverridableKeys = mergeArgs.some(arg => {4092 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {4093 return arg.properties.some(({ key }) => {4094 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||4095 !key.isStatic) {4096 return true;4097 }4098 return (key.content !== 'class' &&4099 key.content !== 'style' &&4100 !isOn(key.content));4101 });4102 }4103 else {4104 // dynamic expression4105 return true;4106 }4107 });4108 if (hasOverridableKeys) {4109 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);4110 }4111 }4112 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {4113 mergeArgs.unshift(exp);4114 continue;4115 }4116 }4117 mergeArgs.push(exp);4118 }4119 else {4120 // v-on="obj" -> toHandlers(obj)4121 mergeArgs.push({4122 type: 14 /* JS_CALL_EXPRESSION */,4123 loc,4124 callee: context.helper(TO_HANDLERS),4125 arguments: [exp]4126 });4127 }4128 }4129 else {4130 context.onError(createCompilerError(isVBind4131 ? 34 /* X_V_BIND_NO_EXPRESSION */4132 : 35 /* X_V_ON_NO_EXPRESSION */, loc));4133 }4134 continue;4135 }4136 const directiveTransform = context.directiveTransforms[name];4137 if (directiveTransform) {4138 // has built-in directive transform.4139 const { props, needRuntime } = directiveTransform(prop, node, context);4140 !ssr && props.forEach(analyzePatchFlag);4141 properties.push(...props);4142 if (needRuntime) {4143 runtimeDirectives.push(prop);4144 if (isSymbol(needRuntime)) {4145 directiveImportMap.set(prop, needRuntime);4146 }4147 }4148 }4149 else {4150 // no built-in transform, this is a user custom directive.4151 runtimeDirectives.push(prop);4152 }4153 }4154 if (prop.type === 6 /* ATTRIBUTE */ &&4155 prop.name === 'ref' &&4156 context.scopes.vFor > 0 &&4157 checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {4158 properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));4159 }4160 }4161 let propsExpression = undefined;4162 // has v-bind="object" or v-on="object", wrap with mergeProps4163 if (mergeArgs.length) {4164 if (properties.length) {4165 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4166 }4167 if (mergeArgs.length > 1) {4168 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);4169 }4170 else {4171 // single v-bind with nothing else - no need for a mergeProps call4172 propsExpression = mergeArgs[0];4173 }4174 }4175 else if (properties.length) {4176 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);4177 }4178 // patchFlag analysis4179 if (hasDynamicKeys) {4180 patchFlag |= 16 /* FULL_PROPS */;4181 }4182 else {4183 if (hasClassBinding && !isComponent) {4184 patchFlag |= 2 /* CLASS */;4185 }4186 if (hasStyleBinding && !isComponent) {4187 patchFlag |= 4 /* STYLE */;4188 }4189 if (dynamicPropNames.length) {4190 patchFlag |= 8 /* PROPS */;4191 }4192 if (hasHydrationEventBinding) {4193 patchFlag |= 32 /* HYDRATE_EVENTS */;4194 }4195 }4196 if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&4197 (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {4198 patchFlag |= 512 /* NEED_PATCH */;4199 }4200 // pre-normalize props, SSR is skipped for now4201 if (!context.inSSR && propsExpression) {4202 switch (propsExpression.type) {4203 case 15 /* JS_OBJECT_EXPRESSION */:4204 // means that there is no v-bind,4205 // but still need to deal with dynamic key binding4206 let classKeyIndex = -1;4207 let styleKeyIndex = -1;4208 let hasDynamicKey = false;4209 for (let i = 0; i < propsExpression.properties.length; i++) {4210 const key = propsExpression.properties[i].key;4211 if (isStaticExp(key)) {4212 if (key.content === 'class') {4213 classKeyIndex = i;4214 }4215 else if (key.content === 'style') {4216 styleKeyIndex = i;4217 }4218 }4219 else if (!key.isHandlerKey) {4220 hasDynamicKey = true;4221 }4222 }4223 const classProp = propsExpression.properties[classKeyIndex];4224 const styleProp = propsExpression.properties[styleKeyIndex];4225 // no dynamic key4226 if (!hasDynamicKey) {4227 if (classProp && !isStaticExp(classProp.value)) {4228 classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]);4229 }4230 if (styleProp &&4231 !isStaticExp(styleProp.value) &&4232 // the static style is compiled into an object,4233 // so use `hasStyleBinding` to ensure that it is a dynamic style binding4234 (hasStyleBinding ||4235 // v-bind:style and style both exist,4236 // v-bind:style with static literal object4237 styleProp.value.type === 17 /* JS_ARRAY_EXPRESSION */)) {4238 styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]);4239 }4240 }4241 else {4242 // dynamic key binding, wrap with `normalizeProps`4243 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]);4244 }4245 break;4246 case 14 /* JS_CALL_EXPRESSION */:4247 // mergeProps call, do nothing4248 break;4249 default:4250 // single v-bind4251 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [4252 createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [4253 propsExpression4254 ])4255 ]);4256 break;4257 }4258 }4259 return {4260 props: propsExpression,4261 directives: runtimeDirectives,4262 patchFlag,4263 dynamicPropNames4264 };4265 }4266 // Dedupe props in an object literal.4267 // Literal duplicated attributes would have been warned during the parse phase,4268 // however, it's possible to encounter duplicated `onXXX` handlers with different4269 // modifiers. We also need to merge static and dynamic class / style attributes.4270 // - onXXX handlers / style: merge into array4271 // - class: merge into single expression with concatenation4272 function dedupeProperties(properties) {4273 const knownProps = new Map();4274 const deduped = [];4275 for (let i = 0; i < properties.length; i++) {4276 const prop = properties[i];4277 // dynamic keys are always allowed4278 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) {4279 deduped.push(prop);4280 continue;4281 }4282 const name = prop.key.content;4283 const existing = knownProps.get(name);4284 if (existing) {4285 if (name === 'style' || name === 'class' || isOn(name)) {4286 mergeAsArray(existing, prop);4287 }4288 // unexpected duplicate, should have emitted error during parse4289 }4290 else {4291 knownProps.set(name, prop);4292 deduped.push(prop);4293 }4294 }4295 return deduped;4296 }4297 function mergeAsArray(existing, incoming) {4298 if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) {4299 existing.value.elements.push(incoming.value);4300 }4301 else {4302 existing.value = createArrayExpression([existing.value, incoming.value], existing.loc);4303 }4304 }4305 function buildDirectiveArgs(dir, context) {4306 const dirArgs = [];4307 const runtime = directiveImportMap.get(dir);4308 if (runtime) {4309 // built-in directive with runtime4310 dirArgs.push(context.helperString(runtime));4311 }4312 else {4313 {4314 // inject statement for resolving directive4315 context.helper(RESOLVE_DIRECTIVE);4316 context.directives.add(dir.name);4317 dirArgs.push(toValidAssetId(dir.name, `directive`));4318 }4319 }4320 const { loc } = dir;4321 if (dir.exp)4322 dirArgs.push(dir.exp);4323 if (dir.arg) {4324 if (!dir.exp) {4325 dirArgs.push(`void 0`);4326 }4327 dirArgs.push(dir.arg);4328 }4329 if (Object.keys(dir.modifiers).length) {4330 if (!dir.arg) {4331 if (!dir.exp) {4332 dirArgs.push(`void 0`);4333 }4334 dirArgs.push(`void 0`);4335 }4336 const trueExpression = createSimpleExpression(`true`, false, loc);4337 dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc));4338 }4339 return createArrayExpression(dirArgs, dir.loc);4340 }4341 function stringifyDynamicPropNames(props) {4342 let propsNamesString = `[`;4343 for (let i = 0, l = props.length; i < l; i++) {4344 propsNamesString += JSON.stringify(props[i]);4345 if (i < l - 1)4346 propsNamesString += ', ';4347 }4348 return propsNamesString + `]`;4349 }4350 function isComponentTag(tag) {4351 return tag[0].toLowerCase() + tag.slice(1) === 'component';4352 }4353 const transformSlotOutlet = (node, context) => {4354 if (isSlotOutlet(node)) {4355 const { children, loc } = node;4356 const { slotName, slotProps } = processSlotOutlet(node, context);4357 const slotArgs = [4358 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,4359 slotName,4360 '{}',4361 'undefined',4362 'true'4363 ];4364 let expectedLen = 2;4365 if (slotProps) {4366 slotArgs[2] = slotProps;4367 expectedLen = 3;4368 }4369 if (children.length) {4370 slotArgs[3] = createFunctionExpression([], children, false, false, loc);4371 expectedLen = 4;4372 }4373 if (context.scopeId && !context.slotted) {4374 expectedLen = 5;4375 }4376 slotArgs.splice(expectedLen); // remove unused arguments4377 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);4378 }4379 };4380 function processSlotOutlet(node, context) {4381 let slotName = `"default"`;4382 let slotProps = undefined;4383 const nonNameProps = [];4384 for (let i = 0; i < node.props.length; i++) {4385 const p = node.props[i];4386 if (p.type === 6 /* ATTRIBUTE */) {4387 if (p.value) {4388 if (p.name === 'name') {4389 slotName = JSON.stringify(p.value.content);4390 }4391 else {4392 p.name = camelize(p.name);4393 nonNameProps.push(p);4394 }4395 }4396 }4397 else {4398 if (p.name === 'bind' && isBindKey(p.arg, 'name')) {4399 if (p.exp)4400 slotName = p.exp;4401 }4402 else {4403 if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) {4404 p.arg.content = camelize(p.arg.content);4405 }4406 nonNameProps.push(p);4407 }4408 }4409 }4410 if (nonNameProps.length > 0) {4411 const { props, directives } = buildProps(node, context, nonNameProps);4412 slotProps = props;4413 if (directives.length) {4414 context.onError(createCompilerError(36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));4415 }4416 }4417 return {4418 slotName,4419 slotProps4420 };4421 }4422 const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;4423 const transformOn = (dir, node, context, augmentor) => {4424 const { loc, modifiers, arg } = dir;4425 if (!dir.exp && !modifiers.length) {4426 context.onError(createCompilerError(35 /* X_V_ON_NO_EXPRESSION */, loc));4427 }4428 let eventName;4429 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4430 if (arg.isStatic) {4431 const rawName = arg.content;4432 // for all event listeners, auto convert it to camelCase. See issue #22494433 eventName = createSimpleExpression(toHandlerKey(camelize(rawName)), true, arg.loc);4434 }4435 else {4436 // #23884437 eventName = createCompoundExpression([4438 `${context.helperString(TO_HANDLER_KEY)}(`,4439 arg,4440 `)`4441 ]);4442 }4443 }4444 else {4445 // already a compound expression.4446 eventName = arg;4447 eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`);4448 eventName.children.push(`)`);4449 }4450 // handler processing4451 let exp = dir.exp;4452 if (exp && !exp.content.trim()) {4453 exp = undefined;4454 }4455 let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;4456 if (exp) {4457 const isMemberExp = isMemberExpression(exp.content);4458 const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));4459 const hasMultipleStatements = exp.content.includes(`;`);4460 {4461 validateBrowserExpression(exp, context, false, hasMultipleStatements);4462 }4463 if (isInlineStatement || (shouldCache && isMemberExp)) {4464 // wrap inline statement in a function expression4465 exp = createCompoundExpression([4466 `${isInlineStatement4467 ? `$event`4468 : `${``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,4469 exp,4470 hasMultipleStatements ? `}` : `)`4471 ]);4472 }4473 }4474 let ret = {4475 props: [4476 createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))4477 ]4478 };4479 // apply extended compiler augmentor4480 if (augmentor) {4481 ret = augmentor(ret);4482 }4483 if (shouldCache) {4484 // cache handlers so that it's always the same handler being passed down.4485 // this avoids unnecessary re-renders when users use inline handlers on4486 // components.4487 ret.props[0].value = context.cache(ret.props[0].value);4488 }4489 // mark the key as handler for props normalization check4490 ret.props.forEach(p => (p.key.isHandlerKey = true));4491 return ret;4492 };4493 // v-bind without arg is handled directly in ./transformElements.ts due to it affecting4494 // codegen for the entire props object. This transform here is only for v-bind4495 // *with* args.4496 const transformBind = (dir, _node, context) => {4497 const { exp, modifiers, loc } = dir;4498 const arg = dir.arg;4499 if (arg.type !== 4 /* SIMPLE_EXPRESSION */) {4500 arg.children.unshift(`(`);4501 arg.children.push(`) || ""`);4502 }4503 else if (!arg.isStatic) {4504 arg.content = `${arg.content} || ""`;4505 }4506 // .sync is replaced by v-model:arg4507 if (modifiers.includes('camel')) {4508 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4509 if (arg.isStatic) {4510 arg.content = camelize(arg.content);4511 }4512 else {4513 arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;4514 }4515 }4516 else {4517 arg.children.unshift(`${context.helperString(CAMELIZE)}(`);4518 arg.children.push(`)`);4519 }4520 }4521 if (!context.inSSR) {4522 if (modifiers.includes('prop')) {4523 injectPrefix(arg, '.');4524 }4525 if (modifiers.includes('attr')) {4526 injectPrefix(arg, '^');4527 }4528 }4529 if (!exp ||4530 (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) {4531 context.onError(createCompilerError(34 /* X_V_BIND_NO_EXPRESSION */, loc));4532 return {4533 props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]4534 };4535 }4536 return {4537 props: [createObjectProperty(arg, exp)]4538 };4539 };4540 const injectPrefix = (arg, prefix) => {4541 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4542 if (arg.isStatic) {4543 arg.content = prefix + arg.content;4544 }4545 else {4546 arg.content = `\`${prefix}\${${arg.content}}\``;4547 }4548 }4549 else {4550 arg.children.unshift(`'${prefix}' + (`);4551 arg.children.push(`)`);4552 }4553 };4554 // Merge adjacent text nodes and expressions into a single expression4555 // e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.4556 const transformText = (node, context) => {4557 if (node.type === 0 /* ROOT */ ||4558 node.type === 1 /* ELEMENT */ ||4559 node.type === 11 /* FOR */ ||4560 node.type === 10 /* IF_BRANCH */) {4561 // perform the transform on node exit so that all expressions have already4562 // been processed.4563 return () => {4564 const children = node.children;4565 let currentContainer = undefined;4566 let hasText = false;4567 for (let i = 0; i < children.length; i++) {4568 const child = children[i];4569 if (isText(child)) {4570 hasText = true;4571 for (let j = i + 1; j < children.length; j++) {4572 const next = children[j];4573 if (isText(next)) {4574 if (!currentContainer) {4575 currentContainer = children[i] = {4576 type: 8 /* COMPOUND_EXPRESSION */,4577 loc: child.loc,4578 children: [child]4579 };4580 }4581 // merge adjacent text node into current4582 currentContainer.children.push(` + `, next);4583 children.splice(j, 1);4584 j--;4585 }4586 else {4587 currentContainer = undefined;4588 break;4589 }4590 }4591 }4592 }4593 if (!hasText ||4594 // if this is a plain element with a single text child, leave it4595 // as-is since the runtime has dedicated fast path for this by directly4596 // setting textContent of the element.4597 // for component root it's always normalized anyway.4598 (children.length === 1 &&4599 (node.type === 0 /* ROOT */ ||4600 (node.type === 1 /* ELEMENT */ &&4601 node.tagType === 0 /* ELEMENT */ &&4602 // #37564603 // custom directives can potentially add DOM elements arbitrarily,4604 // we need to avoid setting textContent of the element at runtime4605 // to avoid accidentally overwriting the DOM elements added4606 // by the user through custom directives.4607 !node.props.find(p => p.type === 7 /* DIRECTIVE */ &&4608 !context.directiveTransforms[p.name]) &&4609 // in compat mode, <template> tags with no special directives4610 // will be rendered as a fragment so its children must be4611 // converted into vnodes.4612 !(node.tag === 'template'))))) {4613 return;4614 }4615 // pre-convert text nodes into createTextVNode(text) calls to avoid4616 // runtime normalization.4617 for (let i = 0; i < children.length; i++) {4618 const child = children[i];4619 if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) {4620 const callArgs = [];4621 // createTextVNode defaults to single whitespace, so if it is a4622 // single space the code could be an empty call to save bytes.4623 if (child.type !== 2 /* TEXT */ || child.content !== ' ') {4624 callArgs.push(child);4625 }4626 // mark dynamic text with flag so it gets patched inside a block4627 if (!context.ssr &&4628 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {4629 callArgs.push(1 /* TEXT */ +4630 (` /* ${PatchFlagNames[1 /* TEXT */]} */` ));4631 }4632 children[i] = {4633 type: 12 /* TEXT_CALL */,4634 content: child,4635 loc: child.loc,4636 codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)4637 };4638 }4639 }4640 };4641 }4642 };4643 const seen = new WeakSet();4644 const transformOnce = (node, context) => {4645 if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) {4646 if (seen.has(node) || context.inVOnce) {4647 return;4648 }4649 seen.add(node);4650 context.inVOnce = true;4651 context.helper(SET_BLOCK_TRACKING);4652 return () => {4653 context.inVOnce = false;4654 const cur = context.currentNode;4655 if (cur.codegenNode) {4656 cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */);4657 }4658 };4659 }4660 };4661 const transformModel = (dir, node, context) => {4662 const { exp, arg } = dir;4663 if (!exp) {4664 context.onError(createCompilerError(41 /* X_V_MODEL_NO_EXPRESSION */, dir.loc));4665 return createTransformProps();4666 }4667 const rawExp = exp.loc.source;4668 const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : rawExp;4669 // im SFC <script setup> inline mode, the exp may have been transformed into4670 // _unref(exp)4671 context.bindingMetadata[rawExp];4672 const maybeRef = !true /* SETUP_CONST */;4673 if (!expString.trim() ||4674 (!isMemberExpression(expString) && !maybeRef)) {4675 context.onError(createCompilerError(42 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));4676 return createTransformProps();4677 }4678 const propName = arg ? arg : createSimpleExpression('modelValue', true);4679 const eventName = arg4680 ? isStaticExp(arg)4681 ? `onUpdate:${arg.content}`4682 : createCompoundExpression(['"onUpdate:" + ', arg])4683 : `onUpdate:modelValue`;4684 let assignmentExp;4685 const eventArg = context.isTS ? `($event: any)` : `$event`;4686 {4687 assignmentExp = createCompoundExpression([4688 `${eventArg} => ((`,4689 exp,4690 `) = $event)`4691 ]);4692 }4693 const props = [4694 // modelValue: foo4695 createObjectProperty(propName, dir.exp),4696 // "onUpdate:modelValue": $event => (foo = $event)4697 createObjectProperty(eventName, assignmentExp)4698 ];4699 // modelModifiers: { foo: true, "bar-baz": true }4700 if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) {4701 const modifiers = dir.modifiers4702 .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)4703 .join(`, `);4704 const modifiersKey = arg4705 ? isStaticExp(arg)4706 ? `${arg.content}Modifiers`4707 : createCompoundExpression([arg, ' + "Modifiers"'])4708 : `modelModifiers`;4709 props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* CAN_HOIST */)));4710 }4711 return createTransformProps(props);4712 };4713 function createTransformProps(props = []) {4714 return { props };4715 }4716 const validDivisionCharRE = /[\w).+\-_$\]]/;4717 const transformFilter = (node, context) => {4718 if (!isCompatEnabled("COMPILER_FILTER" /* COMPILER_FILTERS */, context)) {4719 return;4720 }4721 if (node.type === 5 /* INTERPOLATION */) {4722 // filter rewrite is applied before expression transform so only4723 // simple expressions are possible at this stage4724 rewriteFilter(node.content, context);4725 }4726 if (node.type === 1 /* ELEMENT */) {4727 node.props.forEach((prop) => {4728 if (prop.type === 7 /* DIRECTIVE */ &&4729 prop.name !== 'for' &&4730 prop.exp) {4731 rewriteFilter(prop.exp, context);4732 }4733 });4734 }4735 };4736 function rewriteFilter(node, context) {4737 if (node.type === 4 /* SIMPLE_EXPRESSION */) {4738 parseFilter(node, context);4739 }4740 else {4741 for (let i = 0; i < node.children.length; i++) {4742 const child = node.children[i];4743 if (typeof child !== 'object')4744 continue;4745 if (child.type === 4 /* SIMPLE_EXPRESSION */) {4746 parseFilter(child, context);4747 }4748 else if (child.type === 8 /* COMPOUND_EXPRESSION */) {4749 rewriteFilter(node, context);4750 }4751 else if (child.type === 5 /* INTERPOLATION */) {4752 rewriteFilter(child.content, context);4753 }4754 }4755 }4756 }4757 function parseFilter(node, context) {4758 const exp = node.content;4759 let inSingle = false;4760 let inDouble = false;4761 let inTemplateString = false;4762 let inRegex = false;4763 let curly = 0;4764 let square = 0;4765 let paren = 0;4766 let lastFilterIndex = 0;4767 let c, prev, i, expression, filters = [];4768 for (i = 0; i < exp.length; i++) {4769 prev = c;4770 c = exp.charCodeAt(i);4771 if (inSingle) {4772 if (c === 0x27 && prev !== 0x5c)4773 inSingle = false;4774 }4775 else if (inDouble) {4776 if (c === 0x22 && prev !== 0x5c)4777 inDouble = false;4778 }4779 else if (inTemplateString) {4780 if (c === 0x60 && prev !== 0x5c)4781 inTemplateString = false;4782 }4783 else if (inRegex) {4784 if (c === 0x2f && prev !== 0x5c)4785 inRegex = false;4786 }4787 else if (c === 0x7c && // pipe4788 exp.charCodeAt(i + 1) !== 0x7c &&4789 exp.charCodeAt(i - 1) !== 0x7c &&4790 !curly &&4791 !square &&4792 !paren) {4793 if (expression === undefined) {4794 // first filter, end of expression4795 lastFilterIndex = i + 1;4796 expression = exp.slice(0, i).trim();4797 }4798 else {4799 pushFilter();4800 }4801 }4802 else {4803 switch (c) {4804 case 0x22:4805 inDouble = true;4806 break; // "4807 case 0x27:4808 inSingle = true;4809 break; // '4810 case 0x60:4811 inTemplateString = true;4812 break; // `4813 case 0x28:4814 paren++;4815 break; // (4816 case 0x29:4817 paren--;4818 break; // )4819 case 0x5b:4820 square++;4821 break; // [4822 case 0x5d:4823 square--;4824 break; // ]4825 case 0x7b:4826 curly++;4827 break; // {4828 case 0x7d:4829 curly--;4830 break; // }4831 }4832 if (c === 0x2f) {4833 // /4834 let j = i - 1;4835 let p;4836 // find first non-whitespace prev char4837 for (; j >= 0; j--) {4838 p = exp.charAt(j);4839 if (p !== ' ')4840 break;4841 }4842 if (!p || !validDivisionCharRE.test(p)) {4843 inRegex = true;4844 }4845 }4846 }4847 }4848 if (expression === undefined) {4849 expression = exp.slice(0, i).trim();4850 }4851 else if (lastFilterIndex !== 0) {4852 pushFilter();4853 }4854 function pushFilter() {4855 filters.push(exp.slice(lastFilterIndex, i).trim());4856 lastFilterIndex = i + 1;4857 }4858 if (filters.length) {4859 warnDeprecation("COMPILER_FILTER" /* COMPILER_FILTERS */, context, node.loc);4860 for (i = 0; i < filters.length; i++) {4861 expression = wrapFilter(expression, filters[i], context);4862 }4863 node.content = expression;4864 }4865 }4866 function wrapFilter(exp, filter, context) {4867 context.helper(RESOLVE_FILTER);4868 const i = filter.indexOf('(');4869 if (i < 0) {4870 context.filters.add(filter);4871 return `${toValidAssetId(filter, 'filter')}(${exp})`;4872 }4873 else {4874 const name = filter.slice(0, i);4875 const args = filter.slice(i + 1);4876 context.filters.add(name);4877 return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`;4878 }4879 }4880 const seen$1 = new WeakSet();4881 const transformMemo = (node, context) => {4882 if (node.type === 1 /* ELEMENT */) {4883 const dir = findDir(node, 'memo');4884 if (!dir || seen$1.has(node)) {4885 return;4886 }4887 seen$1.add(node);4888 return () => {4889 const codegenNode = node.codegenNode ||4890 context.currentNode.codegenNode;4891 if (codegenNode && codegenNode.type === 13 /* VNODE_CALL */) {4892 // non-component sub tree should be turned into a block4893 if (node.tagType !== 1 /* COMPONENT */) {4894 makeBlock(codegenNode, context);4895 }4896 node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [4897 dir.exp,4898 createFunctionExpression(undefined, codegenNode),4899 `_cache`,4900 String(context.cached++)4901 ]);4902 }4903 };4904 }4905 };4906 function getBaseTransformPreset(prefixIdentifiers) {4907 return [4908 [4909 transformOnce,4910 transformIf,4911 transformMemo,4912 transformFor,4913 ...([transformFilter] ),4914 ...([transformExpression]4915 ),4916 transformSlotOutlet,4917 transformElement,4918 trackSlotScopes,4919 transformText4920 ],4921 {4922 on: transformOn,4923 bind: transformBind,4924 model: transformModel4925 }4926 ];4927 }4928 // we name it `baseCompile` so that higher order compilers like4929 // @vue/compiler-dom can export `compile` while re-exporting everything else.4930 function baseCompile(template, options = {}) {4931 const onError = options.onError || defaultOnError;4932 const isModuleMode = options.mode === 'module';4933 /* istanbul ignore if */4934 {4935 if (options.prefixIdentifiers === true) {4936 onError(createCompilerError(46 /* X_PREFIX_ID_NOT_SUPPORTED */));4937 }4938 else if (isModuleMode) {4939 onError(createCompilerError(47 /* X_MODULE_MODE_NOT_SUPPORTED */));4940 }4941 }4942 const prefixIdentifiers = !true ;4943 if (options.cacheHandlers) {4944 onError(createCompilerError(48 /* X_CACHE_HANDLER_NOT_SUPPORTED */));4945 }4946 if (options.scopeId && !isModuleMode) {4947 onError(createCompilerError(49 /* X_SCOPE_ID_NOT_SUPPORTED */));4948 }4949 const ast = isString(template) ? baseParse(template, options) : template;4950 const [nodeTransforms, directiveTransforms] = getBaseTransformPreset();4951 transform(ast, extend({}, options, {4952 prefixIdentifiers,4953 nodeTransforms: [4954 ...nodeTransforms,4955 ...(options.nodeTransforms || []) // user transforms4956 ],4957 directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms4958 )4959 }));4960 return generate(ast, extend({}, options, {4961 prefixIdentifiers4962 }));4963 }4964 const noopDirectiveTransform = () => ({ props: [] });4965 const V_MODEL_RADIO = Symbol(`vModelRadio` );4966 const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` );4967 const V_MODEL_TEXT = Symbol(`vModelText` );4968 const V_MODEL_SELECT = Symbol(`vModelSelect` );4969 const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` );4970 const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` );4971 const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` );4972 const V_SHOW = Symbol(`vShow` );4973 const TRANSITION = Symbol(`Transition` );4974 const TRANSITION_GROUP = Symbol(`TransitionGroup` );4975 registerRuntimeHelpers({4976 [V_MODEL_RADIO]: `vModelRadio`,4977 [V_MODEL_CHECKBOX]: `vModelCheckbox`,4978 [V_MODEL_TEXT]: `vModelText`,4979 [V_MODEL_SELECT]: `vModelSelect`,4980 [V_MODEL_DYNAMIC]: `vModelDynamic`,4981 [V_ON_WITH_MODIFIERS]: `withModifiers`,4982 [V_ON_WITH_KEYS]: `withKeys`,4983 [V_SHOW]: `vShow`,4984 [TRANSITION]: `Transition`,4985 [TRANSITION_GROUP]: `TransitionGroup`4986 });4987 /* eslint-disable no-restricted-globals */4988 let decoder;4989 function decodeHtmlBrowser(raw, asAttr = false) {4990 if (!decoder) {4991 decoder = document.createElement('div');4992 }4993 if (asAttr) {4994 decoder.innerHTML = `<div foo="${raw.replace(/"/g, '&quot;')}">`;4995 return decoder.children[0].getAttribute('foo');4996 }4997 else {4998 decoder.innerHTML = raw;4999 return decoder.textContent;5000 }5001 }5002 const isRawTextContainer = /*#__PURE__*/ makeMap('style,iframe,script,noscript', true);5003 const parserOptions = {5004 isVoidTag,5005 isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag),5006 isPreTag: tag => tag === 'pre',5007 decodeEntities: decodeHtmlBrowser ,5008 isBuiltInComponent: (tag) => {5009 if (isBuiltInType(tag, `Transition`)) {5010 return TRANSITION;5011 }5012 else if (isBuiltInType(tag, `TransitionGroup`)) {5013 return TRANSITION_GROUP;5014 }5015 },5016 // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher5017 getNamespace(tag, parent) {5018 let ns = parent ? parent.ns : 0 /* HTML */;5019 if (parent && ns === 2 /* MATH_ML */) {5020 if (parent.tag === 'annotation-xml') {5021 if (tag === 'svg') {5022 return 1 /* SVG */;5023 }5024 if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ &&5025 a.name === 'encoding' &&5026 a.value != null &&5027 (a.value.content === 'text/html' ||5028 a.value.content === 'application/xhtml+xml'))) {5029 ns = 0 /* HTML */;5030 }5031 }5032 else if (/^m(?:[ions]|text)$/.test(parent.tag) &&5033 tag !== 'mglyph' &&5034 tag !== 'malignmark') {5035 ns = 0 /* HTML */;5036 }5037 }5038 else if (parent && ns === 1 /* SVG */) {5039 if (parent.tag === 'foreignObject' ||5040 parent.tag === 'desc' ||5041 parent.tag === 'title') {5042 ns = 0 /* HTML */;5043 }5044 }5045 if (ns === 0 /* HTML */) {5046 if (tag === 'svg') {5047 return 1 /* SVG */;5048 }5049 if (tag === 'math') {5050 return 2 /* MATH_ML */;5051 }5052 }5053 return ns;5054 },5055 // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments5056 getTextMode({ tag, ns }) {5057 if (ns === 0 /* HTML */) {5058 if (tag === 'textarea' || tag === 'title') {5059 return 1 /* RCDATA */;5060 }5061 if (isRawTextContainer(tag)) {5062 return 2 /* RAWTEXT */;5063 }5064 }5065 return 0 /* DATA */;5066 }5067 };5068 // Parse inline CSS strings for static style attributes into an object.5069 // This is a NodeTransform since it works on the static `style` attribute and5070 // converts it into a dynamic equivalent:5071 // style="color: red" -> :style='{ "color": "red" }'5072 // It is then processed by `transformElement` and included in the generated5073 // props.5074 const transformStyle = node => {5075 if (node.type === 1 /* ELEMENT */) {5076 node.props.forEach((p, i) => {5077 if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) {5078 // replace p with an expression node5079 node.props[i] = {5080 type: 7 /* DIRECTIVE */,5081 name: `bind`,5082 arg: createSimpleExpression(`style`, true, p.loc),5083 exp: parseInlineCSS(p.value.content, p.loc),5084 modifiers: [],5085 loc: p.loc5086 };5087 }5088 });5089 }5090 };5091 const parseInlineCSS = (cssText, loc) => {5092 const normalized = parseStringStyle(cssText);5093 return createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* CAN_STRINGIFY */);5094 };5095 function createDOMCompilerError(code, loc) {5096 return createCompilerError(code, loc, DOMErrorMessages );5097 }5098 const DOMErrorMessages = {5099 [50 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,5100 [51 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,5101 [52 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,5102 [53 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,5103 [54 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,5104 [55 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,5105 [56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,5106 [57 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,5107 [58 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,5108 [59 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`,5109 [60 /* X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`5110 };5111 const transformVHtml = (dir, node, context) => {5112 const { exp, loc } = dir;5113 if (!exp) {5114 context.onError(createDOMCompilerError(50 /* X_V_HTML_NO_EXPRESSION */, loc));5115 }5116 if (node.children.length) {5117 context.onError(createDOMCompilerError(51 /* X_V_HTML_WITH_CHILDREN */, loc));5118 node.children.length = 0;5119 }5120 return {5121 props: [5122 createObjectProperty(createSimpleExpression(`innerHTML`, true, loc), exp || createSimpleExpression('', true))5123 ]5124 };5125 };5126 const transformVText = (dir, node, context) => {5127 const { exp, loc } = dir;5128 if (!exp) {5129 context.onError(createDOMCompilerError(52 /* X_V_TEXT_NO_EXPRESSION */, loc));5130 }5131 if (node.children.length) {5132 context.onError(createDOMCompilerError(53 /* X_V_TEXT_WITH_CHILDREN */, loc));5133 node.children.length = 0;5134 }5135 return {5136 props: [5137 createObjectProperty(createSimpleExpression(`textContent`, true), exp5138 ? createCallExpression(context.helperString(TO_DISPLAY_STRING), [exp], loc)5139 : createSimpleExpression('', true))5140 ]5141 };5142 };5143 const transformModel$1 = (dir, node, context) => {5144 const baseResult = transformModel(dir, node, context);5145 // base transform has errors OR component v-model (only need props)5146 if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) {5147 return baseResult;5148 }5149 if (dir.arg) {5150 context.onError(createDOMCompilerError(55 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));5151 }5152 function checkDuplicatedValue() {5153 const value = findProp(node, 'value');5154 if (value) {5155 context.onError(createDOMCompilerError(57 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc));5156 }5157 }5158 const { tag } = node;5159 const isCustomElement = context.isCustomElement(tag);5160 if (tag === 'input' ||5161 tag === 'textarea' ||5162 tag === 'select' ||5163 isCustomElement) {5164 let directiveToUse = V_MODEL_TEXT;5165 let isInvalidType = false;5166 if (tag === 'input' || isCustomElement) {5167 const type = findProp(node, `type`);5168 if (type) {5169 if (type.type === 7 /* DIRECTIVE */) {5170 // :type="foo"5171 directiveToUse = V_MODEL_DYNAMIC;5172 }5173 else if (type.value) {5174 switch (type.value.content) {5175 case 'radio':5176 directiveToUse = V_MODEL_RADIO;5177 break;5178 case 'checkbox':5179 directiveToUse = V_MODEL_CHECKBOX;5180 break;5181 case 'file':5182 isInvalidType = true;5183 context.onError(createDOMCompilerError(56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));5184 break;5185 default:5186 // text type5187 checkDuplicatedValue();5188 break;5189 }5190 }5191 }5192 else if (hasDynamicKeyVBind(node)) {5193 // element has bindings with dynamic keys, which can possibly contain5194 // "type".5195 directiveToUse = V_MODEL_DYNAMIC;5196 }5197 else {5198 // text type5199 checkDuplicatedValue();5200 }5201 }5202 else if (tag === 'select') {5203 directiveToUse = V_MODEL_SELECT;5204 }5205 else {5206 // textarea5207 checkDuplicatedValue();5208 }5209 // inject runtime directive5210 // by returning the helper symbol via needRuntime5211 // the import will replaced a resolveDirective call.5212 if (!isInvalidType) {5213 baseResult.needRuntime = context.helper(directiveToUse);5214 }5215 }5216 else {5217 context.onError(createDOMCompilerError(54 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));5218 }5219 // native vmodel doesn't need the `modelValue` props since they are also5220 // passed to the runtime as `binding.value`. removing it reduces code size.5221 baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* SIMPLE_EXPRESSION */ &&5222 p.key.content === 'modelValue'));5223 return baseResult;5224 };5225 const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`);5226 const isNonKeyModifier = /*#__PURE__*/ makeMap(5227 // event propagation management5228`stop,prevent,self,` +5229 // system modifiers + exact5230 `ctrl,shift,alt,meta,exact,` +5231 // mouse5232 `middle`);5233 // left & right could be mouse or key modifiers based on event type5234 const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right');5235 const isKeyboardEvent = /*#__PURE__*/ makeMap(`onkeyup,onkeydown,onkeypress`, true);5236 const resolveModifiers = (key, modifiers, context, loc) => {5237 const keyModifiers = [];5238 const nonKeyModifiers = [];5239 const eventOptionModifiers = [];5240 for (let i = 0; i < modifiers.length; i++) {5241 const modifier = modifiers[i];5242 if (modifier === 'native' &&5243 checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) {5244 eventOptionModifiers.push(modifier);5245 }5246 else if (isEventOptionModifier(modifier)) {5247 // eventOptionModifiers: modifiers for addEventListener() options,5248 // e.g. .passive & .capture5249 eventOptionModifiers.push(modifier);5250 }5251 else {5252 // runtimeModifiers: modifiers that needs runtime guards5253 if (maybeKeyModifier(modifier)) {5254 if (isStaticExp(key)) {5255 if (isKeyboardEvent(key.content)) {5256 keyModifiers.push(modifier);5257 } ...

Full Screen

Full Screen

compiler-core.cjs.js

Source:compiler-core.cjs.js Github

copy

Full Screen

...800 // in v3 mode, only enable if explicitly set to true801 // otherwise enable for any non-false value802 return mode === 3 ? value === true : value !== false;803}804function checkCompatEnabled(key, context, loc, ...args) {805 const enabled = isCompatEnabled(key, context);806 if (enabled) {807 warnDeprecation(key, context, loc, ...args);808 }809 return enabled;810}811function warnDeprecation(key, context, loc, ...args) {812 const val = getCompatValue(key, context);813 if (val === 'suppress-warning') {814 return;815 }816 const { message, link } = deprecationData[key];817 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;818 const err = new SyntaxError(msg);819 err.code = key;820 if (loc)821 err.loc = loc;822 context.onWarn(err);823}824// The default decoder only provides escapes for characters reserved as part of825// the template syntax, and is only used if the custom renderer did not provide826// a platform-specific decoder.827const decodeRE = /&(gt|lt|amp|apos|quot);/g;828const decodeMap = {829 gt: '>',830 lt: '<',831 amp: '&',832 apos: "'",833 quot: '"'834};835const defaultParserOptions = {836 delimiters: [`{{`, `}}`],837 getNamespace: () => 0 /* HTML */,838 getTextMode: () => 0 /* DATA */,839 isVoidTag: shared.NO,840 isPreTag: shared.NO,841 isCustomElement: shared.NO,842 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),843 onError: defaultOnError,844 onWarn: defaultOnWarn,845 comments: true846};847function baseParse(content, options = {}) {848 const context = createParserContext(content, options);849 const start = getCursor(context);850 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));851}852function createParserContext(content, rawOptions) {853 const options = shared.extend({}, defaultParserOptions);854 let key;855 for (key in rawOptions) {856 // @ts-ignore857 options[key] =858 rawOptions[key] === undefined859 ? defaultParserOptions[key]860 : rawOptions[key];861 }862 return {863 options,864 column: 1,865 line: 1,866 offset: 0,867 originalSource: content,868 source: content,869 inPre: false,870 inVPre: false,871 onWarn: options.onWarn872 };873}874function parseChildren(context, mode, ancestors) {875 const parent = last(ancestors);876 const ns = parent ? parent.ns : 0 /* HTML */;877 const nodes = [];878 while (!isEnd(context, mode, ancestors)) {879 const s = context.source;880 let node = undefined;881 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {882 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {883 // '{{'884 node = parseInterpolation(context, mode);885 }886 else if (mode === 0 /* DATA */ && s[0] === '<') {887 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state888 if (s.length === 1) {889 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);890 }891 else if (s[1] === '!') {892 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state893 if (startsWith(s, '<!--')) {894 node = parseComment(context);895 }896 else if (startsWith(s, '<!DOCTYPE')) {897 // Ignore DOCTYPE by a limitation.898 node = parseBogusComment(context);899 }900 else if (startsWith(s, '<![CDATA[')) {901 if (ns !== 0 /* HTML */) {902 node = parseCDATA(context, ancestors);903 }904 else {905 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);906 node = parseBogusComment(context);907 }908 }909 else {910 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);911 node = parseBogusComment(context);912 }913 }914 else if (s[1] === '/') {915 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state916 if (s.length === 2) {917 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);918 }919 else if (s[2] === '>') {920 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);921 advanceBy(context, 3);922 continue;923 }924 else if (/[a-z]/i.test(s[2])) {925 emitError(context, 23 /* X_INVALID_END_TAG */);926 parseTag(context, 1 /* End */, parent);927 continue;928 }929 else {930 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);931 node = parseBogusComment(context);932 }933 }934 else if (/[a-z]/i.test(s[1])) {935 node = parseElement(context, ancestors);936 // 2.x <template> with no directive compat937 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&938 node &&939 node.tag === 'template' &&940 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&941 isSpecialTemplateDirective(p.name))) {942 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);943 node = node.children;944 }945 }946 else if (s[1] === '?') {947 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);948 node = parseBogusComment(context);949 }950 else {951 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);952 }953 }954 }955 if (!node) {956 node = parseText(context, mode);957 }958 if (shared.isArray(node)) {959 for (let i = 0; i < node.length; i++) {960 pushNode(nodes, node[i]);961 }962 }963 else {964 pushNode(nodes, node);965 }966 }967 // Whitespace handling strategy like v2968 let removedWhitespace = false;969 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {970 const shouldCondense = context.options.whitespace !== 'preserve';971 for (let i = 0; i < nodes.length; i++) {972 const node = nodes[i];973 if (!context.inPre && node.type === 2 /* TEXT */) {974 if (!/[^\t\r\n\f ]/.test(node.content)) {975 const prev = nodes[i - 1];976 const next = nodes[i + 1];977 // Remove if:978 // - the whitespace is the first or last node, or:979 // - (condense mode) the whitespace is adjacent to a comment, or:980 // - (condense mode) the whitespace is between two elements AND contains newline981 if (!prev ||982 !next ||983 (shouldCondense &&984 (prev.type === 3 /* COMMENT */ ||985 next.type === 3 /* COMMENT */ ||986 (prev.type === 1 /* ELEMENT */ &&987 next.type === 1 /* ELEMENT */ &&988 /[\r\n]/.test(node.content))))) {989 removedWhitespace = true;990 nodes[i] = null;991 }992 else {993 // Otherwise, the whitespace is condensed into a single space994 node.content = ' ';995 }996 }997 else if (shouldCondense) {998 // in condense mode, consecutive whitespaces in text are condensed999 // down to a single space.1000 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');1001 }1002 }1003 // Remove comment nodes if desired by configuration.1004 else if (node.type === 3 /* COMMENT */ && !context.options.comments) {1005 removedWhitespace = true;1006 nodes[i] = null;1007 }1008 }1009 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {1010 // remove leading newline per html spec1011 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element1012 const first = nodes[0];1013 if (first && first.type === 2 /* TEXT */) {1014 first.content = first.content.replace(/^\r?\n/, '');1015 }1016 }1017 }1018 return removedWhitespace ? nodes.filter(Boolean) : nodes;1019}1020function pushNode(nodes, node) {1021 if (node.type === 2 /* TEXT */) {1022 const prev = last(nodes);1023 // Merge if both this and the previous node are text and those are1024 // consecutive. This happens for cases like "a < b".1025 if (prev &&1026 prev.type === 2 /* TEXT */ &&1027 prev.loc.end.offset === node.loc.start.offset) {1028 prev.content += node.content;1029 prev.loc.end = node.loc.end;1030 prev.loc.source += node.loc.source;1031 return;1032 }1033 }1034 nodes.push(node);1035}1036function parseCDATA(context, ancestors) {1037 advanceBy(context, 9);1038 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1039 if (context.source.length === 0) {1040 emitError(context, 6 /* EOF_IN_CDATA */);1041 }1042 else {1043 advanceBy(context, 3);1044 }1045 return nodes;1046}1047function parseComment(context) {1048 const start = getCursor(context);1049 let content;1050 // Regular comment.1051 const match = /--(\!)?>/.exec(context.source);1052 if (!match) {1053 content = context.source.slice(4);1054 advanceBy(context, context.source.length);1055 emitError(context, 7 /* EOF_IN_COMMENT */);1056 }1057 else {1058 if (match.index <= 3) {1059 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1060 }1061 if (match[1]) {1062 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1063 }1064 content = context.source.slice(4, match.index);1065 // Advancing with reporting nested comments.1066 const s = context.source.slice(0, match.index);1067 let prevIndex = 1, nestedIndex = 0;1068 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1069 advanceBy(context, nestedIndex - prevIndex + 1);1070 if (nestedIndex + 4 < s.length) {1071 emitError(context, 16 /* NESTED_COMMENT */);1072 }1073 prevIndex = nestedIndex + 1;1074 }1075 advanceBy(context, match.index + match[0].length - prevIndex + 1);1076 }1077 return {1078 type: 3 /* COMMENT */,1079 content,1080 loc: getSelection(context, start)1081 };1082}1083function parseBogusComment(context) {1084 const start = getCursor(context);1085 const contentStart = context.source[1] === '?' ? 1 : 2;1086 let content;1087 const closeIndex = context.source.indexOf('>');1088 if (closeIndex === -1) {1089 content = context.source.slice(contentStart);1090 advanceBy(context, context.source.length);1091 }1092 else {1093 content = context.source.slice(contentStart, closeIndex);1094 advanceBy(context, closeIndex + 1);1095 }1096 return {1097 type: 3 /* COMMENT */,1098 content,1099 loc: getSelection(context, start)1100 };1101}1102function parseElement(context, ancestors) {1103 // Start tag.1104 const wasInPre = context.inPre;1105 const wasInVPre = context.inVPre;1106 const parent = last(ancestors);1107 const element = parseTag(context, 0 /* Start */, parent);1108 const isPreBoundary = context.inPre && !wasInPre;1109 const isVPreBoundary = context.inVPre && !wasInVPre;1110 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1111 // #4030 self-closing <pre> tag1112 if (isPreBoundary) {1113 context.inPre = false;1114 }1115 if (isVPreBoundary) {1116 context.inVPre = false;1117 }1118 return element;1119 }1120 // Children.1121 ancestors.push(element);1122 const mode = context.options.getTextMode(element, parent);1123 const children = parseChildren(context, mode, ancestors);1124 ancestors.pop();1125 // 2.x inline-template compat1126 {1127 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1128 if (inlineTemplateProp &&1129 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1130 const loc = getSelection(context, element.loc.end);1131 inlineTemplateProp.value = {1132 type: 2 /* TEXT */,1133 content: loc.source,1134 loc1135 };1136 }1137 }1138 element.children = children;1139 // End tag.1140 if (startsWithEndTagOpen(context.source, element.tag)) {1141 parseTag(context, 1 /* End */, parent);1142 }1143 else {1144 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1145 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1146 const first = children[0];1147 if (first && startsWith(first.loc.source, '<!--')) {1148 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1149 }1150 }1151 }1152 element.loc = getSelection(context, element.loc.start);1153 if (isPreBoundary) {1154 context.inPre = false;1155 }1156 if (isVPreBoundary) {1157 context.inVPre = false;1158 }1159 return element;1160}1161const isSpecialTemplateDirective = /*#__PURE__*/ shared.makeMap(`if,else,else-if,for,slot`);1162function parseTag(context, type, parent) {1163 // Tag open.1164 const start = getCursor(context);1165 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1166 const tag = match[1];1167 const ns = context.options.getNamespace(tag, parent);1168 advanceBy(context, match[0].length);1169 advanceSpaces(context);1170 // save current state in case we need to re-parse attributes with v-pre1171 const cursor = getCursor(context);1172 const currentSource = context.source;1173 // check <pre> tag1174 if (context.options.isPreTag(tag)) {1175 context.inPre = true;1176 }1177 // Attributes.1178 let props = parseAttributes(context, type);1179 // check v-pre1180 if (type === 0 /* Start */ &&1181 !context.inVPre &&1182 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1183 context.inVPre = true;1184 // reset context1185 shared.extend(context, cursor);1186 context.source = currentSource;1187 // re-parse attrs and filter out v-pre itself1188 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1189 }1190 // Tag close.1191 let isSelfClosing = false;1192 if (context.source.length === 0) {1193 emitError(context, 9 /* EOF_IN_TAG */);1194 }1195 else {1196 isSelfClosing = startsWith(context.source, '/>');1197 if (type === 1 /* End */ && isSelfClosing) {1198 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1199 }1200 advanceBy(context, isSelfClosing ? 2 : 1);1201 }1202 if (type === 1 /* End */) {1203 return;1204 }1205 // 2.x deprecation checks1206 if (isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1207 let hasIf = false;1208 let hasFor = false;1209 for (let i = 0; i < props.length; i++) {1210 const p = props[i];1211 if (p.type === 7 /* DIRECTIVE */) {1212 if (p.name === 'if') {1213 hasIf = true;1214 }1215 else if (p.name === 'for') {1216 hasFor = true;1217 }1218 }1219 if (hasIf && hasFor) {1220 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1221 }1222 }1223 }1224 let tagType = 0 /* ELEMENT */;1225 if (!context.inVPre) {1226 if (tag === 'slot') {1227 tagType = 2 /* SLOT */;1228 }1229 else if (tag === 'template') {1230 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1231 tagType = 3 /* TEMPLATE */;1232 }1233 }1234 else if (isComponent(tag, props, context)) {1235 tagType = 1 /* COMPONENT */;1236 }1237 }1238 return {1239 type: 1 /* ELEMENT */,1240 ns,1241 tag,1242 tagType,1243 props,1244 isSelfClosing,1245 children: [],1246 loc: getSelection(context, start),1247 codegenNode: undefined // to be created during transform phase1248 };1249}1250function isComponent(tag, props, context) {1251 const options = context.options;1252 if (options.isCustomElement(tag)) {1253 return false;1254 }1255 if (tag === 'component' ||1256 /^[A-Z]/.test(tag) ||1257 isCoreComponent(tag) ||1258 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1259 (options.isNativeTag && !options.isNativeTag(tag))) {1260 return true;1261 }1262 // at this point the tag should be a native tag, but check for potential "is"1263 // casting1264 for (let i = 0; i < props.length; i++) {1265 const p = props[i];1266 if (p.type === 6 /* ATTRIBUTE */) {1267 if (p.name === 'is' && p.value) {1268 if (p.value.content.startsWith('vue:')) {1269 return true;1270 }1271 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1272 return true;1273 }1274 }1275 }1276 else {1277 // directive1278 // v-is (TODO Deprecate)1279 if (p.name === 'is') {1280 return true;1281 }1282 else if (1283 // :is on plain element - only treat as component in compat mode1284 p.name === 'bind' &&1285 isBindKey(p.arg, 'is') &&1286 true &&1287 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1288 return true;1289 }1290 }1291 }1292}1293function parseAttributes(context, type) {1294 const props = [];1295 const attributeNames = new Set();1296 while (context.source.length > 0 &&1297 !startsWith(context.source, '>') &&1298 !startsWith(context.source, '/>')) {1299 if (startsWith(context.source, '/')) {1300 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1301 advanceBy(context, 1);1302 advanceSpaces(context);1303 continue;1304 }1305 if (type === 1 /* End */) {1306 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1307 }1308 const attr = parseAttribute(context, attributeNames);1309 // Trim whitespace between class1310 // https://github.com/vuejs/vue-next/issues/42511311 if (attr.type === 6 /* ATTRIBUTE */ &&1312 attr.value &&1313 attr.name === 'class') {1314 attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();1315 }1316 if (type === 0 /* Start */) {1317 props.push(attr);1318 }1319 if (/^[^\t\r\n\f />]/.test(context.source)) {1320 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1321 }1322 advanceSpaces(context);1323 }1324 return props;1325}1326function parseAttribute(context, nameSet) {1327 // Name.1328 const start = getCursor(context);1329 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1330 const name = match[0];1331 if (nameSet.has(name)) {1332 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1333 }1334 nameSet.add(name);1335 if (name[0] === '=') {1336 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1337 }1338 {1339 const pattern = /["'<]/g;1340 let m;1341 while ((m = pattern.exec(name))) {1342 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1343 }1344 }1345 advanceBy(context, name.length);1346 // Value1347 let value = undefined;1348 if (/^[\t\r\n\f ]*=/.test(context.source)) {1349 advanceSpaces(context);1350 advanceBy(context, 1);1351 advanceSpaces(context);1352 value = parseAttributeValue(context);1353 if (!value) {1354 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1355 }1356 }1357 const loc = getSelection(context, start);1358 if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {1359 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1360 let isPropShorthand = startsWith(name, '.');1361 let dirName = match[1] ||1362 (isPropShorthand || startsWith(name, ':')1363 ? 'bind'1364 : startsWith(name, '@')1365 ? 'on'1366 : 'slot');1367 let arg;1368 if (match[2]) {1369 const isSlot = dirName === 'slot';1370 const startOffset = name.lastIndexOf(match[2]);1371 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));1372 let content = match[2];1373 let isStatic = true;1374 if (content.startsWith('[')) {1375 isStatic = false;1376 if (!content.endsWith(']')) {1377 emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1378 content = content.slice(1);1379 }1380 else {1381 content = content.slice(1, content.length - 1);1382 }1383 }1384 else if (isSlot) {1385 // #1241 special case for v-slot: vuetify relies extensively on slot1386 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x1387 // supports such usage so we are keeping it consistent with 2.x.1388 content += match[3] || '';1389 }1390 arg = {1391 type: 4 /* SIMPLE_EXPRESSION */,1392 content,1393 isStatic,1394 constType: isStatic1395 ? 3 /* CAN_STRINGIFY */1396 : 0 /* NOT_CONSTANT */,1397 loc1398 };1399 }1400 if (value && value.isQuoted) {1401 const valueLoc = value.loc;1402 valueLoc.start.offset++;1403 valueLoc.start.column++;1404 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1405 valueLoc.source = valueLoc.source.slice(1, -1);1406 }1407 const modifiers = match[3] ? match[3].slice(1).split('.') : [];1408 if (isPropShorthand)1409 modifiers.push('prop');1410 // 2.x compat v-bind:foo.sync -> v-model:foo1411 if (dirName === 'bind' && arg) {1412 if (modifiers.includes('sync') &&1413 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {1414 dirName = 'model';1415 modifiers.splice(modifiers.indexOf('sync'), 1);1416 }1417 if (modifiers.includes('prop')) {1418 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);1419 }1420 }1421 return {1422 type: 7 /* DIRECTIVE */,1423 name: dirName,1424 exp: value && {1425 type: 4 /* SIMPLE_EXPRESSION */,1426 content: value.content,1427 isStatic: false,1428 // Treat as non-constant by default. This can be potentially set to1429 // other values by `transformExpression` to make it eligible for hoisting.1430 constType: 0 /* NOT_CONSTANT */,1431 loc: value.loc1432 },1433 arg,1434 modifiers,1435 loc1436 };1437 }1438 // missing directive name or illegal directive name1439 if (!context.inVPre && startsWith(name, 'v-')) {1440 emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */);1441 }1442 return {1443 type: 6 /* ATTRIBUTE */,1444 name,1445 value: value && {1446 type: 2 /* TEXT */,1447 content: value.content,1448 loc: value.loc1449 },1450 loc1451 };1452}1453function parseAttributeValue(context) {1454 const start = getCursor(context);1455 let content;1456 const quote = context.source[0];1457 const isQuoted = quote === `"` || quote === `'`;1458 if (isQuoted) {1459 // Quoted value.1460 advanceBy(context, 1);1461 const endIndex = context.source.indexOf(quote);1462 if (endIndex === -1) {1463 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1464 }1465 else {1466 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1467 advanceBy(context, 1);1468 }1469 }1470 else {1471 // Unquoted1472 const match = /^[^\t\r\n\f >]+/.exec(context.source);1473 if (!match) {1474 return undefined;1475 }1476 const unexpectedChars = /["'<=`]/g;1477 let m;1478 while ((m = unexpectedChars.exec(match[0]))) {1479 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1480 }1481 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1482 }1483 return { content, isQuoted, loc: getSelection(context, start) };1484}1485function parseInterpolation(context, mode) {1486 const [open, close] = context.options.delimiters;1487 const closeIndex = context.source.indexOf(close, open.length);1488 if (closeIndex === -1) {1489 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);1490 return undefined;1491 }1492 const start = getCursor(context);1493 advanceBy(context, open.length);1494 const innerStart = getCursor(context);1495 const innerEnd = getCursor(context);1496 const rawContentLength = closeIndex - open.length;1497 const rawContent = context.source.slice(0, rawContentLength);1498 const preTrimContent = parseTextData(context, rawContentLength, mode);1499 const content = preTrimContent.trim();1500 const startOffset = preTrimContent.indexOf(content);1501 if (startOffset > 0) {1502 advancePositionWithMutation(innerStart, rawContent, startOffset);1503 }1504 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1505 advancePositionWithMutation(innerEnd, rawContent, endOffset);1506 advanceBy(context, close.length);1507 return {1508 type: 5 /* INTERPOLATION */,1509 content: {1510 type: 4 /* SIMPLE_EXPRESSION */,1511 isStatic: false,1512 // Set `isConstant` to false by default and will decide in transformExpression1513 constType: 0 /* NOT_CONSTANT */,1514 content,1515 loc: getSelection(context, innerStart, innerEnd)1516 },1517 loc: getSelection(context, start)1518 };1519}1520function parseText(context, mode) {1521 const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];1522 let endIndex = context.source.length;1523 for (let i = 0; i < endTokens.length; i++) {1524 const index = context.source.indexOf(endTokens[i], 1);1525 if (index !== -1 && endIndex > index) {1526 endIndex = index;1527 }1528 }1529 const start = getCursor(context);1530 const content = parseTextData(context, endIndex, mode);1531 return {1532 type: 2 /* TEXT */,1533 content,1534 loc: getSelection(context, start)1535 };1536}1537/**1538 * Get text data with a given length from the current location.1539 * This translates HTML entities in the text data.1540 */1541function parseTextData(context, length, mode) {1542 const rawText = context.source.slice(0, length);1543 advanceBy(context, length);1544 if (mode === 2 /* RAWTEXT */ ||1545 mode === 3 /* CDATA */ ||1546 rawText.indexOf('&') === -1) {1547 return rawText;1548 }1549 else {1550 // DATA or RCDATA containing "&"". Entity decoding required.1551 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);1552 }1553}1554function getCursor(context) {1555 const { column, line, offset } = context;1556 return { column, line, offset };1557}1558function getSelection(context, start, end) {1559 end = end || getCursor(context);1560 return {1561 start,1562 end,1563 source: context.originalSource.slice(start.offset, end.offset)1564 };1565}1566function last(xs) {1567 return xs[xs.length - 1];1568}1569function startsWith(source, searchString) {1570 return source.startsWith(searchString);1571}1572function advanceBy(context, numberOfCharacters) {1573 const { source } = context;1574 advancePositionWithMutation(context, source, numberOfCharacters);1575 context.source = source.slice(numberOfCharacters);1576}1577function advanceSpaces(context) {1578 const match = /^[\t\r\n\f ]+/.exec(context.source);1579 if (match) {1580 advanceBy(context, match[0].length);1581 }1582}1583function getNewPosition(context, start, numberOfCharacters) {1584 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1585}1586function emitError(context, code, offset, loc = getCursor(context)) {1587 if (offset) {1588 loc.offset += offset;1589 loc.column += offset;1590 }1591 context.options.onError(createCompilerError(code, {1592 start: loc,1593 end: loc,1594 source: ''1595 }));1596}1597function isEnd(context, mode, ancestors) {1598 const s = context.source;1599 switch (mode) {1600 case 0 /* DATA */:1601 if (startsWith(s, '</')) {1602 // TODO: probably bad performance1603 for (let i = ancestors.length - 1; i >= 0; --i) {1604 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1605 return true;1606 }1607 }1608 }1609 break;1610 case 1 /* RCDATA */:1611 case 2 /* RAWTEXT */: {1612 const parent = last(ancestors);1613 if (parent && startsWithEndTagOpen(s, parent.tag)) {1614 return true;1615 }1616 break;1617 }1618 case 3 /* CDATA */:1619 if (startsWith(s, ']]>')) {1620 return true;1621 }1622 break;1623 }1624 return !s;1625}1626function startsWithEndTagOpen(source, tag) {1627 return (startsWith(source, '</') &&1628 source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&1629 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));1630}1631function hoistStatic(root, context) {1632 walk(root, context, 1633 // Root node is unfortunately non-hoistable due to potential parent1634 // fallthrough attributes.1635 isSingleElementRoot(root, root.children[0]));1636}1637function isSingleElementRoot(root, child) {1638 const { children } = root;1639 return (children.length === 1 &&1640 child.type === 1 /* ELEMENT */ &&1641 !isSlotOutlet(child));1642}1643function walk(node, context, doNotHoistNode = false) {1644 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1645 // static bindings with expressions. These expressions are guaranteed to be1646 // constant so they are still eligible for hoisting, but they are only1647 // available at runtime and therefore cannot be evaluated ahead of time.1648 // This is only a concern for pre-stringification (via transformHoist by1649 // @vue/compiler-dom), but doing it here allows us to perform only one full1650 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1651 // stringification threshold is met.1652 let canStringify = true;1653 const { children } = node;1654 const originalCount = children.length;1655 let hoistedCount = 0;1656 for (let i = 0; i < children.length; i++) {1657 const child = children[i];1658 // only plain elements & text calls are eligible for hoisting.1659 if (child.type === 1 /* ELEMENT */ &&1660 child.tagType === 0 /* ELEMENT */) {1661 const constantType = doNotHoistNode1662 ? 0 /* NOT_CONSTANT */1663 : getConstantType(child, context);1664 if (constantType > 0 /* NOT_CONSTANT */) {1665 if (constantType < 3 /* CAN_STRINGIFY */) {1666 canStringify = false;1667 }1668 if (constantType >= 2 /* CAN_HOIST */) {1669 child.codegenNode.patchFlag =1670 -1 /* HOISTED */ + (` /* HOISTED */` );1671 child.codegenNode = context.hoist(child.codegenNode);1672 hoistedCount++;1673 continue;1674 }1675 }1676 else {1677 // node may contain dynamic children, but its props may be eligible for1678 // hoisting.1679 const codegenNode = child.codegenNode;1680 if (codegenNode.type === 13 /* VNODE_CALL */) {1681 const flag = getPatchFlag(codegenNode);1682 if ((!flag ||1683 flag === 512 /* NEED_PATCH */ ||1684 flag === 1 /* TEXT */) &&1685 getGeneratedPropsConstantType(child, context) >=1686 2 /* CAN_HOIST */) {1687 const props = getNodeProps(child);1688 if (props) {1689 codegenNode.props = context.hoist(props);1690 }1691 }1692 if (codegenNode.dynamicProps) {1693 codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);1694 }1695 }1696 }1697 }1698 else if (child.type === 12 /* TEXT_CALL */) {1699 const contentType = getConstantType(child.content, context);1700 if (contentType > 0) {1701 if (contentType < 3 /* CAN_STRINGIFY */) {1702 canStringify = false;1703 }1704 if (contentType >= 2 /* CAN_HOIST */) {1705 child.codegenNode = context.hoist(child.codegenNode);1706 hoistedCount++;1707 }1708 }1709 }1710 // walk further1711 if (child.type === 1 /* ELEMENT */) {1712 const isComponent = child.tagType === 1 /* COMPONENT */;1713 if (isComponent) {1714 context.scopes.vSlot++;1715 }1716 walk(child, context);1717 if (isComponent) {1718 context.scopes.vSlot--;1719 }1720 }1721 else if (child.type === 11 /* FOR */) {1722 // Do not hoist v-for single child because it has to be a block1723 walk(child, context, child.children.length === 1);1724 }1725 else if (child.type === 9 /* IF */) {1726 for (let i = 0; i < child.branches.length; i++) {1727 // Do not hoist v-if single child because it has to be a block1728 walk(child.branches[i], context, child.branches[i].children.length === 1);1729 }1730 }1731 }1732 if (canStringify && hoistedCount && context.transformHoist) {1733 context.transformHoist(children, context, node);1734 }1735 // all children were hoisted - the entire children array is hoistable.1736 if (hoistedCount &&1737 hoistedCount === originalCount &&1738 node.type === 1 /* ELEMENT */ &&1739 node.tagType === 0 /* ELEMENT */ &&1740 node.codegenNode &&1741 node.codegenNode.type === 13 /* VNODE_CALL */ &&1742 shared.isArray(node.codegenNode.children)) {1743 node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));1744 }1745}1746function getConstantType(node, context) {1747 const { constantCache } = context;1748 switch (node.type) {1749 case 1 /* ELEMENT */:1750 if (node.tagType !== 0 /* ELEMENT */) {1751 return 0 /* NOT_CONSTANT */;1752 }1753 const cached = constantCache.get(node);1754 if (cached !== undefined) {1755 return cached;1756 }1757 const codegenNode = node.codegenNode;1758 if (codegenNode.type !== 13 /* VNODE_CALL */) {1759 return 0 /* NOT_CONSTANT */;1760 }1761 const flag = getPatchFlag(codegenNode);1762 if (!flag) {1763 let returnType = 3 /* CAN_STRINGIFY */;1764 // Element itself has no patch flag. However we still need to check:1765 // 1. Even for a node with no patch flag, it is possible for it to contain1766 // non-hoistable expressions that refers to scope variables, e.g. compiler1767 // injected keys or cached event handlers. Therefore we need to always1768 // check the codegenNode's props to be sure.1769 const generatedPropsType = getGeneratedPropsConstantType(node, context);1770 if (generatedPropsType === 0 /* NOT_CONSTANT */) {1771 constantCache.set(node, 0 /* NOT_CONSTANT */);1772 return 0 /* NOT_CONSTANT */;1773 }1774 if (generatedPropsType < returnType) {1775 returnType = generatedPropsType;1776 }1777 // 2. its children.1778 for (let i = 0; i < node.children.length; i++) {1779 const childType = getConstantType(node.children[i], context);1780 if (childType === 0 /* NOT_CONSTANT */) {1781 constantCache.set(node, 0 /* NOT_CONSTANT */);1782 return 0 /* NOT_CONSTANT */;1783 }1784 if (childType < returnType) {1785 returnType = childType;1786 }1787 }1788 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-01789 // type, check if any of the props can cause the type to be lowered1790 // we can skip can_patch because it's guaranteed by the absence of a1791 // patchFlag.1792 if (returnType > 1 /* CAN_SKIP_PATCH */) {1793 for (let i = 0; i < node.props.length; i++) {1794 const p = node.props[i];1795 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {1796 const expType = getConstantType(p.exp, context);1797 if (expType === 0 /* NOT_CONSTANT */) {1798 constantCache.set(node, 0 /* NOT_CONSTANT */);1799 return 0 /* NOT_CONSTANT */;1800 }1801 if (expType < returnType) {1802 returnType = expType;1803 }1804 }1805 }1806 }1807 // only svg/foreignObject could be block here, however if they are1808 // static then they don't need to be blocks since there will be no1809 // nested updates.1810 if (codegenNode.isBlock) {1811 context.removeHelper(OPEN_BLOCK);1812 context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));1813 codegenNode.isBlock = false;1814 context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));1815 }1816 constantCache.set(node, returnType);1817 return returnType;1818 }1819 else {1820 constantCache.set(node, 0 /* NOT_CONSTANT */);1821 return 0 /* NOT_CONSTANT */;1822 }1823 case 2 /* TEXT */:1824 case 3 /* COMMENT */:1825 return 3 /* CAN_STRINGIFY */;1826 case 9 /* IF */:1827 case 11 /* FOR */:1828 case 10 /* IF_BRANCH */:1829 return 0 /* NOT_CONSTANT */;1830 case 5 /* INTERPOLATION */:1831 case 12 /* TEXT_CALL */:1832 return getConstantType(node.content, context);1833 case 4 /* SIMPLE_EXPRESSION */:1834 return node.constType;1835 case 8 /* COMPOUND_EXPRESSION */:1836 let returnType = 3 /* CAN_STRINGIFY */;1837 for (let i = 0; i < node.children.length; i++) {1838 const child = node.children[i];1839 if (shared.isString(child) || shared.isSymbol(child)) {1840 continue;1841 }1842 const childType = getConstantType(child, context);1843 if (childType === 0 /* NOT_CONSTANT */) {1844 return 0 /* NOT_CONSTANT */;1845 }1846 else if (childType < returnType) {1847 returnType = childType;1848 }1849 }1850 return returnType;1851 default:1852 return 0 /* NOT_CONSTANT */;1853 }1854}1855const allowHoistedHelperSet = new Set([1856 NORMALIZE_CLASS,1857 NORMALIZE_STYLE,1858 NORMALIZE_PROPS,1859 GUARD_REACTIVE_PROPS1860]);1861function getConstantTypeOfHelperCall(value, context) {1862 if (value.type === 14 /* JS_CALL_EXPRESSION */ &&1863 !shared.isString(value.callee) &&1864 allowHoistedHelperSet.has(value.callee)) {1865 const arg = value.arguments[0];1866 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {1867 return getConstantType(arg, context);1868 }1869 else if (arg.type === 14 /* JS_CALL_EXPRESSION */) {1870 // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`1871 return getConstantTypeOfHelperCall(arg, context);1872 }1873 }1874 return 0 /* NOT_CONSTANT */;1875}1876function getGeneratedPropsConstantType(node, context) {1877 let returnType = 3 /* CAN_STRINGIFY */;1878 const props = getNodeProps(node);1879 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {1880 const { properties } = props;1881 for (let i = 0; i < properties.length; i++) {1882 const { key, value } = properties[i];1883 const keyType = getConstantType(key, context);1884 if (keyType === 0 /* NOT_CONSTANT */) {1885 return keyType;1886 }1887 if (keyType < returnType) {1888 returnType = keyType;1889 }1890 let valueType;1891 if (value.type === 4 /* SIMPLE_EXPRESSION */) {1892 valueType = getConstantType(value, context);1893 }1894 else if (value.type === 14 /* JS_CALL_EXPRESSION */) {1895 // some helper calls can be hoisted,1896 // such as the `normalizeProps` generated by the compiler for pre-normalize class,1897 // in this case we need to respect the ConstantType of the helper's argments1898 valueType = getConstantTypeOfHelperCall(value, context);1899 }1900 else {1901 valueType = 0 /* NOT_CONSTANT */;1902 }1903 if (valueType === 0 /* NOT_CONSTANT */) {1904 return valueType;1905 }1906 if (valueType < returnType) {1907 returnType = valueType;1908 }1909 }1910 }1911 return returnType;1912}1913function getNodeProps(node) {1914 const codegenNode = node.codegenNode;1915 if (codegenNode.type === 13 /* VNODE_CALL */) {1916 return codegenNode.props;1917 }1918}1919function getPatchFlag(node) {1920 const flag = node.patchFlag;1921 return flag ? parseInt(flag, 10) : undefined;1922}1923function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {1924 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);1925 const context = {1926 // options1927 selfName: nameMatch && shared.capitalize(shared.camelize(nameMatch[1])),1928 prefixIdentifiers,1929 hoistStatic,1930 cacheHandlers,1931 nodeTransforms,1932 directiveTransforms,1933 transformHoist,1934 isBuiltInComponent,1935 isCustomElement,1936 expressionPlugins,1937 scopeId,1938 slotted,1939 ssr,1940 inSSR,1941 ssrCssVars,1942 bindingMetadata,1943 inline,1944 isTS,1945 onError,1946 onWarn,1947 compatConfig,1948 // state1949 root,1950 helpers: new Map(),1951 components: new Set(),1952 directives: new Set(),1953 hoists: [],1954 imports: [],1955 constantCache: new Map(),1956 temps: 0,1957 cached: 0,1958 identifiers: Object.create(null),1959 scopes: {1960 vFor: 0,1961 vSlot: 0,1962 vPre: 0,1963 vOnce: 01964 },1965 parent: null,1966 currentNode: root,1967 childIndex: 0,1968 inVOnce: false,1969 // methods1970 helper(name) {1971 const count = context.helpers.get(name) || 0;1972 context.helpers.set(name, count + 1);1973 return name;1974 },1975 removeHelper(name) {1976 const count = context.helpers.get(name);1977 if (count) {1978 const currentCount = count - 1;1979 if (!currentCount) {1980 context.helpers.delete(name);1981 }1982 else {1983 context.helpers.set(name, currentCount);1984 }1985 }1986 },1987 helperString(name) {1988 return `_${helperNameMap[context.helper(name)]}`;1989 },1990 replaceNode(node) {1991 /* istanbul ignore if */1992 {1993 if (!context.currentNode) {1994 throw new Error(`Node being replaced is already removed.`);1995 }1996 if (!context.parent) {1997 throw new Error(`Cannot replace root node.`);1998 }1999 }2000 context.parent.children[context.childIndex] = context.currentNode = node;2001 },2002 removeNode(node) {2003 if (!context.parent) {2004 throw new Error(`Cannot remove root node.`);2005 }2006 const list = context.parent.children;2007 const removalIndex = node2008 ? list.indexOf(node)2009 : context.currentNode2010 ? context.childIndex2011 : -1;2012 /* istanbul ignore if */2013 if (removalIndex < 0) {2014 throw new Error(`node being removed is not a child of current parent`);2015 }2016 if (!node || node === context.currentNode) {2017 // current node removed2018 context.currentNode = null;2019 context.onNodeRemoved();2020 }2021 else {2022 // sibling node removed2023 if (context.childIndex > removalIndex) {2024 context.childIndex--;2025 context.onNodeRemoved();2026 }2027 }2028 context.parent.children.splice(removalIndex, 1);2029 },2030 onNodeRemoved: () => { },2031 addIdentifiers(exp) {2032 // identifier tracking only happens in non-browser builds.2033 {2034 if (shared.isString(exp)) {2035 addId(exp);2036 }2037 else if (exp.identifiers) {2038 exp.identifiers.forEach(addId);2039 }2040 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {2041 addId(exp.content);2042 }2043 }2044 },2045 removeIdentifiers(exp) {2046 {2047 if (shared.isString(exp)) {2048 removeId(exp);2049 }2050 else if (exp.identifiers) {2051 exp.identifiers.forEach(removeId);2052 }2053 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {2054 removeId(exp.content);2055 }2056 }2057 },2058 hoist(exp) {2059 if (shared.isString(exp))2060 exp = createSimpleExpression(exp);2061 context.hoists.push(exp);2062 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);2063 identifier.hoisted = exp;2064 return identifier;2065 },2066 cache(exp, isVNode = false) {2067 return createCacheExpression(context.cached++, exp, isVNode);2068 }2069 };2070 {2071 context.filters = new Set();2072 }2073 function addId(id) {2074 const { identifiers } = context;2075 if (identifiers[id] === undefined) {2076 identifiers[id] = 0;2077 }2078 identifiers[id]++;2079 }2080 function removeId(id) {2081 context.identifiers[id]--;2082 }2083 return context;2084}2085function transform(root, options) {2086 const context = createTransformContext(root, options);2087 traverseNode(root, context);2088 if (options.hoistStatic) {2089 hoistStatic(root, context);2090 }2091 if (!options.ssr) {2092 createRootCodegen(root, context);2093 }2094 // finalize meta information2095 root.helpers = [...context.helpers.keys()];2096 root.components = [...context.components];2097 root.directives = [...context.directives];2098 root.imports = context.imports;2099 root.hoists = context.hoists;2100 root.temps = context.temps;2101 root.cached = context.cached;2102 {2103 root.filters = [...context.filters];2104 }2105}2106function createRootCodegen(root, context) {2107 const { helper } = context;2108 const { children } = root;2109 if (children.length === 1) {2110 const child = children[0];2111 // if the single child is an element, turn it into a block.2112 if (isSingleElementRoot(root, child) && child.codegenNode) {2113 // single element root is never hoisted so codegenNode will never be2114 // SimpleExpressionNode2115 const codegenNode = child.codegenNode;2116 if (codegenNode.type === 13 /* VNODE_CALL */) {2117 makeBlock(codegenNode, context);2118 }2119 root.codegenNode = codegenNode;2120 }2121 else {2122 // - single <slot/>, IfNode, ForNode: already blocks.2123 // - single text node: always patched.2124 // root codegen falls through via genNode()2125 root.codegenNode = child;2126 }2127 }2128 else if (children.length > 1) {2129 // root has multiple nodes - return a fragment block.2130 let patchFlag = 64 /* STABLE_FRAGMENT */;2131 let patchFlagText = shared.PatchFlagNames[64 /* STABLE_FRAGMENT */];2132 // check if the fragment actually contains a single valid child with2133 // the rest being comments2134 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2135 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2136 patchFlagText += `, ${shared.PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;2137 }2138 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, undefined, false /* isComponent */);2139 }2140 else ;2141}2142function traverseChildren(parent, context) {2143 let i = 0;2144 const nodeRemoved = () => {2145 i--;2146 };2147 for (; i < parent.children.length; i++) {2148 const child = parent.children[i];2149 if (shared.isString(child))2150 continue;2151 context.parent = parent;2152 context.childIndex = i;2153 context.onNodeRemoved = nodeRemoved;2154 traverseNode(child, context);2155 }2156}2157function traverseNode(node, context) {2158 context.currentNode = node;2159 // apply transform plugins2160 const { nodeTransforms } = context;2161 const exitFns = [];2162 for (let i = 0; i < nodeTransforms.length; i++) {2163 const onExit = nodeTransforms[i](node, context);2164 if (onExit) {2165 if (shared.isArray(onExit)) {2166 exitFns.push(...onExit);2167 }2168 else {2169 exitFns.push(onExit);2170 }2171 }2172 if (!context.currentNode) {2173 // node was removed2174 return;2175 }2176 else {2177 // node may have been replaced2178 node = context.currentNode;2179 }2180 }2181 switch (node.type) {2182 case 3 /* COMMENT */:2183 if (!context.ssr) {2184 // inject import for the Comment symbol, which is needed for creating2185 // comment nodes with `createVNode`2186 context.helper(CREATE_COMMENT);2187 }2188 break;2189 case 5 /* INTERPOLATION */:2190 // no need to traverse, but we need to inject toString helper2191 if (!context.ssr) {2192 context.helper(TO_DISPLAY_STRING);2193 }2194 break;2195 // for container types, further traverse downwards2196 case 9 /* IF */:2197 for (let i = 0; i < node.branches.length; i++) {2198 traverseNode(node.branches[i], context);2199 }2200 break;2201 case 10 /* IF_BRANCH */:2202 case 11 /* FOR */:2203 case 1 /* ELEMENT */:2204 case 0 /* ROOT */:2205 traverseChildren(node, context);2206 break;2207 }2208 // exit transforms2209 context.currentNode = node;2210 let i = exitFns.length;2211 while (i--) {2212 exitFns[i]();2213 }2214}2215function createStructuralDirectiveTransform(name, fn) {2216 const matches = shared.isString(name)2217 ? (n) => n === name2218 : (n) => name.test(n);2219 return (node, context) => {2220 if (node.type === 1 /* ELEMENT */) {2221 const { props } = node;2222 // structural directive transforms are not concerned with slots2223 // as they are handled separately in vSlot.ts2224 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2225 return;2226 }2227 const exitFns = [];2228 for (let i = 0; i < props.length; i++) {2229 const prop = props[i];2230 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2231 // structural directives are removed to avoid infinite recursion2232 // also we remove them *before* applying so that it can further2233 // traverse itself in case it moves the node around2234 props.splice(i, 1);2235 i--;2236 const onExit = fn(node, prop, context);2237 if (onExit)2238 exitFns.push(onExit);2239 }2240 }2241 return exitFns;2242 }2243 };2244}2245const PURE_ANNOTATION = `/*#__PURE__*/`;2246function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap: sourceMap$1 = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {2247 const context = {2248 mode,2249 prefixIdentifiers,2250 sourceMap: sourceMap$1,2251 filename,2252 scopeId,2253 optimizeImports,2254 runtimeGlobalName,2255 runtimeModuleName,2256 ssrRuntimeModuleName,2257 ssr,2258 isTS,2259 inSSR,2260 source: ast.loc.source,2261 code: ``,2262 column: 1,2263 line: 1,2264 offset: 0,2265 indentLevel: 0,2266 pure: false,2267 map: undefined,2268 helper(key) {2269 return `_${helperNameMap[key]}`;2270 },2271 push(code, node) {2272 context.code += code;2273 if (context.map) {2274 if (node) {2275 let name;2276 if (node.type === 4 /* SIMPLE_EXPRESSION */ && !node.isStatic) {2277 const content = node.content.replace(/^_ctx\./, '');2278 if (content !== node.content && isSimpleIdentifier(content)) {2279 name = content;2280 }2281 }2282 addMapping(node.loc.start, name);2283 }2284 advancePositionWithMutation(context, code);2285 if (node && node.loc !== locStub) {2286 addMapping(node.loc.end);2287 }2288 }2289 },2290 indent() {2291 newline(++context.indentLevel);2292 },2293 deindent(withoutNewLine = false) {2294 if (withoutNewLine) {2295 --context.indentLevel;2296 }2297 else {2298 newline(--context.indentLevel);2299 }2300 },2301 newline() {2302 newline(context.indentLevel);2303 }2304 };2305 function newline(n) {2306 context.push('\n' + ` `.repeat(n));2307 }2308 function addMapping(loc, name) {2309 context.map.addMapping({2310 name,2311 source: context.filename,2312 original: {2313 line: loc.line,2314 column: loc.column - 1 // source-map column is 0 based2315 },2316 generated: {2317 line: context.line,2318 column: context.column - 12319 }2320 });2321 }2322 if (sourceMap$1) {2323 // lazy require source-map implementation, only in non-browser builds2324 context.map = new sourceMap.SourceMapGenerator();2325 context.map.setSourceContent(filename, context.source);2326 }2327 return context;2328}2329function generate(ast, options = {}) {2330 const context = createCodegenContext(ast, options);2331 if (options.onContextCreated)2332 options.onContextCreated(context);2333 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2334 const hasHelpers = ast.helpers.length > 0;2335 const useWithBlock = !prefixIdentifiers && mode !== 'module';2336 const genScopeId = scopeId != null && mode === 'module';2337 const isSetupInlined = !!options.inline;2338 // preambles2339 // in setup() inline mode, the preamble is generated in a sub context2340 // and returned separately.2341 const preambleContext = isSetupInlined2342 ? createCodegenContext(ast, options)2343 : context;2344 if (mode === 'module') {2345 genModulePreamble(ast, preambleContext, genScopeId, isSetupInlined);2346 }2347 else {2348 genFunctionPreamble(ast, preambleContext);2349 }2350 // enter render function2351 const functionName = ssr ? `ssrRender` : `render`;2352 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2353 if (options.bindingMetadata && !options.inline) {2354 // binding optimization args2355 args.push('$props', '$setup', '$data', '$options');2356 }2357 const signature = options.isTS2358 ? args.map(arg => `${arg}: any`).join(',')2359 : args.join(', ');2360 if (isSetupInlined) {2361 push(`(${signature}) => {`);2362 }2363 else {2364 push(`function ${functionName}(${signature}) {`);2365 }2366 indent();2367 if (useWithBlock) {2368 push(`with (_ctx) {`);2369 indent();2370 // function mode const declarations should be inside with block2371 // also they should be renamed to avoid collision with user properties2372 if (hasHelpers) {2373 push(`const { ${ast.helpers2374 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2375 .join(', ')} } = _Vue`);2376 push(`\n`);2377 newline();2378 }2379 }2380 // generate asset resolution statements2381 if (ast.components.length) {2382 genAssets(ast.components, 'component', context);2383 if (ast.directives.length || ast.temps > 0) {2384 newline();2385 }2386 }2387 if (ast.directives.length) {2388 genAssets(ast.directives, 'directive', context);2389 if (ast.temps > 0) {2390 newline();2391 }2392 }2393 if (ast.filters && ast.filters.length) {2394 newline();2395 genAssets(ast.filters, 'filter', context);2396 newline();2397 }2398 if (ast.temps > 0) {2399 push(`let `);2400 for (let i = 0; i < ast.temps; i++) {2401 push(`${i > 0 ? `, ` : ``}_temp${i}`);2402 }2403 }2404 if (ast.components.length || ast.directives.length || ast.temps) {2405 push(`\n`);2406 newline();2407 }2408 // generate the VNode tree expression2409 if (!ssr) {2410 push(`return `);2411 }2412 if (ast.codegenNode) {2413 genNode(ast.codegenNode, context);2414 }2415 else {2416 push(`null`);2417 }2418 if (useWithBlock) {2419 deindent();2420 push(`}`);2421 }2422 deindent();2423 push(`}`);2424 return {2425 ast,2426 code: context.code,2427 preamble: isSetupInlined ? preambleContext.code : ``,2428 // SourceMapGenerator does have toJSON() method but it's not in the types2429 map: context.map ? context.map.toJSON() : undefined2430 };2431}2432function genFunctionPreamble(ast, context) {2433 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;2434 const VueBinding = ssr2435 ? `require(${JSON.stringify(runtimeModuleName)})`2436 : runtimeGlobalName;2437 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2438 // Generate const declaration for helpers2439 // In prefix mode, we place the const declaration at top so it's done2440 // only once; But if we not prefixing, we place the declaration inside the2441 // with block so it doesn't incur the `in` check cost for every helper access.2442 if (ast.helpers.length > 0) {2443 if (prefixIdentifiers) {2444 push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`);2445 }2446 else {2447 // "with" mode.2448 // save Vue in a separate variable to avoid collision2449 push(`const _Vue = ${VueBinding}\n`);2450 // in "with" mode, helpers are declared inside the with block to avoid2451 // has check cost, but hoists are lifted out of the function - we need2452 // to provide the helper here.2453 if (ast.hoists.length) {2454 const staticHelpers = [2455 CREATE_VNODE,2456 CREATE_ELEMENT_VNODE,2457 CREATE_COMMENT,2458 CREATE_TEXT,2459 CREATE_STATIC2460 ]2461 .filter(helper => ast.helpers.includes(helper))2462 .map(aliasHelper)2463 .join(', ');2464 push(`const { ${staticHelpers} } = _Vue\n`);2465 }2466 }2467 }2468 // generate variables for ssr helpers2469 if (ast.ssrHelpers && ast.ssrHelpers.length) {2470 // ssr guarantees prefixIdentifier: true2471 push(`const { ${ast.ssrHelpers2472 .map(aliasHelper)2473 .join(', ')} } = require("${ssrRuntimeModuleName}")\n`);2474 }2475 genHoists(ast.hoists, context);2476 newline();2477 push(`return `);2478}2479function genModulePreamble(ast, context, genScopeId, inline) {2480 const { push, newline, optimizeImports, runtimeModuleName, ssrRuntimeModuleName } = context;2481 if (genScopeId && ast.hoists.length) {2482 ast.helpers.push(PUSH_SCOPE_ID, POP_SCOPE_ID);2483 }2484 // generate import statements for helpers2485 if (ast.helpers.length) {2486 if (optimizeImports) {2487 // when bundled with webpack with code-split, calling an import binding2488 // as a function leads to it being wrapped with `Object(a.b)` or `(0,a.b)`,2489 // incurring both payload size increase and potential perf overhead.2490 // therefore we assign the imports to variables (which is a constant ~50b2491 // cost per-component instead of scaling with template size)2492 push(`import { ${ast.helpers2493 .map(s => helperNameMap[s])2494 .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`);2495 push(`\n// Binding optimization for webpack code-split\nconst ${ast.helpers2496 .map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)2497 .join(', ')}\n`);2498 }2499 else {2500 push(`import { ${ast.helpers2501 .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)2502 .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`);2503 }2504 }2505 if (ast.ssrHelpers && ast.ssrHelpers.length) {2506 push(`import { ${ast.ssrHelpers2507 .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)2508 .join(', ')} } from "${ssrRuntimeModuleName}"\n`);2509 }2510 if (ast.imports.length) {2511 genImports(ast.imports, context);2512 newline();2513 }2514 genHoists(ast.hoists, context);2515 newline();2516 if (!inline) {2517 push(`export `);2518 }2519}2520function genAssets(assets, type, { helper, push, newline, isTS }) {2521 const resolver = helper(type === 'filter'2522 ? RESOLVE_FILTER2523 : type === 'component'2524 ? RESOLVE_COMPONENT2525 : RESOLVE_DIRECTIVE);2526 for (let i = 0; i < assets.length; i++) {2527 let id = assets[i];2528 // potential component implicit self-reference inferred from SFC filename2529 const maybeSelfReference = id.endsWith('__self');2530 if (maybeSelfReference) {2531 id = id.slice(0, -6);2532 }2533 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);2534 if (i < assets.length - 1) {2535 newline();2536 }2537 }2538}2539function genHoists(hoists, context) {2540 if (!hoists.length) {2541 return;2542 }2543 context.pure = true;2544 const { push, newline, helper, scopeId, mode } = context;2545 const genScopeId = scopeId != null && mode !== 'function';2546 newline();2547 // generate inlined withScopeId helper2548 if (genScopeId) {2549 push(`const _withScopeId = n => (${helper(PUSH_SCOPE_ID)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`);2550 newline();2551 }2552 for (let i = 0; i < hoists.length; i++) {2553 const exp = hoists[i];2554 if (exp) {2555 const needScopeIdWrapper = genScopeId && exp.type === 13 /* VNODE_CALL */;2556 push(`const _hoisted_${i + 1} = ${needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : ``}`);2557 genNode(exp, context);2558 if (needScopeIdWrapper) {2559 push(`)`);2560 }2561 newline();2562 }2563 }2564 context.pure = false;2565}2566function genImports(importsOptions, context) {2567 if (!importsOptions.length) {2568 return;2569 }2570 importsOptions.forEach(imports => {2571 context.push(`import `);2572 genNode(imports.exp, context);2573 context.push(` from '${imports.path}'`);2574 context.newline();2575 });2576}2577function isText$1(n) {2578 return (shared.isString(n) ||2579 n.type === 4 /* SIMPLE_EXPRESSION */ ||2580 n.type === 2 /* TEXT */ ||2581 n.type === 5 /* INTERPOLATION */ ||2582 n.type === 8 /* COMPOUND_EXPRESSION */);2583}2584function genNodeListAsArray(nodes, context) {2585 const multilines = nodes.length > 3 ||2586 (nodes.some(n => shared.isArray(n) || !isText$1(n)));2587 context.push(`[`);2588 multilines && context.indent();2589 genNodeList(nodes, context, multilines);2590 multilines && context.deindent();2591 context.push(`]`);2592}2593function genNodeList(nodes, context, multilines = false, comma = true) {2594 const { push, newline } = context;2595 for (let i = 0; i < nodes.length; i++) {2596 const node = nodes[i];2597 if (shared.isString(node)) {2598 push(node);2599 }2600 else if (shared.isArray(node)) {2601 genNodeListAsArray(node, context);2602 }2603 else {2604 genNode(node, context);2605 }2606 if (i < nodes.length - 1) {2607 if (multilines) {2608 comma && push(',');2609 newline();2610 }2611 else {2612 comma && push(', ');2613 }2614 }2615 }2616}2617function genNode(node, context) {2618 if (shared.isString(node)) {2619 context.push(node);2620 return;2621 }2622 if (shared.isSymbol(node)) {2623 context.push(context.helper(node));2624 return;2625 }2626 switch (node.type) {2627 case 1 /* ELEMENT */:2628 case 9 /* IF */:2629 case 11 /* FOR */:2630 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2631 `Apply appropriate transforms first.`);2632 genNode(node.codegenNode, context);2633 break;2634 case 2 /* TEXT */:2635 genText(node, context);2636 break;2637 case 4 /* SIMPLE_EXPRESSION */:2638 genExpression(node, context);2639 break;2640 case 5 /* INTERPOLATION */:2641 genInterpolation(node, context);2642 break;2643 case 12 /* TEXT_CALL */:2644 genNode(node.codegenNode, context);2645 break;2646 case 8 /* COMPOUND_EXPRESSION */:2647 genCompoundExpression(node, context);2648 break;2649 case 3 /* COMMENT */:2650 genComment(node, context);2651 break;2652 case 13 /* VNODE_CALL */:2653 genVNodeCall(node, context);2654 break;2655 case 14 /* JS_CALL_EXPRESSION */:2656 genCallExpression(node, context);2657 break;2658 case 15 /* JS_OBJECT_EXPRESSION */:2659 genObjectExpression(node, context);2660 break;2661 case 17 /* JS_ARRAY_EXPRESSION */:2662 genArrayExpression(node, context);2663 break;2664 case 18 /* JS_FUNCTION_EXPRESSION */:2665 genFunctionExpression(node, context);2666 break;2667 case 19 /* JS_CONDITIONAL_EXPRESSION */:2668 genConditionalExpression(node, context);2669 break;2670 case 20 /* JS_CACHE_EXPRESSION */:2671 genCacheExpression(node, context);2672 break;2673 case 21 /* JS_BLOCK_STATEMENT */:2674 genNodeList(node.body, context, true, false);2675 break;2676 // SSR only types2677 case 22 /* JS_TEMPLATE_LITERAL */:2678 genTemplateLiteral(node, context);2679 break;2680 case 23 /* JS_IF_STATEMENT */:2681 genIfStatement(node, context);2682 break;2683 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2684 genAssignmentExpression(node, context);2685 break;2686 case 25 /* JS_SEQUENCE_EXPRESSION */:2687 genSequenceExpression(node, context);2688 break;2689 case 26 /* JS_RETURN_STATEMENT */:2690 genReturnStatement(node, context);2691 break;2692 /* istanbul ignore next */2693 case 10 /* IF_BRANCH */:2694 // noop2695 break;2696 default:2697 {2698 assert(false, `unhandled codegen node type: ${node.type}`);2699 // make sure we exhaust all possible types2700 const exhaustiveCheck = node;2701 return exhaustiveCheck;2702 }2703 }2704}2705function genText(node, context) {2706 context.push(JSON.stringify(node.content), node);2707}2708function genExpression(node, context) {2709 const { content, isStatic } = node;2710 context.push(isStatic ? JSON.stringify(content) : content, node);2711}2712function genInterpolation(node, context) {2713 const { push, helper, pure } = context;2714 if (pure)2715 push(PURE_ANNOTATION);2716 push(`${helper(TO_DISPLAY_STRING)}(`);2717 genNode(node.content, context);2718 push(`)`);2719}2720function genCompoundExpression(node, context) {2721 for (let i = 0; i < node.children.length; i++) {2722 const child = node.children[i];2723 if (shared.isString(child)) {2724 context.push(child);2725 }2726 else {2727 genNode(child, context);2728 }2729 }2730}2731function genExpressionAsPropertyKey(node, context) {2732 const { push } = context;2733 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2734 push(`[`);2735 genCompoundExpression(node, context);2736 push(`]`);2737 }2738 else if (node.isStatic) {2739 // only quote keys if necessary2740 const text = isSimpleIdentifier(node.content)2741 ? node.content2742 : JSON.stringify(node.content);2743 push(text, node);2744 }2745 else {2746 push(`[${node.content}]`, node);2747 }2748}2749function genComment(node, context) {2750 const { push, helper, pure } = context;2751 if (pure) {2752 push(PURE_ANNOTATION);2753 }2754 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2755}2756function genVNodeCall(node, context) {2757 const { push, helper, pure } = context;2758 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;2759 if (directives) {2760 push(helper(WITH_DIRECTIVES) + `(`);2761 }2762 if (isBlock) {2763 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);2764 }2765 if (pure) {2766 push(PURE_ANNOTATION);2767 }2768 const callHelper = isBlock2769 ? getVNodeBlockHelper(context.inSSR, isComponent)2770 : getVNodeHelper(context.inSSR, isComponent);2771 push(helper(callHelper) + `(`, node);2772 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2773 push(`)`);2774 if (isBlock) {2775 push(`)`);2776 }2777 if (directives) {2778 push(`, `);2779 genNode(directives, context);2780 push(`)`);2781 }2782}2783function genNullableArgs(args) {2784 let i = args.length;2785 while (i--) {2786 if (args[i] != null)2787 break;2788 }2789 return args.slice(0, i + 1).map(arg => arg || `null`);2790}2791// JavaScript2792function genCallExpression(node, context) {2793 const { push, helper, pure } = context;2794 const callee = shared.isString(node.callee) ? node.callee : helper(node.callee);2795 if (pure) {2796 push(PURE_ANNOTATION);2797 }2798 push(callee + `(`, node);2799 genNodeList(node.arguments, context);2800 push(`)`);2801}2802function genObjectExpression(node, context) {2803 const { push, indent, deindent, newline } = context;2804 const { properties } = node;2805 if (!properties.length) {2806 push(`{}`, node);2807 return;2808 }2809 const multilines = properties.length > 1 ||2810 (properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2811 push(multilines ? `{` : `{ `);2812 multilines && indent();2813 for (let i = 0; i < properties.length; i++) {2814 const { key, value } = properties[i];2815 // key2816 genExpressionAsPropertyKey(key, context);2817 push(`: `);2818 // value2819 genNode(value, context);2820 if (i < properties.length - 1) {2821 // will only reach this if it's multilines2822 push(`,`);2823 newline();2824 }2825 }2826 multilines && deindent();2827 push(multilines ? `}` : ` }`);2828}2829function genArrayExpression(node, context) {2830 genNodeListAsArray(node.elements, context);2831}2832function genFunctionExpression(node, context) {2833 const { push, indent, deindent } = context;2834 const { params, returns, body, newline, isSlot } = node;2835 if (isSlot) {2836 // wrap slot functions with owner context2837 push(`_${helperNameMap[WITH_CTX]}(`);2838 }2839 push(`(`, node);2840 if (shared.isArray(params)) {2841 genNodeList(params, context);2842 }2843 else if (params) {2844 genNode(params, context);2845 }2846 push(`) => `);2847 if (newline || body) {2848 push(`{`);2849 indent();2850 }2851 if (returns) {2852 if (newline) {2853 push(`return `);2854 }2855 if (shared.isArray(returns)) {2856 genNodeListAsArray(returns, context);2857 }2858 else {2859 genNode(returns, context);2860 }2861 }2862 else if (body) {2863 genNode(body, context);2864 }2865 if (newline || body) {2866 deindent();2867 push(`}`);2868 }2869 if (isSlot) {2870 if (node.isNonScopedSlot) {2871 push(`, undefined, true`);2872 }2873 push(`)`);2874 }2875}2876function genConditionalExpression(node, context) {2877 const { test, consequent, alternate, newline: needNewline } = node;2878 const { push, indent, deindent, newline } = context;2879 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2880 const needsParens = !isSimpleIdentifier(test.content);2881 needsParens && push(`(`);2882 genExpression(test, context);2883 needsParens && push(`)`);2884 }2885 else {2886 push(`(`);2887 genNode(test, context);2888 push(`)`);2889 }2890 needNewline && indent();2891 context.indentLevel++;2892 needNewline || push(` `);2893 push(`? `);2894 genNode(consequent, context);2895 context.indentLevel--;2896 needNewline && newline();2897 needNewline || push(` `);2898 push(`: `);2899 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2900 if (!isNested) {2901 context.indentLevel++;2902 }2903 genNode(alternate, context);2904 if (!isNested) {2905 context.indentLevel--;2906 }2907 needNewline && deindent(true /* without newline */);2908}2909function genCacheExpression(node, context) {2910 const { push, helper, indent, deindent, newline } = context;2911 push(`_cache[${node.index}] || (`);2912 if (node.isVNode) {2913 indent();2914 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2915 newline();2916 }2917 push(`_cache[${node.index}] = `);2918 genNode(node.value, context);2919 if (node.isVNode) {2920 push(`,`);2921 newline();2922 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2923 newline();2924 push(`_cache[${node.index}]`);2925 deindent();2926 }2927 push(`)`);2928}2929function genTemplateLiteral(node, context) {2930 const { push, indent, deindent } = context;2931 push('`');2932 const l = node.elements.length;2933 const multilines = l > 3;2934 for (let i = 0; i < l; i++) {2935 const e = node.elements[i];2936 if (shared.isString(e)) {2937 push(e.replace(/(`|\$|\\)/g, '\\$1'));2938 }2939 else {2940 push('${');2941 if (multilines)2942 indent();2943 genNode(e, context);2944 if (multilines)2945 deindent();2946 push('}');2947 }2948 }2949 push('`');2950}2951function genIfStatement(node, context) {2952 const { push, indent, deindent } = context;2953 const { test, consequent, alternate } = node;2954 push(`if (`);2955 genNode(test, context);2956 push(`) {`);2957 indent();2958 genNode(consequent, context);2959 deindent();2960 push(`}`);2961 if (alternate) {2962 push(` else `);2963 if (alternate.type === 23 /* JS_IF_STATEMENT */) {2964 genIfStatement(alternate, context);2965 }2966 else {2967 push(`{`);2968 indent();2969 genNode(alternate, context);2970 deindent();2971 push(`}`);2972 }2973 }2974}2975function genAssignmentExpression(node, context) {2976 genNode(node.left, context);2977 context.push(` = `);2978 genNode(node.right, context);2979}2980function genSequenceExpression(node, context) {2981 context.push(`(`);2982 genNodeList(node.expressions, context);2983 context.push(`)`);2984}2985function genReturnStatement({ returns }, context) {2986 context.push(`return `);2987 if (shared.isArray(returns)) {2988 genNodeListAsArray(returns, context);2989 }2990 else {2991 genNode(returns, context);2992 }2993}2994function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {2995 const rootExp = root.type === 'Program' &&2996 root.body[0].type === 'ExpressionStatement' &&2997 root.body[0].expression;2998 estreeWalker.walk(root, {2999 enter(node, parent) {3000 parent && parentStack.push(parent);3001 if (parent &&3002 parent.type.startsWith('TS') &&3003 parent.type !== 'TSAsExpression' &&3004 parent.type !== 'TSNonNullExpression' &&3005 parent.type !== 'TSTypeAssertion') {3006 return this.skip();3007 }3008 if (node.type === 'Identifier') {3009 const isLocal = !!knownIds[node.name];3010 const isRefed = isReferencedIdentifier(node, parent, parentStack);3011 if (includeAll || (isRefed && !isLocal)) {3012 onIdentifier(node, parent, parentStack, isRefed, isLocal);3013 }3014 }3015 else if (node.type === 'ObjectProperty' &&3016 parent.type === 'ObjectPattern') {3017 node.inPattern = true;3018 }3019 else if (isFunctionType(node)) {3020 // walk function expressions and add its arguments to known identifiers3021 // so that we don't prefix them3022 walkFunctionParams(node, id => markScopeIdentifier(node, id, knownIds));3023 }3024 else if (node.type === 'BlockStatement') {3025 // #3445 record block-level local variables3026 walkBlockDeclarations(node, id => markScopeIdentifier(node, id, knownIds));3027 }3028 },3029 leave(node, parent) {3030 parent && parentStack.pop();3031 if (node !== rootExp && node.scopeIds) {3032 for (const id of node.scopeIds) {3033 knownIds[id]--;3034 if (knownIds[id] === 0) {3035 delete knownIds[id];3036 }3037 }3038 }3039 }3040 });3041}3042function isReferencedIdentifier(id, parent, parentStack) {3043 if (!parent) {3044 return true;3045 }3046 // is a special keyword but parsed as identifier3047 if (id.name === 'arguments') {3048 return false;3049 }3050 if (isReferenced(id, parent)) {3051 return true;3052 }3053 // babel's isReferenced check returns false for ids being assigned to, so we3054 // need to cover those cases here3055 switch (parent.type) {3056 case 'AssignmentExpression':3057 case 'AssignmentPattern':3058 return true;3059 case 'ObjectPattern':3060 case 'ArrayPattern':3061 return isInDestructureAssignment(parent, parentStack);3062 }3063 return false;3064}3065function isInDestructureAssignment(parent, parentStack) {3066 if (parent &&3067 (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {3068 let i = parentStack.length;3069 while (i--) {3070 const p = parentStack[i];3071 if (p.type === 'AssignmentExpression') {3072 return true;3073 }3074 else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {3075 break;3076 }3077 }3078 }3079 return false;3080}3081function walkFunctionParams(node, onIdent) {3082 for (const p of node.params) {3083 for (const id of extractIdentifiers(p)) {3084 onIdent(id);3085 }3086 }3087}3088function walkBlockDeclarations(block, onIdent) {3089 for (const stmt of block.body) {3090 if (stmt.type === 'VariableDeclaration') {3091 if (stmt.declare)3092 continue;3093 for (const decl of stmt.declarations) {3094 for (const id of extractIdentifiers(decl.id)) {3095 onIdent(id);3096 }3097 }3098 }3099 else if (stmt.type === 'FunctionDeclaration' ||3100 stmt.type === 'ClassDeclaration') {3101 if (stmt.declare || !stmt.id)3102 continue;3103 onIdent(stmt.id);3104 }3105 }3106}3107function extractIdentifiers(param, nodes = []) {3108 switch (param.type) {3109 case 'Identifier':3110 nodes.push(param);3111 break;3112 case 'MemberExpression':3113 let object = param;3114 while (object.type === 'MemberExpression') {3115 object = object.object;3116 }3117 nodes.push(object);3118 break;3119 case 'ObjectPattern':3120 for (const prop of param.properties) {3121 if (prop.type === 'RestElement') {3122 extractIdentifiers(prop.argument, nodes);3123 }3124 else {3125 extractIdentifiers(prop.value, nodes);3126 }3127 }3128 break;3129 case 'ArrayPattern':3130 param.elements.forEach(element => {3131 if (element)3132 extractIdentifiers(element, nodes);3133 });3134 break;3135 case 'RestElement':3136 extractIdentifiers(param.argument, nodes);3137 break;3138 case 'AssignmentPattern':3139 extractIdentifiers(param.left, nodes);3140 break;3141 }3142 return nodes;3143}3144function markScopeIdentifier(node, child, knownIds) {3145 const { name } = child;3146 if (node.scopeIds && node.scopeIds.has(name)) {3147 return;3148 }3149 if (name in knownIds) {3150 knownIds[name]++;3151 }3152 else {3153 knownIds[name] = 1;3154 }3155 (node.scopeIds || (node.scopeIds = new Set())).add(name);3156}3157const isFunctionType = (node) => {3158 return /Function(?:Expression|Declaration)$|Method$/.test(node.type);3159};3160const isStaticProperty = (node) => node &&3161 (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&3162 !node.computed;3163const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;3164/**3165 * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts3166 * To avoid runtime dependency on @babel/types (which includes process references)3167 * This file should not change very often in babel but we may need to keep it3168 * up-to-date from time to time.3169 *3170 * https://github.com/babel/babel/blob/main/LICENSE3171 *3172 */3173function isReferenced(node, parent, grandparent) {3174 switch (parent.type) {3175 // yes: PARENT[NODE]3176 // yes: NODE.child3177 // no: parent.NODE3178 case 'MemberExpression':3179 case 'OptionalMemberExpression':3180 if (parent.property === node) {3181 return !!parent.computed;3182 }3183 return parent.object === node;3184 case 'JSXMemberExpression':3185 return parent.object === node;3186 // no: let NODE = init;3187 // yes: let id = NODE;3188 case 'VariableDeclarator':3189 return parent.init === node;3190 // yes: () => NODE3191 // no: (NODE) => {}3192 case 'ArrowFunctionExpression':3193 return parent.body === node;3194 // no: class { #NODE; }3195 // no: class { get #NODE() {} }3196 // no: class { #NODE() {} }3197 // no: class { fn() { return this.#NODE; } }3198 case 'PrivateName':3199 return false;3200 // no: class { NODE() {} }3201 // yes: class { [NODE]() {} }3202 // no: class { foo(NODE) {} }3203 case 'ClassMethod':3204 case 'ClassPrivateMethod':3205 case 'ObjectMethod':3206 if (parent.key === node) {3207 return !!parent.computed;3208 }3209 return false;3210 // yes: { [NODE]: "" }3211 // no: { NODE: "" }3212 // depends: { NODE }3213 // depends: { key: NODE }3214 case 'ObjectProperty':3215 if (parent.key === node) {3216 return !!parent.computed;3217 }3218 // parent.value === node3219 return !grandparent || grandparent.type !== 'ObjectPattern';3220 // no: class { NODE = value; }3221 // yes: class { [NODE] = value; }3222 // yes: class { key = NODE; }3223 case 'ClassProperty':3224 if (parent.key === node) {3225 return !!parent.computed;3226 }3227 return true;3228 case 'ClassPrivateProperty':3229 return parent.key !== node;3230 // no: class NODE {}3231 // yes: class Foo extends NODE {}3232 case 'ClassDeclaration':3233 case 'ClassExpression':3234 return parent.superClass === node;3235 // yes: left = NODE;3236 // no: NODE = right;3237 case 'AssignmentExpression':3238 return parent.right === node;3239 // no: [NODE = foo] = [];3240 // yes: [foo = NODE] = [];3241 case 'AssignmentPattern':3242 return parent.right === node;3243 // no: NODE: for (;;) {}3244 case 'LabeledStatement':3245 return false;3246 // no: try {} catch (NODE) {}3247 case 'CatchClause':3248 return false;3249 // no: function foo(...NODE) {}3250 case 'RestElement':3251 return false;3252 case 'BreakStatement':3253 case 'ContinueStatement':3254 return false;3255 // no: function NODE() {}3256 // no: function foo(NODE) {}3257 case 'FunctionDeclaration':3258 case 'FunctionExpression':3259 return false;3260 // no: export NODE from "foo";3261 // no: export * as NODE from "foo";3262 case 'ExportNamespaceSpecifier':3263 case 'ExportDefaultSpecifier':3264 return false;3265 // no: export { foo as NODE };3266 // yes: export { NODE as foo };3267 // no: export { NODE as foo } from "foo";3268 case 'ExportSpecifier':3269 // @ts-expect-error3270 if (grandparent === null || grandparent === void 0 ? void 0 : grandparent.source) {3271 return false;3272 }3273 return parent.local === node;3274 // no: import NODE from "foo";3275 // no: import * as NODE from "foo";3276 // no: import { NODE as foo } from "foo";3277 // no: import { foo as NODE } from "foo";3278 // no: import NODE from "bar";3279 case 'ImportDefaultSpecifier':3280 case 'ImportNamespaceSpecifier':3281 case 'ImportSpecifier':3282 return false;3283 // no: import "foo" assert { NODE: "json" }3284 case 'ImportAttribute':3285 return false;3286 // no: <div NODE="foo" />3287 case 'JSXAttribute':3288 return false;3289 // no: [NODE] = [];3290 // no: ({ NODE }) = [];3291 case 'ObjectPattern':3292 case 'ArrayPattern':3293 return false;3294 // no: new.NODE3295 // no: NODE.target3296 case 'MetaProperty':3297 return false;3298 // yes: type X = { somePropert: NODE }3299 // no: type X = { NODE: OtherType }3300 case 'ObjectTypeProperty':3301 return parent.key !== node;3302 // yes: enum X { Foo = NODE }3303 // no: enum X { NODE }3304 case 'TSEnumMember':3305 return parent.id !== node;3306 // yes: { [NODE]: value }3307 // no: { NODE: value }3308 case 'TSPropertySignature':3309 if (parent.key === node) {3310 return !!parent.computed;3311 }3312 return true;3313 }3314 return true;3315}3316const isLiteralWhitelisted = /*#__PURE__*/ shared.makeMap('true,false,null,this');3317const transformExpression = (node, context) => {3318 if (node.type === 5 /* INTERPOLATION */) {3319 node.content = processExpression(node.content, context);3320 }3321 else if (node.type === 1 /* ELEMENT */) {3322 // handle directives on element3323 for (let i = 0; i < node.props.length; i++) {3324 const dir = node.props[i];3325 // do not process for v-on & v-for since they are special handled3326 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {3327 const exp = dir.exp;3328 const arg = dir.arg;3329 // do not process exp if this is v-on:arg - we need special handling3330 // for wrapping inline statements.3331 if (exp &&3332 exp.type === 4 /* SIMPLE_EXPRESSION */ &&3333 !(dir.name === 'on' && arg)) {3334 dir.exp = processExpression(exp, context, 3335 // slot args must be processed as function params3336 dir.name === 'slot');3337 }3338 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {3339 dir.arg = processExpression(arg, context);3340 }3341 }3342 }3343 }3344};3345// Important: since this function uses Node.js only dependencies, it should3346// always be used with a leading !false check so that it can be3347// tree-shaken from the browser build.3348function processExpression(node, context, 3349// some expressions like v-slot props & v-for aliases should be parsed as3350// function params3351asParams = false, 3352// v-on handler values may contain multiple statements3353asRawStatements = false, localVars = Object.create(context.identifiers)) {3354 if (!context.prefixIdentifiers || !node.content.trim()) {3355 return node;3356 }3357 const { inline, bindingMetadata } = context;3358 const rewriteIdentifier = (raw, parent, id) => {3359 const type = shared.hasOwn(bindingMetadata, raw) && bindingMetadata[raw];3360 if (inline) {3361 // x = y3362 const isAssignmentLVal = parent && parent.type === 'AssignmentExpression' && parent.left === id;3363 // x++3364 const isUpdateArg = parent && parent.type === 'UpdateExpression' && parent.argument === id;3365 // ({ x } = y)3366 const isDestructureAssignment = parent && isInDestructureAssignment(parent, parentStack);3367 if (type === "setup-const" /* SETUP_CONST */ || localVars[raw]) {3368 return raw;3369 }3370 else if (type === "setup-ref" /* SETUP_REF */) {3371 return `${raw}.value`;3372 }3373 else if (type === "setup-maybe-ref" /* SETUP_MAYBE_REF */) {3374 // const binding that may or may not be ref3375 // if it's not a ref, then assignments don't make sense -3376 // so we ignore the non-ref assignment case and generate code3377 // that assumes the value to be a ref for more efficiency3378 return isAssignmentLVal || isUpdateArg || isDestructureAssignment3379 ? `${raw}.value`3380 : `${context.helperString(UNREF)}(${raw})`;3381 }3382 else if (type === "setup-let" /* SETUP_LET */) {3383 if (isAssignmentLVal) {3384 // let binding.3385 // this is a bit more tricky as we need to cover the case where3386 // let is a local non-ref value, and we need to replicate the3387 // right hand side value.3388 // x = y --> isRef(x) ? x.value = y : x = y3389 const { right: rVal, operator } = parent;3390 const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1);3391 const rExpString = stringifyExpression(processExpression(createSimpleExpression(rExp, false), context, false, false, knownIds));3392 return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${raw}.value ${operator} ${rExpString} : ${raw}`;3393 }3394 else if (isUpdateArg) {3395 // make id replace parent in the code range so the raw update operator3396 // is removed3397 id.start = parent.start;3398 id.end = parent.end;3399 const { prefix: isPrefix, operator } = parent;3400 const prefix = isPrefix ? operator : ``;3401 const postfix = isPrefix ? `` : operator;3402 // let binding.3403 // x++ --> isRef(a) ? a.value++ : a++3404 return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`;3405 }3406 else if (isDestructureAssignment) {3407 // TODO3408 // let binding in a destructure assignment - it's very tricky to3409 // handle both possible cases here without altering the original3410 // structure of the code, so we just assume it's not a ref here3411 // for now3412 return raw;3413 }3414 else {3415 return `${context.helperString(UNREF)}(${raw})`;3416 }3417 }3418 else if (type === "props" /* PROPS */) {3419 // use __props which is generated by compileScript so in ts mode3420 // it gets correct type3421 return `__props.${raw}`;3422 }3423 else if (type === "props-aliased" /* PROPS_ALIASED */) {3424 // prop with a different local alias (from defineProps() destructure)3425 return `__props.${bindingMetadata.__propsAliases[raw]}`;3426 }3427 }3428 else {3429 if (type && type.startsWith('setup')) {3430 // setup bindings in non-inline mode3431 return `$setup.${raw}`;3432 }3433 else if (type === "props-aliased" /* PROPS_ALIASED */) {3434 return `$props.${bindingMetadata.__propsAliases[raw]}`;3435 }3436 else if (type) {3437 return `$${type}.${raw}`;3438 }3439 }3440 // fallback to ctx3441 return `_ctx.${raw}`;3442 };3443 // fast path if expression is a simple identifier.3444 const rawExp = node.content;3445 // bail constant on parens (function invocation) and dot (member access)3446 const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0;3447 if (isSimpleIdentifier(rawExp)) {3448 const isScopeVarReference = context.identifiers[rawExp];3449 const isAllowedGlobal = shared.isGloballyWhitelisted(rawExp);3450 const isLiteral = isLiteralWhitelisted(rawExp);3451 if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) {3452 // const bindings exposed from setup can be skipped for patching but3453 // cannot be hoisted to module scope3454 if (bindingMetadata[node.content] === "setup-const" /* SETUP_CONST */) {3455 node.constType = 1 /* CAN_SKIP_PATCH */;3456 }3457 node.content = rewriteIdentifier(rawExp);3458 }3459 else if (!isScopeVarReference) {3460 if (isLiteral) {3461 node.constType = 3 /* CAN_STRINGIFY */;3462 }3463 else {3464 node.constType = 2 /* CAN_HOIST */;3465 }3466 }3467 return node;3468 }3469 let ast;3470 // exp needs to be parsed differently:3471 // 1. Multiple inline statements (v-on, with presence of `;`): parse as raw3472 // exp, but make sure to pad with spaces for consistent ranges3473 // 2. Expressions: wrap with parens (for e.g. object expressions)3474 // 3. Function arguments (v-for, v-slot): place in a function argument position3475 const source = asRawStatements3476 ? ` ${rawExp} `3477 : `(${rawExp})${asParams ? `=>{}` : ``}`;3478 try {3479 ast = parser.parse(source, {3480 plugins: context.expressionPlugins3481 }).program;3482 }3483 catch (e) {3484 context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, e.message));3485 return node;3486 }3487 const ids = [];3488 const parentStack = [];3489 const knownIds = Object.create(context.identifiers);3490 walkIdentifiers(ast, (node, parent, _, isReferenced, isLocal) => {3491 if (isStaticPropertyKey(node, parent)) {3492 return;3493 }3494 // v2 wrapped filter call3495 if (node.name.startsWith('_filter_')) {3496 return;3497 }3498 const needPrefix = isReferenced && canPrefix(node);3499 if (needPrefix && !isLocal) {3500 if (isStaticProperty(parent) && parent.shorthand) {3501 node.prefix = `${node.name}: `;3502 }3503 node.name = rewriteIdentifier(node.name, parent, node);3504 ids.push(node);3505 }3506 else {3507 // The identifier is considered constant unless it's pointing to a3508 // local scope variable (a v-for alias, or a v-slot prop)3509 if (!(needPrefix && isLocal) && !bailConstant) {3510 node.isConstant = true;3511 }3512 // also generate sub-expressions for other identifiers for better3513 // source map support. (except for property keys which are static)3514 ids.push(node);3515 }3516 }, true, // invoke on ALL identifiers3517 parentStack, knownIds);3518 // We break up the compound expression into an array of strings and sub3519 // expressions (for identifiers that have been prefixed). In codegen, if3520 // an ExpressionNode has the `.children` property, it will be used instead of3521 // `.content`.3522 const children = [];3523 ids.sort((a, b) => a.start - b.start);3524 ids.forEach((id, i) => {3525 // range is offset by -1 due to the wrapping parens when parsed3526 const start = id.start - 1;3527 const end = id.end - 1;3528 const last = ids[i - 1];3529 const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);3530 if (leadingText.length || id.prefix) {3531 children.push(leadingText + (id.prefix || ``));3532 }3533 const source = rawExp.slice(start, end);3534 children.push(createSimpleExpression(id.name, false, {3535 source,3536 start: advancePositionWithClone(node.loc.start, source, start),3537 end: advancePositionWithClone(node.loc.start, source, end)3538 }, id.isConstant ? 3 /* CAN_STRINGIFY */ : 0 /* NOT_CONSTANT */));3539 if (i === ids.length - 1 && end < rawExp.length) {3540 children.push(rawExp.slice(end));3541 }3542 });3543 let ret;3544 if (children.length) {3545 ret = createCompoundExpression(children, node.loc);3546 }3547 else {3548 ret = node;3549 ret.constType = bailConstant3550 ? 0 /* NOT_CONSTANT */3551 : 3 /* CAN_STRINGIFY */;3552 }3553 ret.identifiers = Object.keys(knownIds);3554 return ret;3555}3556function canPrefix(id) {3557 // skip whitelisted globals3558 if (shared.isGloballyWhitelisted(id.name)) {3559 return false;3560 }3561 // special case for webpack compilation3562 if (id.name === 'require') {3563 return false;3564 }3565 return true;3566}3567function stringifyExpression(exp) {3568 if (shared.isString(exp)) {3569 return exp;3570 }3571 else if (exp.type === 4 /* SIMPLE_EXPRESSION */) {3572 return exp.content;3573 }3574 else {3575 return exp.children3576 .map(stringifyExpression)3577 .join('');3578 }3579}3580const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {3581 return processIf(node, dir, context, (ifNode, branch, isRoot) => {3582 // #1587: We need to dynamically increment the key based on the current3583 // node's sibling nodes, since chained v-if/else branches are3584 // rendered at the same depth3585 const siblings = context.parent.children;3586 let i = siblings.indexOf(ifNode);3587 let key = 0;3588 while (i-- >= 0) {3589 const sibling = siblings[i];3590 if (sibling && sibling.type === 9 /* IF */) {3591 key += sibling.branches.length;3592 }3593 }3594 // Exit callback. Complete the codegenNode when all children have been3595 // transformed.3596 return () => {3597 if (isRoot) {3598 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);3599 }3600 else {3601 // attach this branch's codegen node to the v-if root.3602 const parentCondition = getParentCondition(ifNode.codegenNode);3603 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);3604 }3605 };3606 });3607});3608// target-agnostic transform used for both Client and SSR3609function processIf(node, dir, context, processCodegen) {3610 if (dir.name !== 'else' &&3611 (!dir.exp || !dir.exp.content.trim())) {3612 const loc = dir.exp ? dir.exp.loc : node.loc;3613 context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc));3614 dir.exp = createSimpleExpression(`true`, false, loc);3615 }3616 if (context.prefixIdentifiers && dir.exp) {3617 // dir.exp can only be simple expression because vIf transform is applied3618 // before expression transform.3619 dir.exp = processExpression(dir.exp, context);3620 }3621 if (dir.name === 'if') {3622 const branch = createIfBranch(node, dir);3623 const ifNode = {3624 type: 9 /* IF */,3625 loc: node.loc,3626 branches: [branch]3627 };3628 context.replaceNode(ifNode);3629 if (processCodegen) {3630 return processCodegen(ifNode, branch, true);3631 }3632 }3633 else {3634 // locate the adjacent v-if3635 const siblings = context.parent.children;3636 const comments = [];3637 let i = siblings.indexOf(node);3638 while (i-- >= -1) {3639 const sibling = siblings[i];3640 if (sibling && sibling.type === 3 /* COMMENT */) {3641 context.removeNode(sibling);3642 comments.unshift(sibling);3643 continue;3644 }3645 if (sibling &&3646 sibling.type === 2 /* TEXT */ &&3647 !sibling.content.trim().length) {3648 context.removeNode(sibling);3649 continue;3650 }3651 if (sibling && sibling.type === 9 /* IF */) {3652 // Check if v-else was followed by v-else-if3653 if (dir.name === 'else-if' &&3654 sibling.branches[sibling.branches.length - 1].condition === undefined) {3655 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3656 }3657 // move the node to the if node's branches3658 context.removeNode();3659 const branch = createIfBranch(node, dir);3660 if (comments.length &&3661 // #3619 ignore comments if the v-if is direct child of <transition>3662 !(context.parent &&3663 context.parent.type === 1 /* ELEMENT */ &&3664 isBuiltInType(context.parent.tag, 'transition'))) {3665 branch.children = [...comments, ...branch.children];3666 }3667 // check if user is forcing same key on different branches3668 {3669 const key = branch.userKey;3670 if (key) {3671 sibling.branches.forEach(({ userKey }) => {3672 if (isSameKey(userKey, key)) {3673 context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc));3674 }3675 });3676 }3677 }3678 sibling.branches.push(branch);3679 const onExit = processCodegen && processCodegen(sibling, branch, false);3680 // since the branch was removed, it will not be traversed.3681 // make sure to traverse here.3682 traverseNode(branch, context);3683 // call on exit3684 if (onExit)3685 onExit();3686 // make sure to reset currentNode after traversal to indicate this3687 // node has been removed.3688 context.currentNode = null;3689 }3690 else {3691 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3692 }3693 break;3694 }3695 }3696}3697function createIfBranch(node, dir) {3698 return {3699 type: 10 /* IF_BRANCH */,3700 loc: node.loc,3701 condition: dir.name === 'else' ? undefined : dir.exp,3702 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')3703 ? node.children3704 : [node],3705 userKey: findProp(node, `key`)3706 };3707}3708function createCodegenNodeForBranch(branch, keyIndex, context) {3709 if (branch.condition) {3710 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 3711 // make sure to pass in asBlock: true so that the comment node call3712 // closes the current block.3713 createCallExpression(context.helper(CREATE_COMMENT), [3714 '"v-if"' ,3715 'true'3716 ]));3717 }3718 else {3719 return createChildrenCodegenNode(branch, keyIndex, context);3720 }3721}3722function createChildrenCodegenNode(branch, keyIndex, context) {3723 const { helper } = context;3724 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));3725 const { children } = branch;3726 const firstChild = children[0];3727 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;3728 if (needFragmentWrapper) {3729 if (children.length === 1 && firstChild.type === 11 /* FOR */) {3730 // optimize away nested fragments when child is a ForNode3731 const vnodeCall = firstChild.codegenNode;3732 injectProp(vnodeCall, keyProperty, context);3733 return vnodeCall;3734 }3735 else {3736 let patchFlag = 64 /* STABLE_FRAGMENT */;3737 let patchFlagText = shared.PatchFlagNames[64 /* STABLE_FRAGMENT */];3738 // check if the fragment actually contains a single valid child with3739 // the rest being comments3740 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {3741 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;3742 patchFlagText += `, ${shared.PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;3743 }3744 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, false, false /* isComponent */, branch.loc);3745 }3746 }3747 else {3748 const ret = firstChild.codegenNode;3749 const vnodeCall = getMemoedVNodeCall(ret);3750 // Change createVNode to createBlock.3751 if (vnodeCall.type === 13 /* VNODE_CALL */) {3752 makeBlock(vnodeCall, context);3753 }3754 // inject branch key3755 injectProp(vnodeCall, keyProperty, context);3756 return ret;3757 }3758}3759function isSameKey(a, b) {3760 if (!a || a.type !== b.type) {3761 return false;3762 }3763 if (a.type === 6 /* ATTRIBUTE */) {3764 if (a.value.content !== b.value.content) {3765 return false;3766 }3767 }3768 else {3769 // directive3770 const exp = a.exp;3771 const branchExp = b.exp;3772 if (exp.type !== branchExp.type) {3773 return false;3774 }3775 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||3776 exp.isStatic !== branchExp.isStatic ||3777 exp.content !== branchExp.content) {3778 return false;3779 }3780 }3781 return true;3782}3783function getParentCondition(node) {3784 while (true) {3785 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3786 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3787 node = node.alternate;3788 }3789 else {3790 return node;3791 }3792 }3793 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {3794 node = node.value;3795 }3796 }3797}3798const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {3799 const { helper, removeHelper } = context;3800 return processFor(node, dir, context, forNode => {3801 // create the loop render function expression now, and add the3802 // iterator on exit after all children have been traversed3803 const renderExp = createCallExpression(helper(RENDER_LIST), [3804 forNode.source3805 ]);3806 const memo = findDir(node, 'memo');3807 const keyProp = findProp(node, `key`);3808 const keyExp = keyProp &&3809 (keyProp.type === 6 /* ATTRIBUTE */3810 ? createSimpleExpression(keyProp.value.content, true)3811 : keyProp.exp);3812 const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;3813 if (context.prefixIdentifiers &&3814 keyProperty &&3815 keyProp.type !== 6 /* ATTRIBUTE */) {3816 // #2085 process :key expression needs to be processed in order for it3817 // to behave consistently for <template v-for> and <div v-for>.3818 // In the case of `<template v-for>`, the node is discarded and never3819 // traversed so its key expression won't be processed by the normal3820 // transforms.3821 keyProperty.value = processExpression(keyProperty.value, context);3822 }3823 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3824 forNode.source.constType > 0 /* NOT_CONSTANT */;3825 const fragmentFlag = isStableFragment3826 ? 64 /* STABLE_FRAGMENT */3827 : keyProp3828 ? 128 /* KEYED_FRAGMENT */3829 : 256 /* UNKEYED_FRAGMENT */;3830 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3831 (` /* ${shared.PatchFlagNames[fragmentFlag]} */` ), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);3832 return () => {3833 // finish the codegen now that all children have been traversed3834 let childBlock;3835 const isTemplate = isTemplateNode(node);3836 const { children } = forNode;3837 // check <template v-for> key placement3838 if (isTemplate) {3839 node.children.some(c => {3840 if (c.type === 1 /* ELEMENT */) {3841 const key = findProp(c, 'key');3842 if (key) {3843 context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3844 return true;3845 }3846 }3847 });3848 }3849 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3850 const slotOutlet = isSlotOutlet(node)3851 ? node3852 : isTemplate &&3853 node.children.length === 1 &&3854 isSlotOutlet(node.children[0])3855 ? node.children[0] // api-extractor somehow fails to infer this3856 : null;3857 if (slotOutlet) {3858 // <slot v-for="..."> or <template v-for="..."><slot/></template>3859 childBlock = slotOutlet.codegenNode;3860 if (isTemplate && keyProperty) {3861 // <template v-for="..." :key="..."><slot/></template>3862 // we need to inject the key to the renderSlot() call.3863 // the props for renderSlot is passed as the 3rd argument.3864 injectProp(childBlock, keyProperty, context);3865 }3866 }3867 else if (needFragmentWrapper) {3868 // <template v-for="..."> with text or multi-elements3869 // should generate a fragment block for each loop3870 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3871 (` /* ${shared.PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`3872 ), undefined, undefined, true, undefined, false /* isComponent */);3873 }3874 else {3875 // Normal element v-for. Directly use the child's codegenNode3876 // but mark it as a block.3877 childBlock = children[0]3878 .codegenNode;3879 if (isTemplate && keyProperty) {3880 injectProp(childBlock, keyProperty, context);3881 }3882 if (childBlock.isBlock !== !isStableFragment) {3883 if (childBlock.isBlock) {3884 // switch from block to vnode3885 removeHelper(OPEN_BLOCK);3886 removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3887 }3888 else {3889 // switch from vnode to block3890 removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));3891 }3892 }3893 childBlock.isBlock = !isStableFragment;3894 if (childBlock.isBlock) {3895 helper(OPEN_BLOCK);3896 helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3897 }3898 else {3899 helper(getVNodeHelper(context.inSSR, childBlock.isComponent));3900 }3901 }3902 if (memo) {3903 const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [3904 createSimpleExpression(`_cached`)3905 ]));3906 loop.body = createBlockStatement([3907 createCompoundExpression([`const _memo = (`, memo.exp, `)`]),3908 createCompoundExpression([3909 `if (_cached`,3910 ...(keyExp ? [` && _cached.key === `, keyExp] : []),3911 ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`3912 ]),3913 createCompoundExpression([`const _item = `, childBlock]),3914 createSimpleExpression(`_item.memo = _memo`),3915 createSimpleExpression(`return _item`)3916 ]);3917 renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));3918 }3919 else {3920 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3921 }3922 };3923 });3924});3925// target-agnostic transform used for both Client and SSR3926function processFor(node, dir, context, processCodegen) {3927 if (!dir.exp) {3928 context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3929 return;3930 }3931 const parseResult = parseForExpression(3932 // can only be simple expression because vFor transform is applied3933 // before expression transform.3934 dir.exp, context);3935 if (!parseResult) {3936 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3937 return;3938 }3939 const { addIdentifiers, removeIdentifiers, scopes } = context;3940 const { source, value, key, index } = parseResult;3941 const forNode = {3942 type: 11 /* FOR */,3943 loc: dir.loc,3944 source,3945 valueAlias: value,3946 keyAlias: key,3947 objectIndexAlias: index,3948 parseResult,3949 children: isTemplateNode(node) ? node.children : [node]3950 };3951 context.replaceNode(forNode);3952 // bookkeeping3953 scopes.vFor++;3954 if (context.prefixIdentifiers) {3955 // scope management3956 // inject identifiers to context3957 value && addIdentifiers(value);3958 key && addIdentifiers(key);3959 index && addIdentifiers(index);3960 }3961 const onExit = processCodegen && processCodegen(forNode);3962 return () => {3963 scopes.vFor--;3964 if (context.prefixIdentifiers) {3965 value && removeIdentifiers(value);3966 key && removeIdentifiers(key);3967 index && removeIdentifiers(index);3968 }3969 if (onExit)3970 onExit();3971 };3972}3973const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3974// This regex doesn't cover the case if key or index aliases have destructuring,3975// but those do not make sense in the first place, so this works in practice.3976const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3977const stripParensRE = /^\(|\)$/g;3978function parseForExpression(input, context) {3979 const loc = input.loc;3980 const exp = input.content;3981 const inMatch = exp.match(forAliasRE);3982 if (!inMatch)3983 return;3984 const [, LHS, RHS] = inMatch;3985 const result = {3986 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3987 value: undefined,3988 key: undefined,3989 index: undefined3990 };3991 if (context.prefixIdentifiers) {3992 result.source = processExpression(result.source, context);3993 }3994 let valueContent = LHS.trim().replace(stripParensRE, '').trim();3995 const trimmedOffset = LHS.indexOf(valueContent);3996 const iteratorMatch = valueContent.match(forIteratorRE);3997 if (iteratorMatch) {3998 valueContent = valueContent.replace(forIteratorRE, '').trim();3999 const keyContent = iteratorMatch[1].trim();4000 let keyOffset;4001 if (keyContent) {4002 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);4003 result.key = createAliasExpression(loc, keyContent, keyOffset);4004 if (context.prefixIdentifiers) {4005 result.key = processExpression(result.key, context, true);4006 }4007 }4008 if (iteratorMatch[2]) {4009 const indexContent = iteratorMatch[2].trim();4010 if (indexContent) {4011 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key4012 ? keyOffset + keyContent.length4013 : trimmedOffset + valueContent.length));4014 if (context.prefixIdentifiers) {4015 result.index = processExpression(result.index, context, true);4016 }4017 }4018 }4019 }4020 if (valueContent) {4021 result.value = createAliasExpression(loc, valueContent, trimmedOffset);4022 if (context.prefixIdentifiers) {4023 result.value = processExpression(result.value, context, true);4024 }4025 }4026 return result;4027}4028function createAliasExpression(range, content, offset) {4029 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));4030}4031function createForLoopParams({ value, key, index }, memoArgs = []) {4032 return createParamsList([value, key, index, ...memoArgs]);4033}4034function createParamsList(args) {4035 let i = args.length;4036 while (i--) {4037 if (args[i])4038 break;4039 }4040 return args4041 .slice(0, i + 1)4042 .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));4043}4044const defaultFallback = createSimpleExpression(`undefined`, false);4045// A NodeTransform that:4046// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed4047// by transformExpression. This is only applied in non-browser builds with4048// { prefixIdentifiers: true }.4049// 2. Track v-slot depths so that we know a slot is inside another slot.4050// Note the exit callback is executed before buildSlots() on the same node,4051// so only nested slots see positive numbers.4052const trackSlotScopes = (node, context) => {4053 if (node.type === 1 /* ELEMENT */ &&4054 (node.tagType === 1 /* COMPONENT */ ||4055 node.tagType === 3 /* TEMPLATE */)) {4056 // We are only checking non-empty v-slot here4057 // since we only care about slots that introduce scope variables.4058 const vSlot = findDir(node, 'slot');4059 if (vSlot) {4060 const slotProps = vSlot.exp;4061 if (context.prefixIdentifiers) {4062 slotProps && context.addIdentifiers(slotProps);4063 }4064 context.scopes.vSlot++;4065 return () => {4066 if (context.prefixIdentifiers) {4067 slotProps && context.removeIdentifiers(slotProps);4068 }4069 context.scopes.vSlot--;4070 };4071 }4072 }4073};4074// A NodeTransform that tracks scope identifiers for scoped slots with v-for.4075// This transform is only applied in non-browser builds with { prefixIdentifiers: true }4076const trackVForSlotScopes = (node, context) => {4077 let vFor;4078 if (isTemplateNode(node) &&4079 node.props.some(isVSlot) &&4080 (vFor = findDir(node, 'for'))) {4081 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));4082 if (result) {4083 const { value, key, index } = result;4084 const { addIdentifiers, removeIdentifiers } = context;4085 value && addIdentifiers(value);4086 key && addIdentifiers(key);4087 index && addIdentifiers(index);4088 return () => {4089 value && removeIdentifiers(value);4090 key && removeIdentifiers(key);4091 index && removeIdentifiers(index);4092 };4093 }4094 }4095};4096const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);4097// Instead of being a DirectiveTransform, v-slot processing is called during4098// transformElement to build the slots object for a component.4099function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {4100 context.helper(WITH_CTX);4101 const { children, loc } = node;4102 const slotsProperties = [];4103 const dynamicSlots = [];4104 // If the slot is inside a v-for or another v-slot, force it to be dynamic4105 // since it likely uses a scope variable.4106 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;4107 // with `prefixIdentifiers: true`, this can be further optimized to make4108 // it dynamic only when the slot actually uses the scope variables.4109 if (!context.ssr && context.prefixIdentifiers) {4110 hasDynamicSlots = hasScopeRef(node, context.identifiers);4111 }4112 // 1. Check for slot with slotProps on component itself.4113 // <Comp v-slot="{ prop }"/>4114 const onComponentSlot = findDir(node, 'slot', true);4115 if (onComponentSlot) {4116 const { arg, exp } = onComponentSlot;4117 if (arg && !isStaticExp(arg)) {4118 hasDynamicSlots = true;4119 }4120 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));4121 }4122 // 2. Iterate through children and check for template slots4123 // <template v-slot:foo="{ prop }">4124 let hasTemplateSlots = false;4125 let hasNamedDefaultSlot = false;4126 const implicitDefaultChildren = [];4127 const seenSlotNames = new Set();4128 for (let i = 0; i < children.length; i++) {4129 const slotElement = children[i];4130 let slotDir;4131 if (!isTemplateNode(slotElement) ||4132 !(slotDir = findDir(slotElement, 'slot', true))) {4133 // not a <template v-slot>, skip.4134 if (slotElement.type !== 3 /* COMMENT */) {4135 implicitDefaultChildren.push(slotElement);4136 }4137 continue;4138 }4139 if (onComponentSlot) {4140 // already has on-component slot - this is incorrect usage.4141 context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));4142 break;4143 }4144 hasTemplateSlots = true;4145 const { children: slotChildren, loc: slotLoc } = slotElement;4146 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;4147 // check if name is dynamic.4148 let staticSlotName;4149 if (isStaticExp(slotName)) {4150 staticSlotName = slotName ? slotName.content : `default`;4151 }4152 else {4153 hasDynamicSlots = true;4154 }4155 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);4156 // check if this slot is conditional (v-if/v-for)4157 let vIf;4158 let vElse;4159 let vFor;4160 if ((vIf = findDir(slotElement, 'if'))) {4161 hasDynamicSlots = true;4162 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));4163 }4164 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {4165 // find adjacent v-if4166 let j = i;4167 let prev;4168 while (j--) {4169 prev = children[j];4170 if (prev.type !== 3 /* COMMENT */) {4171 break;4172 }4173 }4174 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {4175 // remove node4176 children.splice(i, 1);4177 i--;4178 // attach this slot to previous conditional4179 let conditional = dynamicSlots[dynamicSlots.length - 1];4180 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {4181 conditional = conditional.alternate;4182 }4183 conditional.alternate = vElse.exp4184 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)4185 : buildDynamicSlot(slotName, slotFunction);4186 }4187 else {4188 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));4189 }4190 }4191 else if ((vFor = findDir(slotElement, 'for'))) {4192 hasDynamicSlots = true;4193 const parseResult = vFor.parseResult ||4194 parseForExpression(vFor.exp, context);4195 if (parseResult) {4196 // Render the dynamic slots as an array and add it to the createSlot()4197 // args. The runtime knows how to handle it appropriately.4198 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [4199 parseResult.source,4200 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)4201 ]));4202 }4203 else {4204 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));4205 }4206 }4207 else {4208 // check duplicate static names4209 if (staticSlotName) {4210 if (seenSlotNames.has(staticSlotName)) {4211 context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));4212 continue;4213 }4214 seenSlotNames.add(staticSlotName);4215 if (staticSlotName === 'default') {4216 hasNamedDefaultSlot = true;4217 }4218 }4219 slotsProperties.push(createObjectProperty(slotName, slotFunction));4220 }4221 }4222 if (!onComponentSlot) {4223 const buildDefaultSlotProperty = (props, children) => {4224 const fn = buildSlotFn(props, children, loc);4225 if (context.compatConfig) {4226 fn.isNonScopedSlot = true;4227 }4228 return createObjectProperty(`default`, fn);4229 };4230 if (!hasTemplateSlots) {4231 // implicit default slot (on component)4232 slotsProperties.push(buildDefaultSlotProperty(undefined, children));4233 }4234 else if (implicitDefaultChildren.length &&4235 // #37664236 // with whitespace: 'preserve', whitespaces between slots will end up in4237 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.4238 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {4239 // implicit default slot (mixed with named slots)4240 if (hasNamedDefaultSlot) {4241 context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));4242 }4243 else {4244 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));4245 }4246 }4247 }4248 const slotFlag = hasDynamicSlots4249 ? 2 /* DYNAMIC */4250 : hasForwardedSlots(node.children)4251 ? 3 /* FORWARDED */4252 : 1 /* STABLE */;4253 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 4254 // 2 = compiled but dynamic = can skip normalization, but must run diff4255 // 1 = compiled and static = can skip normalization AND diff as optimized4256 createSimpleExpression(slotFlag + (` /* ${shared.slotFlagsText[slotFlag]} */` ), false))), loc);4257 if (dynamicSlots.length) {4258 slots = createCallExpression(context.helper(CREATE_SLOTS), [4259 slots,4260 createArrayExpression(dynamicSlots)4261 ]);4262 }4263 return {4264 slots,4265 hasDynamicSlots4266 };4267}4268function buildDynamicSlot(name, fn) {4269 return createObjectExpression([4270 createObjectProperty(`name`, name),4271 createObjectProperty(`fn`, fn)4272 ]);4273}4274function hasForwardedSlots(children) {4275 for (let i = 0; i < children.length; i++) {4276 const child = children[i];4277 switch (child.type) {4278 case 1 /* ELEMENT */:4279 if (child.tagType === 2 /* SLOT */ ||4280 hasForwardedSlots(child.children)) {4281 return true;4282 }4283 break;4284 case 9 /* IF */:4285 if (hasForwardedSlots(child.branches))4286 return true;4287 break;4288 case 10 /* IF_BRANCH */:4289 case 11 /* FOR */:4290 if (hasForwardedSlots(child.children))4291 return true;4292 break;4293 }4294 }4295 return false;4296}4297function isNonWhitespaceContent(node) {4298 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)4299 return true;4300 return node.type === 2 /* TEXT */4301 ? !!node.content.trim()4302 : isNonWhitespaceContent(node.content);4303}4304// some directive transforms (e.g. v-model) may return a symbol for runtime4305// import, which should be used instead of a resolveDirective call.4306const directiveImportMap = new WeakMap();4307// generate a JavaScript AST for this element's codegen4308const transformElement = (node, context) => {4309 // perform the work on exit, after all child expressions have been4310 // processed and merged.4311 return function postTransformElement() {4312 node = context.currentNode;4313 if (!(node.type === 1 /* ELEMENT */ &&4314 (node.tagType === 0 /* ELEMENT */ ||4315 node.tagType === 1 /* COMPONENT */))) {4316 return;4317 }4318 const { tag, props } = node;4319 const isComponent = node.tagType === 1 /* COMPONENT */;4320 // The goal of the transform is to create a codegenNode implementing the4321 // VNodeCall interface.4322 let vnodeTag = isComponent4323 ? resolveComponentType(node, context)4324 : `"${tag}"`;4325 const isDynamicComponent = shared.isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;4326 let vnodeProps;4327 let vnodeChildren;4328 let vnodePatchFlag;4329 let patchFlag = 0;4330 let vnodeDynamicProps;4331 let dynamicPropNames;4332 let vnodeDirectives;4333 let shouldUseBlock = 4334 // dynamic component may resolve to plain elements4335 isDynamicComponent ||4336 vnodeTag === TELEPORT ||4337 vnodeTag === SUSPENSE ||4338 (!isComponent &&4339 // <svg> and <foreignObject> must be forced into blocks so that block4340 // updates inside get proper isSVG flag at runtime. (#639, #643)4341 // This is technically web-specific, but splitting the logic out of core4342 // leads to too much unnecessary complexity.4343 (tag === 'svg' ||4344 tag === 'foreignObject' ||4345 // #938: elements with dynamic keys should be forced into blocks4346 findProp(node, 'key', true)));4347 // props4348 if (props.length > 0) {4349 const propsBuildResult = buildProps(node, context);4350 vnodeProps = propsBuildResult.props;4351 patchFlag = propsBuildResult.patchFlag;4352 dynamicPropNames = propsBuildResult.dynamicPropNames;4353 const directives = propsBuildResult.directives;4354 vnodeDirectives =4355 directives && directives.length4356 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))4357 : undefined;4358 }4359 // children4360 if (node.children.length > 0) {4361 if (vnodeTag === KEEP_ALIVE) {4362 // Although a built-in component, we compile KeepAlive with raw children4363 // instead of slot functions so that it can be used inside Transition4364 // or other Transition-wrapping HOCs.4365 // To ensure correct updates with block optimizations, we need to:4366 // 1. Force keep-alive into a block. This avoids its children being4367 // collected by a parent block.4368 shouldUseBlock = true;4369 // 2. Force keep-alive to always be updated, since it uses raw children.4370 patchFlag |= 1024 /* DYNAMIC_SLOTS */;4371 if (node.children.length > 1) {4372 context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {4373 start: node.children[0].loc.start,4374 end: node.children[node.children.length - 1].loc.end,4375 source: ''4376 }));4377 }4378 }4379 const shouldBuildAsSlots = isComponent &&4380 // Teleport is not a real component and has dedicated runtime handling4381 vnodeTag !== TELEPORT &&4382 // explained above.4383 vnodeTag !== KEEP_ALIVE;4384 if (shouldBuildAsSlots) {4385 const { slots, hasDynamicSlots } = buildSlots(node, context);4386 vnodeChildren = slots;4387 if (hasDynamicSlots) {4388 patchFlag |= 1024 /* DYNAMIC_SLOTS */;4389 }4390 }4391 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {4392 const child = node.children[0];4393 const type = child.type;4394 // check for dynamic text children4395 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||4396 type === 8 /* COMPOUND_EXPRESSION */;4397 if (hasDynamicTextChild &&4398 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {4399 patchFlag |= 1 /* TEXT */;4400 }4401 // pass directly if the only child is a text node4402 // (plain / interpolation / expression)4403 if (hasDynamicTextChild || type === 2 /* TEXT */) {4404 vnodeChildren = child;4405 }4406 else {4407 vnodeChildren = node.children;4408 }4409 }4410 else {4411 vnodeChildren = node.children;4412 }4413 }4414 // patchFlag & dynamicPropNames4415 if (patchFlag !== 0) {4416 {4417 if (patchFlag < 0) {4418 // special flags (negative and mutually exclusive)4419 vnodePatchFlag = patchFlag + ` /* ${shared.PatchFlagNames[patchFlag]} */`;4420 }4421 else {4422 // bitwise flags4423 const flagNames = Object.keys(shared.PatchFlagNames)4424 .map(Number)4425 .filter(n => n > 0 && patchFlag & n)4426 .map(n => shared.PatchFlagNames[n])4427 .join(`, `);4428 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;4429 }4430 }4431 if (dynamicPropNames && dynamicPropNames.length) {4432 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);4433 }4434 }4435 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);4436 };4437};4438function resolveComponentType(node, context, ssr = false) {4439 let { tag } = node;4440 // 1. dynamic component4441 const isExplicitDynamic = isComponentTag(tag);4442 const isProp = findProp(node, 'is');4443 if (isProp) {4444 if (isExplicitDynamic ||4445 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {4446 const exp = isProp.type === 6 /* ATTRIBUTE */4447 ? isProp.value && createSimpleExpression(isProp.value.content, true)4448 : isProp.exp;4449 if (exp) {4450 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [4451 exp4452 ]);4453 }4454 }4455 else if (isProp.type === 6 /* ATTRIBUTE */ &&4456 isProp.value.content.startsWith('vue:')) {4457 // <button is="vue:xxx">4458 // if not <component>, only is value that starts with "vue:" will be4459 // treated as component by the parse phase and reach here, unless it's4460 // compat mode where all is values are considered components4461 tag = isProp.value.content.slice(4);4462 }4463 }4464 // 1.5 v-is (TODO: Deprecate)4465 const isDir = !isExplicitDynamic && findDir(node, 'is');4466 if (isDir && isDir.exp) {4467 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [4468 isDir.exp4469 ]);4470 }4471 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)4472 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);4473 if (builtIn) {4474 // built-ins are simply fallthroughs / have special handling during ssr4475 // so we don't need to import their runtime equivalents4476 if (!ssr)4477 context.helper(builtIn);4478 return builtIn;4479 }4480 // 3. user component (from setup bindings)4481 // this is skipped in browser build since browser builds do not perform4482 // binding analysis.4483 {4484 const fromSetup = resolveSetupReference(tag, context);4485 if (fromSetup) {4486 return fromSetup;4487 }4488 const dotIndex = tag.indexOf('.');4489 if (dotIndex > 0) {4490 const ns = resolveSetupReference(tag.slice(0, dotIndex), context);4491 if (ns) {4492 return ns + tag.slice(dotIndex);4493 }4494 }4495 }4496 // 4. Self referencing component (inferred from filename)4497 if (context.selfName &&4498 shared.capitalize(shared.camelize(tag)) === context.selfName) {4499 context.helper(RESOLVE_COMPONENT);4500 // codegen.ts has special check for __self postfix when generating4501 // component imports, which will pass additional `maybeSelfReference` flag4502 // to `resolveComponent`.4503 context.components.add(tag + `__self`);4504 return toValidAssetId(tag, `component`);4505 }4506 // 5. user component (resolve)4507 context.helper(RESOLVE_COMPONENT);4508 context.components.add(tag);4509 return toValidAssetId(tag, `component`);4510}4511function resolveSetupReference(name, context) {4512 const bindings = context.bindingMetadata;4513 if (!bindings || bindings.__isScriptSetup === false) {4514 return;4515 }4516 const camelName = shared.camelize(name);4517 const PascalName = shared.capitalize(camelName);4518 const checkType = (type) => {4519 if (bindings[name] === type) {4520 return name;4521 }4522 if (bindings[camelName] === type) {4523 return camelName;4524 }4525 if (bindings[PascalName] === type) {4526 return PascalName;4527 }4528 };4529 const fromConst = checkType("setup-const" /* SETUP_CONST */);4530 if (fromConst) {4531 return context.inline4532 ? // in inline mode, const setup bindings (e.g. imports) can be used as-is4533 fromConst4534 : `$setup[${JSON.stringify(fromConst)}]`;4535 }4536 const fromMaybeRef = checkType("setup-let" /* SETUP_LET */) ||4537 checkType("setup-ref" /* SETUP_REF */) ||4538 checkType("setup-maybe-ref" /* SETUP_MAYBE_REF */);4539 if (fromMaybeRef) {4540 return context.inline4541 ? // setup scope bindings that may be refs need to be unrefed4542 `${context.helperString(UNREF)}(${fromMaybeRef})`4543 : `$setup[${JSON.stringify(fromMaybeRef)}]`;4544 }4545}4546function buildProps(node, context, props = node.props, ssr = false) {4547 const { tag, loc: elementLoc } = node;4548 const isComponent = node.tagType === 1 /* COMPONENT */;4549 let properties = [];4550 const mergeArgs = [];4551 const runtimeDirectives = [];4552 // patchFlag analysis4553 let patchFlag = 0;4554 let hasRef = false;4555 let hasClassBinding = false;4556 let hasStyleBinding = false;4557 let hasHydrationEventBinding = false;4558 let hasDynamicKeys = false;4559 let hasVnodeHook = false;4560 const dynamicPropNames = [];4561 const analyzePatchFlag = ({ key, value }) => {4562 if (isStaticExp(key)) {4563 const name = key.content;4564 const isEventHandler = shared.isOn(name);4565 if (!isComponent &&4566 isEventHandler &&4567 // omit the flag for click handlers because hydration gives click4568 // dedicated fast path.4569 name.toLowerCase() !== 'onclick' &&4570 // omit v-model handlers4571 name !== 'onUpdate:modelValue' &&4572 // omit onVnodeXXX hooks4573 !shared.isReservedProp(name)) {4574 hasHydrationEventBinding = true;4575 }4576 if (isEventHandler && shared.isReservedProp(name)) {4577 hasVnodeHook = true;4578 }4579 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||4580 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||4581 value.type === 8 /* COMPOUND_EXPRESSION */) &&4582 getConstantType(value, context) > 0)) {4583 // skip if the prop is a cached handler or has constant value4584 return;4585 }4586 if (name === 'ref') {4587 hasRef = true;4588 }4589 else if (name === 'class') {4590 hasClassBinding = true;4591 }4592 else if (name === 'style') {4593 hasStyleBinding = true;4594 }4595 else if (name !== 'key' && !dynamicPropNames.includes(name)) {4596 dynamicPropNames.push(name);4597 }4598 // treat the dynamic class and style binding of the component as dynamic props4599 if (isComponent &&4600 (name === 'class' || name === 'style') &&4601 !dynamicPropNames.includes(name)) {4602 dynamicPropNames.push(name);4603 }4604 }4605 else {4606 hasDynamicKeys = true;4607 }4608 };4609 for (let i = 0; i < props.length; i++) {4610 // static attribute4611 const prop = props[i];4612 if (prop.type === 6 /* ATTRIBUTE */) {4613 const { loc, name, value } = prop;4614 let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);4615 if (name === 'ref') {4616 hasRef = true;4617 // in inline mode there is no setupState object, so we can't use string4618 // keys to set the ref. Instead, we need to transform it to pass the4619 // actual ref instead.4620 if (context.inline && (value === null || value === void 0 ? void 0 : value.content)) {4621 valueNode = createFunctionExpression(['_value', '_refs']);4622 valueNode.body = createBlockStatement(processInlineRef(context, value.content));4623 }4624 }4625 // skip is on <component>, or is="vue:xxx"4626 if (name === 'is' &&4627 (isComponentTag(tag) ||4628 (value && value.content.startsWith('vue:')) ||4629 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {4630 continue;4631 }4632 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));4633 }4634 else {4635 // directives4636 const { name, arg, exp, loc } = prop;4637 const isVBind = name === 'bind';4638 const isVOn = name === 'on';4639 // skip v-slot - it is handled by its dedicated transform.4640 if (name === 'slot') {4641 if (!isComponent) {4642 context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc));4643 }4644 continue;4645 }4646 // skip v-once/v-memo - they are handled by dedicated transforms.4647 if (name === 'once' || name === 'memo') {4648 continue;4649 }4650 // skip v-is and :is on <component>4651 if (name === 'is' ||4652 (isVBind &&4653 isBindKey(arg, 'is') &&4654 (isComponentTag(tag) ||4655 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {4656 continue;4657 }4658 // skip v-on in SSR compilation4659 if (isVOn && ssr) {4660 continue;4661 }4662 // special case for v-bind and v-on with no argument4663 if (!arg && (isVBind || isVOn)) {4664 hasDynamicKeys = true;4665 if (exp) {4666 if (properties.length) {4667 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4668 properties = [];4669 }4670 if (isVBind) {4671 {4672 // 2.x v-bind object order compat4673 {4674 const hasOverridableKeys = mergeArgs.some(arg => {4675 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {4676 return arg.properties.some(({ key }) => {4677 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||4678 !key.isStatic) {4679 return true;4680 }4681 return (key.content !== 'class' &&4682 key.content !== 'style' &&4683 !shared.isOn(key.content));4684 });4685 }4686 else {4687 // dynamic expression4688 return true;4689 }4690 });4691 if (hasOverridableKeys) {4692 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);4693 }4694 }4695 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {4696 mergeArgs.unshift(exp);4697 continue;4698 }4699 }4700 mergeArgs.push(exp);4701 }4702 else {4703 // v-on="obj" -> toHandlers(obj)4704 mergeArgs.push({4705 type: 14 /* JS_CALL_EXPRESSION */,4706 loc,4707 callee: context.helper(TO_HANDLERS),4708 arguments: [exp]4709 });4710 }4711 }4712 else {4713 context.onError(createCompilerError(isVBind4714 ? 34 /* X_V_BIND_NO_EXPRESSION */4715 : 35 /* X_V_ON_NO_EXPRESSION */, loc));4716 }4717 continue;4718 }4719 const directiveTransform = context.directiveTransforms[name];4720 if (directiveTransform) {4721 // has built-in directive transform.4722 const { props, needRuntime } = directiveTransform(prop, node, context);4723 !ssr && props.forEach(analyzePatchFlag);4724 properties.push(...props);4725 if (needRuntime) {4726 runtimeDirectives.push(prop);4727 if (shared.isSymbol(needRuntime)) {4728 directiveImportMap.set(prop, needRuntime);4729 }4730 }4731 }4732 else {4733 // no built-in transform, this is a user custom directive.4734 runtimeDirectives.push(prop);4735 }4736 }4737 if (prop.type === 6 /* ATTRIBUTE */ &&4738 prop.name === 'ref' &&4739 context.scopes.vFor > 0 &&4740 checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {4741 properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));4742 }4743 }4744 let propsExpression = undefined;4745 // has v-bind="object" or v-on="object", wrap with mergeProps4746 if (mergeArgs.length) {4747 if (properties.length) {4748 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4749 }4750 if (mergeArgs.length > 1) {4751 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);4752 }4753 else {4754 // single v-bind with nothing else - no need for a mergeProps call ...

Full Screen

Full Screen

compiler-dom.esm-browser.js

Source:compiler-dom.esm-browser.js Github

copy

Full Screen

...952 // in v3 mode, only enable if explicitly set to true953 // otherwise enable for any non-false value954 return mode === 3 ? value === true : value !== false;955}956function checkCompatEnabled(key, context, loc, ...args) {957 const enabled = isCompatEnabled(key, context);958 if (enabled) {959 warnDeprecation(key, context, loc, ...args);960 }961 return enabled;962}963function warnDeprecation(key, context, loc, ...args) {964 const val = getCompatValue(key, context);965 if (val === 'suppress-warning') {966 return;967 }968 const { message, link } = deprecationData[key];969 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;970 const err = new SyntaxError(msg);971 err.code = key;972 if (loc)973 err.loc = loc;974 context.onWarn(err);975}976// The default decoder only provides escapes for characters reserved as part of977// the template syntax, and is only used if the custom renderer did not provide978// a platform-specific decoder.979const decodeRE = /&(gt|lt|amp|apos|quot);/g;980const decodeMap = {981 gt: '>',982 lt: '<',983 amp: '&',984 apos: "'",985 quot: '"'986};987const defaultParserOptions = {988 delimiters: [`{{`, `}}`],989 getNamespace: () => 0 /* HTML */,990 getTextMode: () => 0 /* DATA */,991 isVoidTag: NO,992 isPreTag: NO,993 isCustomElement: NO,994 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),995 onError: defaultOnError,996 onWarn: defaultOnWarn,997 comments: true998};999function baseParse(content, options = {}) {1000 const context = createParserContext(content, options);1001 const start = getCursor(context);1002 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));1003}1004function createParserContext(content, rawOptions) {1005 const options = extend({}, defaultParserOptions);1006 let key;1007 for (key in rawOptions) {1008 // @ts-ignore1009 options[key] =1010 rawOptions[key] === undefined1011 ? defaultParserOptions[key]1012 : rawOptions[key];1013 }1014 return {1015 options,1016 column: 1,1017 line: 1,1018 offset: 0,1019 originalSource: content,1020 source: content,1021 inPre: false,1022 inVPre: false,1023 onWarn: options.onWarn1024 };1025}1026function parseChildren(context, mode, ancestors) {1027 const parent = last(ancestors);1028 const ns = parent ? parent.ns : 0 /* HTML */;1029 const nodes = [];1030 while (!isEnd(context, mode, ancestors)) {1031 const s = context.source;1032 let node = undefined;1033 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {1034 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {1035 // '{{'1036 node = parseInterpolation(context, mode);1037 }1038 else if (mode === 0 /* DATA */ && s[0] === '<') {1039 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state1040 if (s.length === 1) {1041 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);1042 }1043 else if (s[1] === '!') {1044 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state1045 if (startsWith(s, '<!--')) {1046 node = parseComment(context);1047 }1048 else if (startsWith(s, '<!DOCTYPE')) {1049 // Ignore DOCTYPE by a limitation.1050 node = parseBogusComment(context);1051 }1052 else if (startsWith(s, '<![CDATA[')) {1053 if (ns !== 0 /* HTML */) {1054 node = parseCDATA(context, ancestors);1055 }1056 else {1057 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);1058 node = parseBogusComment(context);1059 }1060 }1061 else {1062 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);1063 node = parseBogusComment(context);1064 }1065 }1066 else if (s[1] === '/') {1067 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state1068 if (s.length === 2) {1069 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);1070 }1071 else if (s[2] === '>') {1072 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);1073 advanceBy(context, 3);1074 continue;1075 }1076 else if (/[a-z]/i.test(s[2])) {1077 emitError(context, 23 /* X_INVALID_END_TAG */);1078 parseTag(context, 1 /* End */, parent);1079 continue;1080 }1081 else {1082 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);1083 node = parseBogusComment(context);1084 }1085 }1086 else if (/[a-z]/i.test(s[1])) {1087 node = parseElement(context, ancestors);1088 // 2.x <template> with no directive compat1089 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&1090 node &&1091 node.tag === 'template' &&1092 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&1093 isSpecialTemplateDirective(p.name))) {1094 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);1095 node = node.children;1096 }1097 }1098 else if (s[1] === '?') {1099 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);1100 node = parseBogusComment(context);1101 }1102 else {1103 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);1104 }1105 }1106 }1107 if (!node) {1108 node = parseText(context, mode);1109 }1110 if (isArray(node)) {1111 for (let i = 0; i < node.length; i++) {1112 pushNode(nodes, node[i]);1113 }1114 }1115 else {1116 pushNode(nodes, node);1117 }1118 }1119 // Whitespace handling strategy like v21120 let removedWhitespace = false;1121 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {1122 const shouldCondense = context.options.whitespace !== 'preserve';1123 for (let i = 0; i < nodes.length; i++) {1124 const node = nodes[i];1125 if (!context.inPre && node.type === 2 /* TEXT */) {1126 if (!/[^\t\r\n\f ]/.test(node.content)) {1127 const prev = nodes[i - 1];1128 const next = nodes[i + 1];1129 // Remove if:1130 // - the whitespace is the first or last node, or:1131 // - (condense mode) the whitespace is adjacent to a comment, or:1132 // - (condense mode) the whitespace is between two elements AND contains newline1133 if (!prev ||1134 !next ||1135 (shouldCondense &&1136 (prev.type === 3 /* COMMENT */ ||1137 next.type === 3 /* COMMENT */ ||1138 (prev.type === 1 /* ELEMENT */ &&1139 next.type === 1 /* ELEMENT */ &&1140 /[\r\n]/.test(node.content))))) {1141 removedWhitespace = true;1142 nodes[i] = null;1143 }1144 else {1145 // Otherwise, the whitespace is condensed into a single space1146 node.content = ' ';1147 }1148 }1149 else if (shouldCondense) {1150 // in condense mode, consecutive whitespaces in text are condensed1151 // down to a single space.1152 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');1153 }1154 }1155 // Remove comment nodes if desired by configuration.1156 else if (node.type === 3 /* COMMENT */ && !context.options.comments) {1157 removedWhitespace = true;1158 nodes[i] = null;1159 }1160 }1161 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {1162 // remove leading newline per html spec1163 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element1164 const first = nodes[0];1165 if (first && first.type === 2 /* TEXT */) {1166 first.content = first.content.replace(/^\r?\n/, '');1167 }1168 }1169 }1170 return removedWhitespace ? nodes.filter(Boolean) : nodes;1171}1172function pushNode(nodes, node) {1173 if (node.type === 2 /* TEXT */) {1174 const prev = last(nodes);1175 // Merge if both this and the previous node are text and those are1176 // consecutive. This happens for cases like "a < b".1177 if (prev &&1178 prev.type === 2 /* TEXT */ &&1179 prev.loc.end.offset === node.loc.start.offset) {1180 prev.content += node.content;1181 prev.loc.end = node.loc.end;1182 prev.loc.source += node.loc.source;1183 return;1184 }1185 }1186 nodes.push(node);1187}1188function parseCDATA(context, ancestors) {1189 advanceBy(context, 9);1190 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1191 if (context.source.length === 0) {1192 emitError(context, 6 /* EOF_IN_CDATA */);1193 }1194 else {1195 advanceBy(context, 3);1196 }1197 return nodes;1198}1199function parseComment(context) {1200 const start = getCursor(context);1201 let content;1202 // Regular comment.1203 const match = /--(\!)?>/.exec(context.source);1204 if (!match) {1205 content = context.source.slice(4);1206 advanceBy(context, context.source.length);1207 emitError(context, 7 /* EOF_IN_COMMENT */);1208 }1209 else {1210 if (match.index <= 3) {1211 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1212 }1213 if (match[1]) {1214 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1215 }1216 content = context.source.slice(4, match.index);1217 // Advancing with reporting nested comments.1218 const s = context.source.slice(0, match.index);1219 let prevIndex = 1, nestedIndex = 0;1220 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1221 advanceBy(context, nestedIndex - prevIndex + 1);1222 if (nestedIndex + 4 < s.length) {1223 emitError(context, 16 /* NESTED_COMMENT */);1224 }1225 prevIndex = nestedIndex + 1;1226 }1227 advanceBy(context, match.index + match[0].length - prevIndex + 1);1228 }1229 return {1230 type: 3 /* COMMENT */,1231 content,1232 loc: getSelection(context, start)1233 };1234}1235function parseBogusComment(context) {1236 const start = getCursor(context);1237 const contentStart = context.source[1] === '?' ? 1 : 2;1238 let content;1239 const closeIndex = context.source.indexOf('>');1240 if (closeIndex === -1) {1241 content = context.source.slice(contentStart);1242 advanceBy(context, context.source.length);1243 }1244 else {1245 content = context.source.slice(contentStart, closeIndex);1246 advanceBy(context, closeIndex + 1);1247 }1248 return {1249 type: 3 /* COMMENT */,1250 content,1251 loc: getSelection(context, start)1252 };1253}1254function parseElement(context, ancestors) {1255 // Start tag.1256 const wasInPre = context.inPre;1257 const wasInVPre = context.inVPre;1258 const parent = last(ancestors);1259 const element = parseTag(context, 0 /* Start */, parent);1260 const isPreBoundary = context.inPre && !wasInPre;1261 const isVPreBoundary = context.inVPre && !wasInVPre;1262 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1263 // #4030 self-closing <pre> tag1264 if (isPreBoundary) {1265 context.inPre = false;1266 }1267 if (isVPreBoundary) {1268 context.inVPre = false;1269 }1270 return element;1271 }1272 // Children.1273 ancestors.push(element);1274 const mode = context.options.getTextMode(element, parent);1275 const children = parseChildren(context, mode, ancestors);1276 ancestors.pop();1277 // 2.x inline-template compat1278 {1279 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1280 if (inlineTemplateProp &&1281 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1282 const loc = getSelection(context, element.loc.end);1283 inlineTemplateProp.value = {1284 type: 2 /* TEXT */,1285 content: loc.source,1286 loc1287 };1288 }1289 }1290 element.children = children;1291 // End tag.1292 if (startsWithEndTagOpen(context.source, element.tag)) {1293 parseTag(context, 1 /* End */, parent);1294 }1295 else {1296 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1297 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1298 const first = children[0];1299 if (first && startsWith(first.loc.source, '<!--')) {1300 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1301 }1302 }1303 }1304 element.loc = getSelection(context, element.loc.start);1305 if (isPreBoundary) {1306 context.inPre = false;1307 }1308 if (isVPreBoundary) {1309 context.inVPre = false;1310 }1311 return element;1312}1313const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`);1314function parseTag(context, type, parent) {1315 // Tag open.1316 const start = getCursor(context);1317 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1318 const tag = match[1];1319 const ns = context.options.getNamespace(tag, parent);1320 advanceBy(context, match[0].length);1321 advanceSpaces(context);1322 // save current state in case we need to re-parse attributes with v-pre1323 const cursor = getCursor(context);1324 const currentSource = context.source;1325 // check <pre> tag1326 if (context.options.isPreTag(tag)) {1327 context.inPre = true;1328 }1329 // Attributes.1330 let props = parseAttributes(context, type);1331 // check v-pre1332 if (type === 0 /* Start */ &&1333 !context.inVPre &&1334 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1335 context.inVPre = true;1336 // reset context1337 extend(context, cursor);1338 context.source = currentSource;1339 // re-parse attrs and filter out v-pre itself1340 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1341 }1342 // Tag close.1343 let isSelfClosing = false;1344 if (context.source.length === 0) {1345 emitError(context, 9 /* EOF_IN_TAG */);1346 }1347 else {1348 isSelfClosing = startsWith(context.source, '/>');1349 if (type === 1 /* End */ && isSelfClosing) {1350 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1351 }1352 advanceBy(context, isSelfClosing ? 2 : 1);1353 }1354 if (type === 1 /* End */) {1355 return;1356 }1357 // 2.x deprecation checks1358 if (isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1359 let hasIf = false;1360 let hasFor = false;1361 for (let i = 0; i < props.length; i++) {1362 const p = props[i];1363 if (p.type === 7 /* DIRECTIVE */) {1364 if (p.name === 'if') {1365 hasIf = true;1366 }1367 else if (p.name === 'for') {1368 hasFor = true;1369 }1370 }1371 if (hasIf && hasFor) {1372 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1373 }1374 }1375 }1376 let tagType = 0 /* ELEMENT */;1377 if (!context.inVPre) {1378 if (tag === 'slot') {1379 tagType = 2 /* SLOT */;1380 }1381 else if (tag === 'template') {1382 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1383 tagType = 3 /* TEMPLATE */;1384 }1385 }1386 else if (isComponent(tag, props, context)) {1387 tagType = 1 /* COMPONENT */;1388 }1389 }1390 return {1391 type: 1 /* ELEMENT */,1392 ns,1393 tag,1394 tagType,1395 props,1396 isSelfClosing,1397 children: [],1398 loc: getSelection(context, start),1399 codegenNode: undefined // to be created during transform phase1400 };1401}1402function isComponent(tag, props, context) {1403 const options = context.options;1404 if (options.isCustomElement(tag)) {1405 return false;1406 }1407 if (tag === 'component' ||1408 /^[A-Z]/.test(tag) ||1409 isCoreComponent(tag) ||1410 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1411 (options.isNativeTag && !options.isNativeTag(tag))) {1412 return true;1413 }1414 // at this point the tag should be a native tag, but check for potential "is"1415 // casting1416 for (let i = 0; i < props.length; i++) {1417 const p = props[i];1418 if (p.type === 6 /* ATTRIBUTE */) {1419 if (p.name === 'is' && p.value) {1420 if (p.value.content.startsWith('vue:')) {1421 return true;1422 }1423 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1424 return true;1425 }1426 }1427 }1428 else {1429 // directive1430 // v-is (TODO Deprecate)1431 if (p.name === 'is') {1432 return true;1433 }1434 else if (1435 // :is on plain element - only treat as component in compat mode1436 p.name === 'bind' &&1437 isBindKey(p.arg, 'is') &&1438 true &&1439 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1440 return true;1441 }1442 }1443 }1444}1445function parseAttributes(context, type) {1446 const props = [];1447 const attributeNames = new Set();1448 while (context.source.length > 0 &&1449 !startsWith(context.source, '>') &&1450 !startsWith(context.source, '/>')) {1451 if (startsWith(context.source, '/')) {1452 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1453 advanceBy(context, 1);1454 advanceSpaces(context);1455 continue;1456 }1457 if (type === 1 /* End */) {1458 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1459 }1460 const attr = parseAttribute(context, attributeNames);1461 // Trim whitespace between class1462 // https://github.com/vuejs/vue-next/issues/42511463 if (attr.type === 6 /* ATTRIBUTE */ &&1464 attr.value &&1465 attr.name === 'class') {1466 attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();1467 }1468 if (type === 0 /* Start */) {1469 props.push(attr);1470 }1471 if (/^[^\t\r\n\f />]/.test(context.source)) {1472 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1473 }1474 advanceSpaces(context);1475 }1476 return props;1477}1478function parseAttribute(context, nameSet) {1479 // Name.1480 const start = getCursor(context);1481 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1482 const name = match[0];1483 if (nameSet.has(name)) {1484 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1485 }1486 nameSet.add(name);1487 if (name[0] === '=') {1488 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1489 }1490 {1491 const pattern = /["'<]/g;1492 let m;1493 while ((m = pattern.exec(name))) {1494 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1495 }1496 }1497 advanceBy(context, name.length);1498 // Value1499 let value = undefined;1500 if (/^[\t\r\n\f ]*=/.test(context.source)) {1501 advanceSpaces(context);1502 advanceBy(context, 1);1503 advanceSpaces(context);1504 value = parseAttributeValue(context);1505 if (!value) {1506 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1507 }1508 }1509 const loc = getSelection(context, start);1510 if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {1511 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1512 let isPropShorthand = startsWith(name, '.');1513 let dirName = match[1] ||1514 (isPropShorthand || startsWith(name, ':')1515 ? 'bind'1516 : startsWith(name, '@')1517 ? 'on'1518 : 'slot');1519 let arg;1520 if (match[2]) {1521 const isSlot = dirName === 'slot';1522 const startOffset = name.lastIndexOf(match[2]);1523 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));1524 let content = match[2];1525 let isStatic = true;1526 if (content.startsWith('[')) {1527 isStatic = false;1528 if (!content.endsWith(']')) {1529 emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1530 content = content.slice(1);1531 }1532 else {1533 content = content.slice(1, content.length - 1);1534 }1535 }1536 else if (isSlot) {1537 // #1241 special case for v-slot: vuetify relies extensively on slot1538 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x1539 // supports such usage so we are keeping it consistent with 2.x.1540 content += match[3] || '';1541 }1542 arg = {1543 type: 4 /* SIMPLE_EXPRESSION */,1544 content,1545 isStatic,1546 constType: isStatic1547 ? 3 /* CAN_STRINGIFY */1548 : 0 /* NOT_CONSTANT */,1549 loc1550 };1551 }1552 if (value && value.isQuoted) {1553 const valueLoc = value.loc;1554 valueLoc.start.offset++;1555 valueLoc.start.column++;1556 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1557 valueLoc.source = valueLoc.source.slice(1, -1);1558 }1559 const modifiers = match[3] ? match[3].slice(1).split('.') : [];1560 if (isPropShorthand)1561 modifiers.push('prop');1562 // 2.x compat v-bind:foo.sync -> v-model:foo1563 if (dirName === 'bind' && arg) {1564 if (modifiers.includes('sync') &&1565 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {1566 dirName = 'model';1567 modifiers.splice(modifiers.indexOf('sync'), 1);1568 }1569 if (modifiers.includes('prop')) {1570 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);1571 }1572 }1573 return {1574 type: 7 /* DIRECTIVE */,1575 name: dirName,1576 exp: value && {1577 type: 4 /* SIMPLE_EXPRESSION */,1578 content: value.content,1579 isStatic: false,1580 // Treat as non-constant by default. This can be potentially set to1581 // other values by `transformExpression` to make it eligible for hoisting.1582 constType: 0 /* NOT_CONSTANT */,1583 loc: value.loc1584 },1585 arg,1586 modifiers,1587 loc1588 };1589 }1590 // missing directive name or illegal directive name1591 if (!context.inVPre && startsWith(name, 'v-')) {1592 emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */);1593 }1594 return {1595 type: 6 /* ATTRIBUTE */,1596 name,1597 value: value && {1598 type: 2 /* TEXT */,1599 content: value.content,1600 loc: value.loc1601 },1602 loc1603 };1604}1605function parseAttributeValue(context) {1606 const start = getCursor(context);1607 let content;1608 const quote = context.source[0];1609 const isQuoted = quote === `"` || quote === `'`;1610 if (isQuoted) {1611 // Quoted value.1612 advanceBy(context, 1);1613 const endIndex = context.source.indexOf(quote);1614 if (endIndex === -1) {1615 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1616 }1617 else {1618 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1619 advanceBy(context, 1);1620 }1621 }1622 else {1623 // Unquoted1624 const match = /^[^\t\r\n\f >]+/.exec(context.source);1625 if (!match) {1626 return undefined;1627 }1628 const unexpectedChars = /["'<=`]/g;1629 let m;1630 while ((m = unexpectedChars.exec(match[0]))) {1631 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1632 }1633 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1634 }1635 return { content, isQuoted, loc: getSelection(context, start) };1636}1637function parseInterpolation(context, mode) {1638 const [open, close] = context.options.delimiters;1639 const closeIndex = context.source.indexOf(close, open.length);1640 if (closeIndex === -1) {1641 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);1642 return undefined;1643 }1644 const start = getCursor(context);1645 advanceBy(context, open.length);1646 const innerStart = getCursor(context);1647 const innerEnd = getCursor(context);1648 const rawContentLength = closeIndex - open.length;1649 const rawContent = context.source.slice(0, rawContentLength);1650 const preTrimContent = parseTextData(context, rawContentLength, mode);1651 const content = preTrimContent.trim();1652 const startOffset = preTrimContent.indexOf(content);1653 if (startOffset > 0) {1654 advancePositionWithMutation(innerStart, rawContent, startOffset);1655 }1656 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1657 advancePositionWithMutation(innerEnd, rawContent, endOffset);1658 advanceBy(context, close.length);1659 return {1660 type: 5 /* INTERPOLATION */,1661 content: {1662 type: 4 /* SIMPLE_EXPRESSION */,1663 isStatic: false,1664 // Set `isConstant` to false by default and will decide in transformExpression1665 constType: 0 /* NOT_CONSTANT */,1666 content,1667 loc: getSelection(context, innerStart, innerEnd)1668 },1669 loc: getSelection(context, start)1670 };1671}1672function parseText(context, mode) {1673 const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];1674 let endIndex = context.source.length;1675 for (let i = 0; i < endTokens.length; i++) {1676 const index = context.source.indexOf(endTokens[i], 1);1677 if (index !== -1 && endIndex > index) {1678 endIndex = index;1679 }1680 }1681 const start = getCursor(context);1682 const content = parseTextData(context, endIndex, mode);1683 return {1684 type: 2 /* TEXT */,1685 content,1686 loc: getSelection(context, start)1687 };1688}1689/**1690 * Get text data with a given length from the current location.1691 * This translates HTML entities in the text data.1692 */1693function parseTextData(context, length, mode) {1694 const rawText = context.source.slice(0, length);1695 advanceBy(context, length);1696 if (mode === 2 /* RAWTEXT */ ||1697 mode === 3 /* CDATA */ ||1698 rawText.indexOf('&') === -1) {1699 return rawText;1700 }1701 else {1702 // DATA or RCDATA containing "&"". Entity decoding required.1703 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);1704 }1705}1706function getCursor(context) {1707 const { column, line, offset } = context;1708 return { column, line, offset };1709}1710function getSelection(context, start, end) {1711 end = end || getCursor(context);1712 return {1713 start,1714 end,1715 source: context.originalSource.slice(start.offset, end.offset)1716 };1717}1718function last(xs) {1719 return xs[xs.length - 1];1720}1721function startsWith(source, searchString) {1722 return source.startsWith(searchString);1723}1724function advanceBy(context, numberOfCharacters) {1725 const { source } = context;1726 advancePositionWithMutation(context, source, numberOfCharacters);1727 context.source = source.slice(numberOfCharacters);1728}1729function advanceSpaces(context) {1730 const match = /^[\t\r\n\f ]+/.exec(context.source);1731 if (match) {1732 advanceBy(context, match[0].length);1733 }1734}1735function getNewPosition(context, start, numberOfCharacters) {1736 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1737}1738function emitError(context, code, offset, loc = getCursor(context)) {1739 if (offset) {1740 loc.offset += offset;1741 loc.column += offset;1742 }1743 context.options.onError(createCompilerError(code, {1744 start: loc,1745 end: loc,1746 source: ''1747 }));1748}1749function isEnd(context, mode, ancestors) {1750 const s = context.source;1751 switch (mode) {1752 case 0 /* DATA */:1753 if (startsWith(s, '</')) {1754 // TODO: probably bad performance1755 for (let i = ancestors.length - 1; i >= 0; --i) {1756 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1757 return true;1758 }1759 }1760 }1761 break;1762 case 1 /* RCDATA */:1763 case 2 /* RAWTEXT */: {1764 const parent = last(ancestors);1765 if (parent && startsWithEndTagOpen(s, parent.tag)) {1766 return true;1767 }1768 break;1769 }1770 case 3 /* CDATA */:1771 if (startsWith(s, ']]>')) {1772 return true;1773 }1774 break;1775 }1776 return !s;1777}1778function startsWithEndTagOpen(source, tag) {1779 return (startsWith(source, '</') &&1780 source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&1781 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));1782}1783function hoistStatic(root, context) {1784 walk(root, context, 1785 // Root node is unfortunately non-hoistable due to potential parent1786 // fallthrough attributes.1787 isSingleElementRoot(root, root.children[0]));1788}1789function isSingleElementRoot(root, child) {1790 const { children } = root;1791 return (children.length === 1 &&1792 child.type === 1 /* ELEMENT */ &&1793 !isSlotOutlet(child));1794}1795function walk(node, context, doNotHoistNode = false) {1796 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1797 // static bindings with expressions. These expressions are guaranteed to be1798 // constant so they are still eligible for hoisting, but they are only1799 // available at runtime and therefore cannot be evaluated ahead of time.1800 // This is only a concern for pre-stringification (via transformHoist by1801 // @vue/compiler-dom), but doing it here allows us to perform only one full1802 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1803 // stringification threshold is met.1804 let canStringify = true;1805 const { children } = node;1806 const originalCount = children.length;1807 let hoistedCount = 0;1808 for (let i = 0; i < children.length; i++) {1809 const child = children[i];1810 // only plain elements & text calls are eligible for hoisting.1811 if (child.type === 1 /* ELEMENT */ &&1812 child.tagType === 0 /* ELEMENT */) {1813 const constantType = doNotHoistNode1814 ? 0 /* NOT_CONSTANT */1815 : getConstantType(child, context);1816 if (constantType > 0 /* NOT_CONSTANT */) {1817 if (constantType < 3 /* CAN_STRINGIFY */) {1818 canStringify = false;1819 }1820 if (constantType >= 2 /* CAN_HOIST */) {1821 child.codegenNode.patchFlag =1822 -1 /* HOISTED */ + (` /* HOISTED */` );1823 child.codegenNode = context.hoist(child.codegenNode);1824 hoistedCount++;1825 continue;1826 }1827 }1828 else {1829 // node may contain dynamic children, but its props may be eligible for1830 // hoisting.1831 const codegenNode = child.codegenNode;1832 if (codegenNode.type === 13 /* VNODE_CALL */) {1833 const flag = getPatchFlag(codegenNode);1834 if ((!flag ||1835 flag === 512 /* NEED_PATCH */ ||1836 flag === 1 /* TEXT */) &&1837 getGeneratedPropsConstantType(child, context) >=1838 2 /* CAN_HOIST */) {1839 const props = getNodeProps(child);1840 if (props) {1841 codegenNode.props = context.hoist(props);1842 }1843 }1844 if (codegenNode.dynamicProps) {1845 codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);1846 }1847 }1848 }1849 }1850 else if (child.type === 12 /* TEXT_CALL */) {1851 const contentType = getConstantType(child.content, context);1852 if (contentType > 0) {1853 if (contentType < 3 /* CAN_STRINGIFY */) {1854 canStringify = false;1855 }1856 if (contentType >= 2 /* CAN_HOIST */) {1857 child.codegenNode = context.hoist(child.codegenNode);1858 hoistedCount++;1859 }1860 }1861 }1862 // walk further1863 if (child.type === 1 /* ELEMENT */) {1864 const isComponent = child.tagType === 1 /* COMPONENT */;1865 if (isComponent) {1866 context.scopes.vSlot++;1867 }1868 walk(child, context);1869 if (isComponent) {1870 context.scopes.vSlot--;1871 }1872 }1873 else if (child.type === 11 /* FOR */) {1874 // Do not hoist v-for single child because it has to be a block1875 walk(child, context, child.children.length === 1);1876 }1877 else if (child.type === 9 /* IF */) {1878 for (let i = 0; i < child.branches.length; i++) {1879 // Do not hoist v-if single child because it has to be a block1880 walk(child.branches[i], context, child.branches[i].children.length === 1);1881 }1882 }1883 }1884 if (canStringify && hoistedCount && context.transformHoist) {1885 context.transformHoist(children, context, node);1886 }1887 // all children were hoisted - the entire children array is hoistable.1888 if (hoistedCount &&1889 hoistedCount === originalCount &&1890 node.type === 1 /* ELEMENT */ &&1891 node.tagType === 0 /* ELEMENT */ &&1892 node.codegenNode &&1893 node.codegenNode.type === 13 /* VNODE_CALL */ &&1894 isArray(node.codegenNode.children)) {1895 node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));1896 }1897}1898function getConstantType(node, context) {1899 const { constantCache } = context;1900 switch (node.type) {1901 case 1 /* ELEMENT */:1902 if (node.tagType !== 0 /* ELEMENT */) {1903 return 0 /* NOT_CONSTANT */;1904 }1905 const cached = constantCache.get(node);1906 if (cached !== undefined) {1907 return cached;1908 }1909 const codegenNode = node.codegenNode;1910 if (codegenNode.type !== 13 /* VNODE_CALL */) {1911 return 0 /* NOT_CONSTANT */;1912 }1913 const flag = getPatchFlag(codegenNode);1914 if (!flag) {1915 let returnType = 3 /* CAN_STRINGIFY */;1916 // Element itself has no patch flag. However we still need to check:1917 // 1. Even for a node with no patch flag, it is possible for it to contain1918 // non-hoistable expressions that refers to scope variables, e.g. compiler1919 // injected keys or cached event handlers. Therefore we need to always1920 // check the codegenNode's props to be sure.1921 const generatedPropsType = getGeneratedPropsConstantType(node, context);1922 if (generatedPropsType === 0 /* NOT_CONSTANT */) {1923 constantCache.set(node, 0 /* NOT_CONSTANT */);1924 return 0 /* NOT_CONSTANT */;1925 }1926 if (generatedPropsType < returnType) {1927 returnType = generatedPropsType;1928 }1929 // 2. its children.1930 for (let i = 0; i < node.children.length; i++) {1931 const childType = getConstantType(node.children[i], context);1932 if (childType === 0 /* NOT_CONSTANT */) {1933 constantCache.set(node, 0 /* NOT_CONSTANT */);1934 return 0 /* NOT_CONSTANT */;1935 }1936 if (childType < returnType) {1937 returnType = childType;1938 }1939 }1940 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-01941 // type, check if any of the props can cause the type to be lowered1942 // we can skip can_patch because it's guaranteed by the absence of a1943 // patchFlag.1944 if (returnType > 1 /* CAN_SKIP_PATCH */) {1945 for (let i = 0; i < node.props.length; i++) {1946 const p = node.props[i];1947 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {1948 const expType = getConstantType(p.exp, context);1949 if (expType === 0 /* NOT_CONSTANT */) {1950 constantCache.set(node, 0 /* NOT_CONSTANT */);1951 return 0 /* NOT_CONSTANT */;1952 }1953 if (expType < returnType) {1954 returnType = expType;1955 }1956 }1957 }1958 }1959 // only svg/foreignObject could be block here, however if they are1960 // static then they don't need to be blocks since there will be no1961 // nested updates.1962 if (codegenNode.isBlock) {1963 context.removeHelper(OPEN_BLOCK);1964 context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));1965 codegenNode.isBlock = false;1966 context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));1967 }1968 constantCache.set(node, returnType);1969 return returnType;1970 }1971 else {1972 constantCache.set(node, 0 /* NOT_CONSTANT */);1973 return 0 /* NOT_CONSTANT */;1974 }1975 case 2 /* TEXT */:1976 case 3 /* COMMENT */:1977 return 3 /* CAN_STRINGIFY */;1978 case 9 /* IF */:1979 case 11 /* FOR */:1980 case 10 /* IF_BRANCH */:1981 return 0 /* NOT_CONSTANT */;1982 case 5 /* INTERPOLATION */:1983 case 12 /* TEXT_CALL */:1984 return getConstantType(node.content, context);1985 case 4 /* SIMPLE_EXPRESSION */:1986 return node.constType;1987 case 8 /* COMPOUND_EXPRESSION */:1988 let returnType = 3 /* CAN_STRINGIFY */;1989 for (let i = 0; i < node.children.length; i++) {1990 const child = node.children[i];1991 if (isString(child) || isSymbol(child)) {1992 continue;1993 }1994 const childType = getConstantType(child, context);1995 if (childType === 0 /* NOT_CONSTANT */) {1996 return 0 /* NOT_CONSTANT */;1997 }1998 else if (childType < returnType) {1999 returnType = childType;2000 }2001 }2002 return returnType;2003 default:2004 return 0 /* NOT_CONSTANT */;2005 }2006}2007const allowHoistedHelperSet = new Set([2008 NORMALIZE_CLASS,2009 NORMALIZE_STYLE,2010 NORMALIZE_PROPS,2011 GUARD_REACTIVE_PROPS2012]);2013function getConstantTypeOfHelperCall(value, context) {2014 if (value.type === 14 /* JS_CALL_EXPRESSION */ &&2015 !isString(value.callee) &&2016 allowHoistedHelperSet.has(value.callee)) {2017 const arg = value.arguments[0];2018 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {2019 return getConstantType(arg, context);2020 }2021 else if (arg.type === 14 /* JS_CALL_EXPRESSION */) {2022 // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`2023 return getConstantTypeOfHelperCall(arg, context);2024 }2025 }2026 return 0 /* NOT_CONSTANT */;2027}2028function getGeneratedPropsConstantType(node, context) {2029 let returnType = 3 /* CAN_STRINGIFY */;2030 const props = getNodeProps(node);2031 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {2032 const { properties } = props;2033 for (let i = 0; i < properties.length; i++) {2034 const { key, value } = properties[i];2035 const keyType = getConstantType(key, context);2036 if (keyType === 0 /* NOT_CONSTANT */) {2037 return keyType;2038 }2039 if (keyType < returnType) {2040 returnType = keyType;2041 }2042 let valueType;2043 if (value.type === 4 /* SIMPLE_EXPRESSION */) {2044 valueType = getConstantType(value, context);2045 }2046 else if (value.type === 14 /* JS_CALL_EXPRESSION */) {2047 // some helper calls can be hoisted,2048 // such as the `normalizeProps` generated by the compiler for pre-normalize class,2049 // in this case we need to respect the ConstantType of the helper's argments2050 valueType = getConstantTypeOfHelperCall(value, context);2051 }2052 else {2053 valueType = 0 /* NOT_CONSTANT */;2054 }2055 if (valueType === 0 /* NOT_CONSTANT */) {2056 return valueType;2057 }2058 if (valueType < returnType) {2059 returnType = valueType;2060 }2061 }2062 }2063 return returnType;2064}2065function getNodeProps(node) {2066 const codegenNode = node.codegenNode;2067 if (codegenNode.type === 13 /* VNODE_CALL */) {2068 return codegenNode.props;2069 }2070}2071function getPatchFlag(node) {2072 const flag = node.patchFlag;2073 return flag ? parseInt(flag, 10) : undefined;2074}2075function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {2076 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);2077 const context = {2078 // options2079 selfName: nameMatch && capitalize(camelize(nameMatch[1])),2080 prefixIdentifiers,2081 hoistStatic,2082 cacheHandlers,2083 nodeTransforms,2084 directiveTransforms,2085 transformHoist,2086 isBuiltInComponent,2087 isCustomElement,2088 expressionPlugins,2089 scopeId,2090 slotted,2091 ssr,2092 inSSR,2093 ssrCssVars,2094 bindingMetadata,2095 inline,2096 isTS,2097 onError,2098 onWarn,2099 compatConfig,2100 // state2101 root,2102 helpers: new Map(),2103 components: new Set(),2104 directives: new Set(),2105 hoists: [],2106 imports: [],2107 constantCache: new Map(),2108 temps: 0,2109 cached: 0,2110 identifiers: Object.create(null),2111 scopes: {2112 vFor: 0,2113 vSlot: 0,2114 vPre: 0,2115 vOnce: 02116 },2117 parent: null,2118 currentNode: root,2119 childIndex: 0,2120 inVOnce: false,2121 // methods2122 helper(name) {2123 const count = context.helpers.get(name) || 0;2124 context.helpers.set(name, count + 1);2125 return name;2126 },2127 removeHelper(name) {2128 const count = context.helpers.get(name);2129 if (count) {2130 const currentCount = count - 1;2131 if (!currentCount) {2132 context.helpers.delete(name);2133 }2134 else {2135 context.helpers.set(name, currentCount);2136 }2137 }2138 },2139 helperString(name) {2140 return `_${helperNameMap[context.helper(name)]}`;2141 },2142 replaceNode(node) {2143 /* istanbul ignore if */2144 {2145 if (!context.currentNode) {2146 throw new Error(`Node being replaced is already removed.`);2147 }2148 if (!context.parent) {2149 throw new Error(`Cannot replace root node.`);2150 }2151 }2152 context.parent.children[context.childIndex] = context.currentNode = node;2153 },2154 removeNode(node) {2155 if (!context.parent) {2156 throw new Error(`Cannot remove root node.`);2157 }2158 const list = context.parent.children;2159 const removalIndex = node2160 ? list.indexOf(node)2161 : context.currentNode2162 ? context.childIndex2163 : -1;2164 /* istanbul ignore if */2165 if (removalIndex < 0) {2166 throw new Error(`node being removed is not a child of current parent`);2167 }2168 if (!node || node === context.currentNode) {2169 // current node removed2170 context.currentNode = null;2171 context.onNodeRemoved();2172 }2173 else {2174 // sibling node removed2175 if (context.childIndex > removalIndex) {2176 context.childIndex--;2177 context.onNodeRemoved();2178 }2179 }2180 context.parent.children.splice(removalIndex, 1);2181 },2182 onNodeRemoved: () => { },2183 addIdentifiers(exp) {2184 },2185 removeIdentifiers(exp) {2186 },2187 hoist(exp) {2188 if (isString(exp))2189 exp = createSimpleExpression(exp);2190 context.hoists.push(exp);2191 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);2192 identifier.hoisted = exp;2193 return identifier;2194 },2195 cache(exp, isVNode = false) {2196 return createCacheExpression(context.cached++, exp, isVNode);2197 }2198 };2199 {2200 context.filters = new Set();2201 }2202 return context;2203}2204function transform(root, options) {2205 const context = createTransformContext(root, options);2206 traverseNode(root, context);2207 if (options.hoistStatic) {2208 hoistStatic(root, context);2209 }2210 if (!options.ssr) {2211 createRootCodegen(root, context);2212 }2213 // finalize meta information2214 root.helpers = [...context.helpers.keys()];2215 root.components = [...context.components];2216 root.directives = [...context.directives];2217 root.imports = context.imports;2218 root.hoists = context.hoists;2219 root.temps = context.temps;2220 root.cached = context.cached;2221 {2222 root.filters = [...context.filters];2223 }2224}2225function createRootCodegen(root, context) {2226 const { helper } = context;2227 const { children } = root;2228 if (children.length === 1) {2229 const child = children[0];2230 // if the single child is an element, turn it into a block.2231 if (isSingleElementRoot(root, child) && child.codegenNode) {2232 // single element root is never hoisted so codegenNode will never be2233 // SimpleExpressionNode2234 const codegenNode = child.codegenNode;2235 if (codegenNode.type === 13 /* VNODE_CALL */) {2236 makeBlock(codegenNode, context);2237 }2238 root.codegenNode = codegenNode;2239 }2240 else {2241 // - single <slot/>, IfNode, ForNode: already blocks.2242 // - single text node: always patched.2243 // root codegen falls through via genNode()2244 root.codegenNode = child;2245 }2246 }2247 else if (children.length > 1) {2248 // root has multiple nodes - return a fragment block.2249 let patchFlag = 64 /* STABLE_FRAGMENT */;2250 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];2251 // check if the fragment actually contains a single valid child with2252 // the rest being comments2253 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2254 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2255 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;2256 }2257 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, undefined, false /* isComponent */);2258 }2259 else ;2260}2261function traverseChildren(parent, context) {2262 let i = 0;2263 const nodeRemoved = () => {2264 i--;2265 };2266 for (; i < parent.children.length; i++) {2267 const child = parent.children[i];2268 if (isString(child))2269 continue;2270 context.parent = parent;2271 context.childIndex = i;2272 context.onNodeRemoved = nodeRemoved;2273 traverseNode(child, context);2274 }2275}2276function traverseNode(node, context) {2277 context.currentNode = node;2278 // apply transform plugins2279 const { nodeTransforms } = context;2280 const exitFns = [];2281 for (let i = 0; i < nodeTransforms.length; i++) {2282 const onExit = nodeTransforms[i](node, context);2283 if (onExit) {2284 if (isArray(onExit)) {2285 exitFns.push(...onExit);2286 }2287 else {2288 exitFns.push(onExit);2289 }2290 }2291 if (!context.currentNode) {2292 // node was removed2293 return;2294 }2295 else {2296 // node may have been replaced2297 node = context.currentNode;2298 }2299 }2300 switch (node.type) {2301 case 3 /* COMMENT */:2302 if (!context.ssr) {2303 // inject import for the Comment symbol, which is needed for creating2304 // comment nodes with `createVNode`2305 context.helper(CREATE_COMMENT);2306 }2307 break;2308 case 5 /* INTERPOLATION */:2309 // no need to traverse, but we need to inject toString helper2310 if (!context.ssr) {2311 context.helper(TO_DISPLAY_STRING);2312 }2313 break;2314 // for container types, further traverse downwards2315 case 9 /* IF */:2316 for (let i = 0; i < node.branches.length; i++) {2317 traverseNode(node.branches[i], context);2318 }2319 break;2320 case 10 /* IF_BRANCH */:2321 case 11 /* FOR */:2322 case 1 /* ELEMENT */:2323 case 0 /* ROOT */:2324 traverseChildren(node, context);2325 break;2326 }2327 // exit transforms2328 context.currentNode = node;2329 let i = exitFns.length;2330 while (i--) {2331 exitFns[i]();2332 }2333}2334function createStructuralDirectiveTransform(name, fn) {2335 const matches = isString(name)2336 ? (n) => n === name2337 : (n) => name.test(n);2338 return (node, context) => {2339 if (node.type === 1 /* ELEMENT */) {2340 const { props } = node;2341 // structural directive transforms are not concerned with slots2342 // as they are handled separately in vSlot.ts2343 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2344 return;2345 }2346 const exitFns = [];2347 for (let i = 0; i < props.length; i++) {2348 const prop = props[i];2349 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2350 // structural directives are removed to avoid infinite recursion2351 // also we remove them *before* applying so that it can further2352 // traverse itself in case it moves the node around2353 props.splice(i, 1);2354 i--;2355 const onExit = fn(node, prop, context);2356 if (onExit)2357 exitFns.push(onExit);2358 }2359 }2360 return exitFns;2361 }2362 };2363}2364const PURE_ANNOTATION = `/*#__PURE__*/`;2365function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {2366 const context = {2367 mode,2368 prefixIdentifiers,2369 sourceMap,2370 filename,2371 scopeId,2372 optimizeImports,2373 runtimeGlobalName,2374 runtimeModuleName,2375 ssrRuntimeModuleName,2376 ssr,2377 isTS,2378 inSSR,2379 source: ast.loc.source,2380 code: ``,2381 column: 1,2382 line: 1,2383 offset: 0,2384 indentLevel: 0,2385 pure: false,2386 map: undefined,2387 helper(key) {2388 return `_${helperNameMap[key]}`;2389 },2390 push(code, node) {2391 context.code += code;2392 },2393 indent() {2394 newline(++context.indentLevel);2395 },2396 deindent(withoutNewLine = false) {2397 if (withoutNewLine) {2398 --context.indentLevel;2399 }2400 else {2401 newline(--context.indentLevel);2402 }2403 },2404 newline() {2405 newline(context.indentLevel);2406 }2407 };2408 function newline(n) {2409 context.push('\n' + ` `.repeat(n));2410 }2411 return context;2412}2413function generate(ast, options = {}) {2414 const context = createCodegenContext(ast, options);2415 if (options.onContextCreated)2416 options.onContextCreated(context);2417 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2418 const hasHelpers = ast.helpers.length > 0;2419 const useWithBlock = !prefixIdentifiers && mode !== 'module';2420 // preambles2421 // in setup() inline mode, the preamble is generated in a sub context2422 // and returned separately.2423 const preambleContext = context;2424 {2425 genFunctionPreamble(ast, preambleContext);2426 }2427 // enter render function2428 const functionName = ssr ? `ssrRender` : `render`;2429 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2430 const signature = args.join(', ');2431 {2432 push(`function ${functionName}(${signature}) {`);2433 }2434 indent();2435 if (useWithBlock) {2436 push(`with (_ctx) {`);2437 indent();2438 // function mode const declarations should be inside with block2439 // also they should be renamed to avoid collision with user properties2440 if (hasHelpers) {2441 push(`const { ${ast.helpers2442 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2443 .join(', ')} } = _Vue`);2444 push(`\n`);2445 newline();2446 }2447 }2448 // generate asset resolution statements2449 if (ast.components.length) {2450 genAssets(ast.components, 'component', context);2451 if (ast.directives.length || ast.temps > 0) {2452 newline();2453 }2454 }2455 if (ast.directives.length) {2456 genAssets(ast.directives, 'directive', context);2457 if (ast.temps > 0) {2458 newline();2459 }2460 }2461 if (ast.filters && ast.filters.length) {2462 newline();2463 genAssets(ast.filters, 'filter', context);2464 newline();2465 }2466 if (ast.temps > 0) {2467 push(`let `);2468 for (let i = 0; i < ast.temps; i++) {2469 push(`${i > 0 ? `, ` : ``}_temp${i}`);2470 }2471 }2472 if (ast.components.length || ast.directives.length || ast.temps) {2473 push(`\n`);2474 newline();2475 }2476 // generate the VNode tree expression2477 if (!ssr) {2478 push(`return `);2479 }2480 if (ast.codegenNode) {2481 genNode(ast.codegenNode, context);2482 }2483 else {2484 push(`null`);2485 }2486 if (useWithBlock) {2487 deindent();2488 push(`}`);2489 }2490 deindent();2491 push(`}`);2492 return {2493 ast,2494 code: context.code,2495 preamble: ``,2496 // SourceMapGenerator does have toJSON() method but it's not in the types2497 map: context.map ? context.map.toJSON() : undefined2498 };2499}2500function genFunctionPreamble(ast, context) {2501 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;2502 const VueBinding = runtimeGlobalName;2503 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2504 // Generate const declaration for helpers2505 // In prefix mode, we place the const declaration at top so it's done2506 // only once; But if we not prefixing, we place the declaration inside the2507 // with block so it doesn't incur the `in` check cost for every helper access.2508 if (ast.helpers.length > 0) {2509 {2510 // "with" mode.2511 // save Vue in a separate variable to avoid collision2512 push(`const _Vue = ${VueBinding}\n`);2513 // in "with" mode, helpers are declared inside the with block to avoid2514 // has check cost, but hoists are lifted out of the function - we need2515 // to provide the helper here.2516 if (ast.hoists.length) {2517 const staticHelpers = [2518 CREATE_VNODE,2519 CREATE_ELEMENT_VNODE,2520 CREATE_COMMENT,2521 CREATE_TEXT,2522 CREATE_STATIC2523 ]2524 .filter(helper => ast.helpers.includes(helper))2525 .map(aliasHelper)2526 .join(', ');2527 push(`const { ${staticHelpers} } = _Vue\n`);2528 }2529 }2530 }2531 genHoists(ast.hoists, context);2532 newline();2533 push(`return `);2534}2535function genAssets(assets, type, { helper, push, newline, isTS }) {2536 const resolver = helper(type === 'filter'2537 ? RESOLVE_FILTER2538 : type === 'component'2539 ? RESOLVE_COMPONENT2540 : RESOLVE_DIRECTIVE);2541 for (let i = 0; i < assets.length; i++) {2542 let id = assets[i];2543 // potential component implicit self-reference inferred from SFC filename2544 const maybeSelfReference = id.endsWith('__self');2545 if (maybeSelfReference) {2546 id = id.slice(0, -6);2547 }2548 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);2549 if (i < assets.length - 1) {2550 newline();2551 }2552 }2553}2554function genHoists(hoists, context) {2555 if (!hoists.length) {2556 return;2557 }2558 context.pure = true;2559 const { push, newline, helper, scopeId, mode } = context;2560 newline();2561 for (let i = 0; i < hoists.length; i++) {2562 const exp = hoists[i];2563 if (exp) {2564 push(`const _hoisted_${i + 1} = ${``}`);2565 genNode(exp, context);2566 newline();2567 }2568 }2569 context.pure = false;2570}2571function isText$1(n) {2572 return (isString(n) ||2573 n.type === 4 /* SIMPLE_EXPRESSION */ ||2574 n.type === 2 /* TEXT */ ||2575 n.type === 5 /* INTERPOLATION */ ||2576 n.type === 8 /* COMPOUND_EXPRESSION */);2577}2578function genNodeListAsArray(nodes, context) {2579 const multilines = nodes.length > 3 ||2580 (nodes.some(n => isArray(n) || !isText$1(n)));2581 context.push(`[`);2582 multilines && context.indent();2583 genNodeList(nodes, context, multilines);2584 multilines && context.deindent();2585 context.push(`]`);2586}2587function genNodeList(nodes, context, multilines = false, comma = true) {2588 const { push, newline } = context;2589 for (let i = 0; i < nodes.length; i++) {2590 const node = nodes[i];2591 if (isString(node)) {2592 push(node);2593 }2594 else if (isArray(node)) {2595 genNodeListAsArray(node, context);2596 }2597 else {2598 genNode(node, context);2599 }2600 if (i < nodes.length - 1) {2601 if (multilines) {2602 comma && push(',');2603 newline();2604 }2605 else {2606 comma && push(', ');2607 }2608 }2609 }2610}2611function genNode(node, context) {2612 if (isString(node)) {2613 context.push(node);2614 return;2615 }2616 if (isSymbol(node)) {2617 context.push(context.helper(node));2618 return;2619 }2620 switch (node.type) {2621 case 1 /* ELEMENT */:2622 case 9 /* IF */:2623 case 11 /* FOR */:2624 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2625 `Apply appropriate transforms first.`);2626 genNode(node.codegenNode, context);2627 break;2628 case 2 /* TEXT */:2629 genText(node, context);2630 break;2631 case 4 /* SIMPLE_EXPRESSION */:2632 genExpression(node, context);2633 break;2634 case 5 /* INTERPOLATION */:2635 genInterpolation(node, context);2636 break;2637 case 12 /* TEXT_CALL */:2638 genNode(node.codegenNode, context);2639 break;2640 case 8 /* COMPOUND_EXPRESSION */:2641 genCompoundExpression(node, context);2642 break;2643 case 3 /* COMMENT */:2644 genComment(node, context);2645 break;2646 case 13 /* VNODE_CALL */:2647 genVNodeCall(node, context);2648 break;2649 case 14 /* JS_CALL_EXPRESSION */:2650 genCallExpression(node, context);2651 break;2652 case 15 /* JS_OBJECT_EXPRESSION */:2653 genObjectExpression(node, context);2654 break;2655 case 17 /* JS_ARRAY_EXPRESSION */:2656 genArrayExpression(node, context);2657 break;2658 case 18 /* JS_FUNCTION_EXPRESSION */:2659 genFunctionExpression(node, context);2660 break;2661 case 19 /* JS_CONDITIONAL_EXPRESSION */:2662 genConditionalExpression(node, context);2663 break;2664 case 20 /* JS_CACHE_EXPRESSION */:2665 genCacheExpression(node, context);2666 break;2667 case 21 /* JS_BLOCK_STATEMENT */:2668 genNodeList(node.body, context, true, false);2669 break;2670 // SSR only types2671 case 22 /* JS_TEMPLATE_LITERAL */:2672 break;2673 case 23 /* JS_IF_STATEMENT */:2674 break;2675 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2676 break;2677 case 25 /* JS_SEQUENCE_EXPRESSION */:2678 break;2679 case 26 /* JS_RETURN_STATEMENT */:2680 break;2681 /* istanbul ignore next */2682 case 10 /* IF_BRANCH */:2683 // noop2684 break;2685 default:2686 {2687 assert(false, `unhandled codegen node type: ${node.type}`);2688 // make sure we exhaust all possible types2689 const exhaustiveCheck = node;2690 return exhaustiveCheck;2691 }2692 }2693}2694function genText(node, context) {2695 context.push(JSON.stringify(node.content), node);2696}2697function genExpression(node, context) {2698 const { content, isStatic } = node;2699 context.push(isStatic ? JSON.stringify(content) : content, node);2700}2701function genInterpolation(node, context) {2702 const { push, helper, pure } = context;2703 if (pure)2704 push(PURE_ANNOTATION);2705 push(`${helper(TO_DISPLAY_STRING)}(`);2706 genNode(node.content, context);2707 push(`)`);2708}2709function genCompoundExpression(node, context) {2710 for (let i = 0; i < node.children.length; i++) {2711 const child = node.children[i];2712 if (isString(child)) {2713 context.push(child);2714 }2715 else {2716 genNode(child, context);2717 }2718 }2719}2720function genExpressionAsPropertyKey(node, context) {2721 const { push } = context;2722 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2723 push(`[`);2724 genCompoundExpression(node, context);2725 push(`]`);2726 }2727 else if (node.isStatic) {2728 // only quote keys if necessary2729 const text = isSimpleIdentifier(node.content)2730 ? node.content2731 : JSON.stringify(node.content);2732 push(text, node);2733 }2734 else {2735 push(`[${node.content}]`, node);2736 }2737}2738function genComment(node, context) {2739 const { push, helper, pure } = context;2740 if (pure) {2741 push(PURE_ANNOTATION);2742 }2743 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2744}2745function genVNodeCall(node, context) {2746 const { push, helper, pure } = context;2747 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;2748 if (directives) {2749 push(helper(WITH_DIRECTIVES) + `(`);2750 }2751 if (isBlock) {2752 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);2753 }2754 if (pure) {2755 push(PURE_ANNOTATION);2756 }2757 const callHelper = isBlock2758 ? getVNodeBlockHelper(context.inSSR, isComponent)2759 : getVNodeHelper(context.inSSR, isComponent);2760 push(helper(callHelper) + `(`, node);2761 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2762 push(`)`);2763 if (isBlock) {2764 push(`)`);2765 }2766 if (directives) {2767 push(`, `);2768 genNode(directives, context);2769 push(`)`);2770 }2771}2772function genNullableArgs(args) {2773 let i = args.length;2774 while (i--) {2775 if (args[i] != null)2776 break;2777 }2778 return args.slice(0, i + 1).map(arg => arg || `null`);2779}2780// JavaScript2781function genCallExpression(node, context) {2782 const { push, helper, pure } = context;2783 const callee = isString(node.callee) ? node.callee : helper(node.callee);2784 if (pure) {2785 push(PURE_ANNOTATION);2786 }2787 push(callee + `(`, node);2788 genNodeList(node.arguments, context);2789 push(`)`);2790}2791function genObjectExpression(node, context) {2792 const { push, indent, deindent, newline } = context;2793 const { properties } = node;2794 if (!properties.length) {2795 push(`{}`, node);2796 return;2797 }2798 const multilines = properties.length > 1 ||2799 (properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2800 push(multilines ? `{` : `{ `);2801 multilines && indent();2802 for (let i = 0; i < properties.length; i++) {2803 const { key, value } = properties[i];2804 // key2805 genExpressionAsPropertyKey(key, context);2806 push(`: `);2807 // value2808 genNode(value, context);2809 if (i < properties.length - 1) {2810 // will only reach this if it's multilines2811 push(`,`);2812 newline();2813 }2814 }2815 multilines && deindent();2816 push(multilines ? `}` : ` }`);2817}2818function genArrayExpression(node, context) {2819 genNodeListAsArray(node.elements, context);2820}2821function genFunctionExpression(node, context) {2822 const { push, indent, deindent } = context;2823 const { params, returns, body, newline, isSlot } = node;2824 if (isSlot) {2825 // wrap slot functions with owner context2826 push(`_${helperNameMap[WITH_CTX]}(`);2827 }2828 push(`(`, node);2829 if (isArray(params)) {2830 genNodeList(params, context);2831 }2832 else if (params) {2833 genNode(params, context);2834 }2835 push(`) => `);2836 if (newline || body) {2837 push(`{`);2838 indent();2839 }2840 if (returns) {2841 if (newline) {2842 push(`return `);2843 }2844 if (isArray(returns)) {2845 genNodeListAsArray(returns, context);2846 }2847 else {2848 genNode(returns, context);2849 }2850 }2851 else if (body) {2852 genNode(body, context);2853 }2854 if (newline || body) {2855 deindent();2856 push(`}`);2857 }2858 if (isSlot) {2859 if (node.isNonScopedSlot) {2860 push(`, undefined, true`);2861 }2862 push(`)`);2863 }2864}2865function genConditionalExpression(node, context) {2866 const { test, consequent, alternate, newline: needNewline } = node;2867 const { push, indent, deindent, newline } = context;2868 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2869 const needsParens = !isSimpleIdentifier(test.content);2870 needsParens && push(`(`);2871 genExpression(test, context);2872 needsParens && push(`)`);2873 }2874 else {2875 push(`(`);2876 genNode(test, context);2877 push(`)`);2878 }2879 needNewline && indent();2880 context.indentLevel++;2881 needNewline || push(` `);2882 push(`? `);2883 genNode(consequent, context);2884 context.indentLevel--;2885 needNewline && newline();2886 needNewline || push(` `);2887 push(`: `);2888 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2889 if (!isNested) {2890 context.indentLevel++;2891 }2892 genNode(alternate, context);2893 if (!isNested) {2894 context.indentLevel--;2895 }2896 needNewline && deindent(true /* without newline */);2897}2898function genCacheExpression(node, context) {2899 const { push, helper, indent, deindent, newline } = context;2900 push(`_cache[${node.index}] || (`);2901 if (node.isVNode) {2902 indent();2903 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2904 newline();2905 }2906 push(`_cache[${node.index}] = `);2907 genNode(node.value, context);2908 if (node.isVNode) {2909 push(`,`);2910 newline();2911 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2912 newline();2913 push(`_cache[${node.index}]`);2914 deindent();2915 }2916 push(`)`);2917}2918function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {2919 {2920 return;2921 }2922}2923function isReferencedIdentifier(id, parent, parentStack) {2924 {2925 return false;2926 }2927}2928function isInDestructureAssignment(parent, parentStack) {2929 if (parent &&2930 (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {2931 let i = parentStack.length;2932 while (i--) {2933 const p = parentStack[i];2934 if (p.type === 'AssignmentExpression') {2935 return true;2936 }2937 else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {2938 break;2939 }2940 }2941 }2942 return false;2943}2944function walkFunctionParams(node, onIdent) {2945 for (const p of node.params) {2946 for (const id of extractIdentifiers(p)) {2947 onIdent(id);2948 }2949 }2950}2951function walkBlockDeclarations(block, onIdent) {2952 for (const stmt of block.body) {2953 if (stmt.type === 'VariableDeclaration') {2954 if (stmt.declare)2955 continue;2956 for (const decl of stmt.declarations) {2957 for (const id of extractIdentifiers(decl.id)) {2958 onIdent(id);2959 }2960 }2961 }2962 else if (stmt.type === 'FunctionDeclaration' ||2963 stmt.type === 'ClassDeclaration') {2964 if (stmt.declare || !stmt.id)2965 continue;2966 onIdent(stmt.id);2967 }2968 }2969}2970function extractIdentifiers(param, nodes = []) {2971 switch (param.type) {2972 case 'Identifier':2973 nodes.push(param);2974 break;2975 case 'MemberExpression':2976 let object = param;2977 while (object.type === 'MemberExpression') {2978 object = object.object;2979 }2980 nodes.push(object);2981 break;2982 case 'ObjectPattern':2983 for (const prop of param.properties) {2984 if (prop.type === 'RestElement') {2985 extractIdentifiers(prop.argument, nodes);2986 }2987 else {2988 extractIdentifiers(prop.value, nodes);2989 }2990 }2991 break;2992 case 'ArrayPattern':2993 param.elements.forEach(element => {2994 if (element)2995 extractIdentifiers(element, nodes);2996 });2997 break;2998 case 'RestElement':2999 extractIdentifiers(param.argument, nodes);3000 break;3001 case 'AssignmentPattern':3002 extractIdentifiers(param.left, nodes);3003 break;3004 }3005 return nodes;3006}3007const isFunctionType = (node) => {3008 return /Function(?:Expression|Declaration)$|Method$/.test(node.type);3009};3010const isStaticProperty = (node) => node &&3011 (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&3012 !node.computed;3013const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;3014// these keywords should not appear inside expressions, but operators like3015// typeof, instanceof and in are allowed3016const prohibitedKeywordRE = new RegExp('\\b' +3017 ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +3018 'super,throw,while,yield,delete,export,import,return,switch,default,' +3019 'extends,finally,continue,debugger,function,arguments,typeof,void')3020 .split(',')3021 .join('\\b|\\b') +3022 '\\b');3023// strip strings in expressions3024const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;3025/**3026 * Validate a non-prefixed expression.3027 * This is only called when using the in-browser runtime compiler since it3028 * doesn't prefix expressions.3029 */3030function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) {3031 const exp = node.content;3032 // empty expressions are validated per-directive since some directives3033 // do allow empty expressions.3034 if (!exp.trim()) {3035 return;3036 }3037 try {3038 new Function(asRawStatements3039 ? ` ${exp} `3040 : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`);3041 }3042 catch (e) {3043 let message = e.message;3044 const keywordMatch = exp3045 .replace(stripStringRE, '')3046 .match(prohibitedKeywordRE);3047 if (keywordMatch) {3048 message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`;3049 }3050 context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message));3051 }3052}3053const transformExpression = (node, context) => {3054 if (node.type === 5 /* INTERPOLATION */) {3055 node.content = processExpression(node.content, context);3056 }3057 else if (node.type === 1 /* ELEMENT */) {3058 // handle directives on element3059 for (let i = 0; i < node.props.length; i++) {3060 const dir = node.props[i];3061 // do not process for v-on & v-for since they are special handled3062 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {3063 const exp = dir.exp;3064 const arg = dir.arg;3065 // do not process exp if this is v-on:arg - we need special handling3066 // for wrapping inline statements.3067 if (exp &&3068 exp.type === 4 /* SIMPLE_EXPRESSION */ &&3069 !(dir.name === 'on' && arg)) {3070 dir.exp = processExpression(exp, context, 3071 // slot args must be processed as function params3072 dir.name === 'slot');3073 }3074 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {3075 dir.arg = processExpression(arg, context);3076 }3077 }3078 }3079 }3080};3081// Important: since this function uses Node.js only dependencies, it should3082// always be used with a leading !true check so that it can be3083// tree-shaken from the browser build.3084function processExpression(node, context, 3085// some expressions like v-slot props & v-for aliases should be parsed as3086// function params3087asParams = false, 3088// v-on handler values may contain multiple statements3089asRawStatements = false, localVars = Object.create(context.identifiers)) {3090 {3091 {3092 // simple in-browser validation (same logic in 2.x)3093 validateBrowserExpression(node, context, asParams, asRawStatements);3094 }3095 return node;3096 }3097}3098const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {3099 return processIf(node, dir, context, (ifNode, branch, isRoot) => {3100 // #1587: We need to dynamically increment the key based on the current3101 // node's sibling nodes, since chained v-if/else branches are3102 // rendered at the same depth3103 const siblings = context.parent.children;3104 let i = siblings.indexOf(ifNode);3105 let key = 0;3106 while (i-- >= 0) {3107 const sibling = siblings[i];3108 if (sibling && sibling.type === 9 /* IF */) {3109 key += sibling.branches.length;3110 }3111 }3112 // Exit callback. Complete the codegenNode when all children have been3113 // transformed.3114 return () => {3115 if (isRoot) {3116 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);3117 }3118 else {3119 // attach this branch's codegen node to the v-if root.3120 const parentCondition = getParentCondition(ifNode.codegenNode);3121 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);3122 }3123 };3124 });3125});3126// target-agnostic transform used for both Client and SSR3127function processIf(node, dir, context, processCodegen) {3128 if (dir.name !== 'else' &&3129 (!dir.exp || !dir.exp.content.trim())) {3130 const loc = dir.exp ? dir.exp.loc : node.loc;3131 context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc));3132 dir.exp = createSimpleExpression(`true`, false, loc);3133 }3134 if (dir.exp) {3135 validateBrowserExpression(dir.exp, context);3136 }3137 if (dir.name === 'if') {3138 const branch = createIfBranch(node, dir);3139 const ifNode = {3140 type: 9 /* IF */,3141 loc: node.loc,3142 branches: [branch]3143 };3144 context.replaceNode(ifNode);3145 if (processCodegen) {3146 return processCodegen(ifNode, branch, true);3147 }3148 }3149 else {3150 // locate the adjacent v-if3151 const siblings = context.parent.children;3152 const comments = [];3153 let i = siblings.indexOf(node);3154 while (i-- >= -1) {3155 const sibling = siblings[i];3156 if (sibling && sibling.type === 3 /* COMMENT */) {3157 context.removeNode(sibling);3158 comments.unshift(sibling);3159 continue;3160 }3161 if (sibling &&3162 sibling.type === 2 /* TEXT */ &&3163 !sibling.content.trim().length) {3164 context.removeNode(sibling);3165 continue;3166 }3167 if (sibling && sibling.type === 9 /* IF */) {3168 // Check if v-else was followed by v-else-if3169 if (dir.name === 'else-if' &&3170 sibling.branches[sibling.branches.length - 1].condition === undefined) {3171 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3172 }3173 // move the node to the if node's branches3174 context.removeNode();3175 const branch = createIfBranch(node, dir);3176 if (comments.length &&3177 // #3619 ignore comments if the v-if is direct child of <transition>3178 !(context.parent &&3179 context.parent.type === 1 /* ELEMENT */ &&3180 isBuiltInType(context.parent.tag, 'transition'))) {3181 branch.children = [...comments, ...branch.children];3182 }3183 // check if user is forcing same key on different branches3184 {3185 const key = branch.userKey;3186 if (key) {3187 sibling.branches.forEach(({ userKey }) => {3188 if (isSameKey(userKey, key)) {3189 context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc));3190 }3191 });3192 }3193 }3194 sibling.branches.push(branch);3195 const onExit = processCodegen && processCodegen(sibling, branch, false);3196 // since the branch was removed, it will not be traversed.3197 // make sure to traverse here.3198 traverseNode(branch, context);3199 // call on exit3200 if (onExit)3201 onExit();3202 // make sure to reset currentNode after traversal to indicate this3203 // node has been removed.3204 context.currentNode = null;3205 }3206 else {3207 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3208 }3209 break;3210 }3211 }3212}3213function createIfBranch(node, dir) {3214 return {3215 type: 10 /* IF_BRANCH */,3216 loc: node.loc,3217 condition: dir.name === 'else' ? undefined : dir.exp,3218 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')3219 ? node.children3220 : [node],3221 userKey: findProp(node, `key`)3222 };3223}3224function createCodegenNodeForBranch(branch, keyIndex, context) {3225 if (branch.condition) {3226 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 3227 // make sure to pass in asBlock: true so that the comment node call3228 // closes the current block.3229 createCallExpression(context.helper(CREATE_COMMENT), [3230 '"v-if"' ,3231 'true'3232 ]));3233 }3234 else {3235 return createChildrenCodegenNode(branch, keyIndex, context);3236 }3237}3238function createChildrenCodegenNode(branch, keyIndex, context) {3239 const { helper } = context;3240 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));3241 const { children } = branch;3242 const firstChild = children[0];3243 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;3244 if (needFragmentWrapper) {3245 if (children.length === 1 && firstChild.type === 11 /* FOR */) {3246 // optimize away nested fragments when child is a ForNode3247 const vnodeCall = firstChild.codegenNode;3248 injectProp(vnodeCall, keyProperty, context);3249 return vnodeCall;3250 }3251 else {3252 let patchFlag = 64 /* STABLE_FRAGMENT */;3253 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];3254 // check if the fragment actually contains a single valid child with3255 // the rest being comments3256 if (children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {3257 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;3258 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;3259 }3260 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (` /* ${patchFlagText} */` ), undefined, undefined, true, false, false /* isComponent */, branch.loc);3261 }3262 }3263 else {3264 const ret = firstChild.codegenNode;3265 const vnodeCall = getMemoedVNodeCall(ret);3266 // Change createVNode to createBlock.3267 if (vnodeCall.type === 13 /* VNODE_CALL */) {3268 makeBlock(vnodeCall, context);3269 }3270 // inject branch key3271 injectProp(vnodeCall, keyProperty, context);3272 return ret;3273 }3274}3275function isSameKey(a, b) {3276 if (!a || a.type !== b.type) {3277 return false;3278 }3279 if (a.type === 6 /* ATTRIBUTE */) {3280 if (a.value.content !== b.value.content) {3281 return false;3282 }3283 }3284 else {3285 // directive3286 const exp = a.exp;3287 const branchExp = b.exp;3288 if (exp.type !== branchExp.type) {3289 return false;3290 }3291 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||3292 exp.isStatic !== branchExp.isStatic ||3293 exp.content !== branchExp.content) {3294 return false;3295 }3296 }3297 return true;3298}3299function getParentCondition(node) {3300 while (true) {3301 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3302 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3303 node = node.alternate;3304 }3305 else {3306 return node;3307 }3308 }3309 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {3310 node = node.value;3311 }3312 }3313}3314const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {3315 const { helper, removeHelper } = context;3316 return processFor(node, dir, context, forNode => {3317 // create the loop render function expression now, and add the3318 // iterator on exit after all children have been traversed3319 const renderExp = createCallExpression(helper(RENDER_LIST), [3320 forNode.source3321 ]);3322 const memo = findDir(node, 'memo');3323 const keyProp = findProp(node, `key`);3324 const keyExp = keyProp &&3325 (keyProp.type === 6 /* ATTRIBUTE */3326 ? createSimpleExpression(keyProp.value.content, true)3327 : keyProp.exp);3328 const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;3329 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3330 forNode.source.constType > 0 /* NOT_CONSTANT */;3331 const fragmentFlag = isStableFragment3332 ? 64 /* STABLE_FRAGMENT */3333 : keyProp3334 ? 128 /* KEYED_FRAGMENT */3335 : 256 /* UNKEYED_FRAGMENT */;3336 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3337 (` /* ${PatchFlagNames[fragmentFlag]} */` ), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);3338 return () => {3339 // finish the codegen now that all children have been traversed3340 let childBlock;3341 const isTemplate = isTemplateNode(node);3342 const { children } = forNode;3343 // check <template v-for> key placement3344 if (isTemplate) {3345 node.children.some(c => {3346 if (c.type === 1 /* ELEMENT */) {3347 const key = findProp(c, 'key');3348 if (key) {3349 context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3350 return true;3351 }3352 }3353 });3354 }3355 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3356 const slotOutlet = isSlotOutlet(node)3357 ? node3358 : isTemplate &&3359 node.children.length === 1 &&3360 isSlotOutlet(node.children[0])3361 ? node.children[0] // api-extractor somehow fails to infer this3362 : null;3363 if (slotOutlet) {3364 // <slot v-for="..."> or <template v-for="..."><slot/></template>3365 childBlock = slotOutlet.codegenNode;3366 if (isTemplate && keyProperty) {3367 // <template v-for="..." :key="..."><slot/></template>3368 // we need to inject the key to the renderSlot() call.3369 // the props for renderSlot is passed as the 3rd argument.3370 injectProp(childBlock, keyProperty, context);3371 }3372 }3373 else if (needFragmentWrapper) {3374 // <template v-for="..."> with text or multi-elements3375 // should generate a fragment block for each loop3376 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3377 (` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`3378 ), undefined, undefined, true, undefined, false /* isComponent */);3379 }3380 else {3381 // Normal element v-for. Directly use the child's codegenNode3382 // but mark it as a block.3383 childBlock = children[0]3384 .codegenNode;3385 if (isTemplate && keyProperty) {3386 injectProp(childBlock, keyProperty, context);3387 }3388 if (childBlock.isBlock !== !isStableFragment) {3389 if (childBlock.isBlock) {3390 // switch from block to vnode3391 removeHelper(OPEN_BLOCK);3392 removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3393 }3394 else {3395 // switch from vnode to block3396 removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));3397 }3398 }3399 childBlock.isBlock = !isStableFragment;3400 if (childBlock.isBlock) {3401 helper(OPEN_BLOCK);3402 helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3403 }3404 else {3405 helper(getVNodeHelper(context.inSSR, childBlock.isComponent));3406 }3407 }3408 if (memo) {3409 const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [3410 createSimpleExpression(`_cached`)3411 ]));3412 loop.body = createBlockStatement([3413 createCompoundExpression([`const _memo = (`, memo.exp, `)`]),3414 createCompoundExpression([3415 `if (_cached`,3416 ...(keyExp ? [` && _cached.key === `, keyExp] : []),3417 ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`3418 ]),3419 createCompoundExpression([`const _item = `, childBlock]),3420 createSimpleExpression(`_item.memo = _memo`),3421 createSimpleExpression(`return _item`)3422 ]);3423 renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));3424 }3425 else {3426 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3427 }3428 };3429 });3430});3431// target-agnostic transform used for both Client and SSR3432function processFor(node, dir, context, processCodegen) {3433 if (!dir.exp) {3434 context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3435 return;3436 }3437 const parseResult = parseForExpression(3438 // can only be simple expression because vFor transform is applied3439 // before expression transform.3440 dir.exp, context);3441 if (!parseResult) {3442 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3443 return;3444 }3445 const { addIdentifiers, removeIdentifiers, scopes } = context;3446 const { source, value, key, index } = parseResult;3447 const forNode = {3448 type: 11 /* FOR */,3449 loc: dir.loc,3450 source,3451 valueAlias: value,3452 keyAlias: key,3453 objectIndexAlias: index,3454 parseResult,3455 children: isTemplateNode(node) ? node.children : [node]3456 };3457 context.replaceNode(forNode);3458 // bookkeeping3459 scopes.vFor++;3460 const onExit = processCodegen && processCodegen(forNode);3461 return () => {3462 scopes.vFor--;3463 if (onExit)3464 onExit();3465 };3466}3467const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3468// This regex doesn't cover the case if key or index aliases have destructuring,3469// but those do not make sense in the first place, so this works in practice.3470const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3471const stripParensRE = /^\(|\)$/g;3472function parseForExpression(input, context) {3473 const loc = input.loc;3474 const exp = input.content;3475 const inMatch = exp.match(forAliasRE);3476 if (!inMatch)3477 return;3478 const [, LHS, RHS] = inMatch;3479 const result = {3480 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3481 value: undefined,3482 key: undefined,3483 index: undefined3484 };3485 {3486 validateBrowserExpression(result.source, context);3487 }3488 let valueContent = LHS.trim().replace(stripParensRE, '').trim();3489 const trimmedOffset = LHS.indexOf(valueContent);3490 const iteratorMatch = valueContent.match(forIteratorRE);3491 if (iteratorMatch) {3492 valueContent = valueContent.replace(forIteratorRE, '').trim();3493 const keyContent = iteratorMatch[1].trim();3494 let keyOffset;3495 if (keyContent) {3496 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3497 result.key = createAliasExpression(loc, keyContent, keyOffset);3498 {3499 validateBrowserExpression(result.key, context, true);3500 }3501 }3502 if (iteratorMatch[2]) {3503 const indexContent = iteratorMatch[2].trim();3504 if (indexContent) {3505 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3506 ? keyOffset + keyContent.length3507 : trimmedOffset + valueContent.length));3508 {3509 validateBrowserExpression(result.index, context, true);3510 }3511 }3512 }3513 }3514 if (valueContent) {3515 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3516 {3517 validateBrowserExpression(result.value, context, true);3518 }3519 }3520 return result;3521}3522function createAliasExpression(range, content, offset) {3523 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3524}3525function createForLoopParams({ value, key, index }, memoArgs = []) {3526 return createParamsList([value, key, index, ...memoArgs]);3527}3528function createParamsList(args) {3529 let i = args.length;3530 while (i--) {3531 if (args[i])3532 break;3533 }3534 return args3535 .slice(0, i + 1)3536 .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));3537}3538const defaultFallback = createSimpleExpression(`undefined`, false);3539// A NodeTransform that:3540// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3541// by transformExpression. This is only applied in non-browser builds with3542// { prefixIdentifiers: true }.3543// 2. Track v-slot depths so that we know a slot is inside another slot.3544// Note the exit callback is executed before buildSlots() on the same node,3545// so only nested slots see positive numbers.3546const trackSlotScopes = (node, context) => {3547 if (node.type === 1 /* ELEMENT */ &&3548 (node.tagType === 1 /* COMPONENT */ ||3549 node.tagType === 3 /* TEMPLATE */)) {3550 // We are only checking non-empty v-slot here3551 // since we only care about slots that introduce scope variables.3552 const vSlot = findDir(node, 'slot');3553 if (vSlot) {3554 vSlot.exp;3555 context.scopes.vSlot++;3556 return () => {3557 context.scopes.vSlot--;3558 };3559 }3560 }3561};3562// A NodeTransform that tracks scope identifiers for scoped slots with v-for.3563// This transform is only applied in non-browser builds with { prefixIdentifiers: true }3564const trackVForSlotScopes = (node, context) => {3565 let vFor;3566 if (isTemplateNode(node) &&3567 node.props.some(isVSlot) &&3568 (vFor = findDir(node, 'for'))) {3569 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3570 if (result) {3571 const { value, key, index } = result;3572 const { addIdentifiers, removeIdentifiers } = context;3573 value && addIdentifiers(value);3574 key && addIdentifiers(key);3575 index && addIdentifiers(index);3576 return () => {3577 value && removeIdentifiers(value);3578 key && removeIdentifiers(key);3579 index && removeIdentifiers(index);3580 };3581 }3582 }3583};3584const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3585// Instead of being a DirectiveTransform, v-slot processing is called during3586// transformElement to build the slots object for a component.3587function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3588 context.helper(WITH_CTX);3589 const { children, loc } = node;3590 const slotsProperties = [];3591 const dynamicSlots = [];3592 // If the slot is inside a v-for or another v-slot, force it to be dynamic3593 // since it likely uses a scope variable.3594 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3595 // 1. Check for slot with slotProps on component itself.3596 // <Comp v-slot="{ prop }"/>3597 const onComponentSlot = findDir(node, 'slot', true);3598 if (onComponentSlot) {3599 const { arg, exp } = onComponentSlot;3600 if (arg && !isStaticExp(arg)) {3601 hasDynamicSlots = true;3602 }3603 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));3604 }3605 // 2. Iterate through children and check for template slots3606 // <template v-slot:foo="{ prop }">3607 let hasTemplateSlots = false;3608 let hasNamedDefaultSlot = false;3609 const implicitDefaultChildren = [];3610 const seenSlotNames = new Set();3611 for (let i = 0; i < children.length; i++) {3612 const slotElement = children[i];3613 let slotDir;3614 if (!isTemplateNode(slotElement) ||3615 !(slotDir = findDir(slotElement, 'slot', true))) {3616 // not a <template v-slot>, skip.3617 if (slotElement.type !== 3 /* COMMENT */) {3618 implicitDefaultChildren.push(slotElement);3619 }3620 continue;3621 }3622 if (onComponentSlot) {3623 // already has on-component slot - this is incorrect usage.3624 context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3625 break;3626 }3627 hasTemplateSlots = true;3628 const { children: slotChildren, loc: slotLoc } = slotElement;3629 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3630 // check if name is dynamic.3631 let staticSlotName;3632 if (isStaticExp(slotName)) {3633 staticSlotName = slotName ? slotName.content : `default`;3634 }3635 else {3636 hasDynamicSlots = true;3637 }3638 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3639 // check if this slot is conditional (v-if/v-for)3640 let vIf;3641 let vElse;3642 let vFor;3643 if ((vIf = findDir(slotElement, 'if'))) {3644 hasDynamicSlots = true;3645 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3646 }3647 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3648 // find adjacent v-if3649 let j = i;3650 let prev;3651 while (j--) {3652 prev = children[j];3653 if (prev.type !== 3 /* COMMENT */) {3654 break;3655 }3656 }3657 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3658 // remove node3659 children.splice(i, 1);3660 i--;3661 // attach this slot to previous conditional3662 let conditional = dynamicSlots[dynamicSlots.length - 1];3663 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3664 conditional = conditional.alternate;3665 }3666 conditional.alternate = vElse.exp3667 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3668 : buildDynamicSlot(slotName, slotFunction);3669 }3670 else {3671 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3672 }3673 }3674 else if ((vFor = findDir(slotElement, 'for'))) {3675 hasDynamicSlots = true;3676 const parseResult = vFor.parseResult ||3677 parseForExpression(vFor.exp, context);3678 if (parseResult) {3679 // Render the dynamic slots as an array and add it to the createSlot()3680 // args. The runtime knows how to handle it appropriately.3681 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3682 parseResult.source,3683 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3684 ]));3685 }3686 else {3687 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3688 }3689 }3690 else {3691 // check duplicate static names3692 if (staticSlotName) {3693 if (seenSlotNames.has(staticSlotName)) {3694 context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3695 continue;3696 }3697 seenSlotNames.add(staticSlotName);3698 if (staticSlotName === 'default') {3699 hasNamedDefaultSlot = true;3700 }3701 }3702 slotsProperties.push(createObjectProperty(slotName, slotFunction));3703 }3704 }3705 if (!onComponentSlot) {3706 const buildDefaultSlotProperty = (props, children) => {3707 const fn = buildSlotFn(props, children, loc);3708 if (context.compatConfig) {3709 fn.isNonScopedSlot = true;3710 }3711 return createObjectProperty(`default`, fn);3712 };3713 if (!hasTemplateSlots) {3714 // implicit default slot (on component)3715 slotsProperties.push(buildDefaultSlotProperty(undefined, children));3716 }3717 else if (implicitDefaultChildren.length &&3718 // #37663719 // with whitespace: 'preserve', whitespaces between slots will end up in3720 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.3721 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {3722 // implicit default slot (mixed with named slots)3723 if (hasNamedDefaultSlot) {3724 context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));3725 }3726 else {3727 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));3728 }3729 }3730 }3731 const slotFlag = hasDynamicSlots3732 ? 2 /* DYNAMIC */3733 : hasForwardedSlots(node.children)3734 ? 3 /* FORWARDED */3735 : 1 /* STABLE */;3736 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 3737 // 2 = compiled but dynamic = can skip normalization, but must run diff3738 // 1 = compiled and static = can skip normalization AND diff as optimized3739 createSimpleExpression(slotFlag + (` /* ${slotFlagsText[slotFlag]} */` ), false))), loc);3740 if (dynamicSlots.length) {3741 slots = createCallExpression(context.helper(CREATE_SLOTS), [3742 slots,3743 createArrayExpression(dynamicSlots)3744 ]);3745 }3746 return {3747 slots,3748 hasDynamicSlots3749 };3750}3751function buildDynamicSlot(name, fn) {3752 return createObjectExpression([3753 createObjectProperty(`name`, name),3754 createObjectProperty(`fn`, fn)3755 ]);3756}3757function hasForwardedSlots(children) {3758 for (let i = 0; i < children.length; i++) {3759 const child = children[i];3760 switch (child.type) {3761 case 1 /* ELEMENT */:3762 if (child.tagType === 2 /* SLOT */ ||3763 hasForwardedSlots(child.children)) {3764 return true;3765 }3766 break;3767 case 9 /* IF */:3768 if (hasForwardedSlots(child.branches))3769 return true;3770 break;3771 case 10 /* IF_BRANCH */:3772 case 11 /* FOR */:3773 if (hasForwardedSlots(child.children))3774 return true;3775 break;3776 }3777 }3778 return false;3779}3780function isNonWhitespaceContent(node) {3781 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)3782 return true;3783 return node.type === 2 /* TEXT */3784 ? !!node.content.trim()3785 : isNonWhitespaceContent(node.content);3786}3787// some directive transforms (e.g. v-model) may return a symbol for runtime3788// import, which should be used instead of a resolveDirective call.3789const directiveImportMap = new WeakMap();3790// generate a JavaScript AST for this element's codegen3791const transformElement = (node, context) => {3792 // perform the work on exit, after all child expressions have been3793 // processed and merged.3794 return function postTransformElement() {3795 node = context.currentNode;3796 if (!(node.type === 1 /* ELEMENT */ &&3797 (node.tagType === 0 /* ELEMENT */ ||3798 node.tagType === 1 /* COMPONENT */))) {3799 return;3800 }3801 const { tag, props } = node;3802 const isComponent = node.tagType === 1 /* COMPONENT */;3803 // The goal of the transform is to create a codegenNode implementing the3804 // VNodeCall interface.3805 let vnodeTag = isComponent3806 ? resolveComponentType(node, context)3807 : `"${tag}"`;3808 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;3809 let vnodeProps;3810 let vnodeChildren;3811 let vnodePatchFlag;3812 let patchFlag = 0;3813 let vnodeDynamicProps;3814 let dynamicPropNames;3815 let vnodeDirectives;3816 let shouldUseBlock = 3817 // dynamic component may resolve to plain elements3818 isDynamicComponent ||3819 vnodeTag === TELEPORT ||3820 vnodeTag === SUSPENSE ||3821 (!isComponent &&3822 // <svg> and <foreignObject> must be forced into blocks so that block3823 // updates inside get proper isSVG flag at runtime. (#639, #643)3824 // This is technically web-specific, but splitting the logic out of core3825 // leads to too much unnecessary complexity.3826 (tag === 'svg' ||3827 tag === 'foreignObject' ||3828 // #938: elements with dynamic keys should be forced into blocks3829 findProp(node, 'key', true)));3830 // props3831 if (props.length > 0) {3832 const propsBuildResult = buildProps(node, context);3833 vnodeProps = propsBuildResult.props;3834 patchFlag = propsBuildResult.patchFlag;3835 dynamicPropNames = propsBuildResult.dynamicPropNames;3836 const directives = propsBuildResult.directives;3837 vnodeDirectives =3838 directives && directives.length3839 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))3840 : undefined;3841 }3842 // children3843 if (node.children.length > 0) {3844 if (vnodeTag === KEEP_ALIVE) {3845 // Although a built-in component, we compile KeepAlive with raw children3846 // instead of slot functions so that it can be used inside Transition3847 // or other Transition-wrapping HOCs.3848 // To ensure correct updates with block optimizations, we need to:3849 // 1. Force keep-alive into a block. This avoids its children being3850 // collected by a parent block.3851 shouldUseBlock = true;3852 // 2. Force keep-alive to always be updated, since it uses raw children.3853 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3854 if (node.children.length > 1) {3855 context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {3856 start: node.children[0].loc.start,3857 end: node.children[node.children.length - 1].loc.end,3858 source: ''3859 }));3860 }3861 }3862 const shouldBuildAsSlots = isComponent &&3863 // Teleport is not a real component and has dedicated runtime handling3864 vnodeTag !== TELEPORT &&3865 // explained above.3866 vnodeTag !== KEEP_ALIVE;3867 if (shouldBuildAsSlots) {3868 const { slots, hasDynamicSlots } = buildSlots(node, context);3869 vnodeChildren = slots;3870 if (hasDynamicSlots) {3871 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3872 }3873 }3874 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {3875 const child = node.children[0];3876 const type = child.type;3877 // check for dynamic text children3878 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||3879 type === 8 /* COMPOUND_EXPRESSION */;3880 if (hasDynamicTextChild &&3881 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {3882 patchFlag |= 1 /* TEXT */;3883 }3884 // pass directly if the only child is a text node3885 // (plain / interpolation / expression)3886 if (hasDynamicTextChild || type === 2 /* TEXT */) {3887 vnodeChildren = child;3888 }3889 else {3890 vnodeChildren = node.children;3891 }3892 }3893 else {3894 vnodeChildren = node.children;3895 }3896 }3897 // patchFlag & dynamicPropNames3898 if (patchFlag !== 0) {3899 {3900 if (patchFlag < 0) {3901 // special flags (negative and mutually exclusive)3902 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;3903 }3904 else {3905 // bitwise flags3906 const flagNames = Object.keys(PatchFlagNames)3907 .map(Number)3908 .filter(n => n > 0 && patchFlag & n)3909 .map(n => PatchFlagNames[n])3910 .join(`, `);3911 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;3912 }3913 }3914 if (dynamicPropNames && dynamicPropNames.length) {3915 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);3916 }3917 }3918 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);3919 };3920};3921function resolveComponentType(node, context, ssr = false) {3922 let { tag } = node;3923 // 1. dynamic component3924 const isExplicitDynamic = isComponentTag(tag);3925 const isProp = findProp(node, 'is');3926 if (isProp) {3927 if (isExplicitDynamic ||3928 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {3929 const exp = isProp.type === 6 /* ATTRIBUTE */3930 ? isProp.value && createSimpleExpression(isProp.value.content, true)3931 : isProp.exp;3932 if (exp) {3933 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3934 exp3935 ]);3936 }3937 }3938 else if (isProp.type === 6 /* ATTRIBUTE */ &&3939 isProp.value.content.startsWith('vue:')) {3940 // <button is="vue:xxx">3941 // if not <component>, only is value that starts with "vue:" will be3942 // treated as component by the parse phase and reach here, unless it's3943 // compat mode where all is values are considered components3944 tag = isProp.value.content.slice(4);3945 }3946 }3947 // 1.5 v-is (TODO: Deprecate)3948 const isDir = !isExplicitDynamic && findDir(node, 'is');3949 if (isDir && isDir.exp) {3950 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3951 isDir.exp3952 ]);3953 }3954 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)3955 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);3956 if (builtIn) {3957 // built-ins are simply fallthroughs / have special handling during ssr3958 // so we don't need to import their runtime equivalents3959 if (!ssr)3960 context.helper(builtIn);3961 return builtIn;3962 }3963 // 5. user component (resolve)3964 context.helper(RESOLVE_COMPONENT);3965 context.components.add(tag);3966 return toValidAssetId(tag, `component`);3967}3968function buildProps(node, context, props = node.props, ssr = false) {3969 const { tag, loc: elementLoc } = node;3970 const isComponent = node.tagType === 1 /* COMPONENT */;3971 let properties = [];3972 const mergeArgs = [];3973 const runtimeDirectives = [];3974 // patchFlag analysis3975 let patchFlag = 0;3976 let hasRef = false;3977 let hasClassBinding = false;3978 let hasStyleBinding = false;3979 let hasHydrationEventBinding = false;3980 let hasDynamicKeys = false;3981 let hasVnodeHook = false;3982 const dynamicPropNames = [];3983 const analyzePatchFlag = ({ key, value }) => {3984 if (isStaticExp(key)) {3985 const name = key.content;3986 const isEventHandler = isOn(name);3987 if (!isComponent &&3988 isEventHandler &&3989 // omit the flag for click handlers because hydration gives click3990 // dedicated fast path.3991 name.toLowerCase() !== 'onclick' &&3992 // omit v-model handlers3993 name !== 'onUpdate:modelValue' &&3994 // omit onVnodeXXX hooks3995 !isReservedProp(name)) {3996 hasHydrationEventBinding = true;3997 }3998 if (isEventHandler && isReservedProp(name)) {3999 hasVnodeHook = true;4000 }4001 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||4002 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||4003 value.type === 8 /* COMPOUND_EXPRESSION */) &&4004 getConstantType(value, context) > 0)) {4005 // skip if the prop is a cached handler or has constant value4006 return;4007 }4008 if (name === 'ref') {4009 hasRef = true;4010 }4011 else if (name === 'class') {4012 hasClassBinding = true;4013 }4014 else if (name === 'style') {4015 hasStyleBinding = true;4016 }4017 else if (name !== 'key' && !dynamicPropNames.includes(name)) {4018 dynamicPropNames.push(name);4019 }4020 // treat the dynamic class and style binding of the component as dynamic props4021 if (isComponent &&4022 (name === 'class' || name === 'style') &&4023 !dynamicPropNames.includes(name)) {4024 dynamicPropNames.push(name);4025 }4026 }4027 else {4028 hasDynamicKeys = true;4029 }4030 };4031 for (let i = 0; i < props.length; i++) {4032 // static attribute4033 const prop = props[i];4034 if (prop.type === 6 /* ATTRIBUTE */) {4035 const { loc, name, value } = prop;4036 let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);4037 if (name === 'ref') {4038 hasRef = true;4039 }4040 // skip is on <component>, or is="vue:xxx"4041 if (name === 'is' &&4042 (isComponentTag(tag) ||4043 (value && value.content.startsWith('vue:')) ||4044 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {4045 continue;4046 }4047 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));4048 }4049 else {4050 // directives4051 const { name, arg, exp, loc } = prop;4052 const isVBind = name === 'bind';4053 const isVOn = name === 'on';4054 // skip v-slot - it is handled by its dedicated transform.4055 if (name === 'slot') {4056 if (!isComponent) {4057 context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc));4058 }4059 continue;4060 }4061 // skip v-once/v-memo - they are handled by dedicated transforms.4062 if (name === 'once' || name === 'memo') {4063 continue;4064 }4065 // skip v-is and :is on <component>4066 if (name === 'is' ||4067 (isVBind &&4068 isBindKey(arg, 'is') &&4069 (isComponentTag(tag) ||4070 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {4071 continue;4072 }4073 // skip v-on in SSR compilation4074 if (isVOn && ssr) {4075 continue;4076 }4077 // special case for v-bind and v-on with no argument4078 if (!arg && (isVBind || isVOn)) {4079 hasDynamicKeys = true;4080 if (exp) {4081 if (properties.length) {4082 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4083 properties = [];4084 }4085 if (isVBind) {4086 {4087 // 2.x v-bind object order compat4088 {4089 const hasOverridableKeys = mergeArgs.some(arg => {4090 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {4091 return arg.properties.some(({ key }) => {4092 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||4093 !key.isStatic) {4094 return true;4095 }4096 return (key.content !== 'class' &&4097 key.content !== 'style' &&4098 !isOn(key.content));4099 });4100 }4101 else {4102 // dynamic expression4103 return true;4104 }4105 });4106 if (hasOverridableKeys) {4107 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);4108 }4109 }4110 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {4111 mergeArgs.unshift(exp);4112 continue;4113 }4114 }4115 mergeArgs.push(exp);4116 }4117 else {4118 // v-on="obj" -> toHandlers(obj)4119 mergeArgs.push({4120 type: 14 /* JS_CALL_EXPRESSION */,4121 loc,4122 callee: context.helper(TO_HANDLERS),4123 arguments: [exp]4124 });4125 }4126 }4127 else {4128 context.onError(createCompilerError(isVBind4129 ? 34 /* X_V_BIND_NO_EXPRESSION */4130 : 35 /* X_V_ON_NO_EXPRESSION */, loc));4131 }4132 continue;4133 }4134 const directiveTransform = context.directiveTransforms[name];4135 if (directiveTransform) {4136 // has built-in directive transform.4137 const { props, needRuntime } = directiveTransform(prop, node, context);4138 !ssr && props.forEach(analyzePatchFlag);4139 properties.push(...props);4140 if (needRuntime) {4141 runtimeDirectives.push(prop);4142 if (isSymbol(needRuntime)) {4143 directiveImportMap.set(prop, needRuntime);4144 }4145 }4146 }4147 else {4148 // no built-in transform, this is a user custom directive.4149 runtimeDirectives.push(prop);4150 }4151 }4152 if (prop.type === 6 /* ATTRIBUTE */ &&4153 prop.name === 'ref' &&4154 context.scopes.vFor > 0 &&4155 checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {4156 properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));4157 }4158 }4159 let propsExpression = undefined;4160 // has v-bind="object" or v-on="object", wrap with mergeProps4161 if (mergeArgs.length) {4162 if (properties.length) {4163 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4164 }4165 if (mergeArgs.length > 1) {4166 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);4167 }4168 else {4169 // single v-bind with nothing else - no need for a mergeProps call4170 propsExpression = mergeArgs[0];4171 }4172 }4173 else if (properties.length) {4174 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);4175 }4176 // patchFlag analysis4177 if (hasDynamicKeys) {4178 patchFlag |= 16 /* FULL_PROPS */;4179 }4180 else {4181 if (hasClassBinding && !isComponent) {4182 patchFlag |= 2 /* CLASS */;4183 }4184 if (hasStyleBinding && !isComponent) {4185 patchFlag |= 4 /* STYLE */;4186 }4187 if (dynamicPropNames.length) {4188 patchFlag |= 8 /* PROPS */;4189 }4190 if (hasHydrationEventBinding) {4191 patchFlag |= 32 /* HYDRATE_EVENTS */;4192 }4193 }4194 if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&4195 (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {4196 patchFlag |= 512 /* NEED_PATCH */;4197 }4198 // pre-normalize props, SSR is skipped for now4199 if (!context.inSSR && propsExpression) {4200 switch (propsExpression.type) {4201 case 15 /* JS_OBJECT_EXPRESSION */:4202 // means that there is no v-bind,4203 // but still need to deal with dynamic key binding4204 let classKeyIndex = -1;4205 let styleKeyIndex = -1;4206 let hasDynamicKey = false;4207 for (let i = 0; i < propsExpression.properties.length; i++) {4208 const key = propsExpression.properties[i].key;4209 if (isStaticExp(key)) {4210 if (key.content === 'class') {4211 classKeyIndex = i;4212 }4213 else if (key.content === 'style') {4214 styleKeyIndex = i;4215 }4216 }4217 else if (!key.isHandlerKey) {4218 hasDynamicKey = true;4219 }4220 }4221 const classProp = propsExpression.properties[classKeyIndex];4222 const styleProp = propsExpression.properties[styleKeyIndex];4223 // no dynamic key4224 if (!hasDynamicKey) {4225 if (classProp && !isStaticExp(classProp.value)) {4226 classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]);4227 }4228 if (styleProp &&4229 !isStaticExp(styleProp.value) &&4230 // the static style is compiled into an object,4231 // so use `hasStyleBinding` to ensure that it is a dynamic style binding4232 (hasStyleBinding ||4233 // v-bind:style and style both exist,4234 // v-bind:style with static literal object4235 styleProp.value.type === 17 /* JS_ARRAY_EXPRESSION */)) {4236 styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]);4237 }4238 }4239 else {4240 // dynamic key binding, wrap with `normalizeProps`4241 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]);4242 }4243 break;4244 case 14 /* JS_CALL_EXPRESSION */:4245 // mergeProps call, do nothing4246 break;4247 default:4248 // single v-bind4249 propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [4250 createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [4251 propsExpression4252 ])4253 ]);4254 break;4255 }4256 }4257 return {4258 props: propsExpression,4259 directives: runtimeDirectives,4260 patchFlag,4261 dynamicPropNames4262 };4263}4264// Dedupe props in an object literal.4265// Literal duplicated attributes would have been warned during the parse phase,4266// however, it's possible to encounter duplicated `onXXX` handlers with different4267// modifiers. We also need to merge static and dynamic class / style attributes.4268// - onXXX handlers / style: merge into array4269// - class: merge into single expression with concatenation4270function dedupeProperties(properties) {4271 const knownProps = new Map();4272 const deduped = [];4273 for (let i = 0; i < properties.length; i++) {4274 const prop = properties[i];4275 // dynamic keys are always allowed4276 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) {4277 deduped.push(prop);4278 continue;4279 }4280 const name = prop.key.content;4281 const existing = knownProps.get(name);4282 if (existing) {4283 if (name === 'style' || name === 'class' || isOn(name)) {4284 mergeAsArray(existing, prop);4285 }4286 // unexpected duplicate, should have emitted error during parse4287 }4288 else {4289 knownProps.set(name, prop);4290 deduped.push(prop);4291 }4292 }4293 return deduped;4294}4295function mergeAsArray(existing, incoming) {4296 if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) {4297 existing.value.elements.push(incoming.value);4298 }4299 else {4300 existing.value = createArrayExpression([existing.value, incoming.value], existing.loc);4301 }4302}4303function buildDirectiveArgs(dir, context) {4304 const dirArgs = [];4305 const runtime = directiveImportMap.get(dir);4306 if (runtime) {4307 // built-in directive with runtime4308 dirArgs.push(context.helperString(runtime));4309 }4310 else {4311 {4312 // inject statement for resolving directive4313 context.helper(RESOLVE_DIRECTIVE);4314 context.directives.add(dir.name);4315 dirArgs.push(toValidAssetId(dir.name, `directive`));4316 }4317 }4318 const { loc } = dir;4319 if (dir.exp)4320 dirArgs.push(dir.exp);4321 if (dir.arg) {4322 if (!dir.exp) {4323 dirArgs.push(`void 0`);4324 }4325 dirArgs.push(dir.arg);4326 }4327 if (Object.keys(dir.modifiers).length) {4328 if (!dir.arg) {4329 if (!dir.exp) {4330 dirArgs.push(`void 0`);4331 }4332 dirArgs.push(`void 0`);4333 }4334 const trueExpression = createSimpleExpression(`true`, false, loc);4335 dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc));4336 }4337 return createArrayExpression(dirArgs, dir.loc);4338}4339function stringifyDynamicPropNames(props) {4340 let propsNamesString = `[`;4341 for (let i = 0, l = props.length; i < l; i++) {4342 propsNamesString += JSON.stringify(props[i]);4343 if (i < l - 1)4344 propsNamesString += ', ';4345 }4346 return propsNamesString + `]`;4347}4348function isComponentTag(tag) {4349 return tag[0].toLowerCase() + tag.slice(1) === 'component';4350}4351const transformSlotOutlet = (node, context) => {4352 if (isSlotOutlet(node)) {4353 const { children, loc } = node;4354 const { slotName, slotProps } = processSlotOutlet(node, context);4355 const slotArgs = [4356 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,4357 slotName,4358 '{}',4359 'undefined',4360 'true'4361 ];4362 let expectedLen = 2;4363 if (slotProps) {4364 slotArgs[2] = slotProps;4365 expectedLen = 3;4366 }4367 if (children.length) {4368 slotArgs[3] = createFunctionExpression([], children, false, false, loc);4369 expectedLen = 4;4370 }4371 if (context.scopeId && !context.slotted) {4372 expectedLen = 5;4373 }4374 slotArgs.splice(expectedLen); // remove unused arguments4375 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);4376 }4377};4378function processSlotOutlet(node, context) {4379 let slotName = `"default"`;4380 let slotProps = undefined;4381 const nonNameProps = [];4382 for (let i = 0; i < node.props.length; i++) {4383 const p = node.props[i];4384 if (p.type === 6 /* ATTRIBUTE */) {4385 if (p.value) {4386 if (p.name === 'name') {4387 slotName = JSON.stringify(p.value.content);4388 }4389 else {4390 p.name = camelize(p.name);4391 nonNameProps.push(p);4392 }4393 }4394 }4395 else {4396 if (p.name === 'bind' && isBindKey(p.arg, 'name')) {4397 if (p.exp)4398 slotName = p.exp;4399 }4400 else {4401 if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) {4402 p.arg.content = camelize(p.arg.content);4403 }4404 nonNameProps.push(p);4405 }4406 }4407 }4408 if (nonNameProps.length > 0) {4409 const { props, directives } = buildProps(node, context, nonNameProps);4410 slotProps = props;4411 if (directives.length) {4412 context.onError(createCompilerError(36 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));4413 }4414 }4415 return {4416 slotName,4417 slotProps4418 };4419}4420const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;4421const transformOn = (dir, node, context, augmentor) => {4422 const { loc, modifiers, arg } = dir;4423 if (!dir.exp && !modifiers.length) {4424 context.onError(createCompilerError(35 /* X_V_ON_NO_EXPRESSION */, loc));4425 }4426 let eventName;4427 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4428 if (arg.isStatic) {4429 const rawName = arg.content;4430 // for all event listeners, auto convert it to camelCase. See issue #22494431 eventName = createSimpleExpression(toHandlerKey(camelize(rawName)), true, arg.loc);4432 }4433 else {4434 // #23884435 eventName = createCompoundExpression([4436 `${context.helperString(TO_HANDLER_KEY)}(`,4437 arg,4438 `)`4439 ]);4440 }4441 }4442 else {4443 // already a compound expression.4444 eventName = arg;4445 eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`);4446 eventName.children.push(`)`);4447 }4448 // handler processing4449 let exp = dir.exp;4450 if (exp && !exp.content.trim()) {4451 exp = undefined;4452 }4453 let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;4454 if (exp) {4455 const isMemberExp = isMemberExpression(exp.content);4456 const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));4457 const hasMultipleStatements = exp.content.includes(`;`);4458 {4459 validateBrowserExpression(exp, context, false, hasMultipleStatements);4460 }4461 if (isInlineStatement || (shouldCache && isMemberExp)) {4462 // wrap inline statement in a function expression4463 exp = createCompoundExpression([4464 `${isInlineStatement4465 ? `$event`4466 : `${``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,4467 exp,4468 hasMultipleStatements ? `}` : `)`4469 ]);4470 }4471 }4472 let ret = {4473 props: [4474 createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))4475 ]4476 };4477 // apply extended compiler augmentor4478 if (augmentor) {4479 ret = augmentor(ret);4480 }4481 if (shouldCache) {4482 // cache handlers so that it's always the same handler being passed down.4483 // this avoids unnecessary re-renders when users use inline handlers on4484 // components.4485 ret.props[0].value = context.cache(ret.props[0].value);4486 }4487 // mark the key as handler for props normalization check4488 ret.props.forEach(p => (p.key.isHandlerKey = true));4489 return ret;4490};4491// v-bind without arg is handled directly in ./transformElements.ts due to it affecting4492// codegen for the entire props object. This transform here is only for v-bind4493// *with* args.4494const transformBind = (dir, _node, context) => {4495 const { exp, modifiers, loc } = dir;4496 const arg = dir.arg;4497 if (arg.type !== 4 /* SIMPLE_EXPRESSION */) {4498 arg.children.unshift(`(`);4499 arg.children.push(`) || ""`);4500 }4501 else if (!arg.isStatic) {4502 arg.content = `${arg.content} || ""`;4503 }4504 // .sync is replaced by v-model:arg4505 if (modifiers.includes('camel')) {4506 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4507 if (arg.isStatic) {4508 arg.content = camelize(arg.content);4509 }4510 else {4511 arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;4512 }4513 }4514 else {4515 arg.children.unshift(`${context.helperString(CAMELIZE)}(`);4516 arg.children.push(`)`);4517 }4518 }4519 if (!context.inSSR) {4520 if (modifiers.includes('prop')) {4521 injectPrefix(arg, '.');4522 }4523 if (modifiers.includes('attr')) {4524 injectPrefix(arg, '^');4525 }4526 }4527 if (!exp ||4528 (exp.type === 4 /* SIMPLE_EXPRESSION */ && !exp.content.trim())) {4529 context.onError(createCompilerError(34 /* X_V_BIND_NO_EXPRESSION */, loc));4530 return {4531 props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]4532 };4533 }4534 return {4535 props: [createObjectProperty(arg, exp)]4536 };4537};4538const injectPrefix = (arg, prefix) => {4539 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {4540 if (arg.isStatic) {4541 arg.content = prefix + arg.content;4542 }4543 else {4544 arg.content = `\`${prefix}\${${arg.content}}\``;4545 }4546 }4547 else {4548 arg.children.unshift(`'${prefix}' + (`);4549 arg.children.push(`)`);4550 }4551};4552// Merge adjacent text nodes and expressions into a single expression4553// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.4554const transformText = (node, context) => {4555 if (node.type === 0 /* ROOT */ ||4556 node.type === 1 /* ELEMENT */ ||4557 node.type === 11 /* FOR */ ||4558 node.type === 10 /* IF_BRANCH */) {4559 // perform the transform on node exit so that all expressions have already4560 // been processed.4561 return () => {4562 const children = node.children;4563 let currentContainer = undefined;4564 let hasText = false;4565 for (let i = 0; i < children.length; i++) {4566 const child = children[i];4567 if (isText(child)) {4568 hasText = true;4569 for (let j = i + 1; j < children.length; j++) {4570 const next = children[j];4571 if (isText(next)) {4572 if (!currentContainer) {4573 currentContainer = children[i] = {4574 type: 8 /* COMPOUND_EXPRESSION */,4575 loc: child.loc,4576 children: [child]4577 };4578 }4579 // merge adjacent text node into current4580 currentContainer.children.push(` + `, next);4581 children.splice(j, 1);4582 j--;4583 }4584 else {4585 currentContainer = undefined;4586 break;4587 }4588 }4589 }4590 }4591 if (!hasText ||4592 // if this is a plain element with a single text child, leave it4593 // as-is since the runtime has dedicated fast path for this by directly4594 // setting textContent of the element.4595 // for component root it's always normalized anyway.4596 (children.length === 1 &&4597 (node.type === 0 /* ROOT */ ||4598 (node.type === 1 /* ELEMENT */ &&4599 node.tagType === 0 /* ELEMENT */ &&4600 // #37564601 // custom directives can potentially add DOM elements arbitrarily,4602 // we need to avoid setting textContent of the element at runtime4603 // to avoid accidentally overwriting the DOM elements added4604 // by the user through custom directives.4605 !node.props.find(p => p.type === 7 /* DIRECTIVE */ &&4606 !context.directiveTransforms[p.name]) &&4607 // in compat mode, <template> tags with no special directives4608 // will be rendered as a fragment so its children must be4609 // converted into vnodes.4610 !(node.tag === 'template'))))) {4611 return;4612 }4613 // pre-convert text nodes into createTextVNode(text) calls to avoid4614 // runtime normalization.4615 for (let i = 0; i < children.length; i++) {4616 const child = children[i];4617 if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) {4618 const callArgs = [];4619 // createTextVNode defaults to single whitespace, so if it is a4620 // single space the code could be an empty call to save bytes.4621 if (child.type !== 2 /* TEXT */ || child.content !== ' ') {4622 callArgs.push(child);4623 }4624 // mark dynamic text with flag so it gets patched inside a block4625 if (!context.ssr &&4626 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {4627 callArgs.push(1 /* TEXT */ +4628 (` /* ${PatchFlagNames[1 /* TEXT */]} */` ));4629 }4630 children[i] = {4631 type: 12 /* TEXT_CALL */,4632 content: child,4633 loc: child.loc,4634 codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)4635 };4636 }4637 }4638 };4639 }4640};4641const seen = new WeakSet();4642const transformOnce = (node, context) => {4643 if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) {4644 if (seen.has(node) || context.inVOnce) {4645 return;4646 }4647 seen.add(node);4648 context.inVOnce = true;4649 context.helper(SET_BLOCK_TRACKING);4650 return () => {4651 context.inVOnce = false;4652 const cur = context.currentNode;4653 if (cur.codegenNode) {4654 cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */);4655 }4656 };4657 }4658};4659const transformModel = (dir, node, context) => {4660 const { exp, arg } = dir;4661 if (!exp) {4662 context.onError(createCompilerError(41 /* X_V_MODEL_NO_EXPRESSION */, dir.loc));4663 return createTransformProps();4664 }4665 const rawExp = exp.loc.source;4666 const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : rawExp;4667 // im SFC <script setup> inline mode, the exp may have been transformed into4668 // _unref(exp)4669 context.bindingMetadata[rawExp];4670 const maybeRef = !true /* SETUP_CONST */;4671 if (!expString.trim() ||4672 (!isMemberExpression(expString) && !maybeRef)) {4673 context.onError(createCompilerError(42 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));4674 return createTransformProps();4675 }4676 const propName = arg ? arg : createSimpleExpression('modelValue', true);4677 const eventName = arg4678 ? isStaticExp(arg)4679 ? `onUpdate:${arg.content}`4680 : createCompoundExpression(['"onUpdate:" + ', arg])4681 : `onUpdate:modelValue`;4682 let assignmentExp;4683 const eventArg = context.isTS ? `($event: any)` : `$event`;4684 {4685 assignmentExp = createCompoundExpression([4686 `${eventArg} => ((`,4687 exp,4688 `) = $event)`4689 ]);4690 }4691 const props = [4692 // modelValue: foo4693 createObjectProperty(propName, dir.exp),4694 // "onUpdate:modelValue": $event => (foo = $event)4695 createObjectProperty(eventName, assignmentExp)4696 ];4697 // modelModifiers: { foo: true, "bar-baz": true }4698 if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) {4699 const modifiers = dir.modifiers4700 .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)4701 .join(`, `);4702 const modifiersKey = arg4703 ? isStaticExp(arg)4704 ? `${arg.content}Modifiers`4705 : createCompoundExpression([arg, ' + "Modifiers"'])4706 : `modelModifiers`;4707 props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* CAN_HOIST */)));4708 }4709 return createTransformProps(props);4710};4711function createTransformProps(props = []) {4712 return { props };4713}4714const validDivisionCharRE = /[\w).+\-_$\]]/;4715const transformFilter = (node, context) => {4716 if (!isCompatEnabled("COMPILER_FILTER" /* COMPILER_FILTERS */, context)) {4717 return;4718 }4719 if (node.type === 5 /* INTERPOLATION */) {4720 // filter rewrite is applied before expression transform so only4721 // simple expressions are possible at this stage4722 rewriteFilter(node.content, context);4723 }4724 if (node.type === 1 /* ELEMENT */) {4725 node.props.forEach((prop) => {4726 if (prop.type === 7 /* DIRECTIVE */ &&4727 prop.name !== 'for' &&4728 prop.exp) {4729 rewriteFilter(prop.exp, context);4730 }4731 });4732 }4733};4734function rewriteFilter(node, context) {4735 if (node.type === 4 /* SIMPLE_EXPRESSION */) {4736 parseFilter(node, context);4737 }4738 else {4739 for (let i = 0; i < node.children.length; i++) {4740 const child = node.children[i];4741 if (typeof child !== 'object')4742 continue;4743 if (child.type === 4 /* SIMPLE_EXPRESSION */) {4744 parseFilter(child, context);4745 }4746 else if (child.type === 8 /* COMPOUND_EXPRESSION */) {4747 rewriteFilter(node, context);4748 }4749 else if (child.type === 5 /* INTERPOLATION */) {4750 rewriteFilter(child.content, context);4751 }4752 }4753 }4754}4755function parseFilter(node, context) {4756 const exp = node.content;4757 let inSingle = false;4758 let inDouble = false;4759 let inTemplateString = false;4760 let inRegex = false;4761 let curly = 0;4762 let square = 0;4763 let paren = 0;4764 let lastFilterIndex = 0;4765 let c, prev, i, expression, filters = [];4766 for (i = 0; i < exp.length; i++) {4767 prev = c;4768 c = exp.charCodeAt(i);4769 if (inSingle) {4770 if (c === 0x27 && prev !== 0x5c)4771 inSingle = false;4772 }4773 else if (inDouble) {4774 if (c === 0x22 && prev !== 0x5c)4775 inDouble = false;4776 }4777 else if (inTemplateString) {4778 if (c === 0x60 && prev !== 0x5c)4779 inTemplateString = false;4780 }4781 else if (inRegex) {4782 if (c === 0x2f && prev !== 0x5c)4783 inRegex = false;4784 }4785 else if (c === 0x7c && // pipe4786 exp.charCodeAt(i + 1) !== 0x7c &&4787 exp.charCodeAt(i - 1) !== 0x7c &&4788 !curly &&4789 !square &&4790 !paren) {4791 if (expression === undefined) {4792 // first filter, end of expression4793 lastFilterIndex = i + 1;4794 expression = exp.slice(0, i).trim();4795 }4796 else {4797 pushFilter();4798 }4799 }4800 else {4801 switch (c) {4802 case 0x22:4803 inDouble = true;4804 break; // "4805 case 0x27:4806 inSingle = true;4807 break; // '4808 case 0x60:4809 inTemplateString = true;4810 break; // `4811 case 0x28:4812 paren++;4813 break; // (4814 case 0x29:4815 paren--;4816 break; // )4817 case 0x5b:4818 square++;4819 break; // [4820 case 0x5d:4821 square--;4822 break; // ]4823 case 0x7b:4824 curly++;4825 break; // {4826 case 0x7d:4827 curly--;4828 break; // }4829 }4830 if (c === 0x2f) {4831 // /4832 let j = i - 1;4833 let p;4834 // find first non-whitespace prev char4835 for (; j >= 0; j--) {4836 p = exp.charAt(j);4837 if (p !== ' ')4838 break;4839 }4840 if (!p || !validDivisionCharRE.test(p)) {4841 inRegex = true;4842 }4843 }4844 }4845 }4846 if (expression === undefined) {4847 expression = exp.slice(0, i).trim();4848 }4849 else if (lastFilterIndex !== 0) {4850 pushFilter();4851 }4852 function pushFilter() {4853 filters.push(exp.slice(lastFilterIndex, i).trim());4854 lastFilterIndex = i + 1;4855 }4856 if (filters.length) {4857 warnDeprecation("COMPILER_FILTER" /* COMPILER_FILTERS */, context, node.loc);4858 for (i = 0; i < filters.length; i++) {4859 expression = wrapFilter(expression, filters[i], context);4860 }4861 node.content = expression;4862 }4863}4864function wrapFilter(exp, filter, context) {4865 context.helper(RESOLVE_FILTER);4866 const i = filter.indexOf('(');4867 if (i < 0) {4868 context.filters.add(filter);4869 return `${toValidAssetId(filter, 'filter')}(${exp})`;4870 }4871 else {4872 const name = filter.slice(0, i);4873 const args = filter.slice(i + 1);4874 context.filters.add(name);4875 return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`;4876 }4877}4878const seen$1 = new WeakSet();4879const transformMemo = (node, context) => {4880 if (node.type === 1 /* ELEMENT */) {4881 const dir = findDir(node, 'memo');4882 if (!dir || seen$1.has(node)) {4883 return;4884 }4885 seen$1.add(node);4886 return () => {4887 const codegenNode = node.codegenNode ||4888 context.currentNode.codegenNode;4889 if (codegenNode && codegenNode.type === 13 /* VNODE_CALL */) {4890 // non-component sub tree should be turned into a block4891 if (node.tagType !== 1 /* COMPONENT */) {4892 makeBlock(codegenNode, context);4893 }4894 node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [4895 dir.exp,4896 createFunctionExpression(undefined, codegenNode),4897 `_cache`,4898 String(context.cached++)4899 ]);4900 }4901 };4902 }4903};4904function getBaseTransformPreset(prefixIdentifiers) {4905 return [4906 [4907 transformOnce,4908 transformIf,4909 transformMemo,4910 transformFor,4911 ...([transformFilter] ),4912 ...([transformExpression]4913 ),4914 transformSlotOutlet,4915 transformElement,4916 trackSlotScopes,4917 transformText4918 ],4919 {4920 on: transformOn,4921 bind: transformBind,4922 model: transformModel4923 }4924 ];4925}4926// we name it `baseCompile` so that higher order compilers like4927// @vue/compiler-dom can export `compile` while re-exporting everything else.4928function baseCompile(template, options = {}) {4929 const onError = options.onError || defaultOnError;4930 const isModuleMode = options.mode === 'module';4931 /* istanbul ignore if */4932 {4933 if (options.prefixIdentifiers === true) {4934 onError(createCompilerError(46 /* X_PREFIX_ID_NOT_SUPPORTED */));4935 }4936 else if (isModuleMode) {4937 onError(createCompilerError(47 /* X_MODULE_MODE_NOT_SUPPORTED */));4938 }4939 }4940 const prefixIdentifiers = !true ;4941 if (options.cacheHandlers) {4942 onError(createCompilerError(48 /* X_CACHE_HANDLER_NOT_SUPPORTED */));4943 }4944 if (options.scopeId && !isModuleMode) {4945 onError(createCompilerError(49 /* X_SCOPE_ID_NOT_SUPPORTED */));4946 }4947 const ast = isString(template) ? baseParse(template, options) : template;4948 const [nodeTransforms, directiveTransforms] = getBaseTransformPreset();4949 transform(ast, extend({}, options, {4950 prefixIdentifiers,4951 nodeTransforms: [4952 ...nodeTransforms,4953 ...(options.nodeTransforms || []) // user transforms4954 ],4955 directiveTransforms: extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms4956 )4957 }));4958 return generate(ast, extend({}, options, {4959 prefixIdentifiers4960 }));4961}4962const noopDirectiveTransform = () => ({ props: [] });4963const V_MODEL_RADIO = Symbol(`vModelRadio` );4964const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` );4965const V_MODEL_TEXT = Symbol(`vModelText` );4966const V_MODEL_SELECT = Symbol(`vModelSelect` );4967const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` );4968const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` );4969const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` );4970const V_SHOW = Symbol(`vShow` );4971const TRANSITION = Symbol(`Transition` );4972const TRANSITION_GROUP = Symbol(`TransitionGroup` );4973registerRuntimeHelpers({4974 [V_MODEL_RADIO]: `vModelRadio`,4975 [V_MODEL_CHECKBOX]: `vModelCheckbox`,4976 [V_MODEL_TEXT]: `vModelText`,4977 [V_MODEL_SELECT]: `vModelSelect`,4978 [V_MODEL_DYNAMIC]: `vModelDynamic`,4979 [V_ON_WITH_MODIFIERS]: `withModifiers`,4980 [V_ON_WITH_KEYS]: `withKeys`,4981 [V_SHOW]: `vShow`,4982 [TRANSITION]: `Transition`,4983 [TRANSITION_GROUP]: `TransitionGroup`4984});4985/* eslint-disable no-restricted-globals */4986let decoder;4987function decodeHtmlBrowser(raw, asAttr = false) {4988 if (!decoder) {4989 decoder = document.createElement('div');4990 }4991 if (asAttr) {4992 decoder.innerHTML = `<div foo="${raw.replace(/"/g, '&quot;')}">`;4993 return decoder.children[0].getAttribute('foo');4994 }4995 else {4996 decoder.innerHTML = raw;4997 return decoder.textContent;4998 }4999}5000const isRawTextContainer = /*#__PURE__*/ makeMap('style,iframe,script,noscript', true);5001const parserOptions = {5002 isVoidTag,5003 isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag),5004 isPreTag: tag => tag === 'pre',5005 decodeEntities: decodeHtmlBrowser ,5006 isBuiltInComponent: (tag) => {5007 if (isBuiltInType(tag, `Transition`)) {5008 return TRANSITION;5009 }5010 else if (isBuiltInType(tag, `TransitionGroup`)) {5011 return TRANSITION_GROUP;5012 }5013 },5014 // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher5015 getNamespace(tag, parent) {5016 let ns = parent ? parent.ns : 0 /* HTML */;5017 if (parent && ns === 2 /* MATH_ML */) {5018 if (parent.tag === 'annotation-xml') {5019 if (tag === 'svg') {5020 return 1 /* SVG */;5021 }5022 if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ &&5023 a.name === 'encoding' &&5024 a.value != null &&5025 (a.value.content === 'text/html' ||5026 a.value.content === 'application/xhtml+xml'))) {5027 ns = 0 /* HTML */;5028 }5029 }5030 else if (/^m(?:[ions]|text)$/.test(parent.tag) &&5031 tag !== 'mglyph' &&5032 tag !== 'malignmark') {5033 ns = 0 /* HTML */;5034 }5035 }5036 else if (parent && ns === 1 /* SVG */) {5037 if (parent.tag === 'foreignObject' ||5038 parent.tag === 'desc' ||5039 parent.tag === 'title') {5040 ns = 0 /* HTML */;5041 }5042 }5043 if (ns === 0 /* HTML */) {5044 if (tag === 'svg') {5045 return 1 /* SVG */;5046 }5047 if (tag === 'math') {5048 return 2 /* MATH_ML */;5049 }5050 }5051 return ns;5052 },5053 // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments5054 getTextMode({ tag, ns }) {5055 if (ns === 0 /* HTML */) {5056 if (tag === 'textarea' || tag === 'title') {5057 return 1 /* RCDATA */;5058 }5059 if (isRawTextContainer(tag)) {5060 return 2 /* RAWTEXT */;5061 }5062 }5063 return 0 /* DATA */;5064 }5065};5066// Parse inline CSS strings for static style attributes into an object.5067// This is a NodeTransform since it works on the static `style` attribute and5068// converts it into a dynamic equivalent:5069// style="color: red" -> :style='{ "color": "red" }'5070// It is then processed by `transformElement` and included in the generated5071// props.5072const transformStyle = node => {5073 if (node.type === 1 /* ELEMENT */) {5074 node.props.forEach((p, i) => {5075 if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) {5076 // replace p with an expression node5077 node.props[i] = {5078 type: 7 /* DIRECTIVE */,5079 name: `bind`,5080 arg: createSimpleExpression(`style`, true, p.loc),5081 exp: parseInlineCSS(p.value.content, p.loc),5082 modifiers: [],5083 loc: p.loc5084 };5085 }5086 });5087 }5088};5089const parseInlineCSS = (cssText, loc) => {5090 const normalized = parseStringStyle(cssText);5091 return createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* CAN_STRINGIFY */);5092};5093function createDOMCompilerError(code, loc) {5094 return createCompilerError(code, loc, DOMErrorMessages );5095}5096const DOMErrorMessages = {5097 [50 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,5098 [51 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,5099 [52 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,5100 [53 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,5101 [54 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,5102 [55 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,5103 [56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,5104 [57 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,5105 [58 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,5106 [59 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`,5107 [60 /* X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`5108};5109const transformVHtml = (dir, node, context) => {5110 const { exp, loc } = dir;5111 if (!exp) {5112 context.onError(createDOMCompilerError(50 /* X_V_HTML_NO_EXPRESSION */, loc));5113 }5114 if (node.children.length) {5115 context.onError(createDOMCompilerError(51 /* X_V_HTML_WITH_CHILDREN */, loc));5116 node.children.length = 0;5117 }5118 return {5119 props: [5120 createObjectProperty(createSimpleExpression(`innerHTML`, true, loc), exp || createSimpleExpression('', true))5121 ]5122 };5123};5124const transformVText = (dir, node, context) => {5125 const { exp, loc } = dir;5126 if (!exp) {5127 context.onError(createDOMCompilerError(52 /* X_V_TEXT_NO_EXPRESSION */, loc));5128 }5129 if (node.children.length) {5130 context.onError(createDOMCompilerError(53 /* X_V_TEXT_WITH_CHILDREN */, loc));5131 node.children.length = 0;5132 }5133 return {5134 props: [5135 createObjectProperty(createSimpleExpression(`textContent`, true), exp5136 ? createCallExpression(context.helperString(TO_DISPLAY_STRING), [exp], loc)5137 : createSimpleExpression('', true))5138 ]5139 };5140};5141const transformModel$1 = (dir, node, context) => {5142 const baseResult = transformModel(dir, node, context);5143 // base transform has errors OR component v-model (only need props)5144 if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) {5145 return baseResult;5146 }5147 if (dir.arg) {5148 context.onError(createDOMCompilerError(55 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));5149 }5150 function checkDuplicatedValue() {5151 const value = findProp(node, 'value');5152 if (value) {5153 context.onError(createDOMCompilerError(57 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc));5154 }5155 }5156 const { tag } = node;5157 const isCustomElement = context.isCustomElement(tag);5158 if (tag === 'input' ||5159 tag === 'textarea' ||5160 tag === 'select' ||5161 isCustomElement) {5162 let directiveToUse = V_MODEL_TEXT;5163 let isInvalidType = false;5164 if (tag === 'input' || isCustomElement) {5165 const type = findProp(node, `type`);5166 if (type) {5167 if (type.type === 7 /* DIRECTIVE */) {5168 // :type="foo"5169 directiveToUse = V_MODEL_DYNAMIC;5170 }5171 else if (type.value) {5172 switch (type.value.content) {5173 case 'radio':5174 directiveToUse = V_MODEL_RADIO;5175 break;5176 case 'checkbox':5177 directiveToUse = V_MODEL_CHECKBOX;5178 break;5179 case 'file':5180 isInvalidType = true;5181 context.onError(createDOMCompilerError(56 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));5182 break;5183 default:5184 // text type5185 checkDuplicatedValue();5186 break;5187 }5188 }5189 }5190 else if (hasDynamicKeyVBind(node)) {5191 // element has bindings with dynamic keys, which can possibly contain5192 // "type".5193 directiveToUse = V_MODEL_DYNAMIC;5194 }5195 else {5196 // text type5197 checkDuplicatedValue();5198 }5199 }5200 else if (tag === 'select') {5201 directiveToUse = V_MODEL_SELECT;5202 }5203 else {5204 // textarea5205 checkDuplicatedValue();5206 }5207 // inject runtime directive5208 // by returning the helper symbol via needRuntime5209 // the import will replaced a resolveDirective call.5210 if (!isInvalidType) {5211 baseResult.needRuntime = context.helper(directiveToUse);5212 }5213 }5214 else {5215 context.onError(createDOMCompilerError(54 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));5216 }5217 // native vmodel doesn't need the `modelValue` props since they are also5218 // passed to the runtime as `binding.value`. removing it reduces code size.5219 baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* SIMPLE_EXPRESSION */ &&5220 p.key.content === 'modelValue'));5221 return baseResult;5222};5223const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`);5224const isNonKeyModifier = /*#__PURE__*/ makeMap(5225// event propagation management5226`stop,prevent,self,` +5227 // system modifiers + exact5228 `ctrl,shift,alt,meta,exact,` +5229 // mouse5230 `middle`);5231// left & right could be mouse or key modifiers based on event type5232const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right');5233const isKeyboardEvent = /*#__PURE__*/ makeMap(`onkeyup,onkeydown,onkeypress`, true);5234const resolveModifiers = (key, modifiers, context, loc) => {5235 const keyModifiers = [];5236 const nonKeyModifiers = [];5237 const eventOptionModifiers = [];5238 for (let i = 0; i < modifiers.length; i++) {5239 const modifier = modifiers[i];5240 if (modifier === 'native' &&5241 checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) {5242 eventOptionModifiers.push(modifier);5243 }5244 else if (isEventOptionModifier(modifier)) {5245 // eventOptionModifiers: modifiers for addEventListener() options,5246 // e.g. .passive & .capture5247 eventOptionModifiers.push(modifier);5248 }5249 else {5250 // runtimeModifiers: modifiers that needs runtime guards5251 if (maybeKeyModifier(modifier)) {5252 if (isStaticExp(key)) {5253 if (isKeyboardEvent(key.content)) {5254 keyModifiers.push(modifier);5255 } ...

Full Screen

Full Screen

compiler-core.esm-bundler.js

Source:compiler-core.esm-bundler.js Github

copy

Full Screen

...785 // in v3 mode, only enable if explicitly set to true786 // otherwise enable for any non-false value787 return mode === 3 ? value === true : value !== false;788}789function checkCompatEnabled(key, context, loc, ...args) {790 const enabled = isCompatEnabled(key, context);791 if ((process.env.NODE_ENV !== 'production') && enabled) {792 warnDeprecation(key, context, loc, ...args);793 }794 return enabled;795}796function warnDeprecation(key, context, loc, ...args) {797 const val = getCompatValue(key, context);798 if (val === 'suppress-warning') {799 return;800 }801 const { message, link } = deprecationData[key];802 const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;803 const err = new SyntaxError(msg);804 err.code = key;805 if (loc)806 err.loc = loc;807 context.onWarn(err);808}809// The default decoder only provides escapes for characters reserved as part of810// the template syntax, and is only used if the custom renderer did not provide811// a platform-specific decoder.812const decodeRE = /&(gt|lt|amp|apos|quot);/g;813const decodeMap = {814 gt: '>',815 lt: '<',816 amp: '&',817 apos: "'",818 quot: '"'819};820const defaultParserOptions = {821 delimiters: [`{{`, `}}`],822 getNamespace: () => 0 /* HTML */,823 getTextMode: () => 0 /* DATA */,824 isVoidTag: NO,825 isPreTag: NO,826 isCustomElement: NO,827 decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),828 onError: defaultOnError,829 onWarn: defaultOnWarn,830 comments: (process.env.NODE_ENV !== 'production')831};832function baseParse(content, options = {}) {833 const context = createParserContext(content, options);834 const start = getCursor(context);835 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));836}837function createParserContext(content, rawOptions) {838 const options = extend({}, defaultParserOptions);839 let key;840 for (key in rawOptions) {841 // @ts-ignore842 options[key] =843 rawOptions[key] === undefined844 ? defaultParserOptions[key]845 : rawOptions[key];846 }847 return {848 options,849 column: 1,850 line: 1,851 offset: 0,852 originalSource: content,853 source: content,854 inPre: false,855 inVPre: false,856 onWarn: options.onWarn857 };858}859function parseChildren(context, mode, ancestors) {860 const parent = last(ancestors);861 const ns = parent ? parent.ns : 0 /* HTML */;862 const nodes = [];863 while (!isEnd(context, mode, ancestors)) {864 const s = context.source;865 let node = undefined;866 if (mode === 0 /* DATA */ || mode === 1 /* RCDATA */) {867 if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {868 // '{{'869 node = parseInterpolation(context, mode);870 }871 else if (mode === 0 /* DATA */ && s[0] === '<') {872 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state873 if (s.length === 1) {874 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 1);875 }876 else if (s[1] === '!') {877 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state878 if (startsWith(s, '<!--')) {879 node = parseComment(context);880 }881 else if (startsWith(s, '<!DOCTYPE')) {882 // Ignore DOCTYPE by a limitation.883 node = parseBogusComment(context);884 }885 else if (startsWith(s, '<![CDATA[')) {886 if (ns !== 0 /* HTML */) {887 node = parseCDATA(context, ancestors);888 }889 else {890 emitError(context, 1 /* CDATA_IN_HTML_CONTENT */);891 node = parseBogusComment(context);892 }893 }894 else {895 emitError(context, 11 /* INCORRECTLY_OPENED_COMMENT */);896 node = parseBogusComment(context);897 }898 }899 else if (s[1] === '/') {900 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state901 if (s.length === 2) {902 emitError(context, 5 /* EOF_BEFORE_TAG_NAME */, 2);903 }904 else if (s[2] === '>') {905 emitError(context, 14 /* MISSING_END_TAG_NAME */, 2);906 advanceBy(context, 3);907 continue;908 }909 else if (/[a-z]/i.test(s[2])) {910 emitError(context, 23 /* X_INVALID_END_TAG */);911 parseTag(context, 1 /* End */, parent);912 continue;913 }914 else {915 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);916 node = parseBogusComment(context);917 }918 }919 else if (/[a-z]/i.test(s[1])) {920 node = parseElement(context, ancestors);921 // 2.x <template> with no directive compat922 if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context) &&923 node &&924 node.tag === 'template' &&925 !node.props.some(p => p.type === 7 /* DIRECTIVE */ &&926 isSpecialTemplateDirective(p.name))) {927 (process.env.NODE_ENV !== 'production') &&928 warnDeprecation("COMPILER_NATIVE_TEMPLATE" /* COMPILER_NATIVE_TEMPLATE */, context, node.loc);929 node = node.children;930 }931 }932 else if (s[1] === '?') {933 emitError(context, 21 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);934 node = parseBogusComment(context);935 }936 else {937 emitError(context, 12 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);938 }939 }940 }941 if (!node) {942 node = parseText(context, mode);943 }944 if (isArray(node)) {945 for (let i = 0; i < node.length; i++) {946 pushNode(nodes, node[i]);947 }948 }949 else {950 pushNode(nodes, node);951 }952 }953 // Whitespace handling strategy like v2954 let removedWhitespace = false;955 if (mode !== 2 /* RAWTEXT */ && mode !== 1 /* RCDATA */) {956 const shouldCondense = context.options.whitespace !== 'preserve';957 for (let i = 0; i < nodes.length; i++) {958 const node = nodes[i];959 if (!context.inPre && node.type === 2 /* TEXT */) {960 if (!/[^\t\r\n\f ]/.test(node.content)) {961 const prev = nodes[i - 1];962 const next = nodes[i + 1];963 // Remove if:964 // - the whitespace is the first or last node, or:965 // - (condense mode) the whitespace is adjacent to a comment, or:966 // - (condense mode) the whitespace is between two elements AND contains newline967 if (!prev ||968 !next ||969 (shouldCondense &&970 (prev.type === 3 /* COMMENT */ ||971 next.type === 3 /* COMMENT */ ||972 (prev.type === 1 /* ELEMENT */ &&973 next.type === 1 /* ELEMENT */ &&974 /[\r\n]/.test(node.content))))) {975 removedWhitespace = true;976 nodes[i] = null;977 }978 else {979 // Otherwise, the whitespace is condensed into a single space980 node.content = ' ';981 }982 }983 else if (shouldCondense) {984 // in condense mode, consecutive whitespaces in text are condensed985 // down to a single space.986 node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');987 }988 }989 // Remove comment nodes if desired by configuration.990 else if (node.type === 3 /* COMMENT */ && !context.options.comments) {991 removedWhitespace = true;992 nodes[i] = null;993 }994 }995 if (context.inPre && parent && context.options.isPreTag(parent.tag)) {996 // remove leading newline per html spec997 // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element998 const first = nodes[0];999 if (first && first.type === 2 /* TEXT */) {1000 first.content = first.content.replace(/^\r?\n/, '');1001 }1002 }1003 }1004 return removedWhitespace ? nodes.filter(Boolean) : nodes;1005}1006function pushNode(nodes, node) {1007 if (node.type === 2 /* TEXT */) {1008 const prev = last(nodes);1009 // Merge if both this and the previous node are text and those are1010 // consecutive. This happens for cases like "a < b".1011 if (prev &&1012 prev.type === 2 /* TEXT */ &&1013 prev.loc.end.offset === node.loc.start.offset) {1014 prev.content += node.content;1015 prev.loc.end = node.loc.end;1016 prev.loc.source += node.loc.source;1017 return;1018 }1019 }1020 nodes.push(node);1021}1022function parseCDATA(context, ancestors) {1023 advanceBy(context, 9);1024 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);1025 if (context.source.length === 0) {1026 emitError(context, 6 /* EOF_IN_CDATA */);1027 }1028 else {1029 advanceBy(context, 3);1030 }1031 return nodes;1032}1033function parseComment(context) {1034 const start = getCursor(context);1035 let content;1036 // Regular comment.1037 const match = /--(\!)?>/.exec(context.source);1038 if (!match) {1039 content = context.source.slice(4);1040 advanceBy(context, context.source.length);1041 emitError(context, 7 /* EOF_IN_COMMENT */);1042 }1043 else {1044 if (match.index <= 3) {1045 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);1046 }1047 if (match[1]) {1048 emitError(context, 10 /* INCORRECTLY_CLOSED_COMMENT */);1049 }1050 content = context.source.slice(4, match.index);1051 // Advancing with reporting nested comments.1052 const s = context.source.slice(0, match.index);1053 let prevIndex = 1, nestedIndex = 0;1054 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {1055 advanceBy(context, nestedIndex - prevIndex + 1);1056 if (nestedIndex + 4 < s.length) {1057 emitError(context, 16 /* NESTED_COMMENT */);1058 }1059 prevIndex = nestedIndex + 1;1060 }1061 advanceBy(context, match.index + match[0].length - prevIndex + 1);1062 }1063 return {1064 type: 3 /* COMMENT */,1065 content,1066 loc: getSelection(context, start)1067 };1068}1069function parseBogusComment(context) {1070 const start = getCursor(context);1071 const contentStart = context.source[1] === '?' ? 1 : 2;1072 let content;1073 const closeIndex = context.source.indexOf('>');1074 if (closeIndex === -1) {1075 content = context.source.slice(contentStart);1076 advanceBy(context, context.source.length);1077 }1078 else {1079 content = context.source.slice(contentStart, closeIndex);1080 advanceBy(context, closeIndex + 1);1081 }1082 return {1083 type: 3 /* COMMENT */,1084 content,1085 loc: getSelection(context, start)1086 };1087}1088function parseElement(context, ancestors) {1089 // Start tag.1090 const wasInPre = context.inPre;1091 const wasInVPre = context.inVPre;1092 const parent = last(ancestors);1093 const element = parseTag(context, 0 /* Start */, parent);1094 const isPreBoundary = context.inPre && !wasInPre;1095 const isVPreBoundary = context.inVPre && !wasInVPre;1096 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {1097 // #4030 self-closing <pre> tag1098 if (isPreBoundary) {1099 context.inPre = false;1100 }1101 if (isVPreBoundary) {1102 context.inVPre = false;1103 }1104 return element;1105 }1106 // Children.1107 ancestors.push(element);1108 const mode = context.options.getTextMode(element, parent);1109 const children = parseChildren(context, mode, ancestors);1110 ancestors.pop();1111 // 2.x inline-template compat1112 {1113 const inlineTemplateProp = element.props.find(p => p.type === 6 /* ATTRIBUTE */ && p.name === 'inline-template');1114 if (inlineTemplateProp &&1115 checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {1116 const loc = getSelection(context, element.loc.end);1117 inlineTemplateProp.value = {1118 type: 2 /* TEXT */,1119 content: loc.source,1120 loc1121 };1122 }1123 }1124 element.children = children;1125 // End tag.1126 if (startsWithEndTagOpen(context.source, element.tag)) {1127 parseTag(context, 1 /* End */, parent);1128 }1129 else {1130 emitError(context, 24 /* X_MISSING_END_TAG */, 0, element.loc.start);1131 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {1132 const first = children[0];1133 if (first && startsWith(first.loc.source, '<!--')) {1134 emitError(context, 8 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);1135 }1136 }1137 }1138 element.loc = getSelection(context, element.loc.start);1139 if (isPreBoundary) {1140 context.inPre = false;1141 }1142 if (isVPreBoundary) {1143 context.inVPre = false;1144 }1145 return element;1146}1147const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`);1148function parseTag(context, type, parent) {1149 // Tag open.1150 const start = getCursor(context);1151 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);1152 const tag = match[1];1153 const ns = context.options.getNamespace(tag, parent);1154 advanceBy(context, match[0].length);1155 advanceSpaces(context);1156 // save current state in case we need to re-parse attributes with v-pre1157 const cursor = getCursor(context);1158 const currentSource = context.source;1159 // check <pre> tag1160 if (context.options.isPreTag(tag)) {1161 context.inPre = true;1162 }1163 // Attributes.1164 let props = parseAttributes(context, type);1165 // check v-pre1166 if (type === 0 /* Start */ &&1167 !context.inVPre &&1168 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {1169 context.inVPre = true;1170 // reset context1171 extend(context, cursor);1172 context.source = currentSource;1173 // re-parse attrs and filter out v-pre itself1174 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');1175 }1176 // Tag close.1177 let isSelfClosing = false;1178 if (context.source.length === 0) {1179 emitError(context, 9 /* EOF_IN_TAG */);1180 }1181 else {1182 isSelfClosing = startsWith(context.source, '/>');1183 if (type === 1 /* End */ && isSelfClosing) {1184 emitError(context, 4 /* END_TAG_WITH_TRAILING_SOLIDUS */);1185 }1186 advanceBy(context, isSelfClosing ? 2 : 1);1187 }1188 if (type === 1 /* End */) {1189 return;1190 }1191 // 2.x deprecation checks1192 if ((process.env.NODE_ENV !== 'production') &&1193 isCompatEnabled("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context)) {1194 let hasIf = false;1195 let hasFor = false;1196 for (let i = 0; i < props.length; i++) {1197 const p = props[i];1198 if (p.type === 7 /* DIRECTIVE */) {1199 if (p.name === 'if') {1200 hasIf = true;1201 }1202 else if (p.name === 'for') {1203 hasFor = true;1204 }1205 }1206 if (hasIf && hasFor) {1207 warnDeprecation("COMPILER_V_IF_V_FOR_PRECEDENCE" /* COMPILER_V_IF_V_FOR_PRECEDENCE */, context, getSelection(context, start));1208 }1209 }1210 }1211 let tagType = 0 /* ELEMENT */;1212 if (!context.inVPre) {1213 if (tag === 'slot') {1214 tagType = 2 /* SLOT */;1215 }1216 else if (tag === 'template') {1217 if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {1218 tagType = 3 /* TEMPLATE */;1219 }1220 }1221 else if (isComponent(tag, props, context)) {1222 tagType = 1 /* COMPONENT */;1223 }1224 }1225 return {1226 type: 1 /* ELEMENT */,1227 ns,1228 tag,1229 tagType,1230 props,1231 isSelfClosing,1232 children: [],1233 loc: getSelection(context, start),1234 codegenNode: undefined // to be created during transform phase1235 };1236}1237function isComponent(tag, props, context) {1238 const options = context.options;1239 if (options.isCustomElement(tag)) {1240 return false;1241 }1242 if (tag === 'component' ||1243 /^[A-Z]/.test(tag) ||1244 isCoreComponent(tag) ||1245 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||1246 (options.isNativeTag && !options.isNativeTag(tag))) {1247 return true;1248 }1249 // at this point the tag should be a native tag, but check for potential "is"1250 // casting1251 for (let i = 0; i < props.length; i++) {1252 const p = props[i];1253 if (p.type === 6 /* ATTRIBUTE */) {1254 if (p.name === 'is' && p.value) {1255 if (p.value.content.startsWith('vue:')) {1256 return true;1257 }1258 else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1259 return true;1260 }1261 }1262 }1263 else {1264 // directive1265 // v-is (TODO Deprecate)1266 if (p.name === 'is') {1267 return true;1268 }1269 else if (1270 // :is on plain element - only treat as component in compat mode1271 p.name === 'bind' &&1272 isBindKey(p.arg, 'is') &&1273 true &&1274 checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {1275 return true;1276 }1277 }1278 }1279}1280function parseAttributes(context, type) {1281 const props = [];1282 const attributeNames = new Set();1283 while (context.source.length > 0 &&1284 !startsWith(context.source, '>') &&1285 !startsWith(context.source, '/>')) {1286 if (startsWith(context.source, '/')) {1287 emitError(context, 22 /* UNEXPECTED_SOLIDUS_IN_TAG */);1288 advanceBy(context, 1);1289 advanceSpaces(context);1290 continue;1291 }1292 if (type === 1 /* End */) {1293 emitError(context, 3 /* END_TAG_WITH_ATTRIBUTES */);1294 }1295 const attr = parseAttribute(context, attributeNames);1296 // Trim whitespace between class1297 // https://github.com/vuejs/vue-next/issues/42511298 if (attr.type === 6 /* ATTRIBUTE */ &&1299 attr.value &&1300 attr.name === 'class') {1301 attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();1302 }1303 if (type === 0 /* Start */) {1304 props.push(attr);1305 }1306 if (/^[^\t\r\n\f />]/.test(context.source)) {1307 emitError(context, 15 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1308 }1309 advanceSpaces(context);1310 }1311 return props;1312}1313function parseAttribute(context, nameSet) {1314 // Name.1315 const start = getCursor(context);1316 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1317 const name = match[0];1318 if (nameSet.has(name)) {1319 emitError(context, 2 /* DUPLICATE_ATTRIBUTE */);1320 }1321 nameSet.add(name);1322 if (name[0] === '=') {1323 emitError(context, 19 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1324 }1325 {1326 const pattern = /["'<]/g;1327 let m;1328 while ((m = pattern.exec(name))) {1329 emitError(context, 17 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1330 }1331 }1332 advanceBy(context, name.length);1333 // Value1334 let value = undefined;1335 if (/^[\t\r\n\f ]*=/.test(context.source)) {1336 advanceSpaces(context);1337 advanceBy(context, 1);1338 advanceSpaces(context);1339 value = parseAttributeValue(context);1340 if (!value) {1341 emitError(context, 13 /* MISSING_ATTRIBUTE_VALUE */);1342 }1343 }1344 const loc = getSelection(context, start);1345 if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {1346 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);1347 let isPropShorthand = startsWith(name, '.');1348 let dirName = match[1] ||1349 (isPropShorthand || startsWith(name, ':')1350 ? 'bind'1351 : startsWith(name, '@')1352 ? 'on'1353 : 'slot');1354 let arg;1355 if (match[2]) {1356 const isSlot = dirName === 'slot';1357 const startOffset = name.lastIndexOf(match[2]);1358 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));1359 let content = match[2];1360 let isStatic = true;1361 if (content.startsWith('[')) {1362 isStatic = false;1363 if (!content.endsWith(']')) {1364 emitError(context, 27 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1365 content = content.slice(1);1366 }1367 else {1368 content = content.slice(1, content.length - 1);1369 }1370 }1371 else if (isSlot) {1372 // #1241 special case for v-slot: vuetify relies extensively on slot1373 // names containing dots. v-slot doesn't have any modifiers and Vue 2.x1374 // supports such usage so we are keeping it consistent with 2.x.1375 content += match[3] || '';1376 }1377 arg = {1378 type: 4 /* SIMPLE_EXPRESSION */,1379 content,1380 isStatic,1381 constType: isStatic1382 ? 3 /* CAN_STRINGIFY */1383 : 0 /* NOT_CONSTANT */,1384 loc1385 };1386 }1387 if (value && value.isQuoted) {1388 const valueLoc = value.loc;1389 valueLoc.start.offset++;1390 valueLoc.start.column++;1391 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1392 valueLoc.source = valueLoc.source.slice(1, -1);1393 }1394 const modifiers = match[3] ? match[3].slice(1).split('.') : [];1395 if (isPropShorthand)1396 modifiers.push('prop');1397 // 2.x compat v-bind:foo.sync -> v-model:foo1398 if (dirName === 'bind' && arg) {1399 if (modifiers.includes('sync') &&1400 checkCompatEnabled("COMPILER_V_BIND_SYNC" /* COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {1401 dirName = 'model';1402 modifiers.splice(modifiers.indexOf('sync'), 1);1403 }1404 if ((process.env.NODE_ENV !== 'production') && modifiers.includes('prop')) {1405 checkCompatEnabled("COMPILER_V_BIND_PROP" /* COMPILER_V_BIND_PROP */, context, loc);1406 }1407 }1408 return {1409 type: 7 /* DIRECTIVE */,1410 name: dirName,1411 exp: value && {1412 type: 4 /* SIMPLE_EXPRESSION */,1413 content: value.content,1414 isStatic: false,1415 // Treat as non-constant by default. This can be potentially set to1416 // other values by `transformExpression` to make it eligible for hoisting.1417 constType: 0 /* NOT_CONSTANT */,1418 loc: value.loc1419 },1420 arg,1421 modifiers,1422 loc1423 };1424 }1425 // missing directive name or illegal directive name1426 if (!context.inVPre && startsWith(name, 'v-')) {1427 emitError(context, 26 /* X_MISSING_DIRECTIVE_NAME */);1428 }1429 return {1430 type: 6 /* ATTRIBUTE */,1431 name,1432 value: value && {1433 type: 2 /* TEXT */,1434 content: value.content,1435 loc: value.loc1436 },1437 loc1438 };1439}1440function parseAttributeValue(context) {1441 const start = getCursor(context);1442 let content;1443 const quote = context.source[0];1444 const isQuoted = quote === `"` || quote === `'`;1445 if (isQuoted) {1446 // Quoted value.1447 advanceBy(context, 1);1448 const endIndex = context.source.indexOf(quote);1449 if (endIndex === -1) {1450 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1451 }1452 else {1453 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1454 advanceBy(context, 1);1455 }1456 }1457 else {1458 // Unquoted1459 const match = /^[^\t\r\n\f >]+/.exec(context.source);1460 if (!match) {1461 return undefined;1462 }1463 const unexpectedChars = /["'<=`]/g;1464 let m;1465 while ((m = unexpectedChars.exec(match[0]))) {1466 emitError(context, 18 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1467 }1468 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1469 }1470 return { content, isQuoted, loc: getSelection(context, start) };1471}1472function parseInterpolation(context, mode) {1473 const [open, close] = context.options.delimiters;1474 const closeIndex = context.source.indexOf(close, open.length);1475 if (closeIndex === -1) {1476 emitError(context, 25 /* X_MISSING_INTERPOLATION_END */);1477 return undefined;1478 }1479 const start = getCursor(context);1480 advanceBy(context, open.length);1481 const innerStart = getCursor(context);1482 const innerEnd = getCursor(context);1483 const rawContentLength = closeIndex - open.length;1484 const rawContent = context.source.slice(0, rawContentLength);1485 const preTrimContent = parseTextData(context, rawContentLength, mode);1486 const content = preTrimContent.trim();1487 const startOffset = preTrimContent.indexOf(content);1488 if (startOffset > 0) {1489 advancePositionWithMutation(innerStart, rawContent, startOffset);1490 }1491 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1492 advancePositionWithMutation(innerEnd, rawContent, endOffset);1493 advanceBy(context, close.length);1494 return {1495 type: 5 /* INTERPOLATION */,1496 content: {1497 type: 4 /* SIMPLE_EXPRESSION */,1498 isStatic: false,1499 // Set `isConstant` to false by default and will decide in transformExpression1500 constType: 0 /* NOT_CONSTANT */,1501 content,1502 loc: getSelection(context, innerStart, innerEnd)1503 },1504 loc: getSelection(context, start)1505 };1506}1507function parseText(context, mode) {1508 const endTokens = mode === 3 /* CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];1509 let endIndex = context.source.length;1510 for (let i = 0; i < endTokens.length; i++) {1511 const index = context.source.indexOf(endTokens[i], 1);1512 if (index !== -1 && endIndex > index) {1513 endIndex = index;1514 }1515 }1516 const start = getCursor(context);1517 const content = parseTextData(context, endIndex, mode);1518 return {1519 type: 2 /* TEXT */,1520 content,1521 loc: getSelection(context, start)1522 };1523}1524/**1525 * Get text data with a given length from the current location.1526 * This translates HTML entities in the text data.1527 */1528function parseTextData(context, length, mode) {1529 const rawText = context.source.slice(0, length);1530 advanceBy(context, length);1531 if (mode === 2 /* RAWTEXT */ ||1532 mode === 3 /* CDATA */ ||1533 rawText.indexOf('&') === -1) {1534 return rawText;1535 }1536 else {1537 // DATA or RCDATA containing "&"". Entity decoding required.1538 return context.options.decodeEntities(rawText, mode === 4 /* ATTRIBUTE_VALUE */);1539 }1540}1541function getCursor(context) {1542 const { column, line, offset } = context;1543 return { column, line, offset };1544}1545function getSelection(context, start, end) {1546 end = end || getCursor(context);1547 return {1548 start,1549 end,1550 source: context.originalSource.slice(start.offset, end.offset)1551 };1552}1553function last(xs) {1554 return xs[xs.length - 1];1555}1556function startsWith(source, searchString) {1557 return source.startsWith(searchString);1558}1559function advanceBy(context, numberOfCharacters) {1560 const { source } = context;1561 advancePositionWithMutation(context, source, numberOfCharacters);1562 context.source = source.slice(numberOfCharacters);1563}1564function advanceSpaces(context) {1565 const match = /^[\t\r\n\f ]+/.exec(context.source);1566 if (match) {1567 advanceBy(context, match[0].length);1568 }1569}1570function getNewPosition(context, start, numberOfCharacters) {1571 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1572}1573function emitError(context, code, offset, loc = getCursor(context)) {1574 if (offset) {1575 loc.offset += offset;1576 loc.column += offset;1577 }1578 context.options.onError(createCompilerError(code, {1579 start: loc,1580 end: loc,1581 source: ''1582 }));1583}1584function isEnd(context, mode, ancestors) {1585 const s = context.source;1586 switch (mode) {1587 case 0 /* DATA */:1588 if (startsWith(s, '</')) {1589 // TODO: probably bad performance1590 for (let i = ancestors.length - 1; i >= 0; --i) {1591 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1592 return true;1593 }1594 }1595 }1596 break;1597 case 1 /* RCDATA */:1598 case 2 /* RAWTEXT */: {1599 const parent = last(ancestors);1600 if (parent && startsWithEndTagOpen(s, parent.tag)) {1601 return true;1602 }1603 break;1604 }1605 case 3 /* CDATA */:1606 if (startsWith(s, ']]>')) {1607 return true;1608 }1609 break;1610 }1611 return !s;1612}1613function startsWithEndTagOpen(source, tag) {1614 return (startsWith(source, '</') &&1615 source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&1616 /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));1617}1618function hoistStatic(root, context) {1619 walk(root, context, 1620 // Root node is unfortunately non-hoistable due to potential parent1621 // fallthrough attributes.1622 isSingleElementRoot(root, root.children[0]));1623}1624function isSingleElementRoot(root, child) {1625 const { children } = root;1626 return (children.length === 1 &&1627 child.type === 1 /* ELEMENT */ &&1628 !isSlotOutlet(child));1629}1630function walk(node, context, doNotHoistNode = false) {1631 // Some transforms, e.g. transformAssetUrls from @vue/compiler-sfc, replaces1632 // static bindings with expressions. These expressions are guaranteed to be1633 // constant so they are still eligible for hoisting, but they are only1634 // available at runtime and therefore cannot be evaluated ahead of time.1635 // This is only a concern for pre-stringification (via transformHoist by1636 // @vue/compiler-dom), but doing it here allows us to perform only one full1637 // walk of the AST and allow `stringifyStatic` to stop walking as soon as its1638 // stringification threshold is met.1639 let canStringify = true;1640 const { children } = node;1641 const originalCount = children.length;1642 let hoistedCount = 0;1643 for (let i = 0; i < children.length; i++) {1644 const child = children[i];1645 // only plain elements & text calls are eligible for hoisting.1646 if (child.type === 1 /* ELEMENT */ &&1647 child.tagType === 0 /* ELEMENT */) {1648 const constantType = doNotHoistNode1649 ? 0 /* NOT_CONSTANT */1650 : getConstantType(child, context);1651 if (constantType > 0 /* NOT_CONSTANT */) {1652 if (constantType < 3 /* CAN_STRINGIFY */) {1653 canStringify = false;1654 }1655 if (constantType >= 2 /* CAN_HOIST */) {1656 child.codegenNode.patchFlag =1657 -1 /* HOISTED */ + ((process.env.NODE_ENV !== 'production') ? ` /* HOISTED */` : ``);1658 child.codegenNode = context.hoist(child.codegenNode);1659 hoistedCount++;1660 continue;1661 }1662 }1663 else {1664 // node may contain dynamic children, but its props may be eligible for1665 // hoisting.1666 const codegenNode = child.codegenNode;1667 if (codegenNode.type === 13 /* VNODE_CALL */) {1668 const flag = getPatchFlag(codegenNode);1669 if ((!flag ||1670 flag === 512 /* NEED_PATCH */ ||1671 flag === 1 /* TEXT */) &&1672 getGeneratedPropsConstantType(child, context) >=1673 2 /* CAN_HOIST */) {1674 const props = getNodeProps(child);1675 if (props) {1676 codegenNode.props = context.hoist(props);1677 }1678 }1679 if (codegenNode.dynamicProps) {1680 codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);1681 }1682 }1683 }1684 }1685 else if (child.type === 12 /* TEXT_CALL */) {1686 const contentType = getConstantType(child.content, context);1687 if (contentType > 0) {1688 if (contentType < 3 /* CAN_STRINGIFY */) {1689 canStringify = false;1690 }1691 if (contentType >= 2 /* CAN_HOIST */) {1692 child.codegenNode = context.hoist(child.codegenNode);1693 hoistedCount++;1694 }1695 }1696 }1697 // walk further1698 if (child.type === 1 /* ELEMENT */) {1699 const isComponent = child.tagType === 1 /* COMPONENT */;1700 if (isComponent) {1701 context.scopes.vSlot++;1702 }1703 walk(child, context);1704 if (isComponent) {1705 context.scopes.vSlot--;1706 }1707 }1708 else if (child.type === 11 /* FOR */) {1709 // Do not hoist v-for single child because it has to be a block1710 walk(child, context, child.children.length === 1);1711 }1712 else if (child.type === 9 /* IF */) {1713 for (let i = 0; i < child.branches.length; i++) {1714 // Do not hoist v-if single child because it has to be a block1715 walk(child.branches[i], context, child.branches[i].children.length === 1);1716 }1717 }1718 }1719 if (canStringify && hoistedCount && context.transformHoist) {1720 context.transformHoist(children, context, node);1721 }1722 // all children were hoisted - the entire children array is hoistable.1723 if (hoistedCount &&1724 hoistedCount === originalCount &&1725 node.type === 1 /* ELEMENT */ &&1726 node.tagType === 0 /* ELEMENT */ &&1727 node.codegenNode &&1728 node.codegenNode.type === 13 /* VNODE_CALL */ &&1729 isArray(node.codegenNode.children)) {1730 node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));1731 }1732}1733function getConstantType(node, context) {1734 const { constantCache } = context;1735 switch (node.type) {1736 case 1 /* ELEMENT */:1737 if (node.tagType !== 0 /* ELEMENT */) {1738 return 0 /* NOT_CONSTANT */;1739 }1740 const cached = constantCache.get(node);1741 if (cached !== undefined) {1742 return cached;1743 }1744 const codegenNode = node.codegenNode;1745 if (codegenNode.type !== 13 /* VNODE_CALL */) {1746 return 0 /* NOT_CONSTANT */;1747 }1748 const flag = getPatchFlag(codegenNode);1749 if (!flag) {1750 let returnType = 3 /* CAN_STRINGIFY */;1751 // Element itself has no patch flag. However we still need to check:1752 // 1. Even for a node with no patch flag, it is possible for it to contain1753 // non-hoistable expressions that refers to scope variables, e.g. compiler1754 // injected keys or cached event handlers. Therefore we need to always1755 // check the codegenNode's props to be sure.1756 const generatedPropsType = getGeneratedPropsConstantType(node, context);1757 if (generatedPropsType === 0 /* NOT_CONSTANT */) {1758 constantCache.set(node, 0 /* NOT_CONSTANT */);1759 return 0 /* NOT_CONSTANT */;1760 }1761 if (generatedPropsType < returnType) {1762 returnType = generatedPropsType;1763 }1764 // 2. its children.1765 for (let i = 0; i < node.children.length; i++) {1766 const childType = getConstantType(node.children[i], context);1767 if (childType === 0 /* NOT_CONSTANT */) {1768 constantCache.set(node, 0 /* NOT_CONSTANT */);1769 return 0 /* NOT_CONSTANT */;1770 }1771 if (childType < returnType) {1772 returnType = childType;1773 }1774 }1775 // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-01776 // type, check if any of the props can cause the type to be lowered1777 // we can skip can_patch because it's guaranteed by the absence of a1778 // patchFlag.1779 if (returnType > 1 /* CAN_SKIP_PATCH */) {1780 for (let i = 0; i < node.props.length; i++) {1781 const p = node.props[i];1782 if (p.type === 7 /* DIRECTIVE */ && p.name === 'bind' && p.exp) {1783 const expType = getConstantType(p.exp, context);1784 if (expType === 0 /* NOT_CONSTANT */) {1785 constantCache.set(node, 0 /* NOT_CONSTANT */);1786 return 0 /* NOT_CONSTANT */;1787 }1788 if (expType < returnType) {1789 returnType = expType;1790 }1791 }1792 }1793 }1794 // only svg/foreignObject could be block here, however if they are1795 // static then they don't need to be blocks since there will be no1796 // nested updates.1797 if (codegenNode.isBlock) {1798 context.removeHelper(OPEN_BLOCK);1799 context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));1800 codegenNode.isBlock = false;1801 context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));1802 }1803 constantCache.set(node, returnType);1804 return returnType;1805 }1806 else {1807 constantCache.set(node, 0 /* NOT_CONSTANT */);1808 return 0 /* NOT_CONSTANT */;1809 }1810 case 2 /* TEXT */:1811 case 3 /* COMMENT */:1812 return 3 /* CAN_STRINGIFY */;1813 case 9 /* IF */:1814 case 11 /* FOR */:1815 case 10 /* IF_BRANCH */:1816 return 0 /* NOT_CONSTANT */;1817 case 5 /* INTERPOLATION */:1818 case 12 /* TEXT_CALL */:1819 return getConstantType(node.content, context);1820 case 4 /* SIMPLE_EXPRESSION */:1821 return node.constType;1822 case 8 /* COMPOUND_EXPRESSION */:1823 let returnType = 3 /* CAN_STRINGIFY */;1824 for (let i = 0; i < node.children.length; i++) {1825 const child = node.children[i];1826 if (isString(child) || isSymbol(child)) {1827 continue;1828 }1829 const childType = getConstantType(child, context);1830 if (childType === 0 /* NOT_CONSTANT */) {1831 return 0 /* NOT_CONSTANT */;1832 }1833 else if (childType < returnType) {1834 returnType = childType;1835 }1836 }1837 return returnType;1838 default:1839 if ((process.env.NODE_ENV !== 'production')) ;1840 return 0 /* NOT_CONSTANT */;1841 }1842}1843const allowHoistedHelperSet = new Set([1844 NORMALIZE_CLASS,1845 NORMALIZE_STYLE,1846 NORMALIZE_PROPS,1847 GUARD_REACTIVE_PROPS1848]);1849function getConstantTypeOfHelperCall(value, context) {1850 if (value.type === 14 /* JS_CALL_EXPRESSION */ &&1851 !isString(value.callee) &&1852 allowHoistedHelperSet.has(value.callee)) {1853 const arg = value.arguments[0];1854 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {1855 return getConstantType(arg, context);1856 }1857 else if (arg.type === 14 /* JS_CALL_EXPRESSION */) {1858 // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`1859 return getConstantTypeOfHelperCall(arg, context);1860 }1861 }1862 return 0 /* NOT_CONSTANT */;1863}1864function getGeneratedPropsConstantType(node, context) {1865 let returnType = 3 /* CAN_STRINGIFY */;1866 const props = getNodeProps(node);1867 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {1868 const { properties } = props;1869 for (let i = 0; i < properties.length; i++) {1870 const { key, value } = properties[i];1871 const keyType = getConstantType(key, context);1872 if (keyType === 0 /* NOT_CONSTANT */) {1873 return keyType;1874 }1875 if (keyType < returnType) {1876 returnType = keyType;1877 }1878 let valueType;1879 if (value.type === 4 /* SIMPLE_EXPRESSION */) {1880 valueType = getConstantType(value, context);1881 }1882 else if (value.type === 14 /* JS_CALL_EXPRESSION */) {1883 // some helper calls can be hoisted,1884 // such as the `normalizeProps` generated by the compiler for pre-normalize class,1885 // in this case we need to respect the ConstantType of the helper's argments1886 valueType = getConstantTypeOfHelperCall(value, context);1887 }1888 else {1889 valueType = 0 /* NOT_CONSTANT */;1890 }1891 if (valueType === 0 /* NOT_CONSTANT */) {1892 return valueType;1893 }1894 if (valueType < returnType) {1895 returnType = valueType;1896 }1897 }1898 }1899 return returnType;1900}1901function getNodeProps(node) {1902 const codegenNode = node.codegenNode;1903 if (codegenNode.type === 13 /* VNODE_CALL */) {1904 return codegenNode.props;1905 }1906}1907function getPatchFlag(node) {1908 const flag = node.patchFlag;1909 return flag ? parseInt(flag, 10) : undefined;1910}1911function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, isCustomElement = NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {1912 const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);1913 const context = {1914 // options1915 selfName: nameMatch && capitalize(camelize$1(nameMatch[1])),1916 prefixIdentifiers,1917 hoistStatic,1918 cacheHandlers,1919 nodeTransforms,1920 directiveTransforms,1921 transformHoist,1922 isBuiltInComponent,1923 isCustomElement,1924 expressionPlugins,1925 scopeId,1926 slotted,1927 ssr,1928 inSSR,1929 ssrCssVars,1930 bindingMetadata,1931 inline,1932 isTS,1933 onError,1934 onWarn,1935 compatConfig,1936 // state1937 root,1938 helpers: new Map(),1939 components: new Set(),1940 directives: new Set(),1941 hoists: [],1942 imports: [],1943 constantCache: new Map(),1944 temps: 0,1945 cached: 0,1946 identifiers: Object.create(null),1947 scopes: {1948 vFor: 0,1949 vSlot: 0,1950 vPre: 0,1951 vOnce: 01952 },1953 parent: null,1954 currentNode: root,1955 childIndex: 0,1956 inVOnce: false,1957 // methods1958 helper(name) {1959 const count = context.helpers.get(name) || 0;1960 context.helpers.set(name, count + 1);1961 return name;1962 },1963 removeHelper(name) {1964 const count = context.helpers.get(name);1965 if (count) {1966 const currentCount = count - 1;1967 if (!currentCount) {1968 context.helpers.delete(name);1969 }1970 else {1971 context.helpers.set(name, currentCount);1972 }1973 }1974 },1975 helperString(name) {1976 return `_${helperNameMap[context.helper(name)]}`;1977 },1978 replaceNode(node) {1979 /* istanbul ignore if */1980 if ((process.env.NODE_ENV !== 'production')) {1981 if (!context.currentNode) {1982 throw new Error(`Node being replaced is already removed.`);1983 }1984 if (!context.parent) {1985 throw new Error(`Cannot replace root node.`);1986 }1987 }1988 context.parent.children[context.childIndex] = context.currentNode = node;1989 },1990 removeNode(node) {1991 if ((process.env.NODE_ENV !== 'production') && !context.parent) {1992 throw new Error(`Cannot remove root node.`);1993 }1994 const list = context.parent.children;1995 const removalIndex = node1996 ? list.indexOf(node)1997 : context.currentNode1998 ? context.childIndex1999 : -1;2000 /* istanbul ignore if */2001 if ((process.env.NODE_ENV !== 'production') && removalIndex < 0) {2002 throw new Error(`node being removed is not a child of current parent`);2003 }2004 if (!node || node === context.currentNode) {2005 // current node removed2006 context.currentNode = null;2007 context.onNodeRemoved();2008 }2009 else {2010 // sibling node removed2011 if (context.childIndex > removalIndex) {2012 context.childIndex--;2013 context.onNodeRemoved();2014 }2015 }2016 context.parent.children.splice(removalIndex, 1);2017 },2018 onNodeRemoved: () => { },2019 addIdentifiers(exp) {2020 },2021 removeIdentifiers(exp) {2022 },2023 hoist(exp) {2024 if (isString(exp))2025 exp = createSimpleExpression(exp);2026 context.hoists.push(exp);2027 const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* CAN_HOIST */);2028 identifier.hoisted = exp;2029 return identifier;2030 },2031 cache(exp, isVNode = false) {2032 return createCacheExpression(context.cached++, exp, isVNode);2033 }2034 };2035 {2036 context.filters = new Set();2037 }2038 return context;2039}2040function transform(root, options) {2041 const context = createTransformContext(root, options);2042 traverseNode(root, context);2043 if (options.hoistStatic) {2044 hoistStatic(root, context);2045 }2046 if (!options.ssr) {2047 createRootCodegen(root, context);2048 }2049 // finalize meta information2050 root.helpers = [...context.helpers.keys()];2051 root.components = [...context.components];2052 root.directives = [...context.directives];2053 root.imports = context.imports;2054 root.hoists = context.hoists;2055 root.temps = context.temps;2056 root.cached = context.cached;2057 {2058 root.filters = [...context.filters];2059 }2060}2061function createRootCodegen(root, context) {2062 const { helper } = context;2063 const { children } = root;2064 if (children.length === 1) {2065 const child = children[0];2066 // if the single child is an element, turn it into a block.2067 if (isSingleElementRoot(root, child) && child.codegenNode) {2068 // single element root is never hoisted so codegenNode will never be2069 // SimpleExpressionNode2070 const codegenNode = child.codegenNode;2071 if (codegenNode.type === 13 /* VNODE_CALL */) {2072 makeBlock(codegenNode, context);2073 }2074 root.codegenNode = codegenNode;2075 }2076 else {2077 // - single <slot/>, IfNode, ForNode: already blocks.2078 // - single text node: always patched.2079 // root codegen falls through via genNode()2080 root.codegenNode = child;2081 }2082 }2083 else if (children.length > 1) {2084 // root has multiple nodes - return a fragment block.2085 let patchFlag = 64 /* STABLE_FRAGMENT */;2086 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];2087 // check if the fragment actually contains a single valid child with2088 // the rest being comments2089 if ((process.env.NODE_ENV !== 'production') &&2090 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {2091 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;2092 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;2093 }2094 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, undefined, false /* isComponent */);2095 }2096 else ;2097}2098function traverseChildren(parent, context) {2099 let i = 0;2100 const nodeRemoved = () => {2101 i--;2102 };2103 for (; i < parent.children.length; i++) {2104 const child = parent.children[i];2105 if (isString(child))2106 continue;2107 context.parent = parent;2108 context.childIndex = i;2109 context.onNodeRemoved = nodeRemoved;2110 traverseNode(child, context);2111 }2112}2113function traverseNode(node, context) {2114 context.currentNode = node;2115 // apply transform plugins2116 const { nodeTransforms } = context;2117 const exitFns = [];2118 for (let i = 0; i < nodeTransforms.length; i++) {2119 const onExit = nodeTransforms[i](node, context);2120 if (onExit) {2121 if (isArray(onExit)) {2122 exitFns.push(...onExit);2123 }2124 else {2125 exitFns.push(onExit);2126 }2127 }2128 if (!context.currentNode) {2129 // node was removed2130 return;2131 }2132 else {2133 // node may have been replaced2134 node = context.currentNode;2135 }2136 }2137 switch (node.type) {2138 case 3 /* COMMENT */:2139 if (!context.ssr) {2140 // inject import for the Comment symbol, which is needed for creating2141 // comment nodes with `createVNode`2142 context.helper(CREATE_COMMENT);2143 }2144 break;2145 case 5 /* INTERPOLATION */:2146 // no need to traverse, but we need to inject toString helper2147 if (!context.ssr) {2148 context.helper(TO_DISPLAY_STRING);2149 }2150 break;2151 // for container types, further traverse downwards2152 case 9 /* IF */:2153 for (let i = 0; i < node.branches.length; i++) {2154 traverseNode(node.branches[i], context);2155 }2156 break;2157 case 10 /* IF_BRANCH */:2158 case 11 /* FOR */:2159 case 1 /* ELEMENT */:2160 case 0 /* ROOT */:2161 traverseChildren(node, context);2162 break;2163 }2164 // exit transforms2165 context.currentNode = node;2166 let i = exitFns.length;2167 while (i--) {2168 exitFns[i]();2169 }2170}2171function createStructuralDirectiveTransform(name, fn) {2172 const matches = isString(name)2173 ? (n) => n === name2174 : (n) => name.test(n);2175 return (node, context) => {2176 if (node.type === 1 /* ELEMENT */) {2177 const { props } = node;2178 // structural directive transforms are not concerned with slots2179 // as they are handled separately in vSlot.ts2180 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {2181 return;2182 }2183 const exitFns = [];2184 for (let i = 0; i < props.length; i++) {2185 const prop = props[i];2186 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {2187 // structural directives are removed to avoid infinite recursion2188 // also we remove them *before* applying so that it can further2189 // traverse itself in case it moves the node around2190 props.splice(i, 1);2191 i--;2192 const onExit = fn(node, prop, context);2193 if (onExit)2194 exitFns.push(onExit);2195 }2196 }2197 return exitFns;2198 }2199 };2200}2201const PURE_ANNOTATION = `/*#__PURE__*/`;2202function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {2203 const context = {2204 mode,2205 prefixIdentifiers,2206 sourceMap,2207 filename,2208 scopeId,2209 optimizeImports,2210 runtimeGlobalName,2211 runtimeModuleName,2212 ssrRuntimeModuleName,2213 ssr,2214 isTS,2215 inSSR,2216 source: ast.loc.source,2217 code: ``,2218 column: 1,2219 line: 1,2220 offset: 0,2221 indentLevel: 0,2222 pure: false,2223 map: undefined,2224 helper(key) {2225 return `_${helperNameMap[key]}`;2226 },2227 push(code, node) {2228 context.code += code;2229 },2230 indent() {2231 newline(++context.indentLevel);2232 },2233 deindent(withoutNewLine = false) {2234 if (withoutNewLine) {2235 --context.indentLevel;2236 }2237 else {2238 newline(--context.indentLevel);2239 }2240 },2241 newline() {2242 newline(context.indentLevel);2243 }2244 };2245 function newline(n) {2246 context.push('\n' + ` `.repeat(n));2247 }2248 return context;2249}2250function generate(ast, options = {}) {2251 const context = createCodegenContext(ast, options);2252 if (options.onContextCreated)2253 options.onContextCreated(context);2254 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;2255 const hasHelpers = ast.helpers.length > 0;2256 const useWithBlock = !prefixIdentifiers && mode !== 'module';2257 // preambles2258 // in setup() inline mode, the preamble is generated in a sub context2259 // and returned separately.2260 const preambleContext = context;2261 {2262 genFunctionPreamble(ast, preambleContext);2263 }2264 // enter render function2265 const functionName = ssr ? `ssrRender` : `render`;2266 const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];2267 const signature = args.join(', ');2268 {2269 push(`function ${functionName}(${signature}) {`);2270 }2271 indent();2272 if (useWithBlock) {2273 push(`with (_ctx) {`);2274 indent();2275 // function mode const declarations should be inside with block2276 // also they should be renamed to avoid collision with user properties2277 if (hasHelpers) {2278 push(`const { ${ast.helpers2279 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)2280 .join(', ')} } = _Vue`);2281 push(`\n`);2282 newline();2283 }2284 }2285 // generate asset resolution statements2286 if (ast.components.length) {2287 genAssets(ast.components, 'component', context);2288 if (ast.directives.length || ast.temps > 0) {2289 newline();2290 }2291 }2292 if (ast.directives.length) {2293 genAssets(ast.directives, 'directive', context);2294 if (ast.temps > 0) {2295 newline();2296 }2297 }2298 if (ast.filters && ast.filters.length) {2299 newline();2300 genAssets(ast.filters, 'filter', context);2301 newline();2302 }2303 if (ast.temps > 0) {2304 push(`let `);2305 for (let i = 0; i < ast.temps; i++) {2306 push(`${i > 0 ? `, ` : ``}_temp${i}`);2307 }2308 }2309 if (ast.components.length || ast.directives.length || ast.temps) {2310 push(`\n`);2311 newline();2312 }2313 // generate the VNode tree expression2314 if (!ssr) {2315 push(`return `);2316 }2317 if (ast.codegenNode) {2318 genNode(ast.codegenNode, context);2319 }2320 else {2321 push(`null`);2322 }2323 if (useWithBlock) {2324 deindent();2325 push(`}`);2326 }2327 deindent();2328 push(`}`);2329 return {2330 ast,2331 code: context.code,2332 preamble: ``,2333 // SourceMapGenerator does have toJSON() method but it's not in the types2334 map: context.map ? context.map.toJSON() : undefined2335 };2336}2337function genFunctionPreamble(ast, context) {2338 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;2339 const VueBinding = runtimeGlobalName;2340 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;2341 // Generate const declaration for helpers2342 // In prefix mode, we place the const declaration at top so it's done2343 // only once; But if we not prefixing, we place the declaration inside the2344 // with block so it doesn't incur the `in` check cost for every helper access.2345 if (ast.helpers.length > 0) {2346 {2347 // "with" mode.2348 // save Vue in a separate variable to avoid collision2349 push(`const _Vue = ${VueBinding}\n`);2350 // in "with" mode, helpers are declared inside the with block to avoid2351 // has check cost, but hoists are lifted out of the function - we need2352 // to provide the helper here.2353 if (ast.hoists.length) {2354 const staticHelpers = [2355 CREATE_VNODE,2356 CREATE_ELEMENT_VNODE,2357 CREATE_COMMENT,2358 CREATE_TEXT,2359 CREATE_STATIC2360 ]2361 .filter(helper => ast.helpers.includes(helper))2362 .map(aliasHelper)2363 .join(', ');2364 push(`const { ${staticHelpers} } = _Vue\n`);2365 }2366 }2367 }2368 genHoists(ast.hoists, context);2369 newline();2370 push(`return `);2371}2372function genAssets(assets, type, { helper, push, newline, isTS }) {2373 const resolver = helper(type === 'filter'2374 ? RESOLVE_FILTER2375 : type === 'component'2376 ? RESOLVE_COMPONENT2377 : RESOLVE_DIRECTIVE);2378 for (let i = 0; i < assets.length; i++) {2379 let id = assets[i];2380 // potential component implicit self-reference inferred from SFC filename2381 const maybeSelfReference = id.endsWith('__self');2382 if (maybeSelfReference) {2383 id = id.slice(0, -6);2384 }2385 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);2386 if (i < assets.length - 1) {2387 newline();2388 }2389 }2390}2391function genHoists(hoists, context) {2392 if (!hoists.length) {2393 return;2394 }2395 context.pure = true;2396 const { push, newline, helper, scopeId, mode } = context;2397 newline();2398 for (let i = 0; i < hoists.length; i++) {2399 const exp = hoists[i];2400 if (exp) {2401 push(`const _hoisted_${i + 1} = ${``}`);2402 genNode(exp, context);2403 newline();2404 }2405 }2406 context.pure = false;2407}2408function isText$1(n) {2409 return (isString(n) ||2410 n.type === 4 /* SIMPLE_EXPRESSION */ ||2411 n.type === 2 /* TEXT */ ||2412 n.type === 5 /* INTERPOLATION */ ||2413 n.type === 8 /* COMPOUND_EXPRESSION */);2414}2415function genNodeListAsArray(nodes, context) {2416 const multilines = nodes.length > 3 ||2417 (((process.env.NODE_ENV !== 'production')) && nodes.some(n => isArray(n) || !isText$1(n)));2418 context.push(`[`);2419 multilines && context.indent();2420 genNodeList(nodes, context, multilines);2421 multilines && context.deindent();2422 context.push(`]`);2423}2424function genNodeList(nodes, context, multilines = false, comma = true) {2425 const { push, newline } = context;2426 for (let i = 0; i < nodes.length; i++) {2427 const node = nodes[i];2428 if (isString(node)) {2429 push(node);2430 }2431 else if (isArray(node)) {2432 genNodeListAsArray(node, context);2433 }2434 else {2435 genNode(node, context);2436 }2437 if (i < nodes.length - 1) {2438 if (multilines) {2439 comma && push(',');2440 newline();2441 }2442 else {2443 comma && push(', ');2444 }2445 }2446 }2447}2448function genNode(node, context) {2449 if (isString(node)) {2450 context.push(node);2451 return;2452 }2453 if (isSymbol(node)) {2454 context.push(context.helper(node));2455 return;2456 }2457 switch (node.type) {2458 case 1 /* ELEMENT */:2459 case 9 /* IF */:2460 case 11 /* FOR */:2461 (process.env.NODE_ENV !== 'production') &&2462 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2463 `Apply appropriate transforms first.`);2464 genNode(node.codegenNode, context);2465 break;2466 case 2 /* TEXT */:2467 genText(node, context);2468 break;2469 case 4 /* SIMPLE_EXPRESSION */:2470 genExpression(node, context);2471 break;2472 case 5 /* INTERPOLATION */:2473 genInterpolation(node, context);2474 break;2475 case 12 /* TEXT_CALL */:2476 genNode(node.codegenNode, context);2477 break;2478 case 8 /* COMPOUND_EXPRESSION */:2479 genCompoundExpression(node, context);2480 break;2481 case 3 /* COMMENT */:2482 genComment(node, context);2483 break;2484 case 13 /* VNODE_CALL */:2485 genVNodeCall(node, context);2486 break;2487 case 14 /* JS_CALL_EXPRESSION */:2488 genCallExpression(node, context);2489 break;2490 case 15 /* JS_OBJECT_EXPRESSION */:2491 genObjectExpression(node, context);2492 break;2493 case 17 /* JS_ARRAY_EXPRESSION */:2494 genArrayExpression(node, context);2495 break;2496 case 18 /* JS_FUNCTION_EXPRESSION */:2497 genFunctionExpression(node, context);2498 break;2499 case 19 /* JS_CONDITIONAL_EXPRESSION */:2500 genConditionalExpression(node, context);2501 break;2502 case 20 /* JS_CACHE_EXPRESSION */:2503 genCacheExpression(node, context);2504 break;2505 case 21 /* JS_BLOCK_STATEMENT */:2506 genNodeList(node.body, context, true, false);2507 break;2508 // SSR only types2509 case 22 /* JS_TEMPLATE_LITERAL */:2510 break;2511 case 23 /* JS_IF_STATEMENT */:2512 break;2513 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2514 break;2515 case 25 /* JS_SEQUENCE_EXPRESSION */:2516 break;2517 case 26 /* JS_RETURN_STATEMENT */:2518 break;2519 /* istanbul ignore next */2520 case 10 /* IF_BRANCH */:2521 // noop2522 break;2523 default:2524 if ((process.env.NODE_ENV !== 'production')) {2525 assert(false, `unhandled codegen node type: ${node.type}`);2526 // make sure we exhaust all possible types2527 const exhaustiveCheck = node;2528 return exhaustiveCheck;2529 }2530 }2531}2532function genText(node, context) {2533 context.push(JSON.stringify(node.content), node);2534}2535function genExpression(node, context) {2536 const { content, isStatic } = node;2537 context.push(isStatic ? JSON.stringify(content) : content, node);2538}2539function genInterpolation(node, context) {2540 const { push, helper, pure } = context;2541 if (pure)2542 push(PURE_ANNOTATION);2543 push(`${helper(TO_DISPLAY_STRING)}(`);2544 genNode(node.content, context);2545 push(`)`);2546}2547function genCompoundExpression(node, context) {2548 for (let i = 0; i < node.children.length; i++) {2549 const child = node.children[i];2550 if (isString(child)) {2551 context.push(child);2552 }2553 else {2554 genNode(child, context);2555 }2556 }2557}2558function genExpressionAsPropertyKey(node, context) {2559 const { push } = context;2560 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2561 push(`[`);2562 genCompoundExpression(node, context);2563 push(`]`);2564 }2565 else if (node.isStatic) {2566 // only quote keys if necessary2567 const text = isSimpleIdentifier(node.content)2568 ? node.content2569 : JSON.stringify(node.content);2570 push(text, node);2571 }2572 else {2573 push(`[${node.content}]`, node);2574 }2575}2576function genComment(node, context) {2577 const { push, helper, pure } = context;2578 if (pure) {2579 push(PURE_ANNOTATION);2580 }2581 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2582}2583function genVNodeCall(node, context) {2584 const { push, helper, pure } = context;2585 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;2586 if (directives) {2587 push(helper(WITH_DIRECTIVES) + `(`);2588 }2589 if (isBlock) {2590 push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);2591 }2592 if (pure) {2593 push(PURE_ANNOTATION);2594 }2595 const callHelper = isBlock2596 ? getVNodeBlockHelper(context.inSSR, isComponent)2597 : getVNodeHelper(context.inSSR, isComponent);2598 push(helper(callHelper) + `(`, node);2599 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2600 push(`)`);2601 if (isBlock) {2602 push(`)`);2603 }2604 if (directives) {2605 push(`, `);2606 genNode(directives, context);2607 push(`)`);2608 }2609}2610function genNullableArgs(args) {2611 let i = args.length;2612 while (i--) {2613 if (args[i] != null)2614 break;2615 }2616 return args.slice(0, i + 1).map(arg => arg || `null`);2617}2618// JavaScript2619function genCallExpression(node, context) {2620 const { push, helper, pure } = context;2621 const callee = isString(node.callee) ? node.callee : helper(node.callee);2622 if (pure) {2623 push(PURE_ANNOTATION);2624 }2625 push(callee + `(`, node);2626 genNodeList(node.arguments, context);2627 push(`)`);2628}2629function genObjectExpression(node, context) {2630 const { push, indent, deindent, newline } = context;2631 const { properties } = node;2632 if (!properties.length) {2633 push(`{}`, node);2634 return;2635 }2636 const multilines = properties.length > 1 ||2637 (((process.env.NODE_ENV !== 'production')) &&2638 properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2639 push(multilines ? `{` : `{ `);2640 multilines && indent();2641 for (let i = 0; i < properties.length; i++) {2642 const { key, value } = properties[i];2643 // key2644 genExpressionAsPropertyKey(key, context);2645 push(`: `);2646 // value2647 genNode(value, context);2648 if (i < properties.length - 1) {2649 // will only reach this if it's multilines2650 push(`,`);2651 newline();2652 }2653 }2654 multilines && deindent();2655 push(multilines ? `}` : ` }`);2656}2657function genArrayExpression(node, context) {2658 genNodeListAsArray(node.elements, context);2659}2660function genFunctionExpression(node, context) {2661 const { push, indent, deindent } = context;2662 const { params, returns, body, newline, isSlot } = node;2663 if (isSlot) {2664 // wrap slot functions with owner context2665 push(`_${helperNameMap[WITH_CTX]}(`);2666 }2667 push(`(`, node);2668 if (isArray(params)) {2669 genNodeList(params, context);2670 }2671 else if (params) {2672 genNode(params, context);2673 }2674 push(`) => `);2675 if (newline || body) {2676 push(`{`);2677 indent();2678 }2679 if (returns) {2680 if (newline) {2681 push(`return `);2682 }2683 if (isArray(returns)) {2684 genNodeListAsArray(returns, context);2685 }2686 else {2687 genNode(returns, context);2688 }2689 }2690 else if (body) {2691 genNode(body, context);2692 }2693 if (newline || body) {2694 deindent();2695 push(`}`);2696 }2697 if (isSlot) {2698 if (node.isNonScopedSlot) {2699 push(`, undefined, true`);2700 }2701 push(`)`);2702 }2703}2704function genConditionalExpression(node, context) {2705 const { test, consequent, alternate, newline: needNewline } = node;2706 const { push, indent, deindent, newline } = context;2707 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2708 const needsParens = !isSimpleIdentifier(test.content);2709 needsParens && push(`(`);2710 genExpression(test, context);2711 needsParens && push(`)`);2712 }2713 else {2714 push(`(`);2715 genNode(test, context);2716 push(`)`);2717 }2718 needNewline && indent();2719 context.indentLevel++;2720 needNewline || push(` `);2721 push(`? `);2722 genNode(consequent, context);2723 context.indentLevel--;2724 needNewline && newline();2725 needNewline || push(` `);2726 push(`: `);2727 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2728 if (!isNested) {2729 context.indentLevel++;2730 }2731 genNode(alternate, context);2732 if (!isNested) {2733 context.indentLevel--;2734 }2735 needNewline && deindent(true /* without newline */);2736}2737function genCacheExpression(node, context) {2738 const { push, helper, indent, deindent, newline } = context;2739 push(`_cache[${node.index}] || (`);2740 if (node.isVNode) {2741 indent();2742 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2743 newline();2744 }2745 push(`_cache[${node.index}] = `);2746 genNode(node.value, context);2747 if (node.isVNode) {2748 push(`,`);2749 newline();2750 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2751 newline();2752 push(`_cache[${node.index}]`);2753 deindent();2754 }2755 push(`)`);2756}2757function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {2758 {2759 return;2760 }2761}2762function isReferencedIdentifier(id, parent, parentStack) {2763 {2764 return false;2765 }2766}2767function isInDestructureAssignment(parent, parentStack) {2768 if (parent &&2769 (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {2770 let i = parentStack.length;2771 while (i--) {2772 const p = parentStack[i];2773 if (p.type === 'AssignmentExpression') {2774 return true;2775 }2776 else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {2777 break;2778 }2779 }2780 }2781 return false;2782}2783function walkFunctionParams(node, onIdent) {2784 for (const p of node.params) {2785 for (const id of extractIdentifiers(p)) {2786 onIdent(id);2787 }2788 }2789}2790function walkBlockDeclarations(block, onIdent) {2791 for (const stmt of block.body) {2792 if (stmt.type === 'VariableDeclaration') {2793 if (stmt.declare)2794 continue;2795 for (const decl of stmt.declarations) {2796 for (const id of extractIdentifiers(decl.id)) {2797 onIdent(id);2798 }2799 }2800 }2801 else if (stmt.type === 'FunctionDeclaration' ||2802 stmt.type === 'ClassDeclaration') {2803 if (stmt.declare || !stmt.id)2804 continue;2805 onIdent(stmt.id);2806 }2807 }2808}2809function extractIdentifiers(param, nodes = []) {2810 switch (param.type) {2811 case 'Identifier':2812 nodes.push(param);2813 break;2814 case 'MemberExpression':2815 let object = param;2816 while (object.type === 'MemberExpression') {2817 object = object.object;2818 }2819 nodes.push(object);2820 break;2821 case 'ObjectPattern':2822 for (const prop of param.properties) {2823 if (prop.type === 'RestElement') {2824 extractIdentifiers(prop.argument, nodes);2825 }2826 else {2827 extractIdentifiers(prop.value, nodes);2828 }2829 }2830 break;2831 case 'ArrayPattern':2832 param.elements.forEach(element => {2833 if (element)2834 extractIdentifiers(element, nodes);2835 });2836 break;2837 case 'RestElement':2838 extractIdentifiers(param.argument, nodes);2839 break;2840 case 'AssignmentPattern':2841 extractIdentifiers(param.left, nodes);2842 break;2843 }2844 return nodes;2845}2846const isFunctionType = (node) => {2847 return /Function(?:Expression|Declaration)$|Method$/.test(node.type);2848};2849const isStaticProperty = (node) => node &&2850 (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&2851 !node.computed;2852const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;2853// these keywords should not appear inside expressions, but operators like2854// typeof, instanceof and in are allowed2855const prohibitedKeywordRE = new RegExp('\\b' +2856 ('do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,' +2857 'super,throw,while,yield,delete,export,import,return,switch,default,' +2858 'extends,finally,continue,debugger,function,arguments,typeof,void')2859 .split(',')2860 .join('\\b|\\b') +2861 '\\b');2862// strip strings in expressions2863const stripStringRE = /'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*\$\{|\}(?:[^`\\]|\\.)*`|`(?:[^`\\]|\\.)*`/g;2864/**2865 * Validate a non-prefixed expression.2866 * This is only called when using the in-browser runtime compiler since it2867 * doesn't prefix expressions.2868 */2869function validateBrowserExpression(node, context, asParams = false, asRawStatements = false) {2870 const exp = node.content;2871 // empty expressions are validated per-directive since some directives2872 // do allow empty expressions.2873 if (!exp.trim()) {2874 return;2875 }2876 try {2877 new Function(asRawStatements2878 ? ` ${exp} `2879 : `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`);2880 }2881 catch (e) {2882 let message = e.message;2883 const keywordMatch = exp2884 .replace(stripStringRE, '')2885 .match(prohibitedKeywordRE);2886 if (keywordMatch) {2887 message = `avoid using JavaScript keyword as property name: "${keywordMatch[0]}"`;2888 }2889 context.onError(createCompilerError(44 /* X_INVALID_EXPRESSION */, node.loc, undefined, message));2890 }2891}2892const transformExpression = (node, context) => {2893 if (node.type === 5 /* INTERPOLATION */) {2894 node.content = processExpression(node.content, context);2895 }2896 else if (node.type === 1 /* ELEMENT */) {2897 // handle directives on element2898 for (let i = 0; i < node.props.length; i++) {2899 const dir = node.props[i];2900 // do not process for v-on & v-for since they are special handled2901 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {2902 const exp = dir.exp;2903 const arg = dir.arg;2904 // do not process exp if this is v-on:arg - we need special handling2905 // for wrapping inline statements.2906 if (exp &&2907 exp.type === 4 /* SIMPLE_EXPRESSION */ &&2908 !(dir.name === 'on' && arg)) {2909 dir.exp = processExpression(exp, context, 2910 // slot args must be processed as function params2911 dir.name === 'slot');2912 }2913 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {2914 dir.arg = processExpression(arg, context);2915 }2916 }2917 }2918 }2919};2920// Important: since this function uses Node.js only dependencies, it should2921// always be used with a leading !true check so that it can be2922// tree-shaken from the browser build.2923function processExpression(node, context, 2924// some expressions like v-slot props & v-for aliases should be parsed as2925// function params2926asParams = false, 2927// v-on handler values may contain multiple statements2928asRawStatements = false, localVars = Object.create(context.identifiers)) {2929 {2930 if ((process.env.NODE_ENV !== 'production')) {2931 // simple in-browser validation (same logic in 2.x)2932 validateBrowserExpression(node, context, asParams, asRawStatements);2933 }2934 return node;2935 }2936}2937const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {2938 return processIf(node, dir, context, (ifNode, branch, isRoot) => {2939 // #1587: We need to dynamically increment the key based on the current2940 // node's sibling nodes, since chained v-if/else branches are2941 // rendered at the same depth2942 const siblings = context.parent.children;2943 let i = siblings.indexOf(ifNode);2944 let key = 0;2945 while (i-- >= 0) {2946 const sibling = siblings[i];2947 if (sibling && sibling.type === 9 /* IF */) {2948 key += sibling.branches.length;2949 }2950 }2951 // Exit callback. Complete the codegenNode when all children have been2952 // transformed.2953 return () => {2954 if (isRoot) {2955 ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);2956 }2957 else {2958 // attach this branch's codegen node to the v-if root.2959 const parentCondition = getParentCondition(ifNode.codegenNode);2960 parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);2961 }2962 };2963 });2964});2965// target-agnostic transform used for both Client and SSR2966function processIf(node, dir, context, processCodegen) {2967 if (dir.name !== 'else' &&2968 (!dir.exp || !dir.exp.content.trim())) {2969 const loc = dir.exp ? dir.exp.loc : node.loc;2970 context.onError(createCompilerError(28 /* X_V_IF_NO_EXPRESSION */, dir.loc));2971 dir.exp = createSimpleExpression(`true`, false, loc);2972 }2973 if ((process.env.NODE_ENV !== 'production') && true && dir.exp) {2974 validateBrowserExpression(dir.exp, context);2975 }2976 if (dir.name === 'if') {2977 const branch = createIfBranch(node, dir);2978 const ifNode = {2979 type: 9 /* IF */,2980 loc: node.loc,2981 branches: [branch]2982 };2983 context.replaceNode(ifNode);2984 if (processCodegen) {2985 return processCodegen(ifNode, branch, true);2986 }2987 }2988 else {2989 // locate the adjacent v-if2990 const siblings = context.parent.children;2991 const comments = [];2992 let i = siblings.indexOf(node);2993 while (i-- >= -1) {2994 const sibling = siblings[i];2995 if ((process.env.NODE_ENV !== 'production') && sibling && sibling.type === 3 /* COMMENT */) {2996 context.removeNode(sibling);2997 comments.unshift(sibling);2998 continue;2999 }3000 if (sibling &&3001 sibling.type === 2 /* TEXT */ &&3002 !sibling.content.trim().length) {3003 context.removeNode(sibling);3004 continue;3005 }3006 if (sibling && sibling.type === 9 /* IF */) {3007 // Check if v-else was followed by v-else-if3008 if (dir.name === 'else-if' &&3009 sibling.branches[sibling.branches.length - 1].condition === undefined) {3010 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3011 }3012 // move the node to the if node's branches3013 context.removeNode();3014 const branch = createIfBranch(node, dir);3015 if ((process.env.NODE_ENV !== 'production') &&3016 comments.length &&3017 // #3619 ignore comments if the v-if is direct child of <transition>3018 !(context.parent &&3019 context.parent.type === 1 /* ELEMENT */ &&3020 isBuiltInType(context.parent.tag, 'transition'))) {3021 branch.children = [...comments, ...branch.children];3022 }3023 // check if user is forcing same key on different branches3024 if ((process.env.NODE_ENV !== 'production') || !true) {3025 const key = branch.userKey;3026 if (key) {3027 sibling.branches.forEach(({ userKey }) => {3028 if (isSameKey(userKey, key)) {3029 context.onError(createCompilerError(29 /* X_V_IF_SAME_KEY */, branch.userKey.loc));3030 }3031 });3032 }3033 }3034 sibling.branches.push(branch);3035 const onExit = processCodegen && processCodegen(sibling, branch, false);3036 // since the branch was removed, it will not be traversed.3037 // make sure to traverse here.3038 traverseNode(branch, context);3039 // call on exit3040 if (onExit)3041 onExit();3042 // make sure to reset currentNode after traversal to indicate this3043 // node has been removed.3044 context.currentNode = null;3045 }3046 else {3047 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));3048 }3049 break;3050 }3051 }3052}3053function createIfBranch(node, dir) {3054 return {3055 type: 10 /* IF_BRANCH */,3056 loc: node.loc,3057 condition: dir.name === 'else' ? undefined : dir.exp,3058 children: node.tagType === 3 /* TEMPLATE */ && !findDir(node, 'for')3059 ? node.children3060 : [node],3061 userKey: findProp(node, `key`)3062 };3063}3064function createCodegenNodeForBranch(branch, keyIndex, context) {3065 if (branch.condition) {3066 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context), 3067 // make sure to pass in asBlock: true so that the comment node call3068 // closes the current block.3069 createCallExpression(context.helper(CREATE_COMMENT), [3070 (process.env.NODE_ENV !== 'production') ? '"v-if"' : '""',3071 'true'3072 ]));3073 }3074 else {3075 return createChildrenCodegenNode(branch, keyIndex, context);3076 }3077}3078function createChildrenCodegenNode(branch, keyIndex, context) {3079 const { helper } = context;3080 const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* CAN_HOIST */));3081 const { children } = branch;3082 const firstChild = children[0];3083 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;3084 if (needFragmentWrapper) {3085 if (children.length === 1 && firstChild.type === 11 /* FOR */) {3086 // optimize away nested fragments when child is a ForNode3087 const vnodeCall = firstChild.codegenNode;3088 injectProp(vnodeCall, keyProperty, context);3089 return vnodeCall;3090 }3091 else {3092 let patchFlag = 64 /* STABLE_FRAGMENT */;3093 let patchFlagText = PatchFlagNames[64 /* STABLE_FRAGMENT */];3094 // check if the fragment actually contains a single valid child with3095 // the rest being comments3096 if ((process.env.NODE_ENV !== 'production') &&3097 children.filter(c => c.type !== 3 /* COMMENT */).length === 1) {3098 patchFlag |= 2048 /* DEV_ROOT_FRAGMENT */;3099 patchFlagText += `, ${PatchFlagNames[2048 /* DEV_ROOT_FRAGMENT */]}`;3100 }3101 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${patchFlagText} */` : ``), undefined, undefined, true, false, false /* isComponent */, branch.loc);3102 }3103 }3104 else {3105 const ret = firstChild.codegenNode;3106 const vnodeCall = getMemoedVNodeCall(ret);3107 // Change createVNode to createBlock.3108 if (vnodeCall.type === 13 /* VNODE_CALL */) {3109 makeBlock(vnodeCall, context);3110 }3111 // inject branch key3112 injectProp(vnodeCall, keyProperty, context);3113 return ret;3114 }3115}3116function isSameKey(a, b) {3117 if (!a || a.type !== b.type) {3118 return false;3119 }3120 if (a.type === 6 /* ATTRIBUTE */) {3121 if (a.value.content !== b.value.content) {3122 return false;3123 }3124 }3125 else {3126 // directive3127 const exp = a.exp;3128 const branchExp = b.exp;3129 if (exp.type !== branchExp.type) {3130 return false;3131 }3132 if (exp.type !== 4 /* SIMPLE_EXPRESSION */ ||3133 exp.isStatic !== branchExp.isStatic ||3134 exp.content !== branchExp.content) {3135 return false;3136 }3137 }3138 return true;3139}3140function getParentCondition(node) {3141 while (true) {3142 if (node.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3143 if (node.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3144 node = node.alternate;3145 }3146 else {3147 return node;3148 }3149 }3150 else if (node.type === 20 /* JS_CACHE_EXPRESSION */) {3151 node = node.value;3152 }3153 }3154}3155const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {3156 const { helper, removeHelper } = context;3157 return processFor(node, dir, context, forNode => {3158 // create the loop render function expression now, and add the3159 // iterator on exit after all children have been traversed3160 const renderExp = createCallExpression(helper(RENDER_LIST), [3161 forNode.source3162 ]);3163 const memo = findDir(node, 'memo');3164 const keyProp = findProp(node, `key`);3165 const keyExp = keyProp &&3166 (keyProp.type === 6 /* ATTRIBUTE */3167 ? createSimpleExpression(keyProp.value.content, true)3168 : keyProp.exp);3169 const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;3170 const isStableFragment = forNode.source.type === 4 /* SIMPLE_EXPRESSION */ &&3171 forNode.source.constType > 0 /* NOT_CONSTANT */;3172 const fragmentFlag = isStableFragment3173 ? 64 /* STABLE_FRAGMENT */3174 : keyProp3175 ? 128 /* KEYED_FRAGMENT */3176 : 256 /* UNKEYED_FRAGMENT */;3177 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +3178 ((process.env.NODE_ENV !== 'production') ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);3179 return () => {3180 // finish the codegen now that all children have been traversed3181 let childBlock;3182 const isTemplate = isTemplateNode(node);3183 const { children } = forNode;3184 // check <template v-for> key placement3185 if (((process.env.NODE_ENV !== 'production') || !true) && isTemplate) {3186 node.children.some(c => {3187 if (c.type === 1 /* ELEMENT */) {3188 const key = findProp(c, 'key');3189 if (key) {3190 context.onError(createCompilerError(33 /* X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));3191 return true;3192 }3193 }3194 });3195 }3196 const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* ELEMENT */;3197 const slotOutlet = isSlotOutlet(node)3198 ? node3199 : isTemplate &&3200 node.children.length === 1 &&3201 isSlotOutlet(node.children[0])3202 ? node.children[0] // api-extractor somehow fails to infer this3203 : null;3204 if (slotOutlet) {3205 // <slot v-for="..."> or <template v-for="..."><slot/></template>3206 childBlock = slotOutlet.codegenNode;3207 if (isTemplate && keyProperty) {3208 // <template v-for="..." :key="..."><slot/></template>3209 // we need to inject the key to the renderSlot() call.3210 // the props for renderSlot is passed as the 3rd argument.3211 injectProp(childBlock, keyProperty, context);3212 }3213 }3214 else if (needFragmentWrapper) {3215 // <template v-for="..."> with text or multi-elements3216 // should generate a fragment block for each loop3217 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* STABLE_FRAGMENT */ +3218 ((process.env.NODE_ENV !== 'production')3219 ? ` /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`3220 : ``), undefined, undefined, true, undefined, false /* isComponent */);3221 }3222 else {3223 // Normal element v-for. Directly use the child's codegenNode3224 // but mark it as a block.3225 childBlock = children[0]3226 .codegenNode;3227 if (isTemplate && keyProperty) {3228 injectProp(childBlock, keyProperty, context);3229 }3230 if (childBlock.isBlock !== !isStableFragment) {3231 if (childBlock.isBlock) {3232 // switch from block to vnode3233 removeHelper(OPEN_BLOCK);3234 removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3235 }3236 else {3237 // switch from vnode to block3238 removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));3239 }3240 }3241 childBlock.isBlock = !isStableFragment;3242 if (childBlock.isBlock) {3243 helper(OPEN_BLOCK);3244 helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));3245 }3246 else {3247 helper(getVNodeHelper(context.inSSR, childBlock.isComponent));3248 }3249 }3250 if (memo) {3251 const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [3252 createSimpleExpression(`_cached`)3253 ]));3254 loop.body = createBlockStatement([3255 createCompoundExpression([`const _memo = (`, memo.exp, `)`]),3256 createCompoundExpression([3257 `if (_cached`,3258 ...(keyExp ? [` && _cached.key === `, keyExp] : []),3259 ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`3260 ]),3261 createCompoundExpression([`const _item = `, childBlock]),3262 createSimpleExpression(`_item.memo = _memo`),3263 createSimpleExpression(`return _item`)3264 ]);3265 renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));3266 }3267 else {3268 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));3269 }3270 };3271 });3272});3273// target-agnostic transform used for both Client and SSR3274function processFor(node, dir, context, processCodegen) {3275 if (!dir.exp) {3276 context.onError(createCompilerError(31 /* X_V_FOR_NO_EXPRESSION */, dir.loc));3277 return;3278 }3279 const parseResult = parseForExpression(3280 // can only be simple expression because vFor transform is applied3281 // before expression transform.3282 dir.exp, context);3283 if (!parseResult) {3284 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));3285 return;3286 }3287 const { addIdentifiers, removeIdentifiers, scopes } = context;3288 const { source, value, key, index } = parseResult;3289 const forNode = {3290 type: 11 /* FOR */,3291 loc: dir.loc,3292 source,3293 valueAlias: value,3294 keyAlias: key,3295 objectIndexAlias: index,3296 parseResult,3297 children: isTemplateNode(node) ? node.children : [node]3298 };3299 context.replaceNode(forNode);3300 // bookkeeping3301 scopes.vFor++;3302 const onExit = processCodegen && processCodegen(forNode);3303 return () => {3304 scopes.vFor--;3305 if (onExit)3306 onExit();3307 };3308}3309const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;3310// This regex doesn't cover the case if key or index aliases have destructuring,3311// but those do not make sense in the first place, so this works in practice.3312const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;3313const stripParensRE = /^\(|\)$/g;3314function parseForExpression(input, context) {3315 const loc = input.loc;3316 const exp = input.content;3317 const inMatch = exp.match(forAliasRE);3318 if (!inMatch)3319 return;3320 const [, LHS, RHS] = inMatch;3321 const result = {3322 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),3323 value: undefined,3324 key: undefined,3325 index: undefined3326 };3327 if ((process.env.NODE_ENV !== 'production') && true) {3328 validateBrowserExpression(result.source, context);3329 }3330 let valueContent = LHS.trim().replace(stripParensRE, '').trim();3331 const trimmedOffset = LHS.indexOf(valueContent);3332 const iteratorMatch = valueContent.match(forIteratorRE);3333 if (iteratorMatch) {3334 valueContent = valueContent.replace(forIteratorRE, '').trim();3335 const keyContent = iteratorMatch[1].trim();3336 let keyOffset;3337 if (keyContent) {3338 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3339 result.key = createAliasExpression(loc, keyContent, keyOffset);3340 if ((process.env.NODE_ENV !== 'production') && true) {3341 validateBrowserExpression(result.key, context, true);3342 }3343 }3344 if (iteratorMatch[2]) {3345 const indexContent = iteratorMatch[2].trim();3346 if (indexContent) {3347 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3348 ? keyOffset + keyContent.length3349 : trimmedOffset + valueContent.length));3350 if ((process.env.NODE_ENV !== 'production') && true) {3351 validateBrowserExpression(result.index, context, true);3352 }3353 }3354 }3355 }3356 if (valueContent) {3357 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3358 if ((process.env.NODE_ENV !== 'production') && true) {3359 validateBrowserExpression(result.value, context, true);3360 }3361 }3362 return result;3363}3364function createAliasExpression(range, content, offset) {3365 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3366}3367function createForLoopParams({ value, key, index }, memoArgs = []) {3368 return createParamsList([value, key, index, ...memoArgs]);3369}3370function createParamsList(args) {3371 let i = args.length;3372 while (i--) {3373 if (args[i])3374 break;3375 }3376 return args3377 .slice(0, i + 1)3378 .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));3379}3380const defaultFallback = createSimpleExpression(`undefined`, false);3381// A NodeTransform that:3382// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3383// by transformExpression. This is only applied in non-browser builds with3384// { prefixIdentifiers: true }.3385// 2. Track v-slot depths so that we know a slot is inside another slot.3386// Note the exit callback is executed before buildSlots() on the same node,3387// so only nested slots see positive numbers.3388const trackSlotScopes = (node, context) => {3389 if (node.type === 1 /* ELEMENT */ &&3390 (node.tagType === 1 /* COMPONENT */ ||3391 node.tagType === 3 /* TEMPLATE */)) {3392 // We are only checking non-empty v-slot here3393 // since we only care about slots that introduce scope variables.3394 const vSlot = findDir(node, 'slot');3395 if (vSlot) {3396 vSlot.exp;3397 context.scopes.vSlot++;3398 return () => {3399 context.scopes.vSlot--;3400 };3401 }3402 }3403};3404// A NodeTransform that tracks scope identifiers for scoped slots with v-for.3405// This transform is only applied in non-browser builds with { prefixIdentifiers: true }3406const trackVForSlotScopes = (node, context) => {3407 let vFor;3408 if (isTemplateNode(node) &&3409 node.props.some(isVSlot) &&3410 (vFor = findDir(node, 'for'))) {3411 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3412 if (result) {3413 const { value, key, index } = result;3414 const { addIdentifiers, removeIdentifiers } = context;3415 value && addIdentifiers(value);3416 key && addIdentifiers(key);3417 index && addIdentifiers(index);3418 return () => {3419 value && removeIdentifiers(value);3420 key && removeIdentifiers(key);3421 index && removeIdentifiers(index);3422 };3423 }3424 }3425};3426const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3427// Instead of being a DirectiveTransform, v-slot processing is called during3428// transformElement to build the slots object for a component.3429function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3430 context.helper(WITH_CTX);3431 const { children, loc } = node;3432 const slotsProperties = [];3433 const dynamicSlots = [];3434 // If the slot is inside a v-for or another v-slot, force it to be dynamic3435 // since it likely uses a scope variable.3436 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3437 // 1. Check for slot with slotProps on component itself.3438 // <Comp v-slot="{ prop }"/>3439 const onComponentSlot = findDir(node, 'slot', true);3440 if (onComponentSlot) {3441 const { arg, exp } = onComponentSlot;3442 if (arg && !isStaticExp(arg)) {3443 hasDynamicSlots = true;3444 }3445 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));3446 }3447 // 2. Iterate through children and check for template slots3448 // <template v-slot:foo="{ prop }">3449 let hasTemplateSlots = false;3450 let hasNamedDefaultSlot = false;3451 const implicitDefaultChildren = [];3452 const seenSlotNames = new Set();3453 for (let i = 0; i < children.length; i++) {3454 const slotElement = children[i];3455 let slotDir;3456 if (!isTemplateNode(slotElement) ||3457 !(slotDir = findDir(slotElement, 'slot', true))) {3458 // not a <template v-slot>, skip.3459 if (slotElement.type !== 3 /* COMMENT */) {3460 implicitDefaultChildren.push(slotElement);3461 }3462 continue;3463 }3464 if (onComponentSlot) {3465 // already has on-component slot - this is incorrect usage.3466 context.onError(createCompilerError(37 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3467 break;3468 }3469 hasTemplateSlots = true;3470 const { children: slotChildren, loc: slotLoc } = slotElement;3471 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3472 // check if name is dynamic.3473 let staticSlotName;3474 if (isStaticExp(slotName)) {3475 staticSlotName = slotName ? slotName.content : `default`;3476 }3477 else {3478 hasDynamicSlots = true;3479 }3480 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3481 // check if this slot is conditional (v-if/v-for)3482 let vIf;3483 let vElse;3484 let vFor;3485 if ((vIf = findDir(slotElement, 'if'))) {3486 hasDynamicSlots = true;3487 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3488 }3489 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3490 // find adjacent v-if3491 let j = i;3492 let prev;3493 while (j--) {3494 prev = children[j];3495 if (prev.type !== 3 /* COMMENT */) {3496 break;3497 }3498 }3499 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3500 // remove node3501 children.splice(i, 1);3502 i--;3503 // attach this slot to previous conditional3504 let conditional = dynamicSlots[dynamicSlots.length - 1];3505 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3506 conditional = conditional.alternate;3507 }3508 conditional.alternate = vElse.exp3509 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3510 : buildDynamicSlot(slotName, slotFunction);3511 }3512 else {3513 context.onError(createCompilerError(30 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3514 }3515 }3516 else if ((vFor = findDir(slotElement, 'for'))) {3517 hasDynamicSlots = true;3518 const parseResult = vFor.parseResult ||3519 parseForExpression(vFor.exp, context);3520 if (parseResult) {3521 // Render the dynamic slots as an array and add it to the createSlot()3522 // args. The runtime knows how to handle it appropriately.3523 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3524 parseResult.source,3525 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3526 ]));3527 }3528 else {3529 context.onError(createCompilerError(32 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3530 }3531 }3532 else {3533 // check duplicate static names3534 if (staticSlotName) {3535 if (seenSlotNames.has(staticSlotName)) {3536 context.onError(createCompilerError(38 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3537 continue;3538 }3539 seenSlotNames.add(staticSlotName);3540 if (staticSlotName === 'default') {3541 hasNamedDefaultSlot = true;3542 }3543 }3544 slotsProperties.push(createObjectProperty(slotName, slotFunction));3545 }3546 }3547 if (!onComponentSlot) {3548 const buildDefaultSlotProperty = (props, children) => {3549 const fn = buildSlotFn(props, children, loc);3550 if (context.compatConfig) {3551 fn.isNonScopedSlot = true;3552 }3553 return createObjectProperty(`default`, fn);3554 };3555 if (!hasTemplateSlots) {3556 // implicit default slot (on component)3557 slotsProperties.push(buildDefaultSlotProperty(undefined, children));3558 }3559 else if (implicitDefaultChildren.length &&3560 // #37663561 // with whitespace: 'preserve', whitespaces between slots will end up in3562 // implicitDefaultChildren. Ignore if all implicit children are whitespaces.3563 implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {3564 // implicit default slot (mixed with named slots)3565 if (hasNamedDefaultSlot) {3566 context.onError(createCompilerError(39 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));3567 }3568 else {3569 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));3570 }3571 }3572 }3573 const slotFlag = hasDynamicSlots3574 ? 2 /* DYNAMIC */3575 : hasForwardedSlots(node.children)3576 ? 3 /* FORWARDED */3577 : 1 /* STABLE */;3578 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, 3579 // 2 = compiled but dynamic = can skip normalization, but must run diff3580 // 1 = compiled and static = can skip normalization AND diff as optimized3581 createSimpleExpression(slotFlag + ((process.env.NODE_ENV !== 'production') ? ` /* ${slotFlagsText[slotFlag]} */` : ``), false))), loc);3582 if (dynamicSlots.length) {3583 slots = createCallExpression(context.helper(CREATE_SLOTS), [3584 slots,3585 createArrayExpression(dynamicSlots)3586 ]);3587 }3588 return {3589 slots,3590 hasDynamicSlots3591 };3592}3593function buildDynamicSlot(name, fn) {3594 return createObjectExpression([3595 createObjectProperty(`name`, name),3596 createObjectProperty(`fn`, fn)3597 ]);3598}3599function hasForwardedSlots(children) {3600 for (let i = 0; i < children.length; i++) {3601 const child = children[i];3602 switch (child.type) {3603 case 1 /* ELEMENT */:3604 if (child.tagType === 2 /* SLOT */ ||3605 hasForwardedSlots(child.children)) {3606 return true;3607 }3608 break;3609 case 9 /* IF */:3610 if (hasForwardedSlots(child.branches))3611 return true;3612 break;3613 case 10 /* IF_BRANCH */:3614 case 11 /* FOR */:3615 if (hasForwardedSlots(child.children))3616 return true;3617 break;3618 }3619 }3620 return false;3621}3622function isNonWhitespaceContent(node) {3623 if (node.type !== 2 /* TEXT */ && node.type !== 12 /* TEXT_CALL */)3624 return true;3625 return node.type === 2 /* TEXT */3626 ? !!node.content.trim()3627 : isNonWhitespaceContent(node.content);3628}3629// some directive transforms (e.g. v-model) may return a symbol for runtime3630// import, which should be used instead of a resolveDirective call.3631const directiveImportMap = new WeakMap();3632// generate a JavaScript AST for this element's codegen3633const transformElement = (node, context) => {3634 // perform the work on exit, after all child expressions have been3635 // processed and merged.3636 return function postTransformElement() {3637 node = context.currentNode;3638 if (!(node.type === 1 /* ELEMENT */ &&3639 (node.tagType === 0 /* ELEMENT */ ||3640 node.tagType === 1 /* COMPONENT */))) {3641 return;3642 }3643 const { tag, props } = node;3644 const isComponent = node.tagType === 1 /* COMPONENT */;3645 // The goal of the transform is to create a codegenNode implementing the3646 // VNodeCall interface.3647 let vnodeTag = isComponent3648 ? resolveComponentType(node, context)3649 : `"${tag}"`;3650 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;3651 let vnodeProps;3652 let vnodeChildren;3653 let vnodePatchFlag;3654 let patchFlag = 0;3655 let vnodeDynamicProps;3656 let dynamicPropNames;3657 let vnodeDirectives;3658 let shouldUseBlock = 3659 // dynamic component may resolve to plain elements3660 isDynamicComponent ||3661 vnodeTag === TELEPORT ||3662 vnodeTag === SUSPENSE ||3663 (!isComponent &&3664 // <svg> and <foreignObject> must be forced into blocks so that block3665 // updates inside get proper isSVG flag at runtime. (#639, #643)3666 // This is technically web-specific, but splitting the logic out of core3667 // leads to too much unnecessary complexity.3668 (tag === 'svg' ||3669 tag === 'foreignObject' ||3670 // #938: elements with dynamic keys should be forced into blocks3671 findProp(node, 'key', true)));3672 // props3673 if (props.length > 0) {3674 const propsBuildResult = buildProps(node, context);3675 vnodeProps = propsBuildResult.props;3676 patchFlag = propsBuildResult.patchFlag;3677 dynamicPropNames = propsBuildResult.dynamicPropNames;3678 const directives = propsBuildResult.directives;3679 vnodeDirectives =3680 directives && directives.length3681 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))3682 : undefined;3683 }3684 // children3685 if (node.children.length > 0) {3686 if (vnodeTag === KEEP_ALIVE) {3687 // Although a built-in component, we compile KeepAlive with raw children3688 // instead of slot functions so that it can be used inside Transition3689 // or other Transition-wrapping HOCs.3690 // To ensure correct updates with block optimizations, we need to:3691 // 1. Force keep-alive into a block. This avoids its children being3692 // collected by a parent block.3693 shouldUseBlock = true;3694 // 2. Force keep-alive to always be updated, since it uses raw children.3695 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3696 if ((process.env.NODE_ENV !== 'production') && node.children.length > 1) {3697 context.onError(createCompilerError(45 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {3698 start: node.children[0].loc.start,3699 end: node.children[node.children.length - 1].loc.end,3700 source: ''3701 }));3702 }3703 }3704 const shouldBuildAsSlots = isComponent &&3705 // Teleport is not a real component and has dedicated runtime handling3706 vnodeTag !== TELEPORT &&3707 // explained above.3708 vnodeTag !== KEEP_ALIVE;3709 if (shouldBuildAsSlots) {3710 const { slots, hasDynamicSlots } = buildSlots(node, context);3711 vnodeChildren = slots;3712 if (hasDynamicSlots) {3713 patchFlag |= 1024 /* DYNAMIC_SLOTS */;3714 }3715 }3716 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {3717 const child = node.children[0];3718 const type = child.type;3719 // check for dynamic text children3720 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||3721 type === 8 /* COMPOUND_EXPRESSION */;3722 if (hasDynamicTextChild &&3723 getConstantType(child, context) === 0 /* NOT_CONSTANT */) {3724 patchFlag |= 1 /* TEXT */;3725 }3726 // pass directly if the only child is a text node3727 // (plain / interpolation / expression)3728 if (hasDynamicTextChild || type === 2 /* TEXT */) {3729 vnodeChildren = child;3730 }3731 else {3732 vnodeChildren = node.children;3733 }3734 }3735 else {3736 vnodeChildren = node.children;3737 }3738 }3739 // patchFlag & dynamicPropNames3740 if (patchFlag !== 0) {3741 if ((process.env.NODE_ENV !== 'production')) {3742 if (patchFlag < 0) {3743 // special flags (negative and mutually exclusive)3744 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;3745 }3746 else {3747 // bitwise flags3748 const flagNames = Object.keys(PatchFlagNames)3749 .map(Number)3750 .filter(n => n > 0 && patchFlag & n)3751 .map(n => PatchFlagNames[n])3752 .join(`, `);3753 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;3754 }3755 }3756 else {3757 vnodePatchFlag = String(patchFlag);3758 }3759 if (dynamicPropNames && dynamicPropNames.length) {3760 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);3761 }3762 }3763 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);3764 };3765};3766function resolveComponentType(node, context, ssr = false) {3767 let { tag } = node;3768 // 1. dynamic component3769 const isExplicitDynamic = isComponentTag(tag);3770 const isProp = findProp(node, 'is');3771 if (isProp) {3772 if (isExplicitDynamic ||3773 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {3774 const exp = isProp.type === 6 /* ATTRIBUTE */3775 ? isProp.value && createSimpleExpression(isProp.value.content, true)3776 : isProp.exp;3777 if (exp) {3778 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3779 exp3780 ]);3781 }3782 }3783 else if (isProp.type === 6 /* ATTRIBUTE */ &&3784 isProp.value.content.startsWith('vue:')) {3785 // <button is="vue:xxx">3786 // if not <component>, only is value that starts with "vue:" will be3787 // treated as component by the parse phase and reach here, unless it's3788 // compat mode where all is values are considered components3789 tag = isProp.value.content.slice(4);3790 }3791 }3792 // 1.5 v-is (TODO: Deprecate)3793 const isDir = !isExplicitDynamic && findDir(node, 'is');3794 if (isDir && isDir.exp) {3795 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [3796 isDir.exp3797 ]);3798 }3799 // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)3800 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);3801 if (builtIn) {3802 // built-ins are simply fallthroughs / have special handling during ssr3803 // so we don't need to import their runtime equivalents3804 if (!ssr)3805 context.helper(builtIn);3806 return builtIn;3807 }3808 // 5. user component (resolve)3809 context.helper(RESOLVE_COMPONENT);3810 context.components.add(tag);3811 return toValidAssetId(tag, `component`);3812}3813function buildProps(node, context, props = node.props, ssr = false) {3814 const { tag, loc: elementLoc } = node;3815 const isComponent = node.tagType === 1 /* COMPONENT */;3816 let properties = [];3817 const mergeArgs = [];3818 const runtimeDirectives = [];3819 // patchFlag analysis3820 let patchFlag = 0;3821 let hasRef = false;3822 let hasClassBinding = false;3823 let hasStyleBinding = false;3824 let hasHydrationEventBinding = false;3825 let hasDynamicKeys = false;3826 let hasVnodeHook = false;3827 const dynamicPropNames = [];3828 const analyzePatchFlag = ({ key, value }) => {3829 if (isStaticExp(key)) {3830 const name = key.content;3831 const isEventHandler = isOn(name);3832 if (!isComponent &&3833 isEventHandler &&3834 // omit the flag for click handlers because hydration gives click3835 // dedicated fast path.3836 name.toLowerCase() !== 'onclick' &&3837 // omit v-model handlers3838 name !== 'onUpdate:modelValue' &&3839 // omit onVnodeXXX hooks3840 !isReservedProp(name)) {3841 hasHydrationEventBinding = true;3842 }3843 if (isEventHandler && isReservedProp(name)) {3844 hasVnodeHook = true;3845 }3846 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||3847 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||3848 value.type === 8 /* COMPOUND_EXPRESSION */) &&3849 getConstantType(value, context) > 0)) {3850 // skip if the prop is a cached handler or has constant value3851 return;3852 }3853 if (name === 'ref') {3854 hasRef = true;3855 }3856 else if (name === 'class') {3857 hasClassBinding = true;3858 }3859 else if (name === 'style') {3860 hasStyleBinding = true;3861 }3862 else if (name !== 'key' && !dynamicPropNames.includes(name)) {3863 dynamicPropNames.push(name);3864 }3865 // treat the dynamic class and style binding of the component as dynamic props3866 if (isComponent &&3867 (name === 'class' || name === 'style') &&3868 !dynamicPropNames.includes(name)) {3869 dynamicPropNames.push(name);3870 }3871 }3872 else {3873 hasDynamicKeys = true;3874 }3875 };3876 for (let i = 0; i < props.length; i++) {3877 // static attribute3878 const prop = props[i];3879 if (prop.type === 6 /* ATTRIBUTE */) {3880 const { loc, name, value } = prop;3881 let valueNode = createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc);3882 if (name === 'ref') {3883 hasRef = true;3884 }3885 // skip is on <component>, or is="vue:xxx"3886 if (name === 'is' &&3887 (isComponentTag(tag) ||3888 (value && value.content.startsWith('vue:')) ||3889 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {3890 continue;3891 }3892 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), valueNode));3893 }3894 else {3895 // directives3896 const { name, arg, exp, loc } = prop;3897 const isVBind = name === 'bind';3898 const isVOn = name === 'on';3899 // skip v-slot - it is handled by its dedicated transform.3900 if (name === 'slot') {3901 if (!isComponent) {3902 context.onError(createCompilerError(40 /* X_V_SLOT_MISPLACED */, loc));3903 }3904 continue;3905 }3906 // skip v-once/v-memo - they are handled by dedicated transforms.3907 if (name === 'once' || name === 'memo') {3908 continue;3909 }3910 // skip v-is and :is on <component>3911 if (name === 'is' ||3912 (isVBind &&3913 isBindKey(arg, 'is') &&3914 (isComponentTag(tag) ||3915 (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {3916 continue;3917 }3918 // skip v-on in SSR compilation3919 if (isVOn && ssr) {3920 continue;3921 }3922 // special case for v-bind and v-on with no argument3923 if (!arg && (isVBind || isVOn)) {3924 hasDynamicKeys = true;3925 if (exp) {3926 if (properties.length) {3927 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));3928 properties = [];3929 }3930 if (isVBind) {3931 {3932 // 2.x v-bind object order compat3933 if ((process.env.NODE_ENV !== 'production')) {3934 const hasOverridableKeys = mergeArgs.some(arg => {3935 if (arg.type === 15 /* JS_OBJECT_EXPRESSION */) {3936 return arg.properties.some(({ key }) => {3937 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||3938 !key.isStatic) {3939 return true;3940 }3941 return (key.content !== 'class' &&3942 key.content !== 'style' &&3943 !isOn(key.content));3944 });3945 }3946 else {3947 // dynamic expression3948 return true;3949 }3950 });3951 if (hasOverridableKeys) {3952 checkCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context, loc);3953 }3954 }3955 if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* COMPILER_V_BIND_OBJECT_ORDER */, context)) {3956 mergeArgs.unshift(exp);3957 continue;3958 }3959 }3960 mergeArgs.push(exp);3961 }3962 else {3963 // v-on="obj" -> toHandlers(obj)3964 mergeArgs.push({3965 type: 14 /* JS_CALL_EXPRESSION */,3966 loc,3967 callee: context.helper(TO_HANDLERS),3968 arguments: [exp]3969 });3970 }3971 }3972 else {3973 context.onError(createCompilerError(isVBind3974 ? 34 /* X_V_BIND_NO_EXPRESSION */3975 : 35 /* X_V_ON_NO_EXPRESSION */, loc));3976 }3977 continue;3978 }3979 const directiveTransform = context.directiveTransforms[name];3980 if (directiveTransform) {3981 // has built-in directive transform.3982 const { props, needRuntime } = directiveTransform(prop, node, context);3983 !ssr && props.forEach(analyzePatchFlag);3984 properties.push(...props);3985 if (needRuntime) {3986 runtimeDirectives.push(prop);3987 if (isSymbol(needRuntime)) {3988 directiveImportMap.set(prop, needRuntime);3989 }3990 }3991 }3992 else {3993 // no built-in transform, this is a user custom directive.3994 runtimeDirectives.push(prop);3995 }3996 }3997 if (prop.type === 6 /* ATTRIBUTE */ &&3998 prop.name === 'ref' &&3999 context.scopes.vFor > 0 &&4000 checkCompatEnabled("COMPILER_V_FOR_REF" /* COMPILER_V_FOR_REF */, context, prop.loc)) {4001 properties.push(createObjectProperty(createSimpleExpression('refInFor', true), createSimpleExpression('true', false)));4002 }4003 }4004 let propsExpression = undefined;4005 // has v-bind="object" or v-on="object", wrap with mergeProps4006 if (mergeArgs.length) {4007 if (properties.length) {4008 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));4009 }4010 if (mergeArgs.length > 1) {4011 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);4012 }4013 else {4014 // single v-bind with nothing else - no need for a mergeProps call ...

Full Screen

Full Screen

compiler-dom.esm-bundler.js

Source:compiler-dom.esm-bundler.js Github

copy

Full Screen

...278 const eventOptionModifiers = [];279 for (let i = 0; i < modifiers.length; i++) {280 const modifier = modifiers[i];281 if (modifier === 'native' &&282 checkCompatEnabled("COMPILER_V_ON_NATIVE" /* COMPILER_V_ON_NATIVE */, context, loc)) {283 eventOptionModifiers.push(modifier);284 }285 else if (isEventOptionModifier(modifier)) {286 // eventOptionModifiers: modifiers for addEventListener() options,287 // e.g. .passive & .capture288 eventOptionModifiers.push(modifier);289 }290 else {291 // runtimeModifiers: modifiers that needs runtime guards292 if (maybeKeyModifier(modifier)) {293 if (isStaticExp(key)) {294 if (isKeyboardEvent(key.content)) {295 keyModifiers.push(modifier);296 }...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

1import { checkCompatEnabled } from '@vue/compiler-core';2import { createStore } from 'vuex'3export default createStore({4 state: {5 sabores: [],6 adornos: [],7 nombre: "",8 telefono: "",9 correo: "",10 descripcion: "",11 totCho: 10,12 totVai: 10,13 totNar: 10,14 totZan: 10,15 totMar: 5,16 totBod: 5,17 totGok: 5,18 totVel: 519 },20 getters: {21 },22 mutations: {23 checkVain: function(state) {24 if (state.sabores.includes("Vainilla"))25 state.totVai++;26 else27 state.totVai--;28 },29 checkChoc: function(state) {30 if (state.sabores.includes("Chocolate"))31 state.totCho++;32 else33 state.totCho--;34 },35 checkNara: function(state) {36 if (state.sabores.includes("Naranja"))37 state.totNar++;38 else39 state.totNar--;40 },41 checkZana: function(state) {42 if (state.sabores.includes("Zanahoria"))43 state.totZan++;44 else45 state.totZan--;46 },47 checkBoda: function(state) {48 if (state.adornos.includes("Pareja"))49 state.totBod++;50 else51 state.totBod--;52 },53 checkMario: function(state) {54 if (state.adornos.includes("MarioBros"))55 state.totMar++;56 else57 state.totMar--;58 },59 checkGoku: function(state) {60 if (state.adornos.includes("Goku"))61 state.totGok++;62 else63 state.totGok--;64 },65 checkVela: function(state) {66 if (state.adornos.includes("Vela de número"))67 state.totVel++;68 else69 state.totVel--;70 }71 },72 actions: {73 },74 modules: {75 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 await page.screenshot({ path: `example.png` });6 await browser.close();7})();8"dependencies": {9 }10"dependencies": {11 }

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const page = await browser.newPage();5 const compatEnabled = await page._client.send('Browser.checkCompatEnabled');6 console.log(compatEnabled);7 await browser.close();8})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('playwright/lib/server/browserType');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 const isCompatEnabled = await checkCompatEnabled(page);7 await browser.close();8})();9const { chromium } = require('playwright');10(async () => {11 const browser = await chromium.launch();12 const context = await browser.newContext();13 const page = await context.newPage();14 const isCompatEnabled = await page.checkCompatEnabled();15 await browser.close();16})();17const { chromium } = require('playwright');18(async () => {19 const browser = await chromium.launch();20 const context = await browser.newContext({ compat: false });21 const page = await context.newPage();22 const isCompatEnabled = await page.checkCompatEnabled();23 await browser.close();24})();25const { chromium } = require('playwright');26(async () => {27 const browser = await chromium.launch();28 const context = await browser.newContext();29 const page = await context.newPage();30 await page.evaluate(() => {31 });32 const isCompatEnabled = await page.checkCompatEnabled();33 await browser.close();34})();35const { chromium } = require('playwright');36(async () => {37 const browser = await chromium.launch();38 const context = await browser.newContext();39 const page = await context.newPage();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('@playwright/test/lib/server/compatibility');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 console.log(checkCompatEnabled(context));8 await browser.close();9})();10const { chromium } = require('playwright');11(async () => {12 const browser = await chromium.launch();13 const context = await browser.newContext({14 });15 const page = await context.newPage();16 await browser.close();17})();18browserType.connect()19browserType.launchServer()20browserType.launchPersistentContext()21browser.newContext()22browserType.launch()

Full Screen

Using AI Code Generation

copy

Full Screen

1const { chromium } = require('playwright-chromium');2const { checkCompatEnabled } = require('playwright-chromium/lib/server/chromium');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 const compatEnabled = await checkCompatEnabled(page);7 console.log('Compat enabled: ', compatEnabled);8 await browser.close();9})();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('playwright/lib/server/chromium/crBrowser');2const browser = await chromium.launch();3const page = await browser.newPage();4await checkCompatEnabled(page);5await browser.close();6const { checkCompatEnabled } = require('playwright/lib/server/chromium/crBrowser');7const browser = await chromium.launch();8const page = await browser.newPage();9await checkCompatEnabled(page);10await browser.close();

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('playwright-core/lib/server/chromium/crBrowser');2const { launch } = require('playwright-core');3const browser = await launch({ headless: false });4const page = await browser.newPage();5const { enabled } = await checkCompatEnabled(page);6console.log(enabled);7await browser.close();8from playwright._impl._api_types import Error9from playwright._impl._transport import Transport10from playwright._impl._connection import ChannelOwner11from playwright.sync_api import sync_playwright12from playwright._impl._page import Page13with sync_playwright() as p:14 browser = p.chromium.launch(headless=False)15 page = browser.new_page()16 print(page._sync_check_compat_enabled())17 print(str(e))18 browser.close()19import com.microsoft.playwright.*;20public class Test {21 public static void main(String[] args) {22 try (Playwright playwright = Playwright.create()) {23 BrowserType chromium = playwright.chromium();24 Browser browser = chromium.launch(new BrowserType.LaunchOptions().setHeadless(false));25 Page page = browser.newPage();26 System.out.println(page.checkCompatEnabled());27 browser.close();28 }29 }30}31using Microsoft.Playwright;32using System;33{34 static void Main(string[] args)35 {36 using var playwright = Playwright.CreateAsync().Result;37 var browser = playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions { Headless = false }).Result;38 var page = browser.NewPageAsync().Result;39 Console.WriteLine(page.CheckCompatEnabledAsync().Result);40 browser.CloseAsync().Wait();41 }42}43use Microsoft\Playwright\Playwright;44{45 public function test()46 {47 $playwright = Playwright::create();48 $browser = $playwright->chromium()->launch([49 ]);50 $page = $browser->newPage();51 print_r($page->checkCompat

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('playwright/lib/server/browserContext');2const context = browser.newContext();3const enabled = checkCompatEnabled(context);4console.log(enabled);5const { checkCompatEnabled } = require('playwright/lib/server/browserContext');6const context = browser.newContext();7const enabled = checkCompatEnabled(context);8console.log(enabled);9const { checkCompatEnabled } = require('playwright/lib/server/browserContext');10const context = browser.newContext();11const enabled = checkCompatEnabled(context);12console.log(enabled);13const { checkCompatEnabled } = require('playwright/lib/server/browserContext');14const context = browser.newContext();15const enabled = checkCompatEnabled(context);16console.log(enabled);17const { checkCompatEnabled } = require('playwright/lib/server/browserContext');18const context = browser.newContext();19const enabled = checkCompatEnabled(context);20console.log(enabled);21const { checkCompatEnabled } = require('playwright/lib/server/browserContext');22const context = browser.newContext();23const enabled = checkCompatEnabled(context);24console.log(enabled);25const { checkCompatEnabled } = require('playwright/lib/server/browserContext');26const context = browser.newContext();27const enabled = checkCompatEnabled(context);28console.log(enabled);29const { checkCompatEnabled } = require('playwright/lib/server/browserContext');30const context = browser.newContext();31const enabled = checkCompatEnabled(context);32console.log(enabled);33const { checkCompatEnabled } = require('playwright/lib/server/browserContext');34const context = browser.newContext();35const enabled = checkCompatEnabled(context);36console.log(enabled);37const { checkCompatEnabled } = require('playwright/lib/server/browserContext');38const context = browser.newContext();39const enabled = checkCompatEnabled(context);40console.log(enabled);41const { checkCompatEnabled } =

Full Screen

Using AI Code Generation

copy

Full Screen

1const { checkCompatEnabled } = require('playwright-core/lib/server/browserType');2const isCompatEnabled = checkCompatEnabled();3console.log(isCompatEnabled);4const { chromium } = require('playwright');5(async () => {6 const browser = await chromium.launch({ browsers: 'chromium' });7 const context = await browser.newContext();8 const page = await context.newPage();9 await page.screenshot({ path: 'chromium-compat.png' });10 await browser.close();11})();12const { firefox } = require('playwright');13(async () => {14 const browser = await firefox.launch({ browsers: 'firefox' });15 const context = await browser.newContext();16 const page = await context.newPage();17 await page.screenshot({ path: 'firefox-compat.png' });18 await browser.close();19})();20const { webkit } = require('playwright');21(async () => {22 const browser = await webkit.launch({ browsers: 'webkit' });23 const context = await browser.newContext();24 const page = await context.newPage();

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful