From 224196d3ecf702c0e6bfba5ec3606b816b96901a Mon Sep 17 00:00:00 2001 From: Amour1688 Date: Fri, 30 Apr 2021 01:06:23 +0800 Subject: [PATCH] fix: wrong compilation result of withDirectives (#404) --- packages/babel-plugin-jsx/src/buildProps.ts | 3 +- .../babel-plugin-jsx/src/parseDirectives.ts | 63 ++++++++++--------- .../test/__snapshots__/snapshot.test.ts.snap | 18 ++++++ packages/babel-plugin-jsx/test/index.test.tsx | 26 -------- .../babel-plugin-jsx/test/snapshot.test.ts | 14 +++++ 5 files changed, 66 insertions(+), 58 deletions(-) diff --git a/packages/babel-plugin-jsx/src/buildProps.ts b/packages/babel-plugin-jsx/src/buildProps.ts index 8d5fd60..05636f4 100644 --- a/packages/babel-plugin-jsx/src/buildProps.ts +++ b/packages/babel-plugin-jsx/src/buildProps.ts @@ -242,8 +242,7 @@ const buildProps = (path: NodePath, 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) { diff --git a/packages/babel-plugin-jsx/src/parseDirectives.ts b/packages/babel-plugin-jsx/src/parseDirectives.ts index 63b0da2..d4b7c41 100644 --- a/packages/babel-plugin-jsx/src/parseDirectives.ts +++ b/packages/babel-plugin-jsx/src/parseDirectives.ts @@ -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) => { 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, }; }; diff --git a/packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap b/packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap index 551a558..ede349a 100644 --- a/packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap +++ b/packages/babel-plugin-jsx/test/__snapshots__/snapshot.test.ts.snap @@ -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\\"; diff --git a/packages/babel-plugin-jsx/test/index.test.tsx b/packages/babel-plugin-jsx/test/index.test.tsx index 40d7a14..5dba902 100644 --- a/packages/babel-plugin-jsx/test/index.test.tsx +++ b/packages/babel-plugin-jsx/test/index.test.tsx @@ -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 () => ( - - ); - }, - }); - const node = wrapper.vm.$.subTree; - expect(calls).toEqual(expect.arrayContaining([1])); - expect(node.dirs).toHaveLength(1); - }); - test('vHtml', () => { const wrapper = shallowMount({ setup() { diff --git a/packages/babel-plugin-jsx/test/snapshot.test.ts b/packages/babel-plugin-jsx/test/snapshot.test.ts index b399461..64211fc 100644 --- a/packages/babel-plugin-jsx/test/snapshot.test.ts +++ b/packages/babel-plugin-jsx/test/snapshot.test.ts @@ -139,6 +139,20 @@ const transpile = ( a = {a}; `, }, + { + name: 'custom directive', + from: ` + <> + + + + + + + + + `, + }, { name: 'vModels', from: '',