Skip to content

Commit 989b4b6

Browse files
author
Moshe Kolodny
committed
Add $unset directive
1 parent f0de94a commit 989b4b6

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,23 @@ var defaultCommands = {
9898
invariantSet(spec);
9999
return value;
100100
},
101+
$unset: function(value, nextObject, spec, object) {
102+
invariant(
103+
Array.isArray(value),
104+
'update(): expected spec of $unset to be an array; got %s. ' +
105+
'Did you forget to wrap the key(s) in an array?',
106+
value
107+
);
108+
var originalValue = nextObject;
109+
for (var i = 0; i < value.length; i++) {
110+
var key = value[i];
111+
if (Object.hasOwnProperty.call(originalValue, key)) {
112+
originalValue = nextObject === object ? copy(object) : nextObject;
113+
delete originalValue[key];
114+
}
115+
}
116+
return originalValue;
117+
},
101118
$merge: function(value, nextObject, spec, object) {
102119
var originalValue = nextObject === object ? copy(object) : nextObject;
103120
invariantMerge(originalValue, value);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "immutability-helper",
3-
"version": "2.1.2",
3+
"version": "2.2.0",
44
"description": "mutate a copy of data without changing the original source",
55
"main": "index.js",
66
"scripts": {

test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,28 @@ describe('update', function() {
110110
});
111111
});
112112

113+
describe('$unset', function() {
114+
it('unsets', function() {
115+
expect(update({a: 'b'}, {$unset: ['a']}).a).toBe(undefined);
116+
});
117+
it('removes the key from the object', function() {
118+
var removed = update({a: 'b'}, {$unset: ['a']});
119+
expect('a' in removed).toBe(false);
120+
});
121+
it('does not remove keys from the inherited properties', function() {
122+
function Parent() { this.foo = 'Parent'; }
123+
function Child() {}
124+
Child.prototype = new Parent()
125+
var child = new Child();
126+
expect(update(child, {$unset: ['foo']}).foo).toEqual('Parent');
127+
});
128+
it('keeps reference equality when possible', function() {
129+
var original = {a: 1};
130+
expect(update(original, {$unset: ['b']})).toBe(original);
131+
expect(update(original, {$unset: ['a']})).toNotBe(original);
132+
});
133+
});
134+
113135
describe('$apply', function() {
114136
var applier = function(node) {
115137
return {v: node.v * 2};
@@ -233,6 +255,13 @@ describe('update', function() {
233255
});
234256
});
235257

258+
it('should reject non arrays from $unset', function() {
259+
expect(update.bind(null, {a: 'b'}, {$unset: 'a'})).toThrow(
260+
'update(): expected spec of $unset to be an array; got a. ' +
261+
'Did you forget to wrap the key(s) in an array?'
262+
);
263+
});
264+
236265
it('should require a plain object spec containing command(s)', function() {
237266
var specs = [
238267
null,
@@ -244,7 +273,7 @@ describe('update', function() {
244273
expect(update.bind(null, {a: 'b'}, spec)).toThrow(
245274
'update(): You provided an invalid spec to update(). The spec ' +
246275
'and every included key path must be plain objects containing one ' +
247-
'of the following commands: $push, $unshift, $splice, $set, ' +
276+
'of the following commands: $push, $unshift, $splice, $set, $unset, ' +
248277
'$merge, $apply.'
249278
);
250279
});

0 commit comments

Comments
 (0)