add from-clj to convert rhino to clojure objects

This commit is contained in:
Mariano Guerra 2013-01-09 14:06:24 +01:00
parent 91cfb163e9
commit eb42749079
2 changed files with 75 additions and 1 deletions

View file

@ -1,14 +1,22 @@
(ns clj-rhino
(:refer-clojure :exclude (eval get get-in set!))
(:import [org.mozilla.javascript Context UniqueTag]))
(:import [org.mozilla.javascript Context UniqueTag NativeArray NativeObject]))
(defprotocol RhinoConvertible
(-to-rhino [object scope ctx] "convert a value to a rhino compatible type"))
(defprotocol ClojureConvertible
(-from-rhino [object]
"convert a value from rhino to a more clojure friendly representation"))
(defn to-js [obj scope ctx]
"convert obj to a rhino compatible object"
(-to-rhino obj scope ctx))
(defn from-js [obj]
"convert obj from rhino into a clojure friendly representation"
(-from-rhino obj))
(defn- return-self [obj scope ctx] obj)
(defn to-js-array [arr scope ctx]
@ -52,6 +60,31 @@
;; Maybe a Java array, otherwise fail
(extend java.lang.Object RhinoConvertible {:-to-rhino to-js-generic})
(defn- entryset-to-pair [entry]
(let [str-key (.getKey entry)
key (keyword str-key)
js-value (.getValue entry)
val (from-js js-value)]
[key val]))
(defn- from-js-object [obj]
(apply hash-map (mapcat entryset-to-pair (.entrySet obj))))
(extend nil ClojureConvertible {:-from-rhino identity})
(extend java.lang.Boolean ClojureConvertible {:-from-rhino identity})
(extend java.lang.Number ClojureConvertible {:-from-rhino identity})
(extend java.math.BigInteger ClojureConvertible {:-from-rhino identity})
(extend java.math.BigDecimal ClojureConvertible {:-from-rhino identity})
(extend java.lang.CharSequence ClojureConvertible {:-from-rhino identity})
(extend java.lang.Object ClojureConvertible {:-from-rhino identity})
; NOTE: undefined and null will return nil, there are other tags which should not
; be produced from a js program
; https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/UniqueTag.java
(extend UniqueTag ClojureConvertible {:-from-rhino (fn [obj] nil)})
(extend NativeObject ClojureConvertible {:-from-rhino from-js-object})
(extend NativeArray ClojureConvertible {:-from-rhino (comp vec (partial map from-js))})
(def insecure-vars ["isXMLName" "uneval" "InternalError" "JavaException"
"With" "Call" "Script" "Iterator" "StopIteration",
"Packages" "java" "javax" "org" "com" "edu" "net"

View file

@ -16,6 +16,12 @@
(is (= (js/to-js item scope ctx) js-item)))
(map vector arr js-arr)))))
(defn- is-identity [value]
(is (= (js/from-js value) value)))
(defn- assert-simetric-convertion [obj1 scope ctx obj2]
(is (= (js/from-js (js/to-js obj1 scope ctx)) obj2)))
(deftest js-test
(testing "undefined? works"
(is (not (js/undefined? 1)))
@ -114,4 +120,39 @@
(js/with-context (fn [ctx]
(let [scope (js/new-safe-scope)]
(is (thrown? Exception (js/to-js (atom {}) scope ctx)))))))
(testing "from-js works"
(is-identity nil)
(is-identity 1)
(is-identity 1.2)
(is-identity "asd")
(is-identity true)
(js/with-context
(fn [ctx]
(let [scope (js/new-safe-scope)]
(is (= (js/from-js UniqueTag/NOT_FOUND) nil))
(assert-simetric-convertion [] scope ctx [])
(assert-simetric-convertion [1] scope ctx [1])
(assert-simetric-convertion [1 nil] scope ctx [1 nil])
(assert-simetric-convertion [1 nil 1.2] scope ctx [1 nil 1.2])
(assert-simetric-convertion [1 nil 1.2 "asd"] scope ctx
[1 nil 1.2 "asd"])
(assert-simetric-convertion [1 nil 1.2 "asd" true] scope ctx
[1 nil 1.2 "asd" true])
(assert-simetric-convertion {} scope ctx {})
(assert-simetric-convertion {:b 1} scope ctx {:b 1})
(assert-simetric-convertion {:b 1 "c" true} scope ctx
{:b 1 :c true})
(assert-simetric-convertion {:b 1 "c" true :foo nil} scope ctx
{:b 1 :c true :foo nil})
(assert-simetric-convertion {:b {:c {:d 4}}} scope ctx
{:b {:c {:d 4}}})
(assert-simetric-convertion {:b {"c" {:d 4}}} scope ctx
{:b {:c {:d 4}}})
(assert-simetric-convertion {:b {"c" {:d [{"e" 4}]}}} scope ctx
{:b {:c {:d [{:e 4}]}}})
))))
)