Skip to content

Commit f1f9221

Browse files
authored
fix 3919: new set methods not working with observable set (#3921)
1 parent b7284f3 commit f1f9221

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

.changeset/wet-months-explain.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mobx": patch
3+
---
4+
5+
fix: #3919 new set methods not working with observable set

packages/mobx/__tests__/v5/base/set.js

+20-2
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ test("set.forEach is reactive", () => {
293293
describe("The Set object methods do what they are supposed to do", () => {
294294
const reactiveSet = set([1, 2, 3, 4, 5])
295295

296-
test("Observable Set methods returns correct result", () => {
296+
test("with native Set", () => {
297297
const intersectionObservableResult = reactiveSet.intersection(new Set([1, 2, 6]))
298298
const unionObservableResult = reactiveSet.union(new Set([1, 2, 6]))
299299
const differenceObservableResult = reactiveSet.difference(new Set([1, 2, 3, 4, 5, 6, 7]))
@@ -311,7 +311,25 @@ describe("The Set object methods do what they are supposed to do", () => {
311311
expect(isDisjointFromObservableResult).toBeTruthy()
312312
})
313313

314-
test("Observable Set proper works with Set-like objects", () => {
314+
test("with ObservableSet #3919", () => {
315+
const intersectionObservableResult = reactiveSet.intersection(set([1, 2, 6]))
316+
const unionObservableResult = reactiveSet.union(set([1, 2, 6]))
317+
const differenceObservableResult = reactiveSet.difference(set([1, 2, 3, 4, 5, 6, 7]))
318+
const symmetricDifferenceObservableResult = reactiveSet.symmetricDifference(set([3, 4]))
319+
const isSubsetOfObservableResult = reactiveSet.isSubsetOf(set([1, 2, 3]))
320+
const isSupersetOfObservableResult = reactiveSet.isSupersetOf(set([1, 2, 3, 4, 5, 6]))
321+
const isDisjointFromObservableResult = reactiveSet.isDisjointFrom(set([6, 7]))
322+
323+
expect(intersectionObservableResult).toEqual(new Set([1, 2]))
324+
expect(unionObservableResult).toEqual(new Set([1, 2, 3, 4, 5, 6]))
325+
expect(differenceObservableResult).toEqual(new Set())
326+
expect(symmetricDifferenceObservableResult).toEqual(new Set([1, 2, 5]))
327+
expect(isSubsetOfObservableResult).toBeFalsy()
328+
expect(isSupersetOfObservableResult).toBeFalsy()
329+
expect(isDisjointFromObservableResult).toBeTruthy()
330+
})
331+
332+
test("with Set-like", () => {
315333
const intersectionObservableResult = reactiveSet.intersection(
316334
new Map([1, 2, 6].map(i => [i, i]))
317335
)

packages/mobx/src/types/observableset.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
244244
}
245245

246246
intersection<U>(otherSet: ReadonlySetLike<U> | Set<U>): Set<T & U> {
247-
if (isES6Set(otherSet)) {
247+
if (isES6Set(otherSet) && !isObservableSet(otherSet)) {
248248
return otherSet.intersection(this)
249249
} else {
250250
const dehancedSet = new Set(this)
@@ -253,7 +253,7 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
253253
}
254254

255255
union<U>(otherSet: ReadonlySetLike<U> | Set<U>): Set<T | U> {
256-
if (isES6Set(otherSet)) {
256+
if (isES6Set(otherSet) && !isObservableSet(otherSet)) {
257257
return otherSet.union(this)
258258
} else {
259259
const dehancedSet = new Set(this)
@@ -266,7 +266,7 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
266266
}
267267

268268
symmetricDifference<U>(otherSet: ReadonlySetLike<U> | Set<U>): Set<T | U> {
269-
if (isES6Set(otherSet)) {
269+
if (isES6Set(otherSet) && !isObservableSet(otherSet)) {
270270
return otherSet.symmetricDifference(this)
271271
} else {
272272
const dehancedSet = new Set(this)
@@ -283,7 +283,7 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
283283
}
284284

285285
isDisjointFrom(otherSet: ReadonlySetLike<unknown> | Set<unknown>): boolean {
286-
if (isES6Set(otherSet)) {
286+
if (isES6Set(otherSet) && !isObservableSet(otherSet)) {
287287
return otherSet.isDisjointFrom(this)
288288
} else {
289289
const dehancedSet = new Set(this)

packages/mobx/src/utils/utils.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -140,18 +140,27 @@ export function createInstanceofPredicate<T>(
140140
} as any
141141
}
142142

143-
export function isES6Map(thing: any): thing is Map<any, any> {
143+
/**
144+
* Yields true for both native and observable Map, even across different windows.
145+
*/
146+
export function isES6Map(thing: unknown): thing is Map<any, any> {
144147
return thing != null && Object.prototype.toString.call(thing) === "[object Map]"
145148
}
146149

147-
export function isPlainES6Map(thing: Map<any, any>): boolean {
150+
/**
151+
* Makes sure a Map is an instance of non-inherited native or observable Map.
152+
*/
153+
export function isPlainES6Map(thing: Map<unknown, unknown>): boolean {
148154
const mapProto = Object.getPrototypeOf(thing)
149155
const objectProto = Object.getPrototypeOf(mapProto)
150156
const nullProto = Object.getPrototypeOf(objectProto)
151157
return nullProto === null
152158
}
153159

154-
export function isES6Set(thing: any): thing is Set<any> {
160+
/**
161+
* Yields true for both native and observable Set, even across different windows.
162+
*/
163+
export function isES6Set(thing: unknown): thing is Set<any> {
155164
return thing != null && Object.prototype.toString.call(thing) === "[object Set]"
156165
}
157166

0 commit comments

Comments
 (0)