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 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'