1
1
defmodule Execjs do
2
2
import Execjs.Escape , only: [ escape: 1 ]
3
3
4
+ defexception Error , message: nil
4
5
defexception RuntimeError , message: nil
6
+ defexception RuntimeUnavailable , message: "Could not find JavaScript runtime"
5
7
6
- defexception RuntimeUnavailable ,
7
- message: "Could not find a JavaScript runtime"
8
+ @ spec eval ( String . t ) :: any
9
+ def eval ( source ) when is_binary ( source ) do
10
+ exec % s [ eval ( "#{ escape ( source ) } " ) ]
11
+ end
8
12
9
- def compile ( source ) do
13
+ @ spec compile ( String . t ) :: ( String . t -> String . t )
14
+ def compile ( source ) when is_binary ( source ) do
10
15
{ pre , post } = { "(function(){\n #{ source } ;\n " , ";\n })()" }
11
16
fn ( source ) ->
12
17
pre <> source <> post
13
18
end
14
19
end
15
20
16
- def call ( context , thing , args ) do
17
- source = "return #{ thing } .apply(this, #{ JSON . encode! ( args ) } )"
18
- eval ( context . ( source ) )
21
+ @ spec call ( ( String . t -> String . t ) , String . t , list ( any ) ) :: any
22
+ def call ( context , identifier , args ) when is_binary ( identifier ) and is_list ( args ) do
23
+ source = "return #{ identifier } .apply(this, #{ JSON . encode! ( args ) } )"
24
+ exec context . ( source )
19
25
end
20
26
21
- def eval ( source ) do
27
+ defp exec ( source ) do
22
28
runtime = Execjs.Runtimes . best_available
23
- program = runtime . template ( escape ( source ) )
29
+ program = runtime . template ( source )
24
30
command = runtime . command |> System . find_executable
25
31
tmpfile = compile_to_tempfile ( program )
26
32
27
33
try do
28
34
port = Port . open ( { :spawn_executable , command } ,
29
35
[ :binary , :eof , :hide , { :args , [ tmpfile ] } ] )
30
36
31
- loop ( port )
37
+ extract_result ( loop ( port ) )
32
38
after
33
39
File . rm! tmpfile
34
40
end
@@ -55,4 +61,17 @@ defmodule Execjs do
55
61
File . write! path , program
56
62
path
57
63
end
64
+
65
+ defp extract_result ( output ) do
66
+ case JSON . decode! ( output ) do
67
+ [ "ok" , value ] ->
68
+ value
69
+ [ "ok" ] ->
70
+ :undefined
71
+ [ "err" , message ] ->
72
+ raise Execjs.RuntimeError , message: message
73
+ [ "err" ] ->
74
+ raise Execjs.Error
75
+ end
76
+ end
58
77
end
0 commit comments