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

worker_map

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

worker_map - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

. prettierrc

13

package.json
{
"name": "worker_map",
"description": "Tread-safe map structure for worker_threads.",
"version": "0.0.3",
"version": "0.0.4",
"main": "./src/worker_hash.js",
"scripts": {
"test": "node --test ./test"
"test": "node --test ./test",
"lint": "eslint ./**/*.js"
},
"devDependencies": {
"eslint": "8.49.0",
"eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "9.0.0",
"eslint-plugin-prettier": "5.0.0",
"eslint-plugin-import": "2.28.1",
"prettier": "3.0.3"
},
"homepage": "https://github.com/nairihar/worker_map",

@@ -10,0 +19,0 @@ "keywords": [

26

README.md
![](https://img.shields.io/badge/dependencies-none-brightgreen.svg)
![](https://img.shields.io/npm/l/worker_map.svg)
![](https://img.shields.io/npm/dt/worker_map.svg)
[![Known Vulnerabilities](https://snyk.io/test/github/nairihar/worker_map/badge.svg)](https://snyk.io/test/github/nairihar/funthreads)
![](https://img.shields.io/npm/l/worker_map.svg)

@@ -59,9 +58,11 @@ # worker_map

### `map.get(key):`
Worker_map is much like JavaScript's regular Map.
### `map.set(key, value)`
```
const name = map.get('name');
map.set('name', 'John'); // true
```
### `map.set(key, value)`
### `map.get(key):`
```
map.set('name', 'John');
const name = map.get('name'); // 'John'
```

@@ -71,3 +72,3 @@ ### `map.delete(key):`

map.delete('name'); // true
map.delete('something'); // false because doesn't exist
map.delete('something'); // false because it doesn't exist
```

@@ -94,12 +95,16 @@ ### `map.has(key)`

```
const mapObject = map.toObject();
const mapObject = map.toObject(); // { ... }
mapObject.name; // 'John'
```
#### TODO
## Contributing
See the [contributing guide](https://github.com/nairihar/worker_map/blob/main/CONTRIBUTING.md) for detailed instructions on how to get started with our project.
**TODO**
- `map.clear()`
- `map.entries()`
- `map.forEach()`
- Currently, when performing an action on the map, it temporarily locks the entire map, loads the necessary data, and then unlocks the map, allowing other threads to access it. However, this approach is suboptimal. It would be more efficient if we could lock only the specific portion of memory required for the particular operation.
## Limitations

@@ -110,2 +115,1 @@

2. **NaN Values:** NaN values are not supported.

@@ -5,21 +5,25 @@ const LOCKED = 1;

function lock(buffer) {
for(;;) {
if (Atomics.compareExchange(buffer, 0, UNLCOKED, LOCKED) == UNLCOKED) {
return;
}
Atomics.wait(buffer, 0, LOCKED);
for (;;) {
if (Atomics.compareExchange(buffer, 0, UNLCOKED, LOCKED) === UNLCOKED) {
return;
}
Atomics.wait(buffer, 0, LOCKED);
}
}
function unlock(buffer) {
if (Atomics.compareExchange(buffer, 0, LOCKED, UNLCOKED) != LOCKED) {
throw new Error("Mutex is in inconsistent state: unlock on unlocked Mutex.");
}
if (Atomics.compareExchange(buffer, 0, LOCKED, UNLCOKED) !== LOCKED) {
throw new Error(
"Mutex is in inconsistent state: unlock on unlocked Mutex.",
);
}
Atomics.notify(buffer, 0, 1);
Atomics.notify(buffer, 0, 1);
}
module.exports = {
lock, unlock,
LOCKED, UNLCOKED,
};
lock,
unlock,
LOCKED,
UNLCOKED,
};

@@ -1,5 +0,5 @@

const decoder = new TextDecoder('utf8');
const encoder = new TextEncoder('utf8');
const decoder = new TextDecoder("utf8");
const encoder = new TextEncoder("utf8");
const { lock, unlock, UNLCOKED } = require('./mutex');
const { lock, unlock, UNLCOKED } = require("./mutex");

@@ -9,209 +9,210 @@ const DEFAULT_OBJECT_BYTE_LENGTH = 4096; // total characters of stringified object (2^12)

const MAP_SIZE = Symbol('MAP_SIZE');
const PLAIN_OBJECT = Symbol('PLAIN_OBJECT');
const VALUE_BUFFER = Symbol('VALUE_BUFFER');
const SHARED_BUFFER = Symbol('SHARED_BUFFER');
const MAP_SIZE = Symbol("MAP_SIZE");
const PLAIN_OBJECT = Symbol("PLAIN_OBJECT");
const VALUE_BUFFER = Symbol("VALUE_BUFFER");
const SHARED_BUFFER = Symbol("SHARED_BUFFER");
function getSharedMemoryBuffer(sharedBuffer) {
return new Int32Array(sharedBuffer);
return new Int32Array(sharedBuffer);
}
function calculateUsedBufferLength(valueBuffer) {
// exclude first item
return valueBuffer.reduce((acc, value) => (
acc + (value ? 1 : 0)
), -1);
// exclude first item
return valueBuffer.reduce((acc, value) => acc + (value ? 1 : 0), -1);
}
function loadPlainSharedObject(valueBuffer) {
const usedBufferLength = calculateUsedBufferLength(valueBuffer);
const decodeBuffer = new Uint8Array(usedBufferLength);
const usedBufferLength = calculateUsedBufferLength(valueBuffer);
const decodeBuffer = new Uint8Array(usedBufferLength);
for (let i = 1; i <= usedBufferLength; i++) {
if (valueBuffer[i]) {
decodeBuffer[i - 1] = valueBuffer[i];
}
for (let i = 1; i <= usedBufferLength; i++) {
if (valueBuffer[i]) {
decodeBuffer[i - 1] = valueBuffer[i];
}
}
return JSON.parse(
decoder.decode(decodeBuffer)
);
return JSON.parse(decoder.decode(decodeBuffer));
}
function safeLoadSharedObject(valueBuffer) {
lock(valueBuffer);
lock(valueBuffer);
const sharedObject = loadPlainSharedObject(valueBuffer)
const sharedObject = loadPlainSharedObject(valueBuffer);
unlock(valueBuffer);
unlock(valueBuffer);
return sharedObject;
return sharedObject;
}
function calculateStringByteLength(string) {
return encoder.encode(string).length;
return encoder.encode(string).length;
}
function saveObjectInBuffer(sharedObject, valueBuffer, objString) {
objString ??= JSON.stringify(sharedObject);
objString ??= JSON.stringify(sharedObject);
const stringByteLength = calculateStringByteLength(objString);
const encodeBuffer = new Uint8Array(stringByteLength);
encoder.encodeInto(objString, encodeBuffer)
const stringByteLength = calculateStringByteLength(objString);
const encodeBuffer = new Uint8Array(stringByteLength);
encoder.encodeInto(objString, encodeBuffer);
for (let i = 0; i < stringByteLength; i++) {
valueBuffer[i + 1] = encodeBuffer[i];
}
for (let i = 0; i < stringByteLength; i++) {
valueBuffer[i + 1] = encodeBuffer[i];
}
for (let j = stringByteLength + 1; j < valueBuffer.length; j++) {
valueBuffer[j] = 0;
}
for (let j = stringByteLength + 1; j < valueBuffer.length; j++) {
valueBuffer[j] = 0;
}
}
function adjustSharedBufferGrow(sharedBuffer, sharedObject) {
const objectByteLength = calculateStringByteLength(JSON.stringify(sharedObject));
const diff = (sharedBuffer.byteLength / 4) - objectByteLength;
const objectByteLength = calculateStringByteLength(
JSON.stringify(sharedObject),
);
const diff = sharedBuffer.byteLength / 4 - objectByteLength;
if (diff <= 0) {
if (!sharedBuffer.grow) {
throw new Error(
"No more space, create a new bigger shared object or use Node >= v20 to support auto grow.",
);
}
if (diff <= 0) {
if (!sharedBuffer.grow) {
throw new Error('No more space, create a new bigger shared object or use Node >= v20 to support auto grow.');
}
// byte length of Int32Array should be a multiple of 4
const growedLength = sharedBuffer.byteLength + 4 * Math.abs(diff) + 64;
// byte length of Int32Array should be a multiple of 4
let growedLength = sharedBuffer.byteLength + (4 * Math.abs(diff)) + 64;
sharedBuffer.grow(growedLength);
}
sharedBuffer.grow(growedLength);
}
}
function WorkerMap(providedObject, length=DEFAULT_OBJECT_BYTE_LENGTH) {
if (providedObject instanceof SharedArrayBuffer) {
const sharedBuffer = providedObject;
function WorkerMap(providedObject, length = DEFAULT_OBJECT_BYTE_LENGTH) {
if (providedObject instanceof SharedArrayBuffer) {
const sharedBuffer = providedObject;
const valueBuffer = getSharedMemoryBuffer(sharedBuffer);
this[SHARED_BUFFER] = sharedBuffer;
this[VALUE_BUFFER] = valueBuffer;
this[MAP_SIZE] = this.keys().length;
const valueBuffer = getSharedMemoryBuffer(sharedBuffer);
return this;
}
this[SHARED_BUFFER] = sharedBuffer;
this[VALUE_BUFFER] = valueBuffer;
this[MAP_SIZE] = this.keys().length;
const initialObject = providedObject || {};
const stringifiedObject = JSON.stringify(initialObject);
return this;
}
length += length % 4; // should be a multiple of 4
const initialObject = providedObject || {};
const stringifiedObject = JSON.stringify(initialObject);
if (stringifiedObject.length >= length) {
length = 4 * stringifiedObject.length;
}
length += length % 4; // should be a multiple of 4
const sharedBuffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * length, {
maxByteLength: MAX_OBJECT_BYTE_LENGTH,
});
const valueBuffer = getSharedMemoryBuffer(sharedBuffer);
if (stringifiedObject.length >= length) {
length = 4 * stringifiedObject.length;
}
valueBuffer[0] = UNLCOKED; // first value used for locking and unlocking
const sharedBuffer = new SharedArrayBuffer(
Int32Array.BYTES_PER_ELEMENT * length,
{
maxByteLength: MAX_OBJECT_BYTE_LENGTH,
},
);
const valueBuffer = getSharedMemoryBuffer(sharedBuffer);
saveObjectInBuffer(null, valueBuffer, stringifiedObject);
valueBuffer[0] = UNLCOKED; // first value used for locking and unlocking
this[SHARED_BUFFER] = sharedBuffer;
this[VALUE_BUFFER] = valueBuffer;
this[MAP_SIZE] = 0;
saveObjectInBuffer(null, valueBuffer, stringifiedObject);
return this;
this[SHARED_BUFFER] = sharedBuffer;
this[VALUE_BUFFER] = valueBuffer;
this[MAP_SIZE] = 0;
return this;
}
WorkerMap.prototype.set = function (key, value) {
if (typeof key === 'function' || typeof value === 'function') {
return false;
}
if (typeof key === "function" || typeof value === "function") {
return false;
}
const valueBuffer = this[VALUE_BUFFER];
const sharedBuffer = this[SHARED_BUFFER];
const valueBuffer = this[VALUE_BUFFER];
const sharedBuffer = this[SHARED_BUFFER];
if (Number.isNaN(value) || value === undefined) {
value = null;
}
if (Number.isNaN(value) || value === undefined) {
value = null;
}
lock(valueBuffer);
lock(valueBuffer);
const sharedObject = loadPlainSharedObject(valueBuffer)
sharedObject[key] = value;
const sharedObject = loadPlainSharedObject(valueBuffer);
adjustSharedBufferGrow(sharedBuffer, sharedObject);
sharedObject[key] = value;
saveObjectInBuffer(sharedObject, valueBuffer);
adjustSharedBufferGrow(sharedBuffer, sharedObject);
this[MAP_SIZE] = Object.keys(sharedObject).length;
saveObjectInBuffer(sharedObject, valueBuffer);
unlock(valueBuffer);
this[MAP_SIZE] = Object.keys(sharedObject).length;
return true;
unlock(valueBuffer);
return true;
};
WorkerMap.prototype.get = function (key) {
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer)
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer);
if (key === PLAIN_OBJECT) {
return sharedObject;
}
if (key === PLAIN_OBJECT) {
return sharedObject;
}
return sharedObject[key];
return sharedObject[key];
};
WorkerMap.prototype.delete = function (key) {
const valueBuffer = this[VALUE_BUFFER];
const valueBuffer = this[VALUE_BUFFER];
lock(valueBuffer);
lock(valueBuffer);
const sharedObject = loadPlainSharedObject(valueBuffer)
if (sharedObject[key] === undefined) {
unlock(valueBuffer);
const sharedObject = loadPlainSharedObject(valueBuffer);
return false;
}
delete sharedObject[key];
if (sharedObject[key] === undefined) {
unlock(valueBuffer);
saveObjectInBuffer(sharedObject, valueBuffer);
return false;
}
unlock(valueBuffer);
delete sharedObject[key];
this[MAP_SIZE] = Object.keys(sharedObject).length;
saveObjectInBuffer(sharedObject, valueBuffer);
return true;
unlock(valueBuffer);
this[MAP_SIZE] = Object.keys(sharedObject).length;
return true;
};
WorkerMap.prototype.size = function (key) {
return this[MAP_SIZE];
WorkerMap.prototype.size = function () {
return this[MAP_SIZE];
};
WorkerMap.prototype.keys = function () {
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer)
return Object.keys(sharedObject);
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer);
return Object.keys(sharedObject);
};
WorkerMap.prototype.has = function (key) {
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer)
const valueBuffer = this[VALUE_BUFFER];
const sharedObject = safeLoadSharedObject(valueBuffer);
return sharedObject[key] !== undefined;
return sharedObject[key] !== undefined;
};
WorkerMap.prototype.toSharedBuffer = function () {
return this[SHARED_BUFFER];
return this[SHARED_BUFFER];
};
WorkerMap.prototype.toObject = function() {
return this.get(PLAIN_OBJECT);
WorkerMap.prototype.toObject = function () {
return this.get(PLAIN_OBJECT);
};
module.exports = { WorkerMap };
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