Skip to content

Commit 1237fac

Browse files
Scott TrinhScott Trinh
Scott Trinh
authored and
Scott Trinh
committed
fix: Always remove $$hashKey from object or array objects
1 parent 66b72e5 commit 1237fac

File tree

2 files changed

+104
-10
lines changed

2 files changed

+104
-10
lines changed

src/angular-localForage.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,7 @@
119119
} else {
120120
var deferred = $q.defer(),
121121
args = arguments,
122-
localCopy = value;
123-
124-
//avoid $promises attributes from value objects, if present.
125-
if(angular.isObject(localCopy) && angular.isDefined(localCopy.$promise)) {
126-
localCopy = angular.extend({}, value);
127-
delete localCopy.$promise;
128-
}
122+
localCopy = stripMeta(value);
129123

130124
self._localforage.setItem(self.prefix() + key, localCopy)
131125
.then(function success() {
@@ -144,6 +138,26 @@
144138

145139
return deferred.promise;
146140
}
141+
142+
function stripMeta(value) {
143+
var copy;
144+
if (angular.isArray(value)) {
145+
return value.map(stripMeta);
146+
} else if (angular.isObject(value) && !(value instanceof Blob)) {
147+
copy = angular.extend({}, value);
148+
149+
angular.isDefined(copy.$promise) && delete copy.$promise;
150+
angular.isDefined(copy.$$hashKey) && delete copy.$$hashKey;
151+
152+
return Object
153+
.keys(copy)
154+
.reduce(function stripEntries(acc, key) {
155+
acc[key] = stripMeta(copy[key]);
156+
return acc;
157+
}, {});
158+
}
159+
return value;
160+
}
147161
};
148162

149163
// Directly get a value from storage

tests/angular-localForage.js

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,15 @@ describe('Module: LocalForageModule', function() {
184184
it('setItem and getItem should work', function(done) {
185185
var interval = triggerDigests();
186186
var objectToStore = {
187+
$$hashKey: 'object:1',
187188
name: 'Scott Trinh'
188189
};
189190

190191
spyOn($localForage._localforage, 'setItem').and.callThrough();
191192

192193
$localForage.setItem('myObject', objectToStore).then(function(data) {
193194
expect(data).toEqual({ name: 'Scott Trinh' });
194-
expect($localForage._localforage.setItem.calls.mostRecent().args[1]).toBe(objectToStore);
195+
expect($localForage._localforage.setItem.calls.mostRecent().args[1]).toEqual({ name: 'Scott Trinh'});
195196

196197
$localForage.getItem('myObject').then(function(data) {
197198
stopDigests(interval);
@@ -202,6 +203,84 @@ describe('Module: LocalForageModule', function() {
202203
}, done);
203204
});
204205

206+
it('setItem should remove $$hashKey from nested arrays', function () {
207+
var arrayToStore = [
208+
{
209+
collection: [
210+
{ $$hashKey: 'object:1' },
211+
{ $$hashKey: 'object:2' }
212+
],
213+
deeperCollection: {
214+
collection: [
215+
{ $$hashKey: 'object:3' },
216+
{ $$hashKey: 'object:4' }
217+
]
218+
}
219+
}
220+
];
221+
222+
$localForage.setItem('myArray', arrayToStore).then(function (data) {
223+
expect(data).toEqual([
224+
{
225+
collection: [{}, {}],
226+
deeperCollection: {
227+
collection: [{}, {}]
228+
}
229+
}
230+
]);
231+
expect(arrayToStore).toEqual([
232+
{
233+
collection: [
234+
{ $$hashKey: 'object:1' },
235+
{ $$hashKey: 'object:2' }
236+
],
237+
deeperCollection: {
238+
collection: [
239+
{ $$hashKey: 'object:3' },
240+
{ $$hashKey: 'object:4' }
241+
]
242+
}
243+
}
244+
]);
245+
});
246+
});
247+
248+
it('setItem works with arrays of non-objects, and strips the $$hashKey of any object', function () {
249+
var arrayToStore = [
250+
[[]],
251+
[{}, {$$hashKey: 'object:1'}],
252+
'string',
253+
true,
254+
false,
255+
null,
256+
undefined,
257+
{},
258+
];
259+
260+
$localForage.setItem('myWeirdArray', arrayToStore).then(function (data) {
261+
expect(data).toEqual([
262+
[[]],
263+
[{}, {}],
264+
'string',
265+
true,
266+
false,
267+
null,
268+
undefined,
269+
{},
270+
]);
271+
expect(arrayToStore).toEqual([
272+
[[]],
273+
[{}, {$$hashKey: 'object:1'}],
274+
'string',
275+
true,
276+
false,
277+
null,
278+
undefined,
279+
{},
280+
]);
281+
});
282+
});
283+
205284
it('setItem error should reject promise', function(done) {
206285
var interval = triggerDigests();
207286

@@ -482,7 +561,8 @@ describe('Module: LocalForageModule', function() {
482561
var setWith = $localForage._localforage.setItem.calls.argsFor(0)[1];
483562
var setWithNoPromise = $localForage._localforage.setItem.calls.argsFor(1)[1];
484563
expect(setWith).not.toBe(objectToStore);
485-
expect(setWith.childObject).toBe(objectToStore.childObject);
564+
expect(setWith.childObject).not.toBe(objectToStore.childObject);
565+
expect(setWith.childObject).toEqual(objectToStore.childObject);
486566
expect(setWith).toEqual({
487567
childObject: {}
488568
});
@@ -491,7 +571,7 @@ describe('Module: LocalForageModule', function() {
491571
childObject: {}
492572
});
493573

494-
expect(setWithNoPromise).toBe(objectNoPromise);
574+
expect(setWithNoPromise).toEqual(objectNoPromise);
495575

496576
$localForage.getItem('myObject').then(function(data) {
497577
stopDigests(interval);

0 commit comments

Comments
 (0)