runjs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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