Skip to content
simple api to use rhino from clojure
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
test/clj_rhino
.gitignore
README.rest
project.clj

README.rest

clj-rhino

a nice wrapper to handle rhino from clojure

who?

marianoguerra

why?

the java api for rhino is not really nice

how?

go to clojars page for instructions:

https://clojars.org/org.marianoguerra/clj-rhino

you can see the tests for some usage, here are some REPL examples:

user=> (require '[clj-rhino :as js])
nil
user=> (def sc (js/new-safe-scope))
#'user/sc
user=> (js/eval sc "1 + 1")
2
user=> (js/eval sc "a = 1 + 1")
2
user=> (js/get sc "a")
2
user=> (js/get sc "b")
#<UniqueTag org.mozilla.javascript.UniqueTag@172897f: NOT_FOUND>
user=> (js/undefined? (js/get sc "b"))
true
user=> (js/get sc "b" :w00t?)
:w00t?
user=> (js/defined? (js/get sc "b"))
false
user=> (js/set! sc "b" 42)
nil
user=> (js/defined? (js/get sc "b"))
true
user=> (js/get sc "b" :w00t?)
42
user=> (js/eval sc "a = {name: 'spongebob'}")
#<NativeObject [object Object]>
user=> (js/get-in sc [:a :name])
"spongebob"
user=> (js/get-in sc [:a :age])
#<UniqueTag org.mozilla.javascript.UniqueTag@172897f: NOT_FOUND>
user=> (js/get-in sc [:a :age] :dont-know)
:dont-know
user=> (def compiled-fun (js/compile-function sc "function (a, b) { return a + b; }" :filename "foo.js"))
#'user/compiled-fun
user=> (js/set! sc "add" compiled-fun)
nil
user=> (js/eval sc "add(1, 3)")
4.0

handy convertions:

user=> (def get-field (js/compile-function sc "function getField(obj, field) { return obj[field]; }"))
#'user/get-field

user=> (js/set! sc "getField" get-field)
nil

user=> (js/set! sc "obj" (js/with-context #(js/to-js {:name "spongebob"} sc %)))
nil

user=> (js/eval sc "getField(obj, 'name')")
"spongebob"

user=> (js/eval sc "o = {name: 'spongebob', friends: ['patrick', 'sandy']};")
#<NativeObject [object Object]>

user=> (js/from-js (js/eval sc "o = {name: 'spongebob', friends: ['patrick', 'sandy']};"))
{:friends ["patrick" "sandy"], :name "spongebob"}

exposing clojure functions to rhino:

user=> (require '[clj-rhino :as js])
nil

user=> (defn add [ctx scope this [a b]] (+ a b))
#'user/add

user=> (def scope (js/new-safe-scope))
#'user/scope

user=> (js/set! scope "add" (js/make-fn add))
nil

user=> (js/eval scope "add(1, 2)")
3.0

exposing objects with functions:

user=> (require '[clj-rhino :as js])
nil

user=> (defn add [ctx scope this [a b]] (+ a b))
#'user/add

user=> (defn mul [ctx scope this [a b]] (* a b))
#'user/mul

user=> (def scope (js/new-safe-scope))
#'user/scope

user=> (def api {:add add :multiply mul})
#'user/api

user=> (js/with-context (fn [ctx]
  #_=>   (js/set! scope "api" (js/to-js api scope ctx))
  #_=>   (js/eval scope "api.add(1, 2) + api.multiply(2, 3)")))
9.0

or if you don't need the internal parameters:

(js/with-context
  (fn [ctx]
    (let [scope (js/new-safe-scope)
          add (fn [a b] (+ a b))]

      (js/set! scope "add" (js/wrap-plain-fn add))
      (js/eval scope "add(1, 2)") 3.0)))

execute code with timeout:

(def scope (js/new-safe-scope))
(js/eval-timeout scope "while (true);" 1000)

; will throw a Error exception

call function with timeout:

user=> (def f (js/compile-function scope "function () { while(true); }"))
#'user/f
user=> (js/call-timeout scope f 1000)
TimeOutError
org.marianoguerra.rhino.TimedContextFactory.observeInstructionCount
(TimedContextFactory.java:47)

; function that doesn't timeout
user=> (def f1 (js/compile-function scope "function (a, b) { return a +
b; }"))
#'user/f1
user=> (js/call-timeout scope f1 1000 1 3)
4.0

license?

it seems the clojure people under this circumstances say something like:

Copyright © 2013 marianoguerra

Distributed under the Eclipse Public License, the same as Clojure.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.