TomFrost / Jexl

Javascript Expression Language: Powerful context-based expression parser and evaluator
MIT License
561 stars 92 forks source link

cannot read property 'length' of undefined #77

Closed DearGaz closed 4 years ago

DearGaz commented 4 years ago

Hi, there! @TomFrost thanks for your wonderful project (!!!!), which gives me a great favour in my projects! but i got a problem today ... when i eval 'length' of an empty array, error was thrown. An example here: const emptyArrayLength = jexl.eval('names.length', {names:[]}); // throw error: cannot read property 'length' of undefined

Shouldn't jexl return 0 ?

TomFrost commented 4 years ago

Hi DearGaz, thanks for the kind words! And my apologies for the late response on this.

Jexl has a hotly contested feature where, when you have an array and access a subproperty (meaning, myarray.prop), Jexl will grab the first element of the array and look for the property on that. That means that the syntax for queries like this is simplified and less likely to trip people up:

users[.role == 'admin'].name whereas otherwise you'd have to remember the [0]: users[.role == 'admin'][0].name

But that means, in your case, what's happening in the background is this:

names[0].length -- which, of course, errors because names[0] does not exist.

Here's the rub, though: Even if Jexl didn't have this feature, I still don't like assuming that .length returns the length of an array, because the Jexl expression syntax was written to be portable. There's a popular Python implementation today, and a couple weeks ago I spoke with an engineer porting it to Ruby as well. So this is the preferred way to resolve the length of an array:

jexl.addTransform('length', elem => elem.length)
jexl.evalSync('names|length', { names: [] }) // 0

Hope this helps!

DearGaz commented 4 years ago

A wonderful way! Thanks for your patience !