git ssb

1+

Matt McKegg / mutant



Commit 99538587b3f862c6f3c7fa504500775fc48797de

map: add invalidation, bug fixes, onRemove, non-live updating on collection methods

Matt McKegg committed on 9/10/2016, 6:18:59 AM
Parent: 17c19a6e1cebd8d78dde3d7e061cb8327f773013

Files changed

lib/lazy-watcher.jschanged
map.jschanged
lib/lazy-watcher.jsView
@@ -13,13 +13,17 @@
1313 broadcast()
1414 }
1515 },
1616
17- getValue: function () {
17+ checkUpdated: function () {
1818 if (!obj.live || lazy) {
1919 lazy = false
2020 update()
2121 }
22+ },
23+
24+ getValue: function () {
25+ obj.checkUpdated()
2226 return obj.value
2327 },
2428
2529 addListener: function (listener) {
map.jsView
@@ -1,15 +1,22 @@
11 var resolve = require('./resolve')
22 var LazyWatcher = require('./lib/lazy-watcher')
3-var isReferenceType = require('./lib/is-reference-type')
3+var isSame = require('./lib/is-same')
4+var addCollectionMethods = require('./lib/add-collection-methods')
45
56 module.exports = Map
67
78 function Map (obs, lambda, opts) {
9+ // opts: comparer, maxTime, onRemove
10+
11+ var comparer = opts && opts.comparer || null
812 var releases = []
13+ var invalidateReleases = new global.WeakMap()
914 var binder = LazyWatcher(update, listen, unlisten)
1015
1116 var lastValues = new global.Map()
17+ var rawSet = new global.Set()
18+
1219 var items = []
1320
1421 var raw = []
1522 var values = []
@@ -30,24 +37,10 @@
3037 }
3138 return binder.addListener(listener)
3239 }
3340
34- result.get = function (index) {
35- return raw[index]
36- }
41+ addCollectionMethods(result, raw, binder.checkUpdated)
3742
38- result.getLength = function (index) {
39- return raw.length
40- }
41-
42- result.includes = function (valueOrObs) {
43- return !!~raw.indexOf(valueOrObs)
44- }
45-
46- result.indexOf = function (valueOrObs) {
47- return raw.indexOf(valueOrObs)
48- }
49-
5043 return result
5144
5245 // scoped
5346
@@ -55,16 +48,23 @@
5548 if (typeof obs === 'function') {
5649 releases.push(obs(binder.onUpdate))
5750 }
5851 rebindAll()
52+
53+ if (opts && opts.onListen) {
54+ opts.onListen()
55+ }
5956 }
6057
6158 function unlisten () {
6259 while (releases.length) {
6360 releases.pop()()
6461 }
6562 rebindAll()
66- lastValues.clear()
63+
64+ if (opts && opts.onUnlisten) {
65+ opts.onUnlisten()
66+ }
6767 }
6868
6969 function update () {
7070 var changed = false
@@ -79,9 +79,9 @@
7979 var item = get(obs, i)
8080 var currentItem = items[i]
8181 items[i] = item
8282
83- if (typeof item === 'object' || item !== currentItem) {
83+ if (!isSame(item, currentItem, comparer)) {
8484 if (maxTime && Date.now() - startedAt > maxTime) {
8585 queueUpdateItem(i)
8686 } else {
8787 updateItem(i)
@@ -91,16 +91,18 @@
9191 }
9292
9393 if (changed) {
9494 // clean up cache
95- var oldLength = items.length
95+ var oldLength = raw.length
96+ var newLength = getLength(obs)
9697 Array.from(lastValues.keys()).filter(notIncluded, obs).forEach(deleteEntry, lastValues)
97- items.length = getLength(obs)
98- values.length = items.length
99- raw.length = items.length
100- for (var index = items.length; index < oldLength; index++) {
98+ items.length = newLength
99+ values.length = newLength
100+ raw.length = newLength
101+ for (var index = newLength; index < oldLength; index++) {
101102 rebind(index)
102103 }
104+ Array.from(rawSet.values()).filter(notIncluded, raw).forEach(notifyRemoved)
103105 }
104106
105107 return changed
106108 }
@@ -124,20 +126,56 @@
124126 setImmediate(flushQueue)
125127 }
126128 }
127129
130+ function invalidateOn (item, obs) {
131+ if (!invalidateReleases.has(item)) {
132+ invalidateReleases.set(item, [])
133+ }
134+ invalidateReleases.get(item).push(obs(invalidate.bind(null, item)))
135+ }
136+
137+ function addInvalidateCallback (item) {
138+ return invalidateOn.bind(null, item)
139+ }
140+
141+ function notifyRemoved (item) {
142+ rawSet.delete(item)
143+ invalidateReleases.delete(item)
144+ if (opts && opts.onRemove) {
145+ opts.onRemove(item)
146+ }
147+ }
148+
149+ function invalidate (item) {
150+ var changed = false
151+ var length = getLength(obs)
152+ lastValues.delete(item)
153+ for (var i = 0; i < length; i++) {
154+ if (get(obs, i) === item) {
155+ updateItem(i)
156+ changed = true
157+ }
158+ }
159+ if (changed) {
160+ binder.broadcast()
161+ }
162+ }
163+
128164 function updateItem (i) {
129165 var item = get(obs, i)
130- if (isReferenceType(item)) {
131- raw[i] = lambda(item)
166+ if (!lastValues.has(item) || !isSame(item, item, comparer)) {
167+ var newValue = lambda(item, addInvalidateCallback(item))
168+ if (newValue !== raw[i]) {
169+ raw[i] = newValue
170+ }
171+ rawSet.add(newValue)
172+ lastValues.set(item, raw[i])
173+ rebind(i)
132174 } else {
133- if (!lastValues.has(item)) {
134- lastValues.set(item, lambda(item))
135- }
136175 raw[i] = lastValues.get(item)
137176 }
138177 values[i] = resolve(raw[i])
139- rebind(i)
140178 }
141179
142180 function rebind (index) {
143181 if (watches[index]) {
@@ -159,9 +197,9 @@
159197 }
160198
161199 function updateValue (obs, index) {
162200 return obs(function (value) {
163- if (values[index] !== value || typeof value === 'object') {
201+ if (!isSame(values[index], value, comparer)) {
164202 values[index] = value
165203 binder.broadcast()
166204 }
167205 })

Built with git-ssb-web