execjs-async 0.0.1
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.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +18 -0
- data/Rakefile +11 -0
- data/execjs-async.gemspec +24 -0
- data/lib/execjs-async.rb +62 -0
- data/lib/execjs-async/version.rb +5 -0
- data/test/support.rb +11 -0
- data/test/test_execjs.rb +58 -0
- data/test/test_runtime.rb +117 -0
- metadata +70 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm gemset use execjs-async
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "execjs-async/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "execjs-async"
|
7
|
+
s.version = Execjs::Async::VERSION
|
8
|
+
s.authors = ["Eric Allam"]
|
9
|
+
s.email = ["rubymaverick@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Enables Asynchronous Javascript Execution in ExecJS}
|
12
|
+
s.description = %q{Enables Asynchronous Javascript Execution in ExecJS}
|
13
|
+
|
14
|
+
s.rubyforge_project = "execjs-async"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "execjs", '~> 1.1.0'
|
24
|
+
end
|
data/lib/execjs-async.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "execjs-async/version"
|
2
|
+
require 'execjs'
|
3
|
+
|
4
|
+
module Execjs
|
5
|
+
module Async
|
6
|
+
|
7
|
+
# extend from nodes external runtime context, and
|
8
|
+
# overwrite compile to use the async source.
|
9
|
+
class Context < ExecJS::ExternalRuntime::Context
|
10
|
+
ASYNC_SOURCE = <<-'JAVASCRIPT'
|
11
|
+
(function(program, execJS, module, exports, require) { execJS(program) })(function(callback) { #{source}
|
12
|
+
}, function(program) {
|
13
|
+
var output, print = function(string) {
|
14
|
+
process.stdout.write('' + string);
|
15
|
+
};
|
16
|
+
try {
|
17
|
+
program(function(result){
|
18
|
+
if (typeof result == 'undefined' && result !== null) {
|
19
|
+
print('["ok"]');
|
20
|
+
} else {
|
21
|
+
try {
|
22
|
+
print(JSON.stringify(['ok', result]));
|
23
|
+
} catch (err) {
|
24
|
+
print('["err"]');
|
25
|
+
}
|
26
|
+
}
|
27
|
+
});
|
28
|
+
} catch (err) {
|
29
|
+
print(JSON.stringify(['err', '' + err]));
|
30
|
+
}
|
31
|
+
});
|
32
|
+
JAVASCRIPT
|
33
|
+
|
34
|
+
def compile(source)
|
35
|
+
ASYNC_SOURCE.dup.tap do |output|
|
36
|
+
output.sub!('#{source}') do
|
37
|
+
source
|
38
|
+
end
|
39
|
+
output.sub!('#{encoded_source}') do
|
40
|
+
encoded_source = encode_unicode_codepoints(source)
|
41
|
+
MultiJson.encode("(function(){ #{encoded_source} })()")
|
42
|
+
end
|
43
|
+
output.sub!('#{json2_source}') do
|
44
|
+
IO.read(ExecJS.root + "/support/json2.js")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def compile_async(source)
|
51
|
+
Context.new(self, source)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ExecJS::Runtimes::Node.singleton_class.send(:include, Async)
|
56
|
+
|
57
|
+
ExecJS.module_eval do
|
58
|
+
def self.compile_async(source)
|
59
|
+
runtime.compile_async(source)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/test/support.rb
ADDED
data/test/test_execjs.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "support"
|
2
|
+
|
3
|
+
class TestExecJS < Test::Unit::TestCase
|
4
|
+
def test_exec
|
5
|
+
assert_equal true, ExecJS.exec("return true")
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_eval
|
9
|
+
assert_equal ["red", "yellow", "blue"], ExecJS.eval("'red yellow blue'.split(' ')")
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_runtime_available
|
13
|
+
runtime = ExecJS::ExternalRuntime.new(:command => "nonexistent")
|
14
|
+
assert !runtime.available?
|
15
|
+
|
16
|
+
runtime = ExecJS::ExternalRuntime.new(:command => "ruby")
|
17
|
+
assert runtime.available?
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_runtime_assignment
|
21
|
+
original_runtime = ExecJS.runtime
|
22
|
+
runtime = ExecJS::ExternalRuntime.new(:command => "nonexistent")
|
23
|
+
assert_raises(ExecJS::RuntimeUnavailable) { ExecJS.runtime = runtime }
|
24
|
+
assert_equal original_runtime, ExecJS.runtime
|
25
|
+
|
26
|
+
runtime = ExecJS::ExternalRuntime.new(:command => "ruby")
|
27
|
+
ExecJS.runtime = runtime
|
28
|
+
assert_equal runtime, ExecJS.runtime
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_compile
|
32
|
+
context = ExecJS.compile("foo = function() { return \"bar\"; }")
|
33
|
+
assert_equal "bar", context.exec("return foo()")
|
34
|
+
assert_equal "bar", context.eval("foo()")
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_compile_async
|
38
|
+
context = ExecJS.compile_async("foo = function() { callback('bar') }")
|
39
|
+
assert_equal "bar", context.eval("foo()")
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_context_call
|
43
|
+
context = ExecJS.compile("id = function(v) { return v; }")
|
44
|
+
assert_equal "bar", context.call("id", "bar")
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_nested_context_call
|
48
|
+
context = ExecJS.compile("a = {}; a.b = {}; a.b.id = function(v) { return v; }")
|
49
|
+
assert_equal "bar", context.call("a.b.id", "bar")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_context_call_missing_function
|
53
|
+
context = ExecJS.compile("")
|
54
|
+
assert_raises ExecJS::ProgramError do
|
55
|
+
context.call("missing")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "support"
|
3
|
+
|
4
|
+
class TestRuntime < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
# only use node for now
|
7
|
+
@runtime = ExecJS::Runtimes::Node
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_exec
|
11
|
+
assert_nil @runtime.exec("1")
|
12
|
+
assert_nil @runtime.exec("return")
|
13
|
+
assert_nil @runtime.exec("return null")
|
14
|
+
assert_nil @runtime.exec("return function() {}")
|
15
|
+
assert_equal 0, @runtime.exec("return 0")
|
16
|
+
assert_equal true, @runtime.exec("return true")
|
17
|
+
assert_equal [1, 2], @runtime.exec("return [1, 2]")
|
18
|
+
assert_equal "hello", @runtime.exec("return 'hello'")
|
19
|
+
assert_equal({"a"=>1,"b"=>2}, @runtime.exec("return {a:1,b:2}"))
|
20
|
+
assert_equal "café", @runtime.exec("return 'café'")
|
21
|
+
assert_equal "☃", @runtime.exec('return "☃"')
|
22
|
+
assert_equal "☃", @runtime.exec('return "\u2603"')
|
23
|
+
assert_equal "\\", @runtime.exec('return "\\\\"')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_eval
|
27
|
+
assert_nil @runtime.eval("")
|
28
|
+
assert_nil @runtime.eval(" ")
|
29
|
+
assert_nil @runtime.eval("null")
|
30
|
+
assert_nil @runtime.eval("function() {}")
|
31
|
+
assert_equal 0, @runtime.eval("0")
|
32
|
+
assert_equal true, @runtime.eval("true")
|
33
|
+
assert_equal [1, 2], @runtime.eval("[1, 2]")
|
34
|
+
assert_equal [1, nil], @runtime.eval("[1, function() {}]")
|
35
|
+
assert_equal "hello", @runtime.eval("'hello'")
|
36
|
+
assert_equal({"a"=>1,"b"=>2}, @runtime.eval("{a:1,b:2}"))
|
37
|
+
assert_equal({"a"=>true}, @runtime.eval("{a:true,b:function (){}}"))
|
38
|
+
assert_equal "café", @runtime.eval("'café'")
|
39
|
+
assert_equal "☃", @runtime.eval('"☃"')
|
40
|
+
assert_equal "☃", @runtime.eval('"\u2603"')
|
41
|
+
assert_equal "\\", @runtime.eval('"\\\\"')
|
42
|
+
end
|
43
|
+
|
44
|
+
if defined? Encoding
|
45
|
+
def test_encoding
|
46
|
+
utf8 = Encoding.find('UTF-8')
|
47
|
+
|
48
|
+
assert_equal utf8, @runtime.exec("return 'hello'").encoding
|
49
|
+
assert_equal utf8, @runtime.eval("'☃'").encoding
|
50
|
+
|
51
|
+
ascii = "'hello'".encode('US-ASCII')
|
52
|
+
result = @runtime.eval(ascii)
|
53
|
+
assert_equal "hello", result
|
54
|
+
assert_equal utf8, result.encoding
|
55
|
+
|
56
|
+
assert_raise Encoding::UndefinedConversionError do
|
57
|
+
binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
|
58
|
+
@runtime.eval(binary)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_encoding_compile
|
63
|
+
utf8 = Encoding.find('UTF-8')
|
64
|
+
|
65
|
+
context = @runtime.compile("foo = function(v) { return '¶' + v; }".encode("ISO8859-15"))
|
66
|
+
|
67
|
+
assert_equal utf8, context.exec("return foo('hello')").encoding
|
68
|
+
assert_equal utf8, context.eval("foo('☃')").encoding
|
69
|
+
|
70
|
+
ascii = "foo('hello')".encode('US-ASCII')
|
71
|
+
result = context.eval(ascii)
|
72
|
+
assert_equal "¶hello", result
|
73
|
+
assert_equal utf8, result.encoding
|
74
|
+
|
75
|
+
assert_raise Encoding::UndefinedConversionError do
|
76
|
+
binary = "\xde\xad\xbe\xef".force_encoding("BINARY")
|
77
|
+
context.eval(binary)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_compile
|
83
|
+
context = @runtime.compile("foo = function() { return \"bar\"; }")
|
84
|
+
assert_equal "bar", context.exec("return foo()")
|
85
|
+
assert_equal "bar", context.eval("foo()")
|
86
|
+
assert_equal "bar", context.call("foo")
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_compile_with_async
|
90
|
+
context = @runtime.compile_async("foo = function() { callback('bar') }")
|
91
|
+
assert_equal "bar", context.call("foo")
|
92
|
+
assert_equal "bar", context.eval("foo()")
|
93
|
+
assert_equal "bar", context.exec("return foo()")
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_this_is_global_scope
|
97
|
+
assert_equal true, @runtime.eval("this === (function() {return this})()")
|
98
|
+
assert_equal true, @runtime.exec("return this === (function() {return this})()")
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_compile_large_scripts
|
102
|
+
body = "var foo = 'bar';\n" * 100_000
|
103
|
+
assert @runtime.exec("function foo() {\n#{body}\n};\nreturn true")
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_syntax_error
|
107
|
+
assert_raise ExecJS::RuntimeError do
|
108
|
+
@runtime.exec(")")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_thrown_exception
|
113
|
+
assert_raise ExecJS::ProgramError do
|
114
|
+
@runtime.exec("throw 'hello'")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: execjs-async
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Allam
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-28 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: execjs
|
16
|
+
requirement: &70268197049220 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70268197049220
|
25
|
+
description: Enables Asynchronous Javascript Execution in ExecJS
|
26
|
+
email:
|
27
|
+
- rubymaverick@gmail.com
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- .gitignore
|
33
|
+
- .rvmrc
|
34
|
+
- Gemfile
|
35
|
+
- Gemfile.lock
|
36
|
+
- Rakefile
|
37
|
+
- execjs-async.gemspec
|
38
|
+
- lib/execjs-async.rb
|
39
|
+
- lib/execjs-async/version.rb
|
40
|
+
- test/support.rb
|
41
|
+
- test/test_execjs.rb
|
42
|
+
- test/test_runtime.rb
|
43
|
+
homepage: ''
|
44
|
+
licenses: []
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project: execjs-async
|
63
|
+
rubygems_version: 1.8.6
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Enables Asynchronous Javascript Execution in ExecJS
|
67
|
+
test_files:
|
68
|
+
- test/support.rb
|
69
|
+
- test/test_execjs.rb
|
70
|
+
- test/test_runtime.rb
|