Skip to content
Newer
Older
100644 150 lines (129 sloc) 3.51 KB
0be476d @sstephenson Extract ExecJS::Runtime
authored Feb 6, 2011
1 require "json"
2 require "tempfile"
3
4 module ExecJS
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored Feb 6, 2011
5 class ExternalRuntime
82773bf @josh Context
josh authored Feb 11, 2011
6 class Context
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
7 def initialize(runtime, source = "")
82773bf @josh Context
josh authored Feb 11, 2011
8 @runtime = runtime
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
9 @source = source
50791dd @josh Add Context#call
josh authored Feb 12, 2011
10 end
11
4bc602f @josh Pure function hint
josh authored Feb 11, 2011
12 def eval(source, options = {})
82773bf @josh Context
josh authored Feb 11, 2011
13 if /\S/ =~ source
14 exec("return eval(#{"(#{source})".to_json})")
15 end
16 end
17
4bc602f @josh Pure function hint
josh authored Feb 11, 2011
18 def exec(source, options = {})
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
19 compile_to_tempfile([@source, source].join("\n")) do |file|
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored Mar 10, 2011
20 extract_result(@runtime.send(:exec_runtime, file.path))
82773bf @josh Context
josh authored Feb 11, 2011
21 end
22 end
23
50791dd @josh Add Context#call
josh authored Feb 12, 2011
24 def call(properties, *args)
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
25 eval "#{properties}.apply(this, #{args.to_json})"
50791dd @josh Add Context#call
josh authored Feb 12, 2011
26 end
27
82773bf @josh Context
josh authored Feb 11, 2011
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 Mar 10, 2011
39 @runtime.send(:runner_source).dup.tap do |output|
bd4c71c @josh Fix sub \ escaping
josh authored Mar 10, 2011
40 output.sub!('#{source}') do
41 source
42 end
82773bf @josh Context
josh authored Feb 11, 2011
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 Feb 9, 2011
59 attr_reader :name
60
954db08 @sstephenson Instantiate with options instead of subclassing
authored Feb 6, 2011
61 def initialize(options)
d19c760 @sstephenson Less magic
authored Feb 10, 2011
62 @name = options[:name]
954db08 @sstephenson Instantiate with options instead of subclassing
authored Feb 7, 2011
63 @command = options[:command]
64 @runner_path = options[:runner_path]
5d0d51b @sstephenson therubyracer gem installs an incompatible `v8` binary - make sure we …
authored Feb 6, 2011
65 @test_args = options[:test_args]
66 @test_match = options[:test_match]
24a41df @josh Fix JSC encoding
josh authored Feb 10, 2011
67 @conversion = options[:conversion]
c00ee39 @josh Support "nodejs" binary name
josh authored Feb 7, 2011
68 @binary = locate_binary
954db08 @sstephenson Instantiate with options instead of subclassing
authored Feb 7, 2011
69 end
70
82773bf @josh Context
josh authored Feb 11, 2011
71 def exec(source)
72 context = Context.new(self)
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
73 context.exec(source)
82773bf @josh Context
josh authored Feb 11, 2011
74 end
75
0be476d @sstephenson Extract ExecJS::Runtime
authored Feb 7, 2011
76 def eval(source)
82773bf @josh Context
josh authored Feb 11, 2011
77 context = Context.new(self)
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
78 context.eval(source)
0be476d @sstephenson Extract ExecJS::Runtime
authored Feb 7, 2011
79 end
80
82773bf @josh Context
josh authored Feb 11, 2011
81 def compile(source)
c595c07 @josh Remove pure evaluation
josh authored Mar 10, 2011
82 Context.new(self, source)
c5e22c4 @sstephenson Runtime -> ExternalRuntime
authored Feb 7, 2011
83 end
84
b22082f @sstephenson Add Runtime#available?
authored Feb 6, 2011
85 def available?
c00ee39 @josh Support "nodejs" binary name
josh authored Feb 7, 2011
86 @binary ? true : false
b22082f @sstephenson Add Runtime#available?
authored Feb 7, 2011
87 end
88
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored Mar 10, 2011
89 protected
90 def runner_source
91 @runner_source ||= IO.read(@runner_path)
92 end
82773bf @josh Context
josh authored Feb 11, 2011
93
0dc15c3 @josh Make runner_source and exec_runtime protected
josh authored Mar 10, 2011
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 Feb 11, 2011
101 end
102
c00ee39 @josh Support "nodejs" binary name
josh authored Feb 7, 2011
103 def locate_binary
3cf772e @sstephenson Add `which` support for Windows
authored Feb 7, 2011
104 if binary = which(@command)
c00ee39 @josh Support "nodejs" binary name
josh authored Feb 7, 2011
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 Feb 7, 2011
114 def which(command)
115 Array(command).find do |name|
8b22842 @sstephenson Add WSH JScript support
authored Feb 7, 2011
116 name = name.split(/\s+/).first
3cf772e @sstephenson Add `which` support for Windows
authored Feb 7, 2011
117 result = if ExecJS.windows?
118 `#{ExecJS.root}/support/which.bat #{name}`
119 else
120 `which #{name} 2>&1`
121 end
122 result.strip.split("\n").first
123 end
124 end
125
24a41df @josh Fix JSC encoding
josh authored Feb 10, 2011
126 if "".respond_to?(:force_encoding)
127 def sh(command)
128 output, options = nil, {}
129 options[:internal_encoding] = @conversion[:from] if @conversion
130 IO.popen(command, options) { |f| output = f.read }
131 output.force_encoding(@conversion[:to]) if @conversion
132 output
133 end
134 else
135 require "iconv"
136
137 def sh(command)
138 output = nil
139 IO.popen(command) { |f| output = f.read }
140
141 if @conversion
142 Iconv.iconv(@conversion[:from], @conversion[:to], output).first
143 else
144 output
145 end
146 end
147 end
0be476d @sstephenson Extract ExecJS::Runtime
authored Feb 7, 2011
148 end
149 end
Something went wrong with that request. Please try again.