Skip to content

marianoguerra/clj-rhino

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

simple api to use rhino from clojure

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published