Revisit behaviour of undefined values
ilyapuchka opened this issue · 6 comments
Current behavior of Variable.resolve
when it encounters undefined values is IMO inconsistent with other kinds of errors, like an unknown filter, which results in an exception. Accessing undefined value, i.e. blog.uri
instead of blog.url
results in the empty output instead of exception or JavaScript-like output "undefined" which can be confusing for users.
Before #245 when resolving properties of collections unknown keys were simply skipped, resulting in contacts.something.0
render the same way as contacts.0
instead of raising an exception or returning nil
. With #245 resolving arrays and string properties was refactored so it will now return nil
. But the issue is still present for dictionaries.
Expected behavior:
- accessing undefined property should result in an exception by default, we can add configuration to allow ignoring such errors and printing them out as a warning or completely ignoring them and render empty string, "nil" or anything else
- rendering
nil
values can still result in an empty string or can be configured to render "undefined" or anything else per user choice, i.e. "nil"/"null" - resolving unknown properties on any collection type should behave the same way as resolving unknown properties of any other type
- accessing collection elements out of bounds should result in exception by default but can be configurable to warn in console or completely ignore this and render empty string, "nil" or anything else
I'm in the "throw error if it doesn't exist" camp, but might be best to have this configurable.
An issue might be that sometimes, you don't know if a property exists or not, and we have no way of knowing if the object blog
has a property url
or not, so even if we decide one way or the other, we might want to add some mechanism so that template writers can test for this.
Jinja has a whole bunch of undefined
types that can be configured, we might want to mirror some of that functionality (and obviously have a "decent" default setting):
http://jinja.pocoo.org/docs/2.10/api/#undefined-types
Yes, this should be configurable to some degree. Though what do you mean "don't know if a property exists or not"? We can add is defined
check to test for that, i.e. when resolving dictionary keys (to check if key contains nil
or is not present at all), but IMO as we are talking about Swift environment there shouldn't be such thing as "undefined" on any other type. Also should accessing out of bounds index in collection result in nil or exception? I'd say exception, but can be also configurable.
Nah I mean for example:
- Stencil is configured to the "throw exceptions" mode
- I write a template, but at some point, some property (or variable, ...) may or may not exist
- As a template writer, before I trigger an exception, I'd like to test if the property/variable/... exists
By "may not exist" you mean "value of the property is nil
at runtime" or "there is no such property on the type at all"?
In the first case, I think it should not through any exception by default and there should be a way to check for that at runtime, like != nil
in Swift. But we can have a "strict" mode that will treat accessing any nil
values as errors.
The second case should by default result in the exception, but this can be softened via configuration.
I think there may be multiple levels? And a != nil
check is needed.
- Accessing
nil
is okay, non-existing property is okay (returnsnil
) - Accessing
nil
is okay, non-existing property throws - Accessing
nil
throws, non-existing property throws
The same should actually apply to KVO, if we can't find property using recently introduced selector check - we should raise exception