add function to call a function with a timeout
This commit is contained in:
parent
0439990ed6
commit
a122aa704e
|
@ -145,6 +145,14 @@
|
||||||
(.evaluateString ctx scope code filename line-number sec-domain)
|
(.evaluateString ctx scope code filename line-number sec-domain)
|
||||||
(finally (Context/exit)))))
|
(finally (Context/exit)))))
|
||||||
|
|
||||||
|
(defn call-timeout [scope fun timeout-ms & args]
|
||||||
|
(let [factory (TimedContextFactory. timeout-ms)
|
||||||
|
ctx (.enterContext factory)
|
||||||
|
args (into-array Object (map #(to-js % scope ctx) args))]
|
||||||
|
(try
|
||||||
|
(.call fun ctx scope nil args)
|
||||||
|
(finally (Context/exit)))))
|
||||||
|
|
||||||
(defn undefined? [value]
|
(defn undefined? [value]
|
||||||
"return true if value is undefined"
|
"return true if value is undefined"
|
||||||
(= value (. UniqueTag NOT_FOUND)))
|
(= value (. UniqueTag NOT_FOUND)))
|
||||||
|
@ -225,10 +233,12 @@
|
||||||
"create a new scope using a safe root scope as parent"
|
"create a new scope using a safe root scope as parent"
|
||||||
(new-scope ctx (new-safe-root-scope ctx)))
|
(new-scope ctx (new-safe-root-scope ctx)))
|
||||||
|
|
||||||
(defn compile-function [scope code & {:keys [ctx filename line-number sec-domain]}]
|
(defn compile-function [scope code & {:keys [filename line-number sec-domain]}]
|
||||||
"compile and return function defined in code"
|
"compile and return function defined in code"
|
||||||
(with-context-if-nil ctx (fn [ctx]
|
(let [ctx (.enterContext (TimedContextFactory. 0))]
|
||||||
|
(try
|
||||||
(.compileFunction ctx scope code
|
(.compileFunction ctx scope code
|
||||||
(or filename "<eval>")
|
(or filename "<eval>")
|
||||||
(or line-number 1) sec-domain))))
|
(or line-number 1) sec-domain)
|
||||||
|
(finally (Context/exit)))))
|
||||||
|
|
||||||
|
|
9
src/java/org/marianoguerra/rhino/TimeOutError.java
Normal file
9
src/java/org/marianoguerra/rhino/TimeOutError.java
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package org.marianoguerra.rhino;
|
||||||
|
|
||||||
|
public class TimeOutError extends Error {
|
||||||
|
public final long timeoutMillis;
|
||||||
|
|
||||||
|
public TimeOutError(long timeoutMillis) {
|
||||||
|
this.timeoutMillis = timeoutMillis;
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ public class TimedContextFactory extends ContextFactory {
|
||||||
// it is time to stop the script.
|
// it is time to stop the script.
|
||||||
// Throw Error instance to ensure that script will never
|
// Throw Error instance to ensure that script will never
|
||||||
// get control back through catch or finally.
|
// get control back through catch or finally.
|
||||||
throw new Error();
|
throw new TimeOutError(this.timeoutMillis);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns clj-rhino.core-test
|
(ns clj-rhino.core-test
|
||||||
(:import [org.mozilla.javascript Context UniqueTag EvaluatorException NativeArray])
|
(:import [org.mozilla.javascript Context UniqueTag EvaluatorException NativeArray]
|
||||||
|
[org.marianoguerra.rhino TimeOutError])
|
||||||
(:use clojure.test)
|
(:use clojure.test)
|
||||||
(:require [clj-rhino :as js]))
|
(:require [clj-rhino :as js]))
|
||||||
|
|
||||||
|
@ -197,7 +198,26 @@
|
||||||
|
|
||||||
(testing "eval-timeout times out on infinite loop"
|
(testing "eval-timeout times out on infinite loop"
|
||||||
(let [scope (js/new-safe-scope)]
|
(let [scope (js/new-safe-scope)]
|
||||||
(is (thrown? Error (js/eval-timeout scope "while (true);" 1000)))))
|
(is (thrown? TimeOutError (js/eval-timeout scope "while (true);" 1000)))))
|
||||||
|
|
||||||
|
(testing "call-timeout works"
|
||||||
|
(let [scope (js/new-safe-scope)
|
||||||
|
fun-code "function (a, b) { return a + b; }"
|
||||||
|
compiled-fun (js/compile-function scope fun-code)
|
||||||
|
result (js/call-timeout scope compiled-fun 1000 2 3)]
|
||||||
|
|
||||||
|
(is (= result 5.0))))
|
||||||
|
|
||||||
|
(testing "call-timeout timeouts correctly"
|
||||||
|
(let [scope (js/new-safe-scope)
|
||||||
|
fun-code "function (a, b) { while(true); }"
|
||||||
|
compiled-fun (js/compile-function scope fun-code)]
|
||||||
|
|
||||||
|
(try
|
||||||
|
(js/call-timeout scope compiled-fun 1000 2 3)
|
||||||
|
(throw (Exception. "shouldn't reach this point, should timeout"))
|
||||||
|
(catch TimeOutError error
|
||||||
|
(is (= (.-timeoutMillis error) 1000))))))
|
||||||
|
|
||||||
(testing "native clojure functions can be added"
|
(testing "native clojure functions can be added"
|
||||||
(js/with-context
|
(js/with-context
|
||||||
|
|
Reference in a new issue