statebus 7.1.0 → 7.1.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.
Files changed (3) hide show
  1. package/extras/tests.js +66 -6
  2. package/package.json +1 -1
  3. package/statebus.js +200 -184
package/extras/tests.js CHANGED
@@ -319,7 +319,7 @@ test(function proxy_link (done) {
319
319
  done()
320
320
  })
321
321
 
322
- test(function proxy_links_through (done) {
322
+ test(function proxy_links_through1 (done) {
323
323
  var bus = require('../statebus')()
324
324
 
325
325
  // First try to dereference through three links
@@ -332,16 +332,15 @@ test(function proxy_links_through (done) {
332
332
  log('state.b is', bus.state.b, 'from cache', bus.cache.b)
333
333
  log('state.a is', bus.state.a)
334
334
  log('state.a[0] is', bus.state.a[0])
335
- log('state.a[0]() is', bus.state.a[0]())
336
- log('state.a[0]()() is', bus.state.a[0]()())
337
- assert(bus.state.a[0]()() === 'see')
335
+ log('state.a[0] is', bus.state.a[0])
336
+ assert(bus.state.a[0] === 'see')
338
337
 
339
338
  // Add a little more wrapping and try some more
340
339
 
341
340
  bus.state.nested = [99, {a: bus.link('a')}]
342
341
  log('nested is', bus.state.nested)
343
- log('nested[1].a()[0]()() is', bus.state.nested[1].a()[0]()())
344
- assert(bus.state.nested[1].a()[0]()() === 'see')
342
+ log('nested[1].a[0] is', bus.state.nested[1].a[0])
343
+ assert(bus.state.nested[1].a[0] === 'see')
345
344
 
346
345
  // Now try to go raw at the top-level
347
346
 
@@ -351,6 +350,11 @@ test(function proxy_links_through (done) {
351
350
  bus.state[bus.symbols.raw].nested,
352
351
  bus.raw(bus.state).nested
353
352
  ))
353
+
354
+ log('Gonna deep_quals between:',
355
+ bus.raw(bus.state).nested,
356
+ [ 99, { a: { link: 'a' } } ])
357
+
354
358
  assert(bus.deep_equals(
355
359
  bus.raw(bus.state).nested,
356
360
  [ 99, { a: { link: 'a' } } ]
@@ -366,6 +370,62 @@ test(function proxy_links_through (done) {
366
370
  })
367
371
 
368
372
 
373
+ // Disable the version of proxy_links_through where the user has to explicitly
374
+ // traverse links with ()
375
+ if (false)
376
+ test(function proxy_links_through2 (done) {
377
+ var bus = require('../statebus')()
378
+
379
+ // First try to dereference through three links
380
+
381
+ bus.state.a = [bus.link('b')]
382
+ bus.state.b = bus.link('c')
383
+ bus.state.c = 'see'
384
+
385
+ log('state.c is', bus.state.c)
386
+ log('state.b is', bus.state.b, 'from cache', bus.cache.b)
387
+ log('state.a is', bus.state.a)
388
+ log('state.a[0] is', bus.state.a[0])
389
+ log('state.a[0]() is', bus.state.a[0]())
390
+ log('state.a[0]()() is', bus.state.a[0]()())
391
+ assert(bus.state.a[0]()() === 'see')
392
+
393
+ // Add a little more wrapping and try some more
394
+
395
+ bus.state.nested = [99, {a: bus.link('a')}]
396
+ log('nested is', bus.state.nested)
397
+ log('nested[1].a()[0]()() is', bus.state.nested[1].a()[0]()())
398
+ assert(bus.state.nested[1].a()[0]()() === 'see')
399
+
400
+ // Now try to go raw at the top-level
401
+
402
+ log('Raw is', bus.state[bus.symbols.raw].nested)
403
+ log('Raw is', bus.raw(bus.state).nested)
404
+ assert(bus.deep_equals(
405
+ bus.state[bus.symbols.raw].nested,
406
+ bus.raw(bus.state).nested
407
+ ))
408
+
409
+ console.log('Gonna deep_quals between:',
410
+ bus.raw(bus.state).nested,
411
+ [ 99, { a: { link: 'a' } } ])
412
+
413
+ assert(bus.deep_equals(
414
+ bus.raw(bus.state).nested,
415
+ [ 99, { a: { link: 'a' } } ]
416
+ ))
417
+
418
+ // Now try to go raw within
419
+
420
+ log('Raw inner is', bus.raw(bus.state.nested[1]))
421
+
422
+ log('Bad raw call is', bus.raw(bus.state.nested[0]))
423
+
424
+ done()
425
+ })
426
+
427
+
428
+
369
429
  test(function translate_fields (done) {
370
430
  // Translate Statebus -> Proxy format
371
431
  var tests1 = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "statebus",
3
- "version": "7.1.0",
3
+ "version": "7.1.1",
4
4
  "description": "Synchronize state.",
5
5
  "main": "statebus.js",
6
6
  "scripts": {
package/statebus.js CHANGED
@@ -1455,203 +1455,124 @@
1455
1455
  raw: Symbol('raw'),
1456
1456
  link: Symbol('link')
1457
1457
  }
1458
- function make_proxy () {
1459
- // var custom_inspect_symbol = nodejs && require('util').inspect.custom,
1460
- // custom_inspect = function (depth, options) {
1461
- // return '3333333333';// util.inspect(bus.unescape_from_nelson(this), options)
1462
- // }
1463
- function item_proxy (base, path, o) {
1464
-
1465
- // Primitives pass through unscathed
1466
- if (typeof o === 'number'
1467
- || typeof o === 'string'
1468
- || typeof o === 'boolean'
1469
- || o === undefined
1470
- || o === null
1471
- || typeof o === 'function')
1472
-
1473
- return o
1474
-
1475
- // We recursively descend through {key: ...} links
1476
- if (typeof o === 'object' && 'link' in o) {
1477
- // var new_base = bus.get(o.link)
1478
- // return item_proxy(new_base, '', new_base.val)
1479
- return link_proxy(o.link)
1480
- }
1481
1458
 
1459
+ // The top-level Proxy object holds HTTP resources
1460
+ var top_level_proxy = new Proxy(cache, {
1461
+ get: function get(o, k) {
1462
+ if (k === symbols.is_proxy)
1463
+ return true
1464
+ if (k === symbols.raw)
1465
+ return raw_proxy()
1466
+ if (k === 'inspect' || k === 'valueOf' || typeof k === 'symbol')
1467
+ return undefined
1468
+ bogus_check(k)
1469
+ var base = bus.get(k)
1470
+ return json_proxy(base, '', base.val)
1471
+ },
1472
+ set: function set(o, key, val) {
1473
+ bus.set({
1474
+ key: key,
1475
+ val: escape_json_to_bus(val)
1476
+ })
1477
+ return true
1478
+ },
1479
+ deleteProperty: function del (o, k) {
1480
+ bus.delete(escape_field_to_bus(k))
1481
+ return true // Report success to Proxy
1482
+ }
1483
+ })
1482
1484
 
1483
- // For function proxies:
1484
- //
1485
- // // Javascript won't let us function call a proxy unless the
1486
- // // "target" is a function. So we make a dummy target, and
1487
- // // don't use it.
1488
- // var dummy = function () {}
1489
-
1490
-
1491
- return new Proxy(o, {
1492
- get: function (o, k) {
1493
- if (k === 'inspect' || k === 'valueOf')
1494
- return undefined
1495
- // if (custom_inspect && k === custom_inspect)
1496
- // return custom_inspect
1497
- if (k === symbols.is_proxy)
1498
- return true
1499
- if (k === symbols.raw)
1500
- return o
1501
- if (typeof k === 'symbol')
1502
- return undefined
1503
-
1504
- // Compute the new path
1505
- var new_path = path + '[' + JSON.stringify(k) + ']'
1506
- return item_proxy(base, new_path, o[escape_field_json_to_bus(k)])
1507
- },
1508
- set: function (o, k, v) {
1509
- var value = escape_json_to_bus(v)
1510
- o[escape_field_json_to_bus(k)] = value
1511
- var new_path = path + '[' + JSON.stringify(k) + ']'
1512
- bus.set.sync(
1513
- base,
1514
- // Forward the patches too
1515
- {patches: [{unit: 'json',
1516
- range: new_path,
1517
- content: JSON.stringify(v)}]}
1518
- )
1519
- return true
1520
- },
1521
- has: function (o, k) {
1522
- // if (custom_inspect && k === custom_inspect)
1523
- // return true
1524
- return o.hasOwnProperty(escape_field_json_to_bus(k))
1525
- },
1526
- ownKeys: function () {
1527
- return Object.keys(o).map(unescape_field_bus_to_json)
1528
- },
1529
- getOwnPropertyDescriptor: function (target, key) {
1530
- return { enumerable: true, configurable: true, value: this.get(o, key) }
1531
- },
1532
- deleteProperty: function del (o, k) {
1533
- var new_path = path + '[' + JSON.stringify(k) + ']'
1534
- delete o[escape_field_json_to_bus(k)]
1535
- bus.set(
1536
- base,
1537
- // Forward the patches too
1538
- {patches: [{unit: 'json',
1539
- range: new_path,
1540
- content: undefined}]}
1541
- )
1542
- return true // Report success to Proxy
1543
- }
1544
- // For function proxies:
1545
- //
1546
- // apply: function apply (o, This, args) {
1547
- // return translate_fields(o, unescape_field_from_bus)
1548
- // }
1549
- })}
1550
-
1551
- function link_proxy (url) {
1552
- return new Proxy(function follow_link () {}, {
1553
- get: function (o, k) {
1554
- if (k === 'inspect' || k === 'valueOf')
1555
- return undefined
1556
- // if (custom_inspect && k === custom_inspect)
1557
- // return custom_inspect
1558
- if (k === symbols.is_proxy)
1559
- return true
1560
- if (k === symbols.raw)
1561
- return {link: url}
1562
- if (typeof k === 'symbol')
1563
- return undefined
1564
-
1565
- if (k === 'link')
1566
- return url
1485
+ // The proxy within; a recursive tree holds each piece of JSON in a resource
1486
+ function json_proxy (base, path, o) {
1567
1487
 
1568
- return undefined
1569
- },
1570
- set: function (o, k, v) {
1571
- if (k === 'link') {
1572
- url = v
1573
- }
1488
+ // Primitives pass through unscathed
1489
+ if (typeof o === 'number'
1490
+ || typeof o === 'string'
1491
+ || typeof o === 'boolean'
1492
+ || o === undefined
1493
+ || o === null
1494
+ || typeof o === 'function')
1574
1495
 
1575
- console.assert(false, "Have not fully implemented setting links yet")
1576
-
1577
- // Todo: update the containing proxy object with bus.set.sync
1578
- // else return
1579
- // var value = escape_json_to_bus(v)
1580
- // o[escape_field_json_to_bus(k)] = value
1581
- // var new_path = path + '[' + JSON.stringify(k) + ']'
1582
- // bus.set.sync(
1583
- // base,
1584
- // // Forward the patches too
1585
- // {patches: [{unit: 'json',
1586
- // range: new_path,
1587
- // content: JSON.stringify(v)}]}
1588
- // )
1589
- return true
1590
- },
1591
- has: function (o, k) {
1592
- return k === 'link'
1593
- },
1594
- ownKeys: function () {
1595
- return ['link']
1596
- },
1597
- // getOwnPropertyDescriptor: function (target, key) {
1598
- // return { enumerable: true, configurable: true, value: this.get(o, key) }
1599
- // },
1600
- // deleteProperty: function del (o, k) {
1601
- // var new_path = path + '[' + JSON.stringify(k) + ']'
1602
- // delete o[escape_field_json_to_bus(k)]
1603
- // bus.set(
1604
- // base,
1605
- // // Forward the patches too
1606
- // {patches: [{unit: 'json',
1607
- // range: new_path,
1608
- // content: undefined}]}
1609
- // )
1610
- // return true // Report success to Proxy
1611
- // }
1612
-
1613
- // For function proxy:
1614
- apply: function apply (o, This, args) {
1615
- // console.log('Descending into the link', url, '!')
1616
- return top_level_proxy[url]
1617
- }
1618
- })
1496
+ return o
1497
+
1498
+ // We recursively descend through {key: ...} links
1499
+ if (typeof o === 'object' && 'link' in o) {
1500
+ var new_base = bus.get(o.link)
1501
+ return json_proxy(new_base, '', new_base.val)
1502
+ // return link(o.link)
1619
1503
  }
1620
1504
 
1621
1505
 
1622
- // The top-level Proxy object holds HTTP resources
1623
- var top_level_proxy = new Proxy(cache, {
1624
- get: function get(o, k) {
1506
+ // For function proxies:
1507
+ //
1508
+ // // Javascript won't let us function call a proxy unless the
1509
+ // // "target" is a function. So we make a dummy target, and
1510
+ // // don't use it.
1511
+ // var dummy = function () {}
1512
+
1513
+
1514
+ return new Proxy(o, {
1515
+ get: function (o, k) {
1516
+ if (k === 'inspect' || k === 'valueOf')
1517
+ return undefined
1518
+ // if (custom_inspect && k === custom_inspect)
1519
+ // return custom_inspect
1625
1520
  if (k === symbols.is_proxy)
1626
1521
  return true
1627
1522
  if (k === symbols.raw)
1628
- return raw_proxy()
1629
- if (k === 'inspect' || k === 'valueOf' || typeof k === 'symbol')
1523
+ return o
1524
+ if (typeof k === 'symbol')
1630
1525
  return undefined
1631
- bogus_check(k)
1632
- var base = bus.get(k)
1633
- return item_proxy(base, '', base.val)
1526
+
1527
+ // Compute the new path
1528
+ var new_path = path + '[' + JSON.stringify(k) + ']'
1529
+ return json_proxy(base, new_path, o[escape_field_json_to_bus(k)])
1634
1530
  },
1635
- set: function set(o, key, val) {
1636
- bus.set({
1637
- key: key,
1638
- val: escape_json_to_bus(val)
1639
- })
1531
+ set: function (o, k, v) {
1532
+ var value = escape_json_to_bus(v)
1533
+ o[escape_field_json_to_bus(k)] = value
1534
+ var new_path = path + '[' + JSON.stringify(k) + ']'
1535
+ bus.set.sync(
1536
+ base,
1537
+ // Forward the patches too
1538
+ {patches: [{unit: 'json',
1539
+ range: new_path,
1540
+ content: JSON.stringify(v)}]}
1541
+ )
1640
1542
  return true
1641
1543
  },
1544
+ has: function (o, k) {
1545
+ // if (custom_inspect && k === custom_inspect)
1546
+ // return true
1547
+ return o.hasOwnProperty(escape_field_json_to_bus(k))
1548
+ },
1549
+ ownKeys: function () {
1550
+ return Object.keys(o).map(unescape_field_bus_to_json)
1551
+ },
1552
+ getOwnPropertyDescriptor: function (target, key) {
1553
+ return { enumerable: true, configurable: true, value: this.get(o, key) }
1554
+ },
1642
1555
  deleteProperty: function del (o, k) {
1643
- bus.delete(escape_field_to_bus(k))
1556
+ var new_path = path + '[' + JSON.stringify(k) + ']'
1557
+ delete o[escape_field_json_to_bus(k)]
1558
+ bus.set(
1559
+ base,
1560
+ // Forward the patches too
1561
+ {patches: [{unit: 'json',
1562
+ range: new_path,
1563
+ content: undefined}]}
1564
+ )
1644
1565
  return true // Report success to Proxy
1645
- },
1566
+ }
1646
1567
  // For function proxies:
1568
+ //
1647
1569
  // apply: function apply (o, This, args) {
1648
- // return 'fluffy'
1570
+ // return translate_fields(o, unescape_field_from_bus)
1649
1571
  // }
1650
1572
  })
1651
-
1652
- return top_level_proxy
1653
1573
  }
1654
- bus.state = make_proxy()
1574
+
1575
+ bus.state = top_level_proxy
1655
1576
 
1656
1577
  // This is temporary code to wrap the cache as a flat key/valuel store
1657
1578
  // that returns raw objects, dereferencing .val. We can remove it once we
@@ -1668,9 +1589,100 @@
1668
1589
  })
1669
1590
  }
1670
1591
 
1592
+ // How proxy links work right now:
1593
+ // - The user creates a link with bus.link(key)
1594
+ // - which produces a {[symbols.link]: key}
1595
+ // - which when set() into a proxy, is replaced with a {link: key}, to store internally
1596
+ // - Then, when get()ing that internal {link: key} through Proxy:
1597
+ // - We auto-dereference the key, with another get()
1598
+ // - So the user actually sees the value of the resource on the other side of the link
1671
1599
  function link (url) {
1672
1600
  return {[symbols.link]: url}
1673
1601
  }
1602
+
1603
+ // // The proxy object for links. Disabled for now.
1604
+ // // This type of link has to be function called, as link(), to dereference.
1605
+ // function proxy_link (url) {
1606
+ // function follow_link () {}
1607
+ // return new Proxy(follow_link, {
1608
+ // get: function (o, k) {
1609
+ // console.log('get', k)
1610
+ // if (k === 'inspect' || k === 'valueOf')
1611
+ // return undefined
1612
+ // // if (custom_inspect && k === custom_inspect)
1613
+ // // return custom_inspect
1614
+ // if (k === symbols.is_proxy)
1615
+ // return true
1616
+ // if (k === symbols.link)
1617
+ // return true
1618
+ // if (k === symbols.raw)
1619
+ // return {link: url}
1620
+ // if (typeof k === 'symbol')
1621
+ // return undefined
1622
+
1623
+ // if (k === 'link')
1624
+ // return url
1625
+
1626
+ // return follow_link[k]
1627
+
1628
+ // // return undefined
1629
+ // },
1630
+ // set: function (o, k, v) {
1631
+ // if (k === 'link') {
1632
+ // url = v
1633
+ // }
1634
+
1635
+ // console.assert(false, "Have not fully implemented setting links yet")
1636
+
1637
+ // // Todo: update the containing proxy object with bus.set.sync
1638
+ // // else return
1639
+ // // var value = escape_json_to_bus(v)
1640
+ // // o[escape_field_json_to_bus(k)] = value
1641
+ // // var new_path = path + '[' + JSON.stringify(k) + ']'
1642
+ // // bus.set.sync(
1643
+ // // base,
1644
+ // // // Forward the patches too
1645
+ // // {patches: [{unit: 'json',
1646
+ // // range: new_path,
1647
+ // // content: JSON.stringify(v)}]}
1648
+ // // )
1649
+ // return true
1650
+ // },
1651
+ // has: function (o, k) {
1652
+ // return k === 'link'
1653
+ // },
1654
+ // ownKeys: function () {
1655
+ // console.log('ownkeys')
1656
+ // return ['link', 'arguments', 'caller', 'prototype']
1657
+ // },
1658
+ // getOwnPropertyDescriptor: function (target, key) {
1659
+ // console.log('getownpropertydescriptor', key)
1660
+ // return {
1661
+ // enumerable: true,
1662
+ // configurable: true,
1663
+ // value: key === 'link' ? url : undefined
1664
+ // }
1665
+ // },
1666
+ // // deleteProperty: function del (o, k) {
1667
+ // // var new_path = path + '[' + JSON.stringify(k) + ']'
1668
+ // // delete o[escape_field_json_to_bus(k)]
1669
+ // // bus.set(
1670
+ // // base,
1671
+ // // // Forward the patches too
1672
+ // // {patches: [{unit: 'json',
1673
+ // // range: new_path,
1674
+ // // content: undefined}]}
1675
+ // // )
1676
+ // // return true // Report success to Proxy
1677
+ // // }
1678
+
1679
+ // // For function proxy:
1680
+ // apply: function apply (o, This, args) {
1681
+ // // console.log('Descending into the link', url, '!')
1682
+ // return top_level_proxy[url]
1683
+ // }
1684
+ // })
1685
+ // }
1674
1686
  function raw (proxy) {
1675
1687
  if (!(typeof proxy === 'object' && proxy[symbols.is_proxy]))
1676
1688
  return proxy
@@ -2064,7 +2076,7 @@
2064
2076
 
2065
2077
  // Three levels of escaping through state:
2066
2078
  //
2067
- // - statebus-internal escapes key -> _key
2079
+ // - bus internal escapes key -> _key
2068
2080
  // - nelSON escapes link -> _link
2069
2081
  // - JSON
2070
2082
  //
@@ -2090,7 +2102,7 @@
2090
2102
  : o))
2091
2103
  }
2092
2104
  var unescape_bus_to_json = (obj) =>
2093
- translate_fields(obj, field => unescape_field_bus_to_jsob(field))
2105
+ translate_fields(obj, field => unescape_field_bus_to_json(field))
2094
2106
 
2095
2107
 
2096
2108
  var field_replace = (field, pattern, replacement) => (typeof field === 'string'
@@ -2276,12 +2288,17 @@
2276
2288
  return object
2277
2289
  }
2278
2290
  function deep_equals (a, b) {
2291
+ // This code was only needed for link_proxy:
2292
+ // // Treat link proxy objects as regular JSON links. Otherwise, the
2293
+ // // function fields on them confuse everything.
2294
+ // if (a && typeof a === 'object' && a[symbols.link]) a = {link: a.link}
2295
+ // if (b && typeof b === 'object' && b[symbols.link]) b = {link: b.link}
2296
+
2279
2297
  // Equal Primitives?
2280
2298
  if (a === b
2281
2299
  // But because NaN === NaN returns false:
2282
- || (isNaN(a) && isNaN(b)
2283
- // And because isNaN(undefined) returns true:
2284
- && typeof a === 'number' && typeof b === 'number'))
2300
+ || (typeof a === 'number' && typeof b === 'number'
2301
+ && isNaN(a) && isNaN(b)))
2285
2302
  return true
2286
2303
 
2287
2304
  // Equal Arrays?
@@ -2319,9 +2336,8 @@
2319
2336
  // Equal Primitives?
2320
2337
  if (a === b
2321
2338
  // But because NaN === NaN returns false:
2322
- || (isNaN(a) && isNaN(b)
2323
- // And because isNaN(undefined) returns true:
2324
- && typeof a === 'number' && typeof b === 'number'))
2339
+ || (typeof a === 'number' && typeof b === 'number'
2340
+ && isNaN(a) && isNaN(b)))
2325
2341
  return null
2326
2342
 
2327
2343
  // Equal Arrays?