You can use clj->js, but you have to require it. Your macro will emit 
clojure.core/clj->js, which is incorrect. clj->js is defined in cljs.core, 
though, so you can require cljs.core and write (cljs.core/clj->js ...).

In this case, since you know the full js object structure, you could just use 
cljs.core/js-obj.


However, there are a few poorly documented or undocumented tricks you can use 
instead.

1. You can emit a js object literal directly using 
cljs.tagged-literals/read-js. This is the equivalent of using the #js reader 
literal in clojurescript:

(ns my.macros
  (:require [cljs.tagged-literals :refer [read-js]]))

(defmacro foo-bar-obj [] (read-js {:foo "bar"}))

This will produce the literal javascript code:

{"foo" "bar"}

No extra immediately-invoked function wrappers like js-obj would produce. If 
you provide a vector to read-js it will produce a js array literal.


2. You can access some clojurescript environment information at macro-expansion 
time using the functions in the cljs.analyzer namespace.  For example, if you 
want to know what namespace your function was in, you can evaluate 
(cljs.analyzer/resolve-var &env name) in your macro and get :name out of the 
map.

3. In clojurescript, catch can take ":default" in the type slot to mean "any 
object". This is a little better than using js/Object because it avoids an 
instanceof check. (Remember, type-checking exceptions is emulated in 
clojurescript--javascript just has "catch (e) {}".


Taking all these tips together:

(ns scratch.macros
  (:require cljs.core
            [cljs.tagged-literals :refer [read-js]]
            cljs.analyzer))

(defmacro deftry [name args & body]
  `(defn ~name ~args
     (try ~@body
          (catch :default e#
            (js/HoneyBadger.notify e#
              ~(read-js
                {:context
                 (read-js
                  {:function
                   (str (:name (cljs.analyzer/resolve-var &env name)))})}))))))


Compiled against this namespace:

(ns scratch.core
  (:require-macros [scratch.macros :as m]))

(m/deftry foo []
  (throw (ex-info "I am an Error" #js {})))

(foo)


Will produce the following js (with :optimizations :none):

goog.provide('scratch.core');
goog.require('cljs.core');
scratch.core.foo = (function foo(){
  try {
    throw cljs.core.ex_info.call(null,"I am an Error",{});
  } catch (e42843){
    var e__41630__auto__ = e42843;
    return HoneyBadger.notify(e__41630__auto__, {"context": {"function": 
"scratch.core/foo"}});
  }
});
scratch.core.foo.call(null);


On Sunday, August 17, 2014 10:03:49 AM UTC-5, Yehonathan Sharvit wrote:
> I am trying to write a macro deftry that defines a function enveloped in a 
> try/catch statement that will sends the error to Honeybadger. Everything 
> works fine except the fact that I don't know how to pass a js object to the 
> notify function of Honeybadger. It seems that I cannot call clj->js from 
> inside a macro definition. 
> 
> This is my code:
> 
> (defmacro deftry [name args & body]
>   `(defn ~name ~args
>      (try ~@body
>           (catch js/Object e#
>             (.notify js/Honeybadger e# (clj->js {:context {:function 
> '~name}}))))))
> 
> 
> Any idea how to solve this?

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to