Skip to content

Commit

Permalink
fix(shallowReadonly): watch should work for ref/reactive with shallow…
Browse files Browse the repository at this point in the history
…Readonly (#714)
  • Loading branch information
ygj6 committed Jun 4, 2021
1 parent 620d09b commit b6fc1f7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/reactivity/reactive.ts
Expand Up @@ -101,7 +101,7 @@ export function defineAccessControl(target: AnyObject, key: any, val?: any) {
})
}

function observe<T>(obj: T): T {
export function observe<T>(obj: T): T {
const Vue = getRegisteredVueOrDefault()
let observed: T
if (Vue.observable) {
Expand Down
14 changes: 9 additions & 5 deletions src/reactivity/readonly.ts
@@ -1,7 +1,8 @@
import { reactive, Ref, UnwrapRef } from '.'
import { isArray, isPlainObject, warn } from '../utils'
import { readonlySet } from '../utils/sets'
import { isRef } from './ref'
import { isReactive, observe } from './reactive'
import { isRef, RefImpl } from './ref'

export function isReadonly(obj: any): boolean {
return readonlySet.has(obj)
Expand Down Expand Up @@ -55,17 +56,20 @@ export function shallowReadonly(obj: any): any {
return obj
}

const readonlyObj = {}

const readonlyObj = isRef(obj)
? new RefImpl({} as any)
: isReactive(obj)
? observe({})
: {}
const source = reactive({})
const ob = (source as any).__ob__

for (const key of Object.keys(obj)) {
let val = obj[key]
let getter: (() => any) | undefined
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && !isRef(obj)) {
if (property.configurable === false) {
if (property) {
if (property.configurable === false && !isRef(obj)) {
continue
}
getter = property.get
Expand Down
2 changes: 1 addition & 1 deletion src/reactivity/ref.ts
Expand Up @@ -71,7 +71,7 @@ interface RefOption<T> {
get(): T
set?(x: T): void
}
class RefImpl<T> implements Ref<T> {
export class RefImpl<T> implements Ref<T> {
readonly [_refBrand]!: true
public value!: T
constructor({ get, set }: RefOption<T>) {
Expand Down
67 changes: 65 additions & 2 deletions test/v3/reactivity/readonly.spec.ts
@@ -1,5 +1,12 @@
import { mockWarn } from '../../helpers/mockWarn'
import { shallowReadonly, isReactive, ref, reactive } from '../../../src'
import {
shallowReadonly,
isReactive,
ref,
reactive,
watch,
nextTick,
} from '../../../src'

const Vue = require('vue/dist/vue.common.js')

Expand Down Expand Up @@ -391,7 +398,7 @@ describe('reactivity/readonly', () => {
countReadonly.number++
// @ts-expect-error
countRefReadonly.value++
}, 2000)
}, 1000)
return {
count,
countRef,
Expand All @@ -401,5 +408,61 @@ describe('reactivity/readonly', () => {

expect(vm.$el.textContent).toBe(`{\n "number": 0\n} 0`)
})

// #712
test('watch should work for ref with shallowReadonly', async () => {
const cb = jest.fn()
const vm = new Vue({
template: '<div>{{ countRef }}</div>',
setup() {
const countRef = ref(0)
const countRefReadonly = shallowReadonly(countRef)
watch(countRefReadonly, cb, { deep: true })
return {
countRef,
countRefReadonly,
}
},
}).$mount()

vm.countRef++
await nextTick()
expect(cb).toHaveBeenCalled()

vm.countRefReadonly++
await nextTick()
expect(
`Set operation on key "value" failed: target is readonly.`
).toHaveBeenWarned()
expect(vm.$el.textContent).toBe(`1`)
})

// #712
test('watch should work for reactive with shallowReadonly', async () => {
const cb = jest.fn()
const vm = new Vue({
template: '<div>{{ count.number }}</div>',
setup() {
const count = reactive({ number: 0 })
const countReadonly = shallowReadonly(count)
watch(countReadonly, cb, { deep: true })
return {
count,
countReadonly,
}
},
}).$mount()

vm.count.number++
await nextTick()
expect(cb).toHaveBeenCalled()

vm.countReadonly.number++
await nextTick()
expect(
`Set operation on key "number" failed: target is readonly.`
).toHaveBeenWarned()
expect(vm.$el.textContent).toBe(`1`)
})
})
})

0 comments on commit b6fc1f7

Please sign in to comment.