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
			
		
		
			
		
	
	
					126 lines
				
				2.5 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'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;
							 | 
						||
| 
								 | 
							
								}
							 |