git ssb

1+

Matt McKegg / mutant



Tree: a5b4c88f6f286b74e61e2c73bc8f9f83fae695eb

Files: a5b4c88f6f286b74e61e2c73bc8f9f83fae695eb / struct.js

2527 bytesRaw
1var Value = require('./value')
2var LazyWatcher = require('./lib/lazy-watcher')
3var isSame = require('./lib/is-same')
4
5module.exports = Struct
6
7var blackList = {
8 'length': 'Clashes with `Function.prototype.length`.\n',
9 'name': 'Clashes with `Function.prototype.name`\n',
10 'destroy': '`destroy` is a reserved key of struct\n'
11}
12
13function Struct (properties, opts) {
14 var object = Object.create({})
15 var releases = []
16 var binder = LazyWatcher(update, listen, unlisten)
17 binder.value = object
18
19 if (opts && opts.nextTick) binder.nextTick = true
20 if (opts && opts.idle) binder.idle = true
21
22 var comparer = opts && opts.comparer || null
23
24 var observable = function MutantStruct (listener) {
25 if (!listener) {
26 return binder.getValue()
27 }
28 return binder.addListener(listener)
29 }
30
31 var keys = Object.keys(properties)
32 var suspendBroadcast = false
33
34 keys.forEach(function (key) {
35 if (blackList.hasOwnProperty(key)) {
36 throw new Error("Cannot create a struct with a key named '" + key + "'.\n" + blackList[key])
37 }
38
39 var obs = typeof properties[key] === 'function'
40 ? properties[key]
41 : Value(properties[key])
42
43 object[key] = obs()
44 observable[key] = obs
45 })
46
47 observable.set = function (values) {
48 var lastValue = suspendBroadcast
49 suspendBroadcast = true
50 values = values || {}
51
52 // update inner observables
53 keys.forEach(function (key) {
54 if (observable[key]() !== values[key]) {
55 observable[key].set(values[key])
56 }
57 })
58
59 // store additional keys (but don't create observables)
60 Object.keys(values).forEach(function (key) {
61 if (!(key in properties)) {
62 object[key] = values[key]
63 }
64 })
65
66 suspendBroadcast = lastValue
67 if (!suspendBroadcast) {
68 binder.broadcast()
69 }
70 }
71
72 return observable
73
74 // scoped
75
76 function listen () {
77 keys.map(function (key) {
78 var obs = observable[key]
79 releases.push(obs(function (val) {
80 if (!isSame(val, object[key], comparer)) {
81 object[key] = val
82 if (!suspendBroadcast) {
83 binder.broadcast(object)
84 }
85 }
86 }))
87 })
88 }
89
90 function unlisten () {
91 while (releases.length) {
92 releases.pop()()
93 }
94 }
95
96 function update () {
97 var changed = false
98 keys.forEach(function (key) {
99 var newValue = observable[key]()
100 if (!isSame(newValue, object[key], comparer)) {
101 object[key] = observable[key]()
102 changed = true
103 }
104 })
105 return changed
106 }
107}
108

Built with git-ssb-web