Skip to content

Commit

Permalink
cherry-picked global state improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mweststrate committed Aug 27, 2018
1 parent abcc15e commit 7b9cb35
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 27 deletions.
47 changes: 33 additions & 14 deletions src/core/globalstate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export class MobXGlobals {
* MobXGlobals version.
* MobX compatiblity with other versions loaded in memory as long as this version matches.
* It indicates that the global state still stores similar information
*
* N.B: this version is unrelated to the package version of MobX, and is only the version of the
* internal state storage of MobX, and can be the same across many different package versions
*/
version = 5

Expand Down Expand Up @@ -99,30 +102,46 @@ export class MobXGlobals {
disableErrorBoundaries = false
}

export let globalState: MobXGlobals = new MobXGlobals()

let runInIsolationCalled = false
let canMergeGlobalState = true
let isolateCalled = false

{
export let globalState: MobXGlobals = (function() {
const global = getGlobal()
if (!global.__mobxInstanceCount) {
global.__mobxInstanceCount = 1
} else {
global.__mobxInstanceCount++

if (global.__mobxInstanceCount > 0 && !global.__mobxGlobals) canMergeGlobalState = false
if (global.__mobxGlobals && global.__mobxGlobals.version !== new MobXGlobals().version)
canMergeGlobalState = false

if (!canMergeGlobalState) {
setTimeout(() => {
if (!runInIsolationCalled) {
if (!isolateCalled) {
fail(
process.env.NODE_ENV !== "production" &&
"There are multiple mobx instances active. This might lead to unexpected results. See https://github.com/mobxjs/mobx/issues/1082 for details."
"There are multiple, different versions of MobX active. Make sure MobX is loaded only once or use `configure({ isolateGlobalState: true })`"
)
}
}, 1)
return new MobXGlobals()
} else if (global.__mobxGlobals) {
global.__mobxInstanceCount += 1
return global.__mobxGlobals
} else {
global.__mobxInstanceCount = 1
return (global.__mobxGlobals = new MobXGlobals())
}
}
})()

export function isolateGlobalState() {
runInIsolationCalled = true
getGlobal().__mobxInstanceCount--
if (
globalState.pendingReactions.length ||
globalState.inBatch ||
globalState.isRunningReactions
)
fail("isolateGlobalState should be called before MobX is running any reactions")
isolateCalled = true
if (canMergeGlobalState) {
if (--getGlobal().__mobxInstanceCount === 0) getGlobal().__mobxGlobals = undefined
globalState = new MobXGlobals()
}
}

export function getGlobalState(): any {
Expand Down
67 changes: 62 additions & 5 deletions test/mixed-versions/mixed-versions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,67 @@ const mobx1 = require("../../")
/* istanbul ignore next */
const mobx2 = require("../../lib/mobx.umd.min.js")

test("two versions should not work together if state is not shared", () => {
test("two versions should not work together by default", () => {
expect(global.__mobxInstanceCount).toBe(2)
expect(global.__mobxGlobals).not.toBe(undefined)

const a = mobx1.observable({
x: 1
})
const b = mobx2.observable({
x: 3
})

const values = []
const d1 = mobx1.autorun(() => {
values.push(b.x)
})
const d2 = mobx2.autorun(() => {
values.push(a.x)
})

a.x = 2
b.x = 4

d1()
d2()

expect(values).toEqual([3, 1, 2, 4])
})

test("two versions should not work together if state is isolated", () => {
mobx1.configure({ isolateGlobalState: true })
expect(global.__mobxInstanceCount).toBe(1)
expect(global.__mobxGlobals).not.toBe(undefined)

const a = mobx1.observable({
x: 1
})
const b = mobx2.observable({
x: 3
})

const values = []
const d1 = mobx1.autorun(() => {
values.push(b.x)
})
const d2 = mobx2.autorun(() => {
values.push(a.x)
})

a.x = 2
b.x = 4

d1()
d2()

expect(values).toEqual([3, 1])
})

test("global state should disappear if all imports are isolated", () => {
mobx2.configure({ isolateGlobalState: true })
expect(global.__mobxInstanceCount).toBe(0)
expect(global.__mobxGlobals).toBe(undefined)
const a = mobx1.observable({
x: 1
})
Expand All @@ -32,8 +92,5 @@ test("two versions should not work together if state is not shared", () => {
d1()
d2()

expect(values).toEqual([
3,
1 // no re-runs
])
expect(values).toEqual([3, 1])
})
16 changes: 8 additions & 8 deletions test/mixed-versions/state-sharing.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ function testOutput(cmd, expected) {

describe("it should handle multiple instances with the correct warnings", () => {
testOutput(
'require("../../");require("../../lib/mobx.umd.js")',
"There are multiple mobx instances active."
'require("../../");global.__mobxGlobals.version = -1; require("../../lib/mobx.umd.js")',
"There are multiple, different versions of MobX active. Make sure MobX is loaded only once"
)
testOutput(
'require("../../").configure({isolateGlobalState: true});require("../../lib/mobx.umd.js").configure({isolateGlobalState: true})',
'const m = require("../../"); global.__mobxGlobals.version = -1; m.configure({isolateGlobalState: true});require("../../lib/mobx.umd.js").configure({isolateGlobalState: true})',
""
)
// testOutput(
// 'require("../../");global.__mobxGlobals.version = -1;require("../../lib/mobx.umd.js").configure({isolateGlobalState: true})',
// ""
// )
testOutput(
'require("../../");require("../../lib/mobx.umd.js").configure({isolateGlobalState: true})',
""
)
testOutput(
'require("../../").configure({isolateGlobalState: true});require("../../lib/mobx.umd.js")',
'const m = require("../../");global.__mobxGlobals.version = -1;m.configure({isolateGlobalState: true});require("../../lib/mobx.umd.js")',
""
)
})

0 comments on commit 7b9cb35

Please sign in to comment.