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.
		
		
		
		
		
			
		
			
				
					
					
						
							205 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
	
	
							205 lines
						
					
					
						
							4.3 KiB
						
					
					
				/** | 
						|
 * Based on Kendo UI Core expression code <https://github.com/telerik/kendo-ui-core#license-information> | 
						|
 */ | 
						|
'use strict' | 
						|
 | 
						|
function Cache(maxSize) { | 
						|
  this._maxSize = maxSize | 
						|
  this.clear() | 
						|
} | 
						|
Cache.prototype.clear = function() { | 
						|
  this._size = 0 | 
						|
  this._values = {} | 
						|
} | 
						|
Cache.prototype.get = function(key) { | 
						|
  return this._values[key] | 
						|
} | 
						|
Cache.prototype.set = function(key, value) { | 
						|
  this._size >= this._maxSize && this.clear() | 
						|
  if (!this._values.hasOwnProperty(key)) { | 
						|
    this._size++ | 
						|
  } | 
						|
  return this._values[key] = value | 
						|
} | 
						|
 | 
						|
var SPLIT_REGEX = /[^.^\]^[]+|(?=\[\]|\.\.)/g, | 
						|
  DIGIT_REGEX = /^\d+$/, | 
						|
  LEAD_DIGIT_REGEX = /^\d/, | 
						|
  SPEC_CHAR_REGEX = /[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g, | 
						|
  CLEAN_QUOTES_REGEX = /^\s*(['"]?)(.*?)(\1)\s*$/, | 
						|
  MAX_CACHE_SIZE = 512 | 
						|
 | 
						|
var contentSecurityPolicy = false, | 
						|
  pathCache = new Cache(MAX_CACHE_SIZE), | 
						|
  setCache = new Cache(MAX_CACHE_SIZE), | 
						|
  getCache = new Cache(MAX_CACHE_SIZE) | 
						|
 | 
						|
try { | 
						|
  new Function('') | 
						|
} catch (error) { | 
						|
  contentSecurityPolicy = true | 
						|
} | 
						|
 | 
						|
module.exports = { | 
						|
  Cache: Cache, | 
						|
 | 
						|
  expr: expr, | 
						|
 | 
						|
  split: split, | 
						|
 | 
						|
  normalizePath: normalizePath, | 
						|
 | 
						|
  setter: contentSecurityPolicy | 
						|
    ? function(path) { | 
						|
      var parts = normalizePath(path) | 
						|
      return function(data, value) { | 
						|
        return setterFallback(parts, data, value) | 
						|
      } | 
						|
    } | 
						|
    : function(path) { | 
						|
      return setCache.get(path) || setCache.set( | 
						|
        path, | 
						|
        new Function( | 
						|
          'data, value', | 
						|
          expr(path, 'data') + ' = value' | 
						|
        ) | 
						|
      ) | 
						|
    }, | 
						|
 | 
						|
  getter: contentSecurityPolicy | 
						|
    ? function(path, safe) { | 
						|
      var parts = normalizePath(path) | 
						|
      return function(data) { | 
						|
        return getterFallback(parts, safe, data) | 
						|
      } | 
						|
    } | 
						|
    : function(path, safe) { | 
						|
      var key = path + '_' + safe | 
						|
      return getCache.get(key) || getCache.set( | 
						|
        key, | 
						|
        new Function('data', 'return ' + expr(path, safe, 'data')) | 
						|
      ) | 
						|
    }, | 
						|
 | 
						|
  join: function(segments) { | 
						|
    return segments.reduce(function(path, part) { | 
						|
      return ( | 
						|
        path + | 
						|
        (isQuoted(part) || DIGIT_REGEX.test(part) | 
						|
          ? '[' + part + ']' | 
						|
          : (path ? '.' : '') + part) | 
						|
      ) | 
						|
    }, '') | 
						|
  }, | 
						|
 | 
						|
  forEach: function(path, cb, thisArg) { | 
						|
    forEach(split(path), cb, thisArg) | 
						|
  } | 
						|
} | 
						|
 | 
						|
function setterFallback(parts, data, value) { | 
						|
  var index = 0, | 
						|
    len = parts.length | 
						|
  while (index < len - 1) { | 
						|
    data = data[parts[index++]] | 
						|
  } | 
						|
  data[parts[index]] = value | 
						|
} | 
						|
 | 
						|
function getterFallback(parts, safe, data) { | 
						|
  var index = 0, | 
						|
    len = parts.length | 
						|
  while (index < len) { | 
						|
    if (data != null || !safe) { | 
						|
      data = data[parts[index++]] | 
						|
    } else { | 
						|
      return | 
						|
    } | 
						|
  } | 
						|
  return data | 
						|
} | 
						|
 | 
						|
function normalizePath(path) { | 
						|
  return pathCache.get(path) || pathCache.set( | 
						|
    path, | 
						|
    split(path).map(function(part) { | 
						|
      return part.replace(CLEAN_QUOTES_REGEX, '$2') | 
						|
    }) | 
						|
  ) | 
						|
} | 
						|
 | 
						|
function split(path) { | 
						|
  return path.match(SPLIT_REGEX) | 
						|
} | 
						|
 | 
						|
function expr(expression, safe, param) { | 
						|
  expression = expression || '' | 
						|
 | 
						|
  if (typeof safe === 'string') { | 
						|
    param = safe | 
						|
    safe = false | 
						|
  } | 
						|
 | 
						|
  param = param || 'data' | 
						|
 | 
						|
  if (expression && expression.charAt(0) !== '[') expression = '.' + expression | 
						|
 | 
						|
  return safe ? makeSafe(expression, param) : param + expression | 
						|
} | 
						|
 | 
						|
function forEach(parts, iter, thisArg) { | 
						|
  var len = parts.length, | 
						|
    part, | 
						|
    idx, | 
						|
    isArray, | 
						|
    isBracket | 
						|
 | 
						|
  for (idx = 0; idx < len; idx++) { | 
						|
    part = parts[idx] | 
						|
 | 
						|
    if (part) { | 
						|
      if (shouldBeQuoted(part)) { | 
						|
        part = '"' + part + '"' | 
						|
      } | 
						|
 | 
						|
      isBracket = isQuoted(part) | 
						|
      isArray = !isBracket && /^\d+$/.test(part) | 
						|
 | 
						|
      iter.call(thisArg, part, isBracket, isArray, idx, parts) | 
						|
    } | 
						|
  } | 
						|
} | 
						|
 | 
						|
function isQuoted(str) { | 
						|
  return ( | 
						|
    typeof str === 'string' && str && ["'", '"'].indexOf(str.charAt(0)) !== -1 | 
						|
  ) | 
						|
} | 
						|
 | 
						|
function makeSafe(path, param) { | 
						|
  var result = param, | 
						|
    parts = split(path), | 
						|
    isLast | 
						|
 | 
						|
  forEach(parts, function(part, isBracket, isArray, idx, parts) { | 
						|
    isLast = idx === parts.length - 1 | 
						|
 | 
						|
    part = isBracket || isArray ? '[' + part + ']' : '.' + part | 
						|
 | 
						|
    result += part + (!isLast ? ' || {})' : ')') | 
						|
  }) | 
						|
 | 
						|
  return new Array(parts.length + 1).join('(') + result | 
						|
} | 
						|
 | 
						|
function hasLeadingNumber(part) { | 
						|
  return part.match(LEAD_DIGIT_REGEX) && !part.match(DIGIT_REGEX) | 
						|
} | 
						|
 | 
						|
function hasSpecialChars(part) { | 
						|
  return SPEC_CHAR_REGEX.test(part) | 
						|
} | 
						|
 | 
						|
function shouldBeQuoted(part) { | 
						|
  return !isQuoted(part) && (hasLeadingNumber(part) || hasSpecialChars(part)) | 
						|
}
 | 
						|
 |