]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): allow multiline expression on v-model and v-on (#1234)
authorCarlos Rodrigues <carlos@hypermob.co.uk>
Tue, 9 Jun 2020 21:24:48 +0000 (22:24 +0100)
committerGitHub <noreply@github.com>
Tue, 9 Jun 2020 21:24:48 +0000 (17:24 -0400)
packages/compiler-core/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
packages/compiler-core/__tests__/transforms/vModel.spec.ts
packages/compiler-core/__tests__/transforms/vOn.spec.ts
packages/compiler-core/src/transforms/vModel.ts
packages/compiler-core/src/utils.ts

index 2a4f8d0d9c41927dff39e930bc723beff5251a54..cdbe3c3eefa9c72aa4d8687d3df31e297393fd9f 100644 (file)
@@ -26,6 +26,25 @@ return function render(_ctx, _cache) {
 }"
 `;
 
+exports[`compiler: transform v-model simple expression (with multilines) 1`] = `
+"const _Vue = Vue
+
+return function render(_ctx, _cache) {
+  with (_ctx) {
+    const { createVNode: _createVNode, openBlock: _openBlock, createBlock: _createBlock } = _Vue
+
+    return (_openBlock(), _createBlock(\\"input\\", {
+      modelValue: 
+ model 
+,
+      \\"onUpdate:modelValue\\": $event => (
+ model 
+ = $event)
+    }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
+  }
+}"
+`;
+
 exports[`compiler: transform v-model simple expression (with prefixIdentifiers) 1`] = `
 "import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from \\"vue\\"
 
index ce51602ef8dd20fa6f51fcf9c91e8ae434894b47..42f9c6052b2c6034050b17198e6770477ec8f753 100644 (file)
@@ -115,6 +115,43 @@ describe('compiler: transform v-model', () => {
     expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
   })
 
+  test('simple expression (with multilines)', () => {
+    const root = parseWithVModel('<input v-model="\n model \n" />')
+    const node = root.children[0] as ElementNode
+    const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
+      .properties
+
+    expect(props[0]).toMatchObject({
+      key: {
+        content: 'modelValue',
+        isStatic: true
+      },
+      value: {
+        content: '\n model \n',
+        isStatic: false
+      }
+    })
+
+    expect(props[1]).toMatchObject({
+      key: {
+        content: 'onUpdate:modelValue',
+        isStatic: true
+      },
+      value: {
+        children: [
+          '$event => (',
+          {
+            content: '\n model \n',
+            isStatic: false
+          },
+          ' = $event)'
+        ]
+      }
+    })
+
+    expect(generate(root).code).toMatchSnapshot()
+  })
+
   test('compound expression', () => {
     const root = parseWithVModel('<input v-model="model[index]" />')
     const node = root.children[0] as ElementNode
index b015eabba6b0011b5f092f5dba389bb388e03d03..158daa29b64be6d475e02df0cafc82760a56dc34 100644 (file)
@@ -167,6 +167,24 @@ describe('compiler: transform v-on', () => {
     })
   })
 
+  test('should handle multiple line statement', () => {
+    const { node } = parseWithVOn(`<div @click="\nfoo();\nbar()\n"/>`)
+    expect((node.codegenNode as VNodeCall).props).toMatchObject({
+      properties: [
+        {
+          key: { content: `onClick` },
+          value: {
+            type: NodeTypes.COMPOUND_EXPRESSION,
+            // should wrap with `{` for multiple statements
+            // in this case the return value is discarded and the behavior is
+            // consistent with 2.x
+            children: [`$event => {`, { content: `\nfoo();\nbar()\n` }, `}`]
+          }
+        }
+      ]
+    })
+  })
+
   test('inline statement w/ prefixIdentifiers: true', () => {
     const { node } = parseWithVOn(`<div @click="foo($event)"/>`, {
       prefixIdentifiers: true
index 26d4ec85a732a1d35f33187437a06d88c1597a93..f4ec6ea34ab740d58f379c2c71109b401e5370e8 100644 (file)
@@ -21,6 +21,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
 
   const expString =
     exp.type === NodeTypes.SIMPLE_EXPRESSION ? exp.content : exp.loc.source
+
   if (!isMemberExpression(expString)) {
     context.onError(
       createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc)
index e2c5dd1e5d731c805a920c9b4ea4b4e332c37222..9b974fca05a565654fb0adc63700ba2b594b14fc 100644 (file)
@@ -84,8 +84,10 @@ export const isSimpleIdentifier = (name: string): boolean =>
   !nonIdentifierRE.test(name)
 
 const memberExpRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\[[^\]]+\])*$/
-export const isMemberExpression = (path: string): boolean =>
-  memberExpRE.test(path)
+export const isMemberExpression = (path: string): boolean => {
+  if (!path) return false
+  return memberExpRE.test(path.trim())
+}
 
 export function getInnerRange(
   loc: SourceLocation,