]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(v-model): support calling methods in v-model expression
authorEvan You <yyx990803@gmail.com>
Thu, 15 Jul 2021 17:34:42 +0000 (13:34 -0400)
committerEvan You <yyx990803@gmail.com>
Thu, 15 Jul 2021 17:34:42 +0000 (13:34 -0400)
close #3993

packages/compiler-core/__tests__/utils.spec.ts
packages/compiler-core/src/utils.ts

index e5846ba08890025a0457399efb3b2dc47674a795..0cd73060c5bce27f6858daeb32ae07665e3a3d10 100644 (file)
@@ -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)
index e9e214f277feff9e392036dbc6da7831a7e2e94f..798212193080332fda8b8133040d589034cb34ac 100644 (file)
@@ -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(