statebus 6.1.21 → 7.0.1

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