Best JavaScript code snippet using playwright-internal
vendor-node_modules_r.js
Source:vendor-node_modules_r.js
...605}606function isBindKey(arg, name) {607 return !!(arg && isStaticExp(arg) && arg.content === name);608}609function hasDynamicKeyVBind(node) {610 return node.props.some(p => p.type === 7 /* DIRECTIVE */ &&611 p.name === 'bind' &&612 (!p.arg || // v-bind="obj"613 p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo]614 !p.arg.isStatic) // v-bind:[foo]615 );616}617function isText(node) {618 return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */;619}620function isVSlot(p) {621 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';622}623function isTemplateNode(node) {...
compiler-dom.global.js
Source:compiler-dom.global.js
...546 arg.type === 4 /* SIMPLE_EXPRESSION */ &&547 arg.isStatic &&548 arg.content === name);549 }550 function hasDynamicKeyVBind(node) {551 return node.props.some(p => p.type === 7 /* DIRECTIVE */ &&552 p.name === 'bind' &&553 (!p.arg || // v-bind="obj"554 p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo]555 !p.arg.isStatic) // v-bind:[foo]556 );557 }558 function isText(node) {559 return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */;560 }561 function isVSlot(p) {562 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';563 }564 function isTemplateNode(node) {565 return (node.type === 1 /* ELEMENT */ && node.tagType === 3 /* TEMPLATE */);566 }567 function isSlotOutlet(node) {568 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;569 }570 function injectProp(node, prop, context) {571 let propsWithInjection;572 const props = node.type === 13 /* VNODE_CALL */ ? node.props : node.arguments[2];573 if (props == null || isString(props)) {574 propsWithInjection = createObjectExpression([prop]);575 }576 else if (props.type === 14 /* JS_CALL_EXPRESSION */) {577 // merged props... add ours578 // only inject key to object literal if it's the first argument so that579 // if doesn't override user provided keys580 const first = props.arguments[0];581 if (!isString(first) && first.type === 15 /* JS_OBJECT_EXPRESSION */) {582 first.properties.unshift(prop);583 }584 else {585 props.arguments.unshift(createObjectExpression([prop]));586 }587 propsWithInjection = props;588 }589 else if (props.type === 15 /* JS_OBJECT_EXPRESSION */) {590 let alreadyExists = false;591 // check existing key to avoid overriding user provided keys592 if (prop.key.type === 4 /* SIMPLE_EXPRESSION */) {593 const propKeyName = prop.key.content;594 alreadyExists = props.properties.some(p => p.key.type === 4 /* SIMPLE_EXPRESSION */ &&595 p.key.content === propKeyName);596 }597 if (!alreadyExists) {598 props.properties.unshift(prop);599 }600 propsWithInjection = props;601 }602 else {603 // single v-bind with expression, return a merged replacement604 propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [605 createObjectExpression([prop]),606 props607 ]);608 }609 if (node.type === 13 /* VNODE_CALL */) {610 node.props = propsWithInjection;611 }612 else {613 node.arguments[2] = propsWithInjection;614 }615 }616 function toValidAssetId(name, type) {617 return `_${type}_${name.replace(/[^\w]/g, '_')}`;618 }619 // Check if a node contains expressions that reference current context scope ids620 function hasScopeRef(node, ids) {621 if (!node || Object.keys(ids).length === 0) {622 return false;623 }624 switch (node.type) {625 case 1 /* ELEMENT */:626 for (let i = 0; i < node.props.length; i++) {627 const p = node.props[i];628 if (p.type === 7 /* DIRECTIVE */ &&629 (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) {630 return true;631 }632 }633 return node.children.some(c => hasScopeRef(c, ids));634 case 11 /* FOR */:635 if (hasScopeRef(node.source, ids)) {636 return true;637 }638 return node.children.some(c => hasScopeRef(c, ids));639 case 9 /* IF */:640 return node.branches.some(b => hasScopeRef(b, ids));641 case 10 /* IF_BRANCH */:642 if (hasScopeRef(node.condition, ids)) {643 return true;644 }645 return node.children.some(c => hasScopeRef(c, ids));646 case 4 /* SIMPLE_EXPRESSION */:647 return (!node.isStatic &&648 isSimpleIdentifier(node.content) &&649 !!ids[node.content]);650 case 8 /* COMPOUND_EXPRESSION */:651 return node.children.some(c => isObject(c) && hasScopeRef(c, ids));652 case 5 /* INTERPOLATION */:653 case 12 /* TEXT_CALL */:654 return hasScopeRef(node.content, ids);655 case 2 /* TEXT */:656 case 3 /* COMMENT */:657 return false;658 default:659 return false;660 }661 }662 const defaultParserOptions = {663 delimiters: [`{{`, `}}`],664 getNamespace: () => 0 /* HTML */,665 getTextMode: () => 0 /* DATA */,666 isVoidTag: NO,667 isPreTag: NO,668 isCustomElement: NO,669 namedCharacterReferences: {670 'gt;': '>',671 'lt;': '<',672 'amp;': '&',673 'apos;': "'",674 'quot;': '"'675 },676 maxCRNameLength: 5,677 onError: defaultOnError678 };679 function baseParse(content, options = {}) {680 const context = createParserContext(content, options);681 const start = getCursor(context);682 return createRoot(parseChildren(context, 0 /* DATA */, []), getSelection(context, start));683 }684 function createParserContext(content, options) {685 return {686 options: {687 ...defaultParserOptions,688 ...options689 },690 column: 1,691 line: 1,692 offset: 0,693 originalSource: content,694 source: content,695 inPre: false696 };697 }698 function parseChildren(context, mode, ancestors) {699 const parent = last(ancestors);700 const ns = parent ? parent.ns : 0 /* HTML */;701 const nodes = [];702 while (!isEnd(context, mode, ancestors)) {703 const s = context.source;704 let node = undefined;705 if (mode === 0 /* DATA */) {706 if (!context.inPre && startsWith(s, context.options.delimiters[0])) {707 // '{{'708 node = parseInterpolation(context, mode);709 }710 else if (s[0] === '<') {711 // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state712 if (s.length === 1) {713 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 1);714 }715 else if (s[1] === '!') {716 // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state717 if (startsWith(s, '<!--')) {718 node = parseComment(context);719 }720 else if (startsWith(s, '<!DOCTYPE')) {721 // Ignore DOCTYPE by a limitation.722 node = parseBogusComment(context);723 }724 else if (startsWith(s, '<![CDATA[')) {725 if (ns !== 0 /* HTML */) {726 node = parseCDATA(context, ancestors);727 }728 else {729 emitError(context, 2 /* CDATA_IN_HTML_CONTENT */);730 node = parseBogusComment(context);731 }732 }733 else {734 emitError(context, 14 /* INCORRECTLY_OPENED_COMMENT */);735 node = parseBogusComment(context);736 }737 }738 else if (s[1] === '/') {739 // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state740 if (s.length === 2) {741 emitError(context, 8 /* EOF_BEFORE_TAG_NAME */, 2);742 }743 else if (s[2] === '>') {744 emitError(context, 17 /* MISSING_END_TAG_NAME */, 2);745 advanceBy(context, 3);746 continue;747 }748 else if (/[a-z]/i.test(s[2])) {749 emitError(context, 30 /* X_INVALID_END_TAG */);750 parseTag(context, 1 /* End */, parent);751 continue;752 }753 else {754 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);755 node = parseBogusComment(context);756 }757 }758 else if (/[a-z]/i.test(s[1])) {759 node = parseElement(context, ancestors);760 }761 else if (s[1] === '?') {762 emitError(context, 28 /* UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);763 node = parseBogusComment(context);764 }765 else {766 emitError(context, 15 /* INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);767 }768 }769 }770 if (!node) {771 node = parseText(context, mode);772 }773 if (isArray(node)) {774 for (let i = 0; i < node.length; i++) {775 pushNode(nodes, node[i]);776 }777 }778 else {779 pushNode(nodes, node);780 }781 }782 // Whitespace management for more efficient output783 // (same as v2 whitespace: 'condense')784 let removedWhitespace = false;785 if (mode !== 2 /* RAWTEXT */ &&786 (!parent || !context.options.isPreTag(parent.tag))) {787 for (let i = 0; i < nodes.length; i++) {788 const node = nodes[i];789 if (node.type === 2 /* TEXT */) {790 if (!node.content.trim()) {791 const prev = nodes[i - 1];792 const next = nodes[i + 1];793 // If:794 // - the whitespace is the first or last node, or:795 // - the whitespace is adjacent to a comment, or:796 // - the whitespace is between two elements AND contains newline797 // Then the whitespace is ignored.798 if (!prev ||799 !next ||800 prev.type === 3 /* COMMENT */ ||801 next.type === 3 /* COMMENT */ ||802 (prev.type === 1 /* ELEMENT */ &&803 next.type === 1 /* ELEMENT */ &&804 /[\r\n]/.test(node.content))) {805 removedWhitespace = true;806 nodes[i] = null;807 }808 else {809 // Otherwise, condensed consecutive whitespace inside the text down to810 // a single space811 node.content = ' ';812 }813 }814 else {815 node.content = node.content.replace(/\s+/g, ' ');816 }817 }818 }819 }820 return removedWhitespace ? nodes.filter(Boolean) : nodes;821 }822 function pushNode(nodes, node) {823 if (node.type === 2 /* TEXT */) {824 const prev = last(nodes);825 // Merge if both this and the previous node are text and those are826 // consecutive. This happens for cases like "a < b".827 if (prev &&828 prev.type === 2 /* TEXT */ &&829 prev.loc.end.offset === node.loc.start.offset) {830 prev.content += node.content;831 prev.loc.end = node.loc.end;832 prev.loc.source += node.loc.source;833 return;834 }835 }836 nodes.push(node);837 }838 function parseCDATA(context, ancestors) {839 advanceBy(context, 9);840 const nodes = parseChildren(context, 3 /* CDATA */, ancestors);841 if (context.source.length === 0) {842 emitError(context, 9 /* EOF_IN_CDATA */);843 }844 else {845 advanceBy(context, 3);846 }847 return nodes;848 }849 function parseComment(context) {850 const start = getCursor(context);851 let content;852 // Regular comment.853 const match = /--(\!)?>/.exec(context.source);854 if (!match) {855 content = context.source.slice(4);856 advanceBy(context, context.source.length);857 emitError(context, 10 /* EOF_IN_COMMENT */);858 }859 else {860 if (match.index <= 3) {861 emitError(context, 0 /* ABRUPT_CLOSING_OF_EMPTY_COMMENT */);862 }863 if (match[1]) {864 emitError(context, 13 /* INCORRECTLY_CLOSED_COMMENT */);865 }866 content = context.source.slice(4, match.index);867 // Advancing with reporting nested comments.868 const s = context.source.slice(0, match.index);869 let prevIndex = 1, nestedIndex = 0;870 while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {871 advanceBy(context, nestedIndex - prevIndex + 1);872 if (nestedIndex + 4 < s.length) {873 emitError(context, 20 /* NESTED_COMMENT */);874 }875 prevIndex = nestedIndex + 1;876 }877 advanceBy(context, match.index + match[0].length - prevIndex + 1);878 }879 return {880 type: 3 /* COMMENT */,881 content,882 loc: getSelection(context, start)883 };884 }885 function parseBogusComment(context) {886 const start = getCursor(context);887 const contentStart = context.source[1] === '?' ? 1 : 2;888 let content;889 const closeIndex = context.source.indexOf('>');890 if (closeIndex === -1) {891 content = context.source.slice(contentStart);892 advanceBy(context, context.source.length);893 }894 else {895 content = context.source.slice(contentStart, closeIndex);896 advanceBy(context, closeIndex + 1);897 }898 return {899 type: 3 /* COMMENT */,900 content,901 loc: getSelection(context, start)902 };903 }904 function parseElement(context, ancestors) {905 // Start tag.906 const wasInPre = context.inPre;907 const parent = last(ancestors);908 const element = parseTag(context, 0 /* Start */, parent);909 const isPreBoundary = context.inPre && !wasInPre;910 if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {911 return element;912 }913 // Children.914 ancestors.push(element);915 const mode = context.options.getTextMode(element.tag, element.ns, parent);916 const children = parseChildren(context, mode, ancestors);917 ancestors.pop();918 element.children = children;919 // End tag.920 if (startsWithEndTagOpen(context.source, element.tag)) {921 parseTag(context, 1 /* End */, parent);922 }923 else {924 emitError(context, 31 /* X_MISSING_END_TAG */, 0, element.loc.start);925 if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {926 const first = children[0];927 if (first && startsWith(first.loc.source, '<!--')) {928 emitError(context, 11 /* EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);929 }930 }931 }932 element.loc = getSelection(context, element.loc.start);933 if (isPreBoundary) {934 context.inPre = false;935 }936 return element;937 }938 const isSpecialTemplateDirective = /*#__PURE__*/ makeMap(`if,else,else-if,for,slot`);939 /**940 * Parse a tag (E.g. `<div id=a>`) with that type (start tag or end tag).941 */942 function parseTag(context, type, parent) {943 // Tag open.944 const start = getCursor(context);945 const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);946 const tag = match[1];947 const ns = context.options.getNamespace(tag, parent);948 advanceBy(context, match[0].length);949 advanceSpaces(context);950 // save current state in case we need to re-parse attributes with v-pre951 const cursor = getCursor(context);952 const currentSource = context.source;953 // Attributes.954 let props = parseAttributes(context, type);955 // check v-pre956 if (!context.inPre &&957 props.some(p => p.type === 7 /* DIRECTIVE */ && p.name === 'pre')) {958 context.inPre = true;959 // reset context960 extend(context, cursor);961 context.source = currentSource;962 // re-parse attrs and filter out v-pre itself963 props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');964 }965 // Tag close.966 let isSelfClosing = false;967 if (context.source.length === 0) {968 emitError(context, 12 /* EOF_IN_TAG */);969 }970 else {971 isSelfClosing = startsWith(context.source, '/>');972 if (type === 1 /* End */ && isSelfClosing) {973 emitError(context, 7 /* END_TAG_WITH_TRAILING_SOLIDUS */);974 }975 advanceBy(context, isSelfClosing ? 2 : 1);976 }977 let tagType = 0 /* ELEMENT */;978 const options = context.options;979 if (!context.inPre && !options.isCustomElement(tag)) {980 if (options.isNativeTag) {981 if (!options.isNativeTag(tag))982 tagType = 1 /* COMPONENT */;983 }984 else if (isCoreComponent(tag) ||985 (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||986 /^[A-Z]/.test(tag) ||987 tag === 'component') {988 tagType = 1 /* COMPONENT */;989 }990 if (tag === 'slot') {991 tagType = 2 /* SLOT */;992 }993 else if (tag === 'template' &&994 props.some(p => {995 return (p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name));996 })) {997 tagType = 3 /* TEMPLATE */;998 }999 }1000 return {1001 type: 1 /* ELEMENT */,1002 ns,1003 tag,1004 tagType,1005 props,1006 isSelfClosing,1007 children: [],1008 loc: getSelection(context, start),1009 codegenNode: undefined // to be created during transform phase1010 };1011 }1012 function parseAttributes(context, type) {1013 const props = [];1014 const attributeNames = new Set();1015 while (context.source.length > 0 &&1016 !startsWith(context.source, '>') &&1017 !startsWith(context.source, '/>')) {1018 if (startsWith(context.source, '/')) {1019 emitError(context, 29 /* UNEXPECTED_SOLIDUS_IN_TAG */);1020 advanceBy(context, 1);1021 advanceSpaces(context);1022 continue;1023 }1024 if (type === 1 /* End */) {1025 emitError(context, 6 /* END_TAG_WITH_ATTRIBUTES */);1026 }1027 const attr = parseAttribute(context, attributeNames);1028 if (type === 0 /* Start */) {1029 props.push(attr);1030 }1031 if (/^[^\t\r\n\f />]/.test(context.source)) {1032 emitError(context, 19 /* MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);1033 }1034 advanceSpaces(context);1035 }1036 return props;1037 }1038 function parseAttribute(context, nameSet) {1039 // Name.1040 const start = getCursor(context);1041 const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);1042 const name = match[0];1043 if (nameSet.has(name)) {1044 emitError(context, 5 /* DUPLICATE_ATTRIBUTE */);1045 }1046 nameSet.add(name);1047 if (name[0] === '=') {1048 emitError(context, 26 /* UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);1049 }1050 {1051 const pattern = /["'<]/g;1052 let m;1053 while ((m = pattern.exec(name)) !== null) {1054 emitError(context, 24 /* UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);1055 }1056 }1057 advanceBy(context, name.length);1058 // Value1059 let value = undefined;1060 if (/^[\t\r\n\f ]*=/.test(context.source)) {1061 advanceSpaces(context);1062 advanceBy(context, 1);1063 advanceSpaces(context);1064 value = parseAttributeValue(context);1065 if (!value) {1066 emitError(context, 16 /* MISSING_ATTRIBUTE_VALUE */);1067 }1068 }1069 const loc = getSelection(context, start);1070 if (!context.inPre && /^(v-|:|@|#)/.test(name)) {1071 const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^@|^#)([^\.]+))?(.+)?$/i.exec(name);1072 let arg;1073 if (match[2]) {1074 const startOffset = name.indexOf(match[2]);1075 const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length));1076 let content = match[2];1077 let isStatic = true;1078 if (content.startsWith('[')) {1079 isStatic = false;1080 if (!content.endsWith(']')) {1081 emitError(context, 33 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);1082 }1083 content = content.substr(1, content.length - 2);1084 }1085 arg = {1086 type: 4 /* SIMPLE_EXPRESSION */,1087 content,1088 isStatic,1089 isConstant: isStatic,1090 loc1091 };1092 }1093 if (value && value.isQuoted) {1094 const valueLoc = value.loc;1095 valueLoc.start.offset++;1096 valueLoc.start.column++;1097 valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);1098 valueLoc.source = valueLoc.source.slice(1, -1);1099 }1100 return {1101 type: 7 /* DIRECTIVE */,1102 name: match[1] ||1103 (startsWith(name, ':')1104 ? 'bind'1105 : startsWith(name, '@')1106 ? 'on'1107 : 'slot'),1108 exp: value && {1109 type: 4 /* SIMPLE_EXPRESSION */,1110 content: value.content,1111 isStatic: false,1112 // Treat as non-constant by default. This can be potentially set to1113 // true by `transformExpression` to make it eligible for hoisting.1114 isConstant: false,1115 loc: value.loc1116 },1117 arg,1118 modifiers: match[3] ? match[3].substr(1).split('.') : [],1119 loc1120 };1121 }1122 return {1123 type: 6 /* ATTRIBUTE */,1124 name,1125 value: value && {1126 type: 2 /* TEXT */,1127 content: value.content,1128 loc: value.loc1129 },1130 loc1131 };1132 }1133 function parseAttributeValue(context) {1134 const start = getCursor(context);1135 let content;1136 const quote = context.source[0];1137 const isQuoted = quote === `"` || quote === `'`;1138 if (isQuoted) {1139 // Quoted value.1140 advanceBy(context, 1);1141 const endIndex = context.source.indexOf(quote);1142 if (endIndex === -1) {1143 content = parseTextData(context, context.source.length, 4 /* ATTRIBUTE_VALUE */);1144 }1145 else {1146 content = parseTextData(context, endIndex, 4 /* ATTRIBUTE_VALUE */);1147 advanceBy(context, 1);1148 }1149 }1150 else {1151 // Unquoted1152 const match = /^[^\t\r\n\f >]+/.exec(context.source);1153 if (!match) {1154 return undefined;1155 }1156 let unexpectedChars = /["'<=`]/g;1157 let m;1158 while ((m = unexpectedChars.exec(match[0])) !== null) {1159 emitError(context, 25 /* UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);1160 }1161 content = parseTextData(context, match[0].length, 4 /* ATTRIBUTE_VALUE */);1162 }1163 return { content, isQuoted, loc: getSelection(context, start) };1164 }1165 function parseInterpolation(context, mode) {1166 const [open, close] = context.options.delimiters;1167 const closeIndex = context.source.indexOf(close, open.length);1168 if (closeIndex === -1) {1169 emitError(context, 32 /* X_MISSING_INTERPOLATION_END */);1170 return undefined;1171 }1172 const start = getCursor(context);1173 advanceBy(context, open.length);1174 const innerStart = getCursor(context);1175 const innerEnd = getCursor(context);1176 const rawContentLength = closeIndex - open.length;1177 const rawContent = context.source.slice(0, rawContentLength);1178 const preTrimContent = parseTextData(context, rawContentLength, mode);1179 const content = preTrimContent.trim();1180 const startOffset = preTrimContent.indexOf(content);1181 if (startOffset > 0) {1182 advancePositionWithMutation(innerStart, rawContent, startOffset);1183 }1184 const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);1185 advancePositionWithMutation(innerEnd, rawContent, endOffset);1186 advanceBy(context, close.length);1187 return {1188 type: 5 /* INTERPOLATION */,1189 content: {1190 type: 4 /* SIMPLE_EXPRESSION */,1191 isStatic: false,1192 // Set `isConstant` to false by default and will decide in transformExpression1193 isConstant: false,1194 content,1195 loc: getSelection(context, innerStart, innerEnd)1196 },1197 loc: getSelection(context, start)1198 };1199 }1200 function parseText(context, mode) {1201 const endTokens = ['<', context.options.delimiters[0]];1202 if (mode === 3 /* CDATA */) {1203 endTokens.push(']]>');1204 }1205 let endIndex = context.source.length;1206 for (let i = 0; i < endTokens.length; i++) {1207 const index = context.source.indexOf(endTokens[i], 1);1208 if (index !== -1 && endIndex > index) {1209 endIndex = index;1210 }1211 }1212 const start = getCursor(context);1213 const content = parseTextData(context, endIndex, mode);1214 return {1215 type: 2 /* TEXT */,1216 content,1217 loc: getSelection(context, start)1218 };1219 }1220 /**1221 * Get text data with a given length from the current location.1222 * This translates HTML entities in the text data.1223 */1224 function parseTextData(context, length, mode) {1225 let rawText = context.source.slice(0, length);1226 if (mode === 2 /* RAWTEXT */ ||1227 mode === 3 /* CDATA */ ||1228 rawText.indexOf('&') === -1) {1229 advanceBy(context, length);1230 return rawText;1231 }1232 // DATA or RCDATA containing "&"". Entity decoding required.1233 const end = context.offset + length;1234 let decodedText = '';1235 function advance(length) {1236 advanceBy(context, length);1237 rawText = rawText.slice(length);1238 }1239 while (context.offset < end) {1240 const head = /&(?:#x?)?/i.exec(rawText);1241 if (!head || context.offset + head.index >= end) {1242 const remaining = end - context.offset;1243 decodedText += rawText.slice(0, remaining);1244 advance(remaining);1245 break;1246 }1247 // Advance to the "&".1248 decodedText += rawText.slice(0, head.index);1249 advance(head.index);1250 if (head[0] === '&') {1251 // Named character reference.1252 let name = '';1253 let value = undefined;1254 if (/[0-9a-z]/i.test(rawText[1])) {1255 for (let length = context.options.maxCRNameLength; !value && length > 0; --length) {1256 name = rawText.substr(1, length);1257 value = context.options.namedCharacterReferences[name];1258 }1259 if (value) {1260 const semi = name.endsWith(';');1261 if (mode === 4 /* ATTRIBUTE_VALUE */ &&1262 !semi &&1263 /[=a-z0-9]/i.test(rawText[name.length + 1] || '')) {1264 decodedText += '&' + name;1265 advance(1 + name.length);1266 }1267 else {1268 decodedText += value;1269 advance(1 + name.length);1270 if (!semi) {1271 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1272 }1273 }1274 }1275 else {1276 decodedText += '&' + name;1277 advance(1 + name.length);1278 }1279 }1280 else {1281 decodedText += '&';1282 advance(1);1283 }1284 }1285 else {1286 // Numeric character reference.1287 const hex = head[0] === '&#x';1288 const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;1289 const body = pattern.exec(rawText);1290 if (!body) {1291 decodedText += head[0];1292 emitError(context, 1 /* ABSENCE_OF_DIGITS_IN_NUMERIC_CHARACTER_REFERENCE */);1293 advance(head[0].length);1294 }1295 else {1296 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1297 let cp = Number.parseInt(body[1], hex ? 16 : 10);1298 if (cp === 0) {1299 emitError(context, 22 /* NULL_CHARACTER_REFERENCE */);1300 cp = 0xfffd;1301 }1302 else if (cp > 0x10ffff) {1303 emitError(context, 3 /* CHARACTER_REFERENCE_OUTSIDE_UNICODE_RANGE */);1304 cp = 0xfffd;1305 }1306 else if (cp >= 0xd800 && cp <= 0xdfff) {1307 emitError(context, 23 /* SURROGATE_CHARACTER_REFERENCE */);1308 cp = 0xfffd;1309 }1310 else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) {1311 emitError(context, 21 /* NONCHARACTER_CHARACTER_REFERENCE */);1312 }1313 else if ((cp >= 0x01 && cp <= 0x08) ||1314 cp === 0x0b ||1315 (cp >= 0x0d && cp <= 0x1f) ||1316 (cp >= 0x7f && cp <= 0x9f)) {1317 emitError(context, 4 /* CONTROL_CHARACTER_REFERENCE */);1318 cp = CCR_REPLACEMENTS[cp] || cp;1319 }1320 decodedText += String.fromCodePoint(cp);1321 advance(body[0].length);1322 if (!body[0].endsWith(';')) {1323 emitError(context, 18 /* MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE */);1324 }1325 }1326 }1327 }1328 return decodedText;1329 }1330 function getCursor(context) {1331 const { column, line, offset } = context;1332 return { column, line, offset };1333 }1334 function getSelection(context, start, end) {1335 end = end || getCursor(context);1336 return {1337 start,1338 end,1339 source: context.originalSource.slice(start.offset, end.offset)1340 };1341 }1342 function last(xs) {1343 return xs[xs.length - 1];1344 }1345 function startsWith(source, searchString) {1346 return source.startsWith(searchString);1347 }1348 function advanceBy(context, numberOfCharacters) {1349 const { source } = context;1350 advancePositionWithMutation(context, source, numberOfCharacters);1351 context.source = source.slice(numberOfCharacters);1352 }1353 function advanceSpaces(context) {1354 const match = /^[\t\r\n\f ]+/.exec(context.source);1355 if (match) {1356 advanceBy(context, match[0].length);1357 }1358 }1359 function getNewPosition(context, start, numberOfCharacters) {1360 return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);1361 }1362 function emitError(context, code, offset, loc = getCursor(context)) {1363 if (offset) {1364 loc.offset += offset;1365 loc.column += offset;1366 }1367 context.options.onError(createCompilerError(code, {1368 start: loc,1369 end: loc,1370 source: ''1371 }));1372 }1373 function isEnd(context, mode, ancestors) {1374 const s = context.source;1375 switch (mode) {1376 case 0 /* DATA */:1377 if (startsWith(s, '</')) {1378 //TODO: probably bad performance1379 for (let i = ancestors.length - 1; i >= 0; --i) {1380 if (startsWithEndTagOpen(s, ancestors[i].tag)) {1381 return true;1382 }1383 }1384 }1385 break;1386 case 1 /* RCDATA */:1387 case 2 /* RAWTEXT */: {1388 const parent = last(ancestors);1389 if (parent && startsWithEndTagOpen(s, parent.tag)) {1390 return true;1391 }1392 break;1393 }1394 case 3 /* CDATA */:1395 if (startsWith(s, ']]>')) {1396 return true;1397 }1398 break;1399 }1400 return !s;1401 }1402 function startsWithEndTagOpen(source, tag) {1403 return (startsWith(source, '</') &&1404 source.substr(2, tag.length).toLowerCase() === tag.toLowerCase() &&1405 /[\t\n\f />]/.test(source[2 + tag.length] || '>'));1406 }1407 // https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state1408 const CCR_REPLACEMENTS = {1409 0x80: 0x20ac,1410 0x82: 0x201a,1411 0x83: 0x0192,1412 0x84: 0x201e,1413 0x85: 0x2026,1414 0x86: 0x2020,1415 0x87: 0x2021,1416 0x88: 0x02c6,1417 0x89: 0x2030,1418 0x8a: 0x0160,1419 0x8b: 0x2039,1420 0x8c: 0x0152,1421 0x8e: 0x017d,1422 0x91: 0x2018,1423 0x92: 0x2019,1424 0x93: 0x201c,1425 0x94: 0x201d,1426 0x95: 0x2022,1427 0x96: 0x2013,1428 0x97: 0x2014,1429 0x98: 0x02dc,1430 0x99: 0x2122,1431 0x9a: 0x0161,1432 0x9b: 0x203a,1433 0x9c: 0x0153,1434 0x9e: 0x017e,1435 0x9f: 0x01781436 };1437 function hoistStatic(root, context) {1438 walk(root.children, context, new Map(), 1439 // Root node is unfortuantely non-hoistable due to potential parent1440 // fallthrough attributes.1441 isSingleElementRoot(root, root.children[0]));1442 }1443 function isSingleElementRoot(root, child) {1444 const { children } = root;1445 return (children.length === 1 &&1446 child.type === 1 /* ELEMENT */ &&1447 !isSlotOutlet(child));1448 }1449 function walk(children, context, resultCache, doNotHoistNode = false) {1450 for (let i = 0; i < children.length; i++) {1451 const child = children[i];1452 // only plain elements are eligible for hoisting.1453 if (child.type === 1 /* ELEMENT */ &&1454 child.tagType === 0 /* ELEMENT */) {1455 if (!doNotHoistNode && isStaticNode(child, resultCache)) {1456 child.codegenNode.patchFlag = -1 /* HOISTED */ + ``;1457 const hoisted = context.transformHoist1458 ? context.transformHoist(child, context)1459 : child.codegenNode;1460 child.codegenNode = context.hoist(hoisted);1461 continue;1462 }1463 else {1464 // node may contain dynamic children, but its props may be eligible for1465 // hoisting.1466 const codegenNode = child.codegenNode;1467 if (codegenNode.type === 13 /* VNODE_CALL */) {1468 const flag = getPatchFlag(codegenNode);1469 if ((!flag ||1470 flag === 32 /* NEED_PATCH */ ||1471 flag === 1 /* TEXT */) &&1472 !hasDynamicKeyOrRef(child) &&1473 !hasCachedProps()) {1474 const props = getNodeProps(child);1475 if (props) {1476 codegenNode.props = context.hoist(props);1477 }1478 }1479 }1480 }1481 }1482 if (child.type === 1 /* ELEMENT */) {1483 walk(child.children, context, resultCache);1484 }1485 else if (child.type === 11 /* FOR */) {1486 // Do not hoist v-for single child because it has to be a block1487 walk(child.children, context, resultCache, child.children.length === 1);1488 }1489 else if (child.type === 9 /* IF */) {1490 for (let i = 0; i < child.branches.length; i++) {1491 const branchChildren = child.branches[i].children;1492 // Do not hoist v-if single child because it has to be a block1493 walk(branchChildren, context, resultCache, branchChildren.length === 1);1494 }1495 }1496 else if (child.type === 12 /* TEXT_CALL */ &&1497 isStaticNode(child.content, resultCache)) {1498 child.codegenNode = context.hoist(child.codegenNode);1499 }1500 }1501 }1502 function isStaticNode(node, resultCache = new Map()) {1503 switch (node.type) {1504 case 1 /* ELEMENT */:1505 if (node.tagType !== 0 /* ELEMENT */) {1506 return false;1507 }1508 const cached = resultCache.get(node);1509 if (cached !== undefined) {1510 return cached;1511 }1512 const codegenNode = node.codegenNode;1513 if (codegenNode.type !== 13 /* VNODE_CALL */) {1514 return false;1515 }1516 const flag = getPatchFlag(codegenNode);1517 if (!flag && !hasDynamicKeyOrRef(node) && !hasCachedProps()) {1518 // element self is static. check its children.1519 for (let i = 0; i < node.children.length; i++) {1520 if (!isStaticNode(node.children[i], resultCache)) {1521 resultCache.set(node, false);1522 return false;1523 }1524 }1525 // only svg/foeignObject could be block here, however if they are static1526 // then they don't need to be blocks since there will be no nested1527 // udpates.1528 if (codegenNode.isBlock) {1529 codegenNode.isBlock = false;1530 }1531 resultCache.set(node, true);1532 return true;1533 }1534 else {1535 resultCache.set(node, false);1536 return false;1537 }1538 case 2 /* TEXT */:1539 case 3 /* COMMENT */:1540 return true;1541 case 9 /* IF */:1542 case 11 /* FOR */:1543 return false;1544 case 5 /* INTERPOLATION */:1545 case 12 /* TEXT_CALL */:1546 return isStaticNode(node.content, resultCache);1547 case 4 /* SIMPLE_EXPRESSION */:1548 return node.isConstant;1549 case 8 /* COMPOUND_EXPRESSION */:1550 return node.children.every(child => {1551 return (isString(child) || isSymbol(child) || isStaticNode(child, resultCache));1552 });1553 default:1554 return false;1555 }1556 }1557 function hasDynamicKeyOrRef(node) {1558 return !!(findProp(node, 'key', true) || findProp(node, 'ref', true));1559 }1560 function hasCachedProps(node) {1561 {1562 return false;1563 }1564 }1565 function getNodeProps(node) {1566 const codegenNode = node.codegenNode;1567 if (codegenNode.type === 13 /* VNODE_CALL */) {1568 return codegenNode.props;1569 }1570 }1571 function getPatchFlag(node) {1572 const flag = node.patchFlag;1573 return flag ? parseInt(flag, 10) : undefined;1574 }1575 function createTransformContext(root, { prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, scopeId = null, ssr = false, onError = defaultOnError }) {1576 const context = {1577 // options1578 prefixIdentifiers,1579 hoistStatic,1580 cacheHandlers,1581 nodeTransforms,1582 directiveTransforms,1583 transformHoist,1584 isBuiltInComponent,1585 scopeId,1586 ssr,1587 onError,1588 // state1589 root,1590 helpers: new Set(),1591 components: new Set(),1592 directives: new Set(),1593 hoists: [],1594 imports: new Set(),1595 temps: 0,1596 cached: 0,1597 identifiers: {},1598 scopes: {1599 vFor: 0,1600 vSlot: 0,1601 vPre: 0,1602 vOnce: 01603 },1604 parent: null,1605 currentNode: root,1606 childIndex: 0,1607 // methods1608 helper(name) {1609 context.helpers.add(name);1610 return name;1611 },1612 helperString(name) {1613 return ((context.prefixIdentifiers ? `` : `_`) +1614 helperNameMap[context.helper(name)]);1615 },1616 replaceNode(node) {1617 /* istanbul ignore if */1618 {1619 if (!context.currentNode) {1620 throw new Error(`Node being replaced is already removed.`);1621 }1622 if (!context.parent) {1623 throw new Error(`Cannot replace root node.`);1624 }1625 }1626 context.parent.children[context.childIndex] = context.currentNode = node;1627 },1628 removeNode(node) {1629 if ( !context.parent) {1630 throw new Error(`Cannot remove root node.`);1631 }1632 const list = context.parent.children;1633 const removalIndex = node1634 ? list.indexOf(node)1635 : context.currentNode1636 ? context.childIndex1637 : -1;1638 /* istanbul ignore if */1639 if ( removalIndex < 0) {1640 throw new Error(`node being removed is not a child of current parent`);1641 }1642 if (!node || node === context.currentNode) {1643 // current node removed1644 context.currentNode = null;1645 context.onNodeRemoved();1646 }1647 else {1648 // sibling node removed1649 if (context.childIndex > removalIndex) {1650 context.childIndex--;1651 context.onNodeRemoved();1652 }1653 }1654 context.parent.children.splice(removalIndex, 1);1655 },1656 onNodeRemoved: () => { },1657 addIdentifiers(exp) {1658 },1659 removeIdentifiers(exp) {1660 },1661 hoist(exp) {1662 context.hoists.push(exp);1663 return createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, true);1664 },1665 cache(exp, isVNode = false) {1666 return createCacheExpression(++context.cached, exp, isVNode);1667 }1668 };1669 return context;1670 }1671 function transform(root, options) {1672 const context = createTransformContext(root, options);1673 traverseNode(root, context);1674 if (options.hoistStatic) {1675 hoistStatic(root, context);1676 }1677 if (!options.ssr) {1678 createRootCodegen(root, context);1679 }1680 // finalize meta information1681 root.helpers = [...context.helpers];1682 root.components = [...context.components];1683 root.directives = [...context.directives];1684 root.imports = [...context.imports];1685 root.hoists = context.hoists;1686 root.temps = context.temps;1687 root.cached = context.cached;1688 }1689 function createRootCodegen(root, context) {1690 const { helper } = context;1691 const { children } = root;1692 const child = children[0];1693 if (children.length === 1) {1694 // if the single child is an element, turn it into a block.1695 if (isSingleElementRoot(root, child) && child.codegenNode) {1696 // single element root is never hoisted so codegenNode will never be1697 // SimpleExpressionNode1698 const codegenNode = child.codegenNode;1699 if (codegenNode.type === 13 /* VNODE_CALL */) {1700 codegenNode.isBlock = true;1701 helper(OPEN_BLOCK);1702 helper(CREATE_BLOCK);1703 }1704 root.codegenNode = codegenNode;1705 }1706 else {1707 // - single <slot/>, IfNode, ForNode: already blocks.1708 // - single text node: always patched.1709 // root codegen falls through via genNode()1710 root.codegenNode = child;1711 }1712 }1713 else if (children.length > 1) {1714 // root has multiple nodes - return a fragment block.1715 root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, `${64 /* STABLE_FRAGMENT */} /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`, undefined, undefined, true);1716 }1717 }1718 function traverseChildren(parent, context) {1719 let i = 0;1720 const nodeRemoved = () => {1721 i--;1722 };1723 for (; i < parent.children.length; i++) {1724 const child = parent.children[i];1725 if (isString(child))1726 continue;1727 context.currentNode = child;1728 context.parent = parent;1729 context.childIndex = i;1730 context.onNodeRemoved = nodeRemoved;1731 traverseNode(child, context);1732 }1733 }1734 function traverseNode(node, context) {1735 // apply transform plugins1736 const { nodeTransforms } = context;1737 const exitFns = [];1738 for (let i = 0; i < nodeTransforms.length; i++) {1739 const onExit = nodeTransforms[i](node, context);1740 if (onExit) {1741 if (isArray(onExit)) {1742 exitFns.push(...onExit);1743 }1744 else {1745 exitFns.push(onExit);1746 }1747 }1748 if (!context.currentNode) {1749 // node was removed1750 return;1751 }1752 else {1753 // node may have been replaced1754 node = context.currentNode;1755 }1756 }1757 switch (node.type) {1758 case 3 /* COMMENT */:1759 if (!context.ssr) {1760 // inject import for the Comment symbol, which is needed for creating1761 // comment nodes with `createVNode`1762 context.helper(CREATE_COMMENT);1763 }1764 break;1765 case 5 /* INTERPOLATION */:1766 // no need to traverse, but we need to inject toString helper1767 if (!context.ssr) {1768 context.helper(TO_DISPLAY_STRING);1769 }1770 break;1771 // for container types, further traverse downwards1772 case 9 /* IF */:1773 for (let i = 0; i < node.branches.length; i++) {1774 traverseChildren(node.branches[i], context);1775 }1776 break;1777 case 11 /* FOR */:1778 case 1 /* ELEMENT */:1779 case 0 /* ROOT */:1780 traverseChildren(node, context);1781 break;1782 }1783 // exit transforms1784 let i = exitFns.length;1785 while (i--) {1786 exitFns[i]();1787 }1788 }1789 function createStructuralDirectiveTransform(name, fn) {1790 const matches = isString(name)1791 ? (n) => n === name1792 : (n) => name.test(n);1793 return (node, context) => {1794 if (node.type === 1 /* ELEMENT */) {1795 const { props } = node;1796 // structural directive transforms are not concerned with slots1797 // as they are handled separately in vSlot.ts1798 if (node.tagType === 3 /* TEMPLATE */ && props.some(isVSlot)) {1799 return;1800 }1801 const exitFns = [];1802 for (let i = 0; i < props.length; i++) {1803 const prop = props[i];1804 if (prop.type === 7 /* DIRECTIVE */ && matches(prop.name)) {1805 // structural directives are removed to avoid infinite recursion1806 // also we remove them *before* applying so that it can further1807 // traverse itself in case it moves the node around1808 props.splice(i, 1);1809 i--;1810 const onExit = fn(node, prop, context);1811 if (onExit)1812 exitFns.push(onExit);1813 }1814 }1815 return exitFns;1816 }1817 };1818 }1819 function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeBindings = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false }) {1820 const context = {1821 mode,1822 prefixIdentifiers,1823 sourceMap,1824 filename,1825 scopeId,1826 optimizeBindings,1827 runtimeGlobalName,1828 runtimeModuleName,1829 ssr,1830 source: ast.loc.source,1831 code: ``,1832 column: 1,1833 line: 1,1834 offset: 0,1835 indentLevel: 0,1836 map: undefined,1837 helper(key) {1838 return `_${helperNameMap[key]}`;1839 },1840 push(code, node) {1841 context.code += code;1842 },1843 indent() {1844 newline(++context.indentLevel);1845 },1846 deindent(withoutNewLine = false) {1847 if (withoutNewLine) {1848 --context.indentLevel;1849 }1850 else {1851 newline(--context.indentLevel);1852 }1853 },1854 newline() {1855 newline(context.indentLevel);1856 }1857 };1858 function newline(n) {1859 context.push('\n' + ` `.repeat(n));1860 }1861 return context;1862 }1863 function generate(ast, options = {}) {1864 const context = createCodegenContext(ast, options);1865 const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;1866 const hasHelpers = ast.helpers.length > 0;1867 const useWithBlock = !prefixIdentifiers && mode !== 'module';1868 // preambles1869 {1870 genFunctionPreamble(ast, context);1871 }1872 if (!ssr) {1873 push(`function render(_ctx, _cache) {`);1874 }1875 else {1876 push(`function ssrRender(_ctx, _push, _parent) {`);1877 }1878 indent();1879 if (useWithBlock) {1880 push(`with (this) {`);1881 indent();1882 // function mode const declarations should be inside with block1883 // also they should be renamed to avoid collision with user properties1884 if (hasHelpers) {1885 push(`const { ${ast.helpers1886 .map(s => `${helperNameMap[s]}: _${helperNameMap[s]}`)1887 .join(', ')} } = _Vue`);1888 push(`\n`);1889 newline();1890 }1891 }1892 // generate asset resolution statements1893 if (ast.components.length) {1894 genAssets(ast.components, 'component', context);1895 if (ast.directives.length || ast.temps > 0) {1896 newline();1897 }1898 }1899 if (ast.directives.length) {1900 genAssets(ast.directives, 'directive', context);1901 if (ast.temps > 0) {1902 newline();1903 }1904 }1905 if (ast.temps > 0) {1906 push(`let `);1907 for (let i = 0; i < ast.temps; i++) {1908 push(`${i > 0 ? `, ` : ``}_temp${i}`);1909 }1910 }1911 if (ast.components.length || ast.directives.length || ast.temps) {1912 push(`\n`);1913 newline();1914 }1915 // generate the VNode tree expression1916 if (!ssr) {1917 push(`return `);1918 }1919 if (ast.codegenNode) {1920 genNode(ast.codegenNode, context);1921 }1922 else {1923 push(`null`);1924 }1925 if (useWithBlock) {1926 deindent();1927 push(`}`);1928 }1929 deindent();1930 push(`}`);1931 return {1932 ast,1933 code: context.code,1934 // SourceMapGenerator does have toJSON() method but it's not in the types1935 map: context.map ? context.map.toJSON() : undefined1936 };1937 }1938 function genFunctionPreamble(ast, context) {1939 const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName } = context;1940 const VueBinding = runtimeGlobalName;1941 const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;1942 // Generate const declaration for helpers1943 // In prefix mode, we place the const declaration at top so it's done1944 // only once; But if we not prefixing, we place the declaration inside the1945 // with block so it doesn't incur the `in` check cost for every helper access.1946 if (ast.helpers.length > 0) {1947 {1948 // "with" mode.1949 // save Vue in a separate variable to avoid collision1950 push(`const _Vue = ${VueBinding}\n`);1951 // in "with" mode, helpers are declared inside the with block to avoid1952 // has check cost, but hoists are lifted out of the function - we need1953 // to provide the helper here.1954 if (ast.hoists.length) {1955 const staticHelpers = [1956 CREATE_VNODE,1957 CREATE_COMMENT,1958 CREATE_TEXT,1959 CREATE_STATIC1960 ]1961 .filter(helper => ast.helpers.includes(helper))1962 .map(aliasHelper)1963 .join(', ');1964 push(`const { ${staticHelpers} } = _Vue\n`);1965 }1966 }1967 }1968 genHoists(ast.hoists, context);1969 newline();1970 push(`return `);1971 }1972 function genAssets(assets, type, { helper, push, newline }) {1973 const resolver = helper(type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE);1974 for (let i = 0; i < assets.length; i++) {1975 const id = assets[i];1976 push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)})`);1977 if (i < assets.length - 1) {1978 newline();1979 }1980 }1981 }1982 function genHoists(hoists, context) {1983 if (!hoists.length) {1984 return;1985 }1986 const { push, newline, helper, scopeId, mode } = context;1987 newline();1988 hoists.forEach((exp, i) => {1989 push(`const _hoisted_${i + 1} = `);1990 genNode(exp, context);1991 newline();1992 });1993 }1994 function isText$1(n) {1995 return (isString(n) ||1996 n.type === 4 /* SIMPLE_EXPRESSION */ ||1997 n.type === 2 /* TEXT */ ||1998 n.type === 5 /* INTERPOLATION */ ||1999 n.type === 8 /* COMPOUND_EXPRESSION */);2000 }2001 function genNodeListAsArray(nodes, context) {2002 const multilines = nodes.length > 3 ||2003 ( nodes.some(n => isArray(n) || !isText$1(n)));2004 context.push(`[`);2005 multilines && context.indent();2006 genNodeList(nodes, context, multilines);2007 multilines && context.deindent();2008 context.push(`]`);2009 }2010 function genNodeList(nodes, context, multilines = false, comma = true) {2011 const { push, newline } = context;2012 for (let i = 0; i < nodes.length; i++) {2013 const node = nodes[i];2014 if (isString(node)) {2015 push(node);2016 }2017 else if (isArray(node)) {2018 genNodeListAsArray(node, context);2019 }2020 else {2021 genNode(node, context);2022 }2023 if (i < nodes.length - 1) {2024 if (multilines) {2025 comma && push(',');2026 newline();2027 }2028 else {2029 comma && push(', ');2030 }2031 }2032 }2033 }2034 function genNode(node, context) {2035 if (isString(node)) {2036 context.push(node);2037 return;2038 }2039 if (isSymbol(node)) {2040 context.push(context.helper(node));2041 return;2042 }2043 switch (node.type) {2044 case 1 /* ELEMENT */:2045 case 9 /* IF */:2046 case 11 /* FOR */:2047 2048 assert(node.codegenNode != null, `Codegen node is missing for element/if/for node. ` +2049 `Apply appropriate transforms first.`);2050 genNode(node.codegenNode, context);2051 break;2052 case 2 /* TEXT */:2053 genText(node, context);2054 break;2055 case 4 /* SIMPLE_EXPRESSION */:2056 genExpression(node, context);2057 break;2058 case 5 /* INTERPOLATION */:2059 genInterpolation(node, context);2060 break;2061 case 12 /* TEXT_CALL */:2062 genNode(node.codegenNode, context);2063 break;2064 case 8 /* COMPOUND_EXPRESSION */:2065 genCompoundExpression(node, context);2066 break;2067 case 3 /* COMMENT */:2068 genComment(node, context);2069 break;2070 case 13 /* VNODE_CALL */:2071 genVNodeCall(node, context);2072 break;2073 case 14 /* JS_CALL_EXPRESSION */:2074 genCallExpression(node, context);2075 break;2076 case 15 /* JS_OBJECT_EXPRESSION */:2077 genObjectExpression(node, context);2078 break;2079 case 17 /* JS_ARRAY_EXPRESSION */:2080 genArrayExpression(node, context);2081 break;2082 case 18 /* JS_FUNCTION_EXPRESSION */:2083 genFunctionExpression(node, context);2084 break;2085 case 19 /* JS_CONDITIONAL_EXPRESSION */:2086 genConditionalExpression(node, context);2087 break;2088 case 20 /* JS_CACHE_EXPRESSION */:2089 genCacheExpression(node, context);2090 break;2091 // SSR only types2092 case 21 /* JS_BLOCK_STATEMENT */:2093 break;2094 case 22 /* JS_TEMPLATE_LITERAL */:2095 break;2096 case 23 /* JS_IF_STATEMENT */:2097 break;2098 case 24 /* JS_ASSIGNMENT_EXPRESSION */:2099 break;2100 case 25 /* JS_RETURN_STATEMENT */:2101 break;2102 /* istanbul ignore next */2103 default:2104 {2105 assert(false, `unhandled codegen node type: ${node.type}`);2106 // make sure we exhaust all possible types2107 const exhaustiveCheck = node;2108 return exhaustiveCheck;2109 }2110 }2111 }2112 function genText(node, context) {2113 context.push(JSON.stringify(node.content), node);2114 }2115 function genExpression(node, context) {2116 const { content, isStatic } = node;2117 context.push(isStatic ? JSON.stringify(content) : content, node);2118 }2119 function genInterpolation(node, context) {2120 const { push, helper } = context;2121 push(`${helper(TO_DISPLAY_STRING)}(`);2122 genNode(node.content, context);2123 push(`)`);2124 }2125 function genCompoundExpression(node, context) {2126 for (let i = 0; i < node.children.length; i++) {2127 const child = node.children[i];2128 if (isString(child)) {2129 context.push(child);2130 }2131 else {2132 genNode(child, context);2133 }2134 }2135 }2136 function genExpressionAsPropertyKey(node, context) {2137 const { push } = context;2138 if (node.type === 8 /* COMPOUND_EXPRESSION */) {2139 push(`[`);2140 genCompoundExpression(node, context);2141 push(`]`);2142 }2143 else if (node.isStatic) {2144 // only quote keys if necessary2145 const text = isSimpleIdentifier(node.content)2146 ? node.content2147 : JSON.stringify(node.content);2148 push(text, node);2149 }2150 else {2151 push(`[${node.content}]`, node);2152 }2153 }2154 function genComment(node, context) {2155 {2156 const { push, helper } = context;2157 push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);2158 }2159 }2160 function genVNodeCall(node, context) {2161 const { push, helper } = context;2162 const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, isForBlock } = node;2163 if (directives) {2164 push(helper(WITH_DIRECTIVES) + `(`);2165 }2166 if (isBlock) {2167 push(`(${helper(OPEN_BLOCK)}(${isForBlock ? `true` : ``}), `);2168 }2169 push(helper(isBlock ? CREATE_BLOCK : CREATE_VNODE) + `(`, node);2170 genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);2171 push(`)`);2172 if (isBlock) {2173 push(`)`);2174 }2175 if (directives) {2176 push(`, `);2177 genNode(directives, context);2178 push(`)`);2179 }2180 }2181 function genNullableArgs(args) {2182 let i = args.length;2183 while (i--) {2184 if (args[i] != null)2185 break;2186 }2187 return args.slice(0, i + 1).map(arg => arg || `null`);2188 }2189 // JavaScript2190 function genCallExpression(node, context) {2191 const callee = isString(node.callee)2192 ? node.callee2193 : context.helper(node.callee);2194 context.push(callee + `(`, node);2195 genNodeList(node.arguments, context);2196 context.push(`)`);2197 }2198 function genObjectExpression(node, context) {2199 const { push, indent, deindent, newline } = context;2200 const { properties } = node;2201 if (!properties.length) {2202 push(`{}`, node);2203 return;2204 }2205 const multilines = properties.length > 1 ||2206 (2207 properties.some(p => p.value.type !== 4 /* SIMPLE_EXPRESSION */));2208 push(multilines ? `{` : `{ `);2209 multilines && indent();2210 for (let i = 0; i < properties.length; i++) {2211 const { key, value } = properties[i];2212 // key2213 genExpressionAsPropertyKey(key, context);2214 push(`: `);2215 // value2216 genNode(value, context);2217 if (i < properties.length - 1) {2218 // will only reach this if it's multilines2219 push(`,`);2220 newline();2221 }2222 }2223 multilines && deindent();2224 push(multilines ? `}` : ` }`);2225 }2226 function genArrayExpression(node, context) {2227 genNodeListAsArray(node.elements, context);2228 }2229 function genFunctionExpression(node, context) {2230 const { push, indent, deindent, scopeId, mode } = context;2231 const { params, returns, body, newline, isSlot } = node;2232 push(`(`, node);2233 if (isArray(params)) {2234 genNodeList(params, context);2235 }2236 else if (params) {2237 genNode(params, context);2238 }2239 push(`) => `);2240 if (newline || body) {2241 push(`{`);2242 indent();2243 }2244 if (returns) {2245 if (newline) {2246 push(`return `);2247 }2248 if (isArray(returns)) {2249 genNodeListAsArray(returns, context);2250 }2251 else {2252 genNode(returns, context);2253 }2254 }2255 else if (body) {2256 genNode(body, context);2257 }2258 if (newline || body) {2259 deindent();2260 push(`}`);2261 }2262 }2263 function genConditionalExpression(node, context) {2264 const { test, consequent, alternate, newline: needNewline } = node;2265 const { push, indent, deindent, newline } = context;2266 if (test.type === 4 /* SIMPLE_EXPRESSION */) {2267 const needsParens = !isSimpleIdentifier(test.content);2268 needsParens && push(`(`);2269 genExpression(test, context);2270 needsParens && push(`)`);2271 }2272 else {2273 push(`(`);2274 genNode(test, context);2275 push(`)`);2276 }2277 needNewline && indent();2278 context.indentLevel++;2279 needNewline || push(` `);2280 push(`? `);2281 genNode(consequent, context);2282 context.indentLevel--;2283 needNewline && newline();2284 needNewline || push(` `);2285 push(`: `);2286 const isNested = alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */;2287 if (!isNested) {2288 context.indentLevel++;2289 }2290 genNode(alternate, context);2291 if (!isNested) {2292 context.indentLevel--;2293 }2294 needNewline && deindent(true /* without newline */);2295 }2296 function genCacheExpression(node, context) {2297 const { push, helper, indent, deindent, newline } = context;2298 push(`_cache[${node.index}] || (`);2299 if (node.isVNode) {2300 indent();2301 push(`${helper(SET_BLOCK_TRACKING)}(-1),`);2302 newline();2303 }2304 push(`_cache[${node.index}] = `);2305 genNode(node.value, context);2306 if (node.isVNode) {2307 push(`,`);2308 newline();2309 push(`${helper(SET_BLOCK_TRACKING)}(1),`);2310 newline();2311 push(`_cache[${node.index}]`);2312 deindent();2313 }2314 push(`)`);2315 }2316 const isLiteralWhitelisted = /*#__PURE__*/ makeMap('true,false,null,this');2317 const transformExpression = (node, context) => {2318 if (node.type === 5 /* INTERPOLATION */) {2319 node.content = processExpression(node.content, context);2320 }2321 else if (node.type === 1 /* ELEMENT */) {2322 // handle directives on element2323 for (let i = 0; i < node.props.length; i++) {2324 const dir = node.props[i];2325 // do not process for v-on & v-for since they are special handled2326 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {2327 const exp = dir.exp;2328 const arg = dir.arg;2329 // do not process exp if this is v-on:arg - we need special handling2330 // for wrapping inline statements.2331 if (exp &&2332 exp.type === 4 /* SIMPLE_EXPRESSION */ &&2333 !(dir.name === 'on' && arg)) {2334 dir.exp = processExpression(exp, context, 2335 // slot args must be processed as function params2336 dir.name === 'slot');2337 }2338 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {2339 dir.arg = processExpression(arg, context);2340 }2341 }2342 }2343 }2344 };2345 // Important: since this function uses Node.js only dependencies, it should2346 // always be used with a leading !true check so that it can be2347 // tree-shaken from the browser build.2348 function processExpression(node, context, 2349 // some expressions like v-slot props & v-for aliases should be parsed as2350 // function params2351 asParams = false, 2352 // v-on handler values may contain multiple statements2353 asRawStatements = false) {2354 if (!context.prefixIdentifiers || !node.content.trim()) {2355 return node;2356 }2357 // fast path if expression is a simple identifier.2358 const rawExp = node.content;2359 // bail on parens to prevent any possible function invocations.2360 const bailConstant = rawExp.indexOf(`(`) > -1;2361 if (isSimpleIdentifier(rawExp)) {2362 if (!asParams &&2363 !context.identifiers[rawExp] &&2364 !isGloballyWhitelisted(rawExp) &&2365 !isLiteralWhitelisted(rawExp)) {2366 node.content = `_ctx.${rawExp}`;2367 }2368 else if (!context.identifiers[rawExp] && !bailConstant) {2369 // mark node constant for hoisting unless it's referring a scope variable2370 node.isConstant = true;2371 }2372 return node;2373 }2374 let ast;2375 // exp needs to be parsed differently:2376 // 1. Multiple inline statements (v-on, with presence of `;`): parse as raw2377 // exp, but make sure to pad with spaces for consistent ranges2378 // 2. Expressions: wrap with parens (for e.g. object expressions)2379 // 3. Function arguments (v-for, v-slot): place in a function argument position2380 const source = asRawStatements2381 ? ` ${rawExp} `2382 : `(${rawExp})${asParams ? `=>{}` : ``}`;2383 try {2384 ast = parseJS(source, { ranges: true });2385 }2386 catch (e) {2387 context.onError(createCompilerError(49 /* X_INVALID_EXPRESSION */, node.loc));2388 return node;2389 }2390 const ids = [];2391 const knownIds = Object.create(context.identifiers);2392 // walk the AST and look for identifiers that need to be prefixed with `_ctx.`.2393 walkJS(ast, {2394 enter(node, parent) {2395 if (node.type === 'Identifier') {2396 if (!ids.includes(node)) {2397 const needPrefix = shouldPrefix(node, parent);2398 if (!knownIds[node.name] && needPrefix) {2399 if (isPropertyShorthand(node, parent)) {2400 // property shorthand like { foo }, we need to add the key since we2401 // rewrite the value2402 node.prefix = `${node.name}: `;2403 }2404 node.name = `_ctx.${node.name}`;2405 ids.push(node);2406 }2407 else if (!isStaticPropertyKey(node, parent)) {2408 // The identifier is considered constant unless it's pointing to a2409 // scope variable (a v-for alias, or a v-slot prop)2410 if (!(needPrefix && knownIds[node.name]) && !bailConstant) {2411 node.isConstant = true;2412 }2413 // also generate sub-expressions for other identifiers for better2414 // source map support. (except for property keys which are static)2415 ids.push(node);2416 }2417 }2418 }2419 else if (isFunction(node)) {2420 // walk function expressions and add its arguments to known identifiers2421 // so that we don't prefix them2422 node.params.forEach(p => walkJS(p, {2423 enter(child, parent) {2424 if (child.type === 'Identifier' &&2425 // do not record as scope variable if is a destructured key2426 !isStaticPropertyKey(child, parent) &&2427 // do not record if this is a default value2428 // assignment of a destructured variable2429 !(parent &&2430 parent.type === 'AssignmentPattern' &&2431 parent.right === child)) {2432 const { name } = child;2433 if (node.scopeIds && node.scopeIds.has(name)) {2434 return;2435 }2436 if (name in knownIds) {2437 knownIds[name]++;2438 }2439 else {2440 knownIds[name] = 1;2441 }2442 (node.scopeIds || (node.scopeIds = new Set())).add(name);2443 }2444 }2445 }));2446 }2447 },2448 leave(node) {2449 if (node !== ast.body[0].expression && node.scopeIds) {2450 node.scopeIds.forEach((id) => {2451 knownIds[id]--;2452 if (knownIds[id] === 0) {2453 delete knownIds[id];2454 }2455 });2456 }2457 }2458 });2459 // We break up the compound expression into an array of strings and sub2460 // expressions (for identifiers that have been prefixed). In codegen, if2461 // an ExpressionNode has the `.children` property, it will be used instead of2462 // `.content`.2463 const children = [];2464 ids.sort((a, b) => a.start - b.start);2465 ids.forEach((id, i) => {2466 // range is offset by -1 due to the wrapping parens when parsed2467 const start = id.start - 1;2468 const end = id.end - 1;2469 const last = ids[i - 1];2470 const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);2471 if (leadingText.length || id.prefix) {2472 children.push(leadingText + (id.prefix || ``));2473 }2474 const source = rawExp.slice(start, end);2475 children.push(createSimpleExpression(id.name, false, {2476 source,2477 start: advancePositionWithClone(node.loc.start, source, start),2478 end: advancePositionWithClone(node.loc.start, source, end)2479 }, id.isConstant /* isConstant */));2480 if (i === ids.length - 1 && end < rawExp.length) {2481 children.push(rawExp.slice(end));2482 }2483 });2484 let ret;2485 if (children.length) {2486 ret = createCompoundExpression(children, node.loc);2487 }2488 else {2489 ret = node;2490 ret.isConstant = !bailConstant;2491 }2492 ret.identifiers = Object.keys(knownIds);2493 return ret;2494 }2495 const isFunction = (node) => /Function(Expression|Declaration)$/.test(node.type);2496 const isPropertyKey = (node, parent) => parent &&2497 parent.type === 'Property' &&2498 parent.key === node &&2499 !parent.computed;2500 const isPropertyShorthand = (node, parent) => isPropertyKey(node, parent) && parent.value === node;2501 const isStaticPropertyKey = (node, parent) => isPropertyKey(node, parent) && parent.value !== node;2502 function shouldPrefix(identifier, parent) {2503 if (!(isFunction(parent) &&2504 // not id of a FunctionDeclaration2505 (parent.id === identifier ||2506 // not a params of a function2507 parent.params.includes(identifier))) &&2508 // not a key of Property2509 !isStaticPropertyKey(identifier, parent) &&2510 // not a property of a MemberExpression2511 !(parent.type === 'MemberExpression' &&2512 parent.property === identifier &&2513 !parent.computed) &&2514 // not in an Array destructure pattern2515 !(parent.type === 'ArrayPattern') &&2516 // skip whitelisted globals2517 !isGloballyWhitelisted(identifier.name) &&2518 // special case for webpack compilation2519 identifier.name !== `require` &&2520 // is a special keyword but parsed as identifier2521 identifier.name !== `arguments`) {2522 return true;2523 }2524 }2525 const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {2526 return processIf(node, dir, context, (ifNode, branch, isRoot) => {2527 // Exit callback. Complete the codegenNode when all children have been2528 // transformed.2529 return () => {2530 if (isRoot) {2531 ifNode.codegenNode = createCodegenNodeForBranch(branch, 0, context);2532 }2533 else {2534 // attach this branch's codegen node to the v-if root.2535 let parentCondition = ifNode.codegenNode;2536 while (parentCondition.alternate.type ===2537 19 /* JS_CONDITIONAL_EXPRESSION */) {2538 parentCondition = parentCondition.alternate;2539 }2540 parentCondition.alternate = createCodegenNodeForBranch(branch, ifNode.branches.length - 1, context);2541 }2542 };2543 });2544 });2545 // target-agnostic transform used for both Client and SSR2546 function processIf(node, dir, context, processCodegen) {2547 if (dir.name !== 'else' &&2548 (!dir.exp || !dir.exp.content.trim())) {2549 const loc = dir.exp ? dir.exp.loc : node.loc;2550 context.onError(createCompilerError(34 /* X_V_IF_NO_EXPRESSION */, dir.loc));2551 dir.exp = createSimpleExpression(`true`, false, loc);2552 }2553 if (dir.name === 'if') {2554 const branch = createIfBranch(node, dir);2555 const ifNode = {2556 type: 9 /* IF */,2557 loc: node.loc,2558 branches: [branch]2559 };2560 context.replaceNode(ifNode);2561 if (processCodegen) {2562 return processCodegen(ifNode, branch, true);2563 }2564 }2565 else {2566 // locate the adjacent v-if2567 const siblings = context.parent.children;2568 const comments = [];2569 let i = siblings.indexOf(node);2570 while (i-- >= -1) {2571 const sibling = siblings[i];2572 if ( sibling && sibling.type === 3 /* COMMENT */) {2573 context.removeNode(sibling);2574 comments.unshift(sibling);2575 continue;2576 }2577 if (sibling && sibling.type === 9 /* IF */) {2578 // move the node to the if node's branches2579 context.removeNode();2580 const branch = createIfBranch(node, dir);2581 if ( comments.length) {2582 branch.children = [...comments, ...branch.children];2583 }2584 sibling.branches.push(branch);2585 const onExit = processCodegen && processCodegen(sibling, branch, false);2586 // since the branch was removed, it will not be traversed.2587 // make sure to traverse here.2588 traverseChildren(branch, context);2589 // call on exit2590 if (onExit)2591 onExit();2592 // make sure to reset currentNode after traversal to indicate this2593 // node has been removed.2594 context.currentNode = null;2595 }2596 else {2597 context.onError(createCompilerError(35 /* X_V_ELSE_NO_ADJACENT_IF */, node.loc));2598 }2599 break;2600 }2601 }2602 }2603 function createIfBranch(node, dir) {2604 return {2605 type: 10 /* IF_BRANCH */,2606 loc: node.loc,2607 condition: dir.name === 'else' ? undefined : dir.exp,2608 children: node.tagType === 3 /* TEMPLATE */ ? node.children : [node]2609 };2610 }2611 function createCodegenNodeForBranch(branch, index, context) {2612 if (branch.condition) {2613 return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, index, context), 2614 // make sure to pass in asBlock: true so that the comment node call2615 // closes the current block.2616 createCallExpression(context.helper(CREATE_COMMENT), [2617 '"v-if"' ,2618 'true'2619 ]));2620 }2621 else {2622 return createChildrenCodegenNode(branch, index, context);2623 }2624 }2625 function createChildrenCodegenNode(branch, index, context) {2626 const { helper } = context;2627 const keyProperty = createObjectProperty(`key`, createSimpleExpression(index + '', false));2628 const { children } = branch;2629 const firstChild = children[0];2630 const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* ELEMENT */;2631 if (needFragmentWrapper) {2632 if (children.length === 1 && firstChild.type === 11 /* FOR */) {2633 // optimize away nested fragments when child is a ForNode2634 const vnodeCall = firstChild.codegenNode;2635 injectProp(vnodeCall, keyProperty, context);2636 return vnodeCall;2637 }2638 else {2639 return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, undefined, undefined, undefined, true, false, branch.loc);2640 }2641 }2642 else {2643 const vnodeCall = firstChild2644 .codegenNode;2645 // Change createVNode to createBlock.2646 if (vnodeCall.type === 13 /* VNODE_CALL */) {2647 vnodeCall.isBlock = true;2648 helper(OPEN_BLOCK);2649 helper(CREATE_BLOCK);2650 }2651 // inject branch key2652 injectProp(vnodeCall, keyProperty, context);2653 return vnodeCall;2654 }2655 }2656 const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {2657 const { helper } = context;2658 return processFor(node, dir, context, forNode => {2659 // create the loop render function expression now, and add the2660 // iterator on exit after all children have been traversed2661 const renderExp = createCallExpression(helper(RENDER_LIST), [2662 forNode.source2663 ]);2664 const keyProp = findProp(node, `key`);2665 const fragmentFlag = keyProp2666 ? 128 /* KEYED_FRAGMENT */2667 : 256 /* UNKEYED_FRAGMENT */;2668 forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, `${fragmentFlag} /* ${PatchFlagNames[fragmentFlag]} */`, undefined, undefined, true /* isBlock */, true /* isForBlock */, node.loc);2669 return () => {2670 // finish the codegen now that all children have been traversed2671 let childBlock;2672 const isTemplate = isTemplateNode(node);2673 const { children } = forNode;2674 const needFragmentWrapper = children.length > 1 || children[0].type !== 1 /* ELEMENT */;2675 const slotOutlet = isSlotOutlet(node)2676 ? node2677 : isTemplate &&2678 node.children.length === 1 &&2679 isSlotOutlet(node.children[0])2680 ? node.children[0] // api-extractor somehow fails to infer this2681 : null;2682 const keyProperty = keyProp2683 ? createObjectProperty(`key`, keyProp.type === 6 /* ATTRIBUTE */2684 ? createSimpleExpression(keyProp.value.content, true)2685 : keyProp.exp)2686 : null;2687 if (slotOutlet) {2688 // <slot v-for="..."> or <template v-for="..."><slot/></template>2689 childBlock = slotOutlet.codegenNode;2690 if (isTemplate && keyProperty) {2691 // <template v-for="..." :key="..."><slot/></template>2692 // we need to inject the key to the renderSlot() call.2693 // the props for renderSlot is passed as the 3rd argument.2694 injectProp(childBlock, keyProperty, context);2695 }2696 }2697 else if (needFragmentWrapper) {2698 // <template v-for="..."> with text or multi-elements2699 // should generate a fragment block for each loop2700 childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, `${64 /* STABLE_FRAGMENT */} /* ${PatchFlagNames[64 /* STABLE_FRAGMENT */]} */`, undefined, undefined, true);2701 }2702 else {2703 // Normal element v-for. Directly use the child's codegenNode2704 // but mark it as a block.2705 childBlock = children[0]2706 .codegenNode;2707 childBlock.isBlock = true;2708 helper(OPEN_BLOCK);2709 helper(CREATE_BLOCK);2710 }2711 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));2712 };2713 });2714 });2715 // target-agnostic transform used for both Client and SSR2716 function processFor(node, dir, context, processCodegen) {2717 if (!dir.exp) {2718 context.onError(createCompilerError(36 /* X_V_FOR_NO_EXPRESSION */, dir.loc));2719 return;2720 }2721 const parseResult = parseForExpression(2722 // can only be simple expression because vFor transform is applied2723 // before expression transform.2724 dir.exp);2725 if (!parseResult) {2726 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));2727 return;2728 }2729 const { addIdentifiers, removeIdentifiers, scopes } = context;2730 const { source, value, key, index } = parseResult;2731 const forNode = {2732 type: 11 /* FOR */,2733 loc: dir.loc,2734 source,2735 valueAlias: value,2736 keyAlias: key,2737 objectIndexAlias: index,2738 parseResult,2739 children: node.tagType === 3 /* TEMPLATE */ ? node.children : [node]2740 };2741 context.replaceNode(forNode);2742 // bookkeeping2743 scopes.vFor++;2744 const onExit = processCodegen && processCodegen(forNode);2745 return () => {2746 scopes.vFor--;2747 if (onExit)2748 onExit();2749 };2750 }2751 const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;2752 // This regex doesn't cover the case if key or index aliases have destructuring,2753 // but those do not make sense in the first place, so this works in practice.2754 const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;2755 const stripParensRE = /^\(|\)$/g;2756 function parseForExpression(input, context) {2757 const loc = input.loc;2758 const exp = input.content;2759 const inMatch = exp.match(forAliasRE);2760 if (!inMatch)2761 return;2762 const [, LHS, RHS] = inMatch;2763 const result = {2764 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),2765 value: undefined,2766 key: undefined,2767 index: undefined2768 };2769 let valueContent = LHS.trim()2770 .replace(stripParensRE, '')2771 .trim();2772 const trimmedOffset = LHS.indexOf(valueContent);2773 const iteratorMatch = valueContent.match(forIteratorRE);2774 if (iteratorMatch) {2775 valueContent = valueContent.replace(forIteratorRE, '').trim();2776 const keyContent = iteratorMatch[1].trim();2777 let keyOffset;2778 if (keyContent) {2779 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);2780 result.key = createAliasExpression(loc, keyContent, keyOffset);2781 }2782 if (iteratorMatch[2]) {2783 const indexContent = iteratorMatch[2].trim();2784 if (indexContent) {2785 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key2786 ? keyOffset + keyContent.length2787 : trimmedOffset + valueContent.length));2788 }2789 }2790 }2791 if (valueContent) {2792 result.value = createAliasExpression(loc, valueContent, trimmedOffset);2793 }2794 return result;2795 }2796 function createAliasExpression(range, content, offset) {2797 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));2798 }2799 function createForLoopParams({ value, key, index }) {2800 const params = [];2801 if (value) {2802 params.push(value);2803 }2804 if (key) {2805 if (!value) {2806 params.push(createSimpleExpression(`_`, false));2807 }2808 params.push(key);2809 }2810 if (index) {2811 if (!key) {2812 if (!value) {2813 params.push(createSimpleExpression(`_`, false));2814 }2815 params.push(createSimpleExpression(`__`, false));2816 }2817 params.push(index);2818 }2819 return params;2820 }2821 const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic;2822 const defaultFallback = createSimpleExpression(`undefined`, false);2823 // A NodeTransform that:2824 // 1. Tracks scope identifiers for scoped slots so that they don't get prefixed2825 // by transformExpression. This is only applied in non-browser builds with2826 // { prefixIdentifiers: true }.2827 // 2. Track v-slot depths so that we know a slot is inside another slot.2828 // Note the exit callback is executed before buildSlots() on the same node,2829 // so only nested slots see positive numbers.2830 const trackSlotScopes = (node, context) => {2831 if (node.type === 1 /* ELEMENT */ &&2832 (node.tagType === 1 /* COMPONENT */ ||2833 node.tagType === 3 /* TEMPLATE */)) {2834 // We are only checking non-empty v-slot here2835 // since we only care about slots that introduce scope variables.2836 const vSlot = findDir(node, 'slot');2837 if (vSlot) {2838 const slotProps = vSlot.exp;2839 context.scopes.vSlot++;2840 return () => {2841 context.scopes.vSlot--;2842 };2843 }2844 }2845 };2846 // A NodeTransform that tracks scope identifiers for scoped slots with v-for.2847 // This transform is only applied in non-browser builds with { prefixIdentifiers: true }2848 const trackVForSlotScopes = (node, context) => {2849 let vFor;2850 if (isTemplateNode(node) &&2851 node.props.some(isVSlot) &&2852 (vFor = findDir(node, 'for'))) {2853 const result = (vFor.parseResult = parseForExpression(vFor.exp));2854 if (result) {2855 const { value, key, index } = result;2856 const { addIdentifiers, removeIdentifiers } = context;2857 value && addIdentifiers(value);2858 key && addIdentifiers(key);2859 index && addIdentifiers(index);2860 return () => {2861 value && removeIdentifiers(value);2862 key && removeIdentifiers(key);2863 index && removeIdentifiers(index);2864 };2865 }2866 }2867 };2868 const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);2869 // Instead of being a DirectiveTransform, v-slot processing is called during2870 // transformElement to build the slots object for a component.2871 function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {2872 const { children, loc } = node;2873 const slotsProperties = [];2874 const dynamicSlots = [];2875 const buildDefaultSlotProperty = (props, children) => createObjectProperty(`default`, buildSlotFn(props, children, loc));2876 // If the slot is inside a v-for or another v-slot, force it to be dynamic2877 // since it likely uses a scope variable.2878 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;2879 // 1. Check for default slot with slotProps on component itself.2880 // <Comp v-slot="{ prop }"/>2881 const onComponentDefaultSlot = findDir(node, 'slot', true);2882 if (onComponentDefaultSlot) {2883 const { arg, exp, loc } = onComponentDefaultSlot;2884 if (arg) {2885 context.onError(createCompilerError(41 /* X_V_SLOT_NAMED_SLOT_ON_COMPONENT */, loc));2886 }2887 slotsProperties.push(buildDefaultSlotProperty(exp, children));2888 }2889 // 2. Iterate through children and check for template slots2890 // <template v-slot:foo="{ prop }">2891 let hasTemplateSlots = false;2892 let hasNamedDefaultSlot = false;2893 const implicitDefaultChildren = [];2894 const seenSlotNames = new Set();2895 for (let i = 0; i < children.length; i++) {2896 const slotElement = children[i];2897 let slotDir;2898 if (!isTemplateNode(slotElement) ||2899 !(slotDir = findDir(slotElement, 'slot', true))) {2900 // not a <template v-slot>, skip.2901 if (slotElement.type !== 3 /* COMMENT */) {2902 implicitDefaultChildren.push(slotElement);2903 }2904 continue;2905 }2906 if (onComponentDefaultSlot) {2907 // already has on-component default slot - this is incorrect usage.2908 context.onError(createCompilerError(42 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));2909 break;2910 }2911 hasTemplateSlots = true;2912 const { children: slotChildren, loc: slotLoc } = slotElement;2913 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;2914 // check if name is dynamic.2915 let staticSlotName;2916 if (isStaticExp(slotName)) {2917 staticSlotName = slotName ? slotName.content : `default`;2918 }2919 else {2920 hasDynamicSlots = true;2921 }2922 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);2923 // check if this slot is conditional (v-if/v-for)2924 let vIf;2925 let vElse;2926 let vFor;2927 if ((vIf = findDir(slotElement, 'if'))) {2928 hasDynamicSlots = true;2929 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));2930 }2931 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {2932 // find adjacent v-if2933 let j = i;2934 let prev;2935 while (j--) {2936 prev = children[j];2937 if (prev.type !== 3 /* COMMENT */) {2938 break;2939 }2940 }2941 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {2942 // remove node2943 children.splice(i, 1);2944 i--;2945 // attach this slot to previous conditional2946 let conditional = dynamicSlots[dynamicSlots.length - 1];2947 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {2948 conditional = conditional.alternate;2949 }2950 conditional.alternate = vElse.exp2951 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)2952 : buildDynamicSlot(slotName, slotFunction);2953 }2954 else {2955 context.onError(createCompilerError(35 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));2956 }2957 }2958 else if ((vFor = findDir(slotElement, 'for'))) {2959 hasDynamicSlots = true;2960 const parseResult = vFor.parseResult ||2961 parseForExpression(vFor.exp);2962 if (parseResult) {2963 // Render the dynamic slots as an array and add it to the createSlot()2964 // args. The runtime knows how to handle it appropriately.2965 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [2966 parseResult.source,2967 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)2968 ]));2969 }2970 else {2971 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));2972 }2973 }2974 else {2975 // check duplicate static names2976 if (staticSlotName) {2977 if (seenSlotNames.has(staticSlotName)) {2978 context.onError(createCompilerError(43 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));2979 continue;2980 }2981 seenSlotNames.add(staticSlotName);2982 if (staticSlotName === 'default') {2983 hasNamedDefaultSlot = true;2984 }2985 }2986 slotsProperties.push(createObjectProperty(slotName, slotFunction));2987 }2988 }2989 if (!onComponentDefaultSlot) {2990 if (!hasTemplateSlots) {2991 // implicit default slot (on component)2992 slotsProperties.push(buildDefaultSlotProperty(undefined, children));2993 }2994 else if (implicitDefaultChildren.length) {2995 // implicit default slot (mixed with named slots)2996 if (hasNamedDefaultSlot) {2997 context.onError(createCompilerError(44 /* X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));2998 }2999 else {3000 slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));3001 }3002 }3003 }3004 let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`, createSimpleExpression(`1`, false))), loc);3005 if (dynamicSlots.length) {3006 slots = createCallExpression(context.helper(CREATE_SLOTS), [3007 slots,3008 createArrayExpression(dynamicSlots)3009 ]);3010 }3011 return {3012 slots,3013 hasDynamicSlots3014 };3015 }3016 function buildDynamicSlot(name, fn) {3017 return createObjectExpression([3018 createObjectProperty(`name`, name),3019 createObjectProperty(`fn`, fn)3020 ]);3021 }3022 // some directive transforms (e.g. v-model) may return a symbol for runtime3023 // import, which should be used instead of a resolveDirective call.3024 const directiveImportMap = new WeakMap();3025 // generate a JavaScript AST for this element's codegen3026 const transformElement = (node, context) => {3027 if (!(node.type === 1 /* ELEMENT */ &&3028 (node.tagType === 0 /* ELEMENT */ ||3029 node.tagType === 1 /* COMPONENT */))) {3030 return;3031 }3032 // perform the work on exit, after all child expressions have been3033 // processed and merged.3034 return function postTransformElement() {3035 const { tag, props } = node;3036 const isComponent = node.tagType === 1 /* COMPONENT */;3037 // The goal of the transform is to create a codegenNode implementing the3038 // VNodeCall interface.3039 const vnodeTag = isComponent3040 ? resolveComponentType(node, context)3041 : `"${tag}"`;3042 let vnodeProps;3043 let vnodeChildren;3044 let vnodePatchFlag;3045 let patchFlag = 0;3046 let vnodeDynamicProps;3047 let dynamicPropNames;3048 let vnodeDirectives;3049 // <svg> and <foreignObject> must be forced into blocks so that block3050 // updates inside get proper isSVG flag at runtime. (#639, #643)3051 // This is technically web-specific, but splitting the logic out of core3052 // leads to too much unnecessary complexity.3053 let shouldUseBlock = !isComponent && (tag === 'svg' || tag === 'foreignObject');3054 // props3055 if (props.length > 0) {3056 const propsBuildResult = buildProps(node, context);3057 vnodeProps = propsBuildResult.props;3058 patchFlag = propsBuildResult.patchFlag;3059 dynamicPropNames = propsBuildResult.dynamicPropNames;3060 const directives = propsBuildResult.directives;3061 vnodeDirectives =3062 directives && directives.length3063 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))3064 : undefined;3065 }3066 // children3067 if (node.children.length > 0) {3068 if (vnodeTag === KEEP_ALIVE) {3069 // Although a built-in component, we compile KeepAlive with raw children3070 // instead of slot functions so that it can be used inside Transition3071 // or other Transition-wrapping HOCs.3072 // To ensure correct updates with block optimizations, we need to:3073 // 1. Force keep-alive into a block. This avoids its children being3074 // collected by a parent block.3075 shouldUseBlock = true;3076 // 2. Force keep-alive to always be updated, since it uses raw children.3077 patchFlag |= 512 /* DYNAMIC_SLOTS */;3078 if ( node.children.length > 1) {3079 context.onError(createCompilerError(50 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {3080 start: node.children[0].loc.start,3081 end: node.children[node.children.length - 1].loc.end,3082 source: ''3083 }));3084 }3085 }3086 const shouldBuildAsSlots = isComponent &&3087 // Portal is not a real component has dedicated handling in the renderer3088 vnodeTag !== PORTAL &&3089 // explained above.3090 vnodeTag !== KEEP_ALIVE;3091 if (shouldBuildAsSlots) {3092 const { slots, hasDynamicSlots } = buildSlots(node, context);3093 vnodeChildren = slots;3094 if (hasDynamicSlots) {3095 patchFlag |= 512 /* DYNAMIC_SLOTS */;3096 }3097 }3098 else if (node.children.length === 1) {3099 const child = node.children[0];3100 const type = child.type;3101 // check for dynamic text children3102 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||3103 type === 8 /* COMPOUND_EXPRESSION */;3104 if (hasDynamicTextChild && !isStaticNode(child)) {3105 patchFlag |= 1 /* TEXT */;3106 }3107 // pass directly if the only child is a text node3108 // (plain / interpolation / expression)3109 if (hasDynamicTextChild || type === 2 /* TEXT */) {3110 vnodeChildren = child;3111 }3112 else {3113 vnodeChildren = node.children;3114 }3115 }3116 else {3117 vnodeChildren = node.children;3118 }3119 }3120 // patchFlag & dynamicPropNames3121 if (patchFlag !== 0) {3122 {3123 const flagNames = Object.keys(PatchFlagNames)3124 .map(Number)3125 .filter(n => n > 0 && patchFlag & n)3126 .map(n => PatchFlagNames[n])3127 .join(`, `);3128 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;3129 }3130 if (dynamicPropNames && dynamicPropNames.length) {3131 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);3132 }3133 }3134 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, shouldUseBlock, false /* isForBlock */, node.loc);3135 };3136 };3137 function resolveComponentType(node, context, ssr = false) {3138 const { tag } = node;3139 // 1. dynamic component3140 const isProp = node.tag === 'component' && findProp(node, 'is');3141 if (isProp) {3142 // static <component is="foo" />3143 if (isProp.type === 6 /* ATTRIBUTE */) {3144 const isType = isProp.value && isProp.value.content;3145 if (isType) {3146 context.helper(RESOLVE_COMPONENT);3147 context.components.add(isType);3148 return toValidAssetId(isType, `component`);3149 }3150 }3151 // dynamic <component :is="asdf" />3152 else if (isProp.exp) {3153 return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), 3154 // _ctx.$ exposes the owner instance of current render function3155 [isProp.exp, context.prefixIdentifiers ? `_ctx.$` : `$`]);3156 }3157 }3158 // 2. built-in components (Portal, Transition, KeepAlive, Suspense...)3159 const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);3160 if (builtIn) {3161 // built-ins are simply fallthroughs / have special handling during ssr3162 // no we don't need to import their runtime equivalents3163 if (!ssr)3164 context.helper(builtIn);3165 return builtIn;3166 }3167 // 3. user component (resolve)3168 context.helper(RESOLVE_COMPONENT);3169 context.components.add(tag);3170 return toValidAssetId(tag, `component`);3171 }3172 function buildProps(node, context, props = node.props, ssr = false) {3173 const { tag, loc: elementLoc } = node;3174 const isComponent = node.tagType === 1 /* COMPONENT */;3175 let properties = [];3176 const mergeArgs = [];3177 const runtimeDirectives = [];3178 // patchFlag analysis3179 let patchFlag = 0;3180 let hasRef = false;3181 let hasClassBinding = false;3182 let hasStyleBinding = false;3183 let hasDynamicKeys = false;3184 const dynamicPropNames = [];3185 const analyzePatchFlag = ({ key, value }) => {3186 if (key.type === 4 /* SIMPLE_EXPRESSION */ && key.isStatic) {3187 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||3188 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||3189 value.type === 8 /* COMPOUND_EXPRESSION */) &&3190 isStaticNode(value))) {3191 return;3192 }3193 const name = key.content;3194 if (name === 'ref') {3195 hasRef = true;3196 }3197 else if (name === 'class') {3198 hasClassBinding = true;3199 }3200 else if (name === 'style') {3201 hasStyleBinding = true;3202 }3203 else if (name !== 'key') {3204 dynamicPropNames.push(name);3205 }3206 }3207 else {3208 hasDynamicKeys = true;3209 }3210 };3211 for (let i = 0; i < props.length; i++) {3212 // static attribute3213 const prop = props[i];3214 if (prop.type === 6 /* ATTRIBUTE */) {3215 const { loc, name, value } = prop;3216 if (name === 'ref') {3217 hasRef = true;3218 }3219 // skip :is on <component>3220 if (name === 'is' && tag === 'component') {3221 continue;3222 }3223 properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc)));3224 }3225 else {3226 // directives3227 const { name, arg, exp, loc } = prop;3228 const isBind = name === 'bind';3229 const isOn = name === 'on';3230 // skip v-slot - it is handled by its dedicated transform.3231 if (name === 'slot') {3232 if (!isComponent) {3233 context.onError(createCompilerError(45 /* X_V_SLOT_MISPLACED */, loc));3234 }3235 continue;3236 }3237 // skip v-once - it is handled by its dedicated transform.3238 if (name === 'once') {3239 continue;3240 }3241 // skip :is on <component>3242 if (isBind && tag === 'component' && isBindKey(arg, 'is')) {3243 continue;3244 }3245 // skip v-on in SSR compilation3246 if (isOn && ssr) {3247 continue;3248 }3249 // special case for v-bind and v-on with no argument3250 if (!arg && (isBind || isOn)) {3251 hasDynamicKeys = true;3252 if (exp) {3253 if (properties.length) {3254 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));3255 properties = [];3256 }3257 if (isBind) {3258 mergeArgs.push(exp);3259 }3260 else {3261 // v-on="obj" -> toHandlers(obj)3262 mergeArgs.push({3263 type: 14 /* JS_CALL_EXPRESSION */,3264 loc,3265 callee: context.helper(TO_HANDLERS),3266 arguments: [exp]3267 });3268 }3269 }3270 else {3271 context.onError(createCompilerError(isBind3272 ? 38 /* X_V_BIND_NO_EXPRESSION */3273 : 39 /* X_V_ON_NO_EXPRESSION */, loc));3274 }3275 continue;3276 }3277 const directiveTransform = context.directiveTransforms[name];3278 if (directiveTransform) {3279 // has built-in directive transform.3280 const { props, needRuntime } = directiveTransform(prop, node, context);3281 !ssr && props.forEach(analyzePatchFlag);3282 properties.push(...props);3283 if (needRuntime) {3284 runtimeDirectives.push(prop);3285 if (isSymbol(needRuntime)) {3286 directiveImportMap.set(prop, needRuntime);3287 }3288 }3289 }3290 else {3291 // no built-in transform, this is a user custom directive.3292 runtimeDirectives.push(prop);3293 }3294 }3295 }3296 let propsExpression = undefined;3297 // has v-bind="object" or v-on="object", wrap with mergeProps3298 if (mergeArgs.length) {3299 if (properties.length) {3300 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));3301 }3302 if (mergeArgs.length > 1) {3303 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);3304 }3305 else {3306 // single v-bind with nothing else - no need for a mergeProps call3307 propsExpression = mergeArgs[0];3308 }3309 }3310 else if (properties.length) {3311 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);3312 }3313 // patchFlag analysis3314 if (hasDynamicKeys) {3315 patchFlag |= 16 /* FULL_PROPS */;3316 }3317 else {3318 if (hasClassBinding) {3319 patchFlag |= 2 /* CLASS */;3320 }3321 if (hasStyleBinding) {3322 patchFlag |= 4 /* STYLE */;3323 }3324 if (dynamicPropNames.length) {3325 patchFlag |= 8 /* PROPS */;3326 }3327 }3328 if (patchFlag === 0 && (hasRef || runtimeDirectives.length > 0)) {3329 patchFlag |= 32 /* NEED_PATCH */;3330 }3331 return {3332 props: propsExpression,3333 directives: runtimeDirectives,3334 patchFlag,3335 dynamicPropNames3336 };3337 }3338 // Dedupe props in an object literal.3339 // Literal duplicated attributes would have been warned during the parse phase,3340 // however, it's possible to encounter duplicated `onXXX` handlers with different3341 // modifiers. We also need to merge static and dynamic class / style attributes.3342 // - onXXX handlers / style: merge into array3343 // - class: merge into single expression with concatenation3344 function dedupeProperties(properties) {3345 const knownProps = new Map();3346 const deduped = [];3347 for (let i = 0; i < properties.length; i++) {3348 const prop = properties[i];3349 // dynamic keys are always allowed3350 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) {3351 deduped.push(prop);3352 continue;3353 }3354 const name = prop.key.content;3355 const existing = knownProps.get(name);3356 if (existing) {3357 if (name === 'style' || name === 'class' || name.startsWith('on')) {3358 mergeAsArray(existing, prop);3359 }3360 // unexpected duplicate, should have emitted error during parse3361 }3362 else {3363 knownProps.set(name, prop);3364 deduped.push(prop);3365 }3366 }3367 return deduped;3368 }3369 function mergeAsArray(existing, incoming) {3370 if (existing.value.type === 17 /* JS_ARRAY_EXPRESSION */) {3371 existing.value.elements.push(incoming.value);3372 }3373 else {3374 existing.value = createArrayExpression([existing.value, incoming.value], existing.loc);3375 }3376 }3377 function buildDirectiveArgs(dir, context) {3378 const dirArgs = [];3379 const runtime = directiveImportMap.get(dir);3380 if (runtime) {3381 context.helper(runtime);3382 dirArgs.push(context.helperString(runtime));3383 }3384 else {3385 // inject statement for resolving directive3386 context.helper(RESOLVE_DIRECTIVE);3387 context.directives.add(dir.name);3388 dirArgs.push(toValidAssetId(dir.name, `directive`));3389 }3390 const { loc } = dir;3391 if (dir.exp)3392 dirArgs.push(dir.exp);3393 if (dir.arg) {3394 if (!dir.exp) {3395 dirArgs.push(`void 0`);3396 }3397 dirArgs.push(dir.arg);3398 }3399 if (Object.keys(dir.modifiers).length) {3400 if (!dir.arg) {3401 if (!dir.exp) {3402 dirArgs.push(`void 0`);3403 }3404 dirArgs.push(`void 0`);3405 }3406 const trueExpression = createSimpleExpression(`true`, false, loc);3407 dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc));3408 }3409 return createArrayExpression(dirArgs, dir.loc);3410 }3411 function stringifyDynamicPropNames(props) {3412 let propsNamesString = `[`;3413 for (let i = 0, l = props.length; i < l; i++) {3414 propsNamesString += JSON.stringify(props[i]);3415 if (i < l - 1)3416 propsNamesString += ', ';3417 }3418 return propsNamesString + `]`;3419 }3420 const transformSlotOutlet = (node, context) => {3421 if (isSlotOutlet(node)) {3422 const { children, loc } = node;3423 const { slotName, slotProps } = processSlotOutlet(node, context);3424 const slotArgs = [3425 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,3426 slotName3427 ];3428 if (slotProps) {3429 slotArgs.push(slotProps);3430 }3431 if (children.length) {3432 if (!slotProps) {3433 slotArgs.push(`{}`);3434 }3435 slotArgs.push(children);3436 }3437 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);3438 }3439 };3440 function processSlotOutlet(node, context) {3441 let slotName = `"default"`;3442 let slotProps = undefined;3443 // check for <slot name="xxx" OR :name="xxx" />3444 const name = findProp(node, 'name');3445 if (name) {3446 if (name.type === 6 /* ATTRIBUTE */ && name.value) {3447 // static name3448 slotName = JSON.stringify(name.value.content);3449 }3450 else if (name.type === 7 /* DIRECTIVE */ && name.exp) {3451 // dynamic name3452 slotName = name.exp;3453 }3454 }3455 const propsWithoutName = name3456 ? node.props.filter(p => p !== name)3457 : node.props;3458 if (propsWithoutName.length > 0) {3459 const { props, directives } = buildProps(node, context, propsWithoutName);3460 slotProps = props;3461 if (directives.length) {3462 context.onError(createCompilerError(40 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));3463 }3464 }3465 return {3466 slotName,3467 slotProps3468 };3469 }3470 const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/;3471 const transformOn = (dir, node, context, augmentor) => {3472 const { loc, modifiers, arg } = dir;3473 if (!dir.exp && !modifiers.length) {3474 context.onError(createCompilerError(39 /* X_V_ON_NO_EXPRESSION */, loc));3475 }3476 let eventName;3477 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {3478 if (arg.isStatic) {3479 const rawName = arg.content;3480 // for @vnode-xxx event listeners, auto convert it to camelCase3481 const normalizedName = rawName.startsWith(`vnode`)3482 ? capitalize(camelize(rawName))3483 : capitalize(rawName);3484 eventName = createSimpleExpression(`on${normalizedName}`, true, arg.loc);3485 }3486 else {3487 eventName = createCompoundExpression([`"on" + (`, arg, `)`]);3488 }3489 }3490 else {3491 // already a compound expression.3492 eventName = arg;3493 eventName.children.unshift(`"on" + (`);3494 eventName.children.push(`)`);3495 }3496 // handler processing3497 let exp = dir.exp;3498 let isCacheable = !exp;3499 if (exp) {3500 const isMemberExp = isMemberExpression(exp.content);3501 const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));3502 const hasMultipleStatements = exp.content.includes(`;`);3503 if (isInlineStatement || (isCacheable && isMemberExp)) {3504 // wrap inline statement in a function expression3505 exp = createCompoundExpression([3506 `$event => ${hasMultipleStatements ? `{` : `(`}`,3507 exp,3508 hasMultipleStatements ? `}` : `)`3509 ]);3510 }3511 }3512 let ret = {3513 props: [3514 createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))3515 ]3516 };3517 // apply extended compiler augmentor3518 if (augmentor) {3519 ret = augmentor(ret);3520 }3521 if (isCacheable) {3522 // cache handlers so that it's always the same handler being passed down.3523 // this avoids unnecessary re-renders when users use inline handlers on3524 // components.3525 ret.props[0].value = context.cache(ret.props[0].value);3526 }3527 return ret;3528 };3529 // v-bind without arg is handled directly in ./transformElements.ts due to it affecting3530 // codegen for the entire props object. This transform here is only for v-bind3531 // *with* args.3532 const transformBind = (dir, node, context) => {3533 const { exp, modifiers, loc } = dir;3534 const arg = dir.arg;3535 if (!exp) {3536 context.onError(createCompilerError(38 /* X_V_BIND_NO_EXPRESSION */, loc));3537 }3538 // .prop is no longer necessary due to new patch behavior3539 // .sync is replaced by v-model:arg3540 if (modifiers.includes('camel')) {3541 if (arg.type === 4 /* SIMPLE_EXPRESSION */) {3542 if (arg.isStatic) {3543 arg.content = camelize(arg.content);3544 }3545 else {3546 arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;3547 }3548 }3549 else {3550 arg.children.unshift(`${context.helperString(CAMELIZE)}(`);3551 arg.children.push(`)`);3552 }3553 }3554 return {3555 props: [3556 createObjectProperty(arg, exp || createSimpleExpression('', true, loc))3557 ]3558 };3559 };3560 // Merge adjacent text nodes and expressions into a single expression3561 // e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.3562 const transformText = (node, context) => {3563 if (node.type === 0 /* ROOT */ ||3564 node.type === 1 /* ELEMENT */ ||3565 node.type === 11 /* FOR */) {3566 // perform the transform on node exit so that all expressions have already3567 // been processed.3568 return () => {3569 const children = node.children;3570 let currentContainer = undefined;3571 let hasText = false;3572 for (let i = 0; i < children.length; i++) {3573 const child = children[i];3574 if (isText(child)) {3575 hasText = true;3576 for (let j = i + 1; j < children.length; j++) {3577 const next = children[j];3578 if (isText(next)) {3579 if (!currentContainer) {3580 currentContainer = children[i] = {3581 type: 8 /* COMPOUND_EXPRESSION */,3582 loc: child.loc,3583 children: [child]3584 };3585 }3586 // merge adjacent text node into current3587 currentContainer.children.push(` + `, next);3588 children.splice(j, 1);3589 j--;3590 }3591 else {3592 currentContainer = undefined;3593 break;3594 }3595 }3596 }3597 }3598 if (!hasText ||3599 // if this is a plain element with a single text child, leave it3600 // as-is since the runtime has dedicated fast path for this by directly3601 // setting textContent of the element.3602 // for component root it's always normalized anyway.3603 (children.length === 1 &&3604 (node.type === 0 /* ROOT */ ||3605 (node.type === 1 /* ELEMENT */ &&3606 node.tagType === 0 /* ELEMENT */)))) {3607 return;3608 }3609 // pre-convert text nodes into createTextVNode(text) calls to avoid3610 // runtime normalization.3611 for (let i = 0; i < children.length; i++) {3612 const child = children[i];3613 if (isText(child) || child.type === 8 /* COMPOUND_EXPRESSION */) {3614 const callArgs = [];3615 // createTextVNode defaults to single whitespace, so if it is a3616 // single space the code could be an empty call to save bytes.3617 if (child.type !== 2 /* TEXT */ || child.content !== ' ') {3618 callArgs.push(child);3619 }3620 // mark dynamic text with flag so it gets patched inside a block3621 if (!context.ssr && child.type !== 2 /* TEXT */) {3622 callArgs.push(`${1 /* TEXT */} /* ${PatchFlagNames[1 /* TEXT */]} */`);3623 }3624 children[i] = {3625 type: 12 /* TEXT_CALL */,3626 content: child,3627 loc: child.loc,3628 codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)3629 };3630 }3631 }3632 };3633 }3634 };3635 const transformOnce = (node, context) => {3636 if (node.type === 1 /* ELEMENT */ && findDir(node, 'once', true)) {3637 context.helper(SET_BLOCK_TRACKING);3638 return () => {3639 if (node.codegenNode) {3640 node.codegenNode = context.cache(node.codegenNode, true /* isVNode */);3641 }3642 };3643 }3644 };3645 const transformModel = (dir, node, context) => {3646 const { exp, arg } = dir;3647 if (!exp) {3648 context.onError(createCompilerError(46 /* X_V_MODEL_NO_EXPRESSION */, dir.loc));3649 return createTransformProps();3650 }3651 const expString = exp.type === 4 /* SIMPLE_EXPRESSION */ ? exp.content : exp.loc.source;3652 if (!isMemberExpression(expString)) {3653 context.onError(createCompilerError(47 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));3654 return createTransformProps();3655 }3656 const propName = arg ? arg : createSimpleExpression('modelValue', true);3657 const eventName = arg3658 ? arg.type === 4 /* SIMPLE_EXPRESSION */ && arg.isStatic3659 ? `onUpdate:${arg.content}`3660 : createCompoundExpression(['"onUpdate:" + ', arg])3661 : `onUpdate:modelValue`;3662 const props = [3663 // modelValue: foo3664 createObjectProperty(propName, dir.exp),3665 // "onUpdate:modelValue": $event => (foo = $event)3666 createObjectProperty(eventName, createCompoundExpression([`$event => (`, exp, ` = $event)`]))3667 ];3668 // modelModifiers: { foo: true, "bar-baz": true }3669 if (dir.modifiers.length && node.tagType === 1 /* COMPONENT */) {3670 const modifiers = dir.modifiers3671 .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)3672 .join(`, `);3673 const modifiersKey = arg3674 ? arg.type === 4 /* SIMPLE_EXPRESSION */ && arg.isStatic3675 ? `${arg.content}Modifiers`3676 : createCompoundExpression([arg, ' + "Modifiers"'])3677 : `modelModifiers`;3678 props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, true)));3679 }3680 return createTransformProps(props);3681 };3682 function createTransformProps(props = []) {3683 return { props };3684 }3685 function getBaseTransformPreset(prefixIdentifiers) {3686 return [3687 [3688 transformOnce,3689 transformIf,3690 transformFor,3691 ...( []),3692 transformSlotOutlet,3693 transformElement,3694 trackSlotScopes,3695 transformText3696 ],3697 {3698 on: transformOn,3699 bind: transformBind,3700 model: transformModel3701 }3702 ];3703 }3704 // we name it `baseCompile` so that higher order compilers like3705 // @vue/compiler-dom can export `compile` while re-exporting everything else.3706 function baseCompile(template, options = {}) {3707 const onError = options.onError || defaultOnError;3708 const isModuleMode = options.mode === 'module';3709 /* istanbul ignore if */3710 {3711 if (options.prefixIdentifiers === true) {3712 onError(createCompilerError(51 /* X_PREFIX_ID_NOT_SUPPORTED */));3713 }3714 else if (isModuleMode) {3715 onError(createCompilerError(52 /* X_MODULE_MODE_NOT_SUPPORTED */));3716 }3717 }3718 const prefixIdentifiers = !true ;3719 if ( options.cacheHandlers) {3720 onError(createCompilerError(53 /* X_CACHE_HANDLER_NOT_SUPPORTED */));3721 }3722 if (options.scopeId && !isModuleMode) {3723 onError(createCompilerError(54 /* X_SCOPE_ID_NOT_SUPPORTED */));3724 }3725 const ast = isString(template) ? baseParse(template, options) : template;3726 const [nodeTransforms, directiveTransforms] = getBaseTransformPreset();3727 transform(ast, {3728 ...options,3729 prefixIdentifiers,3730 nodeTransforms: [3731 ...nodeTransforms,3732 ...(options.nodeTransforms || []) // user transforms3733 ],3734 directiveTransforms: {3735 ...directiveTransforms,3736 ...(options.directiveTransforms || {}) // user transforms3737 }3738 });3739 return generate(ast, {3740 ...options,3741 prefixIdentifiers3742 });3743 }3744 const noopDirectiveTransform = () => ({ props: [] });3745 const generateCodeFrame$1 = generateCodeFrame;3746 const V_MODEL_RADIO = Symbol( `vModelRadio` );3747 const V_MODEL_CHECKBOX = Symbol( `vModelCheckbox` );3748 const V_MODEL_TEXT = Symbol( `vModelText` );3749 const V_MODEL_SELECT = Symbol( `vModelSelect` );3750 const V_MODEL_DYNAMIC = Symbol( `vModelDynamic` );3751 const V_ON_WITH_MODIFIERS = Symbol( `vOnModifiersGuard` );3752 const V_ON_WITH_KEYS = Symbol( `vOnKeysGuard` );3753 const V_SHOW = Symbol( `vShow` );3754 const TRANSITION = Symbol( `Transition` );3755 const TRANSITION_GROUP = Symbol( `TransitionGroup` );3756 registerRuntimeHelpers({3757 [V_MODEL_RADIO]: `vModelRadio`,3758 [V_MODEL_CHECKBOX]: `vModelCheckbox`,3759 [V_MODEL_TEXT]: `vModelText`,3760 [V_MODEL_SELECT]: `vModelSelect`,3761 [V_MODEL_DYNAMIC]: `vModelDynamic`,3762 [V_ON_WITH_MODIFIERS]: `withModifiers`,3763 [V_ON_WITH_KEYS]: `withKeys`,3764 [V_SHOW]: `vShow`,3765 [TRANSITION]: `Transition`,3766 [TRANSITION_GROUP]: `TransitionGroup`3767 });3768 const isRawTextContainer = /*#__PURE__*/ makeMap('style,iframe,script,noscript', true);3769 const parserOptionsMinimal = {3770 isVoidTag,3771 isNativeTag: tag => isHTMLTag(tag) || isSVGTag(tag),3772 isPreTag: tag => tag === 'pre',3773 isBuiltInComponent: (tag) => {3774 if (isBuiltInType(tag, `Transition`)) {3775 return TRANSITION;3776 }3777 else if (isBuiltInType(tag, `TransitionGroup`)) {3778 return TRANSITION_GROUP;3779 }3780 },3781 // https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher3782 getNamespace(tag, parent) {3783 let ns = parent ? parent.ns : 0 /* HTML */;3784 if (parent && ns === 2 /* MATH_ML */) {3785 if (parent.tag === 'annotation-xml') {3786 if (tag === 'svg') {3787 return 1 /* SVG */;3788 }3789 if (parent.props.some(a => a.type === 6 /* ATTRIBUTE */ &&3790 a.name === 'encoding' &&3791 a.value != null &&3792 (a.value.content === 'text/html' ||3793 a.value.content === 'application/xhtml+xml'))) {3794 ns = 0 /* HTML */;3795 }3796 }3797 else if (/^m(?:[ions]|text)$/.test(parent.tag) &&3798 tag !== 'mglyph' &&3799 tag !== 'malignmark') {3800 ns = 0 /* HTML */;3801 }3802 }3803 else if (parent && ns === 1 /* SVG */) {3804 if (parent.tag === 'foreignObject' ||3805 parent.tag === 'desc' ||3806 parent.tag === 'title') {3807 ns = 0 /* HTML */;3808 }3809 }3810 if (ns === 0 /* HTML */) {3811 if (tag === 'svg') {3812 return 1 /* SVG */;3813 }3814 if (tag === 'math') {3815 return 2 /* MATH_ML */;3816 }3817 }3818 return ns;3819 },3820 // https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments3821 getTextMode(tag, ns) {3822 if (ns === 0 /* HTML */) {3823 if (tag === 'textarea' || tag === 'title') {3824 return 1 /* RCDATA */;3825 }3826 if (isRawTextContainer(tag)) {3827 return 2 /* RAWTEXT */;3828 }3829 }3830 return 0 /* DATA */;3831 }3832 };3833 // Parse inline CSS strings for static style attributes into an object.3834 // This is a NodeTransform since it works on the static `style` attribute and3835 // converts it into a dynamic equivalent:3836 // style="color: red" -> :style='{ "color": "red" }'3837 // It is then processed by `transformElement` and included in the generated3838 // props.3839 const transformStyle = (node, context) => {3840 if (node.type === 1 /* ELEMENT */) {3841 node.props.forEach((p, i) => {3842 if (p.type === 6 /* ATTRIBUTE */ && p.name === 'style' && p.value) {3843 // replace p with an expression node3844 const exp = context.hoist(parseInlineCSS(p.value.content, p.loc));3845 node.props[i] = {3846 type: 7 /* DIRECTIVE */,3847 name: `bind`,3848 arg: createSimpleExpression(`style`, true, p.loc),3849 exp,3850 modifiers: [],3851 loc: p.loc3852 };3853 }3854 });3855 }3856 };3857 const listDelimiterRE = /;(?![^(]*\))/g;3858 const propertyDelimiterRE = /:(.+)/;3859 function parseInlineCSS(cssText, loc) {3860 const res = {};3861 cssText.split(listDelimiterRE).forEach(item => {3862 if (item) {3863 const tmp = item.split(propertyDelimiterRE);3864 tmp.length > 1 && (res[tmp[0].trim()] = tmp[1].trim());3865 }3866 });3867 return createSimpleExpression(JSON.stringify(res), false, loc);3868 }3869 function createDOMCompilerError(code, loc) {3870 return createCompilerError(code, loc, DOMErrorMessages );3871 }3872 const DOMErrorMessages = {3873 [55 /* X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,3874 [56 /* X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,3875 [57 /* X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,3876 [58 /* X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,3877 [59 /* X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,3878 [60 /* X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,3879 [61 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */]: `v-model cannot used on file inputs since they are read-only. Use a v-on:change listener instead.`,3880 [62 /* X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,3881 [63 /* X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,3882 [64 /* X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`3883 };3884 const transformVHtml = (dir, node, context) => {3885 const { exp, loc } = dir;3886 if (!exp) {3887 context.onError(createDOMCompilerError(55 /* X_V_HTML_NO_EXPRESSION */, loc));3888 }3889 if (node.children.length) {3890 context.onError(createDOMCompilerError(56 /* X_V_HTML_WITH_CHILDREN */, loc));3891 node.children.length = 0;3892 }3893 return {3894 props: [3895 createObjectProperty(createSimpleExpression(`innerHTML`, true, loc), exp || createSimpleExpression('', true))3896 ]3897 };3898 };3899 const transformVText = (dir, node, context) => {3900 const { exp, loc } = dir;3901 if (!exp) {3902 context.onError(createDOMCompilerError(57 /* X_V_TEXT_NO_EXPRESSION */, loc));3903 }3904 if (node.children.length) {3905 context.onError(createDOMCompilerError(58 /* X_V_TEXT_WITH_CHILDREN */, loc));3906 node.children.length = 0;3907 }3908 return {3909 props: [3910 createObjectProperty(createSimpleExpression(`textContent`, true, loc), exp || createSimpleExpression('', true))3911 ]3912 };3913 };3914 const transformModel$1 = (dir, node, context) => {3915 const baseResult = transformModel(dir, node, context);3916 // base transform has errors OR component v-model (only need props)3917 if (!baseResult.props.length || node.tagType === 1 /* COMPONENT */) {3918 return baseResult;3919 }3920 if (dir.arg) {3921 context.onError(createDOMCompilerError(60 /* X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));3922 }3923 function checkDuplicatedValue() {3924 const value = findProp(node, 'value');3925 if (value) {3926 context.onError(createDOMCompilerError(62 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc));3927 }3928 }3929 const { tag } = node;3930 if (tag === 'input' || tag === 'textarea' || tag === 'select') {3931 let directiveToUse = V_MODEL_TEXT;3932 let isInvalidType = false;3933 if (tag === 'input') {3934 const type = findProp(node, `type`);3935 if (type) {3936 if (type.type === 7 /* DIRECTIVE */) {3937 // :type="foo"3938 directiveToUse = V_MODEL_DYNAMIC;3939 }3940 else if (type.value) {3941 switch (type.value.content) {3942 case 'radio':3943 directiveToUse = V_MODEL_RADIO;3944 break;3945 case 'checkbox':3946 directiveToUse = V_MODEL_CHECKBOX;3947 break;3948 case 'file':3949 isInvalidType = true;3950 context.onError(createDOMCompilerError(61 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));3951 break;3952 default:3953 // text type3954 checkDuplicatedValue();3955 break;3956 }3957 }3958 }3959 else if (hasDynamicKeyVBind(node)) {3960 // element has bindings with dynamic keys, which can possibly contain3961 // "type".3962 directiveToUse = V_MODEL_DYNAMIC;3963 }3964 else {3965 // text type3966 checkDuplicatedValue();3967 }3968 }3969 else if (tag === 'select') {3970 directiveToUse = V_MODEL_SELECT;3971 }3972 else if (tag === 'textarea') {3973 checkDuplicatedValue();
...
compiler-core.cjs.js
Source:compiler-core.cjs.js
...524 arg.type === 4 /* SIMPLE_EXPRESSION */ &&525 arg.isStatic &&526 arg.content === name);527}528function hasDynamicKeyVBind(node) {529 return node.props.some(p => p.type === 7 /* DIRECTIVE */ &&530 p.name === 'bind' &&531 (!p.arg || // v-bind="obj"532 p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo]533 !p.arg.isStatic) // v-bind:[foo]534 );535}536function isText(node) {537 return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */;538}539function isVSlot(p) {540 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';541}542function isTemplateNode(node) {
...
compiler-core.cjs.prod.js
Source:compiler-core.cjs.prod.js
...522 arg.type === 4 /* SIMPLE_EXPRESSION */ &&523 arg.isStatic &&524 arg.content === name);525}526function hasDynamicKeyVBind(node) {527 return node.props.some(p => p.type === 7 /* DIRECTIVE */ &&528 p.name === 'bind' &&529 (!p.arg || // v-bind="obj"530 p.arg.type !== 4 /* SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo]531 !p.arg.isStatic) // v-bind:[foo]532 );533}534function isText(node) {535 return node.type === 5 /* INTERPOLATION */ || node.type === 2 /* TEXT */;536}537function isVSlot(p) {538 return p.type === 7 /* DIRECTIVE */ && p.name === 'slot';539}540function isTemplateNode(node) {
...
compiler-ssr.cjs.js
Source:compiler-ssr.cjs.js
...391 const needTagForRuntime = node.tag === 'textarea' || node.tag.indexOf('-') > 0;392 // v-bind="obj" or v-bind:[key] can potentially overwrite other static393 // attrs and can affect final rendering result, so when they are present394 // we need to bail out to full `renderAttrs`395 const hasDynamicVBind = compilerDom.hasDynamicKeyVBind(node);396 if (hasDynamicVBind) {397 const { props } = compilerDom.buildProps(node, context, node.props, true /* ssr */);398 if (props) {399 const propsExp = compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTRS), [props]);400 if (node.tag === 'textarea') {401 // <textarea> with dynamic v-bind. We don't know if the final props402 // will contain .value, so we will have to do something special:403 // assign the merged props to a temp variable, and check whether404 // it contains value (if yes, render is as children).405 const tempId = `_temp${context.temps++}`;406 propsExp.arguments = [407 compilerDom.createAssignmentExpression(compilerDom.createSimpleExpression(tempId, false), props)408 ];409 const existingText = node.children[0];410 rawChildrenMap.set(node, compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [411 compilerDom.createConditionalExpression(compilerDom.createSimpleExpression(`"value" in ${tempId}`, false), compilerDom.createSimpleExpression(`${tempId}.value`, false), compilerDom.createSimpleExpression(existingText ? existingText.content : ``, true), false)412 ]));413 }414 else if (node.tag === 'input') {415 // <input v-bind="obj" v-model>416 // we need to determine the props to render for the dynamic v-model417 // and merge it with the v-bind expression.418 const vModel = findVModel(node);419 if (vModel) {420 // 1. save the props (san v-model) in a temp variable421 const tempId = `_temp${context.temps++}`;422 const tempExp = compilerDom.createSimpleExpression(tempId, false);423 propsExp.arguments = [424 compilerDom.createSequenceExpression([425 compilerDom.createAssignmentExpression(tempExp, props),426 compilerDom.createCallExpression(context.helper(compilerDom.MERGE_PROPS), [427 tempExp,428 compilerDom.createCallExpression(context.helper(SSR_GET_DYNAMIC_MODEL_PROPS), [429 tempExp,430 vModel.exp // model431 ])432 ])433 ])434 ];435 }436 }437 if (needTagForRuntime) {438 propsExp.arguments.push(`"${node.tag}"`);439 }440 openTag.push(propsExp);441 }442 }443 // book keeping static/dynamic class merging.444 let dynamicClassBinding = undefined;445 let staticClassBinding = undefined;446 // all style bindings are converted to dynamic by transformStyle.447 // but we need to make sure to merge them.448 let dynamicStyleBinding = undefined;449 for (let i = 0; i < node.props.length; i++) {450 const prop = node.props[i];451 // special cases with children override452 if (prop.type === 7 /* DIRECTIVE */) {453 if (prop.name === 'html' && prop.exp) {454 rawChildrenMap.set(node, prop.exp);455 }456 else if (prop.name === 'text' && prop.exp) {457 node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];458 }459 else if (prop.name === 'slot') {460 context.onError(compilerDom.createCompilerError(37 /* X_V_SLOT_MISPLACED */, prop.loc));461 }462 else if (isTextareaWithValue(node, prop) && prop.exp) {463 if (!hasDynamicVBind) {464 node.children = [compilerDom.createInterpolation(prop.exp, prop.loc)];465 }466 }467 else {468 // Directive transforms.469 const directiveTransform = context.directiveTransforms[prop.name];470 if (!directiveTransform) {471 // no corresponding ssr directive transform found.472 context.onError(createSSRCompilerError(57 /* X_SSR_CUSTOM_DIRECTIVE_NO_TRANSFORM */, prop.loc));473 }474 else if (!hasDynamicVBind) {475 const { props, ssrTagParts } = directiveTransform(prop, node, context);476 if (ssrTagParts) {477 openTag.push(...ssrTagParts);478 }479 for (let j = 0; j < props.length; j++) {480 const { key, value } = props[j];481 if (key.type === 4 /* SIMPLE_EXPRESSION */ && key.isStatic) {482 let attrName = key.content;483 // static key attr484 if (attrName === 'class') {485 openTag.push(` class="`, (dynamicClassBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_CLASS), [value])), `"`);486 }487 else if (attrName === 'style') {488 if (dynamicStyleBinding) {489 // already has style binding, merge into it.490 mergeCall(dynamicStyleBinding, value);491 }492 else {493 openTag.push(` style="`, (dynamicStyleBinding = compilerDom.createCallExpression(context.helper(SSR_RENDER_STYLE), [value])), `"`);494 }495 }496 else {497 attrName =498 node.tag.indexOf('-') > 0499 ? attrName // preserve raw name on custom elements500 : shared.propsToAttrMap[attrName] || attrName.toLowerCase();501 if (shared.isBooleanAttr(attrName)) {502 openTag.push(compilerDom.createConditionalExpression(value, compilerDom.createSimpleExpression(' ' + attrName, true), compilerDom.createSimpleExpression('', true), false /* no newline */));503 }504 else if (shared.isSSRSafeAttrName(attrName)) {505 openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_ATTR), [506 key,507 value508 ]));509 }510 else {511 context.onError(createSSRCompilerError(58 /* X_SSR_UNSAFE_ATTR_NAME */, key.loc));512 }513 }514 }515 else {516 // dynamic key attr517 // this branch is only encountered for custom directive518 // transforms that returns properties with dynamic keys519 const args = [key, value];520 if (needTagForRuntime) {521 args.push(`"${node.tag}"`);522 }523 openTag.push(compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_ATTR), args));524 }525 }526 }527 }528 }529 else {530 // special case: value on <textarea>531 if (node.tag === 'textarea' && prop.name === 'value' && prop.value) {532 rawChildrenMap.set(node, shared.escapeHtml(prop.value.content));533 }534 else if (!hasDynamicVBind) {535 // static prop536 if (prop.name === 'class' && prop.value) {537 staticClassBinding = JSON.stringify(prop.value.content);538 }539 openTag.push(` ${prop.name}` +540 (prop.value ? `="${shared.escapeHtml(prop.value.content)}"` : ``));541 }542 }543 }544 // handle co-existence of dynamic + static class bindings545 if (dynamicClassBinding && staticClassBinding) {546 mergeCall(dynamicClassBinding, staticClassBinding);547 removeStaticBinding(openTag, 'class');548 }549 if (context.scopeId) {550 openTag.push(` ${context.scopeId}`);551 }552 node.ssrCodegenNode = compilerDom.createTemplateLiteral(openTag);553 };554 }555};556function isTextareaWithValue(node, prop) {557 return !!(node.tag === 'textarea' &&558 prop.name === 'bind' &&559 compilerDom.isBindKey(prop.arg, 'value'));560}561function mergeCall(call, arg) {562 const existing = call.arguments[0];563 if (existing.type === 17 /* JS_ARRAY_EXPRESSION */) {564 existing.elements.push(arg);565 }566 else {567 call.arguments[0] = compilerDom.createArrayExpression([existing, arg]);568 }569}570function removeStaticBinding(tag, binding) {571 const i = tag.findIndex(e => typeof e === 'string' && e.startsWith(` ${binding}=`));572 if (i > -1) {573 tag.splice(i, 1);574 }575}576function findVModel(node) {577 return node.props.find(p => p.type === 7 /* DIRECTIVE */ && p.name === 'model' && p.exp);578}579function ssrProcessElement(node, context) {580 const isVoidTag = context.options.isVoidTag || shared.NO;581 const elementsToAdd = node.ssrCodegenNode.elements;582 for (let j = 0; j < elementsToAdd.length; j++) {583 context.pushStringPart(elementsToAdd[j]);584 }585 // Handle slot scopeId586 if (context.withSlotScopeId) {587 context.pushStringPart(compilerDom.createSimpleExpression(`_scopeId`, false));588 }589 // close open tag590 context.pushStringPart(`>`);591 const rawChildren = rawChildrenMap.get(node);592 if (rawChildren) {593 context.pushStringPart(rawChildren);594 }595 else if (node.children.length) {596 processChildren(node.children, context);597 }598 if (!isVoidTag(node.tag)) {599 // push closing tag600 context.pushStringPart(`</${node.tag}>`);601 }602}603// Because SSR codegen output is completely different from client-side output604// (e.g. multiple elements can be concatenated into a single template literal605// instead of each getting a corresponding call), we need to apply an extra606// transform pass to convert the template AST into a fresh JS AST before607// passing it to codegen.608function ssrCodegenTransform(ast, options) {609 const context = createSSRTransformContext(ast, options);610 const isFragment = ast.children.length > 1 && ast.children.some(c => !compilerDom.isText(c));611 processChildren(ast.children, context, isFragment);612 ast.codegenNode = compilerDom.createBlockStatement(context.body);613 // Finalize helpers.614 // We need to separate helpers imported from 'vue' vs. '@vue/server-renderer'615 ast.ssrHelpers = [616 ...ast.helpers.filter(h => h in ssrHelpers),617 ...context.helpers618 ];619 ast.helpers = ast.helpers.filter(h => !(h in ssrHelpers));620}621function createSSRTransformContext(root, options, helpers = new Set(), withSlotScopeId = false) {622 const body = [];623 let currentString = null;624 return {625 root,626 options,627 body,628 helpers,629 withSlotScopeId,630 onError: options.onError ||631 (e => {632 throw e;633 }),634 helper(name) {635 helpers.add(name);636 return name;637 },638 pushStringPart(part) {639 if (!currentString) {640 const currentCall = compilerDom.createCallExpression(`_push`);641 body.push(currentCall);642 currentString = compilerDom.createTemplateLiteral([]);643 currentCall.arguments.push(currentString);644 }645 const bufferedElements = currentString.elements;646 const lastItem = bufferedElements[bufferedElements.length - 1];647 if (shared.isString(part) && shared.isString(lastItem)) {648 bufferedElements[bufferedElements.length - 1] += part;649 }650 else {651 bufferedElements.push(part);652 }653 },654 pushStatement(statement) {655 // close current string656 currentString = null;657 body.push(statement);658 }659 };660}661function createChildContext(parent, withSlotScopeId = parent.withSlotScopeId) {662 // ensure child inherits parent helpers663 return createSSRTransformContext(parent.root, parent.options, parent.helpers, withSlotScopeId);664}665function processChildren(children, context, asFragment = false) {666 if (asFragment) {667 context.pushStringPart(`<!--[-->`);668 }669 for (let i = 0; i < children.length; i++) {670 const child = children[i];671 if (child.type === 1 /* ELEMENT */) {672 if (child.tagType === 0 /* ELEMENT */) {673 ssrProcessElement(child, context);674 }675 else if (child.tagType === 1 /* COMPONENT */) {676 ssrProcessComponent(child, context);677 }678 else if (child.tagType === 2 /* SLOT */) {679 ssrProcessSlotOutlet(child, context);680 }681 }682 else if (child.type === 2 /* TEXT */) {683 context.pushStringPart(shared.escapeHtml(child.content));684 }685 else if (child.type === 5 /* INTERPOLATION */) {686 context.pushStringPart(compilerDom.createCallExpression(context.helper(SSR_INTERPOLATE), [child.content]));687 }688 else if (child.type === 9 /* IF */) {689 ssrProcessIf(child, context);690 }691 else if (child.type === 11 /* FOR */) {692 ssrProcessFor(child, context);693 }694 }695 if (asFragment) {696 context.pushStringPart(`<!--]-->`);697 }698}699function processChildrenAsStatement(children, parentContext, asFragment = false, withSlotScopeId = parentContext.withSlotScopeId) {700 const childContext = createChildContext(parentContext, withSlotScopeId);701 processChildren(children, childContext, asFragment);702 return compilerDom.createBlockStatement(childContext.body);703}704const ssrTransformModel = (dir, node, context) => {705 const model = dir.exp;706 function checkDuplicatedValue() {707 const value = compilerDom.findProp(node, 'value');708 if (value) {709 context.onError(compilerDom.createDOMCompilerError(54 /* X_V_MODEL_UNNECESSARY_VALUE */, value.loc));710 }711 }712 if (node.tagType === 0 /* ELEMENT */) {713 const res = { props: [] };714 const defaultProps = [715 // default value binding for text type inputs716 compilerDom.createObjectProperty(`value`, model)717 ];718 if (node.tag === 'input') {719 const type = compilerDom.findProp(node, 'type');720 if (type) {721 const value = findValueBinding(node);722 if (type.type === 7 /* DIRECTIVE */) {723 // dynamic type724 res.ssrTagParts = [725 compilerDom.createCallExpression(context.helper(SSR_RENDER_DYNAMIC_MODEL), [726 type.exp,727 model,728 value729 ])730 ];731 }732 else if (type.value) {733 // static type734 switch (type.value.content) {735 case 'radio':736 res.props = [737 compilerDom.createObjectProperty(`checked`, compilerDom.createCallExpression(context.helper(SSR_LOOSE_EQUAL), [738 model,739 value740 ]))741 ];742 break;743 case 'checkbox':744 res.props = [745 compilerDom.createObjectProperty(`checked`, compilerDom.createConditionalExpression(compilerDom.createCallExpression(`Array.isArray`, [model]), compilerDom.createCallExpression(context.helper(SSR_LOOSE_CONTAIN), [746 model,747 value748 ]), model))749 ];750 break;751 case 'file':752 context.onError(compilerDom.createDOMCompilerError(53 /* X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));753 break;754 default:755 checkDuplicatedValue();756 res.props = defaultProps;757 break;758 }759 }760 }761 else if (compilerDom.hasDynamicKeyVBind(node)) ;762 else {763 // text type764 checkDuplicatedValue();765 res.props = defaultProps;766 }767 }768 else if (node.tag === 'textarea') {769 checkDuplicatedValue();770 node.children = [compilerDom.createInterpolation(model, model.loc)];771 }772 else if (node.tag === 'select') ;773 else {774 context.onError(compilerDom.createDOMCompilerError(51 /* X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));775 }
...
compiler-dom.esm-bundler.js
Source:compiler-dom.esm-bundler.js
...227 break;228 }229 }230 }231 else if (hasDynamicKeyVBind(node)) {232 // element has bindings with dynamic keys, which can possibly contain233 // "type".234 directiveToUse = V_MODEL_DYNAMIC;235 }236 else {237 // text type238 (process.env.NODE_ENV !== 'production') && checkDuplicatedValue();239 }240 }241 else if (tag === 'select') {242 directiveToUse = V_MODEL_SELECT;243 }244 else {245 // textarea...
utils.js
Source:utils.js
...100 arg.content === name101 )102 );103}104export function hasDynamicKeyVBind(node) {105 return node.props.some(106 (p) =>107 p.type === NodeTypes.DIRECTIVE &&108 p.name === "bind" &&109 (!p.arg || // v-bind="obj"110 p.arg.type !== NodeTypes.SIMPLE_EXPRESSION || // v-bind:[_ctx.foo]111 !p.arg.isStatic) // v-bind:[foo]112 );113}114export function toValidAssetId(115 name,116 type // 'component' | 'directive'117) {118 return `_${type}_${name.replace(/[^\w]/g, "_")}`;...
vModel.js
Source:vModel.js
...55 checkDuplicatedValue()56 break57 }58 }59 } else if (hasDynamicKeyVBind(node)) {60 directiveToUse = V_MODEL_DYNAMIC61 } else {62 checkDuplicatedValue()63 }64 } else if (tag === 'select') {65 directiveToUse = V_MODEL_SELECT66 } else {67 checkDuplicatedValue()68 }69 if (!isInvalidType) {70 baseResult.needRuntime = context.helper(directiveToUse)71 }72 } else {73 context.onError(createDOMCompilerError(54, dir.loc))...
Using AI Code Generation
1const {chromium} = require('playwright-chromium');2const path = require('path');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForSelector('text=Get started');8 await page.click('text=Get started');9 await page.waitForSelector('h1:has-text("Installing Playwright")');10 await page.click('text=Node.js');11 await page.waitForSelector('text=Install with npm');12 await page.click('text=Install with npm');13 await page.waitForSelector('text=Install with yarn');14 await page.click('text=Install with yarn');15 await page.waitForSelector('text=Install with pnpm');16 await page.click('text=Install with pnpm');17 await page.waitForSelector('text=Install from source');18 await page.click('text=Install from source');19 await page.waitForSelector('text=Create a new project');20 await page.click('text=Create a new project');21 await page.waitForSelector('text=Install with npm');22 await page.click('text=Install with npm');23 await page.waitForSelector('text=Install with yarn');24 await page.click('text=Install with yarn');25 await page.waitForSelector('text=Install with pnpm');26 await page.click('text=Install with pnpm');27 await page.waitForSelector('text=Install from source');28 await page.click('text=Install from source');29 await page.waitForSelector('text=Install with npm');30 await page.click('text=Install with npm');31 await page.waitForSelector('text=Install with yarn');32 await page.click('text=Install with yarn');33 await page.waitForSelector('text=Install with pnpm');34 await page.click('text=Install with pnpm');35 await page.waitForSelector('text=Install from source');36 await page.click('text=Install from source');37 await page.waitForSelector('text=Install with npm');38 await page.click('text=Install with npm');39 await page.waitForSelector('text=Install with yarn');40 await page.click('text=Install with yarn');41 await page.waitForSelector('text=Install with pnpm');42 await page.click('text=Install with pnpm');43 await page.waitForSelector('text=Install from
Using AI Code Generation
1const { chromium } = require('playwright');2const { hasDynamicKeyVBind } = require('playwright/lib/server/supplements/recorder/recorderSupplement');3(async () => {4 const browser = await chromium.launch();5 const page = await browser.newPage();6 const hasDynamicKeyVBind = await page.evaluate(() => {7 const element = document.querySelector('input[name="q"]');8 return hasDynamicKeyVBind(element, 'name');9 });10 await browser.close();11})();12const { chromium } = require('playwright');13const { hasDynamicKeyVBind } = require('playwright/lib/server/supplements/recorder/recorderSupplement');14(async () => {15 const browser = await chromium.launch();16 const page = await browser.newPage();17 const hasDynamicKeyVBind = await page.evaluate(() => {18 const element = document.querySelector('input[name="q"]');19 return hasDynamicKeyVBind(element, 'name');20 });21 await browser.close();22})();23const { chromium } = require('playwright');24const { hasDynamicKeyVBind } = require('playwright/lib/server/supplements/recorder/recorderSupplement');25(async () => {26 const browser = await chromium.launch();27 const page = await browser.newPage();28 const hasDynamicKeyVBind = await page.evaluate(() => {29 const element = document.querySelector('input[name="q"]');30 return hasDynamicKeyVBind(element, 'name');31 });32 await browser.close();33})();34const { chromium } = require('playwright');35const { hasDynamicKeyVBind } = require('playwright/lib/server/supplements/recorder/recorderSupplement');36(async () => {37 const browser = await chromium.launch();
Using AI Code Generation
1import { hasDynamicKeyVBind } from 'playwright-core/lib/server/supplements/recorder/recorderUtils';2const hasDynamicKeyVBind = hasDynamicKeyVBind(page);3const hasDynamicKeyVBind = await page.evaluate((selector) => {4 return hasDynamicKeyVBind(selector);5}, selector);6hasDynamicKeyVBind(selector)7const hasDynamicKeyVBind = await page.evaluate((selector) => {8 return hasDynamicKeyVBind(selector);9}, selector);
Using AI Code Generation
1const page = await browser.newPage();2const selector = await page.$('selector');3const value = await selector.hasDynamicKeyVBind();4console.log(value);5const page = await browser.newPage();6const selector = await page.$('selector');7const value = await selector.hasDynamicKeyVBind();8console.log(value);9const page = await browser.newPage();10const selector = await page.$('selector');11const value = await selector.hasDynamicKeyVBind();12console.log(value);13const page = await browser.newPage();14const selector = await page.$('selector');15const value = await selector.hasDynamicKeyVBind();16console.log(value);17const page = await browser.newPage();18const selector = await page.$('selector');19const value = await selector.hasDynamicKeyVBind();20console.log(value);21const page = await browser.newPage();22const selector = await page.$('selector');23const value = await selector.hasDynamicKeyVBind();24console.log(value);
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.
Get 100 minutes of automation test minutes FREE!!