   (or (:after c)
       (some has-after? (:parents c))))
 
-(defmacro #^{:private true} try-contexts
-  "Creates a try/finally block that opens contexts, stores their state
-  in states, and finally closes contexts.  active is the current map
-  of opened contexts."
-  [active contexts states & body]
-  `(let [active# ~active
-         contexts# ~contexts
-         merged# (reduce open-context active# contexts#)
-         ~states (map merged# contexts#)]
-     (try
-      ~@body
-      (finally
-       (reduce close-context merged#
-               ;; Only close contexts that weren't active at start:
-               (filter #(not (contains? active# %))
-                       (reverse contexts#)))))))
+(defn- close-local-contexts [contexts merged active]
+  (reduce close-context merged
+          ;; Only close contexts that weren't active at start:
+          (filter #(not (contains? active %))
+                  (reverse contexts))))
 
 ;;; Assertion types
 

    (invoke [] (invoke-test this {}))
  TestInvokable
    (invoke-test [active]
      (try-contexts active contexts states
        (let [results (map #(invoke-test % active) children)]
          ;; Force non-lazy evaluation when contexts need closing:
          (when (some has-after? contexts) (dorun results))
          (TestResults this results))
        (catch Throwable t
          (TestThrown this states t)))))


;;; Public API

(deftype ContextualAssertion [contexts pred] :as this
  TestInvokable
    (invoke-test [active]
      (let [merged (reduce open-context active contexts)
            states (map merged contexts)]
        (try
         (if (apply pred states)
           (TestPassed this states)
           (TestFailed this states))
         (catch Throwable t (TestThrown this states t))
         (finally (close-local-contexts contexts merged active))))))


;;; Container types
