Best JavaScript code snippet using playwright-internal
compiler-dom.global.js
Source:compiler-dom.global.js
...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);
...
compiler-core.cjs.js
Source:compiler-core.cjs.js
...2929 childBlock.isBlock = true;2930 helper(OPEN_BLOCK);2931 helper(CREATE_BLOCK);2932 }2933 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));2934 };2935 });2936});2937// target-agnostic transform used for both Client and SSR2938function processFor(node, dir, context, processCodegen) {2939 if (!dir.exp) {2940 context.onError(createCompilerError(36 /* X_V_FOR_NO_EXPRESSION */, dir.loc));2941 return;2942 }2943 const parseResult = parseForExpression(2944 // can only be simple expression because vFor transform is applied2945 // before expression transform.2946 dir.exp, context);2947 if (!parseResult) {2948 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));2949 return;2950 }2951 const { addIdentifiers, removeIdentifiers, scopes } = context;2952 const { source, value, key, index } = parseResult;2953 const forNode = {2954 type: 11 /* FOR */,2955 loc: dir.loc,2956 source,2957 valueAlias: value,2958 keyAlias: key,2959 objectIndexAlias: index,2960 parseResult,2961 children: node.tagType === 3 /* TEMPLATE */ ? node.children : [node]2962 };2963 context.replaceNode(forNode);2964 // bookkeeping2965 scopes.vFor++;2966 if ( context.prefixIdentifiers) {2967 // scope management2968 // inject identifiers to context2969 value && addIdentifiers(value);2970 key && addIdentifiers(key);2971 index && addIdentifiers(index);2972 }2973 const onExit = processCodegen && processCodegen(forNode);2974 return () => {2975 scopes.vFor--;2976 if ( context.prefixIdentifiers) {2977 value && removeIdentifiers(value);2978 key && removeIdentifiers(key);2979 index && removeIdentifiers(index);2980 }2981 if (onExit)2982 onExit();2983 };2984}2985const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;2986// This regex doesn't cover the case if key or index aliases have destructuring,2987// but those do not make sense in the first place, so this works in practice.2988const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;2989const stripParensRE = /^\(|\)$/g;2990function parseForExpression(input, context) {2991 const loc = input.loc;2992 const exp = input.content;2993 const inMatch = exp.match(forAliasRE);2994 if (!inMatch)2995 return;2996 const [, LHS, RHS] = inMatch;2997 const result = {2998 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),2999 value: undefined,3000 key: undefined,3001 index: undefined3002 };3003 if ( context.prefixIdentifiers) {3004 result.source = processExpression(result.source, context);3005 }3006 let valueContent = LHS.trim()3007 .replace(stripParensRE, '')3008 .trim();3009 const trimmedOffset = LHS.indexOf(valueContent);3010 const iteratorMatch = valueContent.match(forIteratorRE);3011 if (iteratorMatch) {3012 valueContent = valueContent.replace(forIteratorRE, '').trim();3013 const keyContent = iteratorMatch[1].trim();3014 let keyOffset;3015 if (keyContent) {3016 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);3017 result.key = createAliasExpression(loc, keyContent, keyOffset);3018 if ( context.prefixIdentifiers) {3019 result.key = processExpression(result.key, context, true);3020 }3021 }3022 if (iteratorMatch[2]) {3023 const indexContent = iteratorMatch[2].trim();3024 if (indexContent) {3025 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key3026 ? keyOffset + keyContent.length3027 : trimmedOffset + valueContent.length));3028 if ( context.prefixIdentifiers) {3029 result.index = processExpression(result.index, context, true);3030 }3031 }3032 }3033 }3034 if (valueContent) {3035 result.value = createAliasExpression(loc, valueContent, trimmedOffset);3036 if ( context.prefixIdentifiers) {3037 result.value = processExpression(result.value, context, true);3038 }3039 }3040 return result;3041}3042function createAliasExpression(range, content, offset) {3043 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3044}3045function createForLoopParams({ value, key, index }) {3046 const params = [];3047 if (value) {3048 params.push(value);3049 }3050 if (key) {3051 if (!value) {3052 params.push(createSimpleExpression(`_`, false));3053 }3054 params.push(key);3055 }3056 if (index) {3057 if (!key) {3058 if (!value) {3059 params.push(createSimpleExpression(`_`, false));3060 }3061 params.push(createSimpleExpression(`__`, false));3062 }3063 params.push(index);3064 }3065 return params;3066}3067const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic;3068const defaultFallback = createSimpleExpression(`undefined`, false);3069// A NodeTransform that:3070// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3071// by transformExpression. This is only applied in non-browser builds with3072// { prefixIdentifiers: true }.3073// 2. Track v-slot depths so that we know a slot is inside another slot.3074// Note the exit callback is executed before buildSlots() on the same node,3075// so only nested slots see positive numbers.3076const trackSlotScopes = (node, context) => {3077 if (node.type === 1 /* ELEMENT */ &&3078 (node.tagType === 1 /* COMPONENT */ ||3079 node.tagType === 3 /* TEMPLATE */)) {3080 // We are only checking non-empty v-slot here3081 // since we only care about slots that introduce scope variables.3082 const vSlot = findDir(node, 'slot');3083 if (vSlot) {3084 const slotProps = vSlot.exp;3085 if ( context.prefixIdentifiers) {3086 slotProps && context.addIdentifiers(slotProps);3087 }3088 context.scopes.vSlot++;3089 return () => {3090 if ( context.prefixIdentifiers) {3091 slotProps && context.removeIdentifiers(slotProps);3092 }3093 context.scopes.vSlot--;3094 };3095 }3096 }3097};3098// A NodeTransform that tracks scope identifiers for scoped slots with v-for.3099// This transform is only applied in non-browser builds with { prefixIdentifiers: true }3100const trackVForSlotScopes = (node, context) => {3101 let vFor;3102 if (isTemplateNode(node) &&3103 node.props.some(isVSlot) &&3104 (vFor = findDir(node, 'for'))) {3105 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3106 if (result) {3107 const { value, key, index } = result;3108 const { addIdentifiers, removeIdentifiers } = context;3109 value && addIdentifiers(value);3110 key && addIdentifiers(key);3111 index && addIdentifiers(index);3112 return () => {3113 value && removeIdentifiers(value);3114 key && removeIdentifiers(key);3115 index && removeIdentifiers(index);3116 };3117 }3118 }3119};3120const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3121// Instead of being a DirectiveTransform, v-slot processing is called during3122// transformElement to build the slots object for a component.3123function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3124 const { children, loc } = node;3125 const slotsProperties = [];3126 const dynamicSlots = [];3127 const buildDefaultSlotProperty = (props, children) => createObjectProperty(`default`, buildSlotFn(props, children, loc));3128 // If the slot is inside a v-for or another v-slot, force it to be dynamic3129 // since it likely uses a scope variable.3130 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3131 // with `prefixIdentifiers: true`, this can be further optimized to make3132 // it dynamic only when the slot actually uses the scope variables.3133 if ( context.prefixIdentifiers) {3134 hasDynamicSlots = hasScopeRef(node, context.identifiers);3135 }3136 // 1. Check for default slot with slotProps on component itself.3137 // <Comp v-slot="{ prop }"/>3138 const onComponentDefaultSlot = findDir(node, 'slot', true);3139 if (onComponentDefaultSlot) {3140 const { arg, exp, loc } = onComponentDefaultSlot;3141 if (arg) {3142 context.onError(createCompilerError(41 /* X_V_SLOT_NAMED_SLOT_ON_COMPONENT */, loc));3143 }3144 slotsProperties.push(buildDefaultSlotProperty(exp, children));3145 }3146 // 2. Iterate through children and check for template slots3147 // <template v-slot:foo="{ prop }">3148 let hasTemplateSlots = false;3149 let hasNamedDefaultSlot = false;3150 const implicitDefaultChildren = [];3151 const seenSlotNames = new Set();3152 for (let i = 0; i < children.length; i++) {3153 const slotElement = children[i];3154 let slotDir;3155 if (!isTemplateNode(slotElement) ||3156 !(slotDir = findDir(slotElement, 'slot', true))) {3157 // not a <template v-slot>, skip.3158 if (slotElement.type !== 3 /* COMMENT */) {3159 implicitDefaultChildren.push(slotElement);3160 }3161 continue;3162 }3163 if (onComponentDefaultSlot) {3164 // already has on-component default slot - this is incorrect usage.3165 context.onError(createCompilerError(42 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3166 break;3167 }3168 hasTemplateSlots = true;3169 const { children: slotChildren, loc: slotLoc } = slotElement;3170 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3171 // check if name is dynamic.3172 let staticSlotName;3173 if (isStaticExp(slotName)) {3174 staticSlotName = slotName ? slotName.content : `default`;3175 }3176 else {3177 hasDynamicSlots = true;3178 }3179 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3180 // check if this slot is conditional (v-if/v-for)3181 let vIf;3182 let vElse;3183 let vFor;3184 if ((vIf = findDir(slotElement, 'if'))) {3185 hasDynamicSlots = true;3186 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3187 }3188 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3189 // find adjacent v-if3190 let j = i;3191 let prev;3192 while (j--) {3193 prev = children[j];3194 if (prev.type !== 3 /* COMMENT */) {3195 break;3196 }3197 }3198 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3199 // remove node3200 children.splice(i, 1);3201 i--;3202 // attach this slot to previous conditional3203 let conditional = dynamicSlots[dynamicSlots.length - 1];3204 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3205 conditional = conditional.alternate;3206 }3207 conditional.alternate = vElse.exp3208 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3209 : buildDynamicSlot(slotName, slotFunction);3210 }3211 else {3212 context.onError(createCompilerError(35 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3213 }3214 }3215 else if ((vFor = findDir(slotElement, 'for'))) {3216 hasDynamicSlots = true;3217 const parseResult = vFor.parseResult ||3218 parseForExpression(vFor.exp, context);3219 if (parseResult) {3220 // Render the dynamic slots as an array and add it to the createSlot()3221 // args. The runtime knows how to handle it appropriately.3222 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3223 parseResult.source,3224 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3225 ]));3226 }3227 else {3228 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3229 }3230 }3231 else {3232 // check duplicate static names3233 if (staticSlotName) {3234 if (seenSlotNames.has(staticSlotName)) {3235 context.onError(createCompilerError(43 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3236 continue;3237 }3238 seenSlotNames.add(staticSlotName);
...
compiler-core.cjs.prod.js
Source:compiler-core.cjs.prod.js
...2889 childBlock.isBlock = true;2890 helper(OPEN_BLOCK);2891 helper(CREATE_BLOCK);2892 }2893 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));2894 };2895 });2896});2897// target-agnostic transform used for both Client and SSR2898function processFor(node, dir, context, processCodegen) {2899 if (!dir.exp) {2900 context.onError(createCompilerError(36 /* X_V_FOR_NO_EXPRESSION */, dir.loc));2901 return;2902 }2903 const parseResult = parseForExpression(2904 // can only be simple expression because vFor transform is applied2905 // before expression transform.2906 dir.exp, context);2907 if (!parseResult) {2908 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));2909 return;2910 }2911 const { addIdentifiers, removeIdentifiers, scopes } = context;2912 const { source, value, key, index } = parseResult;2913 const forNode = {2914 type: 11 /* FOR */,2915 loc: dir.loc,2916 source,2917 valueAlias: value,2918 keyAlias: key,2919 objectIndexAlias: index,2920 parseResult,2921 children: node.tagType === 3 /* TEMPLATE */ ? node.children : [node]2922 };2923 context.replaceNode(forNode);2924 // bookkeeping2925 scopes.vFor++;2926 if ( context.prefixIdentifiers) {2927 // scope management2928 // inject identifiers to context2929 value && addIdentifiers(value);2930 key && addIdentifiers(key);2931 index && addIdentifiers(index);2932 }2933 const onExit = processCodegen && processCodegen(forNode);2934 return () => {2935 scopes.vFor--;2936 if ( context.prefixIdentifiers) {2937 value && removeIdentifiers(value);2938 key && removeIdentifiers(key);2939 index && removeIdentifiers(index);2940 }2941 if (onExit)2942 onExit();2943 };2944}2945const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;2946// This regex doesn't cover the case if key or index aliases have destructuring,2947// but those do not make sense in the first place, so this works in practice.2948const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;2949const stripParensRE = /^\(|\)$/g;2950function parseForExpression(input, context) {2951 const loc = input.loc;2952 const exp = input.content;2953 const inMatch = exp.match(forAliasRE);2954 if (!inMatch)2955 return;2956 const [, LHS, RHS] = inMatch;2957 const result = {2958 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),2959 value: undefined,2960 key: undefined,2961 index: undefined2962 };2963 if ( context.prefixIdentifiers) {2964 result.source = processExpression(result.source, context);2965 }2966 let valueContent = LHS.trim()2967 .replace(stripParensRE, '')2968 .trim();2969 const trimmedOffset = LHS.indexOf(valueContent);2970 const iteratorMatch = valueContent.match(forIteratorRE);2971 if (iteratorMatch) {2972 valueContent = valueContent.replace(forIteratorRE, '').trim();2973 const keyContent = iteratorMatch[1].trim();2974 let keyOffset;2975 if (keyContent) {2976 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);2977 result.key = createAliasExpression(loc, keyContent, keyOffset);2978 if ( context.prefixIdentifiers) {2979 result.key = processExpression(result.key, context, true);2980 }2981 }2982 if (iteratorMatch[2]) {2983 const indexContent = iteratorMatch[2].trim();2984 if (indexContent) {2985 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key2986 ? keyOffset + keyContent.length2987 : trimmedOffset + valueContent.length));2988 if ( context.prefixIdentifiers) {2989 result.index = processExpression(result.index, context, true);2990 }2991 }2992 }2993 }2994 if (valueContent) {2995 result.value = createAliasExpression(loc, valueContent, trimmedOffset);2996 if ( context.prefixIdentifiers) {2997 result.value = processExpression(result.value, context, true);2998 }2999 }3000 return result;3001}3002function createAliasExpression(range, content, offset) {3003 return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));3004}3005function createForLoopParams({ value, key, index }) {3006 const params = [];3007 if (value) {3008 params.push(value);3009 }3010 if (key) {3011 if (!value) {3012 params.push(createSimpleExpression(`_`, false));3013 }3014 params.push(key);3015 }3016 if (index) {3017 if (!key) {3018 if (!value) {3019 params.push(createSimpleExpression(`_`, false));3020 }3021 params.push(createSimpleExpression(`__`, false));3022 }3023 params.push(index);3024 }3025 return params;3026}3027const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic;3028const defaultFallback = createSimpleExpression(`undefined`, false);3029// A NodeTransform that:3030// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed3031// by transformExpression. This is only applied in non-browser builds with3032// { prefixIdentifiers: true }.3033// 2. Track v-slot depths so that we know a slot is inside another slot.3034// Note the exit callback is executed before buildSlots() on the same node,3035// so only nested slots see positive numbers.3036const trackSlotScopes = (node, context) => {3037 if (node.type === 1 /* ELEMENT */ &&3038 (node.tagType === 1 /* COMPONENT */ ||3039 node.tagType === 3 /* TEMPLATE */)) {3040 // We are only checking non-empty v-slot here3041 // since we only care about slots that introduce scope variables.3042 const vSlot = findDir(node, 'slot');3043 if (vSlot) {3044 const slotProps = vSlot.exp;3045 if ( context.prefixIdentifiers) {3046 slotProps && context.addIdentifiers(slotProps);3047 }3048 context.scopes.vSlot++;3049 return () => {3050 if ( context.prefixIdentifiers) {3051 slotProps && context.removeIdentifiers(slotProps);3052 }3053 context.scopes.vSlot--;3054 };3055 }3056 }3057};3058// A NodeTransform that tracks scope identifiers for scoped slots with v-for.3059// This transform is only applied in non-browser builds with { prefixIdentifiers: true }3060const trackVForSlotScopes = (node, context) => {3061 let vFor;3062 if (isTemplateNode(node) &&3063 node.props.some(isVSlot) &&3064 (vFor = findDir(node, 'for'))) {3065 const result = (vFor.parseResult = parseForExpression(vFor.exp, context));3066 if (result) {3067 const { value, key, index } = result;3068 const { addIdentifiers, removeIdentifiers } = context;3069 value && addIdentifiers(value);3070 key && addIdentifiers(key);3071 index && addIdentifiers(index);3072 return () => {3073 value && removeIdentifiers(value);3074 key && removeIdentifiers(key);3075 index && removeIdentifiers(index);3076 };3077 }3078 }3079};3080const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);3081// Instead of being a DirectiveTransform, v-slot processing is called during3082// transformElement to build the slots object for a component.3083function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {3084 const { children, loc } = node;3085 const slotsProperties = [];3086 const dynamicSlots = [];3087 const buildDefaultSlotProperty = (props, children) => createObjectProperty(`default`, buildSlotFn(props, children, loc));3088 // If the slot is inside a v-for or another v-slot, force it to be dynamic3089 // since it likely uses a scope variable.3090 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;3091 // with `prefixIdentifiers: true`, this can be further optimized to make3092 // it dynamic only when the slot actually uses the scope variables.3093 if ( context.prefixIdentifiers) {3094 hasDynamicSlots = hasScopeRef(node, context.identifiers);3095 }3096 // 1. Check for default slot with slotProps on component itself.3097 // <Comp v-slot="{ prop }"/>3098 const onComponentDefaultSlot = findDir(node, 'slot', true);3099 if (onComponentDefaultSlot) {3100 const { arg, exp, loc } = onComponentDefaultSlot;3101 if (arg) {3102 context.onError(createCompilerError(41 /* X_V_SLOT_NAMED_SLOT_ON_COMPONENT */, loc));3103 }3104 slotsProperties.push(buildDefaultSlotProperty(exp, children));3105 }3106 // 2. Iterate through children and check for template slots3107 // <template v-slot:foo="{ prop }">3108 let hasTemplateSlots = false;3109 let hasNamedDefaultSlot = false;3110 const implicitDefaultChildren = [];3111 const seenSlotNames = new Set();3112 for (let i = 0; i < children.length; i++) {3113 const slotElement = children[i];3114 let slotDir;3115 if (!isTemplateNode(slotElement) ||3116 !(slotDir = findDir(slotElement, 'slot', true))) {3117 // not a <template v-slot>, skip.3118 if (slotElement.type !== 3 /* COMMENT */) {3119 implicitDefaultChildren.push(slotElement);3120 }3121 continue;3122 }3123 if (onComponentDefaultSlot) {3124 // already has on-component default slot - this is incorrect usage.3125 context.onError(createCompilerError(42 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));3126 break;3127 }3128 hasTemplateSlots = true;3129 const { children: slotChildren, loc: slotLoc } = slotElement;3130 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;3131 // check if name is dynamic.3132 let staticSlotName;3133 if (isStaticExp(slotName)) {3134 staticSlotName = slotName ? slotName.content : `default`;3135 }3136 else {3137 hasDynamicSlots = true;3138 }3139 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);3140 // check if this slot is conditional (v-if/v-for)3141 let vIf;3142 let vElse;3143 let vFor;3144 if ((vIf = findDir(slotElement, 'if'))) {3145 hasDynamicSlots = true;3146 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));3147 }3148 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {3149 // find adjacent v-if3150 let j = i;3151 let prev;3152 while (j--) {3153 prev = children[j];3154 if (prev.type !== 3 /* COMMENT */) {3155 break;3156 }3157 }3158 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {3159 // remove node3160 children.splice(i, 1);3161 i--;3162 // attach this slot to previous conditional3163 let conditional = dynamicSlots[dynamicSlots.length - 1];3164 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {3165 conditional = conditional.alternate;3166 }3167 conditional.alternate = vElse.exp3168 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)3169 : buildDynamicSlot(slotName, slotFunction);3170 }3171 else {3172 context.onError(createCompilerError(35 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));3173 }3174 }3175 else if ((vFor = findDir(slotElement, 'for'))) {3176 hasDynamicSlots = true;3177 const parseResult = vFor.parseResult ||3178 parseForExpression(vFor.exp, context);3179 if (parseResult) {3180 // Render the dynamic slots as an array and add it to the createSlot()3181 // args. The runtime knows how to handle it appropriately.3182 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [3183 parseResult.source,3184 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)3185 ]));3186 }3187 else {3188 context.onError(createCompilerError(37 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));3189 }3190 }3191 else {3192 // check duplicate static names3193 if (staticSlotName) {3194 if (seenSlotNames.has(staticSlotName)) {3195 context.onError(createCompilerError(43 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));3196 continue;3197 }3198 seenSlotNames.add(staticSlotName);
...
note-ast-transform.js
Source:note-ast-transform.js
...229 helper(OPEN_BLOCK);230 helper(CREATE_BLOCK);231 }232 }233 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));234 };235 });236 });237 function createCallExpression(callee, args = [], loc = locStub) {238 return {239 type: 14 /* JS_CALL_EXPRESSION */,240 loc,241 callee,242 arguments: args243 };244 }245 function createObjectProperty(key, value) {246 return {247 type: 16 /* JS_PROPERTY */,248 loc: locStub,249 key: isString(key) ? createSimpleExpression(key, true) : key,250 value251 };252 }253 function createSimpleExpression(content, isStatic, loc = locStub, isConstant = false) {254 return {255 type: 4 /* SIMPLE_EXPRESSION */,256 loc,257 isConstant,258 content,259 isStatic260 };261 }262 function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) {263 return {264 type: 18 /* JS_FUNCTION_EXPRESSION */,265 params,266 returns,267 newline,268 isSlot,269 loc270 };271 }272 function createForLoopParams({ value, key, index }) {273 const params = [];274 if (value) {275 params.push(value);276 }277 if (key) {278 if (!value) {279 params.push(createSimpleExpression(`_`, false));280 }281 params.push(key);282 }283 if (index) {284 if (!key) {285 if (!value) {286 params.push(createSimpleExpression(`_`, false));287 }288 params.push(createSimpleExpression(`__`, false));289 }290 params.push(index);291 }292 return params;293 }294 function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, loc = locStub) {295 if (context) {296 if (isBlock) {297 context.helper(OPEN_BLOCK);298 context.helper(CREATE_BLOCK);299 }300 else {301 context.helper(CREATE_VNODE);302 }303 if (directives) {304 context.helper(WITH_DIRECTIVES);305 }306 }307 return {308 type: 13 /* VNODE_CALL */,309 tag,310 props,311 children,312 patchFlag,313 dynamicProps,314 directives,315 isBlock,316 disableTracking,317 loc318 };319 }320 // AST Utilities ---------------------------------------------------------------321 // Some expressions, e.g. sequence and conditional expressions, are never322 // associated with template nodes, so their source locations are just a stub.323 // Container types like CompoundExpression also don't need a real location.324 const locStub = {325 source: '',326 start: { line: 1, column: 1, offset: 0 },327 end: { line: 1, column: 1, offset: 0 }328 };329 330 // Patch flags are optimization hints generated by the compiler.331 // when a block with dynamicChildren is encountered during diff, the algorithm332 // enters "optimized mode". In this mode, we know that the vdom is produced by333 // a render function generated by the compiler, so the algorithm only needs to334 // handle updates explicitly marked by these patch flags.335 // dev only flag -> name mapping336 const PatchFlagNames = {337 [1 /* TEXT */]: `TEXT`,338 [2 /* CLASS */]: `CLASS`,339 [4 /* STYLE */]: `STYLE`,340 [8 /* PROPS */]: `PROPS`,341 [16 /* FULL_PROPS */]: `FULL_PROPS`,342 [32 /* HYDRATE_EVENTS */]: `HYDRATE_EVENTS`,343 [64 /* STABLE_FRAGMENT */]: `STABLE_FRAGMENT`,344 [128 /* KEYED_FRAGMENT */]: `KEYED_FRAGMENT`,345 [256 /* UNKEYED_FRAGMENT */]: `UNKEYED_FRAGMENT`,346 [512 /* NEED_PATCH */]: `NEED_PATCH`,347 [1024 /* DYNAMIC_SLOTS */]: `DYNAMIC_SLOTS`,348 [-1 /* HOISTED */]: `HOISTED`,349 [-2 /* BAIL */]: `BAIL`350 };351 function createObjectProperty(key, value) {352 return {353 type: 16 /* JS_PROPERTY */,354 loc: locStub,355 key: isString(key) ? createSimpleExpression(key, true) : key,356 value357 };358 }359 360 // target-agnostic transform used for both Client and SSR361 function processFor(node, dir, context, processCodegen) {362 if (!dir.exp) {363 context.onError(createCompilerError(30 /* X_V_FOR_NO_EXPRESSION */, dir.loc));364 return;365 }366 const parseResult = parseForExpression(367 // can only be simple expression because vFor transform is applied368 // before expression transform.369 dir.exp, context);370 if (!parseResult) {371 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));372 return;373 }374 const { addIdentifiers, removeIdentifiers, scopes } = context;375 const { source, value, key, index } = parseResult;376 const forNode = {377 type: 11 /* FOR */,378 loc: dir.loc,379 source,380 valueAlias: value,381 keyAlias: key,382 objectIndexAlias: index,383 parseResult,384 children: isTemplateNode(node) ? node.children : [node]385 };386 context.replaceNode(forNode);387 // bookkeeping388 scopes.vFor++;389 const onExit = processCodegen && processCodegen(forNode);390 return () => {391 scopes.vFor--;392 if (onExit)393 onExit();394 };395 }396 const forNode = {397 type: 11 /* FOR */,398 loc: dir.loc,399 source,400 valueAlias: value,401 keyAlias: key,402 objectIndexAlias: index,403 parseResult,404 children: isTemplateNode(node) ? node.children : [node]405 };406 const transformExpression = (node, context) => {407 if (node.type === 5 /* INTERPOLATION */) {408 node.content = processExpression(node.content, context);409 }410 else if (node.type === 1 /* ELEMENT */) {411 // handle directives on element412 for (let i = 0; i < node.props.length; i++) {413 const dir = node.props[i];414 // do not process for v-on & v-for since they are special handled415 if (dir.type === 7 /* DIRECTIVE */ && dir.name !== 'for') {416 const exp = dir.exp;417 const arg = dir.arg;418 // do not process exp if this is v-on:arg - we need special handling419 // for wrapping inline statements.420 if (exp &&421 exp.type === 4 /* SIMPLE_EXPRESSION */ &&422 !(dir.name === 'on' && arg)) {423 dir.exp = processExpression(exp, context, 424 // slot args must be processed as function params425 dir.name === 'slot');426 }427 if (arg && arg.type === 4 /* SIMPLE_EXPRESSION */ && !arg.isStatic) {428 dir.arg = processExpression(arg, context);429 }430 }431 }432 }433 };434 const transformSlotOutlet = (node, context) => {435 if (isSlotOutlet(node)) {436 const { children, loc } = node;437 const { slotName, slotProps } = processSlotOutlet(node, context);438 const slotArgs = [439 context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,440 slotName441 ];442 if (slotProps) {443 slotArgs.push(slotProps);444 }445 if (children.length) {446 if (!slotProps) {447 slotArgs.push(`{}`);448 }449 slotArgs.push(createFunctionExpression([], children, false, false, loc));450 }451 node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);452 }453 };454 function isSlotOutlet(node) {455 return node.type === 1 /* ELEMENT */ && node.tagType === 2 /* SLOT */;456 }457 function processSlotOutlet(node, context) {458 let slotName = `"default"`;459 let slotProps = undefined;460 // check for <slot name="xxx" OR :name="xxx" />461 const name = findProp(node, 'name');462 if (name) {463 if (name.type === 6 /* ATTRIBUTE */ && name.value) {464 // static name465 slotName = JSON.stringify(name.value.content);466 }467 else if (name.type === 7 /* DIRECTIVE */ && name.exp) {468 // dynamic name469 slotName = name.exp;470 }471 }472 const propsWithoutName = name473 ? node.props.filter(p => p !== name)474 : node.props;475 if (propsWithoutName.length > 0) {476 const { props, directives } = buildProps(node, context, propsWithoutName);477 slotProps = props;478 if (directives.length) {479 context.onError(createCompilerError(35 /* X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));480 }481 }482 return {483 slotName,484 slotProps485 };486 }487 function buildProps(node, context, props = node.props, ssr = false) {488 const { tag, loc: elementLoc } = node;489 const isComponent = node.tagType === 1 /* COMPONENT */;490 let properties = [];491 const mergeArgs = [];492 const runtimeDirectives = [];493 // patchFlag analysis494 let patchFlag = 0;495 let hasRef = false;496 let hasClassBinding = false;497 let hasStyleBinding = false;498 let hasHydrationEventBinding = false;499 let hasDynamicKeys = false;500 let hasVnodeHook = false;501 const dynamicPropNames = [];502 const analyzePatchFlag = ({ key, value }) => {503 // if (content.startsWith('[')) {504 // isStatic = false;505 // if (!content.endsWith(']')) {506 // emitError(context, 26 /* X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);507 // }508 // content = content.substr(1, content.length - 2);509 // }510 if (isStaticExp(key)) { // const isStaticExp = (p) => p.type === 4 /* SIMPLE_EXPRESSION */ && p.isStatic;511 const name = key.content;512 const isEventHandler = isOn(name);513 if (!isComponent &&514 isEventHandler &&515 // omit the flag for click handlers because hydration gives click516 // dedicated fast path.517 name.toLowerCase() !== 'onclick' &&518 // omit v-model handlers519 name !== 'onUpdate:modelValue' &&520 // omit onVnodeXXX hooks521 !isReservedProp(name)) {522 hasHydrationEventBinding = true;523 }524 if (isEventHandler && isReservedProp(name)) {525 hasVnodeHook = true;526 }527 if (value.type === 20 /* JS_CACHE_EXPRESSION */ ||528 ((value.type === 4 /* SIMPLE_EXPRESSION */ ||529 value.type === 8 /* COMPOUND_EXPRESSION */) &&530 getStaticType(value) > 0)) {531 // skip if the prop is a cached handler or has constant value532 return;533 }534 if (name === 'ref') {535 hasRef = true;536 }537 else if (name === 'class' && !isComponent) {538 hasClassBinding = true;539 }540 else if (name === 'style' && !isComponent) {541 hasStyleBinding = true;542 }543 else if (name !== 'key' && !dynamicPropNames.includes(name)) {544 dynamicPropNames.push(name);545 }546 }547 else {548 hasDynamicKeys = true;549 }550 };551 for (let i = 0; i < props.length; i++) {552 // static attribute553 const prop = props[i];554 if (prop.type === 6 /* ATTRIBUTE */) {555 const { loc, name, value } = prop;556 if (name === 'ref') {557 hasRef = true;558 }559 // skip :is on <component>560 if (name === 'is' && tag === 'component') {561 continue;562 }563 properties.push(createObjectProperty(564 createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), 565 createSimpleExpression(value ? value.content : '', true, value ? value.loc : loc)566 )567 );568 }569 else {570 // directives571 const { name, arg, exp, loc } = prop;572 const isBind = name === 'bind';573 const isOn = name === 'on';574 // skip v-slot - it is handled by its dedicated transform.575 if (name === 'slot') {576 if (!isComponent) {577 context.onError(createCompilerError(39 /* X_V_SLOT_MISPLACED */, loc));578 }579 continue;580 }581 // skip v-once - it is handled by its dedicated transform.582 if (name === 'once') {583 continue;584 }585 // skip v-is and :is on <component>586 if (name === 'is' ||587 (isBind && tag === 'component' && isBindKey(arg, 'is'))) { // åèparseAttribute588 continue;589 }590 // skip v-on in SSR compilation591 if (isOn && ssr) {592 continue;593 }594 // special case for v-bind and v-on with no argument595 if (!arg && (isBind || isOn)) { // åèparseAttribute596 hasDynamicKeys = true;597 if (exp) {598 if (properties.length) {599 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));600 properties = [];601 }602 if (isBind) {603 mergeArgs.push(exp);604 }605 else {606 // v-on="obj" -> toHandlers(obj)607 mergeArgs.push({608 type: 14 /* JS_CALL_EXPRESSION */,609 loc,610 callee: context.helper(TO_HANDLERS),611 arguments: [exp]612 });613 }614 }615 else {616 context.onError(createCompilerError(isBind617 ? 33 /* X_V_BIND_NO_EXPRESSION */618 : 34 /* X_V_ON_NO_EXPRESSION */, loc));619 }620 continue;621 }622 const directiveTransform = context.directiveTransforms[name]; // on, bind. model623 if (directiveTransform) {624 // has built-in directive transform.625 const { props, needRuntime } = directiveTransform(prop, node, context);626 !ssr && props.forEach(analyzePatchFlag);627 properties.push(...props);628 if (needRuntime) {629 runtimeDirectives.push(prop);630 if (isSymbol(needRuntime)) {631 directiveImportMap.set(prop, needRuntime);632 }633 }634 }635 else {636 // no built-in transform, this is a user custom directive.637 runtimeDirectives.push(prop);638 }639 }640 }641 let propsExpression = undefined;642 // has v-bind="object" or v-on="object", wrap with mergeProps643 if (mergeArgs.length) {644 if (properties.length) {645 mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));646 }647 if (mergeArgs.length > 1) {648 propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);649 }650 else {651 // single v-bind with nothing else - no need for a mergeProps call652 propsExpression = mergeArgs[0];653 }654 }655 else if (properties.length) {656 propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);657 }658 // patchFlag analysis659 if (hasDynamicKeys) {660 patchFlag |= 16 /* FULL_PROPS */;661 }662 else {663 if (hasClassBinding) {664 patchFlag |= 2 /* CLASS */;665 }666 if (hasStyleBinding) {667 patchFlag |= 4 /* STYLE */;668 }669 if (dynamicPropNames.length) {670 patchFlag |= 8 /* PROPS */;671 }672 if (hasHydrationEventBinding) {673 patchFlag |= 32 /* HYDRATE_EVENTS */;674 }675 }676 if ((patchFlag === 0 || patchFlag === 32 /* HYDRATE_EVENTS */) &&677 (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {678 patchFlag |= 512 /* NEED_PATCH */;679 }680 return {681 props: propsExpression,682 directives: runtimeDirectives,683 patchFlag,684 dynamicPropNames685 };686 }687 // Dedupe props in an object literal.688 // Literal duplicated attributes would have been warned during the parse phase,689 // however, it's possible to encounter duplicated `onXXX` handlers with different690 // modifiers. We also need to merge static and dynamic class / style attributes.691 // - onXXX handlers / style: merge into array692 // - class: merge into single expression with concatenation693 function dedupeProperties(properties) {694 const knownProps = new Map();695 const deduped = [];696 for (let i = 0; i < properties.length; i++) {697 const prop = properties[i];698 // dynamic keys are always allowed699 if (prop.key.type === 8 /* COMPOUND_EXPRESSION */ || !prop.key.isStatic) { // onXXX700 deduped.push(prop);701 continue;702 }703 const name = prop.key.content;704 const existing = knownProps.get(name);705 if (existing) {706 if (name === 'style' || name === 'class' || name.startsWith('on')) {707 mergeAsArray(existing, prop);708 }709 // unexpected duplicate, should have emitted error during parse710 }711 else {712 knownProps.set(name, prop);713 deduped.push(prop);714 }715 }716 return deduped;717 }718 function createArrayExpression(elements, loc = locStub) {719 return {720 type: 17 /* JS_ARRAY_EXPRESSION */,721 loc,722 elements723 };724 }725 function getStaticType(node, resultCache = new Map()) {726 switch (node.type) {727 case 1 /* ELEMENT */:728 if (node.tagType !== 0 /* ELEMENT */) {729 return 0 /* NOT_STATIC */;730 }731 const cached = resultCache.get(node);732 if (cached !== undefined) {733 return cached;734 }735 const codegenNode = node.codegenNode;736 if (codegenNode.type !== 13 /* VNODE_CALL */) {737 return 0 /* NOT_STATIC */;738 }739 const flag = getPatchFlag(codegenNode);740 if (!flag && !hasNonHoistableProps(node)) {741 // element self is static. check its children.742 let returnType = 1 /* FULL_STATIC */;743 for (let i = 0; i < node.children.length; i++) {744 const childType = getStaticType(node.children[i], resultCache);745 if (childType === 0 /* NOT_STATIC */) {746 resultCache.set(node, 0 /* NOT_STATIC */);747 return 0 /* NOT_STATIC */;748 }749 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {750 returnType = 2 /* HAS_RUNTIME_CONSTANT */;751 }752 }753 // check if any of the props contain runtime constants754 if (returnType !== 2 /* HAS_RUNTIME_CONSTANT */) {755 for (let i = 0; i < node.props.length; i++) {756 const p = node.props[i];757 if (p.type === 7 /* DIRECTIVE */ &&758 p.name === 'bind' &&759 p.exp &&760 (p.exp.type === 8 /* COMPOUND_EXPRESSION */ ||761 p.exp.isRuntimeConstant)) {762 returnType = 2 /* HAS_RUNTIME_CONSTANT */;763 }764 }765 }766 // only svg/foreignObject could be block here, however if they are767 // stati then they don't need to be blocks since there will be no768 // nested updates.769 if (codegenNode.isBlock) {770 codegenNode.isBlock = false;771 }772 resultCache.set(node, returnType);773 return returnType;774 }775 else {776 resultCache.set(node, 0 /* NOT_STATIC */);777 return 0 /* NOT_STATIC */;778 }779 case 2 /* TEXT */:780 case 3 /* COMMENT */:781 return 1 /* FULL_STATIC */;782 case 9 /* IF */:783 case 11 /* FOR */:784 case 10 /* IF_BRANCH */:785 return 0 /* NOT_STATIC */;786 case 5 /* INTERPOLATION */:787 case 12 /* TEXT_CALL */:788 return getStaticType(node.content, resultCache);789 case 4 /* SIMPLE_EXPRESSION */:790 return node.isConstant791 ? node.isRuntimeConstant792 ? 2 /* HAS_RUNTIME_CONSTANT */793 : 1 /* FULL_STATIC */794 : 0 /* NOT_STATIC */;795 case 8 /* COMPOUND_EXPRESSION */:796 let returnType = 1 /* FULL_STATIC */;797 for (let i = 0; i < node.children.length; i++) {798 const child = node.children[i];799 if (isString(child) || isSymbol(child)) {800 continue;801 }802 const childType = getStaticType(child, resultCache);803 if (childType === 0 /* NOT_STATIC */) {804 return 0 /* NOT_STATIC */;805 }806 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {807 returnType = 2 /* HAS_RUNTIME_CONSTANT */;808 }809 }810 return returnType;811 default:812 return 0 /* NOT_STATIC */;813 }814 }815 const transformElement = (node, context) => {816 if (!(node.type === 1 /* ELEMENT */ &&817 (node.tagType === 0 /* ELEMENT */ ||818 node.tagType === 1 /* COMPONENT */))) {819 return;820 }821 // perform the work on exit, after all child expressions have been822 // processed and merged.823 return function postTransformElement() {824 const { tag, props } = node;825 const isComponent = node.tagType === 1 /* COMPONENT */;826 // The goal of the transform is to create a codegenNode implementing the827 // VNodeCall interface.828 const vnodeTag = isComponent829 ? resolveComponentType(node, context)830 : `"${tag}"`;831 const isDynamicComponent = isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;832 let vnodeProps;833 let vnodeChildren;834 let vnodePatchFlag;835 let patchFlag = 0;836 let vnodeDynamicProps;837 let dynamicPropNames;838 let vnodeDirectives;839 let shouldUseBlock = 840 // dynamic component may resolve to plain elements841 isDynamicComponent ||842 vnodeTag === TELEPORT ||843 vnodeTag === SUSPENSE ||844 (!isComponent &&845 // <svg> and <foreignObject> must be forced into blocks so that block846 // updates inside get proper isSVG flag at runtime. (#639, #643)847 // This is technically web-specific, but splitting the logic out of core848 // leads to too much unnecessary complexity.849 (tag === 'svg' ||850 tag === 'foreignObject' ||851 // #938: elements with dynamic keys should be forced into blocks852 findProp(node, 'key', true)));853 // props854 if (props.length > 0) {855 const propsBuildResult = buildProps(node, context);856 vnodeProps = propsBuildResult.props;857 patchFlag = propsBuildResult.patchFlag;858 dynamicPropNames = propsBuildResult.dynamicPropNames;859 const directives = propsBuildResult.directives;860 vnodeDirectives =861 directives && directives.length862 ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))863 : undefined;864 }865 // children866 if (node.children.length > 0) {867 if (vnodeTag === KEEP_ALIVE) {868 // Although a built-in component, we compile KeepAlive with raw children869 // instead of slot functions so that it can be used inside Transition870 // or other Transition-wrapping HOCs.871 // To ensure correct updates with block optimizations, we need to:872 // 1. Force keep-alive into a block. This avoids its children being873 // collected by a parent block.874 shouldUseBlock = true;875 // 2. Force keep-alive to always be updated, since it uses raw children.876 patchFlag |= 1024 /* DYNAMIC_SLOTS */;877 if ( node.children.length > 1) {878 context.onError(createCompilerError(44 /* X_KEEP_ALIVE_INVALID_CHILDREN */, {879 start: node.children[0].loc.start,880 end: node.children[node.children.length - 1].loc.end,881 source: ''882 }));883 }884 }885 const shouldBuildAsSlots = isComponent &&886 // Teleport is not a real component and has dedicated runtime handling887 vnodeTag !== TELEPORT &&888 // explained above.889 vnodeTag !== KEEP_ALIVE;890 if (shouldBuildAsSlots) {891 const { slots, hasDynamicSlots } = buildSlots(node, context);892 vnodeChildren = slots;893 if (hasDynamicSlots) {894 patchFlag |= 1024 /* DYNAMIC_SLOTS */;895 }896 }897 else if (node.children.length === 1 && vnodeTag !== TELEPORT) {898 const child = node.children[0];899 const type = child.type;900 // check for dynamic text children901 const hasDynamicTextChild = type === 5 /* INTERPOLATION */ ||902 type === 8 /* COMPOUND_EXPRESSION */;903 if (hasDynamicTextChild && !getStaticType(child)) {904 patchFlag |= 1 /* TEXT */;905 }906 // pass directly if the only child is a text node907 // (plain / interpolation / expression)908 if (hasDynamicTextChild || type === 2 /* TEXT */) {909 vnodeChildren = child;910 }911 else {912 vnodeChildren = node.children;913 }914 }915 else {916 vnodeChildren = node.children;917 }918 }919 // patchFlag & dynamicPropNames920 if (patchFlag !== 0) {921 {922 if (patchFlag < 0) {923 // special flags (negative and mutually exclusive)924 vnodePatchFlag = patchFlag + ` /* ${PatchFlagNames[patchFlag]} */`;925 }926 else {927 // bitwise flags928 const flagNames = Object.keys(PatchFlagNames)929 .map(Number)930 .filter(n => n > 0 && patchFlag & n)931 .map(n => PatchFlagNames[n])932 .join(`, `);933 vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;934 }935 }936 if (dynamicPropNames && dynamicPropNames.length) {937 vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);938 }939 }940 // function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, loc = locStub) 941 node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, node.loc);942 };943 };944 function stringifyDynamicPropNames(props) {945 let propsNamesString = `[`;946 for (let i = 0, l = props.length; i < l; i++) {947 propsNamesString += JSON.stringify(props[i]);948 if (i < l - 1)949 propsNamesString += ', ';950 }951 return propsNamesString + `]`;952 }953 /**954 * Even for a node with no patch flag, it is possible for it to contain955 * non-hoistable expressions that refers to scope variables, e.g. compiler956 * injected keys or cached event handlers. Therefore we need to always check the957 * codegenNode's props to be sure.958 */959 function hasNonHoistableProps(node) {960 const props = getNodeProps(node);961 if (props && props.type === 15 /* JS_OBJECT_EXPRESSION */) {962 const { properties } = props;963 for (let i = 0; i < properties.length; i++) {964 const { key, value } = properties[i];965 if (key.type !== 4 /* SIMPLE_EXPRESSION */ ||966 !key.isStatic ||967 (value.type !== 4 /* SIMPLE_EXPRESSION */ ||968 (!value.isStatic && !value.isConstant))) {969 return true;970 }971 }972 }973 return false;974 }975 const vModelSelect = {976 created(el, binding, vnode) {977 addEventListener(el, 'change', () => {978 const selectedVal = Array.prototype.filter979 .call(el.options, (o) => o.selected)980 .map(getValue);981 el._assign(el.multiple ? selectedVal : selectedVal[0]);982 });983 el._assign = getModelAssigner(vnode);984 },985 // set value in mounted & updated because <select> relies on its children986 // <option>s.987 mounted(el, { value }) {988 setSelected(el, value);989 },990 beforeUpdate(el, _binding, vnode) {991 el._assign = getModelAssigner(vnode);992 },993 updated(el, { value }) {994 setSelected(el, value);995 }996 };997 /**998 * 999 * node.type:0 ROOT 1 ELEMENT 2 TEXT 3 COMMENT 4 SIMPLE_EXPRESSION 5 INTERPOLATION 8 COMPOUND_EXPRESSION 9 IF 10 IF_BRANCH IF 11 FOR 12 TEXT_CALL1000 * 1001 * static type 0 NOT_STATIC 1 FULL_STATIC 2 HAS_RUNTIME_CONSTANT1002 * tagtype: 0 element 1 template 2 slot1003 * 1004 * codegennode.patchFlag -2 BAIL -1 HOISTED 1 TEXT 2 CLASS 4 STYLE 8 PROPS 16 FULL_PROPS 32 HYDRATE_EVENTS 64 STABLE_FRAGMENT 128 KEYED_FRAGMENT 256 UNKEYED_FRAGMENT 512 NEED_PATCH 1024 DYNAMIC_SLOTS1005 * 1006 */1007 function getStaticType(node, resultCache = new Map()) { // 0 NOT_STATIC 1 FULL_STATIC 2 HAS_RUNTIME_CONSTANT1008 switch (node.type) {1009 case 1 /* ELEMENT */:1010 if (node.tagType !== 0 /* ELEMENT */) {1011 return 0 /* NOT_STATIC */;1012 }1013 const cached = resultCache.get(node);1014 if (cached !== undefined) {1015 return cached;1016 }1017 const codegenNode = node.codegenNode;1018 if (codegenNode.type !== 13 /* VNODE_CALL */) {1019 return 0 /* NOT_STATIC */;1020 }1021 const flag = getPatchFlag(codegenNode);1022 if (!flag && !hasNonHoistableProps(node)) {1023 // element self is static. check its children.1024 let returnType = 1 /* FULL_STATIC */;1025 for (let i = 0; i < node.children.length; i++) {1026 const childType = getStaticType(node.children[i], resultCache);1027 if (childType === 0 /* NOT_STATIC */) {1028 resultCache.set(node, 0 /* NOT_STATIC */);1029 return 0 /* NOT_STATIC */;1030 }1031 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {1032 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1033 }1034 }1035 // check if any of the props contain runtime constants1036 if (returnType !== 2 /* HAS_RUNTIME_CONSTANT */) {1037 for (let i = 0; i < node.props.length; i++) {1038 const p = node.props[i];1039 if (p.type === 7 /* DIRECTIVE */ &&1040 p.name === 'bind' &&1041 p.exp &&1042 (p.exp.type === 8 /* COMPOUND_EXPRESSION */ ||1043 p.exp.isRuntimeConstant)) {1044 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1045 }1046 }1047 }1048 // only svg/foreignObject could be block here, however if they are1049 // stati then they don't need to be blocks since there will be no1050 // nested updates.1051 if (codegenNode.isBlock) {1052 codegenNode.isBlock = false;1053 }1054 resultCache.set(node, returnType);1055 return returnType;1056 }1057 else {1058 resultCache.set(node, 0 /* NOT_STATIC */);1059 return 0 /* NOT_STATIC */;1060 }1061 case 2 /* TEXT */:1062 case 3 /* COMMENT */:1063 return 1 /* FULL_STATIC */;1064 case 9 /* IF */:1065 case 11 /* FOR */:1066 case 10 /* IF_BRANCH */:1067 return 0 /* NOT_STATIC */;1068 case 5 /* INTERPOLATION */:1069 case 12 /* TEXT_CALL */:1070 return getStaticType(node.content, resultCache);1071 case 4 /* SIMPLE_EXPRESSION */:1072 return node.isConstant1073 ? node.isRuntimeConstant1074 ? 2 /* HAS_RUNTIME_CONSTANT */1075 : 1 /* FULL_STATIC */1076 : 0 /* NOT_STATIC */;1077 case 8 /* COMPOUND_EXPRESSION */:1078 let returnType = 1 /* FULL_STATIC */;1079 for (let i = 0; i < node.children.length; i++) {1080 const child = node.children[i];1081 if (isString(child) || isSymbol(child)) {1082 continue;1083 }1084 const childType = getStaticType(child, resultCache);1085 if (childType === 0 /* NOT_STATIC */) {1086 return 0 /* NOT_STATIC */;1087 }1088 else if (childType === 2 /* HAS_RUNTIME_CONSTANT */) {1089 returnType = 2 /* HAS_RUNTIME_CONSTANT */;1090 }1091 }1092 return returnType;1093 default:1094 return 0 /* NOT_STATIC */;1095 }1096 }1097 /**1098 * context.scopes1099 * scopes: {1100 vFor: 0,1101 vSlot: 0,1102 vPre: 0,1103 vOnce: 01104 },1105 */1106 function isCoreComponent(tag) {1107 if (isBuiltInType(tag, 'Teleport')) {1108 return TELEPORT;1109 }1110 else if (isBuiltInType(tag, 'Suspense')) {1111 return SUSPENSE;1112 }1113 else if (isBuiltInType(tag, 'KeepAlive')) {1114 return KEEP_ALIVE;1115 }1116 else if (isBuiltInType(tag, 'BaseTransition')) {1117 return BASE_TRANSITION;1118 }1119 }1120 const buildClientSlotFn = (props, children, loc) => {1121 createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);1122 }1123 function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) {1124 return {1125 type: 18 /* JS_FUNCTION_EXPRESSION */,1126 params,1127 returns,1128 newline,1129 isSlot,1130 loc1131 };1132 }1133 function buildDynamicSlot(name, fn) {1134 return createObjectExpression([1135 createObjectProperty(`name`, name),1136 createObjectProperty(`fn`, fn)1137 ]);1138 }1139 function createConditionalExpression(test, consequent, alternate, newline = true) {1140 return {1141 type: 19 /* JS_CONDITIONAL_EXPRESSION */,1142 test,1143 consequent,1144 alternate,1145 newline,1146 loc: locStub1147 };1148 }1149 function createForLoopParams({ value, key, index }) {1150 const params = [];1151 if (value) {1152 params.push(value);1153 }1154 if (key) {1155 if (!value) {1156 params.push(createSimpleExpression(`_`, false));1157 }1158 params.push(key);1159 }1160 if (index) {1161 if (!key) {1162 if (!value) {1163 params.push(createSimpleExpression(`_`, false));1164 }1165 params.push(createSimpleExpression(`__`, false));1166 }1167 params.push(index);1168 }1169 return params;1170 }1171 // Instead of being a DirectiveTransform, v-slot processing is called during1172 // transformElement to build the slots object for a component.1173 function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {1174 context.helper(WITH_CTX);1175 const { children, loc } = node;1176 const slotsProperties = [];1177 const dynamicSlots = [];1178 const buildDefaultSlotProperty = (props, children) => createObjectProperty(`default`, buildSlotFn(props, children, loc));1179 // If the slot is inside a v-for or another v-slot, force it to be dynamic1180 // since it likely uses a scope variable.1181 1182 let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;1183 // 1. Check for slot with slotProps on component itself.1184 // <Comp v-slot="{ prop }"/>1185 const onComponentSlot = findDir(node, 'slot', true);1186 if (onComponentSlot) {1187 const { arg, exp } = onComponentSlot;1188 if (arg && !isStaticExp(arg)) {1189 hasDynamicSlots = true;1190 }1191 slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));1192 }1193 // 2. Iterate through children and check for template slots1194 // <template v-slot:foo="{ prop }">1195 let hasTemplateSlots = false;1196 let hasNamedDefaultSlot = false;1197 const implicitDefaultChildren = [];1198 const seenSlotNames = new Set();1199 for (let i = 0; i < children.length; i++) {1200 const slotElement = children[i];1201 let slotDir;1202 if (!isTemplateNode(slotElement) ||1203 !(slotDir = findDir(slotElement, 'slot', true))) {1204 // not a <template v-slot>, skip.1205 if (slotElement.type !== 3 /* COMMENT */) {1206 implicitDefaultChildren.push(slotElement);1207 }1208 continue;1209 }1210 if (onComponentSlot) {1211 // already has on-component slot - this is incorrect usage.1212 context.onError(createCompilerError(36 /* X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));1213 break;1214 }1215 hasTemplateSlots = true;1216 const { children: slotChildren, loc: slotLoc } = slotElement;1217 const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;1218 // check if name is dynamic.1219 let staticSlotName;1220 if (isStaticExp(slotName)) {1221 staticSlotName = slotName ? slotName.content : `default`;1222 }1223 else {1224 hasDynamicSlots = true;1225 }1226 const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);1227 // check if this slot is conditional (v-if/v-for)1228 let vIf;1229 let vElse;1230 let vFor;1231 if ((vIf = findDir(slotElement, 'if'))) {1232 hasDynamicSlots = true;1233 dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback));1234 }1235 else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {1236 // find adjacent v-if1237 let j = i;1238 let prev;1239 while (j--) {1240 prev = children[j];1241 if (prev.type !== 3 /* COMMENT */) {1242 break;1243 }1244 }1245 if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {1246 // remove node1247 children.splice(i, 1);1248 i--;1249 // attach this slot to previous conditional1250 let conditional = dynamicSlots[dynamicSlots.length - 1];1251 while (conditional.alternate.type === 19 /* JS_CONDITIONAL_EXPRESSION */) {1252 conditional = conditional.alternate;1253 }1254 conditional.alternate = vElse.exp1255 ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction), defaultFallback)1256 : buildDynamicSlot(slotName, slotFunction);1257 }1258 else {1259 context.onError(createCompilerError(29 /* X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));1260 }1261 }1262 else if ((vFor = findDir(slotElement, 'for'))) {1263 hasDynamicSlots = true;1264 const parseResult = vFor.parseResult ||1265 parseForExpression(vFor.exp, context);1266 if (parseResult) {1267 // Render the dynamic slots as an array and add it to the createSlot()1268 // args. The runtime knows how to handle it appropriately.1269 dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [1270 parseResult.source,1271 createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)1272 ]));1273 }1274 else {1275 context.onError(createCompilerError(31 /* X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));1276 }1277 }1278 else {1279 // check duplicate static names1280 if (staticSlotName) {1281 if (seenSlotNames.has(staticSlotName)) {1282 context.onError(createCompilerError(37 /* X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));1283 continue;1284 }1285 seenSlotNames.add(staticSlotName);...
stable_fragment.js
Source:stable_fragment.js
...259 helper(OPEN_BLOCK);260 helper(CREATE_BLOCK);261 }262 }263 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));264 };265 });...
vFor.js
Source:vFor.js
...92 codegenNode_1.callee = helper(runtimeHelpers_1.CREATE_BLOCK);93 }94 childBlock = utils_1.createBlockExpression(codegenNode_1, context);95 }96 renderExp.arguments.push(ast_1.createFunctionExpression(createForLoopParams(parseResult), childBlock, true));97 };98});99var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;100var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;101var stripParensRE = /^\(|\)$/g;102function parseForExpression(input, context) {103 var loc = input.loc;104 var exp = input.content;105 var inMatch = exp.match(forAliasRE);106 if (!inMatch)107 return;108 var LHS = inMatch[1], RHS = inMatch[2];109 var result = {110 source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),111 value: undefined,112 key: undefined,113 index: undefined114 };115 if (!__BROWSER__ && context.prefixIdentifiers) {116 result.source = transformExpression_1.processExpression(result.source, context);117 }118 var valueContent = LHS.trim()119 .replace(stripParensRE, '')120 .trim();121 var trimmedOffset = LHS.indexOf(valueContent);122 var iteratorMatch = valueContent.match(forIteratorRE);123 if (iteratorMatch) {124 valueContent = valueContent.replace(forIteratorRE, '').trim();125 var keyContent = iteratorMatch[1].trim();126 var keyOffset = void 0;127 if (keyContent) {128 keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);129 result.key = createAliasExpression(loc, keyContent, keyOffset);130 if (!__BROWSER__ && context.prefixIdentifiers) {131 result.key = transformExpression_1.processExpression(result.key, context, true);132 }133 }134 if (iteratorMatch[2]) {135 var indexContent = iteratorMatch[2].trim();136 if (indexContent) {137 result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key138 ? keyOffset + keyContent.length139 : trimmedOffset + valueContent.length));140 if (!__BROWSER__ && context.prefixIdentifiers) {141 result.index = transformExpression_1.processExpression(result.index, context, true);142 }143 }144 }145 }146 if (valueContent) {147 result.value = createAliasExpression(loc, valueContent, trimmedOffset);148 if (!__BROWSER__ && context.prefixIdentifiers) {149 result.value = transformExpression_1.processExpression(result.value, context, true);150 }151 }152 return result;153}154exports.parseForExpression = parseForExpression;155function createAliasExpression(range, content, offset) {156 return ast_1.createSimpleExpression(content, false, utils_1.getInnerRange(range, offset, content.length));157}158function createForLoopParams(_a) {159 var value = _a.value, key = _a.key, index = _a.index;160 var params = [];161 if (value) {162 params.push(value);163 }164 if (key) {165 if (!value) {166 params.push(ast_1.createSimpleExpression("_", false));167 }168 params.push(key);169 }170 if (index) {171 if (!key) {172 if (!value) {...
vSlot.js
Source:vSlot.js
...129 dynamicSlots.push(130 createCallExpression(context.helper(RENDER_LIST), [131 parseResult.source,132 createFunctionExpression(133 createForLoopParams(parseResult),134 buildDynamicSlot(slotName, slotFunction),135 true136 )137 ])138 )139 } else {140 }141 } else {142 if (staticSlotName) {143 if (seenSlotNames.has(staticSlotName)) {144 continue145 }146 seenSlotNames.add(staticSlotName)147 if (staticSlotName === 'default') {...
disableTracking.js
Source:disableTracking.js
...99 helper(OPEN_BLOCK);100 helper(CREATE_BLOCK);101 }102 }103 renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));104 };105 });...
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');2const forLoopParams = createForLoopParams({3});4console.log(forLoopParams);5const { createForLoopParams } = require('playwright');6const forLoopParams = createForLoopParams({7});8console.log(forLoopParams);9import { createForLoopParams } from 'playwright/lib/utils/forLoopParams';10const forLoopParams = createForLoopParams({11});12console.log(forLoopParams);13import { createForLoopParams } from 'playwright';14const forLoopParams = createForLoopParams({15});16console.log(forLoopParams);17const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');18const forLoopParams = createForLoopParams({19});20console.log(forLoopParams);21const { createForLoopParams } = require('playwright');22const forLoopParams = createForLoopParams({23});24console.log(forLoopParams);25import { createForLoopParams } from 'playwright/lib/utils/forLoopParams';26const forLoopParams = createForLoopParams({
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 const params = createForLoopParams(0, 10, 1);5 console.log(params);6});7test('test', async ({ page }) => {8 const params = createForLoopParams(0, 10, 1);9 for (const param of params) {10 console.log(param.value);11 }12});13test('test', async ({ page }) => {14 const params = createForLoopParams(0, 10, 1);15 for (const param of params) {16 await page.click(`button:nth-of-type(${param.value})`);17 }18});19test('test', async ({ page }) => {20 const params = createForLoopParams(0, 10, 1);21 for (const param of params) {22 await page.click(`button:nth-of-type(${param.index})`);23 }24});
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/utils/params');2const params = createForLoopParams(['a', 'b', 'c'], [1, 2, 3], [4, 5, 6]);3console.log(params);4const { createForLoopParams } = require('playwright/lib/utils/params');5const params = createForLoopParams(['a', 'b'], [1, 2, 3], [4, 5, 6]);6for (const param of params) {7 console.log(param);8}
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');2const forLoopParams = createForLoopParams(1, 10, 2);3console.log(forLoopParams);4const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');5const forLoopParams = createForLoopParams(1, 10, 2);6console.log(forLoopParams);7const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');8const forLoopParams = createForLoopParams(1, 10, 2);9console.log(forLoopParams);10const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');11const forLoopParams = createForLoopParams(1, 10, 2);12console.log(forLoopParams);13const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');14const forLoopParams = createForLoopParams(1, 10, 2);15console.log(forLoopParams);16const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');17const forLoopParams = createForLoopParams(1, 10, 2);18console.log(forLoopParams);19const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');20const forLoopParams = createForLoopParams(1, 10, 2);21console.log(forLoopParams);22const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');23const forLoopParams = createForLoopParams(1, 10, 2);24console.log(forLoopParams);25const { createForLoopParams } = require('playwright/lib/internal/utils/forLoopParams');
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');2const forLoopParams = createForLoopParams(0, 10, 2);3console.log(forLoopParams);4const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');5const forLoopParams = createForLoopParams(0, 10, 2);6console.log(forLoopParams);7const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');8const forLoopParams = createForLoopParams(0, 10, 2);9console.log(forLoopParams);10const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');11const forLoopParams = createForLoopParams(0, 10, 2);12console.log(forLoopParams);13const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');14const forLoopParams = createForLoopParams(0, 10, 2);15console.log(forLoopParams);16const { createForLoopParams } = require('playwright/lib/utils/forLoopParams');17const forLoopParams = createForLoopParams(0, 10, 2);18console.log(forLoopParams);
Using AI Code Generation
1const {createForLoopParams} = require('playwright/lib/internal/params');2const {test} = require('playwright/test');3test('test', async ({page}) => {4 const params = createForLoopParams({a: [1, 2, 3]});5 for (const {a} of params) {6 console.log(a);7 }8});9const {test} = require('@playwright/test');10test('test', async ({page}) => {11 await page.screenshot({ path: `example.png` });12});13 ✓ should display "hello world" (32ms)14 1 passing (1s)
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/params');2const { test } = require('playwright-test');3test('playwright test', async ({ page }) => {4 const params = createForLoopParams('i', 1, 5, 1);5 for (const i of params) {6 console.log(i);7 }8});
Using AI Code Generation
1const { createForLoopParams } = require('playwright/lib/internal/recorder/params');2const forLoopParams = createForLoopParams('i', 0, 10, 1);3console.log(forLoopParams);4const { createForLoopParams } = require('playwright/lib/internal/recorder/params');5const forLoopParams = createForLoopParams('i', 0, 10, 1);6console.log(forLoopParams);7const { createForLoopParams } = require('playwright/lib/internal/recorder/params');8const forLoopParams = createForLoopParams('i', 0, 10, 1);9console.log(forLoopParams);10const { createForLoopParams } = require('playwright/lib/internal/recorder/params');11const forLoopParams = createForLoopParams('i', 0, 10, 1);12console.log(forLoopParams);13const { createForLoopParams } = require('playwright/lib/internal/recorder/params');14const forLoopParams = createForLoopParams('i', 0, 10, 1);15console.log(forLoopParams);16const { createForLoopParams } = require('playwright/lib/internal/recorder/params');17const forLoopParams = createForLoopParams('i', 0, 10, 1);18console.log(forLoopParams);19const { createForLoopParams } = require('playwright/lib/internal/recorder/params');20const forLoopParams = createForLoopParams('i', 0, 10, 1);21console.log(forLoopParams);22const { createForLoopParams } = require('playwright/lib/internal
Using AI Code Generation
1const { createForLoopParams } = require('@playwright/test');2const testdata = require('./testdata.json');3const myParams = createForLoopParams(testdata);4module.exports = myParams;5 {6 },7 {8 }9const { test } = require('@playwright/test');10const params = require('./test.js');11test.use({ params });12test('my test', async ({ page }, params) => {13 await page.fill('input[name="q"]', params.data);14 await page.click('text=Search');15 const searchResults = page.locator('text=Results');16 await searchResults;17});
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!