]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(ssr): handle error during ssr render call edison/fix/12575 12601/head
authordaiwei <daiwei521@126.com>
Mon, 23 Dec 2024 07:01:33 +0000 (15:01 +0800)
committerdaiwei <daiwei521@126.com>
Mon, 23 Dec 2024 07:01:33 +0000 (15:01 +0800)
packages/server-renderer/__tests__/render.spec.ts
packages/server-renderer/src/render.ts

index d0a5223b2ff635b2df39b187f8f4438b01bfff38..5083a9830160353b64c50c0f5f6deae10cc8a367 100644 (file)
@@ -12,6 +12,7 @@ import {
   defineComponent,
   getCurrentInstance,
   h,
+  nextTick,
   onErrorCaptured,
   onServerPrefetch,
   reactive,
@@ -819,6 +820,9 @@ function testRender(type: string, render: typeof renderToString) {
           )
         } catch {}
         expect(getCurrentInstance()).toBe(prev)
+        expect(
+          '[Vue warn]: Unhandled error during execution of render function',
+        ).toHaveBeenWarned()
       })
 
       // #7733
@@ -1188,6 +1192,42 @@ function testRender(type: string, render: typeof renderToString) {
       expect((capturedError as unknown as Error).message).toBe('An error')
     })
 
+    test('async setup throwing error', async () => {
+      let capturedError: string[] = []
+
+      const Child = {
+        async setup() {
+          await nextTick()
+          throw new Error('An error')
+          return { foo: { bar: 1 } }
+        },
+        template: `<span>{{ foo.bar }}</span>`,
+      }
+
+      const app = createApp({
+        components: { Child },
+        setup() {
+          onErrorCaptured(e => {
+            capturedError.push(e.message)
+            return false
+          })
+        },
+        template: `<Suspense><Child /></Suspense>`,
+      })
+
+      try {
+        await render(app)
+      } catch (e: any) {}
+      expect(capturedError.length).toBe(2)
+      expect(capturedError).toStrictEqual([
+        'An error',
+        "Cannot read properties of undefined (reading 'bar')",
+      ])
+      expect(
+        '[Vue warn]: Property "foo" was accessed during render but is not defined on instance',
+      ).toHaveBeenWarned()
+    })
+
     test('computed reactivity during SSR with onServerPrefetch', async () => {
       const store = {
         // initial state could be hydrated
index f04080b9c3127d04024b7a18cdc499118ea55af9..cb2a88028d62918789f228f5d62e2d872b0df70c 100644 (file)
@@ -3,6 +3,7 @@ import {
   type Component,
   type ComponentInternalInstance,
   type DirectiveBinding,
+  ErrorCodes,
   Fragment,
   type FunctionalComponent,
   Static,
@@ -10,6 +11,7 @@ import {
   type VNode,
   type VNodeArrayChildren,
   type VNodeProps,
+  handleError,
   mergeProps,
   ssrUtils,
   warn,
@@ -200,6 +202,8 @@ function renderComponentSubTree(
           instance.data,
           instance.ctx,
         )
+      } catch (err) {
+        handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
       } finally {
         setCurrentRenderingInstance(prev)
       }