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

electrum-store

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

electrum-store - npm Package Compare versions

Comparing version 1.12.0 to 2.0.0

35

lib/store/state.js

@@ -14,2 +14,5 @@ 'use strict';

Object.freeze(emptyValues);
Object.freeze(secretKey);
function isPositiveInteger(value) {

@@ -64,5 +67,10 @@ if (typeof value === 'number') {

}
if (values.length === 0) {
if (isEmpty(values)) {
values = emptyValues; // optimize for values set to {}
}
} else {
Object.freeze(values);
for (let key of Object.getOwnPropertyNames(values)) {
State.freezeTop(values[key]);
}
}

@@ -391,2 +399,25 @@ this._id = id;

}
}, {
key: 'freeze',
value: function freeze(obj) {
if (Array.isArray(obj)) {
obj.forEach(x => State.freeze(x));
}
if (obj && typeof obj === 'object') {
Object.freeze(obj);
for (let key of Object.getOwnPropertyNames(obj)) {
State.freeze(obj[key]);
}
}
}
}, {
key: 'freezeTop',
value: function freezeTop(obj) {
if (Array.isArray(obj)) {
obj.forEach(x => State.freezeTop(x));
}
if (obj && typeof obj === 'object') {
Object.freeze(obj);
}
}
}]);

@@ -393,0 +424,0 @@

2

package.json
{
"name": "electrum-store",
"version": "1.12.0",
"version": "2.0.0",
"description": "Electrum store provides a store implementation tailored for Electrum.",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -119,3 +119,3 @@ # Electrum Store

expect (state.generation).to.equal (2);
expect (state.shouldUpdate (1)).to.be.false (); // provided gen=1 older than state.generation
expect (state.shouldUpdate (1)).to.be.false (); // provided gen=1 older than state.generation
expect (state.shouldUpdate (2)).to.be.true ();

@@ -140,3 +140,3 @@ expect (state.shouldUpdate (3)).to.be.true ();

expect (store.select ('a.b').get ('name')).to.equal ('foo');
expect (store.select ('a.b.c').get ('value')).to.equal ('bar');
expect (store.select ('a.b.c').get ('value')).to.equal ('bar');
```

@@ -301,2 +301,31 @@

## Setting values freezes them
When setting values on a state object, we do not want them to be
mutated arbitrarily by an external source (at least at the top
level).
In order to prevent mutation of values stored in a state object,
every value is automatically frozen (`Object.freeze()`):
```javascript
const state = State.create ('a').set ('x', {foo: 'bar'});
expect (Object.isFrozen (state.get ('x'))).to.be.true ();
expect (() => state.get ('x').foo = 'baz').to.throw ();
```
If the value is an array, the values of the array will also be
frozen (recursively for sub-arrays).
## Explicit freeze API
The `State` class exposes two methods to explicitly freeze
objects:
* `State.freeze(obj)` → freezes recursively the full object
tree.
* `State.freezeTop(obj)` → freezes the object; if it is an
array, then every item of the array will be frozen by calling
`freezeTop()` recursively.
## Mutate state in a store

@@ -303,0 +332,0 @@

@@ -33,2 +33,10 @@ 'use strict';

});
it ('freezes the initial values', () => {
const state = State.create ('a', {o: {foo: 'bar'}});
const ref = state.get ('o');
expect (ref).to.deep.equal ({foo: 'bar'});
expect (() => ref.foo = 'baz').to.throw ();
expect (ref).to.deep.equal ({foo: 'bar'});
});
});

@@ -166,2 +174,49 @@

});
describe ('State.freeze()', () => {
it ('accepts plain values', () => {
expect (() => State.freeze (undefined)).to.not.throw ();
expect (() => State.freeze (1)).to.not.throw ();
expect (() => State.freeze ('hello')).to.not.throw ();
expect (() => State.freeze (function (x) {
return x;
})).to.not.throw ();
});
it ('freezes deeply an object', () => {
const obj = {x: 1, y: {a: ['A', [{q: 'Q'}]]}};
State.freeze (obj);
expect (Object.isFrozen (obj)).to.be.true ();
expect (Object.isFrozen (obj.x)).to.be.true ();
expect (Object.isFrozen (obj.y)).to.be.true ();
expect (Object.isFrozen (obj.y.a)).to.be.true ();
expect (Object.isFrozen (obj.y.a[0])).to.be.true ();
expect (Object.isFrozen (obj.y.a[1])).to.be.true ();
expect (Object.isFrozen (obj.y.a[1][0])).to.be.true ();
expect (Object.isFrozen (obj.y.a[1][0].q)).to.be.true ();
// Just to make sure...
expect (() => obj.y.a[1][0].r = 'R').to.throw ();
});
});
describe ('State.freezeTop()', () => {
it ('freezes top level only', () => {
const obj = {x: 1, y: {a: 'A'}};
State.freezeTop (obj);
expect (Object.isFrozen (obj)).to.be.true ();
expect (Object.isFrozen (obj.x)).to.be.true ();
expect (Object.isFrozen (obj.y)).to.be.false ();
expect (() => obj.y.a = 'B').to.not.throw ();
});
it ('freezes top level only, but walks arrays', () => {
const obj = [{x: 1, y: {a: 'A'}}];
State.freezeTop (obj);
expect (Object.isFrozen (obj)).to.be.true ();
expect (Object.isFrozen (obj[0])).to.be.true ();
expect (Object.isFrozen (obj[0].x)).to.be.true ();
expect (Object.isFrozen (obj[0].y)).to.be.false ();
expect (() => obj[0].y.a = 'B').to.not.throw ();
});
});
});

@@ -40,3 +40,3 @@ 'use strict';

describe ('set()', () => {
it ('produces new instance of state', () => {
it ('produces new instance of state (with key)', () => {
const state1 = State.create ('a', {a: 1});

@@ -49,3 +49,3 @@ const state2 = state1.set ('b', 2);

it ('produces new instance of state', () => {
it ('produces new instance of state (without key)', () => {
const state1 = State.create ('a', {'': 'x'});

@@ -56,2 +56,44 @@ const state2 = state1.set ('y');

});
it ('freezes an object value', () => {
const state = State.create ('a').set ('x', {a: 1});
const ref = state.get ('x');
expect (ref).to.deep.equal ({a: 1});
expect (() => ref.a = 2).to.throw ();
expect (ref).to.deep.equal ({a: 1});
});
it ('freezes an array value', () => {
const state = State.create ('a').set ('x', [1, 2]);
const ref = state.get ('x');
expect (ref).to.deep.equal ([1, 2]);
expect (() => ref.a.push (3)).to.throw ();
expect (ref).to.deep.equal ([1, 2]);
});
it ('freezes the top level of an object', () => {
const state = State.create ('a').set ('x', [{a: 1}, {b: {x: 2}}]);
const ref = state.get ('x');
expect (Object.isFrozen (ref[0])).to.be.true ();
expect (Object.isFrozen (ref[1])).to.be.true ();
expect (Object.isFrozen (ref[1].b)).to.be.false ();
expect (ref).to.deep.equal ([{a: 1}, {b: {x: 2}}]);
expect (() => ref[0].a = 0).to.throw ();
expect (() => ref[1].b = 0).to.throw ();
expect (() => ref[1].b.x = 0).to.not.throw ();
expect (ref).to.deep.equal ([{a: 1}, {b: {x: 0}}]);
});
it ('freezes deeply arrays up to the top level objects', () => {
const state = State.create ('a').set ('x', [{a: 1}, [{b: {x: 2}}]]);
const ref = state.get ('x');
expect (Object.isFrozen (ref[0])).to.be.true ();
expect (Object.isFrozen (ref[1])).to.be.true ();
expect (Object.isFrozen (ref[1][0])).to.be.true ();
expect (Object.isFrozen (ref[1][0].b)).to.be.false ();
expect (ref).to.deep.equal ([{a: 1}, [{b: {x: 2}}]]);
expect (() => ref[0].a = 0).to.throw ();
expect (() => ref[1][0].b.x = 0).to.not.throw ();
expect (ref).to.deep.equal ([{a: 1}, [{b: {x: 0}}]]);
});
});

@@ -58,0 +100,0 @@

@@ -9,2 +9,5 @@ 'use strict';

Object.freeze (emptyValues);
Object.freeze (secretKey);
function isPositiveInteger (value) {

@@ -55,4 +58,9 @@ if (typeof value === 'number') {

}
if (values.length === 0) {
if (isEmpty (values)) {
values = emptyValues; // optimize for values set to {}
} else {
Object.freeze (values);
for (let key of Object.getOwnPropertyNames (values)) {
State.freezeTop (values[key]);
}
}

@@ -340,2 +348,23 @@

}
static freeze (obj) {
if (Array.isArray (obj)) {
obj.forEach (x => State.freeze (x));
}
if (obj && typeof obj === 'object') {
Object.freeze (obj);
for (let key of Object.getOwnPropertyNames (obj)) {
State.freeze (obj[key]);
}
}
}
static freezeTop (obj) {
if (Array.isArray (obj)) {
obj.forEach (x => State.freezeTop (x));
}
if (obj && typeof obj === 'object') {
Object.freeze (obj);
}
}
}

@@ -342,0 +371,0 @@

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