Skip to content

Range operator allows invalid expressions #242

@deepilla

Description

@deepilla

The range operator (..) expects both operands to be integers. It usually throws an error if this isn't true. However in some cases the type checking is bypassed (meaning that invalid expressions are evaluated without error). Two such cases are described below. The first definitely seems like a bug. The second looks like a bug but it's possible that this is the intended behaviour.

Case 1. When lhs > rhs

The range operator returns undefined if the left side is greater than the right side. This means that expressions like [10..1] evaluate to an empty array. But because this check comes before the type validation, any types that satisfy the JavaScript condition lhs > rhs trigger an undefined result and never get validated.

The following expressions are all invalid yet they all evaluate to [] instead of throwing a type error.

[10..1.5]

[true..false]

["dogs".."cats"]

[1..""]

[1..[]]

["a"..{}]

[1..false]

[2..true]

If you reverse the operands in any of these expressions, the condition lhs > rhs is no longer true and you get a type error as expected.

Case 2. Undefined inputs

The range operator returns undefined if either of its inputs evaluate to undefined. But again, this test happens before the types have been validated. So an undefined input can override a type error on the other input, e.g.

[0..true]   // error: right side is not an integer
[$x..true]  // returns []

[false..10]  // error: left side is not an integer
[false..$x]  // returns []

It's odd that the test for undefined inputs takes precedence over type checking. I would expect to be notified of the type violation even if the other input is undefined. After all, no value of $x makes those expressions valid.

The range operator isn't the only example of this. Numeric operators behave in the same way:

false + 1   // error: left side is not a number
false + $x  // returns undefined

And so do the comparison operators that validate types:

false > 1   // error: operands must be numbers or strings
false > $x  // returns false

It doesn't happen with function calls though:

$substringBefore("hello", 3)  // error: argument 2 does not match signature
$substringBefore($x, 3)       // same error

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions