WeakMap.spec.ts 4.1 KB

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