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.