stencilproject / Stencil

Stencil is a simple and powerful template language for Swift.
https://stencil.fuller.li
BSD 2-Clause "Simplified" License
2.34k stars 224 forks source link

Revisit behaviour of undefined values #248

Open ilyapuchka opened 6 years ago

ilyapuchka commented 6 years ago

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:

djbe commented 6 years ago

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

ilyapuchka commented 6 years ago

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.

djbe commented 6 years ago

Nah I mean for example:

ilyapuchka commented 6 years ago

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.

djbe commented 6 years ago

I think there may be multiple levels? And a != nil check is needed.

ilyapuchka commented 6 years ago

The same should actually apply to KVO, if we can't find property using recently introduced selector check - we should raise exception