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)
|
||||
(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]
|
||||
"return true if value is undefined"
|
||||
(= value (. UniqueTag NOT_FOUND)))
|
||||
|
@ -225,10 +233,12 @@
|
|||
"create a new scope using a safe root scope as parent"
|
||||
(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"
|
||||
(with-context-if-nil ctx (fn [ctx]
|
||||
(.compileFunction ctx scope code
|
||||
(or filename "<eval>")
|
||||
(or line-number 1) sec-domain))))
|
||||
(let [ctx (.enterContext (TimedContextFactory. 0))]
|
||||
(try
|
||||
(.compileFunction ctx scope code
|
||||
(or filename "<eval>")
|
||||
(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.
|
||||
// Throw Error instance to ensure that script will never
|
||||
// get control back through catch or finally.
|
||||
throw new Error();
|
||||
throw new TimeOutError(this.timeoutMillis);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(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)
|
||||
(:require [clj-rhino :as js]))
|
||||
|
||||
|
@ -197,7 +198,26 @@
|
|||
|
||||
(testing "eval-timeout times out on infinite loop"
|
||||
(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"
|
||||
(js/with-context
|
||||
|
|
Reference in a new issue