From 5af718ba41f53d032fd33861494f96b70c107acd Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 15 Jul 2021 13:34:42 -0400 Subject: [PATCH] fix(v-model): support calling methods in v-model expression close #3993 --- .../compiler-core/__tests__/utils.spec.ts | 1 + packages/compiler-core/src/utils.ts | 25 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/compiler-core/__tests__/utils.spec.ts b/packages/compiler-core/__tests__/utils.spec.ts index e5846ba0889..0cd73060c5b 100644 --- a/packages/compiler-core/__tests__/utils.spec.ts +++ b/packages/compiler-core/__tests__/utils.spec.ts @@ -86,6 +86,7 @@ test('isMemberExpression', () => { expect(isMemberExpression('obj[1][2].foo[3].bar.baz')).toBe(true) expect(isMemberExpression(`a[b[c.d]][0]`)).toBe(true) expect(isMemberExpression('obj?.foo')).toBe(true) + expect(isMemberExpression('foo().test')).toBe(true) // strings expect(isMemberExpression(`a['foo' + bar[baz]["qux"]]`)).toBe(true) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index e9e214f277f..79821219308 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -59,6 +59,7 @@ export const isSimpleIdentifier = (name: string): boolean => const enum MemberExpLexState { inMemberExp, inBrackets, + inParens, inString } @@ -79,6 +80,7 @@ export const isMemberExpression = (path: string): boolean => { let state = MemberExpLexState.inMemberExp let stateStack: MemberExpLexState[] = [] let currentOpenBracketCount = 0 + let currentOpenParensCount = 0 let currentStringType: "'" | '"' | '`' | null = null for (let i = 0; i < path.length; i++) { @@ -89,6 +91,10 @@ export const isMemberExpression = (path: string): boolean => { stateStack.push(state) state = MemberExpLexState.inBrackets currentOpenBracketCount++ + } else if (char === '(') { + stateStack.push(state) + state = MemberExpLexState.inParens + currentOpenParensCount++ } else if ( !(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char) ) { @@ -108,6 +114,23 @@ export const isMemberExpression = (path: string): boolean => { } } break + case MemberExpLexState.inParens: + if (char === `'` || char === `"` || char === '`') { + stateStack.push(state) + state = MemberExpLexState.inString + currentStringType = char + } else if (char === `(`) { + currentOpenParensCount++ + } else if (char === `)`) { + // if the exp ends as a call then it should not be considered valid + if (i === path.length - 1) { + return false + } + if (!--currentOpenParensCount) { + state = stateStack.pop()! + } + } + break case MemberExpLexState.inString: if (char === currentStringType) { state = stateStack.pop()! @@ -116,7 +139,7 @@ export const isMemberExpression = (path: string): boolean => { break } } - return !currentOpenBracketCount + return !currentOpenBracketCount && !currentOpenParensCount } export function getInnerRange(