|
|
@@ -6,6 +6,7 @@ import {
|
|
|
ref,
|
|
|
watch,
|
|
|
watchEffect,
|
|
|
+ withAsyncContext,
|
|
|
} from 'vue'
|
|
|
import { type SSRContext, renderToString } from '../src'
|
|
|
|
|
|
@@ -119,6 +120,89 @@ describe('ssr: watch', () => {
|
|
|
await nextTick()
|
|
|
expect(msg).toBe('start')
|
|
|
})
|
|
|
+
|
|
|
+ test('should not run non-immediate watchers registered after async context restore', async () => {
|
|
|
+ const text = ref('start')
|
|
|
+ let beforeAwaitTriggered = false
|
|
|
+ let afterAwaitTriggered = false
|
|
|
+
|
|
|
+ const App = defineComponent({
|
|
|
+ async setup() {
|
|
|
+ let __temp: any, __restore: any
|
|
|
+
|
|
|
+ watch(text, () => {
|
|
|
+ beforeAwaitTriggered = true
|
|
|
+ })
|
|
|
+ ;[__temp, __restore] = withAsyncContext(() => Promise.resolve())
|
|
|
+ __temp = await __temp
|
|
|
+ __restore()
|
|
|
+
|
|
|
+ watch(text, () => {
|
|
|
+ afterAwaitTriggered = true
|
|
|
+ })
|
|
|
+
|
|
|
+ text.value = 'changed'
|
|
|
+ expect(beforeAwaitTriggered).toBe(false)
|
|
|
+ expect(afterAwaitTriggered).toBe(false)
|
|
|
+
|
|
|
+ return () => h('div', null, text.value)
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ const app = createSSRApp(App)
|
|
|
+ const ctx: SSRContext = {}
|
|
|
+ const html = await renderToString(app, ctx)
|
|
|
+
|
|
|
+ expect(ctx.__watcherHandles).toBeUndefined()
|
|
|
+ expect(html).toMatch('changed')
|
|
|
+ await nextTick()
|
|
|
+ expect(beforeAwaitTriggered).toBe(false)
|
|
|
+ expect(afterAwaitTriggered).toBe(false)
|
|
|
+ })
|
|
|
+
|
|
|
+ test('should not run non-immediate watchers registered after async context restore on rejection', async () => {
|
|
|
+ const text = ref('start')
|
|
|
+ let beforeAwaitTriggered = false
|
|
|
+ let afterAwaitTriggered = false
|
|
|
+
|
|
|
+ const App = defineComponent({
|
|
|
+ async setup() {
|
|
|
+ let __temp: any, __restore: any
|
|
|
+
|
|
|
+ watch(text, () => {
|
|
|
+ beforeAwaitTriggered = true
|
|
|
+ })
|
|
|
+
|
|
|
+ try {
|
|
|
+ ;[__temp, __restore] = withAsyncContext(() =>
|
|
|
+ Promise.reject(new Error('failed')),
|
|
|
+ )
|
|
|
+ __temp = await __temp
|
|
|
+ __restore()
|
|
|
+ } catch {}
|
|
|
+
|
|
|
+ watch(text, () => {
|
|
|
+ afterAwaitTriggered = true
|
|
|
+ })
|
|
|
+
|
|
|
+ text.value = 'changed'
|
|
|
+ expect(beforeAwaitTriggered).toBe(false)
|
|
|
+ expect(afterAwaitTriggered).toBe(false)
|
|
|
+
|
|
|
+ return () => h('div', null, text.value)
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ const app = createSSRApp(App)
|
|
|
+ const ctx: SSRContext = {}
|
|
|
+ const html = await renderToString(app, ctx)
|
|
|
+
|
|
|
+ expect(ctx.__watcherHandles).toBeUndefined()
|
|
|
+ expect(html).toMatch('changed')
|
|
|
+ await nextTick()
|
|
|
+ expect(beforeAwaitTriggered).toBe(false)
|
|
|
+ expect(afterAwaitTriggered).toBe(false)
|
|
|
+ })
|
|
|
})
|
|
|
|
|
|
describe('ssr: watchEffect', () => {
|