mustang 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|