cognitect / transit-cljs

Transit for ClojureScript
http://transit-format.org
Apache License 2.0
323 stars 20 forks source link

Write fails when data contains a js/Function instance #36

Closed James-Thibaudeau closed 7 years ago

James-Thibaudeau commented 7 years ago

I am trying to use transit as a means to send cljs data structures to a chrome extension without having to use clj->js on one end, send, and then js->clj on the other end. If the data structure contains a js/Function instance an error is thrown, cannot write. It seems to work if there is a js/Object instance as data.

I cannot guarantee that the data will not contain js/Function instances as data. Is there any way around this?

alex-dixon commented 7 years ago

Managed to get this working. Hope it helps:

#?(:cljs
   (defn fn->map [v]
     (let [xs (clojure.string/split (.-name v) #"\$")
           name (last xs)
           ns (clojure.string/join "." (butlast xs))]
       {:name (str ns "/" name)
        :ns ns
        :display-name name
        :type "js/Function"
        :fn? true
        :string (.toString v)})))

#?(:cljs
    (deftype FunctionHandler []
      Object
      (tag [this v] "map")
      (rep [this v] (fn->map v))
      (stringRep [this v])))

#?(:cljs
   (defn serialize [x]
     (let [writer (t/writer :json-verbose
                    {:handlers {js/Function (FunctionHandler.)}})]
       (t/write writer x))))

(serialize identity)
=>
"{\"~:name\":\"cljs.core/identity\",\"~:ns\":\"cljs.core\",\"~:display-name\":\"identity\",\"~:type\":\"js/Function\",\"~:fn?\":true,\"~:string\":\"function cljs$core$identity(x){\
 return x;\
 }\"}"
swannodette commented 7 years ago

This not an issue. Serializing functions is not in scope.