diff --git a/.changeset/fresh-apricots-heal.md b/.changeset/fresh-apricots-heal.md new file mode 100644 index 0000000000..b85e9a5327 --- /dev/null +++ b/.changeset/fresh-apricots-heal.md @@ -0,0 +1,5 @@ +--- +"mobx": patch +--- + +Fix ES6 Map/Set checks for cross-window scripts diff --git a/packages/mobx/src/types/observablemap.ts b/packages/mobx/src/types/observablemap.ts index 99bd441750..3cf868b255 100644 --- a/packages/mobx/src/types/observablemap.ts +++ b/packages/mobx/src/types/observablemap.ts @@ -16,6 +16,7 @@ import { hasListeners, interceptChange, isES6Map, + isPlainES6Map, isPlainObject, isSpyEnabled, makeIterable, @@ -351,7 +352,7 @@ export class ObservableMap } else if (Array.isArray(other)) { other.forEach(([key, value]) => this.set(key, value)) } else if (isES6Map(other)) { - if (other.constructor !== Map) { + if (!isPlainES6Map(other)) { die(19, other) } other.forEach((value, key) => this.set(key, value)) diff --git a/packages/mobx/src/utils/utils.ts b/packages/mobx/src/utils/utils.ts index fc2760b04c..1f1ca701d7 100644 --- a/packages/mobx/src/utils/utils.ts +++ b/packages/mobx/src/utils/utils.ts @@ -141,11 +141,18 @@ export function createInstanceofPredicate( } export function isES6Map(thing: any): thing is Map { - return thing instanceof Map + return thing != null && Object.prototype.toString.call(thing) === "[object Map]" +} + +export function isPlainES6Map(thing: Map): 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 { - return thing instanceof Set + return thing != null && Object.prototype.toString.call(thing) === "[object Set]" } const hasGetOwnPropertySymbols = typeof Object.getOwnPropertySymbols !== "undefined"