123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- '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 primative
- 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;
- }
- 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;
- }
|