Repository: vigetlabs/microcosm
Pull request #252 (2017-03-10 20:06:49)

Properly release state changes to children
This commit prevents a bug where children would not receive the latest
updates when their parents emitted a change event.

I believe this was introduced in 12.1.0.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2753d9e..f2a479bd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## 12.1.2
+
+- Fixed issue where parent repos would send out changes before
+  children could reconcile.
+
 ## 12.1.1
 
 - Fixed length caching issue where history would still try to publish
diff --git a/package.json b/package.json
index 0a114dbb..1e42d738 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "microcosm",
-  "version": "12.1.1",
+  "version": "12.1.2",
   "private": true,
   "description": "Flux with actions at center stage. Write optimistic updates, cancel requests, and track changes with ease.",
   "main": "microcosm.js",
diff --git a/src/history.js b/src/history.js
index 2dc78c55..ee9bee4a 100644
--- a/src/history.js
+++ b/src/history.js
@@ -105,6 +105,8 @@ History.prototype = {
 
     this.archive()
 
+    this.invoke('update')
+
     this.invoke('release', action)
   },
 
diff --git a/src/microcosm.js b/src/microcosm.js
index 54fee3ac..b43fae9c 100644
--- a/src/microcosm.js
+++ b/src/microcosm.js
@@ -44,6 +44,11 @@ function Microcosm (options, state, deserialize)  {
   // Microcosm is now ready. Call the setup lifecycle method
   this.setup(options)
 
+  // Track a dirty flag, this is useful so that we can reconcile
+  // all Microcosm repos, then release their new state changes
+  // progressively
+  this.dirty = false
+
   // If given state, reset to that snapshot
   if (state) {
     this.reset(state, deserialize)
@@ -126,12 +131,17 @@ inherit(Microcosm, Emitter, {
     return this
   },
 
-  release (action) {
+  update () {
     let next = this.follower ? this.parent.state : this.recall(this.history.head)
 
-    if (next !== this.state) {
-      this.state = next
-      this._emit('change', next)
+    this.dirty = next !== this.state
+    this.state = next
+  },
+
+  release (action) {
+    if (this.dirty) {
+      this.dirty = false
+      this._emit('change', this.state)
     }
 
     this._emit('effect', action)


Test patch:
diff --git a/test/unit/microcosm/release.test.js b/test/unit/microcosm/release.test.js
index 34568522..5fa5c353 100644
--- a/test/unit/microcosm/release.test.js
+++ b/test/unit/microcosm/release.test.js
@@ -44,4 +44,27 @@ describe('Microcosm::release', function () {
     expect(spy).toHaveBeenCalledTimes(1)
   })
 
+  it('children have the latest state when their parents change', function() {
+    expect.assertions(2)
+
+    let step = n => n
+    let repo = new Microcosm({ maxHistory: Infinity })
+    let fork = repo.fork()
+
+    repo.addDomain('count', {
+      getInitialState() {
+        return 0
+      },
+      register () {
+        return { [step]: (a,b) => a + b }
+      }
+    })
+
+    repo.on('change', function () {
+      expect(repo.state.count).toBe(1)
+      expect(fork.state.count).toBe(repo.state.count)
+    })
+
+    repo.push(step, 1)
+  })
 })