How to use hasDynamicKeyVBind method in Playwright Internal

Best JavaScript code snippet using playwright-internal

vendor-node_modules_r.js

Source:vendor-node_modules_r.js Github

copy

Full Screen

...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) {...

Full Screen

Full Screen

compiler-dom.global.js

Source:compiler-dom.global.js Github

copy

Full Screen

...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(); ...

Full Screen

Full Screen

compiler-core.cjs.js

Source:compiler-core.cjs.js Github

copy

Full Screen

...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) { ...

Full Screen

Full Screen

compiler-core.cjs.prod.js

Source:compiler-core.cjs.prod.js Github

copy

Full Screen

...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) { ...

Full Screen

Full Screen

compiler-ssr.cjs.js

Source:compiler-ssr.cjs.js Github

copy

Full Screen

...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 } ...

Full Screen

Full Screen

compiler-dom.esm-bundler.js

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

copy

Full Screen

...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...

Full Screen

Full Screen

utils.js

Source:utils.js Github

copy

Full Screen

...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, "_")}`;...

Full Screen

Full Screen

vModel.js

Source:vModel.js Github

copy

Full Screen

...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))...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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();

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Using AI Code Generation

copy

Full Screen

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

Full Screen

Playwright tutorial

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

Chapters:

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

Run Playwright Internal automation tests on LambdaTest cloud grid

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

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful