git ssb

1+

Matt McKegg / mutant



Commit 1bfc5e6fd4a84f660a134de905aff9b599e108f3

map: make invalidators respect live state

Matt McKegg committed on 9/11/2016, 11:00:04 AM
Parent: 1e6901f400d4afe7df2471e0952dbbe00748d42c

Files changed

map.jschanged
test/test-map.jschanged
map.jsView
@@ -9,11 +9,11 @@
99 // opts: comparer, maxTime, onRemove
1010
1111 var comparer = opts && opts.comparer || null
1212 var releases = []
13- var invalidateReleases = new global.WeakMap()
1413 var binder = LazyWatcher(update, listen, unlisten)
1514
15+ var itemInvalidators = new global.Map()
1616 var lastValues = new global.Map()
1717 var rawSet = new global.Set()
1818
1919 var items = []
@@ -49,8 +49,14 @@
4949 releases.push(obs(binder.onUpdate))
5050 }
5151 rebindAll()
5252
53+ Array.from(itemInvalidators.values).forEach(function (invalidators) {
54+ invalidators.forEach(function (invalidator) {
55+ invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
56+ })
57+ })
58+
5359 if (opts && opts.onListen) {
5460 opts.onListen()
5561 }
5662 }
@@ -60,8 +66,12 @@
6066 releases.pop()()
6167 }
6268 rebindAll()
6369
70+ Array.from(itemInvalidators.values).forEach(function (invalidators) {
71+ invalidators.forEach(invokeRelease)
72+ })
73+
6474 if (opts && opts.onUnlisten) {
6575 opts.onUnlisten()
6676 }
6777 }
@@ -79,9 +89,9 @@
7989 var item = get(obs, i)
8090 var currentItem = items[i]
8191 items[i] = item
8292
83- if (!isSame(item, currentItem, comparer)) {
93+ if (!isSame(item, currentItem, comparer) || (!binder.live && checkInvalidated(item))) {
8494 if (maxTime && Date.now() - startedAt > maxTime) {
8595 queueUpdateItem(i)
8696 } else {
8797 updateItem(i)
@@ -93,21 +103,30 @@
93103 if (changed) {
94104 // clean up cache
95105 var oldLength = raw.length
96106 var newLength = getLength(obs)
97- Array.from(lastValues.keys()).filter(notIncluded, obs).forEach(deleteEntry, lastValues)
107+ Array.from(lastValues.keys()).filter(notIncluded, obs).forEach(removeItem)
98108 items.length = newLength
99109 values.length = newLength
100110 raw.length = newLength
101111 for (var index = newLength; index < oldLength; index++) {
102112 rebind(index)
103113 }
104- Array.from(rawSet.values()).filter(notIncluded, raw).forEach(notifyRemoved)
114+ Array.from(rawSet.values()).filter(notIncluded, raw).forEach(removeMapped)
105115 }
106116
107117 return changed
108118 }
109119
120+ function checkInvalidated (item) {
121+ if (itemInvalidators.has(item)) {
122+ return itemInvalidators.get(item).some(function (invalidator) {
123+ lastValues.delete(invalidator.item)
124+ return !isSame(invalidator.currentValue, resolve(invalidator.observable), comparer)
125+ })
126+ }
127+ }
128+
110129 function queueUpdateItem (i) {
111130 if (!queue.length) {
112131 setImmediate(flushQueue)
113132 }
@@ -127,32 +146,52 @@
127146 }
128147 }
129148
130149 function invalidateOn (item, obs) {
131- if (!invalidateReleases.has(item)) {
132- invalidateReleases.set(item, [])
150+ if (!itemInvalidators.has(item)) {
151+ itemInvalidators.set(item, [])
133152 }
134- invalidateReleases.get(item).push(obs(invalidate.bind(null, item)))
153+
154+ var invalidators = itemInvalidators.get(item)
155+ var invalidator = {
156+ currentValue: resolve(obs),
157+ observable: obs,
158+ item: item,
159+ release: null
160+ }
161+
162+ invalidators.push(invalidator)
163+
164+ if (binder.live) {
165+ invalidator.release = invalidator.observable(invalidate.bind(null, invalidator))
166+ }
135167 }
136168
137169 function addInvalidateCallback (item) {
138170 return invalidateOn.bind(null, item)
139171 }
140172
141- function notifyRemoved (item) {
142- rawSet.delete(item)
143- invalidateReleases.delete(item)
173+ function removeItem (item) {
174+ lastValues.delete(item)
175+ if (itemInvalidators.has(item)) {
176+ itemInvalidators.get(item).forEach(invokeRelease)
177+ itemInvalidators.delete(item)
178+ }
179+ }
180+
181+ function removeMapped (mappedItem) {
182+ rawSet.delete(mappedItem)
144183 if (opts && opts.onRemove) {
145- opts.onRemove(item)
184+ opts.onRemove(mappedItem)
146185 }
147186 }
148187
149- function invalidate (item) {
188+ function invalidate (entry) {
150189 var changed = false
151190 var length = getLength(obs)
152- lastValues.delete(item)
191+ lastValues.delete(entry.item)
153192 for (var i = 0; i < length; i++) {
154- if (get(obs, i) === item) {
193+ if (get(obs, i) === entry.item) {
155194 updateItem(i)
156195 changed = true
157196 }
158197 }
@@ -163,8 +202,12 @@
163202
164203 function updateItem (i) {
165204 var item = get(obs, i)
166205 if (!lastValues.has(item) || !isSame(item, item, comparer)) {
206+ if (itemInvalidators.has(item)) {
207+ itemInvalidators.get(item).forEach(invokeRelease)
208+ itemInvalidators.delete(item)
209+ }
167210 var newValue = lambda(item, addInvalidateCallback(item))
168211 if (newValue !== raw[i]) {
169212 raw[i] = newValue
170213 }
@@ -248,4 +291,11 @@
248291
249292 function deleteEntry (entry) {
250293 this.delete(entry)
251294 }
295+
296+function invokeRelease (item) {
297+ if (item.release) {
298+ item.release()
299+ item.release = null
300+ }
301+}
test/test-map.jsView
@@ -23,4 +23,15 @@
2323 array.push('chicken')
2424 array.push('wolf')
2525 array.insert('sheep', 0)
2626 value.set('monkey')
27+
28+// offline invalidate
29+var invalidator = Value(false)
30+var count = 0
31+var thing = Map(Array(['cat']), function (obj, invalidateOn) {
32+ invalidateOn(invalidator)
33+ return count++
34+})
35+console.log(thing())
36+invalidator.set(true)
37+console.log(thing())

Built with git-ssb-web