statebus 6.1.20 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/statebus.js CHANGED
@@ -3,17 +3,19 @@
3
3
  if (typeof module != 'undefined') module.exports = definition()
4
4
  else if (typeof define == 'function' && typeof define.amd == 'object') define(definition)
5
5
  else this[name] = definition()
6
- }('statebus', function() {statelog_indent = 0; var busses = {}, executing_funk, global_funk, funks = {}, clean_timer, symbols, nodejs = typeof window === 'undefined'; function make_bus (options) {
6
+ }('statebus', function() {statelog_indent = 0; var busses = {}, bus_count = 0, executing_funk, global_funk, funks = {}, clean_timer, symbols, nodejs = typeof window === 'undefined'; function make_bus (options) {
7
7
 
8
8
 
9
9
  // ****************
10
- // Fetch, Save, Forget, Delete
10
+ // Get, Set, Forget, Delete
11
11
 
12
- function fetch (key, callback) {
12
+ function get (key, callback) {
13
+ if (typeof key !== 'string'
14
+ && !(typeof key === 'object' && typeof key.key === 'string'))
15
+ throw ('Error: get(key) called with key = '
16
+ + JSON.stringify(key))
13
17
  key = key.key || key // You can pass in an object instead of key
14
18
  // We should probably disable this in future
15
- if (typeof key !== 'string')
16
- throw ('Error: fetch(key) called with a non-string key: '+key)
17
19
  bogus_check(key)
18
20
 
19
21
  var called_from_reactive_funk = !callback
@@ -22,7 +24,7 @@
22
24
  // Initialize callback
23
25
  if (callback) {
24
26
  (callback.defined = callback.defined || []
25
- ).push({as:'fetch callback', key:key});
27
+ ).push({as:'get callback', key:key});
26
28
  callback.has_seen = callback.has_seen || function (bus, key, version) {
27
29
  callback.seen_keys = callback.seen_keys || {}
28
30
  var bus_key = JSON.stringify([bus.id, key])
@@ -35,27 +37,27 @@
35
37
 
36
38
  // ** Subscribe the calling funk **
37
39
 
38
- fetches_in.add(key, funk_key(funk))
40
+ gets_in.add(key, funk_key(funk))
39
41
  if (to_be_forgotten[key]) {
40
42
  clearTimeout(to_be_forgotten[key])
41
43
  delete to_be_forgotten[key]
42
44
  }
43
45
 
44
- bind(key, 'on_save', funk)
46
+ bind(key, 'on_set', funk)
45
47
 
46
- // ** Call fetchers upstream **
48
+ // ** Call getters upstream **
47
49
 
48
- // TODO: checking fetches_out[] doesn't count keys that we got which
50
+ // TODO: checking gets_out[] doesn't count keys that we got which
49
51
  // arrived nested within a bigger object, because we never explicity
50
- // fetched those keys. But we don't need to fetch them now cause we
52
+ // got those keys. But we don't need to get them now cause we
51
53
  // already have them.
52
- var to_fetchers = 0
53
- if (!fetches_out[key])
54
- to_fetchers = bus.route(key, 'to_fetch', key)
54
+ var to_getters = 0
55
+ if (!gets_out[key])
56
+ to_getters = bus.route(key, 'to_get', key)
55
57
 
56
58
  // Now there might be a new value pubbed onto this bus.
57
- // Or there might be a pending fetch.
58
- // ... or there weren't any fetchers upstream.
59
+ // Or there might be a pending get.
60
+ // ... or there weren't any getters upstream.
59
61
 
60
62
 
61
63
  // ** Return a value **
@@ -68,29 +70,29 @@
68
70
  }
69
71
 
70
72
  // Otherwise, we want to make sure that a pub gets called on the
71
- // handler. If there's a pending fetch, then it'll get called later.
72
- // If there was a to_fetch, then it already got called. Otherwise,
73
+ // handler. If there's a pending get, then it'll get called later.
74
+ // If there was a to_get, then it already got called. Otherwise,
73
75
  // let's call it now.
74
- else if (!pending_fetches[key] && to_fetchers === 0) {
76
+ else if (!pending_gets[key] && to_getters === 0) {
75
77
  // TODO: my intuition suggests that we might prefer to delay this
76
- // .on_save getting called in a setTimeout(f,0), to be consistent
77
- // with other calls to .on_save.
78
+ // .on_set getting called in a setTimeout(f,0), to be consistent
79
+ // with other calls to .on_set.
78
80
  backup_cache[key] = backup_cache[key] || {key: key}
79
- run_handler(funk, 'on_save', cache[key] = cache[key] || {key: key})
81
+ run_handler(funk, 'on_set', cache[key] = cache[key] || {key: key})
80
82
  }
81
83
  }
82
- function fetch_once (key, cb) {
84
+ function get_once (key, cb) {
83
85
  function cb2 (o) { cb(o); forget(key, cb2) }
84
- // fetch(key) // This prevents key from being forgotten
85
- fetch(key, cb2)
86
+ // get(key) // This prevents key from being forgotten
87
+ get(key, cb2)
86
88
  }
87
- fetch.once = fetch_once
88
- var pending_fetches = {}
89
- var fetches_out = {} // Maps `key' to `func' iff we've fetched `key'
90
- var fetches_in = new One_To_Many() // Maps `key' to `pub_funcs' subscribed to our key
89
+ get.once = get_once
90
+ var pending_gets = {}
91
+ var gets_out = {} // Maps `key' to `func' iff we've got `key'
92
+ var gets_in = new One_To_Many() // Maps `key' to `pub_funcs' subscribed to our key
91
93
 
92
94
  var currently_saving
93
- function save (obj, t) {
95
+ function set (obj, t) {
94
96
  // First let's handle diffs
95
97
  if (typeof obj === 'string' && t && t.patch) {
96
98
  if (typeof t.patch == 'string') t.patch = [t.patch]
@@ -99,8 +101,8 @@
99
101
  }
100
102
 
101
103
  if (!('key' in obj) || typeof obj.key !== 'string') {
102
- console.error('Error: save(obj) called on object without a key: ', obj)
103
- console.trace('Bad save(obj)')
104
+ console.error('Error: set(obj) called on object without a key: ', obj)
105
+ console.trace('Bad set(obj)')
104
106
  }
105
107
  bogus_check(obj.key)
106
108
 
@@ -114,7 +116,7 @@
114
116
  }
115
117
 
116
118
  if (honking_at(obj.key))
117
- var message = save_msg(obj, t, 'save')
119
+ var message = set_msg(obj, t, 'set')
118
120
 
119
121
  // Ignore if nothing happened
120
122
  if (obj.key && !changed(obj)) {
@@ -128,11 +130,11 @@
128
130
  var was_saving = currently_saving
129
131
  currently_saving = obj.key
130
132
 
131
- // Call the to_save() handlers!
132
- var num_handlers = bus.route(obj.key, 'to_save', obj, t)
133
+ // Call the to_set() handlers!
134
+ var num_handlers = bus.route(obj.key, 'to_set', obj, t)
133
135
  if (num_handlers === 0) {
134
136
  // And fire if there weren't any!
135
- save.fire(obj, t)
137
+ set.fire(obj, t)
136
138
  bus.route(obj.key, 'on_set_sync', obj, t)
137
139
  }
138
140
  }
@@ -141,13 +143,13 @@
141
143
  currently_saving = was_saving
142
144
  }
143
145
  // TODO: Here's an alternative. Instead of counting the handlers and
144
- // seeing if there are zero, I could just make a to_save handler that
146
+ // seeing if there are zero, I could just make a to_set handler that
145
147
  // is shadowed by other handlers if I can get later handlers to shadow
146
148
  // earlier ones.
147
149
  }
148
150
 
149
- // save.sync() will save with the version of the current executing reaction
150
- save.sync = function save_sync (obj, t) {
151
+ // set.sync() will set with the version of the current executing reaction
152
+ set.sync = function set_sync (obj, t) {
151
153
  t = bus.clone(t || {})
152
154
  // t.version: executing_funk?.transaction?.version
153
155
  // || executing_funk?.latest_reaction_at
@@ -156,13 +158,13 @@
156
158
  && executing_funk.transaction.version)
157
159
  || (executing_funk
158
160
  && executing_funk.latest_reaction_at))
159
- save(obj, t)
161
+ set(obj, t)
160
162
  }
161
163
 
162
- // We might eventually want a save.fire.sync() too, which defaults the
164
+ // We might eventually want a set.fire.sync() too, which defaults the
163
165
  // version to `executing_funk?.transaction?.version`
164
166
 
165
- save.fire = fire
167
+ set.fire = fire
166
168
  function fire (obj, t) {
167
169
  t = t || {}
168
170
 
@@ -176,7 +178,7 @@
176
178
  // Warning: Changes to *nested* objects will *not* be printed out!
177
179
  // In the future, we'll remove the recursion from fire() so that
178
180
  // nested objects aren't even changed.
179
- var message = save_msg(obj, t, 'save.fire')
181
+ var message = set_msg(obj, t, 'set.fire')
180
182
  var color, icon
181
183
  if (currently_saving === obj.key &&
182
184
  !(obj.key && !changed(obj))) {
@@ -189,18 +191,18 @@
189
191
  if (obj.key && !changed(obj)) {
190
192
  color = grey
191
193
  icon = 'x'
192
- if (t.to_fetch)
193
- message = (t.m) || 'Fetched ' + bus + "('"+obj.key+"')"
194
+ if (t.to_get)
195
+ message = (t.m) || 'Got ' + bus + "('"+obj.key+"')"
194
196
  if (t.version) message += ' [' + t.version + ']'
195
197
  statelog(obj.key, color, icon, message)
196
198
  return
197
199
  }
198
200
 
199
201
  color = red, icon = '•'
200
- if (t.to_fetch || pending_fetches[obj.key]) {
202
+ if (t.to_get || pending_gets[obj.key]) {
201
203
  color = green
202
204
  icon = '^'
203
- message = add_diff_msg((t.m)||'Fetched '+bus+"('"+obj.key+"')",
205
+ message = add_diff_msg((t.m)||'Got '+bus+"('"+obj.key+"')",
204
206
  obj)
205
207
  if (t.version) message += ' [' + t.version + ']'
206
208
  }
@@ -213,7 +215,7 @@
213
215
  // Recursively add all of obj, and its sub-objects, into the cache
214
216
  var modified_keys = update_cache(obj, cache)
215
217
 
216
- delete pending_fetches[obj.key]
218
+ delete pending_gets[obj.key]
217
219
 
218
220
  if ((executing_funk !== global_funk) && executing_funk.loading()) {
219
221
  abort_changes(modified_keys)
@@ -234,7 +236,7 @@
234
236
  }
235
237
  }
236
238
 
237
- save.abort = function (obj, t) {
239
+ set.abort = function (obj, t) {
238
240
  if (!obj) console.error('No obj', obj)
239
241
  abort_changes([obj.key])
240
242
  statelog(obj.key, yellow, '<', 'Aborting ' + obj.key)
@@ -247,19 +249,19 @@
247
249
  }
248
250
 
249
251
  // Now create the statebus object
250
- function bus (arg) {
252
+ function bus (arg1, arg2) {
251
253
  // Called with a function to react to
252
- if (typeof arg === 'function') {
253
- var f = reactive(arg)
254
+ if (typeof arg1 === 'function') {
255
+ var f = reactive(arg1)
254
256
  f()
255
257
  return f
256
258
  }
257
259
 
258
260
  // Called with a key to produce a subspace
259
- else return subspace(arg)
261
+ else return subspace(arg1, arg2)
260
262
  }
261
- var id = 'bus ' + Math.random().toString(36).substring(7)
262
- bus.toString = function () { return bus.label || id }
263
+ var id = 'bus-' + Math.random().toString(36).substring(7)
264
+ bus.toString = function () { return bus.label || 'bus'+this_bus_num || id }
263
265
  bus.delete_bus = function () {
264
266
  // // Forget all wildcard handlers
265
267
  // for (var i=0; i<wildcard_handlers.length; i++) {
@@ -295,7 +297,7 @@
295
297
  // time they are pubbed into the cache. After that, we can
296
298
  // trust that they aren't referenced elsewhere. (We make it
297
299
  // the programmer's responsibility to clone data if necessary
298
- // on fetch, but not when on pub.)
300
+ // on get, but not when on pub.)
299
301
  //
300
302
  // We'll optimize this once we have history. We can look at
301
303
  // the old version to see if an object/array existed already
@@ -303,7 +305,7 @@
303
305
  //
304
306
  // 2. Don't go infinitely deep.
305
307
  //
306
- // Eventually, each save/pub will be limited to the scope
308
+ // Eventually, each set/pub will be limited to the scope
307
309
  // underneath nested keyed objects. Right now I'm just
308
310
  // recursing infinitely on the whole data structure with each
309
311
  // pub.
@@ -363,7 +365,7 @@
363
365
  }
364
366
 
365
367
  function changed (object) {
366
- return pending_fetches[object.key]
368
+ return pending_gets[object.key]
367
369
  || ! cache.hasOwnProperty(object.key)
368
370
  || !backup_cache.hasOwnProperty(object.key)
369
371
  || !(deep_equals(object, backup_cache[object.key]))
@@ -374,7 +376,7 @@
374
376
  }
375
377
 
376
378
 
377
- function forget (key, save_handler, t) {
379
+ function forget (key, set_handler, t) {
378
380
  if (arguments.length === 0) {
379
381
  // Then we're forgetting the executing funk
380
382
  console.assert(executing_funk !== global_funk,
@@ -384,26 +386,26 @@
384
386
  }
385
387
  bogus_check(key)
386
388
 
387
- //log('forget:', key, funk_name(save_handler), funk_name(executing_funk))
388
- save_handler = save_handler || executing_funk
389
- var fkey = funk_key(save_handler)
390
- //console.log('Fetches in is', fetches_in.hash)
391
- if (!fetches_in.has(key, fkey)) {
389
+ //log('forget:', key, funk_name(set_handler), funk_name(executing_funk))
390
+ set_handler = set_handler || executing_funk
391
+ var fkey = funk_key(set_handler)
392
+ //console.log('Gets in is', gets_in.hash)
393
+ if (!gets_in.has(key, fkey)) {
392
394
  console.error("***\n****\nTrying to forget lost key", key,
393
- 'from', funk_name(save_handler), fkey,
394
- "that hasn't fetched that key.")
395
+ 'from', funk_name(set_handler), fkey,
396
+ "that hasn't got that key.")
395
397
  console.trace()
396
398
  return
397
399
  // throw Error('asdfalsdkfajsdf')
398
400
  }
399
401
 
400
- fetches_in.delete(key, fkey)
401
- unbind(key, 'on_save', save_handler)
402
+ gets_in.delete(key, fkey)
403
+ unbind(key, 'on_set', set_handler)
402
404
 
403
405
  // If this is the last handler listening to this key, then we can
404
406
  // delete the cache entry, send a forget upstream, and de-activate the
405
- // .on_fetch handler.
406
- if (!fetches_in.has_any(key)) {
407
+ // .on_get handler.
408
+ if (!gets_in.has_any(key)) {
407
409
  clearTimeout(to_be_forgotten[key])
408
410
  to_be_forgotten[key] = setTimeout(function () {
409
411
  // Send a forget upstream
@@ -411,7 +413,7 @@
411
413
 
412
414
  // Delete the cache entry...?
413
415
  // delete cache[key]
414
- delete fetches_out[key]
416
+ delete gets_out[key]
415
417
  delete to_be_forgotten[key]
416
418
  }, 200)
417
419
  }
@@ -443,7 +445,7 @@
443
445
  // etc.
444
446
  // - NOTE: I did a crappy implementation of abort just now above!
445
447
  // But it doesn't work if called after the to_delete handler returns.
446
- // - Generalize the code across save and del with a "mutate"
448
+ // - Generalize the code across set and del with a "mutate"
447
449
  // operation
448
450
  //
449
451
  // - Right now we fire the to_delete handlers right here.
@@ -458,18 +460,18 @@
458
460
  }
459
461
 
460
462
  var changed_keys = new Set()
461
- var dirty_fetchers = {} // Maps funk_key => version dirtied at
463
+ var dirty_getters = {} // Maps funk_key => version dirtied at
462
464
  function dirty (key, t) {
463
465
  statelog(key, brown, '*', bus + ".dirty('"+key+"')")
464
466
  bogus_check(key)
465
467
 
466
468
  var version = (t && t.version) || 'dirty-' + new_version()
467
469
 
468
- // Find any .to_fetch, and mark as dirty so that it re-runs
470
+ // Find any .to_get, and mark as dirty so that it re-runs
469
471
  var found = false
470
- if (fetches_out.hasOwnProperty(key))
471
- for (var i=0; i<fetches_out[key].length; i++) {
472
- dirty_fetchers[funk_key(fetches_out[key][i])] = version
472
+ if (gets_out.hasOwnProperty(key))
473
+ for (var i=0; i<gets_out[key].length; i++) {
474
+ dirty_getters[funk_key(gets_out[key][i])] = version
473
475
  found = true
474
476
  }
475
477
  clean_timer = clean_timer || setTimeout(clean)
@@ -486,7 +488,7 @@
486
488
  }
487
489
 
488
490
  function clean () {
489
- // 1. Collect all functions for all keys and dirtied fetchers
491
+ // 1. Collect all functions for all keys and dirtied getters
490
492
  var dirty_funks = {}
491
493
  for (var b in busses) {
492
494
  var fs = busses[b].rerunnable_funks()
@@ -495,7 +497,7 @@
495
497
  }
496
498
  clean_timer = null
497
499
 
498
- // 2. Run any priority function first (e.g. file_store's on_save)
500
+ // 2. Run any priority function first (e.g. file_store's on_set)
499
501
  log(bus.label, 'Cleaning up', Object.keys(dirty_funks).length, 'funks')
500
502
  for (var k in dirty_funks) {
501
503
  var funk = funks[k],
@@ -535,19 +537,19 @@
535
537
  var result = []
536
538
  var keys = changed_keys.values()
537
539
 
538
- //log(bus+' Cleaning up!', keys, 'keys, and', fetchers.length, 'fetchers')
540
+ //log(bus+' Cleaning up!', keys, 'keys, and', getters.length, 'getters')
539
541
  for (var i=0; i<keys.length; i++) { // Collect all keys
540
542
  // if (to_be_forgotten[keys[i]])
541
543
  // // Ignore changes to keys that have been forgotten, but not
542
544
  // // processed yet
543
545
  // continue
544
- var fs = bindings(keys[i], 'on_save')
546
+ var fs = bindings(keys[i], 'on_set')
545
547
  for (var j=0; j<fs.length; j++) {
546
548
  var f = fs[j].func
547
549
  if (f.react) {
548
550
  // Skip if it's already up to date
549
- var v = f.fetched_keys[JSON.stringify([this.id, keys[i]])]
550
- //log('re-run:', keys[i], f.statebus_id, f.fetched_keys)
551
+ var v = f.getted_keys[JSON.stringify([this.id, keys[i]])]
552
+ //log('re-run:', keys[i], f.statebus_id, f.getted_keys)
551
553
  if (v && v.indexOf(versions[keys[i]]) !== -1) {
552
554
  log('skipping', funk_name(f), 'already at version', versions[keys[i]], 'proof:', v)
553
555
  continue
@@ -564,19 +566,19 @@
564
566
  continue
565
567
  }
566
568
  autodetect_args(f)
567
- f = run_handler(f, 'on_save', cache[keys[i]], {dont_run: true,
568
- binding: keys[i]})
569
+ f = run_handler(f, 'on_set', cache[keys[i]], {dont_run: true,
570
+ binding: keys[i]})
569
571
  }
570
572
  result.push({funk_key: funk_key(f),
571
573
  at_version: versions[keys[i]]})
572
574
  }
573
575
  }
574
- for (var k in dirty_fetchers) // Collect all fetchers
576
+ for (var k in dirty_getters) // Collect all getters
575
577
  result.push({funk_key: k,
576
- at_version: dirty_fetchers[k]})
578
+ at_version: dirty_getters[k]})
577
579
 
578
580
  changed_keys.clear()
579
- dirty_fetchers = {}
581
+ dirty_getters = {}
580
582
 
581
583
  //log('found', result.length, 'funks to re run')
582
584
 
@@ -585,28 +587,43 @@
585
587
 
586
588
  // ****************
587
589
  // Connections
588
- function subspace (key) {
589
- var result = {}
590
- for (var method in {to_fetch:null, to_save:null, on_save:null, on_set_sync:null,
591
- on_delete:null, to_delete:null, to_forget:null})
592
- (function (method) {
593
- Object.defineProperty(result, method, {
594
- set: function (func) {
595
- autodetect_args(func)
596
- func.defined = func.defined || []
597
- func.defined.push(
598
- {as:'handler', bus:bus, method:method, key:key})
599
- bind(key, method, func, 'allow_wildcards')
600
- },
601
- get: function () {
602
- var result = bindings(key, method)
603
- for (var i=0; i<result.length; i++) result[i] = result[i].func
604
- result.delete = function (func) { unbind (key, method, func, 'allow_wildcards') }
605
- return result
606
- }
607
- })
608
- })(method)
609
- return result
590
+ function subspace (key, params) {
591
+ var methods = {to_get:null, to_set:null, on_set:null, on_set_sync:null,
592
+ on_delete:null, to_delete:null, to_forget:null}
593
+
594
+ if (params) {
595
+ for (var method in params) {
596
+ console.assert(method in methods)
597
+ var func = params[method]
598
+ autodetect_args(func)
599
+ func.defined = func.defined || []
600
+ func.defined.push({bus, method, key, as: 'handler'})
601
+ func.use_linked_json = true
602
+ bind(key, method, func, 'allow_wildcards')
603
+ }
604
+ }
605
+ else {
606
+ var result = {}
607
+ for (var method in methods)
608
+ (function (method) {
609
+ Object.defineProperty(result, method, {
610
+ set: function (func) {
611
+ autodetect_args(func)
612
+ func.defined = func.defined || []
613
+ func.defined.push(
614
+ {as:'handler', bus:bus, method:method, key:key})
615
+ bind(key, method, func, 'allow_wildcards')
616
+ },
617
+ get: function () {
618
+ var result = bindings(key, method)
619
+ for (var i=0; i<result.length; i++) result[i] = result[i].func
620
+ result.delete = function (func) { unbind (key, method, func, 'allow_wildcards') }
621
+ return result
622
+ }
623
+ })
624
+ })(method)
625
+ return result
626
+ }
610
627
  }
611
628
 
612
629
  function autodetect_args (handler) {
@@ -630,6 +647,7 @@
630
647
  case 'star':
631
648
  case 'rest':
632
649
  handler.args['rest'] = i; break
650
+ case 'cb':
633
651
  case 't':
634
652
  case 'transaction':
635
653
  handler.args['t'] = i; break
@@ -644,7 +662,7 @@
644
662
  }
645
663
  }
646
664
 
647
- // The funks attached to each key, maps e.g. 'fetch /point/3' to '/30'
665
+ // The funks attached to each key, maps e.g. 'get /point/3' to '/30'
648
666
  var handlers = new One_To_Many()
649
667
  var wildcard_handlers = [] // An array of {prefix, method, funk}
650
668
 
@@ -659,7 +677,7 @@
659
677
  else
660
678
  handlers.add(method + ' ' + key, funk_key(func))
661
679
 
662
- // Now check if the method is a fetch and there's a fetched
680
+ // Now check if the method is a get and there's a getted
663
681
  // key in this space, and if so call the handler.
664
682
  }
665
683
  function unbind (key, method, funk, allow_wildcards) {
@@ -726,9 +744,9 @@
726
744
  just_make_it = options.dont_run,
727
745
  binding = options.binding
728
746
 
729
- // When we first run a handler (e.g. a fetch or save), we wrap it in a
730
- // reactive() funk that calls it with its arg. Then if it fetches or
731
- // saves, it'll register a .on_save handler with this funk.
747
+ // When we first run a handler (e.g. a get or set), we wrap it in a
748
+ // reactive() funk that calls it with its arg. Then if it gets or
749
+ // sets, it'll register a .on_set handler with this funk.
732
750
 
733
751
  // Is it reactive already? Let's distinguish it.
734
752
  var funk = funck.react && funck, // Funky! So reactive!
@@ -738,7 +756,7 @@
738
756
 
739
757
  if (false && !funck.global_funk) {
740
758
  // \u26A1
741
- var event = {'to_save':'save','on_save':'save.fire','to_fetch':'fetch',
759
+ var event = {'to_set':'set','on_set':'set.fire','to_get':'get',
742
760
  'to_delete':'delete','to_forget':'forget'}[method],
743
761
  triggering = funk ? 're-running' : 'initiating'
744
762
  console.log(' > a', bus+'.'+event + "('" + (arg.key||arg) + "') is " + triggering
@@ -746,43 +764,50 @@
746
764
  }
747
765
 
748
766
  if (funk) {
749
- // Then this is an on_save event re-triggering an already-wrapped
767
+ // Then this is an on_set event re-triggering an already-wrapped
750
768
  // funk. It has its own arg internally that it's calling itself
751
769
  // with. Let's tell it to re-trigger itself with that arg.
752
770
 
753
- if (method !== 'on_save') {
754
- console.error(method === 'on_save', 'Funk is being re-triggered, but isn\'t on_save. It is: "' + method + '", oh and funk: ' + funk_name(funk))
771
+ if (method !== 'on_set') {
772
+ console.error(method === 'on_set', 'Funk is being re-triggered, but isn\'t on_set. It is: "' + method + '", oh and funk: ' + funk_name(funk))
755
773
  return
756
774
  }
757
775
  return funk.react()
758
776
 
759
777
  // Hmm... does this do the right thing? Example:
760
778
  //
761
- // bus('foo').on_save = function (o) {...}
762
- // save({key: 'foo'})
763
- // save({key: 'foo'})
764
- // save({key: 'foo'})
779
+ // bus('foo').on_set = function (o) {...}
780
+ // set({key: 'foo'})
781
+ // set({key: 'foo'})
782
+ // set({key: 'foo'})
765
783
  //
766
784
  // Does this spin up 3 reactive functions? Hmm...
767
785
  // Well, I think it does, but they all get forgotten once
768
786
  // they run once, and then are garbage collected.
769
787
  //
770
- // bus('foo*').on_save = function (o) {...}
771
- // save({key: 'foo1'})
772
- // save({key: 'foo2'})
773
- // save({key: 'foo1'})
774
- // save({key: 'foo3'})
788
+ // bus('foo*').on_set = function (o) {...}
789
+ // set({key: 'foo1'})
790
+ // set({key: 'foo2'})
791
+ // set({key: 'foo1'})
792
+ // set({key: 'foo3'})
775
793
  //
776
794
  // Does this work ok? Yeah, I think so.
777
795
  }
778
796
 
779
797
  // Alright then. Let's wrap this func with some funk.
780
798
 
781
- // Fresh fetch/save/forget/delete handlers will just be regular
799
+ // Fresh get/set/forget/delete handlers will just be regular
782
800
  // functions. We'll store their arg and transaction and let them
783
801
  // re-run until they are done re-running.
784
802
  function key_arg () { return ((typeof arg.key) == 'string') ? arg.key : arg }
785
803
  function rest_arg () { return (key_arg()).substr(binding.length-1) }
804
+ function val_arg () {
805
+ console.assert(method === 'to_set' || method === 'on_set' || method === 'on_set_sync')
806
+ // Is there a time I am supposed to return bus.cache[arg]? It used to say:
807
+ // arg.key ? arg : bus.cache[arg]
808
+
809
+ return arg.key ? (func.use_linked_json ? arg.val : arg) : undefined
810
+ }
786
811
  function vars_arg () {
787
812
  var r = rest_arg()
788
813
  try {
@@ -792,49 +817,50 @@
792
817
  }
793
818
  }
794
819
  var f = reactive(function () {
795
-
796
820
  // Initialize transaction
797
821
  t = clone(t || {})
798
822
 
799
823
  // Add .abort() method
800
- if (method === 'to_save' || method === 'to_delete')
824
+ if (method === 'to_set' || method === 'to_delete')
801
825
  t.abort = function () {
802
- var key = method === 'to_save' ? arg.key : arg
826
+ var key = method === 'to_set' ? arg.key : arg
803
827
  if (f.loading()) return
804
828
  bus.cache[key] = bus.cache[key] || {key: key}
805
829
  bus.backup_cache[key] = bus.backup_cache[key] || {key: key}
806
- bus.save.abort(bus.cache[key])
830
+ bus.set.abort(bus.cache[key])
807
831
  }
808
832
 
809
833
  // Add .done() method
810
834
  if (method !== 'to_forget')
811
835
  t.done = function (o) {
812
- var key = method === 'to_save' ? arg.key : arg
836
+ var key = method === 'to_set' ? arg.key : arg
837
+ if (func.use_linked_json)
838
+ o = {key, val: o}
813
839
  bus.log('We are DONE()ing', method, key, o||arg)
814
840
 
815
841
  // We use a simple (and crappy?) heuristic to know if the
816
- // to_save handler has changed the state: whether the
842
+ // to_set handler has changed the state: whether the
817
843
  // programmer passed (o) to the t.done(o) handler. If
818
844
  // not, we assume it hasn't changed. If so, we assume it
819
845
  // *has* changed, and thus we change the version of the
820
846
  // state. I imagine it would be more accurate to diff
821
- // from before the to_save handler began with when
847
+ // from before the to_set handler began with when
822
848
  // t.done(o) ran.
823
849
  //
824
850
  // Note: We will likely solve this in the future by
825
- // preventing .to_save() from changing the incoming state,
851
+ // preventing .to_set() from changing the incoming state,
826
852
  // except through an explicit .revise() function.
827
853
  if (o) t.version = new_version()
828
854
 
829
855
  if (method === 'to_delete')
830
856
  delete bus.cache[key]
831
- else if (method === 'to_save') {
832
- bus.save.fire(o || arg, t)
857
+ else if (method === 'to_set') {
858
+ bus.set.fire(o || arg, t)
833
859
  bus.route(key, 'on_set_sync', o || arg, t)
834
860
  } else {
835
- // Now method === 'to_fetch'
861
+ // Now method === 'to_get'
836
862
  o.key = key
837
- bus.save.fire(o, t)
863
+ bus.set.fire(o, t)
838
864
  // And now reset the version cause it could get called again
839
865
  delete t.version
840
866
  }
@@ -843,14 +869,14 @@
843
869
  // Alias .return() to .done(), in case that feels better to you
844
870
  t.return = t.done
845
871
 
846
- // Alias t.refetch() to bus.dirty()
847
- if (method === 'to_save')
848
- t.refetch = function () { bus.dirty(arg.key) }
872
+ // Alias t.reget() to bus.dirty()
873
+ if (method === 'to_set')
874
+ t.reget = function () { bus.dirty(arg.key) }
849
875
 
850
876
  // Now to call the handler, let's line up the function's special
851
877
  // named arguemnts like key, o, t, rest, vars, etc.
852
878
  var args = []
853
- args[0] = arg
879
+ args[0] = (method in {to_set:1, on_set:1, on_set_sync:1}) ? val_arg() : arg
854
880
  args[1] = t
855
881
  for (var k in (func.args||{})) {
856
882
  switch (k) {
@@ -864,7 +890,7 @@
864
890
  case 't':
865
891
  args[func.args[k]] = t; break
866
892
  case 'obj':
867
- args[func.args[k]] = arg.key ? arg : bus.cache[arg]; break
893
+ args[func.args[k]] = val_arg(); break
868
894
  case 'old':
869
895
  var key = key_arg()
870
896
  args[func.args[k]] = bus.cache[key] || (bus.cache[key] = {key:key})
@@ -881,35 +907,45 @@
881
907
  // arr[func.args[k]] = <compute_blah(k)>
882
908
 
883
909
  // Trigger done() or abort() by return value
884
- console.assert(!(result === 'to_fetch' &&
910
+ console.assert(!(result === 'to_get' &&
885
911
  (result === 'done' || result === 'abort')),
886
- 'Returning "done" or "abort" is not allowed from to_fetch handlers')
912
+ 'Returning "done" or "abort" is not allowed from to_get handlers')
887
913
  if (result === 'done') t.done()
888
914
  if (result === 'abort') t.abort()
889
915
 
890
- // For fetch
891
- if (method === 'to_fetch' && result instanceof Object
892
- && !f.loading() // Experimental.
893
- ) {
894
- result.key = arg
895
- var new_t = clone(t || {})
896
- new_t.to_fetch = true
897
- save.fire(result, new_t)
898
- return result
916
+ // For get
917
+ if (func.use_linked_json) {
918
+ if (method === 'to_get' && result !== undefined && !f.loading()) {
919
+ var obj = {key: arg, val: result}
920
+ var new_t = clone(t || {})
921
+ new_t.to_get = true
922
+ set.fire(obj, new_t)
923
+ return result
924
+ }
925
+ } else {
926
+ if (method === 'to_get' && result instanceof Object
927
+ && !f.loading() // Experimental.
928
+ ) {
929
+ result.key = arg
930
+ var new_t = clone(t || {})
931
+ new_t.to_get = true
932
+ set.fire(result, new_t)
933
+ return result
934
+ }
899
935
  }
900
936
 
901
- // Save, forget and delete handlers stop re-running once they've
937
+ // Set, forget and delete handlers stop re-running once they've
902
938
  // completed without anything loading.
903
939
  // ... with f.forget()
904
- if (method !== 'to_fetch' && !f.loading())
940
+ if (method !== 'to_get' && !f.loading())
905
941
  f.forget()
906
942
  })
907
943
  f.proxies_for = func
908
944
  f.arg = arg
909
945
  f.transaction = t || {}
910
946
 
911
- // to_fetch handlers stop re-running when the key is forgotten
912
- if (method === 'to_fetch') {
947
+ // to_get handlers stop re-running when the key is forgotten
948
+ if (method === 'to_get') {
913
949
  var key = arg
914
950
  function handler_done () {
915
951
  f.forget()
@@ -918,13 +954,13 @@
918
954
  bind(key, 'to_forget', handler_done)
919
955
 
920
956
  // // Check if it's doubled-up
921
- // if (fetches_out[key])
922
- // console.error('Two .to_fetch functions are running on the same key',
923
- // key+'!', funk_name(funck), funk_name(fetches_out[key]))
957
+ // if (gets_out[key])
958
+ // console.error('Two .to_get functions are running on the same key',
959
+ // key+'!', funk_name(funck), funk_name(gets_out[key]))
924
960
 
925
- fetches_out[key] = fetches_out[key] || []
926
- fetches_out[key].push(f) // Record active to_fetch handler
927
- pending_fetches[key] = f // Record that the fetch is pending
961
+ gets_out[key] = gets_out[key] || []
962
+ gets_out[key].push(f) // Record active to_get handler
963
+ pending_gets[key] = f // Record that the get is pending
928
964
  }
929
965
 
930
966
  if (just_make_it)
@@ -943,9 +979,9 @@
943
979
  for (var i=0; i<handlers.length; i++)
944
980
  bus.run_handler(handlers[i].func, method, arg, {t: t, binding: handlers[i].key})
945
981
 
946
- // if (method === 'to_fetch')
982
+ // if (method === 'to_get')
947
983
  // console.assert(handlers.length<2,
948
- // 'Two to_fetch functions are registered for the same key '+key,
984
+ // 'Two to_get functions are registered for the same key '+key,
949
985
  // handlers)
950
986
  return handlers.length
951
987
  }
@@ -955,7 +991,7 @@
955
991
  // Reactive functions
956
992
  //
957
993
  // We wrap any function with a reactive wrapper that re-calls it whenever
958
- // state it's fetched changes.
994
+ // state it's got changes.
959
995
 
960
996
  if (!global_funk) {
961
997
  global_funk = reactive(function global_funk () {})
@@ -970,7 +1006,7 @@
970
1006
  // f = reactive(func)
971
1007
  // f(arg1, arg2)
972
1008
  //
973
- // This will remember every fetch it depends on, and make it re-call
1009
+ // This will remember every get it depends on, and make it re-call
974
1010
  // itself whenever that state changes. It will remember arg1 and arg2
975
1011
  // and use those again. You can also trigger a re-action manually
976
1012
  // with:
@@ -1029,14 +1065,14 @@
1029
1065
 
1030
1066
  funk.func = func // just for debugging
1031
1067
  funk.called_directly = true
1032
- funk.fetched_keys = {} // maps [bus,key] to version
1068
+ funk.getted_keys = {} // maps [bus,key] to version
1033
1069
  // version will be undefined until loaded
1034
1070
  funk.abortable_keys = []
1035
1071
  funk.has_seen = function (bus, key, version) {
1036
1072
  //console.log('depend:', bus, key, versions[key])
1037
1073
  var bus_key = JSON.stringify([bus.id, key])
1038
1074
  var seen_versions =
1039
- this.fetched_keys[bus_key] = this.fetched_keys[bus_key] || []
1075
+ this.getted_keys[bus_key] = this.getted_keys[bus_key] || []
1040
1076
  seen_versions.push(version)
1041
1077
  if (seen_versions.length > 50) seen_versions.shift()
1042
1078
  }
@@ -1051,29 +1087,29 @@
1051
1087
  return result
1052
1088
  }
1053
1089
  funk.forget = function () {
1054
- // Todo: This will bug out if an .on_save handler for a key also
1055
- // fetches that key once, and then doesn't fetch it again, because
1056
- // when it fetches the key, that key will end up being a
1057
- // fetched_key, and will then be forgotten as soon as the funk is
1058
- // re-run, and doesn't fetch it again, and the fact that it is
1059
- // defined as an .on_save .on_save handler won't matter anymore.
1090
+ // Todo: This will bug out if an .on_set handler for a key also
1091
+ // gets that key once, and then doesn't get it again, because
1092
+ // when it gets the key, that key will end up being a
1093
+ // getted_key, and will then be forgotten as soon as the funk is
1094
+ // re-run, and doesn't get it again, and the fact that it is
1095
+ // defined as an .on_set .on_set handler won't matter anymore.
1060
1096
 
1061
1097
  if (funk.statebus_id === 'global funk') return
1062
1098
 
1063
- for (var hash in funk.fetched_keys) {
1099
+ for (var hash in funk.getted_keys) {
1064
1100
  var tmp = JSON.parse(hash),
1065
1101
  bus = busses[tmp[0]], key = tmp[1]
1066
1102
  if (bus) // Cause it might have been deleted
1067
1103
  bus.forget(key, funk)
1068
1104
  }
1069
- funk.fetched_keys = {}
1105
+ funk.getted_keys = {}
1070
1106
  }
1071
1107
  funk.loading = function () {
1072
- for (var hash in funk.fetched_keys) {
1108
+ for (var hash in funk.getted_keys) {
1073
1109
  var tmp = JSON.parse(hash),
1074
1110
  bus = busses[tmp[0]], key = tmp[1]
1075
1111
  if (bus // Cause it might have been deleted
1076
- && bus.pending_fetches[key])
1112
+ && bus.pending_gets[key])
1077
1113
  return true
1078
1114
  }
1079
1115
  return false
@@ -1087,9 +1123,9 @@
1087
1123
 
1088
1124
  function loading_keys (keys) {
1089
1125
  // Do any of these keys have outstanding gets?
1090
- //console.log('Loading: pending_keys is', pending_fetches)
1126
+ //console.log('Loading: pending_keys is', pending_gets)
1091
1127
  for (var i=0; i<keys.length; i++)
1092
- if (pending_fetches[keys[i]]) return true
1128
+ if (pending_gets[keys[i]]) return true
1093
1129
  return false
1094
1130
  }
1095
1131
 
@@ -1123,7 +1159,8 @@
1123
1159
  var red = '', normal = '', grey = '',
1124
1160
  green = '', brown = ''
1125
1161
  function add_diff_msg (message, obj) {
1126
- var diff = sorta_diff(backup_cache[obj.key], obj)
1162
+ var diff = sorta_diff(backup_cache[obj.key] && backup_cache[obj.key].val,
1163
+ obj && obj.val)
1127
1164
  if (diff) {
1128
1165
  var end_col = message.length + 2 + statelog_indent * 3
1129
1166
  for (var i=0; i<40-end_col; i++) message += ' '
@@ -1132,7 +1169,7 @@
1132
1169
  else message += ' <no diff>'
1133
1170
  return message
1134
1171
  }
1135
- function save_msg (obj, t, meth) {
1172
+ function set_msg (obj, t, meth) {
1136
1173
  if (!honking_at(obj.key)) return
1137
1174
  var message = (t && t.m) || bus + "."+meth+"('"+obj.key+"')"
1138
1175
  message = add_diff_msg(message, obj)
@@ -1150,14 +1187,14 @@
1150
1187
  if (!name) throw 'Uncallback function needs a name'
1151
1188
  var watching = {}
1152
1189
  var prefix = 'uncallback/' + name
1153
- bus(prefix + '/*').to_fetch = function (key, json) {
1190
+ bus(prefix + '/*').to_get = function (key, json) {
1154
1191
  var args = json
1155
1192
  function cb (err, result) {
1156
1193
  if (err) {
1157
1194
  console.trace('have err:', err, 'and result is', JSON.stringify(result))
1158
1195
  throw err
1159
1196
  } else
1160
- bus.save.fire({key: key, _: result})
1197
+ bus.set.fire({key: key, _: result})
1161
1198
  }
1162
1199
 
1163
1200
  // Inject the callback into the right place
@@ -1184,7 +1221,7 @@
1184
1221
  }
1185
1222
  return function () {
1186
1223
  var args = [].slice.call(arguments)
1187
- return bus.fetch(prefix + '/' + JSON.stringify(args))._
1224
+ return bus.get(prefix + '/' + JSON.stringify(args))._
1188
1225
  }
1189
1226
  }
1190
1227
 
@@ -1198,392 +1235,31 @@
1198
1235
  }
1199
1236
 
1200
1237
 
1201
- // Old Proxy Prototype
1202
- if (true) {
1203
- var sb = (function sb () {
1204
- // I have the cache behind the scenes
1205
- // Each proxy has a target object -- the raw data on cache
1206
- // If we're proxying a {_: ...} singleton then ...
1207
-
1208
- function item_proxy (base, o) {
1209
- if (typeof o === 'number'
1210
- || typeof o === 'string'
1211
- || typeof o === 'boolean'
1212
- || o === undefined
1213
- || o === null
1214
- || typeof o === 'function') return o
1215
-
1216
- return new Proxy(o, {
1217
- get: function get(o, k) {
1218
- if (k === 'inspect' || k === 'valueOf' || typeof k === 'symbol')
1219
- return undefined
1220
- k = escape_keys(k)
1221
- return item_proxy(base, o[k])
1222
- },
1223
- set: function set(o, k, v) {
1224
- var result = o[escape_keys(k)] = v
1225
- bus.save(base)
1226
- return result
1227
- },
1228
- has: function has(o, k) {
1229
- return o.hasOwnProperty(escape_keys(k))
1230
- },
1231
- deleteProperty: function del (o, k) {
1232
- delete o[escape_keys(k)]
1233
- },
1234
- apply: function apply (o, This, args) {
1235
- return o
1236
- }
1237
- })}
1238
-
1239
- return new Proxy(cache, {
1240
- get: function get(o, k) {
1241
- if (k in bogus_keys) return o[k]
1242
- if (k === 'inspect' || k === 'valueOf' || typeof k === 'symbol')
1243
- return undefined
1244
- var raw = bus.fetch(k),
1245
- obj = raw
1246
- while (typeof obj == 'object' && '_' in obj) obj = obj._
1247
- return item_proxy(raw, obj)
1248
- },
1249
- set: function set(o, k, v) {
1250
- if (typeof v === 'number'
1251
- || typeof v === 'string'
1252
- || typeof v === 'boolean'
1253
- || v === undefined
1254
- || v === null
1255
- || typeof v === 'function'
1256
- || Array.isArray(v))
1257
- v = {_:v}
1258
- else
1259
- v = bus.clone(v)
1260
- v.key = k
1261
- bus.save(v)
1262
- },
1263
- // In future, this might check if there's a .to_fetch function OR
1264
- // something in the cache:
1265
- //
1266
- // has: function has(o, k) {
1267
- // return k in o
1268
- // },
1269
- // ... but I haven't had a need yet.
1270
- deleteProperty: function del (o, k) {
1271
- bus.delete(escape_keys(k))
1272
- }
1273
- })
1274
- })()
1275
-
1276
-
1277
- // ******** State (Proxy) API *********
1278
- //
1279
- // The top-level state[..] object translates pointers of the
1280
- // special form:
1281
- //
1282
- // {key: <s>, _: *}
1283
- //
1284
- // Examples:
1285
- //
1286
- // state['uninitialized']
1287
- // >> undefined
1288
- //
1289
- // state['uninitialized'] = {}
1290
- // >> {key: 'uninitialized'}
1291
- //
1292
- // state['uninitialized'] = {a: 3}
1293
- // >> {key: 'uninitialized', a: 3}
1294
- //
1295
- // state['uninitialized'] = []
1296
- // >> {key: 'uninitialized', _: []}
1297
- //
1298
- // delete state['uninitialized']
1299
- // state['uninitialized']
1300
- // >> undefined
1301
- //
1302
- // ** Rules
1303
- // Setting:
1304
- // - Escape-translate each field recursively
1305
- // - If setting an object, put each field directly on it
1306
- // - If setting anything else, put it into ._
1307
- //
1308
- // Getting:
1309
- // - If it has unescaped fields other than ._, return object with them
1310
- // - Otherwise, return ._
1311
- // - Unescape all fields
1312
-
1313
- var strict_mode = (function () {return !this})()
1314
- function pget (base, o, k) {
1315
- // console.log('pget:', {base, o, k})
1316
-
1317
- if (base) {
1318
- o = o[k]
1319
-
1320
- // If new base, update and subscribe
1321
- if (typeof o == 'object' && 'key' in o) {
1322
- base = o
1323
- bus.fetch(o.key)
1324
- }
1325
- } else {
1326
- // We are getting from the Root
1327
- o = bus.fetch(k)
1328
- // console.log('pget: fetched', k, 'and got', o)
1329
- base = o
1330
- if (bus.validate(o, {key: '*', '?_': '*'})) {
1331
- // console.log('pget: jumping into the _')
1332
- o = o._
1333
- }
1334
- if (typeof o === 'object' && o.key)
1335
- base = o
1336
- }
1337
-
1338
- // Follow symlinks
1339
- if (typeof o == 'object' && 'key' in o && '_' in o) {
1340
- // Note: I don't actually need this recursion here, because
1341
- // recursively linked state cannot be created by the proxy API.
1342
- // So it can be undefined behavior.
1343
- var tmp = pget(base, o, '_')
1344
- base = tmp[0]
1345
- o = tmp[1]
1346
- }
1347
-
1348
- return [base, o]
1349
- }
1350
-
1351
- function proxy_encode_val (x) {
1352
- // Arrays
1353
- if (Array.isArray(x)) {
1354
- var result = []
1355
- for (var i=0; i < x.length; i++)
1356
- result[i] = proxy_encode_val(x[i])
1357
- return result
1358
- }
1359
-
1360
- // Objects
1361
- else if (typeof x === 'object') {
1362
- // Actual objects need their keys translated
1363
- var result = {}
1364
- for (var k in x)
1365
- result[escape_keys(k)] = proxy_encode_val(x[k])
1366
- return result
1367
- }
1368
-
1369
- // Proxieds: already have JSON, stored inside. Return it.
1370
- else if (typeof x === 'function' && x[symbols.is_proxy]) {
1371
- return x()
1372
- }
1373
-
1374
- // Everything else return
1375
- return x
1376
- }
1377
- function proxy_decode_json (json) {
1378
- // Returns data for proxies
1379
- // - Remove keys
1380
- // - Translate
1381
-
1382
- // Root objects of special form
1383
- if (bus.validate(json, {key: '*', '_': '*'}))
1384
- return proxy_decode_json(json._)
1385
-
1386
- // Arrays
1387
- if (Array.isArray(json)) {
1388
- var arr = json.slice()
1389
- for (var i=0; i<arr.length; i++)
1390
- arr[i] = proxy_decode_json(arr[i])
1391
- return arr
1392
- }
1393
-
1394
- // Objects
1395
- if (typeof json === 'object' && json !== null) {
1396
- var obj = {}
1397
- for (var k in json)
1398
- if (k !== 'key')
1399
- obj[unescape_keys(k)] = proxy_decode_json(json[k])
1400
- return obj
1401
- }
1402
-
1403
- // Other primitives just return
1404
- return json
1405
- }
1406
-
1407
- if (nodejs) var util = require('util')
1408
- function make_proxy (base, o) {
1409
- if (!symbols)
1410
- symbols = {is_proxy: Symbol('is_proxy'),
1411
- get_json: Symbol('get_json'),
1412
- get_base: Symbol('get_base')}
1413
-
1414
- if (typeof o !== 'object' || o === null) return o
1415
-
1416
- function get_json() {
1417
- // Pop up to parent if this is a singleton array.
1418
- // We know it's a singleton array if base._ === x(), and base is
1419
- // of the form {key: *, _: x}
1420
- if (base && base._ && Object.keys(base).length === 2
1421
- && base._ === o)
1422
- return base
1423
-
1424
- // Otherwise return x's JSON.
1425
- return o
1426
- }
1427
-
1428
- // Javascript won't let us function call a proxy unless the "target"
1429
- // is a function. So we make a dummy target, and don't use it.
1430
- var dummy_obj = function () {}
1431
- return new Proxy(dummy_obj, {
1432
- get: function (dummy_obj, k) {
1433
- // console.log('get:', k, '::'+typeof k, 'on', o)
1434
-
1435
- // Print something nice for Node console inspector
1436
- if (nodejs && k === util.inspect.custom) {
1437
- if (o == bus.cache)
1438
- return function () {return 'state'+bus.toString().substr(3)}
1439
- return function () {return 'p: '+util.format(proxy_decode_json(o))}
1440
- }
1441
- if (k in bogus_keys) return o[k]
1442
- // Proxies distinguish themselves via proxy.is_proxy == true
1443
- if (k === symbols.is_proxy) return true
1444
- if (k === symbols.get_json) return get_json()
1445
- if (k === symbols.get_base) return base
1446
- if (k === Symbol.isConcatSpreadable) return Array.isArray(o)
1447
- if (k === Symbol.toPrimitive) return function () {
1448
- return JSON.stringify(proxy_decode_json(o))
1449
- }
1450
- if (typeof k === 'symbol') {
1451
- console.warn('Got request for weird symbol', k)
1452
- return undefined
1453
- }
1454
-
1455
- var tmp2 = pget(base, o, escape_keys(k))
1456
- var base2 = tmp2[0]
1457
- var o2 = tmp2[1]
1458
-
1459
- // console.log('returning proxy on', base2, o2)
1460
- return make_proxy(base2, o2)
1461
- },
1462
- set: function (dummy_obj, k, v) {
1463
- // console.log('set:', {base, o, k, v})
1464
-
1465
- if (base) {
1466
- var encoded_v = o[escape_keys(k)] = proxy_encode_val(v)
1467
- // console.log(' set: saving', encoded_v, 'into', base)
1468
-
1469
- // Collapse state of the form:
1470
- // {key: '*', _: {foo: bar, ...}}
1471
- // down to:
1472
- // {key: '*', foo: bar}
1473
- if (base._
1474
- && Object.keys(base).length === 2
1475
- && typeof base._ === 'object'
1476
- && base._ !== null
1477
- && !Array.isArray(base._)
1478
- && !base._.key
1479
- && Object.keys(base._).length !== 0) {
1480
- // console.log('Collapsing', JSON.stringify(base))
1481
- for (var k2 in base._)
1482
- base[k2] = base._[k2]
1483
- delete base._
1484
- }
1485
-
1486
- bus.save(base)
1487
- }
1488
-
1489
- // Saving into top-level state
1490
- else {
1491
- var encoded_v = proxy_encode_val(v)
1492
- // console.log(' set top-level:', {v, encoded_v})
1493
-
1494
- // Setting a top-level object to undefined wipes it out
1495
- if (v === undefined)
1496
- encoded_v = {key: k}
1497
-
1498
- // Prefix with _: anything that is:
1499
- else if (// A proxy to another state
1500
- (typeof v === 'object' && v[symbols.is_proxy])
1501
- // An empty {} object
1502
- || (typeof v === 'object' && Object.keys(v).length === 0)
1503
- // A number, bool, string, function, etc
1504
- || typeof v !== 'object' || v === null
1505
- // An array
1506
- || Array.isArray(v))
1507
- encoded_v = {_: encoded_v}
1508
- encoded_v.key = k
1509
-
1510
- // console.log(' set top-level: now encoded_v is', encoded_v)
1511
- bus.save(encoded_v)
1512
- }
1238
+ // ******************
1239
+ // Proxy
1513
1240
 
1514
- var newbase = (encoded_v && encoded_v.key) ? encoded_v : base
1515
- return true
1516
- },
1517
- has: function has(O, k) {
1518
- // XXX QUESTIONS:
1519
- //
1520
- // - Do I want this to return true if there's a .to_fetch()
1521
- // function for this o, k?
1522
- //
1523
- // - Does this need to do a fetch as well?
1524
- //
1525
- // - For a keyed object, should this do a loading() check?
1526
- return o.hasOwnProperty(escape_keys(k))
1527
- },
1528
- deleteProperty: function del (O, k) {
1529
- if (base) {
1530
- // console.log(' deleting:', escape_keys(k), 'of', o)
1531
- delete o[escape_keys(k)] // Deleting innards
1532
- if (Object.keys(o).length === 1 && o.key)
1533
- o._ = {}
1534
- bus.save(base)
1535
- }
1536
- else
1537
- bus.delete(escape_keys(k)) // Deleting top-level
1538
- },
1539
- apply: function apply (f, This, args) { return get_json() }
1540
- })
1541
- }
1542
- if (nodejs || window.Proxy)
1543
- var state = make_proxy(null, cache)
1544
-
1545
- // So chrome can print out proxy objects decently
1546
- if (!nodejs)
1547
- window.devtoolsFormatters = [{
1548
- header: function (x) {
1549
- if (x[symbols.is_proxy])
1550
- return ['span', {style: 'background-color: #feb; padding: 3px;'},
1551
- JSON.stringify(proxy_decode_json(x()))]
1552
- else if (x[symbols.is_braid_proxy])
1553
- return ['span', {style: 'background-color: #fffbe5; padding: 3px;'},
1554
- JSON.stringify(x)]
1555
- // For function proxies:
1556
- // JSON.stringify(x(), null, 2)]
1557
- },
1558
- hasBody: function (x) {return false}
1559
- }]
1241
+ var symbols = {
1242
+ is_proxy: Symbol('is_proxy'),
1243
+ is_link: Symbol('is_link'),
1244
+ get_json: Symbol('get_json'),
1245
+ get_base: Symbol('get_base')
1560
1246
  }
1561
-
1562
- // ******************
1563
- // Braid Test Mode Proxy
1564
-
1565
- var symbols = {is_braid_proxy: Symbol('is_braid_proxy'),
1566
- is_proxy: Symbol('is_proxy'),
1567
- is_link: Symbol('is_link'),
1568
- get_json: Symbol('get_json'),
1569
- get_base: Symbol('get_base')
1570
- }
1571
- function braid_proxy () {
1247
+ function make_proxy () {
1572
1248
  function item_proxy (base, o) {
1573
1249
 
1574
- // We only create a proxy for objects.
1250
+ // Primitives pass through unscathed
1575
1251
  if (typeof o === 'number'
1576
1252
  || typeof o === 'string'
1577
1253
  || typeof o === 'boolean'
1578
1254
  || o === undefined
1579
1255
  || o === null
1580
1256
  || typeof o === 'function')
1581
- // Everything else passes through unscathed
1257
+
1582
1258
  return o
1583
1259
 
1584
1260
  // We recursively descend through {key: ...} links
1585
1261
  if (typeof o === 'object' && 'key' in o) {
1586
- var new_base = bus.fetch(o.key)
1262
+ var new_base = bus.get(o.key)
1587
1263
  return item_proxy(new_base, new_base.val)
1588
1264
  }
1589
1265
 
@@ -1600,7 +1276,7 @@
1600
1276
  get: function get(o, k) {
1601
1277
  if (k === 'inspect' || k === 'valueOf')
1602
1278
  return undefined
1603
- if (k === symbols.is_braid_proxy)
1279
+ if (k === symbols.is_proxy)
1604
1280
  return true
1605
1281
  if (typeof k === 'symbol')
1606
1282
  return undefined
@@ -1609,7 +1285,7 @@
1609
1285
  set: function set(o, k, v) {
1610
1286
  var value = translate_fields(v, proxied_2_keyed)
1611
1287
  o[proxied_2_keyed(k)] = value
1612
- bus.save(base)
1288
+ bus.set(base)
1613
1289
  return true
1614
1290
  },
1615
1291
  has: function has(o, k) {
@@ -1635,11 +1311,11 @@
1635
1311
  if (k === 'inspect' || k === 'valueOf' || typeof k === 'symbol')
1636
1312
  return undefined
1637
1313
  bogus_check(k)
1638
- var base = bus.fetch(k)
1314
+ var base = bus.get(k)
1639
1315
  return item_proxy(base, base.val)
1640
1316
  },
1641
1317
  set: function set(o, key, val) {
1642
- bus.save({key: key,
1318
+ bus.set({key: key,
1643
1319
  val: translate_fields(val, proxied_2_keyed)})
1644
1320
  return true
1645
1321
  },
@@ -1652,17 +1328,27 @@
1652
1328
  // }
1653
1329
  })
1654
1330
  }
1331
+ bus.state = make_proxy()
1655
1332
 
1656
1333
  function link (url) {
1657
- var result = fetch(url)
1334
+ var result = bus.get(url)
1658
1335
  result[symbols.is_link] = true
1659
1336
  return result
1660
1337
  }
1661
1338
 
1662
- if ((nodejs && bus.options && bus.options.braid_mode)
1663
- || (!nodejs && window.Proxy && clientjs_option('braid_mode')))
1664
- state = braid_proxy()
1665
1339
 
1340
+ // So chrome can print out proxy objects decently
1341
+ if (!nodejs)
1342
+ window.devtoolsFormatters = [{
1343
+ header: function (x) {
1344
+ if (x[symbols.is_proxy])
1345
+ return ['span', {style: 'background-color: #fffbe5; padding: 3px;'},
1346
+ JSON.stringify(x)]
1347
+ // For function proxies:
1348
+ // JSON.stringify(x(), null, 2)]
1349
+ },
1350
+ hasBody: function (x) {return false}
1351
+ }]
1666
1352
 
1667
1353
  // ******************
1668
1354
  // Network client
@@ -1671,13 +1357,13 @@
1671
1357
  return m && m[0]
1672
1358
  }
1673
1359
  function message_method (m) {
1674
- return (m.fetch && 'fetch')
1675
- || (m.save && 'save')
1360
+ return (m.get && 'get')
1361
+ || (m.set && 'set')
1676
1362
  || (m['delete'] && 'delete')
1677
1363
  || (m.forget && 'forget')
1678
1364
  }
1679
1365
 
1680
- function net_mount (prefix, url, client_creds) {
1366
+ function ws_mount (prefix, url, client_creds) {
1681
1367
  // Local: state://foo.com/* or /*
1682
1368
  var preprefix = prefix.slice(0,-1)
1683
1369
  var is_absolute = /^i?statei?:\/\//
@@ -1686,7 +1372,7 @@
1686
1372
  var sock
1687
1373
  var attempts = 0
1688
1374
  var outbox = []
1689
- var client_fetched_keys = new bus.Set()
1375
+ var client_getted_keys = new bus.Set()
1690
1376
  var heartbeat
1691
1377
  if (url[url.length-1]=='/') url = url.substr(0,url.length-1)
1692
1378
  function nlog (s) {
@@ -1696,9 +1382,9 @@
1696
1382
  pushpop = pushpop || 'push'
1697
1383
  o = rem_prefixes(o)
1698
1384
  var m = message_method(o)
1699
- if (m == 'fetch' || m == 'delete' || m == 'forget')
1385
+ if (m == 'get' || m == 'delete' || m == 'forget')
1700
1386
  o[m] = rem_prefix(o[m])
1701
- bus.log('net_mount.send:', JSON.stringify(o))
1387
+ bus.log('ws_mount.send:', JSON.stringify(o))
1702
1388
  outbox[pushpop](JSON.stringify(o))
1703
1389
  flush_outbox()
1704
1390
  }
@@ -1727,19 +1413,19 @@
1727
1413
  function rem_prefixes (obj) {
1728
1414
  return bus.translate_keys(bus.clone(obj), rem_prefix) }
1729
1415
 
1730
- bus(prefix).to_save = function (obj, t) {
1731
- bus.save.fire(obj)
1732
- var x = {save: obj}
1416
+ bus(prefix).to_set = function (obj, t) {
1417
+ bus.set.fire(obj)
1418
+ var x = {set: obj}
1733
1419
  if (t.version) x.version = t.version
1734
1420
  if (t.parents) x.parents = t.parents
1735
1421
  if (t.patch) x.patch = t.patch
1736
- if (t.patch) x.save = rem_prefix(x.save.key)
1422
+ if (t.patch) x.set = rem_prefix(x.set.key)
1737
1423
  send(x)
1738
1424
  }
1739
- bus(prefix).to_fetch = function (key) { send({fetch: key}),
1740
- client_fetched_keys.add(key) }
1425
+ bus(prefix).to_get = function (key) { send({get: key}),
1426
+ client_getted_keys.add(key) }
1741
1427
  bus(prefix).to_forget = function (key) { send({forget: key}),
1742
- client_fetched_keys.delete(key) }
1428
+ client_getted_keys.delete(key) }
1743
1429
  bus(prefix).to_delete = function (key) { send({'delete': key}) }
1744
1430
 
1745
1431
  function connect () {
@@ -1749,16 +1435,16 @@
1749
1435
  nlog('[*] opened ' + url)
1750
1436
 
1751
1437
  // Update state
1752
- var peers = bus.fetch('peers')
1438
+ var peers = bus.get('peers')
1753
1439
  peers[url] = peers[url] || {}
1754
1440
  peers[url].connected = true
1755
- save(peers)
1441
+ set(peers)
1756
1442
 
1757
1443
  // Login
1758
1444
  var creds = client_creds || (bus.client_creds && bus.client_creds(url))
1759
1445
  if (creds) {
1760
1446
  var i = []
1761
- function intro (o) {i.push(JSON.stringify({save: o}))}
1447
+ function intro (o) {i.push(JSON.stringify({set: o}))}
1762
1448
  if (creds.clientid)
1763
1449
  intro({key: 'current_user', client: creds.clientid})
1764
1450
  if (creds.name && creds.pass)
@@ -1777,11 +1463,11 @@
1777
1463
 
1778
1464
  // Reconnect
1779
1465
  if (attempts > 0) {
1780
- // Then we need to refetch everything, cause it
1466
+ // Then we need to reget everything, cause it
1781
1467
  // might have changed
1782
- var keys = client_fetched_keys.values()
1468
+ var keys = client_getted_keys.values()
1783
1469
  for (var i=0; i<keys.length; i++)
1784
- send({fetch: keys[i]})
1470
+ send({get: keys[i]})
1785
1471
  }
1786
1472
 
1787
1473
  attempts = 0
@@ -1797,14 +1483,14 @@
1797
1483
  setTimeout(connect, attempts++ < 3 ? 1500 : 5000)
1798
1484
 
1799
1485
  // Update state
1800
- var peers = bus.fetch('peers')
1486
+ var peers = bus.get('peers')
1801
1487
  peers[url] = peers[url] || {}
1802
1488
  peers[url].connected = false
1803
- save(peers)
1489
+ set(peers)
1804
1490
 
1805
- // Remove all fetches and forgets from queue
1491
+ // Remove all gets and forgets from queue
1806
1492
  var new_outbox = []
1807
- var bad = {'fetch':1, 'forget':1}
1493
+ var bad = {'get':1, 'forget':1}
1808
1494
  for (var i=0; i<outbox.length; i++)
1809
1495
  if (!bad[JSON.parse(outbox[i]).method])
1810
1496
  new_outbox.push(outbox[i])
@@ -1826,18 +1512,18 @@
1826
1512
  var message = JSON.parse(event.data)
1827
1513
  var method = message_method(message)
1828
1514
 
1829
- // We only take saves from the server for now
1830
- if (method !== 'save' && method !== 'pong') throw 'barf'
1515
+ // We only take sets from the server for now
1516
+ if (method !== 'set' && method !== 'pong') throw 'barf'
1831
1517
  bus.log('net client received', message)
1832
1518
  var t = {version: message.version,
1833
1519
  parents: message.parents,
1834
1520
  patch: message.patch}
1835
1521
  if (t.patch)
1836
- msg.save = apply_patch(bus.cache[msg.save] || {key: msg.save},
1522
+ msg.set = apply_patch(bus.cache[msg.set] || {key: msg.set},
1837
1523
  message.patch[0])
1838
1524
  if (!(t.version||t.parents||t.patch))
1839
1525
  t = undefined
1840
- bus.save.fire(add_prefixes(message.save), t)
1526
+ bus.set.fire(add_prefixes(message.set), t)
1841
1527
  } catch (err) {
1842
1528
  console.error('Received bad network message from '
1843
1529
  +url+': ', event.data, err)
@@ -1861,7 +1547,7 @@
1861
1547
  bus.route = function (key, method, arg, t) {
1862
1548
  var d = get_domain(key)
1863
1549
  if (d && !connections[d]) {
1864
- bus.net_mount(d + '/*', d)
1550
+ bus.ws_mount(d + '/*', d)
1865
1551
  connections[d] = true
1866
1552
  }
1867
1553
 
@@ -2210,8 +1896,8 @@
2210
1896
  }
2211
1897
 
2212
1898
  // This prune() function is a temporary workaround for dealing with nested
2213
- // objects in save() handlers, until we change statebus' behavior. Right
2214
- // now, it calls .to_save only on the top-level state. But if that state
1899
+ // objects in set() handlers, until we change statebus' behavior. Right
1900
+ // now, it calls .to_set only on the top-level state. But if that state
2215
1901
  // validates, it calls fire() on *every* level of state. This means that
2216
1902
  // state changes can sneak inside. Prune() will take out any changes from
2217
1903
  // the nested levels of state in a new object -- replacing them with the
@@ -2228,7 +1914,7 @@
2228
1914
  // Recurse through each property on objects
2229
1915
  else if (typeof(o) === 'object')
2230
1916
  if (o !== null && o.key)
2231
- return bus.fetch(o.key)
1917
+ return bus.get(o.key)
2232
1918
  else
2233
1919
  for (var k in o)
2234
1920
  o[k] = recurse(o[k])
@@ -2334,8 +2020,8 @@
2334
2020
  switch (def.as) {
2335
2021
  case 'handler':
2336
2022
  return def.bus+"('"+def.key+"')."+def.method+' = '+f_string
2337
- case 'fetch callback':
2338
- return 'fetch('+def.key+', '+f_string+')'
2023
+ case 'get callback':
2024
+ return 'get('+def.key+', '+f_string+')'
2339
2025
  case 'reactive':
2340
2026
  return "reactive('"+f_string+"')"
2341
2027
  default:
@@ -2346,7 +2032,7 @@
2346
2032
  function deps (key) {
2347
2033
  // First print out everything waiting for it to pub
2348
2034
  var result = 'Deps: ('+key+') fires into:'
2349
- var pubbers = bindings(key, 'on_save')
2035
+ var pubbers = bindings(key, 'on_set')
2350
2036
  if (pubbers.length === 0) result += ' nothing'
2351
2037
  for (var i=0; i<pubbers.length; i++)
2352
2038
  result += '\n ' + funk_name(pubbers[i].func)
@@ -2390,16 +2076,16 @@
2390
2076
  }
2391
2077
 
2392
2078
  // Make these private methods accessible
2393
- var api = ['cache backup_cache fetch save forget del fire dirty fetch_once',
2079
+ var api = ['cache backup_cache get set forget del fire dirty get_once',
2394
2080
  'subspace bindings run_handler bind unbind reactive uncallback',
2395
2081
  'versions new_version',
2396
- 'make_proxy braid_proxy state sb link',
2082
+ 'link',
2397
2083
  'funk_key funk_name funks key_id key_name id',
2398
- 'pending_fetches fetches_in fetches_out loading_keys loading once',
2084
+ 'pending_gets gets_in gets_out loading_keys loading once',
2399
2085
  'global_funk busses rerunnable_funks',
2400
2086
  'escape_keys unescape_keys translate_keys apply_patch',
2401
2087
  'keyed_2_proxied proxied_2_keyed translate_fields',
2402
- 'net_mount net_automount message_method',
2088
+ 'ws_mount net_automount message_method',
2403
2089
  'parse Set One_To_Many clone extend deep_map deep_equals prune validate sorta_diff log deps symbols'
2404
2090
  ].join(' ').split(' ')
2405
2091
  for (var i=0; i<api.length; i++)
@@ -2417,27 +2103,20 @@
2417
2103
  document.querySelector('script[src^="client"][src$=".js"]'))
2418
2104
  return script_elem && script_elem.getAttribute(option_name)
2419
2105
  }
2420
- if (nodejs || clientjs_option('globals') !== 'false') {
2421
- var globals = ['loading', 'clone', 'forget']
2422
- var client_globals = ['fetch', 'save', 'del', 'state']
2423
- if (!nodejs && Object.keys(busses).length == 0)
2424
- globals = globals.concat(client_globals)
2425
-
2426
- this.og_fetch = this.fetch // Cause fetch() is actually a browser API now
2427
- for (var i=0; i<globals.length; i++)
2428
- this[globals[i]] = eval(globals[i])
2429
- }
2430
2106
 
2431
2107
  busses[bus.id] = bus
2108
+ var this_bus_num = bus_count++
2109
+
2110
+ bus.libs = {}
2432
2111
 
2433
2112
  if (nodejs)
2434
- require('./server').import_server(bus, options)
2113
+ require('./servers').import_server(bus, options)
2435
2114
 
2436
2115
  bus.render_when_loading = true
2437
2116
  return bus
2438
2117
  }
2439
2118
 
2440
- if (nodejs) require('./server').import_module(make_bus)
2119
+ if (nodejs) require('./servers').import_module(make_bus)
2441
2120
 
2442
2121
  return make_bus
2443
2122
  }))