Skip to content
Newer
Older
100644 152 lines (131 sloc) 3.49 KB
0be476d @sstephenson Extract ExecJS::Runtime
authored
1 require "json"
2 require "tempfile"
3
4 module ExecJS
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored
5 class ExternalRuntime
82773bf @josh Context
josh authored
6 class Context
7 def initialize(runtime)
8 @runtime = runtime
9 @script = ""
10 end
11
4bc602f @josh Pure function hint
josh authored
12 def eval(source, options = {})
82773bf @josh Context
josh authored
13 if /\S/ =~ source
14 exec("return eval(#{"(#{source})".to_json})")
15 end
16 end
17
4bc602f @josh Pure function hint
josh authored
18 def exec(source, options = {})
19 if !options[:pure]
20 @script << source
21 @script << "\n"
22 source = @script
23 end
82773bf @josh Context
josh authored
24
4bc602f @josh Pure function hint
josh authored
25 compile_to_tempfile(source) do |file|
82773bf @josh Context
josh authored
26 extract_result(@runtime.exec_runtime(file.path))
27 end
28 end
29
30 protected
31 def compile_to_tempfile(source)
32 tempfile = Tempfile.open("execjs")
33 tempfile.write compile(source)
34 tempfile.close
35 yield tempfile
36 ensure
37 tempfile.close!
38 end
39
40 def compile(source)
41 @runtime.runner_source.dup.tap do |output|
42 output.sub!('#{source}', source)
43 output.sub!('#{json2_source}') do
44 IO.read(ExecJS.root + "/support/json2.js")
45 end
46 end
47 end
48
49 def extract_result(output)
50 status, value = output.empty? ? [] : JSON.parse(output)
51 if status == "ok"
52 value
53 else
54 raise ProgramError, value
55 end
56 end
57 end
58
d19c760 @sstephenson Less magic
authored
59 attr_reader :name
60
954db08 @sstephenson Instantiate with options instead of subclassing
authored
61 def initialize(options)
d19c760 @sstephenson Less magic
authored
62 @name = options[:name]
954db08 @sstephenson Instantiate with options instead of subclassing
authored
63 @command = options[:command]
64 @runner_path = options[:runner_path]
5d0d51b @sstephenson therubyracer gem installs an incompatible `v8` binary - make sure we …
authored
65 @test_args = options[:test_args]
66 @test_match = options[:test_match]
24a41df @josh Fix JSC encoding
josh authored
67 @conversion = options[:conversion]
c00ee39 @josh Support "nodejs" binary name
josh authored
68 @binary = locate_binary
954db08 @sstephenson Instantiate with options instead of subclassing
authored
69 end
70
82773bf @josh Context
josh authored
71 def exec(source)
72 context = Context.new(self)
4bc602f @josh Pure function hint
josh authored
73 context.exec(source, :pure => true)
82773bf @josh Context
josh authored
74 end
75
0be476d @sstephenson Extract ExecJS::Runtime
authored
76 def eval(source)
82773bf @josh Context
josh authored
77 context = Context.new(self)
4bc602f @josh Pure function hint
josh authored
78 context.eval(source, :pure => true)
0be476d @sstephenson Extract ExecJS::Runtime
authored
79 end
80
82773bf @josh Context
josh authored
81 def compile(source)
82 context = Context.new(self)
83 context.exec(source)
84 context
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored
85 end
86
b22082f @sstephenson Add Runtime#available?
authored
87 def available?
c00ee39 @josh Support "nodejs" binary name
josh authored
88 @binary ? true : false
b22082f @sstephenson Add Runtime#available?
authored
89 end
90
82773bf @josh Context
josh authored
91 def runner_source
92 @runner_source ||= IO.read(@runner_path)
93 end
94
95 def exec_runtime(filename)
96 output = sh("#{@binary} #{filename} 2>&1")
97 if $?.success?
98 output
99 else
100 raise RuntimeError, output
101 end
102 end
103
0be476d @sstephenson Extract ExecJS::Runtime
authored
104 protected
c00ee39 @josh Support "nodejs" binary name
josh authored
105 def locate_binary
3cf772e @sstephenson Add `which` support for Windows
authored
106 if binary = which(@command)
c00ee39 @josh Support "nodejs" binary name
josh authored
107 if @test_args
108 output = `#{binary} #{@test_args} 2>&1`
109 binary if output.match(@test_match)
110 else
111 binary
112 end
113 end
114 end
115
3cf772e @sstephenson Add `which` support for Windows
authored
116 def which(command)
117 Array(command).find do |name|
8b22842 @sstephenson Add WSH JScript support
authored
118 name = name.split(/\s+/).first
3cf772e @sstephenson Add `which` support for Windows
authored
119 result = if ExecJS.windows?
120 `#{ExecJS.root}/support/which.bat #{name}`
121 else
122 `which #{name} 2>&1`
123 end
124 result.strip.split("\n").first
125 end
126 end
127
24a41df @josh Fix JSC encoding
josh authored
128 if "".respond_to?(:force_encoding)
129 def sh(command)
130 output, options = nil, {}
131 options[:internal_encoding] = @conversion[:from] if @conversion
132 IO.popen(command, options) { |f| output = f.read }
133 output.force_encoding(@conversion[:to]) if @conversion
134 output
135 end
136 else
137 require "iconv"
138
139 def sh(command)
140 output = nil
141 IO.popen(command) { |f| output = f.read }
142
143 if @conversion
144 Iconv.iconv(@conversion[:from], @conversion[:to], output).first
145 else
146 output
147 end
148 end
149 end
0be476d @sstephenson Extract ExecJS::Runtime
authored
150 end
151 end
Something went wrong with that request. Please try again.