(obj: any, path: PathType, value: any, opts: SetPathOpts)
| 143 | } |
| 144 | |
| 145 | function setPathInternal(obj: any, path: PathType, value: any, opts: SetPathOpts): any { |
| 146 | if (path.length == 0) { |
| 147 | if (opts.combinefn != null) { |
| 148 | return opts.combinefn(obj, value, opts); |
| 149 | } |
| 150 | return value; |
| 151 | } |
| 152 | const pathPart = path[0]; |
| 153 | if (typeof pathPart === "string") { |
| 154 | if (obj == null) { |
| 155 | if (opts.remove) { |
| 156 | return null; |
| 157 | } |
| 158 | obj = {}; |
| 159 | } |
| 160 | if (!isObject(obj)) { |
| 161 | if (opts.force) { |
| 162 | obj = {}; |
| 163 | } else { |
| 164 | throw new Error("Cannot set path on non-object: " + obj); |
| 165 | } |
| 166 | } |
| 167 | if (opts.remove && path.length == 1) { |
| 168 | delete obj[pathPart]; |
| 169 | if (isEmpty(obj)) { |
| 170 | return null; |
| 171 | } |
| 172 | return obj; |
| 173 | } |
| 174 | const newVal = setPathInternal(obj[pathPart], path.slice(1), value, opts); |
| 175 | if (opts.remove && newVal == null) { |
| 176 | delete obj[pathPart]; |
| 177 | if (isEmpty(obj)) { |
| 178 | return null; |
| 179 | } |
| 180 | return obj; |
| 181 | } |
| 182 | obj[pathPart] = newVal; |
| 183 | return obj; |
| 184 | } else if (typeof pathPart === "number") { |
| 185 | if (pathPart < 0 || !Number.isInteger(pathPart)) { |
| 186 | throw new Error("Invalid path part: " + pathPart); |
| 187 | } |
| 188 | if (obj == null) { |
| 189 | if (opts.remove) { |
| 190 | return null; |
| 191 | } |
| 192 | obj = []; |
| 193 | } |
| 194 | if (!isArray(obj)) { |
| 195 | if (opts.force) { |
| 196 | obj = []; |
| 197 | } else { |
| 198 | throw new Error("Cannot set path on non-array: " + obj); |
| 199 | } |
| 200 | } |
| 201 | if (opts.remove && path.length == 1) { |
| 202 | return removeFromArr(obj, pathPart); |
no test coverage detected