Skip to content

Instantly share code, notes, and snippets.

@teramako
Last active December 15, 2015 02:28
Show Gist options
  • Save teramako/5187008 to your computer and use it in GitHub Desktop.
Save teramako/5187008 to your computer and use it in GitHub Desktop.
WeakReference な Set オブジェクトを無理やり作ってみた。Firefox のSystem権限(Components.utils.getWeakReferenceを使用)が必要だけど。
(function(global) {
function mixin (aTarget, aSource) {
for (var key of Object.getOwnPropertyNames(aSource)) {
var desc = Object.getOwnPropertyDescriptor(aSource, key);
desc.enumerable = false;
Object.defineProperty(aTarget, key, desc);
}
return aTarget;
}
/**
* @class
* @param {Object[]} items
*/
function WeakSet (...items) {
mixin(this, { w: new WeakMap, s: new Set, });
for (var item of items) {
if (Object(item) === Object(item))
this.add(item);
}
}
mixin(WeakSet.prototype, {
/**
* @param {Object} item
*/
add: function (item) {
if (this.has(item)
return;
// 弱参照なオブジェクトを得る
var value = Cu.getWeakReference(item);
// 追加するオブジェクトをキーとしてWeakMapに格納
this.w.set(item, value);
// イテレート可能にするために、弱参照オブジェクトを格納
this.s.add(value);
},
/**
* @param {Object} item
* @return {Boolean}
*/
has: function (item) { return this.w.has(item); },
/**
* @param {Object} item
*/
delete: function (item) {
if (this.w.has(item)) {
this.s.delete(this.w.get(item));
this.w.delete(item);
}
},
/**
* delete all items
*/
clear:function () {
this.s.clear();
this.w.clear();
},
/**
* @type {Number} items count
* @getter
* GC されている可能性があるので、一旦全て舐めてからカウントする
*/
get size() {
var i = 0, v;
for (v of this.s) {
if (v.get())
++i;
else
this.s.delete(v);
}
return i;
},
/**
* @return {Generator}
* GC 済みのものは削除する
*/
iterator: function() {
var v, item;
for (v of this.s) {
item = v.get();
if (item)
yield item;
else
this.s.delete(v);
}
},
});
global.WeakSet = WeakSet;
}(this));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment