simple api to use rhino from clojure (Note: Originally a fork of: https://github.com/marianoguerra/clj-rhino)
This repository has been archived on 2023-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
Go to file
2014-02-20 18:10:22 -05:00
src add clojure function to easily toggle dynamic scope creation on/off 2014-02-20 18:10:22 -05:00
test/clj_rhino test defined? 2013-02-11 11:26:14 +01:00
.gitignore initial import 2013-01-08 16:55:55 +01:00
project.clj compile against java 1.6 2013-07-31 18:37:29 +02:00
README.rest add call-timeout function docs in README 2013-02-08 17:50:25 +01:00

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.