mustang 0.1.1 → 0.2.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.
- data/README.md +11 -1
- data/Rakefile +1 -1
- data/TODO.md +2 -1
- data/ext/v8/extconf.rb +3 -1
- data/ext/v8/v8_array.cpp +2 -0
- data/ext/v8/v8_context.cpp +32 -5
- data/ext/v8/v8_date.cpp +1 -0
- data/ext/v8/v8_external.cpp +1 -0
- data/ext/v8/v8_function.cpp +3 -0
- data/ext/v8/v8_integer.cpp +1 -0
- data/ext/v8/v8_macros.h +6 -0
- data/ext/v8/v8_main.cpp +3 -1
- data/ext/v8/v8_number.cpp +1 -0
- data/ext/v8/v8_object.cpp +2 -0
- data/ext/v8/v8_regexp.cpp +1 -0
- data/ext/v8/v8_string.cpp +1 -0
- data/ext/v8/v8_value.cpp +2 -0
- data/lib/mustang.rb +20 -27
- data/lib/mustang/context.rb +0 -26
- data/lib/{core_ext → mustang/core_ext}/class.rb +1 -1
- data/lib/{core_ext → mustang/core_ext}/object.rb +2 -4
- data/lib/{core_ext → mustang/core_ext}/symbol.rb +0 -0
- data/lib/{support → mustang/support}/delegated.rb +0 -0
- data/lib/mustang/v8/array.rb +21 -0
- data/lib/mustang/v8/context.rb +15 -0
- data/lib/mustang/v8/date.rb +20 -0
- data/lib/mustang/v8/error.rb +17 -0
- data/lib/mustang/v8/external.rb +16 -0
- data/lib/mustang/v8/function.rb +13 -0
- data/lib/mustang/v8/integer.rb +16 -0
- data/lib/mustang/v8/number.rb +16 -0
- data/lib/mustang/v8/object.rb +66 -0
- data/lib/mustang/v8/regexp.rb +23 -0
- data/lib/mustang/v8/string.rb +27 -0
- data/mustang.gemspec +1 -1
- data/spec/{core_ext → mustang/core_ext}/class_spec.rb +3 -3
- data/spec/{core_ext → mustang/core_ext}/object_spec.rb +3 -3
- data/spec/{core_ext → mustang/core_ext}/symbol_spec.rb +1 -1
- data/spec/{v8 → mustang/v8}/array_spec.rb +12 -5
- data/spec/{v8 → mustang/v8}/cast_spec.rb +10 -10
- data/spec/{v8 → mustang/v8}/context_spec.rb +52 -6
- data/spec/{v8 → mustang/v8}/data_spec.rb +4 -4
- data/spec/{v8 → mustang/v8}/date_spec.rb +12 -5
- data/spec/{v8 → mustang/v8}/empty_spec.rb +4 -4
- data/spec/{v8 → mustang/v8}/errors_spec.rb +9 -9
- data/spec/{v8 → mustang/v8}/external_spec.rb +14 -7
- data/spec/{v8 → mustang/v8}/function_spec.rb +20 -13
- data/spec/{v8 → mustang/v8}/integer_spec.rb +13 -6
- data/spec/{v8 → mustang/v8}/main_spec.rb +2 -2
- data/spec/{v8 → mustang/v8}/null_spec.rb +4 -4
- data/spec/{v8 → mustang/v8}/number_spec.rb +5 -5
- data/spec/{v8 → mustang/v8}/object_spec.rb +13 -6
- data/spec/mustang/v8/primitive_spec.rb +9 -0
- data/spec/{v8 → mustang/v8}/regexp_spec.rb +12 -5
- data/spec/{v8 → mustang/v8}/string_spec.rb +12 -5
- data/spec/{v8 → mustang/v8}/undefined_spec.rb +4 -4
- data/spec/mustang/v8/value_spec.rb +222 -0
- data/spec/spec_helper.rb +1 -1
- metadata +91 -62
- data/lib/v8/array.rb +0 -21
- data/lib/v8/context.rb +0 -13
- data/lib/v8/date.rb +0 -20
- data/lib/v8/error.rb +0 -15
- data/lib/v8/external.rb +0 -16
- data/lib/v8/function.rb +0 -11
- data/lib/v8/integer.rb +0 -16
- data/lib/v8/number.rb +0 -16
- data/lib/v8/object.rb +0 -66
- data/lib/v8/regexp.rb +0 -23
- data/lib/v8/string.rb +0 -27
- data/spec/v8/primitive_spec.rb +0 -9
- data/spec/v8/value_spec.rb +0 -215
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
Mustang development is proudly sponsored by [Cubox, Agile Rails Devshop](http://cuboxsa.com)
|
2
2
|
|
3
3
|
# Mustang - V8 engine in Ruby's body
|
4
4
|
|
@@ -6,6 +6,12 @@ Mustang is ruby proxy library for awesome Google V8 JavaScript engine.
|
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
+
Before you install mustang gem make sure you have `scons` installed.
|
10
|
+
|
11
|
+
$ sudo apt-get install scons # on debian
|
12
|
+
$ sudo pacman -S scons # on archlinux
|
13
|
+
$ brew install scons # on mac...
|
14
|
+
|
9
15
|
Using rubygems:
|
10
16
|
|
11
17
|
$ gem install mustang
|
@@ -28,6 +34,10 @@ For now it's only proof of concept. It implements very simple evaluation of java
|
|
28
34
|
cxt.eval("var a=1;")
|
29
35
|
cxt.eval("a+5;") # => 6
|
30
36
|
|
37
|
+
cxt[:puts] = method(:puts)
|
38
|
+
cxt.eval("puts(a)") # displays "1" on the screen
|
39
|
+
cxt[:a] # => 1
|
40
|
+
|
31
41
|
## Note on Patches/Pull Requests
|
32
42
|
|
33
43
|
* Fork the project.
|
data/Rakefile
CHANGED
data/TODO.md
CHANGED
data/ext/v8/extconf.rb
CHANGED
@@ -52,8 +52,10 @@ find_library('v8', nil, lib)
|
|
52
52
|
have_library('pthread')
|
53
53
|
have_header('v8.h')
|
54
54
|
|
55
|
+
CONFIG['LDSHARED'] = '$(CXX) -shared' unless darwin?
|
56
|
+
|
55
57
|
%w[-Wall -g -rdynamic -fPIC].each { |flag|
|
56
58
|
$CPPFLAGS += " #{flag}" unless $CPPFLAGS.include?(flag)
|
57
59
|
}
|
58
60
|
|
59
|
-
create_makefile('v8')
|
61
|
+
create_makefile('mustang/v8')
|
data/ext/v8/v8_array.cpp
CHANGED
@@ -36,6 +36,8 @@ Handle<Value> to_v8_array(VALUE value)
|
|
36
36
|
static VALUE rb_v8_array_new(VALUE klass, VALUE data)
|
37
37
|
{
|
38
38
|
HandleScope scope;
|
39
|
+
PREVENT_CREATION_WITHOUT_CONTEXT();
|
40
|
+
|
39
41
|
VALUE ary = rb_funcall2(data, rb_intern("to_a"), 0, NULL);
|
40
42
|
VALUE self = v8_ref_new(klass, to_v8_array(ary));
|
41
43
|
|
data/ext/v8/v8_context.cpp
CHANGED
@@ -11,6 +11,8 @@ UNWRAPPER(Context);
|
|
11
11
|
|
12
12
|
/* V8::Context methods */
|
13
13
|
|
14
|
+
static VALUE rb_v8_context_enter(VALUE self);
|
15
|
+
|
14
16
|
/*
|
15
17
|
* call-seq:
|
16
18
|
* V8::Context.new => new_context
|
@@ -24,6 +26,7 @@ static VALUE rb_v8_context_new(VALUE self)
|
|
24
26
|
Persistent<Context> context(Context::New());
|
25
27
|
|
26
28
|
VALUE ref = v8_ref_new(self, context);
|
29
|
+
rb_v8_context_enter(ref);
|
27
30
|
rb_iv_set(ref, "@errors", rb_ary_new());
|
28
31
|
|
29
32
|
context.Dispose();
|
@@ -129,6 +132,19 @@ static VALUE rb_v8_context_global(VALUE self)
|
|
129
132
|
return to_ruby(global);
|
130
133
|
}
|
131
134
|
|
135
|
+
/*
|
136
|
+
* call-seq:
|
137
|
+
* cxt.entered? => true or false
|
138
|
+
*
|
139
|
+
* Returns <code>true</code> when this context is entered.
|
140
|
+
*
|
141
|
+
*/
|
142
|
+
static VALUE rb_v8_context_entered_p(VALUE self)
|
143
|
+
{
|
144
|
+
HandleScope scope;
|
145
|
+
return unwrap(self) == Context::GetEntered() ? Qtrue : Qfalse;
|
146
|
+
}
|
147
|
+
|
132
148
|
/*
|
133
149
|
* call-seq:
|
134
150
|
* cxt.exit => nil
|
@@ -139,21 +155,31 @@ static VALUE rb_v8_context_global(VALUE self)
|
|
139
155
|
static VALUE rb_v8_context_exit(VALUE self)
|
140
156
|
{
|
141
157
|
HandleScope scope;
|
142
|
-
|
158
|
+
Handle<Context> context;
|
159
|
+
|
160
|
+
if (Context::InContext()) {
|
161
|
+
context->Exit();
|
162
|
+
}
|
163
|
+
|
143
164
|
return Qnil;
|
144
165
|
}
|
145
166
|
|
146
167
|
/*
|
147
168
|
* call-seq:
|
148
|
-
*
|
169
|
+
* V8::Context.exit_all! => nil
|
149
170
|
*
|
150
|
-
*
|
171
|
+
* Exits from all entered context.
|
151
172
|
*
|
152
173
|
*/
|
153
|
-
static VALUE
|
174
|
+
static VALUE rb_v8_context_exit_all_bang(VALUE klass)
|
154
175
|
{
|
155
176
|
HandleScope scope;
|
156
|
-
|
177
|
+
|
178
|
+
while (Context::InContext()) {
|
179
|
+
Context::GetEntered()->Exit();
|
180
|
+
}
|
181
|
+
|
182
|
+
return Qnil;
|
157
183
|
}
|
158
184
|
|
159
185
|
|
@@ -162,6 +188,7 @@ void Init_V8_Context()
|
|
162
188
|
{
|
163
189
|
rb_cV8Context = rb_define_class_under(rb_mV8, "Context", rb_cObject);
|
164
190
|
rb_define_singleton_method(rb_cV8Context, "new", RUBY_METHOD_FUNC(rb_v8_context_new), 0);
|
191
|
+
rb_define_singleton_method(rb_cV8Context, "exit_all!", RUBY_METHOD_FUNC(rb_v8_context_exit_all_bang), 0);
|
165
192
|
rb_define_method(rb_cV8Context, "evaluate", RUBY_METHOD_FUNC(rb_v8_context_evaluate), 2);
|
166
193
|
rb_define_method(rb_cV8Context, "eval", RUBY_METHOD_FUNC(rb_v8_context_evaluate), 2);
|
167
194
|
rb_define_method(rb_cV8Context, "prototype", RUBY_METHOD_FUNC(rb_v8_context_prototype), 0);
|
data/ext/v8/v8_date.cpp
CHANGED
data/ext/v8/v8_external.cpp
CHANGED
data/ext/v8/v8_function.cpp
CHANGED
@@ -61,6 +61,8 @@ Handle<Value> to_v8_function(VALUE value)
|
|
61
61
|
static VALUE rb_v8_function_new(int argc, VALUE *argv, VALUE klass)
|
62
62
|
{
|
63
63
|
HandleScope scope;
|
64
|
+
PREVENT_CREATION_WITHOUT_CONTEXT();
|
65
|
+
|
64
66
|
VALUE orig;
|
65
67
|
|
66
68
|
if (rb_block_given_p()) {
|
@@ -76,6 +78,7 @@ static VALUE rb_v8_function_new(int argc, VALUE *argv, VALUE klass)
|
|
76
78
|
|
77
79
|
VALUE self = v8_ref_new(klass, to_v8_function(orig), orig);
|
78
80
|
rb_iv_set(self, "@origin", orig);
|
81
|
+
rb_iv_set(self, "@receiver", Qnil);
|
79
82
|
v8_set_peer(self);
|
80
83
|
|
81
84
|
return self;
|
data/ext/v8/v8_integer.cpp
CHANGED
@@ -28,6 +28,7 @@ Handle<Value> to_v8_integer(VALUE value)
|
|
28
28
|
static VALUE rb_v8_integer_new(VALUE klass, VALUE data)
|
29
29
|
{
|
30
30
|
HandleScope scope;
|
31
|
+
PREVENT_CREATION_WITHOUT_CONTEXT();
|
31
32
|
VALUE num = rb_funcall2(data, rb_intern("to_i"), 0, NULL);
|
32
33
|
return v8_ref_new(klass, to_v8_integer(num));
|
33
34
|
}
|
data/ext/v8/v8_macros.h
CHANGED
@@ -27,4 +27,10 @@
|
|
27
27
|
return v8_ref_get<T>(self); \
|
28
28
|
}
|
29
29
|
|
30
|
+
#define PREVENT_CREATION_WITHOUT_CONTEXT() \
|
31
|
+
if (!Context::InContext()) { \
|
32
|
+
rb_raise(rb_eRuntimeError, "can't create V8 object without entering into context"); \
|
33
|
+
return Qnil; \
|
34
|
+
}
|
35
|
+
|
30
36
|
#endif//__V8_MACROS_H
|
data/ext/v8/v8_main.cpp
CHANGED
@@ -46,7 +46,9 @@ static VALUE rb_v8_version(VALUE self)
|
|
46
46
|
/* V8 module initializer. */
|
47
47
|
void Init_V8()
|
48
48
|
{
|
49
|
-
|
49
|
+
VALUE rb_mMustang = rb_define_module("Mustang");
|
50
|
+
|
51
|
+
rb_mV8 = rb_define_module_under(rb_mMustang, "V8");
|
50
52
|
rb_define_singleton_method(rb_mV8, "dead?", RUBY_METHOD_FUNC(rb_v8_dead_p), 0);
|
51
53
|
rb_define_singleton_method(rb_mV8, "alive?", RUBY_METHOD_FUNC(rb_v8_alive_p), 0);
|
52
54
|
rb_define_singleton_method(rb_mV8, "version", RUBY_METHOD_FUNC(rb_v8_version), 0);
|
data/ext/v8/v8_number.cpp
CHANGED
@@ -28,6 +28,7 @@ Handle<Value> to_v8_number(VALUE value)
|
|
28
28
|
static VALUE rb_v8_number_new(VALUE klass, VALUE data)
|
29
29
|
{
|
30
30
|
HandleScope scope;
|
31
|
+
PREVENT_CREATION_WITHOUT_CONTEXT();
|
31
32
|
VALUE num = rb_funcall2(data, rb_intern("to_f"), 0, NULL);
|
32
33
|
return v8_ref_new(klass, to_v8_number(num));
|
33
34
|
}
|
data/ext/v8/v8_object.cpp
CHANGED
data/ext/v8/v8_regexp.cpp
CHANGED
data/ext/v8/v8_string.cpp
CHANGED
@@ -28,6 +28,7 @@ Handle<Value> to_v8_string(VALUE value)
|
|
28
28
|
static VALUE rb_v8_string_new(VALUE klass, VALUE data)
|
29
29
|
{
|
30
30
|
HandleScope scope;
|
31
|
+
PREVENT_CREATION_WITHOUT_CONTEXT();
|
31
32
|
VALUE str = rb_funcall2(data, rb_intern("to_s"), 0, NULL);
|
32
33
|
return v8_ref_new(klass, to_v8_string(str));
|
33
34
|
}
|
data/ext/v8/v8_value.cpp
CHANGED
data/lib/mustang.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
require 'v8
|
4
|
-
require 'v8/
|
5
|
-
require 'v8/
|
6
|
-
require 'v8/
|
7
|
-
require 'v8/
|
8
|
-
require 'v8/
|
9
|
-
require 'v8/
|
10
|
-
require 'v8/
|
11
|
-
require 'v8/
|
12
|
-
require 'v8/
|
13
|
-
|
14
|
-
require '
|
15
|
-
|
16
|
-
require 'core_ext/object'
|
17
|
-
require 'core_ext/class'
|
18
|
-
require 'core_ext/symbol'
|
1
|
+
require 'mustang/support/delegated'
|
2
|
+
|
3
|
+
require 'mustang/v8'
|
4
|
+
require 'mustang/v8/context'
|
5
|
+
require 'mustang/v8/object'
|
6
|
+
require 'mustang/v8/string'
|
7
|
+
require 'mustang/v8/integer'
|
8
|
+
require 'mustang/v8/number'
|
9
|
+
require 'mustang/v8/array'
|
10
|
+
require 'mustang/v8/date'
|
11
|
+
require 'mustang/v8/regexp'
|
12
|
+
require 'mustang/v8/function'
|
13
|
+
require 'mustang/v8/external'
|
14
|
+
require 'mustang/v8/error'
|
15
|
+
|
16
|
+
require 'mustang/core_ext/object'
|
17
|
+
require 'mustang/core_ext/class'
|
18
|
+
require 'mustang/core_ext/symbol'
|
19
19
|
|
20
20
|
require 'mustang/context'
|
21
21
|
|
@@ -26,19 +26,12 @@ module Mustang
|
|
26
26
|
global
|
27
27
|
end
|
28
28
|
|
29
|
-
# Global context.
|
30
29
|
def self.global
|
31
30
|
@global or reset!
|
32
31
|
end
|
33
32
|
|
34
|
-
# Resets global context state
|
35
|
-
# context and enters it.
|
33
|
+
# Resets global context state (just creates new global context and enters to it).
|
36
34
|
def self.reset!(*args, &block)
|
37
|
-
@global =
|
35
|
+
@global = Context.new(*args, &block)
|
38
36
|
end
|
39
|
-
|
40
|
-
# We need enter into global context to avoid segfaults. Apart of my laziness
|
41
|
-
# keeping one global context is much easier than handling errors in all
|
42
|
-
# V8 datatypes implementation...
|
43
|
-
enter
|
44
37
|
end # Mustang
|
data/lib/mustang/context.rb
CHANGED
@@ -3,10 +3,6 @@ module Mustang
|
|
3
3
|
class ScriptNotFoundError < Errno::ENOENT
|
4
4
|
end
|
5
5
|
|
6
|
-
# Raised when try to exit from global context.
|
7
|
-
class ImmortalContextError < RuntimeError
|
8
|
-
end
|
9
|
-
|
10
6
|
# Extended and more user-friendly version of <tt>Mustang::V8::Context</tt>.
|
11
7
|
class Context < V8::Context
|
12
8
|
# Evaluates given javascript source. Before evaluation it's able to
|
@@ -43,27 +39,5 @@ module Mustang
|
|
43
39
|
def errors
|
44
40
|
@errors ||= []
|
45
41
|
end
|
46
|
-
|
47
|
-
# Returns <tt>true</tt> when it is global (immortal) context.
|
48
|
-
def global?
|
49
|
-
false
|
50
|
-
end
|
51
42
|
end # Context
|
52
|
-
|
53
|
-
# This kind of context is used by <tt>Mustang</tt> module.
|
54
|
-
class GlobalContext < Context
|
55
|
-
def initialize(*)
|
56
|
-
super
|
57
|
-
enter
|
58
|
-
end
|
59
|
-
|
60
|
-
def exit
|
61
|
-
# We have to disable exit, because global context is immortal.
|
62
|
-
raise ImmortalContextError, "Global context can't be exited"
|
63
|
-
end
|
64
|
-
|
65
|
-
def global?
|
66
|
-
true
|
67
|
-
end
|
68
|
-
end # GlobalContext
|
69
43
|
end # Mustang
|
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'v8'
|
2
|
-
|
3
1
|
class Object
|
4
2
|
# From now on each object can be easily converted to <tt>V8::*</tt> object
|
5
3
|
# using <tt>#to_v8</tt> method.
|
6
|
-
include V8::Cast
|
4
|
+
include Mustang::V8::Cast
|
7
5
|
|
8
6
|
# Returns <tt>true</tt> when given object is reflected from within V8.
|
9
7
|
def v8?
|
10
|
-
kind_of?(V8::Data)
|
8
|
+
kind_of?(Mustang::V8::Data)
|
11
9
|
end
|
12
10
|
end # Object
|
File without changes
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Mustang
|
2
|
+
module V8
|
3
|
+
class Array
|
4
|
+
include Comparable
|
5
|
+
include Enumerable
|
6
|
+
include Delegated
|
7
|
+
|
8
|
+
def <=>(other)
|
9
|
+
to_a <=> other
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(*args, &block)
|
13
|
+
to_a.each(*args, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def delegate
|
17
|
+
to_a
|
18
|
+
end
|
19
|
+
end # Array
|
20
|
+
end # V8
|
21
|
+
end # Mustang
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mustang
|
2
|
+
module V8
|
3
|
+
class Date
|
4
|
+
include Comparable
|
5
|
+
include Delegated
|
6
|
+
|
7
|
+
def to_time
|
8
|
+
Time.at(to_i);
|
9
|
+
end
|
10
|
+
|
11
|
+
def <=>(other)
|
12
|
+
to_time <=> other
|
13
|
+
end
|
14
|
+
|
15
|
+
def delegate
|
16
|
+
to_time
|
17
|
+
end
|
18
|
+
end # Date
|
19
|
+
end # V8
|
20
|
+
end # Mustang
|