ruby_box 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,6 @@
1
+ require 'ruby_box'
2
+
3
+ module RubyBox
4
+ class CompilationError < Error
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'ruby_box'
2
+
3
+ module RubyBox
4
+ class Error < StandardError
5
+ end
6
+ 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,6 @@
1
+ require 'ruby_box'
2
+
3
+ module RubyBox
4
+ class ExecutionError < Error
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ require 'ruby_box'
2
+
3
+ module RubyBox
4
+ class Metal
5
+ include Execution
6
+ include RuntimeEnvironment
7
+ include Bindings
8
+ include Bridging
9
+ include ThreadSafety
10
+
11
+ def self.execute(*args, &block)
12
+ new.execute(*args, &block)
13
+ end
14
+ end
15
+ 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
+
@@ -0,0 +1,6 @@
1
+ require 'ruby_box'
2
+
3
+ module RubyBox
4
+ class TimeoutError < Error
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module RubyBox
2
+ VERSION = '0.0.0'
3
+ end
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'