Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / dot-prop / index.js
1 'use strict';
2 const isObj = require('is-obj');
3
4 const disallowedKeys = [
5         '__proto__',
6         'prototype',
7         'constructor'
8 ];
9
10 const isValidPath = pathSegments => !pathSegments.some(segment => disallowedKeys.includes(segment));
11
12 function getPathSegments(path) {
13         const pathArray = path.split('.');
14         const parts = [];
15
16         for (let i = 0; i < pathArray.length; i++) {
17                 let p = pathArray[i];
18
19                 while (p[p.length - 1] === '\\' && pathArray[i + 1] !== undefined) {
20                         p = p.slice(0, -1) + '.';
21                         p += pathArray[++i];
22                 }
23
24                 parts.push(p);
25         }
26
27         if (!isValidPath(parts)) {
28                 return [];
29         }
30
31         return parts;
32 }
33
34 module.exports = {
35         get(object, path, value) {
36                 if (!isObj(object) || typeof path !== 'string') {
37                         return value === undefined ? object : value;
38                 }
39
40                 const pathArray = getPathSegments(path);
41                 if (pathArray.length === 0) {
42                         return;
43                 }
44
45                 for (let i = 0; i < pathArray.length; i++) {
46                         if (!Object.prototype.propertyIsEnumerable.call(object, pathArray[i])) {
47                                 return value;
48                         }
49
50                         object = object[pathArray[i]];
51
52                         if (object === undefined || object === null) {
53                                 // `object` is either `undefined` or `null` so we want to stop the loop, and
54                                 // if this is not the last bit of the path, and
55                                 // if it did't return `undefined`
56                                 // it would return `null` if `object` is `null`
57                                 // but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied value, not `null`
58                                 if (i !== pathArray.length - 1) {
59                                         return value;
60                                 }
61
62                                 break;
63                         }
64                 }
65
66                 return object;
67         },
68
69         set(object, path, value) {
70                 if (!isObj(object) || typeof path !== 'string') {
71                         return object;
72                 }
73
74                 const root = object;
75                 const pathArray = getPathSegments(path);
76
77                 for (let i = 0; i < pathArray.length; i++) {
78                         const p = pathArray[i];
79
80                         if (!isObj(object[p])) {
81                                 object[p] = {};
82                         }
83
84                         if (i === pathArray.length - 1) {
85                                 object[p] = value;
86                         }
87
88                         object = object[p];
89                 }
90
91                 return root;
92         },
93
94         delete(object, path) {
95                 if (!isObj(object) || typeof path !== 'string') {
96                         return false;
97                 }
98
99                 const pathArray = getPathSegments(path);
100
101                 for (let i = 0; i < pathArray.length; i++) {
102                         const p = pathArray[i];
103
104                         if (i === pathArray.length - 1) {
105                                 delete object[p];
106                                 return true;
107                         }
108
109                         object = object[p];
110
111                         if (!isObj(object)) {
112                                 return false;
113                         }
114                 }
115         },
116
117         has(object, path) {
118                 if (!isObj(object) || typeof path !== 'string') {
119                         return false;
120                 }
121
122                 const pathArray = getPathSegments(path);
123                 if (pathArray.length === 0) {
124                         return false;
125                 }
126
127                 // eslint-disable-next-line unicorn/no-for-loop
128                 for (let i = 0; i < pathArray.length; i++) {
129                         if (isObj(object)) {
130                                 if (!(pathArray[i] in object)) {
131                                         return false;
132                                 }
133
134                                 object = object[pathArray[i]];
135                         } else {
136                                 return false;
137                         }
138                 }
139
140                 return true;
141         }
142 };