Kaynağa Gözat

fix(compiler-core): prevent incorrect entity parsing with logical AND

daiwei 11 ay önce
ebeveyn
işleme
47bb99c3b0

+ 11 - 0
packages/compiler-core/__tests__/parse.spec.ts

@@ -1264,6 +1264,17 @@ describe('compiler: parse', () => {
       })
     })
 
+    // #13361
+    test('directive with multiline value', () => {
+      const ast = baseParse(
+        `<div v-if="
+          foo &&
+          bar
+        "></div>`,
+      )
+      expect(ast.loc.end.line).toBe(4)
+    })
+
     test('directive with argument', () => {
       const ast = baseParse('<div v-on:click/>')
       const directive = (ast.children[0] as ElementNode).props[0]

+ 11 - 4
packages/compiler-core/src/tokenizer.ts

@@ -322,7 +322,7 @@ export default class Tokenizer {
       }
       this.state = State.BeforeTagName
       this.sectionStart = this.index
-    } else if (!__BROWSER__ && c === CharCodes.Amp) {
+    } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) {
       this.startEntity()
     } else if (!this.inVPre && c === this.delimiterOpen[0]) {
       this.state = State.InterpolationOpen
@@ -436,7 +436,7 @@ export default class Tokenizer {
         (this.currentSequence === Sequences.TextareaEnd && !this.inSFCRoot)
       ) {
         // We have to parse entities in <title> and <textarea> tags.
-        if (!__BROWSER__ && c === CharCodes.Amp) {
+        if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) {
           this.startEntity()
         } else if (!this.inVPre && c === this.delimiterOpen[0]) {
           // We also need to handle interpolation
@@ -795,7 +795,7 @@ export default class Tokenizer {
         this.index + 1,
       )
       this.state = State.BeforeAttrName
-    } else if (!__BROWSER__ && c === CharCodes.Amp) {
+    } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) {
       this.startEntity()
     }
   }
@@ -823,7 +823,7 @@ export default class Tokenizer {
         ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
         this.index,
       )
-    } else if (!__BROWSER__ && c === CharCodes.Amp) {
+    } else if (!__BROWSER__ && c === CharCodes.Amp && !this.isLogicalAnd()) {
       this.startEntity()
     }
   }
@@ -1178,4 +1178,11 @@ export default class Tokenizer {
       }
     }
   }
+
+  private isLogicalAnd(): boolean {
+    return (
+      this.buffer.charCodeAt(this.index - 1) === CharCodes.Amp ||
+      this.buffer.charCodeAt(this.index + 1) === CharCodes.Amp
+    )
+  }
 }