diff --git a/packages/compiler-sfc/__tests__/compileScript.spec.ts b/packages/compiler-sfc/__tests__/compileScript.spec.ts index 1da416b36fb..d75927d33bb 100644 --- a/packages/compiler-sfc/__tests__/compileScript.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript.spec.ts @@ -847,6 +847,9 @@ const emit = defineEmits(['a', 'b']) const { content } = compile(``, { refSugar: true }) + if (shouldAsync) { + expect(content).toMatch(`let __temp, __restore`) + } expect(content).toMatch(`${shouldAsync ? `async ` : ``}setup(`) if (typeof expected === 'string') { expect(content).toMatch(expected) @@ -856,28 +859,35 @@ const emit = defineEmits(['a', 'b']) } test('expression statement', () => { - assertAwaitDetection(`await foo`, `await _withAsyncContext(foo)`) + assertAwaitDetection( + `await foo`, + `;(([__temp,__restore]=_withAsyncContext(()=>(foo))),__temp=await __temp,__restore())` + ) }) test('variable', () => { assertAwaitDetection( `const a = 1 + (await foo)`, - `1 + (await _withAsyncContext(foo))` + `1 + ((([__temp,__restore]=_withAsyncContext(()=>(foo))),__temp=await __temp,__restore(),__temp))` ) }) test('ref', () => { assertAwaitDetection( `ref: a = 1 + (await foo)`, - `1 + (await _withAsyncContext(foo))` + `1 + ((([__temp,__restore]=_withAsyncContext(()=>(foo))),__temp=await __temp,__restore(),__temp))` ) }) test('nested statements', () => { assertAwaitDetection(`if (ok) { await foo } else { await bar }`, code => { return ( - code.includes(`await _withAsyncContext(foo)`) && - code.includes(`await _withAsyncContext(bar)`) + code.includes( + `;(([__temp,__restore]=_withAsyncContext(()=>(foo))),__temp=await __temp,__restore())` + ) && + code.includes( + `;(([__temp,__restore]=_withAsyncContext(()=>(bar))),__temp=await __temp,__restore())` + ) ) }) }) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index 94d351ab03c..e5a792d77c3 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -32,7 +32,8 @@ import { LabeledStatement, CallExpression, RestElement, - TSInterfaceBody + TSInterfaceBody, + AwaitExpression } from '@babel/types' import { walk } from 'estree-walker' import { RawSourceMap } from 'source-map' @@ -487,6 +488,25 @@ export function compileScript( }) } + /** + * await foo() + * --> + * (([__temp, __restore] = withAsyncContext(() => foo())),__temp=await __temp,__restore(),__temp) + */ + function processAwait(node: AwaitExpression, isStatement: boolean) { + s.overwrite( + node.start! + startOffset, + node.argument.start! + startOffset, + `${isStatement ? `;` : ``}(([__temp,__restore]=${helper( + `withAsyncContext` + )}(()=>(` + ) + s.appendLeft( + node.end! + startOffset, + `))),__temp=await __temp,__restore()${isStatement ? `` : `,__temp`})` + ) + } + function processRefExpression(exp: Expression, statement: LabeledStatement) { if (exp.type === 'AssignmentExpression') { const { left, right } = exp @@ -949,17 +969,13 @@ export function compileScript( node.type.endsWith('Statement') ) { ;(walk as any)(node, { - enter(node: Node) { - if (isFunction(node)) { + enter(child: Node, parent: Node) { + if (isFunction(child)) { this.skip() } - if (node.type === 'AwaitExpression') { + if (child.type === 'AwaitExpression') { hasAwait = true - s.prependRight( - node.argument.start! + startOffset, - helper(`withAsyncContext`) + `(` - ) - s.appendLeft(node.argument.end! + startOffset, `)`) + processAwait(child, parent.type === 'ExpressionStatement') } } }) @@ -1151,6 +1167,11 @@ export function compileScript( if (propsIdentifier) { s.prependRight(startOffset, `\nconst ${propsIdentifier} = __props`) } + // inject temp variables for async context preservation + if (hasAwait) { + const any = isTS ? `:any` : `` + s.prependRight(startOffset, `\nlet __temp${any}, __restore${any}\n`) + } const destructureElements = hasDefineExposeCall || !options.inlineTemplate ? [`expose`] : [] diff --git a/packages/runtime-core/__tests__/apiSetupHelpers.spec.ts b/packages/runtime-core/__tests__/apiSetupHelpers.spec.ts index 5244a9a87b8..3dc22e67ce5 100644 --- a/packages/runtime-core/__tests__/apiSetupHelpers.spec.ts +++ b/packages/runtime-core/__tests__/apiSetupHelpers.spec.ts @@ -119,12 +119,20 @@ describe('SFC