]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-core): fix parsing `<script setup>` generics with >
authorEvan You <yyx990803@gmail.com>
Fri, 22 Dec 2023 14:49:03 +0000 (22:49 +0800)
committerEvan You <yyx990803@gmail.com>
Fri, 22 Dec 2023 14:49:30 +0000 (22:49 +0800)
close #9890

packages/compiler-core/__tests__/__snapshots__/parse.spec.ts.snap
packages/compiler-core/__tests__/parse.spec.ts
packages/compiler-core/src/parser.ts
packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap
packages/compiler-sfc/__tests__/compileScript.spec.ts

index 63dea7e19ddb0f8cc9031d463e8a0408adce76ce..678548e35b5093a2c4b537f1eddcfb8b1175130e 100644 (file)
@@ -838,9 +838,9 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template>< 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 13,
+          "column": 12,
           "line": 1,
-          "offset": 12,
+          "offset": 11,
         },
         "source": "<template><",
         "start": {
@@ -908,9 +908,9 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template></ 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 14,
+          "column": 13,
           "line": 1,
-          "offset": 13,
+          "offset": 12,
         },
         "source": "<template></",
         "start": {
@@ -962,9 +962,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`]
           "codegenNode": undefined,
           "loc": {
             "end": {
-              "column": 26,
+              "column": 25,
               "line": 1,
-              "offset": 25,
+              "offset": 24,
             },
             "source": "<svg><![CDATA[",
             "start": {
@@ -983,9 +983,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`]
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 26,
+          "column": 25,
           "line": 1,
-          "offset": 25,
+          "offset": 24,
         },
         "source": "<template><svg><![CDATA[",
         "start": {
@@ -1055,9 +1055,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata
           "codegenNode": undefined,
           "loc": {
             "end": {
-              "column": 31,
+              "column": 30,
               "line": 1,
-              "offset": 30,
+              "offset": 29,
             },
             "source": "<svg><![CDATA[cdata",
             "start": {
@@ -1076,9 +1076,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 31,
+          "column": 30,
           "line": 1,
-          "offset": 30,
+          "offset": 29,
         },
         "source": "<template><svg><![CDATA[cdata",
         "start": {
@@ -1128,9 +1128,9 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!-- 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 16,
+          "column": 15,
           "line": 1,
-          "offset": 15,
+          "offset": 14,
         },
         "source": "<template><!--",
         "start": {
@@ -1198,9 +1198,9 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!--comment 1`] =
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 23,
+          "column": 22,
           "line": 1,
-          "offset": 22,
+          "offset": 21,
         },
         "source": "<template><!--comment",
         "start": {
@@ -1250,9 +1250,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <div></div 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 12,
+          "column": 11,
           "line": 1,
-          "offset": 11,
+          "offset": 10,
         },
         "source": "<div></div",
         "start": {
@@ -1302,9 +1302,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div  1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 17,
+          "column": 16,
           "line": 1,
-          "offset": 16,
+          "offset": 15,
         },
         "source": "<template><div ",
         "start": {
@@ -1354,9 +1354,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 16,
+          "column": 15,
           "line": 1,
-          "offset": 15,
+          "offset": 14,
         },
         "source": "<template><div",
         "start": {
@@ -1406,9 +1406,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id  1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 20,
+          "column": 19,
           "line": 1,
-          "offset": 19,
+          "offset": 18,
         },
         "source": "<template><div id ",
         "start": {
@@ -1458,9 +1458,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id = 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 21,
+          "column": 20,
           "line": 1,
-          "offset": 20,
+          "offset": 19,
         },
         "source": "<template><div id =",
         "start": {
@@ -1510,9 +1510,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 19,
+          "column": 18,
           "line": 1,
-          "offset": 18,
+          "offset": 17,
         },
         "source": "<template><div id",
         "start": {
@@ -1562,9 +1562,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 24,
+          "column": 23,
           "line": 1,
-          "offset": 23,
+          "offset": 22,
         },
         "source": "<template><div id="abc",
         "start": {
@@ -1614,9 +1614,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc" 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 25,
+          "column": 24,
           "line": 1,
-          "offset": 24,
+          "offset": 23,
         },
         "source": "<template><div id="abc"",
         "start": {
@@ -1684,9 +1684,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc"/ 1`] =
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 26,
+          "column": 25,
           "line": 1,
-          "offset": 25,
+          "offset": 24,
         },
         "source": "<template><div id="abc"/",
         "start": {
@@ -1736,9 +1736,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 24,
+          "column": 23,
           "line": 1,
-          "offset": 23,
+          "offset": 22,
         },
         "source": "<template><div id='abc",
         "start": {
@@ -1788,9 +1788,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc' 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 25,
+          "column": 24,
           "line": 1,
-          "offset": 24,
+          "offset": 23,
         },
         "source": "<template><div id='abc'",
         "start": {
@@ -1858,9 +1858,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc'/ 1`] =
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 26,
+          "column": 25,
           "line": 1,
-          "offset": 25,
+          "offset": 24,
         },
         "source": "<template><div id='abc'/",
         "start": {
@@ -1928,9 +1928,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc / 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 25,
+          "column": 24,
           "line": 1,
-          "offset": 24,
+          "offset": 23,
         },
         "source": "<template><div id=abc /",
         "start": {
@@ -1980,9 +1980,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc 1`] = `
       "codegenNode": undefined,
       "loc": {
         "end": {
-          "column": 23,
+          "column": 22,
           "line": 1,
-          "offset": 22,
+          "offset": 21,
         },
         "source": "<template><div id=abc",
         "start": {
index 7c6b9f463d8a5afaa68ee29a770fef188b9f4e45..e49ce2bd4ce5adee1033bcc0f3dfa54901fa45f7 100644 (file)
@@ -984,6 +984,89 @@ describe('compiler: parse', () => {
       })
     })
 
+    test('attribute value with >', () => {
+      const ast = baseParse(
+        '<script setup lang="ts" generic="T extends Record<string,string>"></script>',
+        { parseMode: 'sfc' }
+      )
+      const element = ast.children[0] as ElementNode
+      expect(element).toMatchObject({
+        type: NodeTypes.ELEMENT,
+        ns: Namespaces.HTML,
+        tag: 'script',
+        tagType: ElementTypes.ELEMENT,
+        codegenNode: undefined,
+        children: [],
+        innerLoc: {
+          start: { column: 67, line: 1, offset: 66 },
+          end: { column: 67, line: 1, offset: 66 }
+        },
+        props: [
+          {
+            loc: {
+              source: 'setup',
+              end: { column: 14, line: 1, offset: 13 },
+              start: { column: 9, line: 1, offset: 8 }
+            },
+            name: 'setup',
+            nameLoc: {
+              source: 'setup',
+              end: { column: 14, line: 1, offset: 13 },
+              start: { column: 9, line: 1, offset: 8 }
+            },
+            type: NodeTypes.ATTRIBUTE,
+            value: undefined
+          },
+          {
+            loc: {
+              source: 'lang="ts"',
+              end: { column: 24, line: 1, offset: 23 },
+              start: { column: 15, line: 1, offset: 14 }
+            },
+            name: 'lang',
+            nameLoc: {
+              source: 'lang',
+              end: { column: 19, line: 1, offset: 18 },
+              start: { column: 15, line: 1, offset: 14 }
+            },
+            type: NodeTypes.ATTRIBUTE,
+            value: {
+              content: 'ts',
+              loc: {
+                source: '"ts"',
+                end: { column: 24, line: 1, offset: 23 },
+                start: { column: 20, line: 1, offset: 19 }
+              },
+              type: NodeTypes.TEXT
+            }
+          },
+          {
+            loc: {
+              source: 'generic="T extends Record<string,string>"',
+              end: { column: 66, line: 1, offset: 65 },
+              start: { column: 25, line: 1, offset: 24 }
+            },
+            name: 'generic',
+            nameLoc: {
+              source: 'generic',
+              end: { column: 32, line: 1, offset: 31 },
+              start: { column: 25, line: 1, offset: 24 }
+            },
+            type: NodeTypes.ATTRIBUTE,
+            value: {
+              content: 'T extends Record<string,string>',
+              loc: {
+                source: '"T extends Record<string,string>"',
+                end: { column: 66, line: 1, offset: 65 },
+                start: { column: 33, line: 1, offset: 32 }
+              },
+              type: NodeTypes.TEXT
+            }
+          }
+        ]
+      })
+    })
+
     test('multiple attributes', () => {
       const ast = baseParse('<div id=a class="c" inert style=\'\'></div>')
       const element = ast.children[0] as ElementNode
index 2250719f5707d23e94ad2551b4469174863dae35..923d161dd738f593baf1133dd40e103715d2a4ac 100644 (file)
@@ -145,13 +145,6 @@ const tokenizer = new Tokenizer(stack, {
       loc: getLoc(start - 1, end),
       codegenNode: undefined
     }
-    if (tokenizer.inSFCRoot) {
-      // in SFC mode, generate locations for root-level tags' inner content.
-      currentOpenTag.innerLoc = getLoc(
-        end + fastForward(end, CharCodes.Gt) + 1,
-        end
-      )
-    }
   },
 
   onopentagend(end) {
@@ -572,6 +565,10 @@ function getSlice(start: number, end: number) {
 }
 
 function endOpenTag(end: number) {
+  if (tokenizer.inSFCRoot) {
+    // in SFC mode, generate locations for root-level tags' inner content.
+    currentOpenTag!.innerLoc = getLoc(end + 1, end + 1)
+  }
   addNode(currentOpenTag!)
   const { tag, ns } = currentOpenTag!
   if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {
@@ -616,7 +613,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
     // implied close, end should be backtracked to close
     setLocEnd(el.loc, backTrack(end, CharCodes.Lt))
   } else {
-    setLocEnd(el.loc, end + fastForward(end, CharCodes.Gt) + 1)
+    setLocEnd(el.loc, end + 1)
   }
 
   if (tokenizer.inSFCRoot) {
@@ -738,17 +735,6 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
   }
 }
 
-function fastForward(start: number, c: number) {
-  let offset = 0
-  while (
-    currentInput.charCodeAt(start + offset) !== CharCodes.Gt &&
-    start + offset < currentInput.length
-  ) {
-    offset++
-  }
-  return offset
-}
-
 function backTrack(index: number, c: number) {
   let i = index
   while (currentInput.charCodeAt(i) !== c && i >= 0) i--
index 01267cd42c74c6990cd1876a073303e14bb00bbd..a2d24599cfab8c5cdcf6553b3d2528d95035003f 100644 (file)
@@ -1383,6 +1383,21 @@ return { D, C, B, Foo }
 })"
 `;
 
+exports[`SFC compile <script setup> > with TypeScript > with generic attribute 1`] = `
+"import { defineComponent as _defineComponent } from 'vue'
+type Bar = {}
+      
+export default /*#__PURE__*/_defineComponent({
+  setup(__props, { expose: __expose }) {
+  __expose();
+
+        
+return {  }
+}
+
+})"
+`;
+
 exports[`SFC genDefaultAs > <script setup> only 1`] = `
 "const a = 1
       
index 96338b022f313ae54aaf2c015f15a74f38f22a53..276808cf1c9e61de7266bd0b0fb710db77b543d2 100644 (file)
@@ -938,6 +938,14 @@ describe('SFC compile <script setup>', () => {
       expect(content).toMatch(`return { get Baz() { return Baz } }`)
       assertCode(content)
     })
+
+    test('with generic attribute', () => {
+      const { content } = compile(`
+      <script setup lang="ts" generic="T extends Record<string,string>">
+        type Bar = {}
+      </script>`)
+      assertCode(content)
+    })
   })
 
   describe('async/await detection', () => {