runjs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'runjs'
3
+ spec.version = '0.1.0'
4
+ spec.license = 'MIT'
5
+
6
+ spec.author = 'AS Harbitz'
7
+ spec.email = 'asharbitz@gmail.com'
8
+ spec.homepage = 'https://github.com/asharbitz/runjs'
9
+
10
+ spec.summary = 'Run JavaScript code from Ruby'
11
+ spec.description = 'You can run JavaScript code from Ruby with RunJS. ' +
12
+ 'The supported JavaScript engines are: Node, V8, ' +
13
+ 'TheRubyRacer, JavaScriptCore and JScript.'
14
+
15
+ spec.files = Dir['LICENSE', 'Rakefile', 'runjs.gemspec', '*.md',
16
+ 'lib/**/*.*']
17
+ spec.test_files = Dir['test/**/*.*']
18
+
19
+ spec.add_development_dependency 'minitest', '~> 4.0'
20
+ spec.add_development_dependency 'coffee-script-source', '>= 1.6.2'
21
+ spec.add_development_dependency 'therubyracer'
22
+ spec.add_development_dependency 'therubyrhino'
23
+
24
+ spec.required_ruby_version = '>= 1.8.7'
25
+
26
+ spec.post_install_message = <<-EOF.gsub(' ', '')
27
+
28
+ If your version of ruby is older than 1.9, you may need to install json:
29
+ gem install json || gem install json_pure
30
+
31
+ EOF
32
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ describe 'compile CoffeeScript' do
4
+
5
+ before do
6
+ begin
7
+ require 'coffee_script/source'
8
+ @coffee = File.read(CoffeeScript::Source.bundled_path)
9
+ @version = @coffee[/CoffeeScript Compiler v([.\d]+)/, 1]
10
+ rescue LoadError
11
+ skip
12
+ end
13
+ end
14
+
15
+ def compile(*args)
16
+ RunJS.context(@coffee).apply('CoffeeScript.compile', 'CoffeeScript', *args)
17
+ end
18
+
19
+ it 'can compile CoffeeScript' do
20
+ js = compile('alert yes', :bare => true)
21
+ assert_equal 'alert(true);', js.strip
22
+ end
23
+
24
+ it 'includes the version number in the header' do
25
+ js = compile('', :header => true)
26
+ assert_match "// Generated by CoffeeScript #{@version}", js
27
+ end
28
+
29
+ it 'captures the error location' do
30
+ skip if @version < '1.6.2'
31
+
32
+ error = assert_raises(RunJS::JavaScriptError) do
33
+ compile('evil = (eval) ->')
34
+ end
35
+ assert_equal 0, error['location']['first_line']
36
+ assert_equal 8, error['location']['first_column']
37
+ end
38
+
39
+ end
@@ -0,0 +1,35 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe 'encoding' do
6
+
7
+ it 'handles UTF-8 characters' do
8
+ skip if RunJS.runtime == RunJS::SpiderMonkey # SpiderMonkey does not support UTF-8
9
+
10
+ upcase = RunJS.run('return "ꝏå@ø\ua74f".toUpperCase();')
11
+ if [RunJS::JScript, RunJS::TheRubyRhino].include?(RunJS.runtime)
12
+ assert_equal 'ꝏÅ@Øꝏ', upcase
13
+ else
14
+ assert_equal 'ꝎÅ@ØꝎ', upcase
15
+ end
16
+ end
17
+
18
+ it 'converts other encodings to UTF-8 (if ruby version >= 1.9)' do
19
+ skip unless defined? Encoding
20
+ skip if RunJS.runtime == RunJS::SpiderMonkey
21
+
22
+ context = 'function star(text) { return text.split("").join("★"); }'
23
+ context = RunJS.context(context.encode('Shift_JIS'))
24
+ [
25
+ context.apply('star', 'this', 'スター'),
26
+ context.call('star', 'スター'.encode('Shift_JIS')),
27
+ context.eval('star("スター")'.encode('UTF-16LE')),
28
+ context.run('return star("スター");'.encode('UTF-16'))
29
+ ].each do |star|
30
+ assert_equal 'ス★タ★ー', star
31
+ assert_equal 'UTF-8', star.encoding.name
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,415 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
4
+ # #
5
+ # These tests are copied from ExecJS: #
6
+ # https://github.com/sstephenson/execjs/blob/v1.4.0/test/test_execjs.rb #
7
+ # #
8
+ # The purpose is to document the differences between RunJS and ExecJS #
9
+ # #
10
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
11
+
12
+
13
+ # require "test/unit"
14
+ # require "execjs/module"
15
+ #
16
+ # begin
17
+ # require "execjs"
18
+ # rescue ExecJS::RuntimeUnavailable => e
19
+ # warn e
20
+ # exit 2
21
+ # end
22
+ #
23
+ # class TestExecJS < Test::Unit::TestCase
24
+
25
+ require "test_helper"
26
+ require "runjs" # RunJS does not set the runtime when the file is loaded, so
27
+ # this statement will never raise a RuntimeUnavailable error
28
+
29
+ class TestRunJS < MiniTest::Unit::TestCase
30
+
31
+
32
+ # def test_runtime_available
33
+ # runtime = ExecJS::ExternalRuntime.new(:command => "nonexistent")
34
+ # assert !runtime.available?
35
+ #
36
+ # runtime = ExecJS::ExternalRuntime.new(:command => "ruby")
37
+ # assert runtime.available?
38
+ # end
39
+
40
+ def test_runtime_available
41
+ # RunJS::SystemRuntime is equivalent to ExecJS::ExternalRuntime
42
+ # Both available? and cmd= are class methods
43
+
44
+ runtime = RunJS::SystemRuntime
45
+ runtime.cmd = "nonexistent"
46
+ assert !runtime.available?
47
+
48
+ runtime.cmd = "ruby"
49
+ assert runtime.available?
50
+ ensure
51
+ runtime.cmd = nil
52
+ end
53
+
54
+
55
+ # def test_runtime_assignment
56
+ # original_runtime = ExecJS.runtime
57
+ # runtime = ExecJS::ExternalRuntime.new(:command => "nonexistent")
58
+ # assert_raises(ExecJS::RuntimeUnavailable) { ExecJS.runtime = runtime }
59
+ # assert_equal original_runtime, ExecJS.runtime
60
+ #
61
+ # runtime = ExecJS::ExternalRuntime.new(:command => "ruby")
62
+ # ExecJS.runtime = runtime
63
+ # assert_equal runtime, ExecJS.runtime
64
+ # ensure
65
+ # ExecJS.runtime = original_runtime
66
+ # end
67
+
68
+ def test_runtime_assignment
69
+ # RunJS.runtime= accepts a class (and not an instance)
70
+
71
+ original_runtime = RunJS.runtime
72
+ runtime = RunJS::SystemRuntime
73
+ runtime.cmd = "nonexistent"
74
+ assert_raises(RunJS::RuntimeUnavailable) { RunJS.runtime = runtime }
75
+ assert_equal original_runtime, RunJS.runtime
76
+
77
+ runtime.cmd = "ruby"
78
+ RunJS.runtime = runtime
79
+ assert_equal runtime, RunJS.runtime
80
+ ensure
81
+ RunJS.runtime = original_runtime
82
+ runtime.cmd = nil
83
+ end
84
+
85
+
86
+ # def test_context_call
87
+ # context = ExecJS.compile("id = function(v) { return v; }")
88
+ # assert_equal "bar", context.call("id", "bar")
89
+ # end
90
+
91
+ def test_context_call
92
+ # RunJS#context serves the same purpose as ExecJS#compile
93
+
94
+ context = RunJS.context("id = function(v) { return v; }")
95
+ assert_equal "bar", context.call("id", "bar")
96
+ end
97
+
98
+
99
+ # def test_nested_context_call
100
+ # context = ExecJS.compile("a = {}; a.b = {}; a.b.id = function(v) { return v; }")
101
+ # assert_equal "bar", context.call("a.b.id", "bar")
102
+ # end
103
+
104
+ def test_nested_context_call
105
+ context = RunJS.context("a = {}; a.b = {}; a.b.id = function(v) { return v; }")
106
+ assert_equal "bar", context.call("a.b.id", "bar")
107
+ end
108
+
109
+
110
+ # def test_context_call_missing_function
111
+ # context = ExecJS.compile("")
112
+ # assert_raises ExecJS::ProgramError do
113
+ # context.call("missing")
114
+ # end
115
+ # end
116
+
117
+ def test_context_call_missing_function
118
+ # RunJS::JavaScriptError is similar to ExecJS::ProgramError
119
+
120
+ context = RunJS.context("")
121
+ assert_raises RunJS::JavaScriptError do
122
+ context.call("missing")
123
+ end
124
+ end
125
+
126
+
127
+ # def test_exec
128
+ # assert_nil ExecJS.exec("1")
129
+ # assert_nil ExecJS.exec("return")
130
+ # assert_nil ExecJS.exec("return null")
131
+ # assert_nil ExecJS.exec("return function() {}")
132
+ # assert_equal 0, ExecJS.exec("return 0")
133
+ # assert_equal true, ExecJS.exec("return true")
134
+ # assert_equal [1, 2], ExecJS.exec("return [1, 2]")
135
+ # assert_equal "hello", ExecJS.exec("return 'hello'")
136
+ # assert_equal({"a"=>1,"b"=>2}, ExecJS.exec("return {a:1,b:2}"))
137
+ # assert_equal "café", ExecJS.exec("return 'café'")
138
+ # assert_equal "☃", ExecJS.exec('return "☃"')
139
+ # assert_equal "☃", ExecJS.exec('return "\u2603"')
140
+ # assert_equal "\\", ExecJS.exec('return "\\\\"')
141
+ # end
142
+
143
+ def test_exec
144
+ # RunJS.run is equivalent to ExecJS.exec
145
+
146
+ assert_nil RunJS.run("1")
147
+ assert_nil RunJS.run("return")
148
+ assert_nil RunJS.run("return null")
149
+ assert_nil RunJS.run("return function() {}")
150
+ assert_equal 0, RunJS.run("return 0")
151
+ assert_equal true, RunJS.run("return true")
152
+ assert_equal [1, 2], RunJS.run("return [1, 2]")
153
+ assert_equal "hello", RunJS.run("return 'hello'")
154
+ assert_equal({"a"=>1,"b"=>2}, RunJS.run("return {a:1,b:2}"))
155
+ assert_equal "café", RunJS.run("return 'café'")
156
+ assert_equal "☃", RunJS.run('return "☃"')
157
+
158
+ if RunJS.runtime != RunJS::SpiderMonkey
159
+ assert_equal "☃", RunJS.run('return "\u2603"')
160
+ else
161
+ assert_raises(JSON::ParserError) { RunJS.run('return "\u2603"') }
162
+ # result == "[\"\u0003\",true]"
163
+ end
164
+
165
+ assert_equal "\\", RunJS.run('return "\\\\"')
166
+ end
167
+
168
+
169
+ # def test_eval
170
+ # assert_nil ExecJS.eval("")
171
+ # assert_nil ExecJS.eval(" ")
172
+ # assert_nil ExecJS.eval("null")
173
+ # assert_nil ExecJS.eval("function() {}")
174
+ # assert_equal 0, ExecJS.eval("0")
175
+ # assert_equal true, ExecJS.eval("true")
176
+ # assert_equal [1, 2], ExecJS.eval("[1, 2]")
177
+ # assert_equal [1, nil], ExecJS.eval("[1, function() {}]")
178
+ # assert_equal "hello", ExecJS.eval("'hello'")
179
+ # assert_equal ["red", "yellow", "blue"], ExecJS.eval("'red yellow blue'.split(' ')")
180
+ # assert_equal({"a"=>1,"b"=>2}, ExecJS.eval("{a:1,b:2}"))
181
+ # assert_equal({"a"=>true}, ExecJS.eval("{a:true,b:function (){}}"))
182
+ # assert_equal "café", ExecJS.eval("'café'")
183
+ # assert_equal "☃", ExecJS.eval('"☃"')
184
+ # assert_equal "☃", ExecJS.eval('"\u2603"')
185
+ # assert_equal "\\", ExecJS.eval('"\\\\"')
186
+ # end
187
+
188
+ def test_eval
189
+ # RunJS does not wrap the string to eval in parentheses
190
+
191
+ assert_nil RunJS.eval("")
192
+ assert_nil RunJS.eval(" ")
193
+ assert_nil RunJS.eval("null")
194
+
195
+ # assert_nil ExecJS.eval("function() {}")
196
+ assert_nil RunJS.eval("(function() {})")
197
+
198
+ assert_equal 0, RunJS.eval("0")
199
+ assert_equal true, RunJS.eval("true")
200
+ assert_equal [1, 2], RunJS.eval("[1, 2]")
201
+ assert_equal [1, nil], RunJS.eval("[1, function() {}]")
202
+ assert_equal "hello", RunJS.eval("'hello'")
203
+ assert_equal ["red", "yellow", "blue"], RunJS.eval("'red yellow blue'.split(' ')")
204
+
205
+ # assert_equal({"a"=>1,"b"=>2}, ExecJS.eval("{a:1,b:2}"))
206
+ assert_equal({"a"=>1,"b"=>2}, RunJS.eval("({a:1,b:2})"))
207
+
208
+ # assert_equal({"a"=>true}, ExecJS.eval("{a:true,b:function (){}}"))
209
+ assert_equal({"a"=>true}, RunJS.eval("({a:true,b:function (){}})"))
210
+
211
+ assert_equal "café", RunJS.eval("'café'")
212
+ assert_equal "☃", RunJS.eval('"☃"')
213
+ assert_equal "☃", RunJS.eval('"\u2603"') if RunJS.runtime != RunJS::SpiderMonkey
214
+ assert_equal "\\", RunJS.eval('"\\\\"')
215
+ end
216
+
217
+
218
+ # if defined? Encoding
219
+ # def test_encoding
220
+ # utf8 = Encoding.find('UTF-8')
221
+ #
222
+ # assert_equal utf8, ExecJS.exec("return 'hello'").encoding
223
+ # assert_equal utf8, ExecJS.eval("'☃'").encoding
224
+ #
225
+ # ascii = "'hello'".encode('US-ASCII')
226
+ # result = ExecJS.eval(ascii)
227
+ # assert_equal "hello", result
228
+ # assert_equal utf8, result.encoding
229
+ #
230
+ # assert_raise Encoding::UndefinedConversionError do
231
+ # binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
232
+ # ExecJS.eval(binary)
233
+ # end
234
+ # end
235
+
236
+ def test_encoding
237
+ skip unless defined? Encoding
238
+
239
+ utf8 = Encoding.find('UTF-8')
240
+
241
+ assert_equal utf8, RunJS.run("return 'hello'").encoding
242
+ assert_equal utf8, RunJS.eval("'☃'").encoding
243
+
244
+ ascii = "'hello'".encode('US-ASCII')
245
+ result = RunJS.eval(ascii)
246
+ assert_equal "hello", result
247
+ assert_equal utf8, result.encoding
248
+
249
+ assert_raises Encoding::UndefinedConversionError do
250
+ binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
251
+ RunJS.eval(binary)
252
+ end
253
+ end
254
+
255
+
256
+ # def test_encoding_compile
257
+ # utf8 = Encoding.find('UTF-8')
258
+ #
259
+ # context = ExecJS.compile("foo = function(v) { return '¶' + v; }".encode("ISO8859-15"))
260
+ #
261
+ # assert_equal utf8, context.exec("return foo('hello')").encoding
262
+ # assert_equal utf8, context.eval("foo('☃')").encoding
263
+ #
264
+ # ascii = "foo('hello')".encode('US-ASCII')
265
+ # result = context.eval(ascii)
266
+ # assert_equal "¶hello", result
267
+ # assert_equal utf8, result.encoding
268
+ #
269
+ # assert_raise Encoding::UndefinedConversionError do
270
+ # binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
271
+ # context.eval(binary)
272
+ # end
273
+ # end
274
+ # end
275
+
276
+ def test_encoding_compile
277
+ skip unless defined? Encoding
278
+
279
+ utf8 = Encoding.find('UTF-8')
280
+
281
+ context = RunJS.context("foo = function(v) { return '¶' + v; }".encode("ISO8859-15"))
282
+
283
+ assert_equal utf8, context.run("return foo('hello')").encoding
284
+ assert_equal utf8, context.eval("foo('☃')").encoding
285
+
286
+ ascii = "foo('hello')".encode('US-ASCII')
287
+ result = context.eval(ascii)
288
+ assert_equal "¶hello", result
289
+ assert_equal utf8, result.encoding
290
+
291
+ assert_raises Encoding::UndefinedConversionError do
292
+ binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
293
+ context.eval(binary)
294
+ end
295
+ end
296
+
297
+
298
+ # def test_compile
299
+ # context = ExecJS.compile("foo = function() { return \"bar\"; }")
300
+ # assert_equal "bar", context.exec("return foo()")
301
+ # assert_equal "bar", context.eval("foo()")
302
+ # assert_equal "bar", context.call("foo")
303
+ # end
304
+
305
+ def test_compile
306
+ context = RunJS.context("foo = function() { return \"bar\"; }")
307
+ assert_equal "bar", context.run("return foo()")
308
+ assert_equal "bar", context.eval("foo()")
309
+ assert_equal "bar", context.call("foo")
310
+ end
311
+
312
+
313
+ # def test_this_is_global_scope
314
+ # assert_equal true, ExecJS.eval("this === (function() {return this})()")
315
+ # assert_equal true, ExecJS.exec("return this === (function() {return this})()")
316
+ # end
317
+
318
+ def test_this_is_global_scope
319
+ assert_equal true, RunJS.eval("this === (function() {return this})()")
320
+ assert_equal true, RunJS.run("return this === (function() {return this})()")
321
+ end
322
+
323
+
324
+ # def test_commonjs_vars_are_undefined
325
+ # assert ExecJS.eval("typeof module == 'undefined'")
326
+ # assert ExecJS.eval("typeof exports == 'undefined'")
327
+ # assert ExecJS.eval("typeof require == 'undefined'")
328
+ # end
329
+
330
+ def test_commonjs_vars_are_undefined
331
+ # The test passes if the end of lib/runjs/support/runner.js is changed to:
332
+ # })(function(module, exports, require, console) { %s });
333
+ skip if RunJS.runtime == RunJS::Node
334
+
335
+ assert RunJS.eval("typeof module == 'undefined'")
336
+ assert RunJS.eval("typeof exports == 'undefined'")
337
+ assert RunJS.eval("typeof require == 'undefined'")
338
+ end
339
+
340
+
341
+ # def test_console_is_undefined
342
+ # assert ExecJS.eval("typeof console == 'undefined'")
343
+ # end
344
+
345
+ def test_console_is_undefined
346
+ skip if RunJS.runtime == RunJS::Node
347
+
348
+ assert RunJS.eval("typeof console == 'undefined'")
349
+ end
350
+
351
+
352
+ # def test_compile_large_scripts
353
+ # body = "var foo = 'bar';\n" * 100_000
354
+ # assert ExecJS.exec("function foo() {\n#{body}\n};\nreturn true")
355
+ # end
356
+
357
+ def test_compile_large_scripts
358
+ # RunJS::TheRubyRhino (but not ExecJS::Runtimes::RubyRhino) causes this warning:
359
+ # [INFO] Rhino byte-code generation failed forcing org.mozilla.javascript.Context@37eaab into interpreted mode
360
+
361
+ body = "var foo = 'bar';\n" * 100_000
362
+ assert RunJS.run("function foo() {\n#{body}\n};\nreturn true")
363
+ end
364
+
365
+
366
+ # def test_syntax_error
367
+ # assert_raise ExecJS::RuntimeError do
368
+ # ExecJS.exec(")")
369
+ # end
370
+ # end
371
+
372
+ def test_syntax_error
373
+ # RunJS::CompileError is similar to ExecJS::RuntimeError
374
+
375
+ assert_raises RunJS::CompileError do
376
+ RunJS.run(")")
377
+ end
378
+ end
379
+
380
+
381
+ # def test_thrown_exception
382
+ # assert_raise ExecJS::ProgramError do
383
+ # ExecJS.exec("throw 'hello'")
384
+ # end
385
+ # end
386
+
387
+ def test_thrown_exception
388
+ assert_raises RunJS::JavaScriptError do
389
+ RunJS.run("throw 'hello'")
390
+ end
391
+ end
392
+
393
+
394
+ # def test_coffeescript
395
+ # require "open-uri"
396
+ # assert source = open("http://jashkenas.github.com/coffee-script/extras/coffee-script.js").read
397
+ # context = ExecJS.compile(source)
398
+ # assert_equal 64, context.call("CoffeeScript.eval", "((x) -> x * x)(8)")
399
+ # end
400
+
401
+ begin
402
+ require 'coffee_script/source'
403
+ COFFEE = File.read(CoffeeScript::Source.bundled_path)
404
+ rescue LoadError
405
+ COFFEE = nil
406
+ end
407
+
408
+ def test_coffeescript
409
+ skip unless COFFEE
410
+
411
+ context = RunJS.context(COFFEE)
412
+ assert_equal 64, context.call("CoffeeScript.eval", "((x) -> x * x)(8)")
413
+ end
414
+
415
+ end