// Generated by IcedCoffeeScript 1.7.1-c (function() { var ACCTYPES, BTC, CHECK, Cryptocurrency, E, Link, LinkTable, RemoteProof, Revoke, SHA256, ST, SelfSig, Track, Untrack, Warnings, asyncify, athrow, bitcoyne, cheerio, colors, constants, date_to_unix, db, deq, dict_union, env, format_fingerprint, iced, log, make_email, make_esc, proofs, req, request, scrapemod, util, __iced_k, __iced_k_noop, _ref, _ref1, _ref2, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; iced = require('iced-runtime').iced; __iced_k = __iced_k_noop = function() {}; db = require('./db'); req = require('./req'); log = require('./log'); constants = require('./constants').constants; SHA256 = require('./keyutils').SHA256; E = require('./err').E; _ref = require('pgp-utils').util, format_fingerprint = _ref.format_fingerprint, Warnings = _ref.Warnings, asyncify = _ref.asyncify; make_esc = require('iced-error').make_esc; ST = constants.signature_types; ACCTYPES = constants.allowed_cryptocurrency_types; _ref1 = require('./util'), dict_union = _ref1.dict_union, date_to_unix = _ref1.date_to_unix, make_email = _ref1.make_email; proofs = require('keybase-proofs'); cheerio = require('cheerio'); request = require('request'); colors = require('./colors'); deq = require('deep-equal'); util = require('util'); env = require('./env').env; scrapemod = require('./scrapers'); _ref2 = require('./display'), CHECK = _ref2.CHECK, BTC = _ref2.BTC; athrow = require('iced-utils').util.athrow; bitcoyne = require('bitcoyne'); exports.Link = Link = (function() { Link.ID_TYPE = constants.ids.sig_chain_link; function Link(_arg) { this.id = _arg.id, this.obj = _arg.obj; this.id || (this.id = this.obj.payload_hash); this._revoked = false; } Link.prototype.export_to_user = function() { return { seqno: this.seqno(), payload_hash: this.id, sig_id: this.sig_id() }; }; Link.prototype.prev = function() { return this.obj.prev; }; Link.prototype.seqno = function() { return this.obj.seqno; }; Link.prototype.sig = function() { return this.obj.sig; }; Link.prototype.payload_json_str = function() { return this.obj.payload_json; }; Link.prototype.fingerprint = function() { return this.obj.fingerprint.toLowerCase(); }; Link.prototype.short_key_id = function() { return this.fingerprint().slice(-8).toUpperCase(); }; Link.prototype.is_self_sig = function() { return false; }; Link.prototype.self_signer = function() { var _ref3, _ref4, _ref5; return (_ref3 = this.payload_json()) != null ? (_ref4 = _ref3.body) != null ? (_ref5 = _ref4.key) != null ? _ref5.username : void 0 : void 0 : void 0; }; Link.prototype.sig_type = function() { return this.obj.sig_type; }; Link.prototype.sig_id = function() { return this.obj.sig_id; }; Link.prototype.remote_id = function() { return this.obj.remote_id; }; Link.prototype.body = function() { var _ref3; return (_ref3 = this.payload_json()) != null ? _ref3.body : void 0; }; Link.prototype.ctime = function() { return date_to_unix(this.obj.ctime); }; Link.prototype.revoke = function() { return this._revoked = true; }; Link.prototype.is_revoked = function() { return this._revoked; }; Link.prototype.to_track_obj = function() { return { seqno: this.seqno(), sig_id: this.sig_id(), payload_hash: this.id }; }; Link.prototype.payload_json = function() { var e, ret, s; if (this._payload_obj == null) { s = this.payload_json_str(); ret = {}; try { ret = JSON.parse(s); } catch (_error) { e = _error; log.error("Error parsing JSON " + s + ": " + e.message); } this._payload_obj = ret; } return this._payload_obj; }; Link.prototype.walk = function(_arg) { var fn, key, parent; fn = _arg.fn, parent = _arg.parent, key = _arg.key; return fn({ value: this, key: key, parent: parent }); }; Link.prototype.flatten = function() { return [this]; }; Link.prototype.is_leaf = function() { return true; }; Link.prototype.is_revocable = function() { return false; }; Link.prototype.matches = function(rxx) { return !!(JSON.stringify(this.condense()).match(rxx)); }; Link.prototype.condense = function() { return this.payload_json(); }; Link.prototype.summary = function() { return { seqno: this.seqno(), id: this.sig_id(), type: this.type_str(), ctime: this.ctime(), live: !(this.is_revoked()), payload: this.condense() }; }; Link.prototype.verify = function() { var a, b, err, j; err = null; if ((a = this.obj.payload_hash) !== (b = this.id)) { err = new E.CorruptionError("Link ID mismatch: " + a + " != " + b); } else if ((j = SHA256(this.payload_json_str()).toString('hex')) !== this.id) { err = new E.CorruptionError("Link has wrong id: " + this.id + " != " + this.j); } return err; }; Link.prototype.store = function(cb) { var err, ___iced_passed_deferral, __iced_deferrals, __iced_k, _ref3; __iced_k = __iced_k_noop; ___iced_passed_deferral = iced.findDeferral(arguments); if (((_ref3 = this.obj.prev) != null ? _ref3.length : void 0) === 0) { this.obj.prev = null; } log.debug("| putting link: " + this.id); (function(_this) { return (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "Link.store" }); db.put({ type: Link.ID_TYPE, key: _this.id, value: _this.obj }, __iced_deferrals.defer({ assign_fn: (function() { return function() { return err = arguments[0]; }; })(), lineno: 118 })); __iced_deferrals._fulfill(); }); })(this)((function(_this) { return function() { return cb(err); }; })(this)); }; Link.prototype.refresh = function(cb) { return cb(null); }; Link.alloc = function(_arg) { var id, klass, obj; obj = _arg.obj, id = _arg.id; klass = (function() { switch (obj.sig_type) { case ST.SELF_SIG: return SelfSig; case ST.REMOTE_PROOF: return RemoteProof; case ST.TRACK: return Track; case ST.CRYPTOCURRENCY: return Cryptocurrency; case ST.REVOKE: return Revoke; case ST.UNTRACK: return Untrack; default: return Link; } })(); return new klass({ obj: obj, id: id }); }; Link.load = function(id, cb) { var err, obj, ret, ___iced_passed_deferral, __iced_deferrals, __iced_k; __iced_k = __iced_k_noop; ___iced_passed_deferral = iced.findDeferral(arguments); ret = null; (function(_this) { return (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "Link.load" }); db.get({ type: Link.ID_TYPE, key: id }, __iced_deferrals.defer({ assign_fn: (function() { return function() { err = arguments[0]; return obj = arguments[1]; }; })(), lineno: 144 })); __iced_deferrals._fulfill(); }); })(this)((function(_this) { return function() { if (typeof err !== "undefined" && err !== null) { } else if (typeof obj !== "undefined" && obj !== null) { ret = Link.alloc({ id: id, obj: obj }); if ((err = ret.verify()) != null) { ret = null; } } return cb(err, ret); }; })(this)); }; Link.prototype.insert_into_table = function() { return log.warn("unhandled public sig type: " + (this.sig_type())); }; return Link; })(); SelfSig = (function(_super) { __extends(SelfSig, _super); function SelfSig() { return SelfSig.__super__.constructor.apply(this, arguments); } SelfSig.prototype.is_self_sig = function() { return true; }; SelfSig.prototype.condense = function() { return "self"; }; SelfSig.prototype.type_str = function() { return "self"; }; SelfSig.prototype.is_revocable = function() { return true; }; SelfSig.prototype.insert_into_table = function(_arg) { var table; table = _arg.table; return table.insert(this.sig_type(), this); }; return SelfSig; })(Link); RemoteProof = (function(_super) { __extends(RemoteProof, _super); function RemoteProof() { return RemoteProof.__super__.constructor.apply(this, arguments); } RemoteProof.prototype.proof_service_object = function() { var _ref3, _ref4; return (_ref3 = this.payload_json()) != null ? (_ref4 = _ref3.body) != null ? _ref4.service : void 0 : void 0; }; RemoteProof.prototype.proof_type = function() { return this.obj.proof_type; }; RemoteProof.prototype.proof_state = function() { return this.obj.proof_state; }; RemoteProof.prototype.remote_username = function() { var _ref3; return (_ref3 = this.proof_service_object()) != null ? _ref3.username : void 0; }; RemoteProof.prototype.api_url = function() { return this.obj.api_url; }; RemoteProof.prototype.human_url = function() { return this.obj.human_url; }; RemoteProof.prototype.proof_text_check = function() { return this.obj.proof_text_check; }; RemoteProof.prototype.type_str = function() { return "proof"; }; RemoteProof.prototype.is_revocable = function() { return true; }; RemoteProof.prototype.condense = function() { var key, pso, val; pso = this.proof_service_object(); key = pso.name || pso.protocol; if (key.slice(-1)[0] !== ':') { key += ":"; } val = pso.username || pso.domain || pso.hostname; return [key, val].join('//'); }; RemoteProof.prototype.insert_into_table = function(_arg) { var S, index, keys, opts, states, sub_id, table, _ref3; table = _arg.table, index = _arg.index, opts = _arg.opts; log.debug("+ RemoteProof::insert_into_table"); S = constants.proof_state; states = [S.OK, S.TEMP_FAILURE, S.LOOKING]; if (opts != null ? opts.show_perm_failures : void 0) { states.push(S.PERM_FAILURE); } if (_ref3 = this.proof_state(), __indexOf.call(states, _ref3) >= 0) { keys = [this.sig_type(), this.proof_type()]; if ((sub_id = this.get_sub_id()) != null) { keys.push(sub_id); } table.insert_path(keys, this); } else { log.debug("Skipping remote proof in state " + (this.proof_state()) + ": " + (this.payload_json_str())); } return log.debug("- RemoteProof::insert_into_table"); }; RemoteProof.prototype.get_sub_id = function() { var _ref3; return (_ref3 = scrapemod.alloc_stub(this.proof_type())) != null ? _ref3.get_sub_id(this.proof_service_object()) : void 0; }; RemoteProof.prototype.check_remote_proof = function(_arg, cb) { var arg, e2, err, errmsg, esc, msg, ok, proof_vec, rc, rsc, scraper, skip, type, type_s, username, warnings, ___iced_passed_deferral, __iced_deferrals, __iced_k; __iced_k = __iced_k_noop; ___iced_passed_deferral = iced.findDeferral(arguments); skip = _arg.skip, type = _arg.type, warnings = _arg.warnings, proof_vec = _arg.proof_vec; username = this.self_signer(); esc = make_esc(cb, "SigChain::Link::check_remote_proof'"); (function(_this) { return (function(__iced_k) { if ((type_s = proofs.proof_type_to_string[type]) == null) { err = new E.VerifyError("Unknown proof type (" + type + ") found; consider a `keybase update`"); (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.check_remote_proof" }); athrow(err, esc(__iced_deferrals.defer({ lineno: 228 }))); __iced_deferrals._fulfill(); })(__iced_k); } else { return __iced_k(); } }); })(this)((function(_this) { return function() { log.debug("+ " + username + ": checking remote " + type_s + " proof"); (function(__iced_k) { if (!skip && !_this.api_url()) { (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.check_remote_proof" }); _this.refresh(__iced_deferrals.defer({ assign_fn: (function() { return function() { return e2 = arguments[0]; }; })(), lineno: 233 })); __iced_deferrals._fulfill(); })(function() { return __iced_k(typeof e2 !== "undefined" && e2 !== null ? log.warn("Error fetching URL for proof: " + e2.message) : void 0); }); } else { return __iced_k(); } })(function() { rsc = JSON.stringify(_this.proof_service_object()); log.debug("| remote service desc is " + rsc); (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.check_remote_proof" }); scrapemod.alloc(type, esc(__iced_deferrals.defer({ assign_fn: (function() { return function() { return scraper = arguments[0]; }; })(), lineno: 240 }))); __iced_deferrals._fulfill(); })(function() { arg = { api_url: _this.api_url(), signature: _this.sig(), proof_text_check: _this.proof_text_check(), remote_id: "" + _this.remote_id(), human_url: _this.human_url() }; arg = dict_union(arg, _this.proof_service_object()); proof_vec.push(scraper.to_proof(arg)); errmsg = ""; (function(__iced_k) { if (skip) { return __iced_k(rc = proofs.constants.v_codes.OK); } else { (function(__iced_k) { if (!_this.api_url()) { return __iced_k(rc = proofs.constants.v_codes.NOT_FOUND); } else { log.debug("+ Calling into scraper -> " + rsc + "@" + type_s + " -> " + (_this.api_url())); (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.check_remote_proof" }); scraper.validate(arg, __iced_deferrals.defer({ assign_fn: (function() { return function() { err = arguments[0]; return rc = arguments[1]; }; })(), lineno: 259 })); __iced_deferrals._fulfill(); })(function() { log.debug("- Called scraper -> " + rc); return __iced_k(typeof err !== "undefined" && err !== null ? errmsg = ": " + err.message : void 0); }); } })(__iced_k); } })(function() { ok = false; if (rc !== proofs.constants.v_codes.OK) { warnings.push(new E.RemoteCheckError("Remote check failed (code: " + rc + ")")); _this.obj.proof_state = rc; } else { ok = true; log.debug("| proof checked out"); } msg = scraper.format_msg({ arg: arg, ok: ok }); if (skip) { msg.push("(you've recently OK'ed this proof)"); } if (!ok) { msg.push("(failed with code " + rc + errmsg + ")"); } log.lconsole("error", log["package"]().INFO, msg.join(' ')); log.debug("- " + username + ": checked remote " + type_s + " proof"); return cb(null); }); }); }); }; })(this)); }; RemoteProof.prototype.remote_proof_to_track_obj = function() { var _ref3, _ref4; return { ctime: this.obj.ctime, etime: this.obj.etime, seqno: this.obj.seqno, curr: this.id, sig_type: this.obj.sig_type, sig_id: this.obj.sig_id, remote_key_proof: { check_data_json: (_ref3 = this.payload_json()) != null ? (_ref4 = _ref3.body) != null ? _ref4.service : void 0 : void 0, state: this.obj.proof_state, proof_type: this.obj.proof_type } }; }; RemoteProof.prototype.to_list_display = function(opts) { var name, _ref3; name = (_ref3 = scrapemod.alloc_stub(this.proof_type())) != null ? _ref3.to_list_display(this.proof_service_object()) : void 0; if ((opts != null ? opts.with_sig_ids : void 0) || ((opts != null ? opts.with_proof_states : void 0) != null)) { return { name: name, sig_id: this.sig_id(), proof_state: this.proof_state() }; } else { return name; } }; RemoteProof.prototype.refresh = function(cb) { var arg, body, err, row, u, ___iced_passed_deferral, __iced_deferrals, __iced_k; __iced_k = __iced_k_noop; ___iced_passed_deferral = iced.findDeferral(arguments); err = null; log.debug("+ refresh RemoteProof link"); (function(_this) { return (function(__iced_k) { if (_this.api_url() == null) { log.debug("| Proof_id = " + _this.obj.proof_id); arg = { endpoint: "sig/remote_proof", args: { proof_id: _this.obj.proof_id } }; log.debug("| request proof refresh for id=" + _this.obj.proof_id); (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.refresh" }); req.get(arg, __iced_deferrals.defer({ assign_fn: (function() { return function() { err = arguments[0]; return body = arguments[1]; }; })(), lineno: 315 })); __iced_deferrals._fulfill(); })(function() { (function(__iced_k) { if ((err == null) && ((row = typeof body !== "undefined" && body !== null ? body.row : void 0) != null) && ((u = row.api_url) != null)) { log.debug("| Refreshed with api_url -> " + u); _this.obj.api_url = u; _this.obj.human_url = row.human_url; (function(__iced_k) { __iced_deferrals = new iced.Deferrals(__iced_k, { parent: ___iced_passed_deferral, filename: "/home/jacko/node-client/src/chainlink.iced", funcname: "RemoteProof.refresh" }); _this.store(__iced_deferrals.defer({ assign_fn: (function() { return function() { return err = arguments[0]; }; })(), lineno: 320 })); __iced_deferrals._fulfill(); })(__iced_k); } else { return __iced_k(); } })(__iced_k); }); } else { return __iced_k(); } }); })(this)((function(_this) { return function() { log.debug("- refresh RemoteProof link"); return cb(err); }; })(this)); }; RemoteProof.prototype.is_self_sig = function() { return true; }; return RemoteProof; })(Link); Track = (function(_super) { __extends(Track, _super); function Track() { return Track.__super__.constructor.apply(this, arguments); } Track.prototype.to_table_obj = function() { var ret; ret = this.body().track; ret.ctime = this.ctime(); return ret; }; Track.prototype.is_self_sig = function() { return true; }; Track.prototype.condense = function() { return this.body().track.basics.username; }; Track.prototype.type_str = function() { return "track"; }; Track.prototype.insert_into_table = function(_arg) { var id, opts, path, table, _ref3, _ref4; table = _arg.table, opts = _arg.opts; log.debug("+ Track::insert_into_table " + (this.sig_id())); if ((id = (_ref3 = this.body()) != null ? (_ref4 = _ref3.track) != null ? _ref4.id : void 0 : void 0) == null) { log.warn("Missing track in signature"); log.debug("Full JSON in signature:"); log.debug(this.payload_json_str()); } else { path = [this.sig_type(), id]; if (opts.show_revoked) { path.push(this.seqno()); } table.insert_path(path, this); } return log.debug("- Track::insert_into_table " + (this.sig_id()) + " (uid=" + id + ")"); }; return Track; })(Link); Cryptocurrency = (function(_super) { __extends(Cryptocurrency, _super); function Cryptocurrency() { return Cryptocurrency.__super__.constructor.apply(this, arguments); } Cryptocurrency.prototype.to_cryptocurrency = function(opts) { var _ref3; return (_ref3 = this.body()) != null ? _ref3.cryptocurrency : void 0; }; Cryptocurrency.prototype.condense = function() { var d, ret; d = this.body().cryptocurrency; ret = {}; ret[d.type] = d.address; return ret; }; Cryptocurrency.prototype.type_str = function() { return "currency"; }; Cryptocurrency.prototype.is_revocable = function() { return true; }; Cryptocurrency.prototype.display_cryptocurrency = function(opts, cb) { var cc, msg; cc = this.to_cryptocurrency(opts); msg = [BTC, cc.type, colors.green(cc.address)]; log.lconsole("error", log["package"]().INFO, msg.join(' ')); return cb(null); }; Cryptocurrency.prototype.insert_into_table = function(_arg) { var err, id, index, opts, path, ret, table, _ref3, _ref4, _ref5; table = _arg.table, index = _arg.index, opts = _arg.opts; log.debug("+ Cryptocurrency::insert_into_table " + (this.sig_id())); if ((id = (_ref3 = this.body()) != null ? (_ref4 = _ref3.cryptocurrency) != null ? _ref4.address : void 0 : void 0) == null) { log.warn("Missing Cryptocurrency address"); log.debug("Full JSON in signature:"); log.debug(this.payload_json_str()); } else if ((_ref5 = bitcoyne.address.check(id, { version: ACCTYPES }), err = _ref5[0], ret = _ref5[1], _ref5) == null) { log.error("Error in checking cryptocurrency address: " + id); } else if (err != null) { log.warn("Error in cryptocurrency address: " + err.message); } else { path = [this.sig_type(), ret.version]; if (opts != null ? opts.show_revoked : void 0) { path.push(this.seqno()); } table.insert_path(path, this); } return log.debug("- Cryptocurrency::insert_into_table " + (this.sig_id())); }; return Cryptocurrency; })(Link); Revoke = (function(_super) { __extends(Revoke, _super); function Revoke() { return Revoke.__super__.constructor.apply(this, arguments); } Revoke.prototype.insert_into_table = function(_arg) { var index; index = _arg.index; log.debug("+ Revoke::insert_into_table"); return log.debug("- Revoke::insert_into_table"); }; return Revoke; })(Link); Untrack = (function(_super) { __extends(Untrack, _super); function Untrack() { return Untrack.__super__.constructor.apply(this, arguments); } Untrack.prototype.insert_into_table = function(_arg) { var id, index, link, links, opts, table, _i, _len, _ref3, _ref4, _ref5; table = _arg.table, index = _arg.index, opts = _arg.opts; log.debug("+ Untrack::insert_into_table"); if ((id = (_ref3 = this.body()) != null ? (_ref4 = _ref3.untrack) != null ? _ref4.id : void 0 : void 0) == null) { log.warn("Mssing untrack in signature: " + (this.payload_json_str())); } else if ((link = (_ref5 = table.get(ST.TRACK)) != null ? _ref5.get(id) : void 0) == null) { log.debug("Unexpected untrack of " + id + " in signature chain"); } else if (!(link.is_leaf()) && !(opts != null ? opts.show_revoked : void 0)) { log.warn("Unexpected multi-follow"); } else { links = link.is_leaf() ? [link] : link.flatten(); for (_i = 0, _len = links.length; _i < _len; _i++) { link = links[_i]; if (link.is_revoked()) { log.debug("| Tracking was already revoked for " + id + " (ignoring untrack)"); } else { link.revoke(); } } } return log.debug("- Untrack::insert_into_table"); }; return Untrack; })(Link); exports.LinkTable = LinkTable = (function() { function LinkTable(table) { this.table = table != null ? table : {}; } LinkTable.prototype.insert = function(key, value) { return this.table[key] = value; }; LinkTable.prototype.insert_path = function(path, value) { var d, k, v, _i, _len, _ref3; d = this; _ref3 = path.slice(0, -1); for (_i = 0, _len = _ref3.length; _i < _len; _i++) { k = _ref3[_i]; if ((v = d.get(k)) == null) { v = new LinkTable(); d.insert(k, v); } d = v; } return d.insert(path.slice(-1)[0], value); }; LinkTable.prototype.get = function(key) { return this.table[key]; }; LinkTable.prototype.keys = function() { return Object.keys(this.table); }; LinkTable.prototype.get_path = function(path) { var p, v, _i, _len; v = this; for (_i = 0, _len = path.length; _i < _len; _i++) { p = path[_i]; if (v != null) { v = v.get(p); } } return v; }; LinkTable.prototype.remove = function(key) { return delete this.table[key]; }; LinkTable.prototype.to_dict = function() { return this.table; }; LinkTable.prototype.is_leaf = function() { return false; }; LinkTable.prototype.walk = function(_arg) { var fn, k, v, _ref3, _results; fn = _arg.fn; _ref3 = this.table; _results = []; for (k in _ref3) { v = _ref3[k]; _results.push(v.walk({ fn: fn, parent: this, key: k })); } return _results; }; LinkTable.prototype.flatten = function() { var fn, out; out = []; fn = function(_arg) { var key, parent, value; key = _arg.key, value = _arg.value, parent = _arg.parent; return out.push(value); }; this.walk({ fn: fn }); return out; }; LinkTable.prototype.prune = function(prune_condition) { var fn; fn = function(_arg) { var key, parent, value; key = _arg.key, value = _arg.value, parent = _arg.parent; if (prune_condition(value)) { return parent.remove(key); } }; return this.walk({ fn: fn }); }; LinkTable.prototype.select = function(keys) { var k, out, _i, _len; out = new LinkTable; for (_i = 0, _len = keys.length; _i < _len; _i++) { k = keys[_i]; out.insert(k, this.get(k)); } return out; }; return LinkTable; })(); }).call(this);