[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

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

View File

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

View File

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

View File

@@ -27,29 +27,24 @@ func testContext() {
} }
$0.it("allows you to retrieve a value from a parent") { $0.it("allows you to retrieve a value from a parent") {
context.push() try context.push {
try expect(context["name"] as? String) == "Kyle" try expect(context["name"] as? String) == "Kyle"
} }
}
$0.it("allows you to override a parent's value") { $0.it("allows you to override a parent's value") {
context.push() try context.push {
context["name"] = "Katie" context["name"] = "Katie"
try expect(context["name"] as? String) == "Katie" try expect(context["name"] as? String) == "Katie"
} }
}
$0.it("allows you to pop to restore previous state") { $0.it("allows you to pop to restore previous state") {
context.push() context.push {
context["name"] = "Katie" context["name"] = "Katie"
context.pop()
try expect(context["name"] as? String) == "Kyle"
} }
$0.it("allows you to push a dictionary onto the stack") { try expect(context["name"] as? String) == "Kyle"
context.push(["name": "Katie"])
try expect(context["name"] as? String) == "Katie"
} }
$0.it("allows you to push a dictionary and run a closure then restoring previous state") { $0.it("allows you to push a dictionary and run a closure then restoring previous state") {

View File

@@ -21,7 +21,7 @@ func testVariable() {
]) ])
#if os(OSX) #if os(OSX)
context.push(["object": Object()]) context["object"] = Object()
#endif #endif
$0.it("can resolve a string literal with double quotes") { $0.it("can resolve a string literal with double quotes") {