[Context] Ensure pop happens when an error is thrown

This commit is contained in:
Kyle Fuller
2016-03-05 00:23:08 +00:00
parent 48026cde2c
commit 67d4c52535
5 changed files with 26 additions and 36 deletions

View File

@@ -1,9 +1,9 @@
/// A container for template variables.
public class Context {
var dictionaries:[[String: Any]]
var dictionaries: [[String: Any]]
/// Initialise a Context with a dictionary
public init(dictionary:[String: Any]) {
public init(dictionary: [String: Any]) {
dictionaries = [dictionary]
}
@@ -35,20 +35,19 @@ public class Context {
}
/// Push a new level into the Context
public func push(dictionary: [String: Any]? = nil) {
private func push(dictionary: [String: Any]? = nil) {
dictionaries.append(dictionary ?? [:])
}
/// Pop the last level off of the Context
public func pop() -> [String: Any]? {
private func pop() -> [String: Any]? {
return dictionaries.popLast()
}
/// Push a new level onto the context for the duration of the execution of the given closure
public func push<Result>(dictionary: [String: Any]? = nil, @noescape closure: (() throws -> Result)) rethrows -> Result {
push(dictionary)
let result = try closure()
pop()
return result
defer { pop() }
return try closure()
}
}

View File

@@ -67,15 +67,12 @@ public class IfNode : NodeType {
truthy = true
}
context.push()
let output:String
if truthy {
output = try renderNodes(trueNodes, context)
} else {
output = try renderNodes(falseNodes, context)
return try context.push {
if truthy {
return try renderNodes(trueNodes, context)
} else {
return try renderNodes(falseNodes, context)
}
}
context.pop()
return output
}
}

View File

@@ -74,10 +74,9 @@ class ExtendsNode : NodeType {
}
let blockContext = BlockContext(blocks: blocks)
context.push([BlockContext.contextKey: blockContext])
let result = try template.render(context)
context.pop()
return result
return try context.push([BlockContext.contextKey: blockContext]) {
return try template.render(context)
}
}
}