mirror of https://github.com/vuejs/core.git
fix(compiler-core): fix parsing `<script setup>` generics with >
close #9890
This commit is contained in:
parent
e7135f7100
commit
7aa3f250f2
|
@ -838,9 +838,9 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template>< 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 13,
|
"column": 12,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 12,
|
"offset": 11,
|
||||||
},
|
},
|
||||||
"source": "<template><",
|
"source": "<template><",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -908,9 +908,9 @@ exports[`compiler: parse > Errors > EOF_BEFORE_TAG_NAME > <template></ 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 14,
|
"column": 13,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 13,
|
"offset": 12,
|
||||||
},
|
},
|
||||||
"source": "<template></",
|
"source": "<template></",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -962,9 +962,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`]
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 26,
|
"column": 25,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 25,
|
"offset": 24,
|
||||||
},
|
},
|
||||||
"source": "<svg><![CDATA[",
|
"source": "<svg><![CDATA[",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -983,9 +983,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[ 1`]
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 26,
|
"column": 25,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 25,
|
"offset": 24,
|
||||||
},
|
},
|
||||||
"source": "<template><svg><![CDATA[",
|
"source": "<template><svg><![CDATA[",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1055,9 +1055,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 31,
|
"column": 30,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 30,
|
"offset": 29,
|
||||||
},
|
},
|
||||||
"source": "<svg><![CDATA[cdata",
|
"source": "<svg><![CDATA[cdata",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1076,9 +1076,9 @@ exports[`compiler: parse > Errors > EOF_IN_CDATA > <template><svg><![CDATA[cdata
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 31,
|
"column": 30,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 30,
|
"offset": 29,
|
||||||
},
|
},
|
||||||
"source": "<template><svg><![CDATA[cdata",
|
"source": "<template><svg><![CDATA[cdata",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1128,9 +1128,9 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!-- 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 16,
|
"column": 15,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 15,
|
"offset": 14,
|
||||||
},
|
},
|
||||||
"source": "<template><!--",
|
"source": "<template><!--",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1198,9 +1198,9 @@ exports[`compiler: parse > Errors > EOF_IN_COMMENT > <template><!--comment 1`] =
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 23,
|
"column": 22,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 22,
|
"offset": 21,
|
||||||
},
|
},
|
||||||
"source": "<template><!--comment",
|
"source": "<template><!--comment",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1250,9 +1250,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <div></div 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 12,
|
"column": 11,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 11,
|
"offset": 10,
|
||||||
},
|
},
|
||||||
"source": "<div></div",
|
"source": "<div></div",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1302,9 +1302,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 17,
|
"column": 16,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 16,
|
"offset": 15,
|
||||||
},
|
},
|
||||||
"source": "<template><div ",
|
"source": "<template><div ",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1354,9 +1354,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 16,
|
"column": 15,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 15,
|
"offset": 14,
|
||||||
},
|
},
|
||||||
"source": "<template><div",
|
"source": "<template><div",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1406,9 +1406,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 20,
|
"column": 19,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 19,
|
"offset": 18,
|
||||||
},
|
},
|
||||||
"source": "<template><div id ",
|
"source": "<template><div id ",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1458,9 +1458,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id = 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 21,
|
"column": 20,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 20,
|
"offset": 19,
|
||||||
},
|
},
|
||||||
"source": "<template><div id =",
|
"source": "<template><div id =",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1510,9 +1510,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 19,
|
"column": 18,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 18,
|
"offset": 17,
|
||||||
},
|
},
|
||||||
"source": "<template><div id",
|
"source": "<template><div id",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1562,9 +1562,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 24,
|
"column": 23,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 23,
|
"offset": 22,
|
||||||
},
|
},
|
||||||
"source": "<template><div id="abc",
|
"source": "<template><div id="abc",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1614,9 +1614,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc" 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 25,
|
"column": 24,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 24,
|
"offset": 23,
|
||||||
},
|
},
|
||||||
"source": "<template><div id="abc"",
|
"source": "<template><div id="abc"",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1684,9 +1684,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id="abc"/ 1`] =
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 26,
|
"column": 25,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 25,
|
"offset": 24,
|
||||||
},
|
},
|
||||||
"source": "<template><div id="abc"/",
|
"source": "<template><div id="abc"/",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1736,9 +1736,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 24,
|
"column": 23,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 23,
|
"offset": 22,
|
||||||
},
|
},
|
||||||
"source": "<template><div id='abc",
|
"source": "<template><div id='abc",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1788,9 +1788,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc' 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 25,
|
"column": 24,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 24,
|
"offset": 23,
|
||||||
},
|
},
|
||||||
"source": "<template><div id='abc'",
|
"source": "<template><div id='abc'",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1858,9 +1858,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id='abc'/ 1`] =
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 26,
|
"column": 25,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 25,
|
"offset": 24,
|
||||||
},
|
},
|
||||||
"source": "<template><div id='abc'/",
|
"source": "<template><div id='abc'/",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1928,9 +1928,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc / 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 25,
|
"column": 24,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 24,
|
"offset": 23,
|
||||||
},
|
},
|
||||||
"source": "<template><div id=abc /",
|
"source": "<template><div id=abc /",
|
||||||
"start": {
|
"start": {
|
||||||
|
@ -1980,9 +1980,9 @@ exports[`compiler: parse > Errors > EOF_IN_TAG > <template><div id=abc 1`] = `
|
||||||
"codegenNode": undefined,
|
"codegenNode": undefined,
|
||||||
"loc": {
|
"loc": {
|
||||||
"end": {
|
"end": {
|
||||||
"column": 23,
|
"column": 22,
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"offset": 22,
|
"offset": 21,
|
||||||
},
|
},
|
||||||
"source": "<template><div id=abc",
|
"source": "<template><div id=abc",
|
||||||
"start": {
|
"start": {
|
||||||
|
|
|
@ -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', () => {
|
test('multiple attributes', () => {
|
||||||
const ast = baseParse('<div id=a class="c" inert style=\'\'></div>')
|
const ast = baseParse('<div id=a class="c" inert style=\'\'></div>')
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
|
|
|
@ -145,13 +145,6 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
loc: getLoc(start - 1, end),
|
loc: getLoc(start - 1, end),
|
||||||
codegenNode: undefined
|
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) {
|
onopentagend(end) {
|
||||||
|
@ -572,6 +565,10 @@ function getSlice(start: number, end: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function endOpenTag(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!)
|
addNode(currentOpenTag!)
|
||||||
const { tag, ns } = currentOpenTag!
|
const { tag, ns } = currentOpenTag!
|
||||||
if (ns === Namespaces.HTML && currentOptions.isPreTag(tag)) {
|
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
|
// implied close, end should be backtracked to close
|
||||||
setLocEnd(el.loc, backTrack(end, CharCodes.Lt))
|
setLocEnd(el.loc, backTrack(end, CharCodes.Lt))
|
||||||
} else {
|
} else {
|
||||||
setLocEnd(el.loc, end + fastForward(end, CharCodes.Gt) + 1)
|
setLocEnd(el.loc, end + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokenizer.inSFCRoot) {
|
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) {
|
function backTrack(index: number, c: number) {
|
||||||
let i = index
|
let i = index
|
||||||
while (currentInput.charCodeAt(i) !== c && i >= 0) i--
|
while (currentInput.charCodeAt(i) !== c && i >= 0) i--
|
||||||
|
|
|
@ -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`] = `
|
exports[`SFC genDefaultAs > <script setup> only 1`] = `
|
||||||
"const a = 1
|
"const a = 1
|
||||||
|
|
||||||
|
|
|
@ -938,6 +938,14 @@ describe('SFC compile <script setup>', () => {
|
||||||
expect(content).toMatch(`return { get Baz() { return Baz } }`)
|
expect(content).toMatch(`return { get Baz() { return Baz } }`)
|
||||||
assertCode(content)
|
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', () => {
|
describe('async/await detection', () => {
|
||||||
|
|
Loading…
Reference in New Issue