property-expr
Advanced tools
Comparing version 1.5.1 to 2.0.0
148
index.js
@@ -12,3 +12,3 @@ /** | ||
this._size = 0 | ||
this._values = {} | ||
this._values = Object.create(null) | ||
} | ||
@@ -20,6 +20,5 @@ Cache.prototype.get = function(key) { | ||
this._size >= this._maxSize && this.clear() | ||
if (!this._values.hasOwnProperty(key)) { | ||
this._size++ | ||
} | ||
return this._values[key] = value | ||
if (!(key in this._values)) this._size++ | ||
return (this._values[key] = value) | ||
} | ||
@@ -34,12 +33,7 @@ | ||
var contentSecurityPolicy = false, | ||
pathCache = new Cache(MAX_CACHE_SIZE), | ||
var 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 | ||
} | ||
var config | ||
@@ -49,4 +43,2 @@ module.exports = { | ||
expr: expr, | ||
split: split, | ||
@@ -56,34 +48,34 @@ | ||
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' | ||
) | ||
) | ||
}, | ||
setter: function(path) { | ||
var parts = normalizePath(path) | ||
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')) | ||
) | ||
}, | ||
return ( | ||
setCache.get(path) || | ||
setCache.set(path, function setter(data, value) { | ||
var index = 0, | ||
len = parts.length | ||
while (index < len - 1) { | ||
data = data[parts[index++]] | ||
} | ||
data[parts[index]] = value | ||
}) | ||
) | ||
}, | ||
getter: function(path, safe) { | ||
var parts = normalizePath(path) | ||
return ( | ||
getCache.get(path) || | ||
getCache.set(path, function getter(data) { | ||
var index = 0, | ||
len = parts.length | ||
while (index < len) { | ||
if (data != null || !safe) data = data[parts[index++]] | ||
else return | ||
} | ||
return data | ||
}) | ||
) | ||
}, | ||
join: function(segments) { | ||
@@ -101,34 +93,15 @@ return segments.reduce(function(path, part) { | ||
forEach: function(path, cb, thisArg) { | ||
forEach(split(path), cb, thisArg) | ||
forEach(Array.isArray(path) ? path : 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') | ||
}) | ||
return ( | ||
pathCache.get(path) || | ||
pathCache.set( | ||
path, | ||
split(path).map(function(part) { | ||
return part.replace(CLEAN_QUOTES_REGEX, '$2') | ||
}) | ||
) | ||
) | ||
@@ -141,17 +114,2 @@ } | ||
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) { | ||
@@ -186,18 +144,2 @@ var len = parts.length, | ||
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) { | ||
@@ -204,0 +146,0 @@ return part.match(LEAD_DIGIT_REGEX) && !part.match(DIGIT_REGEX) |
{ | ||
"name": "property-expr", | ||
"version": "1.5.1", | ||
"version": "2.0.0", | ||
"description": "tiny util for getting and setting deep object props safely", | ||
"main": "index.js", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"index.js", | ||
"index.d.ts", | ||
"compiler.js" | ||
], | ||
"scripts": { | ||
@@ -7,0 +13,0 @@ "test": "node ./test.js", |
@@ -1,5 +0,4 @@ | ||
expr | ||
======= | ||
# expr | ||
Tiny expression helper for creating compiled accessors; handles most stuff, including ["bracket notation"] for property access. Originally based off of Kendo UI Core expression code | ||
Tiny property path utilities, including path parsing and metadata and deep property setters and getters | ||
@@ -10,17 +9,19 @@ npm install property-expr | ||
Setters and getters are compiled to functions and cached for Performance™ | ||
Setters and getters: | ||
var expr = require('property-expr') | ||
, obj = { | ||
foo: { | ||
bar: [ "hi", { buz: { baz: 'found me!' } }] | ||
} | ||
}; | ||
```js | ||
let expr = require('property-expr') | ||
let obj = { | ||
foo: { | ||
bar: ['hi', { buz: { baz: 'found me!' } }] | ||
} | ||
} | ||
var getBaz = expr.getter('foo.bar[1]["buz"].baz') | ||
, setBaz = expr.setter('foo.bar[1]["buz"].baz') | ||
let getBaz = expr.getter('foo.bar[1]["buz"].baz') | ||
let setBaz = expr.setter('foo.bar[1]["buz"].baz') | ||
console.log(getBaz(obj)) // => 'found me!' | ||
setBaz(obj, 'set me!') | ||
console.log(obj.foo.bar[1].buz.baz) // => 'set me!' | ||
console.log(getBaz(obj)) // => 'found me!' | ||
setBaz(obj, 'set me!') | ||
console.log(obj.foo.bar[1].buz.baz) // => 'set me!' | ||
``` | ||
@@ -31,4 +32,6 @@ ### `getter(expression, [ safeAccess ])` | ||
expr.getter('foo.bar.baz', true)({ foo: {} }) // => undefined | ||
//instead of val = foo.bar && foo.bar.baz | ||
```js | ||
expr.getter('foo.bar.baz', true)({ foo: {} }) // => undefined | ||
//instead of val = foo.bar && foo.bar.baz | ||
``` | ||
@@ -39,3 +42,2 @@ ### `setter(expression)` | ||
### `expr(expression, [ safeAccess], [ paramName = 'data'])` | ||
@@ -61,3 +63,9 @@ | ||
```js | ||
expr.forEach('foo["bar"][1]', function(pathSegment, isBracket, isArray, idx, segments) { | ||
expr.forEach('foo["bar"][1]', function( | ||
pathSegment, | ||
isBracket, | ||
isArray, | ||
idx, | ||
segments | ||
) { | ||
// 'foo' -> isBracket = false, isArray = false, idx = 0 | ||
@@ -72,2 +80,3 @@ // '"bar"' -> isBracket = true, isArray = false, idx = 1 | ||
Returns an array of path segments without quotes and spaces. | ||
```js | ||
@@ -81,2 +90,3 @@ expr.normalizePath('foo["bar"][ "1" ][2][ " sss " ]') | ||
Just an utility class, returns an instance of cache. When the max size is exceeded, cache clears its storage. | ||
```js | ||
@@ -92,1 +102,10 @@ var cache = new Cache(2) | ||
``` | ||
### CSP | ||
This pacakge used to rely on `new Function` to compile setters and getters into fast | ||
reusable functions. Since `new Function` is forbidden by folks using Content Security Policy `unsafe-eval` | ||
we've moved away from that approach. I believe that for most cases the perf hit is not noticable | ||
but if it is in your case please reach out. | ||
If you really want to use the old version require `property-expr/compiler` instead |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
105
9818
6
195
3