weak-set.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. module.metadata = {
  5. "stability": "experimental"
  6. };
  7. "use strict";
  8. const { Cu } = require("chrome");
  9. function makeGetterFor(Type) {
  10. let cache = new WeakMap();
  11. return function getFor(target) {
  12. if (!cache.has(target))
  13. cache.set(target, new Type());
  14. return cache.get(target);
  15. }
  16. }
  17. let getLookupFor = makeGetterFor(WeakMap);
  18. let getRefsFor = makeGetterFor(Set);
  19. function add(target, value) {
  20. if (has(target, value))
  21. return;
  22. getLookupFor(target).set(value, true);
  23. getRefsFor(target).add(Cu.getWeakReference(value));
  24. }
  25. exports.add = add;
  26. function remove(target, value) {
  27. getLookupFor(target).delete(value);
  28. }
  29. exports.remove = remove;
  30. function has(target, value) {
  31. return getLookupFor(target).has(value);
  32. }
  33. exports.has = has;
  34. function clear(target) {
  35. getLookupFor(target).clear();
  36. getRefsFor(target).clear();
  37. }
  38. exports.clear = clear;
  39. function iterator(target) {
  40. let refs = getRefsFor(target);
  41. for (let ref of refs) {
  42. let value = ref.get();
  43. // If `value` is already gc'ed, it would be `null`.
  44. // The `has` function is using a WeakMap as lookup table, so passing `null`
  45. // would raise an exception because WeakMap accepts as value only non-null
  46. // object.
  47. // Plus, if `value` is already gc'ed, we do not have to take it in account
  48. // during the iteration, and remove it from the references.
  49. if (value !== null && has(target, value))
  50. yield value;
  51. else
  52. refs.delete(ref);
  53. }
  54. }
  55. exports.iterator = iterator;