fix(compiler-sfc): fix TLA codegen semicolon insertion

fix #4596
This commit is contained in:
Evan You 2021-09-16 16:49:59 -04:00
parent ae942cdcd9
commit 39cebf5f7a
3 changed files with 92 additions and 17 deletions

View File

@ -96,6 +96,36 @@ export default /*#__PURE__*/ Object.assign(__default__, {
})" })"
`; `;
exports[`SFC compile <script setup> async/await detection await in expression statement 1`] = `
"import { withAsyncContext as _withAsyncContext } from 'vue'
export default {
async setup(__props, { expose }) {
expose()
let __temp, __restore
foo()
;(
([__temp,__restore] = _withAsyncContext(() => {
return 1
})),
__temp = await __temp,
__restore(),
__temp
) + (
([__temp,__restore] = _withAsyncContext(() => {
return 2
})),
__temp = await __temp,
__restore(),
__temp
)
return { }
}
}"
`;
exports[`SFC compile <script setup> async/await detection expression statement 1`] = ` exports[`SFC compile <script setup> async/await detection expression statement 1`] = `
"import { withAsyncContext as _withAsyncContext } from 'vue' "import { withAsyncContext as _withAsyncContext } from 'vue'
@ -109,7 +139,8 @@ let __temp, __restore
return foo return foo
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
__temp
) )
return { } return { }
} }
@ -137,7 +168,8 @@ let __temp, __restore
)) ))
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
__temp
) )
return { } return { }
} }
@ -165,7 +197,8 @@ let __temp, __restore
))) )))
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
__temp
) )
return { } return { }
} }
@ -200,7 +233,8 @@ let __temp, __restore
)) ))
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
__temp
) )
return { } return { }
} }
@ -216,18 +250,20 @@ export default {
expose() expose()
let __temp, __restore let __temp, __restore
if (ok) { ;( if (ok) { (
([__temp,__restore] = _withAsyncContext(() => { ([__temp,__restore] = _withAsyncContext(() => {
return foo return foo
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
) } else { ;( __temp
) } else { (
([__temp,__restore] = _withAsyncContext(() => { ([__temp,__restore] = _withAsyncContext(() => {
return bar return bar
})), })),
__temp = await __temp, __temp = await __temp,
__restore() __restore(),
__temp
) } ) }
return { } return { }
} }
@ -301,6 +337,28 @@ return { cls }
}" }"
`; `;
exports[`SFC compile <script setup> async/await detection single line conditions 1`] = `
"import { withAsyncContext as _withAsyncContext } from 'vue'
export default {
async setup(__props, { expose }) {
expose()
let __temp, __restore
if (false) (
([__temp,__restore] = _withAsyncContext(() => {
return foo()
})),
__temp = await __temp,
__restore(),
__temp
)
return { }
}
}"
`;
exports[`SFC compile <script setup> async/await detection variable 1`] = ` exports[`SFC compile <script setup> async/await detection variable 1`] = `
"import { withAsyncContext as _withAsyncContext } from 'vue' "import { withAsyncContext as _withAsyncContext } from 'vue'

View File

@ -1066,6 +1066,7 @@ const emit = defineEmits(['a', 'b'])
} }
expect(content).toMatch(`${shouldAsync ? `async ` : ``}setup(`) expect(content).toMatch(`${shouldAsync ? `async ` : ``}setup(`)
assertCode(content) assertCode(content)
return content
} }
test('expression statement', () => { test('expression statement', () => {
@ -1080,12 +1081,25 @@ const emit = defineEmits(['a', 'b'])
assertAwaitDetection(`let a = $ref(1 + (await foo))`) assertAwaitDetection(`let a = $ref(1 + (await foo))`)
}) })
// #4448
test('nested await', () => { test('nested await', () => {
assertAwaitDetection(`await (await foo)`) assertAwaitDetection(`await (await foo)`)
assertAwaitDetection(`await ((await foo))`) assertAwaitDetection(`await ((await foo))`)
assertAwaitDetection(`await (await (await foo))`) assertAwaitDetection(`await (await (await foo))`)
}) })
// should prepend semicolon
test('await in expression statement', () => {
const code = assertAwaitDetection(`foo()\nawait 1 + await 2`)
expect(code).toMatch(`foo()\n;(`)
})
// #4596 should NOT prepend semicolon
test('single line conditions', () => {
const code = assertAwaitDetection(`if (false) await foo()`)
expect(code).not.toMatch(`if (false) ;(`)
})
test('nested statements', () => { test('nested statements', () => {
assertAwaitDetection(`if (ok) { await foo } else { await bar }`) assertAwaitDetection(`if (ok) { await foo } else { await bar }`)
}) })

View File

@ -507,11 +507,13 @@ export function compileScript(
} }
/** /**
* await foo() * await foo() -->
* --> *
* (([__temp, __restore] = withAsyncContext(async () => foo())),__temp=await __temp,__restore(),__temp) * (([__temp, __restore] = withAsyncContext(async () => {
* return foo()
* })),__temp=await __temp,__restore(),__temp)
*/ */
function processAwait(node: AwaitExpression, isStatement: boolean) { function processAwait(node: AwaitExpression, needSemi: boolean) {
const argumentStart = const argumentStart =
node.argument.extra && node.argument.extra.parenthesized node.argument.extra && node.argument.extra.parenthesized
? (node.argument.extra.parenStart as number) ? (node.argument.extra.parenStart as number)
@ -527,15 +529,13 @@ export function compileScript(
s.overwrite( s.overwrite(
node.start! + startOffset, node.start! + startOffset,
argumentStart + startOffset, argumentStart + startOffset,
`${isStatement ? `;` : ``}(\n ([__temp,__restore] = ${helper( `${needSemi ? `;` : ``}(\n ([__temp,__restore] = ${helper(
`withAsyncContext` `withAsyncContext`
)}(${containsNestedAwait ? `async ` : ``}() => {\n return ` )}(${containsNestedAwait ? `async ` : ``}() => {\n return `
) )
s.appendLeft( s.appendLeft(
node.end! + startOffset, node.end! + startOffset,
`\n })),\n __temp = await __temp,\n __restore()${ `\n })),\n __temp = await __temp,\n __restore(),\n __temp\n)`
isStatement ? `` : `,\n __temp`
}\n)`
) )
} }
@ -934,7 +934,10 @@ export function compileScript(
} }
if (child.type === 'AwaitExpression') { if (child.type === 'AwaitExpression') {
hasAwait = true hasAwait = true
processAwait(child, parent.type === 'ExpressionStatement') const needsSemi = scriptSetupAst.body.some(n => {
return n.type === 'ExpressionStatement' && n.start === child.start
})
processAwait(child, needsSemi)
} }
} }
}) })