         (-> (r/read {:read-cond :allow :features #{:cljs}} rdr)
           meta :source)))))
 
+(defn- run-async!
+  "Like cljs.core/run!, but for an async procedure, and with the
+  ability to break prior to processing the entire collection.
+
+  Chains successive calls to the supplied procedure for items in
+  the collection. The procedure should accept an item from the
+  collection and a callback of one argument. If the break? predicate,
+  when applied to the procedure callback value, yields a truthy
+  result, terminates early calling the supplied cb with the callback
+  value. Otherwise, when complete, calls cb with nil."
+  [proc coll break? cb]
+  (if (seq coll)
+    (proc (first coll)
+      (fn [res]
+        (if (break? res)
+          (cb res)
+          (run-async! proc (rest coll) break? cb))))
+    (cb nil)))
+
+(defn- process-deps
+  [names opts cb]
+  (run-async! (fn [name cb]
+                (cljs/require name opts cb))
+    names
+    :error
+    cb))
+
+(defn- process-macros-deps
+  [cache cb]
+  (process-deps (distinct (vals (:require-macros cache))) {:macros-ns true} cb))
+
+(defn- process-libs-deps
+  [cache cb]
+  (process-deps (distinct (concat (vals (:requires cache)) (vals (:imports cache)))) {} cb))
+
 (defn execute-source
   [[source-type source-value] {:keys [expression? print-nil-expression? in-exit-context? include-stacktrace?] :as opts}]
   (binding [ana/*cljs-ns* @current-ns

          (if source
            (case lang
              :clj (execute-source ["text" source] opts)
              :js (js/eval source))
            (handle-error (js/Error. (str "Could not load file " source-value)) false in-exit-context?))))
      (let [source-text source-value
            expression-form (and expression? (repl-read-string source-text))]

              source-text
              (if expression? "Expression" "File")
              (merge
                {:ns         @current-ns
                 :source-map false
                 :verbose    (:verbose @app-env)}
                (if expression?
                  {:context       :expr
                   :def-emits-var true}
                  (when (:cache-path @app-env)
                    {:cache-source (fn [x cb]
                                     (when (and (= "File" (:name x)) (:source x))
                                       (let [source (:source x)
                                             [file-namespace relpath] (extract-cache-metadata-mem source-text)]
                                         (js/PLANCK_CACHE (cache-prefix-for-path relpath) source
                                           (when file-namespace
                                             (cljs->transit-json (get-in @st [:cljs.analyzer/namespaces file-namespace]))))))
                                     (cb {:value nil}))})))
              (fn [{:keys [ns value error] :as ret}]
                (if expression?
                  (when-not error
