Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 154 lines (132 sloc) 3.735 kb
0be476d @sstephenson Extract ExecJS::Runtime
authored
1 require "tempfile"
2
3 module ExecJS
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored
4 class ExternalRuntime
82773bf @josh Context
josh authored
5 class Context
c595c07 @josh Remove pure evaluation
josh authored
6 def initialize(runtime, source = "")
82773bf @josh Context
josh authored
7 @runtime = runtime
c595c07 @josh Remove pure evaluation
josh authored
8 @source = source
50791dd @josh Add Context#call
josh authored
9 end
10
4bc602f @josh Pure function hint
josh authored
11 def eval(source, options = {})
82773bf @josh Context
josh authored
12 if /\S/ =~ source
3097959 @josh Switch to multi_json lib
josh authored
13 exec("return eval(#{MultiJson.encode("(#{source})")})")
82773bf @josh Context
josh authored
14 end
15 end
16
4bc602f @josh Pure function hint
josh authored
17 def exec(source, options = {})
c595c07 @josh Remove pure evaluation
josh authored
18 compile_to_tempfile([@source, source].join("\n")) do |file|
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
19 extract_result(@runtime.send(:exec_runtime, file.path))
82773bf @josh Context
josh authored
20 end
21 end
22
f815272 @sstephenson properties -> identifier
authored
23 def call(identifier, *args)
3097959 @josh Switch to multi_json lib
josh authored
24 eval "#{identifier}.apply(this, #{MultiJson.encode(args)})"
50791dd @josh Add Context#call
josh authored
25 end
26
82773bf @josh Context
josh authored
27 protected
28 def compile_to_tempfile(source)
6d42f54 @swaits force .js extension on tempfile to make win32 ExecJS happy
swaits authored
29 tempfile = Tempfile.open(["execjs",".js"])
82773bf @josh Context
josh authored
30 tempfile.write compile(source)
31 tempfile.close
32 yield tempfile
33 ensure
34 tempfile.close!
35 end
36
37 def compile(source)
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored
38 @runtime.send(:runner_source).dup.tap do |output|
bd4c71c @josh Fix sub \ escaping
josh authored
39 output.sub!('#{source}') do
40 source
41 end
82773bf @josh Context
josh authored
42 output.sub!('#{json2_source}') do
43 IO.read(ExecJS.root + "/support/json2.js")
44 end
45 end
46 end
47
48 def extract_result(output)
3097959 @josh Switch to multi_json lib
josh authored
49 status, value = output.empty? ? [] : MultiJson.decode(output)
82773bf @josh Context
josh authored
50 if status == "ok"
51 value
52 else
53 raise ProgramError, value
54 end
55 end
56 end
57
d19c760 @sstephenson Less magic
authored
58 attr_reader :name
59
954db08 @sstephenson Instantiate with options instead of subclassing
authored
60 def initialize(options)
d19c760 @sstephenson Less magic
authored
61 @name = options[:name]
954db08 @sstephenson Instantiate with options instead of subclassing
authored
62 @command = options[:command]
63 @runner_path = options[:runner_path]
5d0d51b @sstephenson therubyracer gem installs an incompatible `v8` binary - make sure we don...
authored
64 @test_args = options[:test_args]
65 @test_match = options[:test_match]
24a41df @josh Fix JSC encoding
josh authored
66 @conversion = options[:conversion]
c00ee39 @josh Support "nodejs" binary name
josh authored
67 @binary = locate_binary
954db08 @sstephenson Instantiate with options instead of subclassing
authored
68 end
69
82773bf @josh Context
josh authored
70 def exec(source)
71 context = Context.new(self)
c595c07 @josh Remove pure evaluation
josh authored
72 context.exec(source)
82773bf @josh Context
josh authored
73 end
74
0be476d @sstephenson Extract ExecJS::Runtime
authored
75 def eval(source)
82773bf @josh Context
josh authored
76 context = Context.new(self)
c595c07 @josh Remove pure evaluation
josh authored
77 context.eval(source)
0be476d @sstephenson Extract ExecJS::Runtime
authored
78 end
79
82773bf @josh Context
josh authored
80 def compile(source)
c595c07 @josh Remove pure evaluation
josh authored
81 Context.new(self, source)
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored
82 end
83
b22082f @sstephenson Add Runtime#available?
authored
84 def available?
3097959 @josh Switch to multi_json lib
josh authored
85 require "multi_json"
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|
88fa6b7 @swaits Preserve command flags passed to which
swaits authored
116 name, args = name.split(/\s+/, 2)
3cf772e @sstephenson Add `which` support for Windows
authored
117 result = if ExecJS.windows?
118 `#{ExecJS.root}/support/which.bat #{name}`
119 else
0aad760 @josh Redirect which stderr to null
josh authored
120 `which #{name} 2>/dev/null`
3cf772e @sstephenson Add `which` support for Windows
authored
121 end
612c95e @josh Fix external runtime which to return the expanded path
josh authored
122
123 if path = result.strip.split("\n").first
88fa6b7 @swaits Preserve command flags passed to which
swaits authored
124 return args ? "#{path} #{args}" : path
612c95e @josh Fix external runtime which to return the expanded path
josh authored
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.