mirror of
				https://github.com/vuejs/babel-plugin-jsx.git
				synced 2025-10-31 01:12:17 +08:00 
			
		
		
		
	fix: wrong compilation result of withDirectives (#404)
This commit is contained in:
		| @@ -242,8 +242,7 @@ const buildProps = (path: NodePath<t.JSXElement>, state: State) => { | ||||
|             values.forEach((value, index) => { | ||||
|               const propName = args[index]; | ||||
|               // v-model target with variable | ||||
|               // const isIdentifierProp = t.isIdentifier(propName); | ||||
|               const isDynamic = !t.isStringLiteral(propName) && !t.isNullLiteral(propName); | ||||
|               const isDynamic = propName && !t.isStringLiteral(propName) && !t.isNullLiteral(propName); | ||||
|  | ||||
|               // must be v-model or v-models and is a component | ||||
|               if (!directive) { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import * as t from '@babel/types'; | ||||
| import { NodePath } from '@babel/traverse'; | ||||
| import { createIdentifier } from './utils'; | ||||
| import { State, ExcludesBoolean } from '.'; | ||||
| import { State } from '.'; | ||||
|  | ||||
| export type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression; | ||||
|  | ||||
| @@ -24,7 +24,7 @@ const getType = (path: NodePath<t.JSXOpeningElement>) => { | ||||
|   return typePath ? typePath.get('value').node : null; | ||||
| }; | ||||
|  | ||||
| const parseModifiers = (value: t.ArrayExpression): string[] => ( | ||||
| const parseModifiers = (value: any): string[] => ( | ||||
|   t.isArrayExpression(value) | ||||
|     ? value.elements | ||||
|       .map((el) => (t.isStringLiteral(el) ? el.value : '')) | ||||
| @@ -64,37 +64,38 @@ const parseDirectives = (params: { | ||||
|   const shouldResolve = !['html', 'text', 'model', 'models'].includes(directiveName) | ||||
|     || (isVModel && !isComponent); | ||||
|  | ||||
|   if (['models', 'model'].includes(directiveName)) { | ||||
|     if (t.isArrayExpression(value)) { | ||||
|       const elementsList = isVModels ? value.elements! : [value]; | ||||
|   let modifiers = underscoreModifiers; | ||||
|  | ||||
|       elementsList.forEach((element) => { | ||||
|         if (isVModels && !t.isArrayExpression(element)) { | ||||
|           throw new Error('You should pass a Two-dimensional Arrays to v-models'); | ||||
|         } | ||||
|   if (t.isArrayExpression(value)) { | ||||
|     const elementsList = isVModels ? value.elements! : [value]; | ||||
|  | ||||
|         const { elements } = element as t.ArrayExpression; | ||||
|         const [first, second, third] = elements; | ||||
|         let modifiers = underscoreModifiers; | ||||
|     elementsList.forEach((element) => { | ||||
|       if (isVModels && !t.isArrayExpression(element)) { | ||||
|         throw new Error('You should pass a Two-dimensional Arrays to v-models'); | ||||
|       } | ||||
|  | ||||
|         if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) { | ||||
|           args.push(second); | ||||
|           modifiers = parseModifiers(third as t.ArrayExpression); | ||||
|         } else if (t.isArrayExpression(second)) { | ||||
|           args.push(t.nullLiteral()); | ||||
|           modifiers = parseModifiers(second); | ||||
|         } else { | ||||
|           // work as v-model={[value]} or v-models={[[value]]} | ||||
|       const { elements } = element as t.ArrayExpression; | ||||
|       const [first, second, third] = elements; | ||||
|  | ||||
|       if (second && !t.isArrayExpression(second) && !t.isSpreadElement(second)) { | ||||
|         args.push(second); | ||||
|         modifiers = parseModifiers(third as t.ArrayExpression); | ||||
|       } else if (t.isArrayExpression(second)) { | ||||
|         if (!shouldResolve) { | ||||
|           args.push(t.nullLiteral()); | ||||
|         } | ||||
|         modifiersSet.push(new Set(modifiers)); | ||||
|         vals.push(first as t.Expression); | ||||
|       }); | ||||
|     } else if (isVModel) { | ||||
|       // work as v-model={value} | ||||
|       args.push(t.nullLiteral()); | ||||
|       modifiersSet.push(new Set(underscoreModifiers)); | ||||
|     } | ||||
|         modifiers = parseModifiers(second); | ||||
|       } else if (!shouldResolve) { | ||||
|         // work as v-model={[value]} or v-models={[[value]]} | ||||
|         args.push(t.nullLiteral()); | ||||
|       } | ||||
|       modifiersSet.push(new Set(modifiers)); | ||||
|       vals.push(first as t.Expression); | ||||
|     }); | ||||
|   } else if (isVModel && !shouldResolve) { | ||||
|     // work as v-model={value} | ||||
|     args.push(t.nullLiteral()); | ||||
|     modifiersSet.push(new Set(underscoreModifiers)); | ||||
|   } else { | ||||
|     modifiersSet.push(new Set(underscoreModifiers)); | ||||
|   } | ||||
| @@ -107,7 +108,9 @@ const parseDirectives = (params: { | ||||
|     directive: shouldResolve ? [ | ||||
|       resolveDirective(path, state, tag, directiveName), | ||||
|       vals[0] || value, | ||||
|       !!modifiersSet[0]?.size && t.unaryExpression('void', t.numericLiteral(0), true), | ||||
|       modifiersSet[0]?.size | ||||
|         ? args[0] || t.unaryExpression('void', t.numericLiteral(0), true) | ||||
|         : args[0], | ||||
|       !!modifiersSet[0]?.size && t.objectExpression( | ||||
|         [...modifiersSet[0]].map( | ||||
|           (modifier) => t.objectProperty( | ||||
| @@ -116,7 +119,7 @@ const parseDirectives = (params: { | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ].filter(Boolean as any as ExcludesBoolean) : undefined, | ||||
|     ].filter(Boolean) as t.Expression[] : undefined, | ||||
|   }; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,24 @@ exports[`custom directive: custom directive 1`] = ` | ||||
| _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"cus\\"), x]]);" | ||||
| `; | ||||
|  | ||||
| exports[`custom directive: custom directive 2`] = ` | ||||
| "import { withDirectives as _withDirectives, createVNode as _createVNode, resolveDirective as _resolveDirective, resolveComponent as _resolveComponent, Fragment as _Fragment } from \\"vue\\"; | ||||
|  | ||||
| _createVNode(_Fragment, null, [_withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, 'y']]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, 'y', { | ||||
|   a: true, | ||||
|   b: true | ||||
| }]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, void 0, { | ||||
|   a: true, | ||||
|   b: true | ||||
| }]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, y, { | ||||
|   a: true, | ||||
|   b: true | ||||
| }]]), _withDirectives(_createVNode(_resolveComponent(\\"A\\"), null, null, 512), [[_resolveDirective(\\"xxx\\"), x, y, { | ||||
|   a: true, | ||||
|   b: true | ||||
| }]])]);" | ||||
| `; | ||||
|  | ||||
| exports[`disable object slot syntax with defaultSlot: defaultSlot 1`] = ` | ||||
| "import { createVNode as _createVNode, resolveComponent as _resolveComponent } from \\"vue\\"; | ||||
|  | ||||
|   | ||||
| @@ -257,32 +257,6 @@ describe('Transform JSX', () => { | ||||
| }); | ||||
|  | ||||
| describe('directive', () => { | ||||
|   test('custom', () => { | ||||
|     const calls: number[] = []; | ||||
|     const customDirective = { | ||||
|       mounted() { | ||||
|         calls.push(1); | ||||
|       }, | ||||
|     }; | ||||
|     const wrapper = shallowMount({ | ||||
|       directives: { custom: customDirective }, | ||||
|       setup() { | ||||
|         return () => ( | ||||
|           <a | ||||
|             v-custom={{ | ||||
|               value: 123, | ||||
|               modifiers: { modifier: true }, | ||||
|               arg: 'arg', | ||||
|             }} | ||||
|           /> | ||||
|         ); | ||||
|       }, | ||||
|     }); | ||||
|     const node = wrapper.vm.$.subTree; | ||||
|     expect(calls).toEqual(expect.arrayContaining([1])); | ||||
|     expect(node.dirs).toHaveLength(1); | ||||
|   }); | ||||
|  | ||||
|   test('vHtml', () => { | ||||
|     const wrapper = shallowMount({ | ||||
|       setup() { | ||||
|   | ||||
| @@ -139,6 +139,20 @@ const transpile = ( | ||||
|       a = <A>{a}</A>; | ||||
|     `, | ||||
|   }, | ||||
|   { | ||||
|     name: 'custom directive', | ||||
|     from: ` | ||||
|       <> | ||||
|         <A v-xxx={x} /> | ||||
|         <A v-xxx={[x]} /> | ||||
|         <A v-xxx={[x, 'y']} /> | ||||
|         <A v-xxx={[x, 'y', ['a', 'b']]} /> | ||||
|         <A v-xxx={[x, ['a', 'b']]} /> | ||||
|         <A v-xxx={[x, y, ['a', 'b']]} /> | ||||
|         <A v-xxx={[x, y, ['a', 'b']]} /> | ||||
|       </> | ||||
|     `, | ||||
|   }, | ||||
|   { | ||||
|     name: 'vModels', | ||||
|     from: '<C v-models={[[foo, ["modifier"]], [bar, "bar", ["modifier1", "modifier2"]]]} />', | ||||
|   | ||||
		Reference in New Issue
	
	Block a user