+54
-8
lines changedFilter options
+54
-8
lines changed Original file line number Diff line number Diff line change
@@ -632,6 +632,49 @@ describe('Suspense', () => {
632
632
expect(serializeInner(root)).toBe(`<div>oops</div>`)
633
633
})
634
634
635
+
// #3857
636
+
test('error handling w/ template optimization', async () => {
637
+
const Async = {
638
+
async setup() {
639
+
throw new Error('oops')
640
+
}
641
+
}
642
+
643
+
const Comp = {
644
+
template: `
645
+
<div v-if="errorMessage">{{ errorMessage }}</div>
646
+
<Suspense v-else>
647
+
<div>
648
+
<Async />
649
+
</div>
650
+
<template #fallback>
651
+
<div>fallback</div>
652
+
</template>
653
+
</Suspense>
654
+
`,
655
+
components: { Async },
656
+
setup() {
657
+
const errorMessage = ref<string | null>(null)
658
+
onErrorCaptured(err => {
659
+
errorMessage.value =
660
+
err instanceof Error
661
+
? err.message
662
+
: `A non-Error value thrown: ${err}`
663
+
return false
664
+
})
665
+
return { errorMessage }
666
+
}
667
+
}
668
+
669
+
const root = nodeOps.createElement('div')
670
+
render(h(Comp), root)
671
+
expect(serializeInner(root)).toBe(`<div>fallback</div>`)
672
+
673
+
await Promise.all(deps)
674
+
await nextTick()
675
+
expect(serializeInner(root)).toBe(`<div>oops</div>`)
676
+
})
677
+
635
678
it('combined usage (nested async + nested suspense + multiple deps)', async () => {
636
679
const msg = ref('nested msg')
637
680
const calls: number[] = []
Original file line number Diff line number Diff line change
@@ -1073,16 +1073,19 @@ function baseCreateRenderer(
1073
1073
const newVNode = newChildren[i]
1074
1074
// Determine the container (parent element) for the patch.
1075
1075
const container =
1076
+
// oldVNode may be an errored async setup() component inside Suspense
1077
+
// which will not have a mounted element
1078
+
oldVNode.el &&
1076
1079
// - In the case of a Fragment, we need to provide the actual parent
1077
1080
// of the Fragment itself so it can move its children.
1078
-
oldVNode.type === Fragment ||
1079
-
// - In the case of different nodes, there is going to be a replacement
1080
-
// which also requires the correct parent container
1081
-
!isSameVNodeType(oldVNode, newVNode) ||
1082
-
// - In the case of a component, it could contain anything.
1083
-
oldVNode.shapeFlag & ShapeFlags.COMPONENT ||
1084
-
oldVNode.shapeFlag & ShapeFlags.TELEPORT
1085
-
? hostParentNode(oldVNode.el!)!
1081
+
(oldVNode.type === Fragment ||
1082
+
// - In the case of different nodes, there is going to be a replacement
1083
+
// which also requires the correct parent container
1084
+
!isSameVNodeType(oldVNode, newVNode) ||
1085
+
// - In the case of a component, it could contain anything.
1086
+
oldVNode.shapeFlag & ShapeFlags.COMPONENT ||
1087
+
oldVNode.shapeFlag & ShapeFlags.TELEPORT)
1088
+
? hostParentNode(oldVNode.el)!
1086
1089
: // In other cases, the parent container is not actually used so we
1087
1090
// just pass the block element here to avoid a DOM parentNode call.
1088
1091
fallbackContainer
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4