Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/dot-prop/index.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
142 lines (109 sloc)
2.69 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const isObj = require('is-obj'); | |
const disallowedKeys = [ | |
'__proto__', | |
'prototype', | |
'constructor' | |
]; | |
const isValidPath = pathSegments => !pathSegments.some(segment => disallowedKeys.includes(segment)); | |
function getPathSegments(path) { | |
const pathArray = path.split('.'); | |
const parts = []; | |
for (let i = 0; i < pathArray.length; i++) { | |
let p = pathArray[i]; | |
while (p[p.length - 1] === '\\' && pathArray[i + 1] !== undefined) { | |
p = p.slice(0, -1) + '.'; | |
p += pathArray[++i]; | |
} | |
parts.push(p); | |
} | |
if (!isValidPath(parts)) { | |
return []; | |
} | |
return parts; | |
} | |
module.exports = { | |
get(object, path, value) { | |
if (!isObj(object) || typeof path !== 'string') { | |
return value === undefined ? object : value; | |
} | |
const pathArray = getPathSegments(path); | |
if (pathArray.length === 0) { | |
return; | |
} | |
for (let i = 0; i < pathArray.length; i++) { | |
if (!Object.prototype.propertyIsEnumerable.call(object, pathArray[i])) { | |
return value; | |
} | |
object = object[pathArray[i]]; | |
if (object === undefined || object === null) { | |
// `object` is either `undefined` or `null` so we want to stop the loop, and | |
// if this is not the last bit of the path, and | |
// if it did't return `undefined` | |
// it would return `null` if `object` is `null` | |
// but we want `get({foo: null}, 'foo.bar')` to equal `undefined`, or the supplied value, not `null` | |
if (i !== pathArray.length - 1) { | |
return value; | |
} | |
break; | |
} | |
} | |
return object; | |
}, | |
set(object, path, value) { | |
if (!isObj(object) || typeof path !== 'string') { | |
return object; | |
} | |
const root = object; | |
const pathArray = getPathSegments(path); | |
for (let i = 0; i < pathArray.length; i++) { | |
const p = pathArray[i]; | |
if (!isObj(object[p])) { | |
object[p] = {}; | |
} | |
if (i === pathArray.length - 1) { | |
object[p] = value; | |
} | |
object = object[p]; | |
} | |
return root; | |
}, | |
delete(object, path) { | |
if (!isObj(object) || typeof path !== 'string') { | |
return; | |
} | |
const pathArray = getPathSegments(path); | |
for (let i = 0; i < pathArray.length; i++) { | |
const p = pathArray[i]; | |
if (i === pathArray.length - 1) { | |
delete object[p]; | |
return; | |
} | |
object = object[p]; | |
if (!isObj(object)) { | |
return; | |
} | |
} | |
}, | |
has(object, path) { | |
if (!isObj(object) || typeof path !== 'string') { | |
return false; | |
} | |
const pathArray = getPathSegments(path); | |
if (pathArray.length === 0) { | |
return false; | |
} | |
// eslint-disable-next-line unicorn/no-for-loop | |
for (let i = 0; i < pathArray.length; i++) { | |
if (isObj(object)) { | |
if (!(pathArray[i] in object)) { | |
return false; | |
} | |
object = object[pathArray[i]]; | |
} else { | |
return false; | |
} | |
} | |
return true; | |
} | |
}; |