You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
2.5 KiB

'use strict';
function undefsafe(obj, path, value, __res) {
// I'm not super keen on this private function, but it's because
// it'll also be use in the browser and I wont *one* function exposed
function split(path) {
var res = [];
var level = 0;
var key = '';
for (var i = 0; i < path.length; i++) {
var c = path.substr(i, 1);
if (level === 0 && (c === '.' || c === '[')) {
if (c === '[') {
level++;
i++;
c = path.substr(i, 1);
}
if (key) {
// the first value could be a string
res.push(key);
}
key = '';
continue;
}
if (c === ']') {
level--;
key = key.slice(0, -1);
continue;
}
key += c;
}
res.push(key);
return res;
}
// bail if there's nothing
if (obj === undefined || obj === null) {
return undefined;
}
var parts = split(path);
var key = null;
var type = typeof obj;
var root = obj;
var parent = obj;
var star =
parts.filter(function(_) {
return _ === '*';
}).length > 0;
// we're dealing with a primitive
if (type !== 'object' && type !== 'function') {
return obj;
} else if (path.trim() === '') {
return obj;
}
key = parts[0];
var i = 0;
for (; i < parts.length; i++) {
key = parts[i];
parent = obj;
if (key === '*') {
// loop through each property
var prop = '';
var res = __res || [];
for (prop in parent) {
var shallowObj = undefsafe(
obj[prop],
parts.slice(i + 1).join('.'),
value,
res
);
if (shallowObj && shallowObj !== res) {
if ((value && shallowObj === value) || value === undefined) {
if (value !== undefined) {
return shallowObj;
}
res.push(shallowObj);
}
}
}
if (res.length === 0) {
return undefined;
}
return res;
}
if (Object.getOwnPropertyNames(obj).indexOf(key) == -1) {
return undefined;
}
obj = obj[key];
if (obj === undefined || obj === null) {
break;
}
}
// if we have a null object, make sure it's the one the user was after,
// if it's not (i.e. parts has a length) then give undefined back.
if (obj === null && i !== parts.length - 1) {
obj = undefined;
} else if (!star && value) {
key = path.split('.').pop();
parent[key] = value;
}
return obj;
}
if (typeof module !== 'undefined') {
module.exports = undefsafe;
}