Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 154 lines (132 sloc) 3.652 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
c595c07 @josh Remove pure evaluation
josh authored
7 def initialize(runtime, source = "")
82773bf @josh Context
josh authored
8 @runtime = runtime
c595c07 @josh Remove pure evaluation
josh authored
9 @source = source
50791dd @josh Add Context#call
josh authored
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 = {})
c595c07 @josh Remove pure evaluation
josh authored
19 compile_to_tempfile([@source, source].join("\n")) do |file|
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
20 extract_result(@runtime.send(:exec_runtime, file.path))
82773bf @josh Context
josh authored
21 end
22 end
23
f815272 @sstephenson properties -> identifier
authored
24 def call(identifier, *args)
25 eval "#{identifier}.apply(this, #{args.to_json})"
50791dd @josh Add Context#call
josh authored
26 end
27
82773bf @josh Context
josh authored
28 protected
29 def compile_to_tempfile(source)
30 tempfile = Tempfile.open("execjs")
31 tempfile.write compile(source)
32 tempfile.close
33 yield tempfile
34 ensure
35 tempfile.close!
36 end
37
38 def compile(source)
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
39 @runtime.send(:runner_source).dup.tap do |output|
bd4c71c @josh Fix sub \ escaping
josh authored
40 output.sub!('#{source}') do
41 source
42 end
82773bf @josh Context
josh authored
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)
c595c07 @josh Remove pure evaluation
josh authored
73 context.exec(source)
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)
c595c07 @josh Remove pure evaluation
josh authored
78 context.eval(source)
0be476d @sstephenson Extract ExecJS::Runtime
authored
79 end
80
82773bf @josh Context
josh authored
81 def compile(source)
c595c07 @josh Remove pure evaluation
josh authored
82 Context.new(self, source)
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored
83 end
84
b22082f @sstephenson Add Runtime#available?
authored
85 def available?
c00ee39 @josh Support "nodejs" binary name
josh authored
86 @binary ? true : false
b22082f @sstephenson Add Runtime#available?
authored
87 end
88
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
89 protected
90 def runner_source
91 @runner_source ||= IO.read(@runner_path)
92 end
82773bf @josh Context
josh authored
93
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
94 def exec_runtime(filename)
95 output = sh("#{@binary} #{filename} 2>&1")
96 if $?.success?
97 output
98 else
99 raise RuntimeError, output
100 end
82773bf @josh Context
josh authored
101 end
102
c00ee39 @josh Support "nodejs" binary name
josh authored
103 def locate_binary
3cf772e @sstephenson Add `which` support for Windows
authored
104 if binary = which(@command)
c00ee39 @josh Support "nodejs" binary name
josh authored
105 if @test_args
106 output = `#{binary} #{@test_args} 2>&1`
107 binary if output.match(@test_match)
108 else
109 binary
110 end
111 end
112 end
113
3cf772e @sstephenson Add `which` support for Windows
authored
114 def which(command)
612c95e @josh Fix external runtime which to return the expanded path
josh authored
115 Array(command).each do |name|
8b22842 @sstephenson Add WSH JScript support
authored
116 name = name.split(/\s+/).first
3cf772e @sstephenson Add `which` support for Windows
authored
117 result = if ExecJS.windows?
118 `#{ExecJS.root}/support/which.bat #{name}`
119 else
120 `which #{name} 2>&1`
121 end
612c95e @josh Fix external runtime which to return the expanded path
josh authored
122
123 if path = result.strip.split("\n").first
124 return path
125 end
3cf772e @sstephenson Add `which` support for Windows
authored
126 end
612c95e @josh Fix external runtime which to return the expanded path
josh authored
127 nil
3cf772e @sstephenson Add `which` support for Windows
authored
128 end
129
24a41df @josh Fix JSC encoding
josh authored
130 if "".respond_to?(:force_encoding)
131 def sh(command)
132 output, options = nil, {}
133 options[:internal_encoding] = @conversion[:from] if @conversion
134 IO.popen(command, options) { |f| output = f.read }
135 output.force_encoding(@conversion[:to]) if @conversion
136 output
137 end
138 else
139 require "iconv"
140
141 def sh(command)
142 output = nil
143 IO.popen(command) { |f| output = f.read }
144
145 if @conversion
146 Iconv.iconv(@conversion[:from], @conversion[:to], output).first
147 else
148 output
149 end
150 end
151 end
0be476d @sstephenson Extract ExecJS::Runtime
authored
152 end
153 end
Something went wrong with that request. Please try again.