runjs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,150 @@
1
+ require 'test_helper'
2
+
3
+ describe 'syntax error' do
4
+
5
+ specify 'a JavaScript syntax error raises a CompileError' do
6
+ assert_raises(RunJS::CompileError) do
7
+ RunJS.run(']')
8
+ end
9
+ end
10
+
11
+ specify 'eval with syntax error raises a JavaScriptError' do
12
+ error = assert_raises(RunJS::JavaScriptError) do
13
+ RunJS.eval(']')
14
+ end
15
+ assert_equal 'SyntaxError', error['name']
16
+ end
17
+
18
+ specify 'throw SyntaxError raises a JavaScriptError' do
19
+ error = assert_raises(RunJS::JavaScriptError) do
20
+ RunJS.run('throw new SyntaxError();')
21
+ end
22
+ assert_equal 'SyntaxError', error[:name]
23
+ end
24
+
25
+ end
26
+
27
+ describe 'runtime error' do
28
+
29
+ describe 'raising a JavaScriptError' do
30
+
31
+ specify 'the JavaScript code throws an error' do
32
+ assert_raises(RunJS::JavaScriptError) do
33
+ RunJS.run('throw new Error();')
34
+ end
35
+ end
36
+
37
+ specify 'calling an undefined function' do
38
+ assert_raises(RunJS::JavaScriptError) do
39
+ RunJS.call('notAFunction')
40
+ end
41
+ end
42
+
43
+ specify 'JSON.stringify gets a cyclic structure' do
44
+ assert_raises(RunJS::JavaScriptError) do
45
+ RunJS.run('var cycle = {}; cycle.self = cycle; return cycle;')
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ specify 'the error message' do
52
+ error = RunJS.run('throw new Error("msg");') rescue $!
53
+ assert_equal 'Error: msg', error.message
54
+
55
+ error = RunJS.run('throw new Error();') rescue $!
56
+ assert_equal 'Error', error.message
57
+
58
+ error = RunJS.run('throw "msg";') rescue $!
59
+ assert_equal 'msg', error.message
60
+
61
+ error = RunJS.run('throw "";') rescue $!
62
+ assert_equal '', error.message
63
+
64
+ error = RunJS.run('throw [];') rescue $!
65
+ assert_equal '', error.message
66
+
67
+ error = RunJS.run('throw 0;') rescue $!
68
+ assert_equal '0', error.message
69
+ end
70
+
71
+ describe 'the error object' do
72
+
73
+ it 'contains the thrown JavaScript object' do
74
+ error = RunJS.run('throw "msg";') rescue $!
75
+ assert_equal 'msg', error.error
76
+
77
+ error = RunJS.run('throw 0;') rescue $!
78
+ assert_equal 0, error.error
79
+
80
+ error = RunJS.run('throw null;') rescue $!
81
+ assert_equal nil, error.error
82
+ end
83
+
84
+ it 'captures all the properties of the thrown error object' do
85
+ error = assert_raises(RunJS::JavaScriptError) do
86
+ RunJS.run(
87
+ 'var err = new Error("msg");' <<
88
+ 'err.location = { line: 4, column: 8 };' <<
89
+ 'throw err;'
90
+ )
91
+ end
92
+ assert_equal 'Error', error['name']
93
+ assert_equal 'msg', error['message']
94
+ assert_equal 4, error['location']['line']
95
+
96
+ skip if RunJS.runtime == RunJS::JScript
97
+ skip if RunJS.runtime == RunJS::TheRubyRhino
98
+
99
+ refute_empty error['stack']
100
+ end
101
+
102
+ it 'handles array error objects' do
103
+ error = RunJS.run('throw [false];') rescue $!
104
+ assert_equal [false], error.error
105
+ assert_equal false, error[0]
106
+ end
107
+
108
+ it 'handles error properties that cannot be stringified (cyclic objects)' do
109
+ error = assert_raises(RunJS::JavaScriptError) do
110
+ context = RunJS.context('var cycle = {}; cycle.self = cycle;')
111
+ context.run('throw { name: "Cycle", cycle: cycle };')
112
+ end
113
+ assert_equal 'Cycle', error['name']
114
+ assert_equal '[object Object]', error['cycle']
115
+ end
116
+
117
+ it 'shortens the stack trace produced by SpiderMonkey' do
118
+ error = RunJS.call('notAFunction', 'x' * 2000) rescue $!
119
+ if RunJS.runtime == RunJS::SpiderMonkey
120
+ assert_equal 1005, error.error['stack'].size
121
+ assert_match 'xxx ... xxx', error['stack']
122
+ else
123
+ refute_match ' ... ', error[:stack]
124
+ end
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+
131
+ describe 'accessing the JavaScript source code that caused the error' do
132
+
133
+ def runner(js)
134
+ if RunJS.runtime == RunJS::JScript
135
+ js = [RunJS::JScript::JSON_JS, js].join("\n")
136
+ end
137
+ RunJS::Runtime::RUNNER % js
138
+ end
139
+
140
+ specify 'CompileError#source contains the runner code' do
141
+ error = assert_raises(RunJS::CompileError) { RunJS.run('(') }
142
+ assert_equal runner('('), error.source
143
+ end
144
+
145
+ specify 'JavaScriptError#source contains the runner code' do
146
+ error = assert_raises(RunJS::JavaScriptError) { RunJS.run('foo();') }
147
+ assert_equal runner('foo();'), error.source
148
+ end
149
+
150
+ end
@@ -0,0 +1,93 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ describe 'run JavaScript' do
6
+
7
+ specify 'call' do
8
+ assert_equal 5, RunJS.call('Math.sqrt', 25)
9
+ assert_equal 0, RunJS.call('Date.parse', 'Jan 1 1970 UTC')
10
+ end
11
+
12
+ specify 'apply' do
13
+ result = RunJS.apply('Array.prototype.concat', '["cat"]', 2, :food => nil)
14
+ assert_equal ['cat', 2, { 'food' => nil }], result
15
+
16
+ skip if RunJS.runtime == RunJS::JScript
17
+
18
+ result = RunJS.apply('Array.prototype.slice', 'cat'.to_json)
19
+ assert_equal ['c', 'a', 't'], result
20
+ end
21
+
22
+ specify 'run' do
23
+ assert_nil RunJS.run('true;')
24
+ assert_nil RunJS.run('return undefined;')
25
+ assert_equal 4, RunJS.run('return 2 + 2;')
26
+ assert_equal false, RunJS.run('var x = 2, y = 2; return x > y;')
27
+ assert_equal [1, 'cat'], RunJS.run('return [1].concat("cat");')
28
+ assert_equal '\\', RunJS.run('return "\\\\";')
29
+ end
30
+
31
+ describe 'eval' do
32
+
33
+ specify 'eval' do
34
+ assert_nil RunJS.eval(nil)
35
+ assert_nil RunJS.eval('')
36
+ assert_equal 4, RunJS.eval('2 + 2')
37
+ assert_equal 4, RunJS.eval('var x = 2, y = 2; x + y')
38
+ assert_equal ['c', 'a', 't'], RunJS.eval('"cat".split("")')
39
+ end
40
+
41
+ it 'requires parentheses around objects' do
42
+ assert_equal Hash['one' => 1], RunJS.eval('({ one: 1 })')
43
+ end
44
+
45
+ it 'requires parentheses around anonymous functions' do
46
+ assert_nil RunJS.eval('(function() {})')
47
+ assert_nil RunJS.eval('function notAnonymous() {}')
48
+ assert_nil RunJS.eval('var notAnonymous = function() {}')
49
+ end
50
+
51
+ end
52
+
53
+ describe 'context' do
54
+
55
+ it 'supports nested context' do
56
+ js = 'a = {}; a.b = {}; a.b.c = function(d) { return d; }'
57
+ assert_equal 'nest', RunJS.context(js).call('a.b.c', 'nest')
58
+ end
59
+
60
+ it 'supports many contexts' do
61
+ heart = 'function heart(s) { return "♥ " + s + " ♥"; }'
62
+ upcase = 'function upcase(s) { return s.toUpperCase(); }'
63
+ decorate = 'function decorate(s) { return heart(upcase(s)); }'
64
+ context = RunJS.context(upcase).context(heart).context(decorate)
65
+ assert_equal '♥ RUBY ♥', context.call('decorate', 'ruby')
66
+ end
67
+
68
+ specify 'using a runtime instance' do
69
+ instance = RunJS.runtime.new
70
+ instance.context('function upcase(s) { return s.toUpperCase(); }')
71
+ instance.context('function star(s) { return "★" + upcase(s) + "★"; }')
72
+ assert_equal '★RUBY★', instance.run('return star("ruby");')
73
+ assert_equal '★RUBY★', instance.apply('star', nil, 'ruby')
74
+ assert_equal '★RUBY★', instance.call('star', 'ruby')
75
+ assert_equal '★RUBY★', instance.eval('star("ruby")')
76
+ end
77
+
78
+ end
79
+
80
+ it 'does not use strict mode by default' do
81
+ js = 'aGlobalVariable = true; return aGlobalVariable;'
82
+ assert_equal true, RunJS.run(js)
83
+
84
+ skip if RunJS.runtime == RunJS::JScript
85
+ skip if RunJS.runtime == RunJS::TheRubyRhino
86
+
87
+ error = assert_raises(RunJS::JavaScriptError) do
88
+ RunJS.run("'use strict'; #{js}")
89
+ end
90
+ assert_equal 'ReferenceError', error[:name]
91
+ end
92
+
93
+ end
@@ -0,0 +1,103 @@
1
+ require 'test_helper'
2
+
3
+ describe 'select a runtime' do
4
+
5
+ class AvailableRuntime < RunJS::SystemRuntime
6
+ @cmd = 'ruby'
7
+ end
8
+
9
+ class DeprecatedRuntime < RunJS::SystemRuntime
10
+ @cmd = 'ruby'
11
+ @deprecated = true
12
+ end
13
+
14
+ class UnavailableRuntime < RunJS::SystemRuntime
15
+ @cmd = 'this is not a command'
16
+ end
17
+
18
+ specify 'the runtime is available if @cmd is executable' do
19
+ assert AvailableRuntime.available?
20
+ refute UnavailableRuntime.available?
21
+ end
22
+
23
+ specify 'deprecated' do
24
+ refute AvailableRuntime.deprecated?
25
+ assert DeprecatedRuntime.deprecated?
26
+ end
27
+
28
+ before { @runtime = RunJS.runtime }
29
+ after { RunJS.runtime = @runtime }
30
+
31
+ describe 'setting the runtime manually' do
32
+
33
+ it 'sets the runtime if it is available' do
34
+ RunJS.runtime = AvailableRuntime
35
+ assert_equal AvailableRuntime, RunJS.runtime
36
+ end
37
+
38
+ it 'accepts a deprecated runtime' do
39
+ RunJS.runtime = DeprecatedRuntime
40
+ assert_equal DeprecatedRuntime, RunJS.runtime
41
+ end
42
+
43
+ it 'raises RuntimeUnavailable if the runtime is unavailable' do
44
+ assert_raises(RunJS::RuntimeUnavailable) do
45
+ RunJS.runtime = UnavailableRuntime
46
+ end
47
+ assert_equal @runtime, RunJS.runtime
48
+ end
49
+
50
+ end
51
+
52
+ describe 'selecting a runtime automatically' do
53
+
54
+ before do
55
+ @runtimes = RunJS::RUNTIMES.dup
56
+ @environment = ENV['RUNJS_RUNTIME']
57
+
58
+ ENV['RUNJS_RUNTIME'] = nil
59
+ RunJS.instance_variable_set(:@runtime, nil)
60
+ end
61
+
62
+ after do
63
+ RunJS::RUNTIMES.replace(@runtimes)
64
+ ENV['RUNJS_RUNTIME'] = @environment
65
+ end
66
+
67
+ it 'selects the first available runtime' do
68
+ RunJS::RUNTIMES.replace([UnavailableRuntime, AvailableRuntime] + @runtimes)
69
+ assert_equal AvailableRuntime, RunJS.runtime
70
+ end
71
+
72
+ it 'will not select a deprecated runtime automatically' do
73
+ RunJS::RUNTIMES.replace([DeprecatedRuntime])
74
+ assert_raises(RunJS::RuntimeUnavailable) { RunJS.runtime }
75
+ end
76
+
77
+ it 'raises RuntimeUnavailable if none of the supported runtimes are installed' do
78
+ RunJS::RUNTIMES.replace([UnavailableRuntime, DeprecatedRuntime])
79
+ assert_raises(RunJS::RuntimeUnavailable) { RunJS.runtime }
80
+ end
81
+
82
+ describe 'the RUNJS_RUNTIME environment variable' do
83
+
84
+ it 'selects the runtime set by the environment' do
85
+ ENV['RUNJS_RUNTIME'] = 'AvailableRuntime'
86
+ assert_equal AvailableRuntime, RunJS.runtime
87
+ end
88
+
89
+ it 'will accept a deprecated runtime from the environment' do
90
+ ENV['RUNJS_RUNTIME'] = 'DeprecatedRuntime'
91
+ assert_equal DeprecatedRuntime, RunJS.runtime
92
+ end
93
+
94
+ it 'raises RuntimeUnavailable if the runtime is unavailable' do
95
+ ENV['RUNJS_RUNTIME'] = 'UnavailableRuntime'
96
+ assert_raises(RunJS::RuntimeUnavailable) { RunJS.runtime }
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+
103
+ end
@@ -0,0 +1,17 @@
1
+ require 'runjs'
2
+
3
+ def display_banner(width)
4
+ runtime = RunJS.runtime.class_name rescue ENV['RUNJS_RUNTIME']
5
+ ruby = defined?(JRUBY_VERSION) ? "JRuby #{JRUBY_VERSION}" :
6
+ "Ruby #{RUBY_VERSION}"
7
+ puts
8
+ puts '=' * width
9
+ puts "#{runtime} - #{ruby}".center(width)
10
+ puts '=' * width
11
+ puts
12
+ end
13
+
14
+ display_banner(40)
15
+ RunJS.runtime rescue abort $!.message # abort if no runtime is detected
16
+
17
+ require 'minitest/autorun'
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: runjs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - AS Harbitz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: coffee-script-source
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.6.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.6.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: therubyracer
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: therubyrhino
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: 'You can run JavaScript code from Ruby with RunJS. The supported JavaScript
70
+ engines are: Node, V8, TheRubyRacer, JavaScriptCore and JScript.'
71
+ email: asharbitz@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - LICENSE
77
+ - Rakefile
78
+ - runjs.gemspec
79
+ - README.md
80
+ - lib/runjs/encoding.rb
81
+ - lib/runjs/error.rb
82
+ - lib/runjs/os.rb
83
+ - lib/runjs/runtime.rb
84
+ - lib/runjs/runtimes/java_script_core.rb
85
+ - lib/runjs/runtimes/jscript.rb
86
+ - lib/runjs/runtimes/node.rb
87
+ - lib/runjs/runtimes/spider_monkey.rb
88
+ - lib/runjs/runtimes/the_ruby_racer.rb
89
+ - lib/runjs/runtimes/the_ruby_rhino.rb
90
+ - lib/runjs/runtimes/v8.rb
91
+ - lib/runjs/support/runner.js
92
+ - lib/runjs/system_runtime.rb
93
+ - lib/runjs/vendor/json2.js
94
+ - lib/runjs.rb
95
+ - test/coffeescript_test.rb
96
+ - test/encoding_test.rb
97
+ - test/execjs_test.rb
98
+ - test/javascript_error_test.rb
99
+ - test/javascript_test.rb
100
+ - test/select_runtime_test.rb
101
+ - test/test_helper.rb
102
+ homepage: https://github.com/asharbitz/runjs
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message: |2+
107
+
108
+ If your version of ruby is older than 1.9, you may need to install json:
109
+ gem install json || gem install json_pure
110
+
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - '>='
117
+ - !ruby/object:Gem::Version
118
+ version: 1.8.7
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.0.3
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: Run JavaScript code from Ruby
130
+ test_files:
131
+ - test/coffeescript_test.rb
132
+ - test/encoding_test.rb
133
+ - test/execjs_test.rb
134
+ - test/javascript_error_test.rb
135
+ - test/javascript_test.rb
136
+ - test/select_runtime_test.rb
137
+ - test/test_helper.rb