dot-object 2.1.0 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # ChangeLog
2
2
 
3
+ ## 2020-09-10 Version 2.1.4
4
+ * [[`94b9eb8a2d`](https://github.com/rhalff/dot-object/commit/94b9eb8a2d)] - Fix parsing of array paths for non standard separators (Fixed by boidolr #58)
5
+
6
+ ## 2020-02-16 Version 2.1.3
7
+ * fix possible pollution of prototype for paths containing __proto__
8
+
9
+ ## 2019-11-02 Version 2.1.1
10
+ * fix undefined key with root level array.
11
+
12
+ ## 2019-11-02 Version 2.1.1
13
+ * Wrong array conversion when brackets are used (Reported by vladshcherbin #27)
14
+
3
15
  ## 2019-11-02 Version 2.1.0
4
16
  * fix delete function not being wrapped. (Reported by murphyke #40)
5
17
 
package/README.md CHANGED
@@ -359,6 +359,33 @@ Result:
359
359
  }
360
360
  ```
361
361
 
362
+ ### Keep array
363
+
364
+ Set keepArray to true.
365
+
366
+ ```javascript
367
+ var dot = require('dot-object');
368
+
369
+ var obj = {
370
+ id: 'my-id',
371
+ other: [1, 2, 3],
372
+ some: { array: ['A', 'B'] }
373
+ };
374
+
375
+ dot.keepArray = true;
376
+ var tgt = dot.dot(obj);
377
+
378
+ console.log(tgt);
379
+ ```
380
+ Result:
381
+ ```json
382
+ {
383
+ "id": "my-id",
384
+ "other": [1, 2, 3],
385
+ "some.array": ["A", "B"]
386
+ }
387
+ ```
388
+
362
389
  ## Using a different separator
363
390
 
364
391
  If you do not like dot notation, you are free to specify a different separator.
package/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dot-object",
3
- "version": "2.1.0",
3
+ "version": "2.1.4",
4
4
  "description": "dot-object makes it possible to transform and read (JSON) objects using dot notation.",
5
5
  "main": "dist/dot-object.js",
6
6
  "authors": [
@@ -46,11 +46,25 @@
46
46
  return Object.keys(val).length === 0
47
47
  }
48
48
 
49
+ var blacklist = ['__proto__', 'prototype', 'constructor']
50
+ var blacklistFilter = function(part) {
51
+ return blacklist.indexOf(part) === -1
52
+ }
53
+
49
54
  function parsePath(path, sep) {
50
55
  if (path.indexOf('[') >= 0) {
51
- path = path.replace(/\[/g, '.').replace(/]/g, '')
56
+ path = path.replace(/\[/g, sep).replace(/]/g, '')
57
+ }
58
+
59
+ var parts = path.split(sep)
60
+
61
+ var check = parts.filter(blacklistFilter)
62
+
63
+ if (check.length !== parts.length) {
64
+ throw Error('Refusing to update blacklisted property ' + path)
52
65
  }
53
- return path.split(sep)
66
+
67
+ return parts
54
68
  }
55
69
 
56
70
  var hasOwnProperty = Object.prototype.hasOwnProperty
@@ -85,8 +99,7 @@
85
99
  var k = a.shift()
86
100
 
87
101
  if (a.length > 0) {
88
- obj[k] = obj[k] ||
89
- (this.useArray && isIndex(a[0]) ? [] : {})
102
+ obj[k] = obj[k] || (this.useArray && isIndex(a[0]) ? [] : {})
90
103
 
91
104
  if (!isArrayOrObject(obj[k])) {
92
105
  if (this.override) {
@@ -104,8 +117,7 @@
104
117
 
105
118
  this._fill(a, obj[k], v, mod)
106
119
  } else {
107
- if (!this.override &&
108
- isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
120
+ if (!this.override && isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
109
121
  if (!(isArrayOrObject(v) && isEmptyObject(v))) {
110
122
  throw new Error("Trying to redefine non-empty obj['" + k + "']")
111
123
  }
@@ -165,8 +177,10 @@
165
177
  * @param {Function|Array} mod optional modifier
166
178
  */
167
179
  DotObject.prototype.str = function(path, v, obj, mod) {
180
+ var ok = parsePath(path, this.separator).join(this.separator)
181
+
168
182
  if (path.indexOf(this.separator) !== -1) {
169
- this._fill(path.split(this.separator), obj, v, mod)
183
+ this._fill(ok.split(this.separator), obj, v, mod)
170
184
  } else {
171
185
  obj[path] = _process(v, mod)
172
186
  }
@@ -195,7 +209,7 @@
195
209
  for (i = 0; i < keys.length; i++) {
196
210
  key = parseKey(keys[i], obj)
197
211
  if (obj && typeof obj === 'object' && key in obj) {
198
- if (i === (keys.length - 1)) {
212
+ if (i === keys.length - 1) {
199
213
  if (remove) {
200
214
  val = obj[key]
201
215
  if (reindexArray && Array.isArray(obj)) {
@@ -340,13 +354,21 @@
340
354
  * @param {Function|Array} mods
341
355
  * @param {Boolean} merge
342
356
  */
343
- DotObject.prototype.transfer = function(source, target, obj1, obj2, mods, merge) {
357
+ DotObject.prototype.transfer = function(
358
+ source,
359
+ target,
360
+ obj1,
361
+ obj2,
362
+ mods,
363
+ merge
364
+ ) {
344
365
  if (typeof mods === 'function' || Array.isArray(mods)) {
345
- this.set(target,
346
- _process(
347
- this.pick(source, obj1, true),
348
- mods
349
- ), obj2, merge)
366
+ this.set(
367
+ target,
368
+ _process(this.pick(source, obj1, true), mods),
369
+ obj2,
370
+ merge
371
+ )
350
372
  } else {
351
373
  merge = mods
352
374
  this.set(target, this.pick(source, obj1, true), obj2, merge)
@@ -371,16 +393,16 @@
371
393
  */
372
394
  DotObject.prototype.copy = function(source, target, obj1, obj2, mods, merge) {
373
395
  if (typeof mods === 'function' || Array.isArray(mods)) {
374
- this.set(target,
396
+ this.set(
397
+ target,
375
398
  _process(
376
399
  // clone what is picked
377
- JSON.parse(
378
- JSON.stringify(
379
- this.pick(source, obj1, false)
380
- )
381
- ),
400
+ JSON.parse(JSON.stringify(this.pick(source, obj1, false))),
382
401
  mods
383
- ), obj2, merge)
402
+ ),
403
+ obj2,
404
+ merge
405
+ )
384
406
  } else {
385
407
  merge = mods
386
408
  this.set(target, this.pick(source, obj1, false), obj2, merge)
@@ -412,7 +434,7 @@
412
434
 
413
435
  for (i = 0; i < keys.length; i++) {
414
436
  key = keys[i]
415
- if (i === (keys.length - 1)) {
437
+ if (i === keys.length - 1) {
416
438
  if (merge && isObject(val) && isObject(obj[key])) {
417
439
  for (k in val) {
418
440
  if (hasOwnProperty.call(val, k)) {
@@ -470,9 +492,11 @@
470
492
  DotObject.prototype.transform = function(recipe, obj, tgt) {
471
493
  obj = obj || {}
472
494
  tgt = tgt || {}
473
- Object.keys(recipe).forEach(function(key) {
474
- this.set(recipe[key], this.pick(key, obj), tgt)
475
- }.bind(this))
495
+ Object.keys(recipe).forEach(
496
+ function(key) {
497
+ this.set(recipe[key], this.pick(key, obj), tgt)
498
+ }.bind(this)
499
+ )
476
500
  return tgt
477
501
  }
478
502
 
@@ -498,30 +522,33 @@
498
522
  path = path || []
499
523
  var isArray = Array.isArray(obj)
500
524
 
501
- Object.keys(obj).forEach(function(key) {
502
- var index = isArray && this.useBrackets ? '[' + key + ']' : key
503
- if (
504
- (
525
+ Object.keys(obj).forEach(
526
+ function(key) {
527
+ var index = isArray && this.useBrackets ? '[' + key + ']' : key
528
+ if (
505
529
  isArrayOrObject(obj[key]) &&
506
- (
507
- (isObject(obj[key]) && !isEmptyObject(obj[key])) ||
508
- (Array.isArray(obj[key]) && (!this.keepArray && (obj[key].length !== 0)))
509
- )
510
- )
511
- ) {
512
- if (isArray && this.useBrackets) {
513
- return this.dot(obj[key], tgt, path.slice(0, -1).concat(path[path.length - 1] + index))
514
- } else {
515
- return this.dot(obj[key], tgt, path.concat(index))
516
- }
517
- } else {
518
- if (isArray && this.useBrackets) {
519
- tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
530
+ ((isObject(obj[key]) && !isEmptyObject(obj[key])) ||
531
+ (Array.isArray(obj[key]) && !this.keepArray && obj[key].length !== 0))
532
+ ) {
533
+ if (isArray && this.useBrackets) {
534
+ var previousKey = path[path.length - 1] || ''
535
+ return this.dot(
536
+ obj[key],
537
+ tgt,
538
+ path.slice(0, -1).concat(previousKey + index)
539
+ )
540
+ } else {
541
+ return this.dot(obj[key], tgt, path.concat(index))
542
+ }
520
543
  } else {
521
- tgt[path.concat(index).join(this.separator)] = obj[key]
544
+ if (isArray && this.useBrackets) {
545
+ tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
546
+ } else {
547
+ tgt[path.concat(index).join(this.separator)] = obj[key]
548
+ }
522
549
  }
523
- }
524
- }.bind(this))
550
+ }.bind(this)
551
+ )
525
552
  return tgt
526
553
  }
527
554
 
@@ -535,9 +562,7 @@
535
562
  DotObject.set = wrap('set')
536
563
  DotObject.delete = wrap('delete')
537
564
  DotObject.del = DotObject.remove = wrap('remove')
538
- DotObject.dot = wrap('dot')
539
-
540
- ;
565
+ DotObject.dot = wrap('dot');
541
566
  ['override', 'overwrite'].forEach(function(prop) {
542
567
  Object.defineProperty(DotObject, prop, {
543
568
  get: function() {
@@ -547,9 +572,7 @@
547
572
  dotDefault.override = !!val
548
573
  }
549
574
  })
550
- })
551
-
552
- ;
575
+ });
553
576
  ['useArray', 'keepArray', 'useBrackets'].forEach(function(prop) {
554
577
  Object.defineProperty(DotObject, prop, {
555
578
  get: function() {
@@ -1 +1 @@
1
- !function(t){"use strict";function s(t,r){var e,i;if("function"==typeof r)void 0!==(i=r(t))&&(t=i);else if(Array.isArray(r))for(e=0;e<r.length;e++)void 0!==(i=r[e](t))&&(t=i);return t}function f(t){return"[object Object]"===Object.prototype.toString.call(t)}function c(t){return Object(t)===t}function a(t){return 0===Object.keys(t).length}function u(t,r){return 0<=t.indexOf("[")&&(t=t.replace(/\[/g,".").replace(/]/g,"")),t.split(r)}var p=Object.prototype.hasOwnProperty;function n(t,r,e,i){if(!(this instanceof n))return new n(t,r,e,i);void 0===r&&(r=!1),void 0===e&&(e=!0),void 0===i&&(i=!0),this.separator=t||".",this.override=r,this.useArray=e,this.useBrackets=i,this.keepArray=!1,this.cleanup=[]}var e=new n(".",!1,!0,!0);function r(t){return function(){return e[t].apply(e,arguments)}}n.prototype._fill=function(t,r,e,i){var n=t.shift();if(0<t.length){if(r[n]=r[n]||(this.useArray&&function(t){return/^\d+$/.test(t)}(t[0])?[]:{}),!c(r[n])){if(!this.override){if(!c(e)||!a(e))throw new Error("Trying to redefine `"+n+"` which is a "+typeof r[n]);return}r[n]={}}this._fill(t,r[n],e,i)}else{if(!this.override&&c(r[n])&&!a(r[n])){if(!c(e)||!a(e))throw new Error("Trying to redefine non-empty obj['"+n+"']");return}r[n]=s(e,i)}},n.prototype.object=function(i,n){var o=this;return Object.keys(i).forEach(function(t){var r=void 0===n?null:n[t],e=u(t,o.separator).join(o.separator);-1!==e.indexOf(o.separator)?(o._fill(e.split(o.separator),i,i[t],r),delete i[t]):i[t]=s(i[t],r)}),i},n.prototype.str=function(t,r,e,i){return-1!==t.indexOf(this.separator)?this._fill(t.split(this.separator),e,r,i):e[t]=s(r,i),e},n.prototype.pick=function(t,r,e,i){var n,o,s,c,a,f,p;for(o=u(t,this.separator),n=0;n<o.length;n++){if(f=o[n],p=r,c="-"===f[0]&&Array.isArray(p)&&/^-\d+$/.test(f)?p.length+parseInt(f,10):f,!(r&&"object"==typeof r&&c in r))return;if(n===o.length-1)return e?(s=r[c],i&&Array.isArray(r)?r.splice(c,1):delete r[c],Array.isArray(r)&&(a=o.slice(0,-1).join("."),-1===this.cleanup.indexOf(a)&&this.cleanup.push(a)),s):r[c];r=r[c]}return e&&Array.isArray(r)&&(r=r.filter(function(t){return void 0!==t})),r},n.prototype.delete=function(t,r){return this.remove(t,r,!0)},n.prototype.remove=function(t,r,e){var i;if(this.cleanup=[],Array.isArray(t)){for(i=0;i<t.length;i++)this.pick(t[i],r,!0,e);return e||this._cleanup(r),r}return this.pick(t,r,!0,e)},n.prototype._cleanup=function(t){var r,e,i,n;if(this.cleanup.length){for(e=0;e<this.cleanup.length;e++)r=(r=(n=(i=this.cleanup[e].split(".")).splice(0,-1).join("."))?this.pick(n,t):t)[i[0]].filter(function(t){return void 0!==t}),this.set(this.cleanup[e],r,t);this.cleanup=[]}},n.prototype.del=n.prototype.remove,n.prototype.move=function(t,r,e,i,n){return"function"==typeof i||Array.isArray(i)?this.set(r,s(this.pick(t,e,!0),i),e,n):(n=i,this.set(r,this.pick(t,e,!0),e,n)),e},n.prototype.transfer=function(t,r,e,i,n,o){return"function"==typeof n||Array.isArray(n)?this.set(r,s(this.pick(t,e,!0),n),i,o):(o=n,this.set(r,this.pick(t,e,!0),i,o)),i},n.prototype.copy=function(t,r,e,i,n,o){return"function"==typeof n||Array.isArray(n)?this.set(r,s(JSON.parse(JSON.stringify(this.pick(t,e,!1))),n),i,o):(o=n,this.set(r,this.pick(t,e,!1),i,o)),i},n.prototype.set=function(t,r,e,i){var n,o,s,c;if(void 0===r)return e;for(s=u(t,this.separator),n=0;n<s.length;n++){if(c=s[n],n===s.length-1)if(i&&f(r)&&f(e[c]))for(o in r)p.call(r,o)&&(e[c][o]=r[o]);else if(i&&Array.isArray(e[c])&&Array.isArray(r))for(var a=0;a<r.length;a++)e[s[n]].push(r[a]);else e[c]=r;else p.call(e,c)&&(f(e[c])||Array.isArray(e[c]))||(/^\d+$/.test(s[n+1])?e[c]=[]:e[c]={});e=e[c]}return e},n.prototype.transform=function(r,e,i){return e=e||{},i=i||{},Object.keys(r).forEach(function(t){this.set(r[t],this.pick(t,e),i)}.bind(this)),i},n.prototype.dot=function(e,i,n){i=i||{},n=n||[];var o=Array.isArray(e);return Object.keys(e).forEach(function(t){var r=o&&this.useBrackets?"["+t+"]":t;if(c(e[t])&&(f(e[t])&&!a(e[t])||Array.isArray(e[t])&&!this.keepArray&&0!==e[t].length))return o&&this.useBrackets?this.dot(e[t],i,n.slice(0,-1).concat(n[n.length-1]+r)):this.dot(e[t],i,n.concat(r));o&&this.useBrackets?i[n.join(this.separator).concat("["+t+"]")]=e[t]:i[n.concat(r).join(this.separator)]=e[t]}.bind(this)),i},n.pick=r("pick"),n.move=r("move"),n.transfer=r("transfer"),n.transform=r("transform"),n.copy=r("copy"),n.object=r("object"),n.str=r("str"),n.set=r("set"),n.delete=r("delete"),n.del=n.remove=r("remove"),n.dot=r("dot"),["override","overwrite"].forEach(function(t){Object.defineProperty(n,t,{get:function(){return e.override},set:function(t){e.override=!!t}})}),["useArray","keepArray","useBrackets"].forEach(function(r){Object.defineProperty(n,r,{get:function(){return e[r]},set:function(t){e[r]=t}})}),n._process=s,"function"==typeof define&&define.amd?define(function(){return n}):"undefined"!=typeof module&&module.exports?module.exports=n:t.DotObject=n}(this);
1
+ !function(t){"use strict";function s(t,r){var e,i;if("function"==typeof r)void 0!==(i=r(t))&&(t=i);else if(Array.isArray(r))for(e=0;e<r.length;e++)void 0!==(i=r[e](t))&&(t=i);return t}function p(t){return"[object Object]"===Object.prototype.toString.call(t)}function a(t){return Object(t)===t}function c(t){return 0===Object.keys(t).length}function i(t){return-1===r.indexOf(t)}var r=["__proto__","prototype","constructor"];function u(t,r){0<=t.indexOf("[")&&(t=t.replace(/\[/g,r).replace(/]/g,""));var e=t.split(r);if(e.filter(i).length!==e.length)throw Error("Refusing to update blacklisted property "+t);return e}var f=Object.prototype.hasOwnProperty;function n(t,r,e,i){if(!(this instanceof n))return new n(t,r,e,i);void 0===r&&(r=!1),void 0===e&&(e=!0),void 0===i&&(i=!0),this.separator=t||".",this.override=r,this.useArray=e,this.useBrackets=i,this.keepArray=!1,this.cleanup=[]}var e=new n(".",!1,!0,!0);function o(t){return function(){return e[t].apply(e,arguments)}}n.prototype._fill=function(t,r,e,i){var n=t.shift();if(0<t.length){if(r[n]=r[n]||(this.useArray&&function(t){return/^\d+$/.test(t)}(t[0])?[]:{}),!a(r[n])){if(!this.override){if(!a(e)||!c(e))throw new Error("Trying to redefine `"+n+"` which is a "+typeof r[n]);return}r[n]={}}this._fill(t,r[n],e,i)}else{if(!this.override&&a(r[n])&&!c(r[n])){if(!a(e)||!c(e))throw new Error("Trying to redefine non-empty obj['"+n+"']");return}r[n]=s(e,i)}},n.prototype.object=function(i,n){var o=this;return Object.keys(i).forEach(function(t){var r=void 0===n?null:n[t],e=u(t,o.separator).join(o.separator);-1!==e.indexOf(o.separator)?(o._fill(e.split(o.separator),i,i[t],r),delete i[t]):i[t]=s(i[t],r)}),i},n.prototype.str=function(t,r,e,i){var n=u(t,this.separator).join(this.separator);return-1!==t.indexOf(this.separator)?this._fill(n.split(this.separator),e,r,i):e[t]=s(r,i),e},n.prototype.pick=function(t,r,e,i){var n,o,s,a,c,p,f;for(o=u(t,this.separator),n=0;n<o.length;n++){if(p=o[n],f=r,a="-"===p[0]&&Array.isArray(f)&&/^-\d+$/.test(p)?f.length+parseInt(p,10):p,!(r&&"object"==typeof r&&a in r))return;if(n===o.length-1)return e?(s=r[a],i&&Array.isArray(r)?r.splice(a,1):delete r[a],Array.isArray(r)&&(c=o.slice(0,-1).join("."),-1===this.cleanup.indexOf(c)&&this.cleanup.push(c)),s):r[a];r=r[a]}return e&&Array.isArray(r)&&(r=r.filter(function(t){return void 0!==t})),r},n.prototype.delete=function(t,r){return this.remove(t,r,!0)},n.prototype.remove=function(t,r,e){var i;if(this.cleanup=[],Array.isArray(t)){for(i=0;i<t.length;i++)this.pick(t[i],r,!0,e);return e||this._cleanup(r),r}return this.pick(t,r,!0,e)},n.prototype._cleanup=function(t){var r,e,i,n;if(this.cleanup.length){for(e=0;e<this.cleanup.length;e++)r=(r=(n=(i=this.cleanup[e].split(".")).splice(0,-1).join("."))?this.pick(n,t):t)[i[0]].filter(function(t){return void 0!==t}),this.set(this.cleanup[e],r,t);this.cleanup=[]}},n.prototype.del=n.prototype.remove,n.prototype.move=function(t,r,e,i,n){return"function"==typeof i||Array.isArray(i)?this.set(r,s(this.pick(t,e,!0),i),e,n):(n=i,this.set(r,this.pick(t,e,!0),e,n)),e},n.prototype.transfer=function(t,r,e,i,n,o){return"function"==typeof n||Array.isArray(n)?this.set(r,s(this.pick(t,e,!0),n),i,o):(o=n,this.set(r,this.pick(t,e,!0),i,o)),i},n.prototype.copy=function(t,r,e,i,n,o){return"function"==typeof n||Array.isArray(n)?this.set(r,s(JSON.parse(JSON.stringify(this.pick(t,e,!1))),n),i,o):(o=n,this.set(r,this.pick(t,e,!1),i,o)),i},n.prototype.set=function(t,r,e,i){var n,o,s,a;if(void 0===r)return e;for(s=u(t,this.separator),n=0;n<s.length;n++){if(a=s[n],n===s.length-1)if(i&&p(r)&&p(e[a]))for(o in r)f.call(r,o)&&(e[a][o]=r[o]);else if(i&&Array.isArray(e[a])&&Array.isArray(r))for(var c=0;c<r.length;c++)e[s[n]].push(r[c]);else e[a]=r;else f.call(e,a)&&(p(e[a])||Array.isArray(e[a]))||(/^\d+$/.test(s[n+1])?e[a]=[]:e[a]={});e=e[a]}return e},n.prototype.transform=function(r,e,i){return e=e||{},i=i||{},Object.keys(r).forEach(function(t){this.set(r[t],this.pick(t,e),i)}.bind(this)),i},n.prototype.dot=function(i,n,o){n=n||{},o=o||[];var s=Array.isArray(i);return Object.keys(i).forEach(function(t){var r=s&&this.useBrackets?"["+t+"]":t;if(a(i[t])&&(p(i[t])&&!c(i[t])||Array.isArray(i[t])&&!this.keepArray&&0!==i[t].length)){if(s&&this.useBrackets){var e=o[o.length-1]||"";return this.dot(i[t],n,o.slice(0,-1).concat(e+r))}return this.dot(i[t],n,o.concat(r))}s&&this.useBrackets?n[o.join(this.separator).concat("["+t+"]")]=i[t]:n[o.concat(r).join(this.separator)]=i[t]}.bind(this)),n},n.pick=o("pick"),n.move=o("move"),n.transfer=o("transfer"),n.transform=o("transform"),n.copy=o("copy"),n.object=o("object"),n.str=o("str"),n.set=o("set"),n.delete=o("delete"),n.del=n.remove=o("remove"),n.dot=o("dot"),["override","overwrite"].forEach(function(t){Object.defineProperty(n,t,{get:function(){return e.override},set:function(t){e.override=!!t}})}),["useArray","keepArray","useBrackets"].forEach(function(r){Object.defineProperty(n,r,{get:function(){return e[r]},set:function(t){e[r]=t}})}),n._process=s,"function"==typeof define&&define.amd?define(function(){return n}):"undefined"!=typeof module&&module.exports?module.exports=n:t.DotObject=n}(this);
package/index.js CHANGED
@@ -45,11 +45,23 @@ function isEmptyObject (val) {
45
45
  return Object.keys(val).length === 0
46
46
  }
47
47
 
48
+ var blacklist = ['__proto__', 'prototype', 'constructor']
49
+ var blacklistFilter = function (part) { return blacklist.indexOf(part) === -1 }
50
+
48
51
  function parsePath (path, sep) {
49
52
  if (path.indexOf('[') >= 0) {
50
- path = path.replace(/\[/g, '.').replace(/]/g, '')
53
+ path = path.replace(/\[/g, sep).replace(/]/g, '')
54
+ }
55
+
56
+ var parts = path.split(sep)
57
+
58
+ var check = parts.filter(blacklistFilter)
59
+
60
+ if (check.length !== parts.length) {
61
+ throw Error('Refusing to update blacklisted property ' + path)
51
62
  }
52
- return path.split(sep)
63
+
64
+ return parts
53
65
  }
54
66
 
55
67
  var hasOwnProperty = Object.prototype.hasOwnProperty
@@ -83,8 +95,7 @@ DotObject.prototype._fill = function (a, obj, v, mod) {
83
95
  var k = a.shift()
84
96
 
85
97
  if (a.length > 0) {
86
- obj[k] = obj[k] ||
87
- (this.useArray && isIndex(a[0]) ? [] : {})
98
+ obj[k] = obj[k] || (this.useArray && isIndex(a[0]) ? [] : {})
88
99
 
89
100
  if (!isArrayOrObject(obj[k])) {
90
101
  if (this.override) {
@@ -102,8 +113,7 @@ DotObject.prototype._fill = function (a, obj, v, mod) {
102
113
 
103
114
  this._fill(a, obj[k], v, mod)
104
115
  } else {
105
- if (!this.override &&
106
- isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
116
+ if (!this.override && isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
107
117
  if (!(isArrayOrObject(v) && isEmptyObject(v))) {
108
118
  throw new Error("Trying to redefine non-empty obj['" + k + "']")
109
119
  }
@@ -163,8 +173,10 @@ DotObject.prototype.object = function (obj, mods) {
163
173
  * @param {Function|Array} mod optional modifier
164
174
  */
165
175
  DotObject.prototype.str = function (path, v, obj, mod) {
176
+ var ok = parsePath(path, this.separator).join(this.separator)
177
+
166
178
  if (path.indexOf(this.separator) !== -1) {
167
- this._fill(path.split(this.separator), obj, v, mod)
179
+ this._fill(ok.split(this.separator), obj, v, mod)
168
180
  } else {
169
181
  obj[path] = _process(v, mod)
170
182
  }
@@ -193,7 +205,7 @@ DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
193
205
  for (i = 0; i < keys.length; i++) {
194
206
  key = parseKey(keys[i], obj)
195
207
  if (obj && typeof obj === 'object' && key in obj) {
196
- if (i === (keys.length - 1)) {
208
+ if (i === keys.length - 1) {
197
209
  if (remove) {
198
210
  val = obj[key]
199
211
  if (reindexArray && Array.isArray(obj)) {
@@ -219,7 +231,9 @@ DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
219
231
  }
220
232
  }
221
233
  if (remove && Array.isArray(obj)) {
222
- obj = obj.filter(function (n) { return n !== undefined })
234
+ obj = obj.filter(function (n) {
235
+ return n !== undefined
236
+ })
223
237
  }
224
238
  return obj
225
239
  }
@@ -277,7 +291,9 @@ DotObject.prototype._cleanup = function (obj) {
277
291
  keys = this.cleanup[i].split('.')
278
292
  root = keys.splice(0, -1).join('.')
279
293
  ret = root ? this.pick(root, obj) : obj
280
- ret = ret[keys[0]].filter(function (v) { return v !== undefined })
294
+ ret = ret[keys[0]].filter(function (v) {
295
+ return v !== undefined
296
+ })
281
297
  this.set(this.cleanup[i], ret, obj)
282
298
  }
283
299
  this.cleanup = []
@@ -334,13 +350,21 @@ DotObject.prototype.move = function (source, target, obj, mods, merge) {
334
350
  * @param {Function|Array} mods
335
351
  * @param {Boolean} merge
336
352
  */
337
- DotObject.prototype.transfer = function (source, target, obj1, obj2, mods, merge) {
353
+ DotObject.prototype.transfer = function (
354
+ source,
355
+ target,
356
+ obj1,
357
+ obj2,
358
+ mods,
359
+ merge
360
+ ) {
338
361
  if (typeof mods === 'function' || Array.isArray(mods)) {
339
- this.set(target,
340
- _process(
341
- this.pick(source, obj1, true),
342
- mods
343
- ), obj2, merge)
362
+ this.set(
363
+ target,
364
+ _process(this.pick(source, obj1, true), mods),
365
+ obj2,
366
+ merge
367
+ )
344
368
  } else {
345
369
  merge = mods
346
370
  this.set(target, this.pick(source, obj1, true), obj2, merge)
@@ -365,16 +389,16 @@ DotObject.prototype.transfer = function (source, target, obj1, obj2, mods, merge
365
389
  */
366
390
  DotObject.prototype.copy = function (source, target, obj1, obj2, mods, merge) {
367
391
  if (typeof mods === 'function' || Array.isArray(mods)) {
368
- this.set(target,
392
+ this.set(
393
+ target,
369
394
  _process(
370
395
  // clone what is picked
371
- JSON.parse(
372
- JSON.stringify(
373
- this.pick(source, obj1, false)
374
- )
375
- ),
396
+ JSON.parse(JSON.stringify(this.pick(source, obj1, false))),
376
397
  mods
377
- ), obj2, merge)
398
+ ),
399
+ obj2,
400
+ merge
401
+ )
378
402
  } else {
379
403
  merge = mods
380
404
  this.set(target, this.pick(source, obj1, false), obj2, merge)
@@ -406,7 +430,7 @@ DotObject.prototype.set = function (path, val, obj, merge) {
406
430
 
407
431
  for (i = 0; i < keys.length; i++) {
408
432
  key = keys[i]
409
- if (i === (keys.length - 1)) {
433
+ if (i === keys.length - 1) {
410
434
  if (merge && isObject(val) && isObject(obj[key])) {
411
435
  for (k in val) {
412
436
  if (hasOwnProperty.call(val, k)) {
@@ -445,14 +469,14 @@ DotObject.prototype.set = function (path, val, obj, merge) {
445
469
  *
446
470
  * var obj = {
447
471
  * "id": 1,
448
- * "some": {
449
- * "thing": "else"
450
- * }
472
+ * "some": {
473
+ * "thing": "else"
474
+ * }
451
475
  * }
452
476
  *
453
477
  * var transform = {
454
478
  * "id": "nr",
455
- * "some.thing": "name"
479
+ * "some.thing": "name"
456
480
  * }
457
481
  *
458
482
  * var tgt = dot.transform(transform, obj)
@@ -464,9 +488,11 @@ DotObject.prototype.set = function (path, val, obj, merge) {
464
488
  DotObject.prototype.transform = function (recipe, obj, tgt) {
465
489
  obj = obj || {}
466
490
  tgt = tgt || {}
467
- Object.keys(recipe).forEach(function (key) {
468
- this.set(recipe[key], this.pick(key, obj), tgt)
469
- }.bind(this))
491
+ Object.keys(recipe).forEach(
492
+ function (key) {
493
+ this.set(recipe[key], this.pick(key, obj), tgt)
494
+ }.bind(this)
495
+ )
470
496
  return tgt
471
497
  }
472
498
 
@@ -492,30 +518,33 @@ DotObject.prototype.dot = function (obj, tgt, path) {
492
518
  path = path || []
493
519
  var isArray = Array.isArray(obj)
494
520
 
495
- Object.keys(obj).forEach(function (key) {
496
- var index = isArray && this.useBrackets ? '[' + key + ']' : key
497
- if (
498
- (
521
+ Object.keys(obj).forEach(
522
+ function (key) {
523
+ var index = isArray && this.useBrackets ? '[' + key + ']' : key
524
+ if (
499
525
  isArrayOrObject(obj[key]) &&
500
- (
501
- (isObject(obj[key]) && !isEmptyObject(obj[key])) ||
502
- (Array.isArray(obj[key]) && (!this.keepArray && (obj[key].length !== 0)))
503
- )
504
- )
505
- ) {
506
- if (isArray && this.useBrackets) {
507
- return this.dot(obj[key], tgt, path.slice(0, -1).concat(path[path.length - 1] + index))
508
- } else {
509
- return this.dot(obj[key], tgt, path.concat(index))
510
- }
511
- } else {
512
- if (isArray && this.useBrackets) {
513
- tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
526
+ ((isObject(obj[key]) && !isEmptyObject(obj[key])) ||
527
+ (Array.isArray(obj[key]) && !this.keepArray && obj[key].length !== 0))
528
+ ) {
529
+ if (isArray && this.useBrackets) {
530
+ var previousKey = path[path.length - 1] || ''
531
+ return this.dot(
532
+ obj[key],
533
+ tgt,
534
+ path.slice(0, -1).concat(previousKey + index)
535
+ )
536
+ } else {
537
+ return this.dot(obj[key], tgt, path.concat(index))
538
+ }
514
539
  } else {
515
- tgt[path.concat(index).join(this.separator)] = obj[key]
540
+ if (isArray && this.useBrackets) {
541
+ tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
542
+ } else {
543
+ tgt[path.concat(index).join(this.separator)] = obj[key]
544
+ }
516
545
  }
517
- }
518
- }.bind(this))
546
+ }.bind(this)
547
+ )
519
548
  return tgt
520
549
  }
521
550
 
@@ -529,9 +558,8 @@ DotObject.str = wrap('str')
529
558
  DotObject.set = wrap('set')
530
559
  DotObject.delete = wrap('delete')
531
560
  DotObject.del = DotObject.remove = wrap('remove')
532
- DotObject.dot = wrap('dot')
533
-
534
- ;['override', 'overwrite'].forEach(function (prop) {
561
+ DotObject.dot = wrap('dot');
562
+ ['override', 'overwrite'].forEach(function (prop) {
535
563
  Object.defineProperty(DotObject, prop, {
536
564
  get: function () {
537
565
  return dotDefault.override
@@ -540,9 +568,8 @@ DotObject.dot = wrap('dot')
540
568
  dotDefault.override = !!val
541
569
  }
542
570
  })
543
- })
544
-
545
- ;['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
571
+ });
572
+ ['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
546
573
  Object.defineProperty(DotObject, prop, {
547
574
  get: function () {
548
575
  return dotDefault[prop]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dot-object",
3
3
  "description": "dot-object makes it possible to transform and read (JSON) objects using dot notation.",
4
- "version": "2.1.0",
4
+ "version": "2.1.4",
5
5
  "author": {
6
6
  "name": "Rob Halff",
7
7
  "email": "rob.halff@gmail.com"
package/src/dot-object.js CHANGED
@@ -45,11 +45,23 @@ function isEmptyObject (val) {
45
45
  return Object.keys(val).length === 0
46
46
  }
47
47
 
48
+ var blacklist = ['__proto__', 'prototype', 'constructor']
49
+ var blacklistFilter = function (part) { return blacklist.indexOf(part) === -1 }
50
+
48
51
  function parsePath (path, sep) {
49
52
  if (path.indexOf('[') >= 0) {
50
- path = path.replace(/\[/g, '.').replace(/]/g, '')
53
+ path = path.replace(/\[/g, sep).replace(/]/g, '')
54
+ }
55
+
56
+ var parts = path.split(sep)
57
+
58
+ var check = parts.filter(blacklistFilter)
59
+
60
+ if (check.length !== parts.length) {
61
+ throw Error('Refusing to update blacklisted property ' + path)
51
62
  }
52
- return path.split(sep)
63
+
64
+ return parts
53
65
  }
54
66
 
55
67
  var hasOwnProperty = Object.prototype.hasOwnProperty
@@ -83,8 +95,7 @@ DotObject.prototype._fill = function (a, obj, v, mod) {
83
95
  var k = a.shift()
84
96
 
85
97
  if (a.length > 0) {
86
- obj[k] = obj[k] ||
87
- (this.useArray && isIndex(a[0]) ? [] : {})
98
+ obj[k] = obj[k] || (this.useArray && isIndex(a[0]) ? [] : {})
88
99
 
89
100
  if (!isArrayOrObject(obj[k])) {
90
101
  if (this.override) {
@@ -102,8 +113,7 @@ DotObject.prototype._fill = function (a, obj, v, mod) {
102
113
 
103
114
  this._fill(a, obj[k], v, mod)
104
115
  } else {
105
- if (!this.override &&
106
- isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
116
+ if (!this.override && isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
107
117
  if (!(isArrayOrObject(v) && isEmptyObject(v))) {
108
118
  throw new Error("Trying to redefine non-empty obj['" + k + "']")
109
119
  }
@@ -163,8 +173,10 @@ DotObject.prototype.object = function (obj, mods) {
163
173
  * @param {Function|Array} mod optional modifier
164
174
  */
165
175
  DotObject.prototype.str = function (path, v, obj, mod) {
176
+ var ok = parsePath(path, this.separator).join(this.separator)
177
+
166
178
  if (path.indexOf(this.separator) !== -1) {
167
- this._fill(path.split(this.separator), obj, v, mod)
179
+ this._fill(ok.split(this.separator), obj, v, mod)
168
180
  } else {
169
181
  obj[path] = _process(v, mod)
170
182
  }
@@ -193,7 +205,7 @@ DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
193
205
  for (i = 0; i < keys.length; i++) {
194
206
  key = parseKey(keys[i], obj)
195
207
  if (obj && typeof obj === 'object' && key in obj) {
196
- if (i === (keys.length - 1)) {
208
+ if (i === keys.length - 1) {
197
209
  if (remove) {
198
210
  val = obj[key]
199
211
  if (reindexArray && Array.isArray(obj)) {
@@ -219,7 +231,9 @@ DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
219
231
  }
220
232
  }
221
233
  if (remove && Array.isArray(obj)) {
222
- obj = obj.filter(function (n) { return n !== undefined })
234
+ obj = obj.filter(function (n) {
235
+ return n !== undefined
236
+ })
223
237
  }
224
238
  return obj
225
239
  }
@@ -277,7 +291,9 @@ DotObject.prototype._cleanup = function (obj) {
277
291
  keys = this.cleanup[i].split('.')
278
292
  root = keys.splice(0, -1).join('.')
279
293
  ret = root ? this.pick(root, obj) : obj
280
- ret = ret[keys[0]].filter(function (v) { return v !== undefined })
294
+ ret = ret[keys[0]].filter(function (v) {
295
+ return v !== undefined
296
+ })
281
297
  this.set(this.cleanup[i], ret, obj)
282
298
  }
283
299
  this.cleanup = []
@@ -334,13 +350,21 @@ DotObject.prototype.move = function (source, target, obj, mods, merge) {
334
350
  * @param {Function|Array} mods
335
351
  * @param {Boolean} merge
336
352
  */
337
- DotObject.prototype.transfer = function (source, target, obj1, obj2, mods, merge) {
353
+ DotObject.prototype.transfer = function (
354
+ source,
355
+ target,
356
+ obj1,
357
+ obj2,
358
+ mods,
359
+ merge
360
+ ) {
338
361
  if (typeof mods === 'function' || Array.isArray(mods)) {
339
- this.set(target,
340
- _process(
341
- this.pick(source, obj1, true),
342
- mods
343
- ), obj2, merge)
362
+ this.set(
363
+ target,
364
+ _process(this.pick(source, obj1, true), mods),
365
+ obj2,
366
+ merge
367
+ )
344
368
  } else {
345
369
  merge = mods
346
370
  this.set(target, this.pick(source, obj1, true), obj2, merge)
@@ -365,16 +389,16 @@ DotObject.prototype.transfer = function (source, target, obj1, obj2, mods, merge
365
389
  */
366
390
  DotObject.prototype.copy = function (source, target, obj1, obj2, mods, merge) {
367
391
  if (typeof mods === 'function' || Array.isArray(mods)) {
368
- this.set(target,
392
+ this.set(
393
+ target,
369
394
  _process(
370
395
  // clone what is picked
371
- JSON.parse(
372
- JSON.stringify(
373
- this.pick(source, obj1, false)
374
- )
375
- ),
396
+ JSON.parse(JSON.stringify(this.pick(source, obj1, false))),
376
397
  mods
377
- ), obj2, merge)
398
+ ),
399
+ obj2,
400
+ merge
401
+ )
378
402
  } else {
379
403
  merge = mods
380
404
  this.set(target, this.pick(source, obj1, false), obj2, merge)
@@ -406,7 +430,7 @@ DotObject.prototype.set = function (path, val, obj, merge) {
406
430
 
407
431
  for (i = 0; i < keys.length; i++) {
408
432
  key = keys[i]
409
- if (i === (keys.length - 1)) {
433
+ if (i === keys.length - 1) {
410
434
  if (merge && isObject(val) && isObject(obj[key])) {
411
435
  for (k in val) {
412
436
  if (hasOwnProperty.call(val, k)) {
@@ -445,14 +469,14 @@ DotObject.prototype.set = function (path, val, obj, merge) {
445
469
  *
446
470
  * var obj = {
447
471
  * "id": 1,
448
- * "some": {
449
- * "thing": "else"
450
- * }
472
+ * "some": {
473
+ * "thing": "else"
474
+ * }
451
475
  * }
452
476
  *
453
477
  * var transform = {
454
478
  * "id": "nr",
455
- * "some.thing": "name"
479
+ * "some.thing": "name"
456
480
  * }
457
481
  *
458
482
  * var tgt = dot.transform(transform, obj)
@@ -464,9 +488,11 @@ DotObject.prototype.set = function (path, val, obj, merge) {
464
488
  DotObject.prototype.transform = function (recipe, obj, tgt) {
465
489
  obj = obj || {}
466
490
  tgt = tgt || {}
467
- Object.keys(recipe).forEach(function (key) {
468
- this.set(recipe[key], this.pick(key, obj), tgt)
469
- }.bind(this))
491
+ Object.keys(recipe).forEach(
492
+ function (key) {
493
+ this.set(recipe[key], this.pick(key, obj), tgt)
494
+ }.bind(this)
495
+ )
470
496
  return tgt
471
497
  }
472
498
 
@@ -492,30 +518,33 @@ DotObject.prototype.dot = function (obj, tgt, path) {
492
518
  path = path || []
493
519
  var isArray = Array.isArray(obj)
494
520
 
495
- Object.keys(obj).forEach(function (key) {
496
- var index = isArray && this.useBrackets ? '[' + key + ']' : key
497
- if (
498
- (
521
+ Object.keys(obj).forEach(
522
+ function (key) {
523
+ var index = isArray && this.useBrackets ? '[' + key + ']' : key
524
+ if (
499
525
  isArrayOrObject(obj[key]) &&
500
- (
501
- (isObject(obj[key]) && !isEmptyObject(obj[key])) ||
502
- (Array.isArray(obj[key]) && (!this.keepArray && (obj[key].length !== 0)))
503
- )
504
- )
505
- ) {
506
- if (isArray && this.useBrackets) {
507
- return this.dot(obj[key], tgt, path.slice(0, -1).concat(path[path.length - 1] + index))
508
- } else {
509
- return this.dot(obj[key], tgt, path.concat(index))
510
- }
511
- } else {
512
- if (isArray && this.useBrackets) {
513
- tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
526
+ ((isObject(obj[key]) && !isEmptyObject(obj[key])) ||
527
+ (Array.isArray(obj[key]) && !this.keepArray && obj[key].length !== 0))
528
+ ) {
529
+ if (isArray && this.useBrackets) {
530
+ var previousKey = path[path.length - 1] || ''
531
+ return this.dot(
532
+ obj[key],
533
+ tgt,
534
+ path.slice(0, -1).concat(previousKey + index)
535
+ )
536
+ } else {
537
+ return this.dot(obj[key], tgt, path.concat(index))
538
+ }
514
539
  } else {
515
- tgt[path.concat(index).join(this.separator)] = obj[key]
540
+ if (isArray && this.useBrackets) {
541
+ tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
542
+ } else {
543
+ tgt[path.concat(index).join(this.separator)] = obj[key]
544
+ }
516
545
  }
517
- }
518
- }.bind(this))
546
+ }.bind(this)
547
+ )
519
548
  return tgt
520
549
  }
521
550
 
@@ -529,9 +558,8 @@ DotObject.str = wrap('str')
529
558
  DotObject.set = wrap('set')
530
559
  DotObject.delete = wrap('delete')
531
560
  DotObject.del = DotObject.remove = wrap('remove')
532
- DotObject.dot = wrap('dot')
533
-
534
- ;['override', 'overwrite'].forEach(function (prop) {
561
+ DotObject.dot = wrap('dot');
562
+ ['override', 'overwrite'].forEach(function (prop) {
535
563
  Object.defineProperty(DotObject, prop, {
536
564
  get: function () {
537
565
  return dotDefault.override
@@ -540,9 +568,8 @@ DotObject.dot = wrap('dot')
540
568
  dotDefault.override = !!val
541
569
  }
542
570
  })
543
- })
544
-
545
- ;['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
571
+ });
572
+ ['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
546
573
  Object.defineProperty(DotObject, prop, {
547
574
  get: function () {
548
575
  return dotDefault[prop]
@@ -167,4 +167,10 @@ describe('Dotted Array notation', function () {
167
167
  describe('with bracket notation', function () {
168
168
  runVariant('bracket')
169
169
  })
170
+
171
+ describe('Refuse to update __proto__', function () {
172
+ var obj = { path: [] }
173
+
174
+ ;(() => Dot.set('path[0].__proto__.toString', 'test', obj)).should.throw(/Refusing to update/)
175
+ })
170
176
  })
package/test/dot-json.js CHANGED
@@ -55,6 +55,28 @@ describe('Object test:', function () {
55
55
  })
56
56
  })
57
57
 
58
+ it('Should expand dotted keys with array notation with different separator', function () {
59
+ var row = {
60
+ id: 2,
61
+ my_arr_0: 'one',
62
+ my_arr_1: 'two',
63
+ my_arr_2: 'three',
64
+ 'my_arr2[0]': 'one',
65
+ 'my_arr2[1]': 'two',
66
+ 'my_arr2[2]': 'three'
67
+ }
68
+
69
+ new Dot('_').object(row)
70
+
71
+ row.should.eql({
72
+ id: 2,
73
+ my: {
74
+ arr: ['one', 'two', 'three'],
75
+ arr2: ['one', 'two', 'three']
76
+ }
77
+ })
78
+ })
79
+
58
80
  it('Should allow keys with numbers', function () {
59
81
  var row = {
60
82
  id: 2,
@@ -205,4 +227,11 @@ describe('Object test:', function () {
205
227
 
206
228
  row.should.eql({ page: { name: 'my_page' } })
207
229
  })
230
+
231
+ it('Dot.object should disallow to set __proto__', function () {
232
+ var row = { '__proto__.toString': 'hi' }
233
+
234
+ var dot = new Dot()
235
+ ;(() => dot.object(row)).should.throw(/Refusing to update/)
236
+ })
208
237
  })
package/test/dot.js CHANGED
@@ -7,6 +7,8 @@ var pkg = require('./fixtures/package.json')
7
7
  describe('dot():', function () {
8
8
  var obj
9
9
 
10
+ // Dot.useBrackets = false;
11
+
10
12
  beforeEach(function () {
11
13
  obj = {
12
14
  id: 'my-id',
@@ -36,7 +38,25 @@ describe('dot():', function () {
36
38
  ehrm: 123,
37
39
  dates: {
38
40
  first: new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)')
39
- }
41
+ },
42
+ arrays: [
43
+ [
44
+ [
45
+ {
46
+ all: [
47
+ [
48
+ {
49
+ the: [
50
+ 'way',
51
+ ['down']
52
+ ]
53
+ }
54
+ ]
55
+ ]
56
+ }
57
+ ]
58
+ ]
59
+ ]
40
60
  }
41
61
  })
42
62
 
@@ -50,7 +70,9 @@ describe('dot():', function () {
50
70
  'some.array[0]': 'A',
51
71
  'some.array[1]': 'B',
52
72
  ehrm: 123,
53
- 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)')
73
+ 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)'),
74
+ 'arrays[0][0][0].all[0][0].the[0]': 'way',
75
+ 'arrays[0][0][0].all[0][0].the[1][0]': 'down'
54
76
  }
55
77
 
56
78
  Dot.dot(obj).should.eql(expected)
@@ -72,7 +94,8 @@ describe('dot():', function () {
72
94
  }],
73
95
  'some.array': ['A', 'B'],
74
96
  ehrm: 123,
75
- 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)')
97
+ 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)'),
98
+ arrays: JSON.parse(JSON.stringify(obj.arrays))
76
99
  }
77
100
 
78
101
  Dot.keepArray = true
@@ -92,10 +115,32 @@ describe('dot():', function () {
92
115
  'some.array[0]': 'A',
93
116
  'some.array[1]': 'B',
94
117
  ehrm: 123,
95
- 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)')
118
+ 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)'),
119
+ 'arrays[0][0][0].all[0][0].the[0]': 'way',
120
+ 'arrays[0][0][0].all[0][0].the[1][0]': 'down'
121
+ }
122
+
123
+ Dot.dot(obj).should.eql(expected)
124
+ })
125
+
126
+ it('useBrackets wrap indexes without brackets', function () {
127
+ var expected = {
128
+ id: 'my-id',
129
+ 'nes.ted.value': true,
130
+ 'other.nested.stuff': 5,
131
+ 'nested.array.0.with': 'object1',
132
+ 'nested.array.1.and': 'object2',
133
+ 'some.array.0': 'A',
134
+ 'some.array.1': 'B',
135
+ ehrm: 123,
136
+ 'dates.first': new Date('Mon Oct 13 2014 00:00:00 GMT+0100 (BST)'),
137
+ 'arrays.0.0.0.all.0.0.the.0': 'way',
138
+ 'arrays.0.0.0.all.0.0.the.1.0': 'down'
96
139
  }
97
140
 
141
+ Dot.useBrackets = false
98
142
  Dot.dot(obj).should.eql(expected)
143
+ Dot.useBrackets = true
99
144
  })
100
145
 
101
146
  it('Always keeps empty arrays', function () {
package/test/str.js CHANGED
@@ -24,6 +24,28 @@ describe('str:', function () {
24
24
  })
25
25
  })
26
26
 
27
+ it('can set nested with array notation', function () {
28
+ var obj = {
29
+ a: 1
30
+ }
31
+ Dot.str('object.fields[0].subfield', 'value', obj)
32
+ Dot.str('object.fields[1].subfield', 'value1', obj)
33
+
34
+ obj.should.deepEqual({
35
+ a: 1,
36
+ object: {
37
+ fields: [
38
+ {
39
+ subfield: 'value'
40
+ },
41
+ {
42
+ subfield: 'value1'
43
+ }
44
+ ]
45
+ }
46
+ })
47
+ })
48
+
27
49
  it('can set root level property regardless whether override is set', function () {
28
50
  Dot.str('a', 'b', {
29
51
  a: 1
@@ -31,4 +53,11 @@ describe('str:', function () {
31
53
  a: 'b'
32
54
  })
33
55
  })
56
+
57
+ it('cannot set __proto__ property', function () {
58
+ (() => Dot.str('__proto__.toString', 'hi', {})).should.throw(
59
+ /Refusing to update/
60
+ );
61
+ ({}.toString().should.deepEqual('[object Object]'))
62
+ })
34
63
  })