From 53d5417d4aee6e32ad02d8285723d1a6f42412df Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Sat, 17 Dec 2016 12:25:36 -0800 Subject: [PATCH] Update gun.js --- gun.js | 862 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 431 insertions(+), 431 deletions(-) diff --git a/gun.js b/gun.js index 2eeb9634..81f28e23 100644 --- a/gun.js +++ b/gun.js @@ -1,5 +1,5 @@ -//console.log("!!!!!!!!!!!!!!!! WARNING THIS IS GUN 0.5 !!!!!!!!!!!!!!!!!!!!!!"); -;(function(){ +//console.log("!!!!!!!!!!!!!!!! WARNING THIS IS GUN 0.5 !!!!!!!!!!!!!!!!!!!!!!"); +;(function(){ /* UNBUILD */ var root; @@ -119,7 +119,7 @@ t.r[k] = v; return; } t.r = t.r || []; - t.r.push(k); + t.r.push(k); }; Type.obj.map = function(l, c, _){ var u, i = 0, x, r, ll, lle, f = fn_is(c); @@ -903,40 +903,40 @@ ;(function(){ - Gun.chain.opt = function(opt){ - opt = opt || {}; - var peers = obj_is(opt) ? opt.peers : opt; - if (text_is(peers)) { - peers = [peers]; - } - if (list_is(peers)) { - peers = obj_map(peers, function (url, field, m) { - m(url, {}); - }); - } - if (!obj_is(opt)) { - opt = {}; - } - opt.peers = peers; - var gun = this, at = gun._; - at.root = at.root || gun; + Gun.chain.opt = function(opt){ + opt = opt || {}; + var peers = obj_is(opt) ? opt.peers : opt; + if (text_is(peers)) { + peers = [peers]; + } + if (list_is(peers)) { + peers = obj_map(peers, function (url, field, m) { + m(url, {}); + }); + } + if (!obj_is(opt)) { + opt = {}; + } + opt.peers = peers; + var gun = this, at = gun._; + at.root = at.root || gun; at.graph = at.graph || {}; at.dedup = new Dedup(); - at.opt = at.opt || {}; - - at.opt.peers = Gun.obj.to(at.opt.peers || {}, peers); - Gun.obj.to(opt, at.opt); - - Gun.on('opt', at); - if(!at.once){ - gun.on('in', input, at); - gun.on('out', output, at); - } - at.once = true; - return gun; - } + at.opt = at.opt || {}; + + at.opt.peers = Gun.obj.to(at.opt.peers || {}, peers); + Gun.obj.to(opt, at.opt); + + Gun.on('opt', at); + if(!at.once){ + gun.on('in', input, at); + gun.on('out', output, at); + } + at.once = true; + return gun; + } function output(at){ - var cat = this, gun = cat.gun, tmp; + var cat = this, gun = cat.gun, tmp; // TODO: BUG! Outgoing `get` to read from in memory!!! if(at.get && get(at, cat)){ return } //if(at.put){ @@ -1034,8 +1034,8 @@ var de = this; var now = Gun.time.is(); var oldest = now; - var maxAge = 5 * 60 * 1000; - // TODO: Gun.scheduler already does this? Reuse that. + var maxAge = 5 * 60 * 1000; + // TODO: Gun.scheduler already does this? Reuse that. Gun.obj.map(de.cache, function (time, id) { oldest = Math.min(now, time); @@ -1043,8 +1043,8 @@ return; } - delete de.cache[id]; - }); + delete de.cache[id]; + }); var done = Gun.obj.empty(de.cache); @@ -1435,8 +1435,8 @@ return gun; } function output(at){ - var cat = this, gun = cat.gun, root = gun.Back(-1), put, get, tmp; - if(!at.gun){ + var cat = this, gun = cat.gun, root = gun.Back(-1), put, get, tmp; + if(!at.gun){ at.gun = gun; } if(at.get && !at.get[_soul]){ @@ -1750,7 +1750,7 @@ via: at, put: at.put[cat.get] } - + } else { if(obj_has(at.put, cat.get)){ return ev.off() } at = { @@ -2142,13 +2142,13 @@ var put = {}, soul = Gun.node.soul(node); if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + node + '"!')}) } gun.put(Gun.obj.put(put, soul, Gun.val.rel.ify(soul)), cb, opt); - }); + }, {wait:0}); } }()); })(require, './api'); ;require(function(module){ - if(typeof Gun === 'undefined'){ return } // TODO: localStorage is Browser only. But it would be nice if it could somehow plugin into NodeJS compatible localStorage APIs? + if(typeof Gun === 'undefined'){ return } // TODO: localStorage is Browser only. But it would be nice if it could somehow plugin into NodeJS compatible localStorage APIs? var root, noop = function(){}; if(typeof window !== 'undefined'){ root = window } @@ -2177,7 +2177,7 @@ gun.Back(-1).on('in', {'@': at['#']}); } return; - } + } if(Gun.obj.has(lex, '.')){var tmp = data[lex['.']];data = {_: data._};if(u !== tmp){data[lex['.']] = tmp}} //console.log('@@@@@@@@@@@@local get', data, at); gun.Back(-1).on('in', {'@': at['#'], put: Gun.graph.node(data)}); @@ -2187,391 +2187,391 @@ Gun.on('get', get); })(require, './adapters/localStorage'); - ;require(function(module){ - var Gun = require('./gun'); - - // Check for stone-age browsers. - if (typeof JSON === 'undefined') { - throw new Error( - 'Gun depends on JSON. Please load it first:\n' + - 'ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js' - ); - } - - function Client (url, options) { - if (!(this instanceof Client)) { - return new Client(url, options); - } - - this.url = Client.formatURL(url); - this.socket = null; - this.queue = []; - this.sid = Gun.text.random(10); - - this.on = Gun.on; - - this.options = options || {}; - this.resetBackoff(); - } - - Client.prototype = { - constructor: Client, - - drainQueue: function () { - var queue = this.queue; - var client = this; - - // Reset the queue. - this.queue = []; - - // Send each message. - queue.forEach(function (msg) { - client.send(msg); - }); - - return queue.length; - }, - - connect: function () { - var client = this; - var socket = new Client.WebSocket(this.url); - this.socket = socket; - - // Forward messages into the emitter. - socket.addEventListener('message', function (msg) { - client.on('message', msg); - }); - - // Reconnect on close events. - socket.addEventListener('close', function () { - client.scheduleReconnect(); - }); - - // Send the messages in the queue. - this.ready(function () { - client.drainQueue(); - }); - - return socket; - }, - - resetBackoff: function () { - var backoff = this.options; - - this.backoff = { - time: backoff.time || 100, - max: backoff.max || 30000, - factor: backoff.factor || 2 - }; - - return this.backoff; - }, - - nextBackoff: function () { - var backoff = this.backoff; - var next = backoff.time * backoff.factor; - var max = backoff.max; - - if (next > max) { - next = max; - } - - return (backoff.time = next); - }, - - // Try to efficiently reconnect. - scheduleReconnect: function () { - var client = this; - var time = this.backoff.time; - this.nextBackoff(); - - setTimeout(function () { - client.connect(); - - client.ready(function () { - client.resetBackoff(); - }); - }, time); - }, - - isClosed: function () { - var socket = this.socket; - - if (!socket) { - return true; - } - - var state = socket.readyState; - - if (state === socket.CLOSING || state === socket.CLOSED) { - return true; - } - - return false; - }, - - ready: function (callback) { - var socket = this.socket; - var state = socket.readyState; - - if (state === socket.OPEN) { - callback(); - return; - } - - if (state === socket.CONNECTING) { - socket.addEventListener('open', callback); - } - }, - - send: function (msg) { - if (this.isClosed()) { - this.queue.push(msg); - - // Will send once connected. - this.connect(); - return false; - } - - var socket = this.socket; - - // Make sure the socket is open. - this.ready(function () { - socket.send(msg); - }); - - return true; - } - }; - - if (typeof window !== 'undefined') { - Client.WebSocket = window.WebSocket || - window.webkitWebSocket || - window.mozWebSocket || - null; - } - - Client.isSupported = Client.WebSocket !== null; - - // Ensure the protocol is correct. - Client.formatURL = function (url) { - return url.replace('http', 'ws'); - }; - - // Send a message to a group of peers. - Client.broadcast = function (urls, msg) { - var pool = Client.pool; - msg.headers = msg.headers || {}; - - Gun.obj.map(urls, function (options, addr) { - - var url = Client.formatURL(addr); - - var peer = pool[url]; - - var envelope = { - headers: Gun.obj.to(msg.headers, { - 'gun-sid': peer.sid - }), - body: msg.body - }; - - var serialized = Gun.text.ify(envelope); - - peer.send(serialized); - }); - - }; - - // A map of URLs to client instances. - Client.pool = {}; - - // Close all WebSockets when the window closes. - if (typeof window !== 'undefined') { - window.addEventListener('unload', function () { - Gun.obj.map(Client.pool, function (client) { - if (client.isClosed()) { - return; - } - - client.socket.close(); - }); - }); - } - - // Define client instances as gun needs them. - // Sockets will not be opened until absolutely necessary. - Gun.on('opt', function (ctx) { - - var gun = ctx.gun; - var peers = gun.Back('opt.peers') || {}; - - Gun.obj.map(peers, function (options, addr) { - var url = Client.formatURL(addr); - - // Ignore clients we've seen before. - if (Client.pool.hasOwnProperty(url)) { - return; - } - - var client = new Client(url, options.backoff); - - // Add it to the pool. - Client.pool[url] = client; - - // Listen to incoming messages. - client.on('message', function (msg) { - var data; - - try { - data = Gun.obj.ify(msg.data); - } catch (err) { - // Invalid message, discard it. - return; - } - - if (!data || !data.body) { - return; - } - - gun.on('in', data.body); - }); - }); - }); - - function request (peers, ctx) { - if (Client.isSupported) { - Client.broadcast(peers, { body: ctx }); - } - } - - // Broadcast the messages. - Gun.on('out', function (ctx) { - var gun = ctx.gun; - - var peers = gun.Back('opt.peers') || {}; - - // Validate. - if (Gun.obj.empty(peers)) { - return; - } - - request(peers, ctx); - }); - - request.jsonp = function (opt, cb) { - request.jsonp.ify(opt, function (url) { - if (!url) { - return; - } - request.jsonp.send(url, function (err, reply) { - cb(err, reply); - request.jsonp.poll(opt, reply); - }, opt.jsonp); - }); - }; - request.jsonp.send = function (url, cb, id) { - var js = document.createElement('script'); - js.src = url; - js.onerror = function () { - (window[js.id] || function () {})(null, { - err: 'JSONP failed!' - }); - }; - window[js.id = id] = function (res, err) { - cb(err, res); - cb.id = js.id; - js.parentNode.removeChild(js); - delete window[cb.id]; - }; - js.async = true; - document.getElementsByTagName('head')[0].appendChild(js); - return js; - }; - request.jsonp.poll = function (opt, res) { - if (!opt || !opt.base || !res || !res.headers || !res.headers.poll) { - return; - } - var polls = request.jsonp.poll.s = request.jsonp.poll.s || {}; - polls[opt.base] = polls[opt.base] || setTimeout(function () { - var msg = { - base: opt.base, - headers: { pull: 1 } - }; - - request.each(opt.headers, function (header, name) { - msg.headers[name] = header; - }); - - request.jsonp(msg, function (err, reply) { - delete polls[opt.base]; - - var body = reply.body || []; - while (body.length && body.shift) { - var res = reply.body.shift(); - if (res && res.body) { - request.createServer.ing(res, function () { - request(opt.base, null, null, res); - }); - } - } - }); - }, res.headers.poll); - }; - request.jsonp.ify = function (opt, cb) { - var uri = encodeURIComponent, query = '?'; - if (opt.url && opt.url.pathname) { - query = opt.url.pathname + query; - } - query = opt.base + query; - request.each((opt.url || {}).query, function (value, key) { - query += (uri(key) + '=' + uri(value) + '&'); - }); - if (opt.headers) { - query += uri('`') + '=' + uri( - JSON.stringify(opt.headers) - ) + '&'; - } - if (request.jsonp.max < query.length) { - return cb(); - } - var random = Math.floor(Math.random() * (0xffff + 1)); - query += (uri('jsonp') + '=' + uri(opt.jsonp = 'P' + random)); - if (opt.body) { - query += '&'; - var w = opt.body, wls = function (w, l, s) { - return uri('%') + '=' + uri(w+'-'+(l||w)+'/'+(s||w)) + '&' + uri('$') + '='; + ;require(function(module){ + var Gun = require('./gun'); + + // Check for stone-age browsers. + if (typeof JSON === 'undefined') { + throw new Error( + 'Gun depends on JSON. Please load it first:\n' + + 'ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js' + ); + } + + function Client (url, options) { + if (!(this instanceof Client)) { + return new Client(url, options); + } + + this.url = Client.formatURL(url); + this.socket = null; + this.queue = []; + this.sid = Gun.text.random(10); + + this.on = Gun.on; + + this.options = options || {}; + this.resetBackoff(); + } + + Client.prototype = { + constructor: Client, + + drainQueue: function () { + var queue = this.queue; + var client = this; + + // Reset the queue. + this.queue = []; + + // Send each message. + queue.forEach(function (msg) { + client.send(msg); + }); + + return queue.length; + }, + + connect: function () { + var client = this; + var socket = new Client.WebSocket(this.url); + this.socket = socket; + + // Forward messages into the emitter. + socket.addEventListener('message', function (msg) { + client.on('message', msg); + }); + + // Reconnect on close events. + socket.addEventListener('close', function () { + client.scheduleReconnect(); + }); + + // Send the messages in the queue. + this.ready(function () { + client.drainQueue(); + }); + + return socket; + }, + + resetBackoff: function () { + var backoff = this.options; + + this.backoff = { + time: backoff.time || 100, + max: backoff.max || 30000, + factor: backoff.factor || 2 + }; + + return this.backoff; + }, + + nextBackoff: function () { + var backoff = this.backoff; + var next = backoff.time * backoff.factor; + var max = backoff.max; + + if (next > max) { + next = max; } - if (typeof w != 'string') { - w = JSON.stringify(w); - query += uri('^') + '=' + uri('json') + '&'; - } - w = uri(w); - var i = 0, l = w.length - , s = request.jsonp.max - (query.length + wls(l.toString()).length); - if (s < 0){ - return cb(); - } - while (w) { - cb(query + wls(i, (i += s), l) + w.slice(0, i)); - w = w.slice(i); - } - } else { - cb(query); - } - }; - request.jsonp.max = 2000; - request.each = function (obj, cb, as) { - if (!obj || !cb) { - return; - } - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - cb.call(as, obj[key], key); - } - } - }; - module.exports = Client; - })(require, './polyfill/request'); - -}()); + + return (backoff.time = next); + }, + + // Try to efficiently reconnect. + scheduleReconnect: function () { + var client = this; + var time = this.backoff.time; + this.nextBackoff(); + + setTimeout(function () { + client.connect(); + + client.ready(function () { + client.resetBackoff(); + }); + }, time); + }, + + isClosed: function () { + var socket = this.socket; + + if (!socket) { + return true; + } + + var state = socket.readyState; + + if (state === socket.CLOSING || state === socket.CLOSED) { + return true; + } + + return false; + }, + + ready: function (callback) { + var socket = this.socket; + var state = socket.readyState; + + if (state === socket.OPEN) { + callback(); + return; + } + + if (state === socket.CONNECTING) { + socket.addEventListener('open', callback); + } + }, + + send: function (msg) { + if (this.isClosed()) { + this.queue.push(msg); + + // Will send once connected. + this.connect(); + return false; + } + + var socket = this.socket; + + // Make sure the socket is open. + this.ready(function () { + socket.send(msg); + }); + + return true; + } + }; + + if (typeof window !== 'undefined') { + Client.WebSocket = window.WebSocket || + window.webkitWebSocket || + window.mozWebSocket || + null; + } + + Client.isSupported = Client.WebSocket !== null; + + // Ensure the protocol is correct. + Client.formatURL = function (url) { + return url.replace('http', 'ws'); + }; + + // Send a message to a group of peers. + Client.broadcast = function (urls, msg) { + var pool = Client.pool; + msg.headers = msg.headers || {}; + + Gun.obj.map(urls, function (options, addr) { + + var url = Client.formatURL(addr); + + var peer = pool[url]; + + var envelope = { + headers: Gun.obj.to(msg.headers, { + 'gun-sid': peer.sid + }), + body: msg.body + }; + + var serialized = Gun.text.ify(envelope); + + peer.send(serialized); + }); + + }; + + // A map of URLs to client instances. + Client.pool = {}; + + // Close all WebSockets when the window closes. + if (typeof window !== 'undefined') { + window.addEventListener('unload', function () { + Gun.obj.map(Client.pool, function (client) { + if (client.isClosed()) { + return; + } + + client.socket.close(); + }); + }); + } + + // Define client instances as gun needs them. + // Sockets will not be opened until absolutely necessary. + Gun.on('opt', function (ctx) { + + var gun = ctx.gun; + var peers = gun.Back('opt.peers') || {}; + + Gun.obj.map(peers, function (options, addr) { + var url = Client.formatURL(addr); + + // Ignore clients we've seen before. + if (Client.pool.hasOwnProperty(url)) { + return; + } + + var client = new Client(url, options.backoff); + + // Add it to the pool. + Client.pool[url] = client; + + // Listen to incoming messages. + client.on('message', function (msg) { + var data; + + try { + data = Gun.obj.ify(msg.data); + } catch (err) { + // Invalid message, discard it. + return; + } + + if (!data || !data.body) { + return; + } + + gun.on('in', data.body); + }); + }); + }); + + function request (peers, ctx) { + if (Client.isSupported) { + Client.broadcast(peers, { body: ctx }); + } + } + + // Broadcast the messages. + Gun.on('out', function (ctx) { + var gun = ctx.gun; + + var peers = gun.Back('opt.peers') || {}; + + // Validate. + if (Gun.obj.empty(peers)) { + return; + } + + request(peers, ctx); + }); + + request.jsonp = function (opt, cb) { + request.jsonp.ify(opt, function (url) { + if (!url) { + return; + } + request.jsonp.send(url, function (err, reply) { + cb(err, reply); + request.jsonp.poll(opt, reply); + }, opt.jsonp); + }); + }; + request.jsonp.send = function (url, cb, id) { + var js = document.createElement('script'); + js.src = url; + js.onerror = function () { + (window[js.id] || function () {})(null, { + err: 'JSONP failed!' + }); + }; + window[js.id = id] = function (res, err) { + cb(err, res); + cb.id = js.id; + js.parentNode.removeChild(js); + delete window[cb.id]; + }; + js.async = true; + document.getElementsByTagName('head')[0].appendChild(js); + return js; + }; + request.jsonp.poll = function (opt, res) { + if (!opt || !opt.base || !res || !res.headers || !res.headers.poll) { + return; + } + var polls = request.jsonp.poll.s = request.jsonp.poll.s || {}; + polls[opt.base] = polls[opt.base] || setTimeout(function () { + var msg = { + base: opt.base, + headers: { pull: 1 } + }; + + request.each(opt.headers, function (header, name) { + msg.headers[name] = header; + }); + + request.jsonp(msg, function (err, reply) { + delete polls[opt.base]; + + var body = reply.body || []; + while (body.length && body.shift) { + var res = reply.body.shift(); + if (res && res.body) { + request.createServer.ing(res, function () { + request(opt.base, null, null, res); + }); + } + } + }); + }, res.headers.poll); + }; + request.jsonp.ify = function (opt, cb) { + var uri = encodeURIComponent, query = '?'; + if (opt.url && opt.url.pathname) { + query = opt.url.pathname + query; + } + query = opt.base + query; + request.each((opt.url || {}).query, function (value, key) { + query += (uri(key) + '=' + uri(value) + '&'); + }); + if (opt.headers) { + query += uri('`') + '=' + uri( + JSON.stringify(opt.headers) + ) + '&'; + } + if (request.jsonp.max < query.length) { + return cb(); + } + var random = Math.floor(Math.random() * (0xffff + 1)); + query += (uri('jsonp') + '=' + uri(opt.jsonp = 'P' + random)); + if (opt.body) { + query += '&'; + var w = opt.body, wls = function (w, l, s) { + return uri('%') + '=' + uri(w+'-'+(l||w)+'/'+(s||w)) + '&' + uri('$') + '='; + } + if (typeof w != 'string') { + w = JSON.stringify(w); + query += uri('^') + '=' + uri('json') + '&'; + } + w = uri(w); + var i = 0, l = w.length + , s = request.jsonp.max - (query.length + wls(l.toString()).length); + if (s < 0){ + return cb(); + } + while (w) { + cb(query + wls(i, (i += s), l) + w.slice(0, i)); + w = w.slice(i); + } + } else { + cb(query); + } + }; + request.jsonp.max = 2000; + request.each = function (obj, cb, as) { + if (!obj || !cb) { + return; + } + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + cb.call(as, obj[key], key); + } + } + }; + module.exports = Client; + })(require, './polyfill/request'); + +}());