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; | ||
|  | } |