WeakMap.spec.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { effect, isReactive, reactive, toRaw } from '../../src'
  2. describe('reactivity/collections', () => {
  3. describe('WeakMap', () => {
  4. test('instanceof', () => {
  5. const original = new WeakMap()
  6. const observed = reactive(original)
  7. expect(isReactive(observed)).toBe(true)
  8. expect(original).toBeInstanceOf(WeakMap)
  9. expect(observed).toBeInstanceOf(WeakMap)
  10. })
  11. it('should observe mutations', () => {
  12. let dummy
  13. const key = {}
  14. const map = reactive(new WeakMap())
  15. effect(() => {
  16. dummy = map.get(key)
  17. })
  18. expect(dummy).toBe(undefined)
  19. map.set(key, 'value')
  20. expect(dummy).toBe('value')
  21. map.set(key, 'value2')
  22. expect(dummy).toBe('value2')
  23. map.delete(key)
  24. expect(dummy).toBe(undefined)
  25. })
  26. it('should observe mutations with observed value as key', () => {
  27. let dummy
  28. const key = reactive({})
  29. const value = reactive({})
  30. const map = reactive(new WeakMap())
  31. effect(() => {
  32. dummy = map.get(key)
  33. })
  34. expect(dummy).toBe(undefined)
  35. map.set(key, value)
  36. expect(dummy).toBe(value)
  37. map.delete(key)
  38. expect(dummy).toBe(undefined)
  39. })
  40. it('should not observe custom property mutations', () => {
  41. let dummy
  42. const map: any = reactive(new WeakMap())
  43. effect(() => (dummy = map.customProp))
  44. expect(dummy).toBe(undefined)
  45. map.customProp = 'Hello World'
  46. expect(dummy).toBe(undefined)
  47. })
  48. it('should not observe non value changing mutations', () => {
  49. let dummy
  50. const key = {}
  51. const map = reactive(new WeakMap())
  52. const mapSpy = vi.fn(() => (dummy = map.get(key)))
  53. effect(mapSpy)
  54. expect(dummy).toBe(undefined)
  55. expect(mapSpy).toHaveBeenCalledTimes(1)
  56. map.set(key, undefined)
  57. expect(dummy).toBe(undefined)
  58. expect(mapSpy).toHaveBeenCalledTimes(2)
  59. map.set(key, 'value')
  60. expect(dummy).toBe('value')
  61. expect(mapSpy).toHaveBeenCalledTimes(3)
  62. map.set(key, 'value')
  63. expect(dummy).toBe('value')
  64. expect(mapSpy).toHaveBeenCalledTimes(3)
  65. map.delete(key)
  66. expect(dummy).toBe(undefined)
  67. expect(mapSpy).toHaveBeenCalledTimes(4)
  68. map.delete(key)
  69. expect(dummy).toBe(undefined)
  70. expect(mapSpy).toHaveBeenCalledTimes(4)
  71. })
  72. it('should not observe raw data', () => {
  73. let dummy
  74. const key = {}
  75. const map = reactive(new WeakMap())
  76. effect(() => (dummy = toRaw(map).get(key)))
  77. expect(dummy).toBe(undefined)
  78. map.set(key, 'Hello')
  79. expect(dummy).toBe(undefined)
  80. map.delete(key)
  81. expect(dummy).toBe(undefined)
  82. })
  83. it('should not pollute original Map with Proxies', () => {
  84. const map = new WeakMap()
  85. const observed = reactive(map)
  86. const key = {}
  87. const value = reactive({})
  88. observed.set(key, value)
  89. expect(map.get(key)).not.toBe(value)
  90. expect(map.get(key)).toBe(toRaw(value))
  91. })
  92. it('should return observable versions of contained values', () => {
  93. const observed = reactive(new WeakMap())
  94. const key = {}
  95. const value = {}
  96. observed.set(key, value)
  97. const wrapped = observed.get(key)
  98. expect(isReactive(wrapped)).toBe(true)
  99. expect(toRaw(wrapped)).toBe(value)
  100. })
  101. it('should observed nested data', () => {
  102. const observed = reactive(new WeakMap())
  103. const key = {}
  104. observed.set(key, { a: 1 })
  105. let dummy
  106. effect(() => {
  107. dummy = observed.get(key).a
  108. })
  109. observed.get(key).a = 2
  110. expect(dummy).toBe(2)
  111. })
  112. it('should not be trigger when the value and the old value both are NaN', () => {
  113. const map = new WeakMap()
  114. const key = {}
  115. map.set(key, NaN)
  116. const mapSpy = vi.fn(() => map.get(key))
  117. effect(mapSpy)
  118. map.set(key, NaN)
  119. expect(mapSpy).toHaveBeenCalledTimes(1)
  120. })
  121. it('should return proxy from WeakMap.set call', () => {
  122. const map = reactive(new WeakMap())
  123. const result = map.set({}, 'a')
  124. expect(result).toBe(map)
  125. })
  126. })
  127. })