Skip to content

Commit

Permalink
fix 3919: new set methods not working with observable set (#3921)
Browse files Browse the repository at this point in the history
  • Loading branch information
urugator authored Sep 7, 2024
1 parent b7284f3 commit f1f9221
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/wet-months-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"mobx": patch
---

fix: #3919 new set methods not working with observable set
22 changes: 20 additions & 2 deletions packages/mobx/__tests__/v5/base/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ test("set.forEach is reactive", () => {
describe("The Set object methods do what they are supposed to do", () => {
const reactiveSet = set([1, 2, 3, 4, 5])

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

test("Observable Set proper works with Set-like objects", () => {
test("with ObservableSet #3919", () => {
const intersectionObservableResult = reactiveSet.intersection(set([1, 2, 6]))
const unionObservableResult = reactiveSet.union(set([1, 2, 6]))
const differenceObservableResult = reactiveSet.difference(set([1, 2, 3, 4, 5, 6, 7]))
const symmetricDifferenceObservableResult = reactiveSet.symmetricDifference(set([3, 4]))
const isSubsetOfObservableResult = reactiveSet.isSubsetOf(set([1, 2, 3]))
const isSupersetOfObservableResult = reactiveSet.isSupersetOf(set([1, 2, 3, 4, 5, 6]))
const isDisjointFromObservableResult = reactiveSet.isDisjointFrom(set([6, 7]))

expect(intersectionObservableResult).toEqual(new Set([1, 2]))
expect(unionObservableResult).toEqual(new Set([1, 2, 3, 4, 5, 6]))
expect(differenceObservableResult).toEqual(new Set())
expect(symmetricDifferenceObservableResult).toEqual(new Set([1, 2, 5]))
expect(isSubsetOfObservableResult).toBeFalsy()
expect(isSupersetOfObservableResult).toBeFalsy()
expect(isDisjointFromObservableResult).toBeTruthy()
})

test("with Set-like", () => {
const intersectionObservableResult = reactiveSet.intersection(
new Map([1, 2, 6].map(i => [i, i]))
)
Expand Down
8 changes: 4 additions & 4 deletions packages/mobx/src/types/observableset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
}

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

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

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

isDisjointFrom(otherSet: ReadonlySetLike<unknown> | Set<unknown>): boolean {
if (isES6Set(otherSet)) {
if (isES6Set(otherSet) && !isObservableSet(otherSet)) {
return otherSet.isDisjointFrom(this)
} else {
const dehancedSet = new Set(this)
Expand Down
15 changes: 12 additions & 3 deletions packages/mobx/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,27 @@ export function createInstanceofPredicate<T>(
} as any
}

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

export function isPlainES6Map(thing: Map<any, any>): boolean {
/**
* Makes sure a Map is an instance of non-inherited native or observable Map.
*/
export function isPlainES6Map(thing: Map<unknown, unknown>): boolean {
const mapProto = Object.getPrototypeOf(thing)
const objectProto = Object.getPrototypeOf(mapProto)
const nullProto = Object.getPrototypeOf(objectProto)
return nullProto === null
}

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

Expand Down

0 comments on commit f1f9221

Please sign in to comment.