ruby_box 0.0.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.
- checksums.yaml +7 -0
- data/lib/ruby_box/bindings.rb +39 -0
- data/lib/ruby_box/boxed_error.rb +15 -0
- data/lib/ruby_box/bridging.rb +119 -0
- data/lib/ruby_box/compilation_error.rb +6 -0
- data/lib/ruby_box/error.rb +6 -0
- data/lib/ruby_box/execution.rb +62 -0
- data/lib/ruby_box/execution_error.rb +6 -0
- data/lib/ruby_box/metal.rb +15 -0
- data/lib/ruby_box/runtime_environment.rb +75 -0
- data/lib/ruby_box/thread_safety.rb +97 -0
- data/lib/ruby_box/timeout_error.rb +6 -0
- data/lib/ruby_box/version.rb +3 -0
- data/lib/ruby_box.rb +29 -0
- data/vendor/gems/mini_racer/ext/mini_racer_extension/extconf.rb +54 -0
- data/vendor/gems/mini_racer/ext/mini_racer_extension/mini_racer_extension.cc +910 -0
- data/vendor/gems/mini_racer/lib/mini_racer/version.rb +3 -0
- data/vendor/gems/mini_racer/lib/mini_racer.rb +261 -0
- data/vendor/gems/mini_racer/lib/mini_racer_extension.bundle +0 -0
- metadata +205 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 74ee4ebcf60636a60c2307bbb3b84758d6132689
|
4
|
+
data.tar.gz: da737b1c1922db5b821437c806c66dc672ccd8a9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 91f3c7f353453860a7a160997d002f0fe6b5e8d716221ad16244a8f9b13d8de1d9197bc66ac56ddd17a610d7c171f4f6f38a2c67a50596610b0f2c9de4732f6a
|
7
|
+
data.tar.gz: c428446d7ff6c5ddf170cf0f3425c27968d089f9f0bf51e4019df1750c2a18ff6a4c99d8ec0ec6dbdc3c6ad848ce16ab88a0021396dedbfe75670b8d0dd3f5a4
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
module RubyBox
|
4
|
+
module Bindings
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def bindings
|
9
|
+
@bindings ||= begin
|
10
|
+
if superclass.respond_to?(:bindings)
|
11
|
+
superclass.bindings.dup
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def binds(target, proc = Proc.new)
|
21
|
+
bindings << [target, proc]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(*)
|
26
|
+
super
|
27
|
+
|
28
|
+
self.class.bindings.each do |target, proc|
|
29
|
+
bind target, proc { |*args| instance_exec(*args, &proc) }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def bind(target, proc = Proc.new)
|
36
|
+
context.attach(target, proc)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
module RubyBox
|
4
|
+
class BoxedError < Error
|
5
|
+
def self.[](class_name)
|
6
|
+
boxed_class_name = :"Boxed#{class_name}"
|
7
|
+
|
8
|
+
if const_defined?(boxed_class_name) && (klass = const_get(boxed_class_name)) < self
|
9
|
+
klass
|
10
|
+
else
|
11
|
+
const_set(boxed_class_name, Class.new(self))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'active_support/concern'
|
5
|
+
|
6
|
+
module RubyBox
|
7
|
+
module Bridging
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
requires 'native'
|
12
|
+
requires 'singleton'
|
13
|
+
requires 'json'
|
14
|
+
|
15
|
+
binds('Opal.exit') { |status| raise Error, "Exit with status #{status.inspect}" }
|
16
|
+
|
17
|
+
binds('Opal.STDOUT.write_proc') { |data| stdout << data }
|
18
|
+
binds('Opal.STDERR.write_proc') { |data| stderr << data }
|
19
|
+
|
20
|
+
executes <<-RUBY
|
21
|
+
module RubyBox
|
22
|
+
VERSION = #{VERSION.inspect}
|
23
|
+
|
24
|
+
class CurrentBoxProxy
|
25
|
+
include Singleton
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.boxed?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.current
|
33
|
+
CurrentBoxProxy.instance
|
34
|
+
end
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
|
39
|
+
class_methods do
|
40
|
+
def exposes(*method_names)
|
41
|
+
method_names.each do |method_name|
|
42
|
+
handle = "Opal.RubyBox.CurrentBoxProxy.__exposed_method_#{method_name}"
|
43
|
+
|
44
|
+
wrapper = ->(serialized_args) do
|
45
|
+
args = JSON.parse(serialized_args)
|
46
|
+
value = send(method_name, *args)
|
47
|
+
value.to_json
|
48
|
+
end
|
49
|
+
|
50
|
+
binds(handle, wrapper)
|
51
|
+
|
52
|
+
executes <<-RUBY
|
53
|
+
class RubyBox::CurrentBoxProxy
|
54
|
+
define_method(#{method_name.inspect}) do |*args, &block|
|
55
|
+
raise ArgumentError, 'Cannot pass block to bridged method `RubyBox::CurrentBoxProxy##{method_name}`' unless block.nil?
|
56
|
+
|
57
|
+
serialized_args = args.to_json
|
58
|
+
serialized_value = Native(`#{handle}`).call(serialized_args)
|
59
|
+
|
60
|
+
JSON.parse(serialized_value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
RUBY
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def stdout
|
69
|
+
@stdout ||= []
|
70
|
+
end
|
71
|
+
|
72
|
+
def stderr
|
73
|
+
@stderr ||= []
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def eval_compiled_source(source)
|
79
|
+
is_caught_value, serialized_value = super(<<-JAVASCRIPT)
|
80
|
+
(function(evaluator, source) {
|
81
|
+
var isCaughtValue = false;
|
82
|
+
var value;
|
83
|
+
|
84
|
+
try{
|
85
|
+
value = evaluator(source);
|
86
|
+
|
87
|
+
if(value && typeof(value.$to_json) === 'function') {
|
88
|
+
value = value.$to_json();
|
89
|
+
}
|
90
|
+
}catch(error){
|
91
|
+
if(error && typeof(error.$class) === 'function' && typeof(error.$message) === 'function') {
|
92
|
+
isCaughtValue = true;
|
93
|
+
value = [error.$class().$name(), error.$message()];
|
94
|
+
}else{
|
95
|
+
throw error;
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
if(typeof(value) !== 'string') {
|
100
|
+
value = JSON.stringify(value);
|
101
|
+
}
|
102
|
+
|
103
|
+
return [isCaughtValue, value];
|
104
|
+
})(eval, #{source.to_json});
|
105
|
+
JAVASCRIPT
|
106
|
+
|
107
|
+
value = JSON.parse(serialized_value) if serialized_value
|
108
|
+
|
109
|
+
if is_caught_value
|
110
|
+
class_name, message = value
|
111
|
+
raise BoxedError[class_name], message
|
112
|
+
else
|
113
|
+
value
|
114
|
+
end
|
115
|
+
rescue RuntimeError => error
|
116
|
+
raise ExecutionError, error.message
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'mini_racer'
|
5
|
+
|
6
|
+
module RubyBox
|
7
|
+
module Execution
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def maximum_execution_time
|
12
|
+
@maximum_execution_time ||= begin
|
13
|
+
if superclass.respond_to?(:maximum_execution_time)
|
14
|
+
superclass.maximum_execution_time
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def snapshot
|
22
|
+
@snapshot ||= begin
|
23
|
+
MiniRacer::Snapshot.new snapshot_source
|
24
|
+
end
|
25
|
+
rescue MiniRacer::SnapshotError
|
26
|
+
raise ExecutionError, "The base snapshot for `#{name}` could not be created."
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def snapshot_source
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def times_out_in(seconds)
|
36
|
+
@maximum_execution_time = seconds
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def maximum_execution_time
|
41
|
+
@maximum_execution_time ||= self.class.maximum_execution_time
|
42
|
+
end
|
43
|
+
|
44
|
+
def maximum_execution_time_ms
|
45
|
+
maximum_execution_time * 1000 if maximum_execution_time
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def context
|
51
|
+
@context ||= MiniRacer::Context.new(snapshot: self.class.snapshot, timeout: maximum_execution_time_ms)
|
52
|
+
end
|
53
|
+
|
54
|
+
def eval_compiled_source(source)
|
55
|
+
context.eval source
|
56
|
+
rescue MiniRacer::RuntimeError => error
|
57
|
+
raise RuntimeError, error.message
|
58
|
+
rescue MiniRacer::ScriptTerminatedError => error
|
59
|
+
raise TimeoutError, error.message
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'opal'
|
5
|
+
|
6
|
+
module RubyBox
|
7
|
+
module RuntimeEnvironment
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
uses 'opal'
|
12
|
+
requires 'opal'
|
13
|
+
end
|
14
|
+
|
15
|
+
class_methods do
|
16
|
+
def builder
|
17
|
+
@builder ||= begin
|
18
|
+
if superclass.respond_to?(:builder)
|
19
|
+
superclass.builder.dup
|
20
|
+
else
|
21
|
+
Opal::Builder.new compiler_options: { arity_check: true, dynamic_require_severity: :error }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def uses(*gem_names)
|
29
|
+
gem_names.each { |gem_name| builder.use_gem gem_name }
|
30
|
+
rescue SyntaxError => error
|
31
|
+
raise CompilationError, error.message
|
32
|
+
end
|
33
|
+
|
34
|
+
def requires(*paths)
|
35
|
+
paths.each { |path| builder.build path }
|
36
|
+
rescue SyntaxError => error
|
37
|
+
raise CompilationError, error.message
|
38
|
+
end
|
39
|
+
|
40
|
+
def executes(source)
|
41
|
+
builder.build_str source, '(executes)'
|
42
|
+
rescue SyntaxError => error
|
43
|
+
raise CompilationError, error.message
|
44
|
+
end
|
45
|
+
|
46
|
+
def snapshot_source
|
47
|
+
builder.to_s
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def builder
|
52
|
+
@builder ||= self.class.builder.dup
|
53
|
+
end
|
54
|
+
|
55
|
+
def execute(source)
|
56
|
+
execute_newly_processed_dependencies { builder.build_str source, '(execute)' }
|
57
|
+
rescue SyntaxError => error
|
58
|
+
raise CompilationError, error.message
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def execute_newly_processed_dependencies
|
64
|
+
value = nil
|
65
|
+
capture_newly_processed_dependencies { yield }.each { |dependency| value = eval_compiled_source dependency.source }
|
66
|
+
value
|
67
|
+
end
|
68
|
+
|
69
|
+
def capture_newly_processed_dependencies
|
70
|
+
processed_was = builder.processed.dup
|
71
|
+
yield
|
72
|
+
builder.processed - processed_was
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'ruby_box'
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'thread'
|
5
|
+
require 'monitor'
|
6
|
+
|
7
|
+
module RubyBox
|
8
|
+
module ThreadSafety
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
SEMAPHORE = Mutex.new
|
12
|
+
|
13
|
+
class_methods do
|
14
|
+
def maximum_execution_time
|
15
|
+
synchronize { super }
|
16
|
+
end
|
17
|
+
|
18
|
+
def builder
|
19
|
+
synchronize { super }
|
20
|
+
end
|
21
|
+
|
22
|
+
def snapshot
|
23
|
+
synchronize { super }
|
24
|
+
end
|
25
|
+
|
26
|
+
def bindings
|
27
|
+
synchronize { super }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def times_out_in(*)
|
33
|
+
synchronize { super }
|
34
|
+
end
|
35
|
+
|
36
|
+
def uses(*)
|
37
|
+
synchronize { super }
|
38
|
+
end
|
39
|
+
|
40
|
+
def requires(*)
|
41
|
+
synchronize { super }
|
42
|
+
end
|
43
|
+
|
44
|
+
def executes(*)
|
45
|
+
synchronize { super }
|
46
|
+
end
|
47
|
+
|
48
|
+
def binds(*)
|
49
|
+
synchronize { super }
|
50
|
+
end
|
51
|
+
|
52
|
+
def exposes(*)
|
53
|
+
synchronize { super }
|
54
|
+
end
|
55
|
+
|
56
|
+
def synchronize
|
57
|
+
monitor.synchronize { yield }
|
58
|
+
end
|
59
|
+
|
60
|
+
def monitor
|
61
|
+
SEMAPHORE.synchronize { @monitor ||= Monitor.new }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def maximum_execution_time
|
66
|
+
synchronize { super }
|
67
|
+
end
|
68
|
+
|
69
|
+
def builder
|
70
|
+
synchronize { super }
|
71
|
+
end
|
72
|
+
|
73
|
+
def execute(*)
|
74
|
+
synchronize { super }
|
75
|
+
end
|
76
|
+
|
77
|
+
def stdout
|
78
|
+
synchronize { super }
|
79
|
+
end
|
80
|
+
|
81
|
+
def stderr
|
82
|
+
synchronize { super }
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def synchronize
|
88
|
+
monitor.synchronize { yield }
|
89
|
+
end
|
90
|
+
|
91
|
+
def monitor
|
92
|
+
SEMAPHORE.synchronize { @monitor ||= Monitor.new }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
data/lib/ruby_box.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'ruby_box/version'
|
2
|
+
|
3
|
+
module RubyBox
|
4
|
+
autoload :Bindings, 'ruby_box/bindings'
|
5
|
+
autoload :BoxedError, 'ruby_box/boxed_error'
|
6
|
+
autoload :Bridging, 'ruby_box/bridging'
|
7
|
+
autoload :CompilationError, 'ruby_box/compilation_error'
|
8
|
+
autoload :Error, 'ruby_box/error'
|
9
|
+
autoload :Execution, 'ruby_box/execution'
|
10
|
+
autoload :ExecutionError, 'ruby_box/execution_error'
|
11
|
+
autoload :Metal, 'ruby_box/metal'
|
12
|
+
autoload :RuntimeEnvironment, 'ruby_box/runtime_environment'
|
13
|
+
autoload :ThreadSafety, 'ruby_box/thread_safety'
|
14
|
+
autoload :TimeoutError, 'ruby_box/timeout_error'
|
15
|
+
|
16
|
+
extend self
|
17
|
+
|
18
|
+
def self.boxed?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.current
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute(*args, &block)
|
27
|
+
Metal.execute(*args, &block)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'libv8'
|
3
|
+
|
4
|
+
have_library('pthread')
|
5
|
+
have_library('objc') if RUBY_PLATFORM =~ /darwin/
|
6
|
+
$CPPFLAGS += " -Wall" unless $CPPFLAGS.split.include? "-Wall"
|
7
|
+
$CPPFLAGS += " -g" unless $CPPFLAGS.split.include? "-g"
|
8
|
+
$CPPFLAGS += " -rdynamic" unless $CPPFLAGS.split.include? "-rdynamic"
|
9
|
+
$CPPFLAGS += " -fPIC" unless $CPPFLAGS.split.include? "-rdynamic" or RUBY_PLATFORM =~ /darwin/
|
10
|
+
$CPPFLAGS += " -std=c++0x"
|
11
|
+
$CPPFLAGS += " -fpermissive"
|
12
|
+
|
13
|
+
$LDFLAGS.insert 0, " -stdlib=libstdc++ " if RUBY_PLATFORM =~ /darwin/
|
14
|
+
|
15
|
+
if ENV['CXX']
|
16
|
+
puts "SETTING CXX"
|
17
|
+
CONFIG['CXX'] = ENV['CXX']
|
18
|
+
end
|
19
|
+
|
20
|
+
CXX11_TEST = <<EOS
|
21
|
+
#if __cplusplus <= 199711L
|
22
|
+
# error A compiler that supports at least C++11 is required in order to compile this project.
|
23
|
+
#endif
|
24
|
+
EOS
|
25
|
+
|
26
|
+
`echo "#{CXX11_TEST}" | #{CONFIG['CXX']} -std=c++0x -x c++ -E -`
|
27
|
+
unless $?.success?
|
28
|
+
warn <<EOS
|
29
|
+
|
30
|
+
|
31
|
+
WARNING: C++11 support is required for compiling mini_racer. Please make sure
|
32
|
+
you are using a compiler that supports at least C++11. Examples of such
|
33
|
+
compilers are GCC 4.7+ and Clang 3.2+.
|
34
|
+
|
35
|
+
If you are using Travis, consider either migrating your bulid to Ubuntu Trusty or
|
36
|
+
installing GCC 4.8. See mini_racer's README.md for more information.
|
37
|
+
|
38
|
+
|
39
|
+
EOS
|
40
|
+
end
|
41
|
+
|
42
|
+
CONFIG['LDSHARED'] = '$(CXX) -shared' unless RUBY_PLATFORM =~ /darwin/
|
43
|
+
if CONFIG['warnflags']
|
44
|
+
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
|
45
|
+
CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '')
|
46
|
+
end
|
47
|
+
|
48
|
+
if enable_config('debug')
|
49
|
+
CONFIG['debugflags'] << ' -ggdb3 -O0'
|
50
|
+
end
|
51
|
+
|
52
|
+
Libv8.configure_makefile
|
53
|
+
|
54
|
+
create_makefile 'mini_racer_extension'
|