Repository: vuejs/vue-next (ts)

Issue:
Script Setup nullable prop type causes compile error
### Version
3.2.20

### Reproduction link
[sfc.vuejs.org/](https://sfc.vuejs.org/#eyJBcHAudnVlIjoiPHNjcmlwdCBzZXR1cCBsYW5nPVwidHNcIj5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcblxuY29uc3QgbXNnID0gcmVmKCdIZWxsbyBXb3JsZCEnKVxuPC9zY3JpcHQ+XG5cbjx0ZW1wbGF0ZT5cbiAgPGgxPnt7IG1zZyB9fTwvaDE+XG4gIDxpbnB1dCB2LW1vZGVsPVwibXNnXCI+XG48L3RlbXBsYXRlPiIsImltcG9ydC1tYXAuanNvbiI6IntcbiAgXCJpbXBvcnRzXCI6IHtcbiAgICBcInZ1ZVwiOiBcImh0dHBzOi8vc2ZjLnZ1ZWpzLm9yZy92dWUucnVudGltZS5lc20tYnJvd3Nlci5qc1wiXG4gIH1cbn0iLCJFcnJvcnMudnVlIjoiPHNjcmlwdCBzZXR1cCBsYW5nPVwidHNcIj5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcbiAgXG5pbnRlcmZhY2UgUHJvcHMge1xuICAgIHNob3c/OiBJdGVtIHwgYm9vbGVhbiB8IG51bGxcbn1cbmNvbnN0IHByb3BzID0gd2l0aERlZmF1bHRzKGRlZmluZVByb3BzPFByb3BzPigpLCB7XG4gICAgc2hvdzogKCkgPT4gZmFsc2UsXG59KVxuXG5jb25zdCBtc2cgPSByZWYoJ0hlbGxvIFdvcmxkIScpXG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8aDEgdi1pZj1cInNob3dcIj57eyBtc2cgfX08L2gxPlxuICA8aW5wdXQgdi1tb2RlbD1cIm1zZ1wiPlxuPC90ZW1wbGF0ZT4iLCJOb0NvbXBpbGVFcnJvcnMudnVlIjoiPHNjcmlwdCBzZXR1cCBsYW5nPVwidHNcIj5cbmltcG9ydCB7IHJlZiB9IGZyb20gJ3Z1ZSdcbiAgXG5jb25zdCBwcm9wcyA9IGRlZmluZVByb3BzKHtcbiAgICBzaG93OiB7XG4gICAgICAgIHR5cGU6IEJvb2xlYW4gYXMgUHJvcFR5cGU8Qm9vbGVhbiB8IEl0ZW0gfCBudWxsPixcbiAgICAgICAgZGVmYXVsdDogZmFsc2VcbiAgICB9XG59KVxuXG5jb25zdCBtc2cgPSByZWYoJ0hlbGxvIFdvcmxkIScpXG48L3NjcmlwdD5cblxuPHRlbXBsYXRlPlxuICA8aDEgdi1pZj1cInNob3dcIj57eyBtc2cgfX08L2gxPlxuICA8aW5wdXQgdi1tb2RlbD1cIm1zZ1wiPlxuPC90ZW1wbGF0ZT4ifQ==)







### Steps to reproduce
Run the SFC Playground code with `npm run dev` and the Errors.vue file will throw a build error.

The NoErrors.vue file will not throw an error.

The only difference is the way nullable props are defined in script setup

### What is expected?
Should compile without errors.

### What is actually happening?
`withDefaults(defineProps<Props>(), {` in script setup throws an error when `<Props>` interface declaration includes the `null` type.

<!-- generated by vue-issues. DO NOT REMOVE -->

Pull request description:
fix(runtime-core): script-setup+ts: ensure proper hanlding of `null` as default prop value in types. (fix #4868)
`null` was missing from the list of primitive types in `InferDefault`, so it caused a type error when used in `withDefaults()`

fix:  #4868

Patch:
diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts
index 29367007c..0fa1c4bc2 100644
--- a/packages/reactivity/src/baseHandlers.ts
+++ b/packages/reactivity/src/baseHandlers.ts
@@ -7,7 +7,8 @@ import {
   readonlyMap,
   reactiveMap,
   shallowReactiveMap,
-  shallowReadonlyMap
+  shallowReadonlyMap,
+  isReadonly
 } from './reactive'
 import { TrackOpTypes, TriggerOpTypes } from './operations'
 import {
@@ -146,7 +147,7 @@ function createSetter(shallow = false) {
     receiver: object
   ): boolean {
     let oldValue = (target as any)[key]
-    if (!shallow) {
+    if (!shallow && !isReadonly(value)) {
       value = toRaw(value)
       oldValue = toRaw(oldValue)
       if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
diff --git a/packages/runtime-core/src/apiSetupHelpers.ts b/packages/runtime-core/src/apiSetupHelpers.ts
index fc1866af9..02ca5d53e 100644
--- a/packages/runtime-core/src/apiSetupHelpers.ts
+++ b/packages/runtime-core/src/apiSetupHelpers.ts
@@ -131,6 +131,7 @@ type InferDefaults<T> = {
 }
 
 type InferDefault<P, T> = T extends
+  | null
   | number
   | string
   | boolean
diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts
index 30ad4400d..223a7c602 100644
--- a/packages/runtime-core/src/components/KeepAlive.ts
+++ b/packages/runtime-core/src/components/KeepAlive.ts
@@ -381,7 +381,7 @@ function registerKeepAliveHook(
         }
         current = current.parent
       }
-      hook()
+      return hook()
     })
   injectHook(type, wrappedHook, target)
   // In addition to registering it on the target instance, we walk up the parent


Test patch:
diff --git a/packages/reactivity/__tests__/readonly.spec.ts b/packages/reactivity/__tests__/readonly.spec.ts
index 63426bb5e..185bb3107 100644
--- a/packages/reactivity/__tests__/readonly.spec.ts
+++ b/packages/reactivity/__tests__/readonly.spec.ts
@@ -465,4 +465,13 @@ describe('reactivity/readonly', () => {
       'Set operation on key "randomProperty" failed: target is readonly.'
     ).toHaveBeenWarned()
   })
+
+  // #4986
+  test('setting a readonly object as a property of a reactive object should retain readonly proxy', () => {
+    const r = readonly({})
+    const rr = reactive({}) as any
+    rr.foo = r
+    expect(rr.foo).toBe(r)
+    expect(isReadonly(rr.foo)).toBe(true)
+  })
 })
diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
index 4dce5d144..b60931e1f 100644
--- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
+++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
@@ -16,7 +16,9 @@ import {
   cloneVNode,
   provide,
   defineAsyncComponent,
-  Component
+  Component,
+  createApp,
+  onActivated
 } from '@vue/runtime-test'
 import { KeepAliveProps } from '../../src/components/KeepAlive'
 
@@ -874,4 +876,31 @@ describe('KeepAlive', () => {
     await nextTick()
     expect(serializeInner(root)).toBe('<p>1</p>')
   })
+
+  // #4976
+  test('handle error in async onActivated', async () => {
+    const err = new Error('foo')
+    const handler = jest.fn()
+
+    const app = createApp({
+      setup() {
+        return () => h(KeepAlive, null, () => h(Child))
+      }
+    })
+
+    const Child = {
+      setup() {
+        onActivated(async () => {
+          throw err
+        })
+      },
+      render() {}
+    }
+
+    app.config.errorHandler = handler
+    app.mount(nodeOps.createElement('div'))
+
+    await nextTick()
+    expect(handler).toHaveBeenCalledWith(err, {}, 'activated hook')
+  })
 })