]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: pass all compiler-core tests
authorEvan You <yyx990803@gmail.com>
Sat, 18 Nov 2023 03:22:15 +0000 (11:22 +0800)
committerEvan You <yyx990803@gmail.com>
Sat, 25 Nov 2023 08:18:29 +0000 (16:18 +0800)
packages/compiler-core/src/parser/Tokenizer.ts

index b1e9874185c54e24f580e45a7011c5d438ba9540..536de3a61e2af338eca4581a9ee4e92617257d4c 100644 (file)
@@ -77,7 +77,11 @@ const defaultDelimitersClose = new Uint8Array([125, 125]) // "}}"
 /** All the states the tokenizer can be in. */
 const enum State {
   Text = 1,
+
+  // interpolation
+  InterpolationOpen,
   Interpolation,
+  InterpolationClose,
 
   // Tags
   BeforeTagName, // After <
@@ -288,38 +292,55 @@ export default class Tokenizer {
       this.sectionStart = this.index
     } else if (c === CharCodes.Amp) {
       this.startEntity()
-    } else if (this.matchDelimiter(c, this.delimiterOpen)) {
-      if (this.index > this.sectionStart) {
-        this.cbs.ontext(this.sectionStart, this.index)
-      }
-      this.state = State.Interpolation
-      this.sectionStart = this.index
-      this.index += this.delimiterOpen.length - 1
+    } else if (c === this.delimiterOpen[0]) {
+      this.state = State.InterpolationOpen
+      this.delimiterIndex = 0
+      this.stateInterpolationOpen(c)
     }
   }
 
   public delimiterOpen: Uint8Array = defaultDelimitersOpen
   public delimiterClose: Uint8Array = defaultDelimitersClose
-  private matchDelimiter(c: number, delimiter: Uint8Array): boolean {
-    if (c === delimiter[0]) {
-      const l = delimiter.length
-      for (let i = 1; i < l; i++) {
-        if (this.buffer.charCodeAt(this.index + i) !== delimiter[i]) {
-          return false
+  private delimiterIndex = -1
+
+  private stateInterpolationOpen(c: number): void {
+    if (c === this.delimiterOpen[this.delimiterIndex]) {
+      if (this.delimiterIndex === this.delimiterOpen.length - 1) {
+        const start = this.index + 1 - this.delimiterOpen.length
+        if (start > this.sectionStart) {
+          this.cbs.ontext(this.sectionStart, start)
         }
+        this.state = State.Interpolation
+        this.sectionStart = start
+      } else {
+        this.delimiterIndex++
       }
-      return true
+    } else {
+      this.state = State.Text
+      this.stateText(c)
     }
-    return false
   }
 
   private stateInterpolation(c: number): void {
-    if (this.matchDelimiter(c, this.delimiterClose)) {
-      this.index += this.delimiterClose.length
-      this.cbs.oninterpolation(this.sectionStart, this.index)
-      this.state = State.Text
-      this.sectionStart = this.index
-      this.stateText(this.buffer.charCodeAt(this.index))
+    if (c === this.delimiterClose[0]) {
+      this.state = State.InterpolationClose
+      this.delimiterIndex = 0
+      this.stateInterpolationClose(c)
+    }
+  }
+
+  private stateInterpolationClose(c: number) {
+    if (c === this.delimiterClose[this.delimiterIndex]) {
+      if (this.delimiterIndex === this.delimiterClose.length - 1) {
+        this.cbs.oninterpolation(this.sectionStart, this.index + 1)
+        this.state = State.Text
+        this.sectionStart = this.index + 1
+      } else {
+        this.delimiterIndex++
+      }
+    } else {
+      this.state = State.Interpolation
+      this.stateInterpolation(c)
     }
   }
 
@@ -815,10 +836,18 @@ export default class Tokenizer {
           this.stateText(c)
           break
         }
+        case State.InterpolationOpen: {
+          this.stateInterpolationOpen(c)
+          break
+        }
         case State.Interpolation: {
           this.stateInterpolation(c)
           break
         }
+        case State.InterpolationClose: {
+          this.stateInterpolationClose(c)
+          break
+        }
         case State.SpecialStartSequence: {
           this.stateSpecialStartSequence(c)
           break