diff --git a/.changeset/fix-observableset-receiver-order.md b/.changeset/fix-observableset-receiver-order.md new file mode 100644 index 000000000..12a1cc135 --- /dev/null +++ b/.changeset/fix-observableset-receiver-order.md @@ -0,0 +1,5 @@ +--- +"mobx": patch +--- + +Fix ObservableSet union, intersection and symmetricDifference to return results in receiver order, matching native Set, when the argument is a plain Set. diff --git a/packages/mobx/__tests__/base/set.js b/packages/mobx/__tests__/base/set.js index 45d893547..fc4b54902 100644 --- a/packages/mobx/__tests__/base/set.js +++ b/packages/mobx/__tests__/base/set.js @@ -339,6 +339,17 @@ describe("The Set object methods do what they are supposed to do", () => { expect(isDisjointFromObservableResult).toBeTruthy() }) + test("set methods preserve receiver order (matches native Set)", () => { + const nativeCopy = new Set(reactiveSet) + const other = new Set([6, 2, 1]) + + expect([...reactiveSet.union(other)]).toEqual([...nativeCopy.union(other)]) + expect([...reactiveSet.intersection(other)]).toEqual([...nativeCopy.intersection(other)]) + expect([...reactiveSet.symmetricDifference(other)]).toEqual([ + ...nativeCopy.symmetricDifference(other) + ]) + }) + test("with ObservableSet #3919", () => { const intersectionObservableResult = reactiveSet.intersection(set([1, 2, 6])) const unionObservableResult = reactiveSet.union(set([1, 2, 6])) diff --git a/packages/mobx/src/types/observableset.ts b/packages/mobx/src/types/observableset.ts index ba9cdc2f4..7e9e9bf07 100644 --- a/packages/mobx/src/types/observableset.ts +++ b/packages/mobx/src/types/observableset.ts @@ -55,16 +55,14 @@ export type ISetWillDeleteChange = { type: "delete" object: ObservableSet oldValue: T -}; +} export type ISetWillAddChange = { type: "add" object: ObservableSet newValue: T -}; +} -export type ISetWillChange = - | ISetWillDeleteChange - | ISetWillAddChange +export type ISetWillChange = ISetWillDeleteChange | ISetWillAddChange export class ObservableSet implements Set, IInterceptable, IListenable { [$mobx] = ObservableSetMarker @@ -133,8 +131,7 @@ export class ObservableSet implements Set, IInterceptable { @@ -244,21 +241,11 @@ export class ObservableSet implements Set, IInterceptable(otherSet: ReadonlySetLike | Set): Set { - if (isES6Set(otherSet) && !isObservableSet(otherSet)) { - return otherSet.intersection(this) - } else { - const dehancedSet = new Set(this) - return dehancedSet.intersection(otherSet) - } + return new Set(this).intersection(otherSet) } union(otherSet: ReadonlySetLike | Set): Set { - if (isES6Set(otherSet) && !isObservableSet(otherSet)) { - return otherSet.union(this) - } else { - const dehancedSet = new Set(this) - return dehancedSet.union(otherSet) - } + return new Set(this).union(otherSet) } difference(otherSet: ReadonlySetLike): Set { @@ -266,12 +253,7 @@ export class ObservableSet implements Set, IInterceptable(otherSet: ReadonlySetLike | Set): Set { - if (isES6Set(otherSet) && !isObservableSet(otherSet)) { - return otherSet.symmetricDifference(this) - } else { - const dehancedSet = new Set(this) - return dehancedSet.symmetricDifference(otherSet) - } + return new Set(this).symmetricDifference(otherSet) } isSubsetOf(otherSet: ReadonlySetLike): boolean { @@ -283,12 +265,7 @@ export class ObservableSet implements Set, IInterceptable | Set): boolean { - if (isES6Set(otherSet) && !isObservableSet(otherSet)) { - return otherSet.isDisjointFrom(this) - } else { - const dehancedSet = new Set(this) - return dehancedSet.isDisjointFrom(otherSet) - } + return new Set(this).isDisjointFrom(otherSet) } replace(other: ObservableSet | IObservableSetInitialValues): ObservableSet {