Skip to content

Commit

Permalink
fix: javascript multithreaded exception
Browse files Browse the repository at this point in the history
  • Loading branch information
dainiusjocas committed Mar 9, 2021
1 parent 191366c commit 91bafbb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
11 changes: 9 additions & 2 deletions src/polyglot/js.clj
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
(let [^Context ctx (.build (Context/newBuilder (into-array String ["js"])))
^String wrapped-script (format "(query) => JSON.stringify((%s)(JSON.parse(query)))" script)
^Value f (.eval ctx "js" wrapped-script)]
(fn [^String value] (.asString (.execute f (object-array [value]))))))
(fn [^String value]
; Turns out that can't be accesses by multiple threads
; TODO: every thread should create its own Context
; https://medium.com/graalvm/multi-threaded-java-javascript-language-interoperability-in-graalvm-2f19c1f9c37b
(locking ctx
(.asString (.execute f (object-array [value])))))))

(defn script->transform-fn-vals
"Given a JavaScript source code snippet creates a function that expects
Expand All @@ -39,7 +44,9 @@
(let [^Context ctx (.build (Context/newBuilder (into-array String ["js"])))
^String wrapped-script (format "(...args) => { args[0] = JSON.parse(args[0]); return JSON.stringify((%s).apply(null, args));}" script)
^Value f (.eval ctx "js" wrapped-script)]
(fn [& vals] (.asString (.execute f (object-array vals))))))
(fn [& vals]
(locking ctx
(.asString (.execute f (object-array vals)))))))

(comment
(time
Expand Down
20 changes: 15 additions & 5 deletions test/polyglot_test.clj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(ns polyglot-test
(:require [clojure.test :refer :all]
[polyglot.js :as js]
[core.async :as a]
[core.json :as json]
[polyglot.js :as js]
[polyglot :as polyglot]))

(def empty-map {})
Expand All @@ -18,15 +19,24 @@
(let [input-string (json/encode nested-map)]
(is (= (json/encode (assoc-in nested-map [:foo :bar :quuz] "corge"))
(js/string->string input-string
"(s) => {
s['foo']['bar']['quuz'] = 'corge';
return s;
}")))))
"(s) => {
s['foo']['bar']['quuz'] = 'corge';
return s;
}")))))

(testing "invalid script"
(let [input-string (json/encode empty-map)]
(is (thrown? Exception (= input-string (js/string->string input-string "(s) => function")))))))

(deftest multithreaded-js
(let [data (json/encode {"foo" "bar"})
tf (polyglot.js/script->transform-fn
"(s) => {
s['foo'] = 'corge';
return s;
}")]
(is (= 100 (count (a/map-pipeline (fn [d] (tf d)) 10 (repeat 100 data)))))))

(deftest polyglot-map-transformations
(testing "simple cases"
(let [m empty-map]
Expand Down

0 comments on commit 91bafbb

Please sign in to comment.