Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

weak-ref-collections

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

weak-ref-collections - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

101

index.js

@@ -0,1 +1,6 @@

// In Node.js this is packaged into a module
// In the browser exports are bound directly to the window namespace
const global =
typeof exports !== 'undefined' && exports !== null ? exports : this
class WeakRefMap extends Map {

@@ -95,2 +100,96 @@ // Delete the corresponding key when object is collected

}
module.exports = WeakRefMap
// Custom Set with weakly held values (WeakSet does something else)
class WeakRefSet extends Set {
// Used to check existing membership of the underlying target
// Maps the target to its ref
#membership = new WeakMap()
// Delete the corresponding ref when object is collected
#registry = new FinalizationRegistry(ref => {
super.delete(ref)
})
// When generating with an iterable, use the modified add
// so that we generate weakrefs
constructor (iterable) {
super()
if (iterable) {
for (const value of iterable) {
this.add(value)
}
}
}
// When add wrap the target in a weakref instead
add (value) {
// If it is already contained then skip
if (this.#membership.has(value)) return this
// Otherwise mark the membership
// mark for clean up
// and store the reference
const ref = new WeakRef(value)
this.#membership.set(value, ref)
this.#registry.register(value, ref, ref)
return super.add(ref)
}
has (value) {
const ref = this.#membership.get(value)
if (typeof ref === 'undefined') return false
if (typeof ref.deref() === 'undefined') return false
return true
}
delete (value) {
const ref = this.#membership.get(value)
// Early return if nothing defined
if (typeof ref === 'undefined') return false
// Otherwise an entry was found
this.#membership.delete(value)
this.#registry.unregister(ref)
super.delete(ref)
// Only return a successful delete if ref was still live
if (typeof ref.deref() === 'undefined') return false
return true
}
clear () {
this.#membership = new WeakMap()
this.#registry = new FinalizationRegistry(ref => {
super.delete(ref)
})
return super.clear()
}
// Follows the map API convention but passes value twice instead of
// value and key
forEach (callback, context) {
for (const value of this) {
callback.call(context, value, value, this)
}
}
// Default iterator
// Iterates but only yields live references
* [Symbol.iterator] () {
for (const ref of super[Symbol.iterator]()) {
const value = ref.deref()
if (typeof value !== 'undefined') yield value
}
}
// The Set API follows a similar structure to Map despite lack of keys
// Returns an array of [value, value] pairs
* entries () {
for (const value of this) {
yield [value, value]
}
}
* keys () { yield * this }
* values () { yield * this }
}
global.WeakRefMap = WeakRefMap
global.WeakRefSet = WeakRefSet

17

package.json
{
"name": "weak-ref-collections",
"version": "1.0.0",
"description": "Iterable WeakMaps and WeakSets. Unlike WeakMap which stores keys weakly, this stores keys strongly but stores values using WeakRefs. Is fully iterable. Works just like a normal Map object but holds its values weakly and cleans itself up when its values are garbage collected.",
"version": "1.1.0",
"description": "Iterable WeakMaps and WeakSets. Provides WeakRefMap and WeakRefSet which store values using WeakRefs and clean themselves up when garbage collected.",
"main": "index.js",

@@ -18,13 +18,16 @@ "scripts": {

"type": "git",
"url": "git+https://github.com/fynyky/com.docker.devenvironments.code.git"
"url": "git+https://github.com/fynyky/weak-ref-collections.git"
},
"keywords": [
"weakref",
"weakmap",
"weakref",
"weak"
"weakset",
"weak",
"iterable",
"enumerable"
],
"bugs": {
"url": "https://github.com/fynyky/com.docker.devenvironments.code/issues"
"url": "https://github.com/fynyky/weak-ref-collections/issues"
},
"homepage": "https://github.com/fynyky/com.docker.devenvironments.code#readme"
"homepage": "https://github.com/fynyky/weak-ref-collections#readme"
}

@@ -1,8 +0,8 @@

# WeakRefMap
A Map of WeakRefs. Unlike WeakMap which stores keys weakly, this stores keys strongly but stores values using WeakRefs. Is fully iterable. Works just like a normal Map object but holds its values weakly and cleans itself up when its values are garbage collected.
# Weak Ref Collections
Iterable WeakMaps and WeakSets. Provides WeakRefMap and WeakRefSet which store values using WeakRefs and clean themselves up when garbage collected.
Follows the [Map API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
Unlike WeakMap which stores keys weakly, WeakRefMap stores keys strongly but stores values using WeakRefs. Is fully iterable. Works just like a normal Map object but holds its values weakly and cleans itself up when its values are garbage collected. Follows the [Map API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
```javascript
const WeakRefMap = require("weak-ref-map");
const { WeakRefMap } = require("weak-ref-collections");

@@ -16,3 +16,2 @@ weakRefMap = new WeakRefMap();

weakRefMap.forEach((value, key, map) => {});
// Supports iteration

@@ -23,2 +22,20 @@ for (const [key, value] of weakRefMap) {}

for (const value of weakRefMap.values()) {}
```
Similarly for WeakRefSet is fully iterable unlike WeakSet. Works just like a normal Set object but holds its values weakly and cleans itself up when its values are garbage collected. Follows the [Set API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
```javascript
const { WeakRefSet } = require("weak-ref-set");
weakRefSet = new WeakRefSet();
const element = {"bar": 1};
weakRefSet.add(element);
weakRefSet.has(element); // true
weakRefSet.delete(element); // true
weakRefSet.clear(); // undefined
weakRefSet.forEach((value, alsoValue, set) => {});
// Supports iteration
for (const [value, alsoValue] of weakRefSet) {}
for (const [value, alsoValue] of weakRefSet.entries()) {}
for (const value of weakRefSet.keys()) {}
for (const value of weakRefSet.values()) {}
```
/* global describe, it */
const assert = require('assert')
const WeakRefMap = require('./index.js')
const { WeakRefMap, WeakRefSet } = require('./index.js')
describe('WeakValueMap', () => {
describe('WeakRefMap', () => {
let weakRefMap, regularMap

@@ -32,13 +32,13 @@ const normalizeMap = (a) => JSON.stringify(Array.from(a))

it('can have a value gotten', () => {
const weakValueResult = weakRefMap.get('foo')
const weakRefResult = weakRefMap.get('foo')
const regularResult = regularMap.get('foo')
assert(JSON.stringify(weakValueResult) === '{"qoo":1}')
assert(JSON.stringify(weakValueResult) === JSON.stringify(regularResult))
assert(JSON.stringify(weakRefResult) === '{"qoo":1}')
assert(JSON.stringify(weakRefResult) === JSON.stringify(regularResult))
})
it('can fails to get a nonexistent value', () => {
const weakValueResult = weakRefMap.get('food')
const weakRefResult = weakRefMap.get('food')
const regularResult = regularMap.get('food')
assert(typeof weakValueResult === 'undefined')
assert(JSON.stringify(weakValueResult) === JSON.stringify(regularResult))
assert(typeof weakRefResult === 'undefined')
assert(JSON.stringify(weakRefResult) === JSON.stringify(regularResult))
})

@@ -75,3 +75,3 @@

]
let weakValueResult = ''
let weakRefResult = ''
let regularResult = ''

@@ -81,3 +81,3 @@ weakRefMap = new WeakRefMap(seedData)

for (const [key, value] of weakRefMap) {
weakValueResult += JSON.stringify([key, value])
weakRefResult += JSON.stringify([key, value])
}

@@ -87,11 +87,11 @@ for (const [key, value] of regularMap) {

}
assert(weakValueResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakValueResult === regularResult)
assert(weakRefResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakRefResult === regularResult)
})
it('can use forEach', () => {
let weakValueResult = ''
let weakRefResult = ''
let regularResult = ''
weakRefMap.forEach((value, key) => {
weakValueResult += JSON.stringify([key, value])
weakRefResult += JSON.stringify([key, value])
})

@@ -101,11 +101,11 @@ regularMap.forEach((value, key) => {

})
assert(weakValueResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakValueResult === regularResult)
assert(weakRefResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakRefResult === regularResult)
})
it('can iterate over entries', () => {
let weakValueResult = ''
let weakRefResult = ''
let regularResult = ''
for (const [key, value] of weakRefMap.entries()) {
weakValueResult += JSON.stringify([key, value])
weakRefResult += JSON.stringify([key, value])
}

@@ -115,11 +115,11 @@ for (const [key, value] of regularMap) {

}
assert(weakValueResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakValueResult === regularResult)
assert(weakRefResult === '["foo",{"qoo":1}]["bar",{"qar":2}]')
assert(weakRefResult === regularResult)
})
it('can iterate over keys', () => {
let weakValueResult = ''
let weakRefResult = ''
let regularResult = ''
for (const key of weakRefMap.keys()) {
weakValueResult += JSON.stringify(key)
weakRefResult += JSON.stringify(key)
}

@@ -129,11 +129,11 @@ for (const key of regularMap.keys()) {

}
assert(weakValueResult === '"foo""bar"')
assert(weakValueResult === regularResult)
assert(weakRefResult === '"foo""bar"')
assert(weakRefResult === regularResult)
})
it('can iterate over values', () => {
let weakValueResult = ''
let weakRefResult = ''
let regularResult = ''
for (const value of weakRefMap.values()) {
weakValueResult += JSON.stringify(value)
weakRefResult += JSON.stringify(value)
}

@@ -143,5 +143,137 @@ for (const value of regularMap.values()) {

}
assert(weakValueResult === '{"qoo":1}{"qar":2}')
assert(weakValueResult === regularResult)
assert(weakRefResult === '{"qoo":1}{"qar":2}')
assert(weakRefResult === regularResult)
})
})
describe('WeakRefSet', () => {
let weakRefSet, regularSet
const normalizeSet = (a) => JSON.stringify(Array.from(a))
it('can be created', () => {
weakRefSet = new WeakRefSet()
regularSet = new Set()
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
})
it('can be created with iterable', () => {
const seedData = [{ foo: 1 }, { bar: 2 }, { baz: 3 }]
weakRefSet = new WeakRefSet(seedData)
regularSet = new Set(seedData)
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
})
it('can have a value added', () => {
weakRefSet.add({ qaz: 4 })
regularSet.add({ qaz: 4 })
assert(normalizeSet(weakRefSet) === '[{"foo":1},{"bar":2},{"baz":3},{"qaz":4}]')
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
})
const newElement = { qux: 5 }
it('can have a value added only once', () => {
weakRefSet.add(newElement)
weakRefSet.add(newElement)
regularSet.add(newElement)
regularSet.add(newElement)
assert(normalizeSet(weakRefSet) === '[{"foo":1},{"bar":2},{"baz":3},{"qaz":4},{"qux":5}]')
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
})
it('can check if it has element', () => {
assert(weakRefSet.has(newElement) === true)
})
it('can check if it does not have element', () => {
assert(weakRefSet.has({}) === false)
})
it('can delete an element', () => {
let weakDidDelete = weakRefSet.delete(newElement)
let regularDidDelete = regularSet.delete(newElement)
assert(normalizeSet(weakRefSet) === '[{"foo":1},{"bar":2},{"baz":3},{"qaz":4}]')
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
assert(weakDidDelete === true)
weakDidDelete = weakRefSet.delete(newElement)
regularDidDelete = regularSet.delete(newElement)
assert(weakDidDelete === false)
assert(weakDidDelete === regularDidDelete)
})
it('can clear itself', () => {
weakRefSet.clear()
regularSet.clear()
assert(normalizeSet(weakRefSet) === '[]')
assert(normalizeSet(weakRefSet) === normalizeSet(regularSet))
})
it('can forEach', () => {
const seedData = [{ foo: 1 }, { bar: 2 }, { baz: 3 }]
weakRefSet = new WeakRefSet(seedData)
regularSet = new Set(seedData)
let weakRefResult = ''
let regularResult = ''
weakRefSet.forEach((value, key, set) => {
weakRefResult += (JSON.stringify(value) + JSON.stringify(key))
assert(set === weakRefSet)
})
regularSet.forEach((value, key, set) => {
regularResult += (JSON.stringify(value) + JSON.stringify(key))
assert(set === regularSet)
})
assert(weakRefResult === '{"foo":1}{"foo":1}{"bar":2}{"bar":2}{"baz":3}{"baz":3}')
assert(weakRefResult === regularResult)
})
it('can iterate normally', () => {
let weakRefResult = ''
let regularResult = ''
for (const value of weakRefSet) {
weakRefResult += JSON.stringify(value)
}
for (const value of regularSet) {
regularResult += JSON.stringify(value)
}
assert(weakRefResult === '{"foo":1}{"bar":2}{"baz":3}')
assert(weakRefResult === regularResult)
})
it('can iterate over entries', () => {
let weakRefResult = ''
let regularResult = ''
for (const value of weakRefSet.entries()) {
weakRefResult += JSON.stringify(value)
}
for (const value of regularSet.entries()) {
regularResult += JSON.stringify(value)
}
assert(weakRefResult === '[{"foo":1},{"foo":1}][{"bar":2},{"bar":2}][{"baz":3},{"baz":3}]')
assert(weakRefResult === regularResult)
})
it('can iterate over keys', () => {
let weakRefResult = ''
let regularResult = ''
for (const value of weakRefSet.keys()) {
weakRefResult += JSON.stringify(value)
}
for (const value of regularSet.keys()) {
regularResult += JSON.stringify(value)
}
assert(weakRefResult === '{"foo":1}{"bar":2}{"baz":3}')
assert(weakRefResult === regularResult)
})
it('can iterate over values', () => {
let weakRefResult = ''
let regularResult = ''
for (const value of weakRefSet.values()) {
weakRefResult += JSON.stringify(value)
}
for (const value of regularSet.values()) {
regularResult += JSON.stringify(value)
}
assert(weakRefResult === '{"foo":1}{"bar":2}{"baz":3}')
assert(weakRefResult === regularResult)
})
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc