git ssb

1+

Matt McKegg / mutant



Tree: b2fdeb4fd6885660fbabd2c35067dd8f334cd4d6

Files: b2fdeb4fd6885660fbabd2c35067dd8f334cd4d6 / dict.js

2839 bytesRaw
1var LazyWatcher = require('./lib/lazy-watcher')
2var isReferenceType = require('./lib/is-reference-type')
3var resolve = require('./resolve')
4
5// TODO: reimplement using LazyWatcher
6
7module.exports = Dict
8
9function Dict (defaultValues) {
10 var object = Object.create({})
11 var sources = []
12 var releases = []
13
14 var binder = LazyWatcher(update, listen, unlisten)
15 binder.value = object
16
17 if (defaultValues) {
18 Object.keys(defaultValues).forEach(function (key) {
19 put(key, defaultValues[key])
20 })
21 }
22
23 var observable = function MutantDictionary (listener) {
24 if (!listener) {
25 return binder.getValue()
26 }
27 return binder.addListener(listener)
28 }
29
30 observable.put = function (key, valueOrObs) {
31 put(key, valueOrObs)
32 binder.broadcast()
33 }
34
35 observable.get = function (key) {
36 return sources[key]
37 }
38
39 observable.keys = function () {
40 return Object.keys(sources)
41 }
42
43 observable.clear = function () {
44 Object.keys(sources).forEach(function (key) {
45 tryInvoke(releases[key])
46 delete sources[key]
47 delete releases[key]
48 delete object[key]
49 })
50 binder.broadcast()
51 }
52
53 observable.delete = function (key) {
54 tryInvoke(releases[key])
55 delete sources[key]
56 delete releases[key]
57 delete object[key]
58 binder.broadcast()
59 }
60
61 observable.includes = function (valueOrObs) {
62 return !!~object.indexOf(valueOrObs)
63 }
64
65 observable.set = function (values) {
66 Object.keys(sources).forEach(function (key) {
67 tryInvoke(releases[key])
68 delete sources[key]
69 delete releases[key]
70 delete object[key]
71 })
72
73 Object.keys(values).forEach(function (key) {
74 put(key, values[key])
75 })
76
77 binder.broadcast()
78 }
79
80 return observable
81
82 // scoped
83
84 function put (key, valueOrObs) {
85 tryInvoke(releases[key])
86 sources[key] = valueOrObs
87 if (binder.live) {
88 releases[key] = bind(key, valueOrObs)
89 }
90 object[key] = resolve(valueOrObs)
91 }
92
93 function bind (key, valueOrObs) {
94 return typeof valueOrObs === 'function' ? valueOrObs(updateKey.bind(this, key)) : null
95 }
96
97 function updateKey (key, value) {
98 object[key] = value
99 binder.broadcast()
100 }
101
102 function listen () {
103 Object.keys(sources).forEach(function (key) {
104 releases[key] = bind(sources[key])
105 })
106 }
107
108 function unlisten () {
109 Object.keys(sources).forEach(function (key) {
110 tryInvoke(releases[key])
111 delete releases[key]
112 })
113 }
114
115 function update () {
116 var changed = false
117 Object.keys(sources).forEach(function (key) {
118 var newValue = resolve(sources[key])
119 if (newValue !== object[key] || isReferenceType(newValue)) {
120 object[key] = newValue
121 changed = true
122 }
123 })
124 return changed
125 }
126}
127
128function tryInvoke (func) {
129 if (typeof func === 'function') {
130 func()
131 }
132}
133

Built with git-ssb-web