Skip to content

Instantly share code, notes, and snippets.

@oconnore
Last active December 30, 2015 22:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oconnore/7896810 to your computer and use it in GitHub Desktop.
Save oconnore/7896810 to your computer and use it in GitHub Desktop.
Allow enumeration of harmony collections in node.js (relies on generators and non-enumerable collections).
// AMD header
if (typeof define !== 'function') {
var define = require('amdefine')(module);
}
define(function() {
'use strict';
var priv = new WeakMap();
var rMap = Map;
var rSet = Set;
function Node(value, prev, next) {
this.value = value;
this.prev = prev;
this.next = next;
}
function Sequence(iter) {
var p = {};
priv.set(this, p);
p.sequence = null;
p.nodeMap = new rMap();
if (iter) {
for (var i of iter) {
this.add.apply(this, i);
}
}
}
Sequence.prototype = {
constructor: Sequence,
clear: function clear() {
var p = priv.get(this);
p.sequence = null;
p.nodeMap.clear();
},
get size() {
var p = priv.get(this);
return p.nodeMap.size;
},
add: function set(key, value) {
var p = priv.get(this);
if (!p.nodeMap.has(key)) {
var node = new Node([key, value], null, p.sequence);
if (p.sequence) {
p.sequence.prev = node;
}
p.sequence = node;
p.nodeMap.set(key, node);
} else {
var node = p.nodeMap.get(key);
node.value = [key, value];
}
},
has: function has(key) {
var p = priv.get(this);
return p.nodeMap.has(key);
},
get: function get(key) {
var p = priv.get(this);
if (p.nodeMap.has(key)) {
return p.nodeMap.get(key).value[1];
}
},
delete: function _delete(key) {
var p = priv.get(this);
if (p.nodeMap.has(key)) {
var node = p.nodeMap.get(key);
var prev = node.prev, next = node.next;
if (prev) {
prev.next = next;
}
if (next) {
next.prev = prev;
}
p.nodeMap.delete(key);
return true;
}
return false;
},
entries: function* entries() {
var p = priv.get(this);
var cur = p.sequence;
while (cur) {
var tmp = cur;
cur = cur.next;
yield tmp.value;
}
},
keys: function*() {
for (var i of this.entries()) {
yield i[0];
}
},
values: function*() {
for (var i of this.entries()) {
yield i[1];
}
},
forEach: function(caller, cb, thisArg) {
if (typeof cb === 'function') {
for (var i of this.entries()) {
cb.call(thisArg, i[1], i[0], caller);
}
}
}
};
function bindHelper(fn) {
var myself = this;
return function() {
var self = myself || this;
var p = priv.get(self);
return fn.apply(p.sequence, Array.prototype.slice.call(arguments));
}
}
function EnumMap(iter) {
var p = {};
priv.set(this, p);
p.sequence = new Sequence(iter);
}
EnumMap.prototype = {
constructor: EnumMap,
get size() {
var p = priv.get(this);
return p.sequence.size;
},
has: bindHelper(Sequence.prototype.has),
get: bindHelper(Sequence.prototype.get),
delete: bindHelper(Sequence.prototype.delete),
clear: bindHelper(Sequence.prototype.clear),
set: bindHelper(Sequence.prototype.add),
entries: bindHelper(Sequence.prototype.entries),
keys: bindHelper(Sequence.prototype.keys),
values: bindHelper(Sequence.prototype.values),
forEach: function() {
bindHelper.call(this, Sequence.prototype.forEach).bind(null, this).apply(null,
arguments);
}
}
global.Map = EnumMap;
function EnumSet(iter) {
var p = {};
priv.set(this, p);
p.sequence = new Sequence(iter);
}
EnumSet.prototype = {
constructor: EnumSet,
get size() {
var p = priv.get(this);
return p.sequence.size;
},
has: bindHelper(Sequence.prototype.has),
get: bindHelper(Sequence.prototype.get),
delete: bindHelper(Sequence.prototype.delete),
clear: bindHelper(Sequence.prototype.clear),
add: (function() {
var helper = bindHelper(Sequence.prototype.add);
return function add(value) {
helper.call(this, value, value);
};
})(),
entries: bindHelper(Sequence.prototype.entries),
keys: bindHelper(Sequence.prototype.keys),
values: bindHelper(Sequence.prototype.values),
forEach: function() {
bindHelper.call(this, Sequence.prototype.forEach).bind(null, this).apply(
null, arguments);
}
}
global.Set = EnumSet;
return {
Map: EnumMap,
Set: EnumSet
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment