stencilproject/Stencil

Context includes optionals holding `nil`

svanimpe opened this issue · 6 comments

I am using Stencil with Kitura and noticed that, when building a rendering context with instances of my own types (instead of a dictionary), that context includes properties that are nil. The if tag evaluates these properties as true, which is very confusing.

For example:

{% if post.lastUpdate %}
Last updated on {{ post.lastUpdate }}
{% endif %}

results in

Last updated on

because the lastUpdate property is present in the context even if it is nil.

kylef commented

I've just test this and I can't reproduce it:

diff --git a/Tests/StencilTests/IfNodeSpec.swift b/Tests/StencilTests/IfNodeSpec.swift
index f174b6a..844e0d6 100644
--- a/Tests/StencilTests/IfNodeSpec.swift
+++ b/Tests/StencilTests/IfNodeSpec.swift
@@ -253,5 +253,20 @@ func testIfNode() {
         let result = try renderNodes(nodes, Context(dictionary: ["value": "test"]))
         try expect(result) == "true"
     }
+
+    $0.it("supports nil as value") {
+      let tokens: [Token] = [
+        .block(value: "if value"),
+        .text(value: "true"),
+        .block(value: "endif")
+      ]
+
+      let parser = TokenParser(tokens: tokens, environment: Environment())
+      let nodes = try parser.parse()
+
+      let value: String? = nil
+      let result = try renderNodes(nodes, Context(dictionary: ["value": value]))
+      try expect(result) == ""
+    }
   }
 }

Do you have a specific way you are passing nil into the context? Is it NSNull?

kylef commented

@svanimpe Perhaps you can modify that test case to make it fail?

In my code, the optional is a property of an instance and not a top-level element of the context dictionary. If I change the test as follows, it fails:

let tokens: [Token] = [
    .block(value: "if instance.value"),
    .text(value: "true"),
    .block(value: "endif")
]

let parser = TokenParser(tokens: tokens, environment: Environment())
let nodes = try parser.parse()

struct SomeType {
    let value: String? = nil
}
let result = try renderNodes(nodes, Context(dictionary: ["instance": SomeType()]))
try expect(result) == ""

When will this fix be available in a release? I am currently working around this issue in some code I'd like to open source, but I'd rather not have to include (and explain) this workaround.

@kylef Is it possible to do a point release? There hasn't been a new release in 6 months now.

Thanks!