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.
Files changed (72) hide show
  1. data/README.md +11 -1
  2. data/Rakefile +1 -1
  3. data/TODO.md +2 -1
  4. data/ext/v8/extconf.rb +3 -1
  5. data/ext/v8/v8_array.cpp +2 -0
  6. data/ext/v8/v8_context.cpp +32 -5
  7. data/ext/v8/v8_date.cpp +1 -0
  8. data/ext/v8/v8_external.cpp +1 -0
  9. data/ext/v8/v8_function.cpp +3 -0
  10. data/ext/v8/v8_integer.cpp +1 -0
  11. data/ext/v8/v8_macros.h +6 -0
  12. data/ext/v8/v8_main.cpp +3 -1
  13. data/ext/v8/v8_number.cpp +1 -0
  14. data/ext/v8/v8_object.cpp +2 -0
  15. data/ext/v8/v8_regexp.cpp +1 -0
  16. data/ext/v8/v8_string.cpp +1 -0
  17. data/ext/v8/v8_value.cpp +2 -0
  18. data/lib/mustang.rb +20 -27
  19. data/lib/mustang/context.rb +0 -26
  20. data/lib/{core_ext → mustang/core_ext}/class.rb +1 -1
  21. data/lib/{core_ext → mustang/core_ext}/object.rb +2 -4
  22. data/lib/{core_ext → mustang/core_ext}/symbol.rb +0 -0
  23. data/lib/{support → mustang/support}/delegated.rb +0 -0
  24. data/lib/mustang/v8/array.rb +21 -0
  25. data/lib/mustang/v8/context.rb +15 -0
  26. data/lib/mustang/v8/date.rb +20 -0
  27. data/lib/mustang/v8/error.rb +17 -0
  28. data/lib/mustang/v8/external.rb +16 -0
  29. data/lib/mustang/v8/function.rb +13 -0
  30. data/lib/mustang/v8/integer.rb +16 -0
  31. data/lib/mustang/v8/number.rb +16 -0
  32. data/lib/mustang/v8/object.rb +66 -0
  33. data/lib/mustang/v8/regexp.rb +23 -0
  34. data/lib/mustang/v8/string.rb +27 -0
  35. data/mustang.gemspec +1 -1
  36. data/spec/{core_ext → mustang/core_ext}/class_spec.rb +3 -3
  37. data/spec/{core_ext → mustang/core_ext}/object_spec.rb +3 -3
  38. data/spec/{core_ext → mustang/core_ext}/symbol_spec.rb +1 -1
  39. data/spec/{v8 → mustang/v8}/array_spec.rb +12 -5
  40. data/spec/{v8 → mustang/v8}/cast_spec.rb +10 -10
  41. data/spec/{v8 → mustang/v8}/context_spec.rb +52 -6
  42. data/spec/{v8 → mustang/v8}/data_spec.rb +4 -4
  43. data/spec/{v8 → mustang/v8}/date_spec.rb +12 -5
  44. data/spec/{v8 → mustang/v8}/empty_spec.rb +4 -4
  45. data/spec/{v8 → mustang/v8}/errors_spec.rb +9 -9
  46. data/spec/{v8 → mustang/v8}/external_spec.rb +14 -7
  47. data/spec/{v8 → mustang/v8}/function_spec.rb +20 -13
  48. data/spec/{v8 → mustang/v8}/integer_spec.rb +13 -6
  49. data/spec/{v8 → mustang/v8}/main_spec.rb +2 -2
  50. data/spec/{v8 → mustang/v8}/null_spec.rb +4 -4
  51. data/spec/{v8 → mustang/v8}/number_spec.rb +5 -5
  52. data/spec/{v8 → mustang/v8}/object_spec.rb +13 -6
  53. data/spec/mustang/v8/primitive_spec.rb +9 -0
  54. data/spec/{v8 → mustang/v8}/regexp_spec.rb +12 -5
  55. data/spec/{v8 → mustang/v8}/string_spec.rb +12 -5
  56. data/spec/{v8 → mustang/v8}/undefined_spec.rb +4 -4
  57. data/spec/mustang/v8/value_spec.rb +222 -0
  58. data/spec/spec_helper.rb +1 -1
  59. metadata +91 -62
  60. data/lib/v8/array.rb +0 -21
  61. data/lib/v8/context.rb +0 -13
  62. data/lib/v8/date.rb +0 -20
  63. data/lib/v8/error.rb +0 -15
  64. data/lib/v8/external.rb +0 -16
  65. data/lib/v8/function.rb +0 -11
  66. data/lib/v8/integer.rb +0 -16
  67. data/lib/v8/number.rb +0 -16
  68. data/lib/v8/object.rb +0 -66
  69. data/lib/v8/regexp.rb +0 -23
  70. data/lib/v8/string.rb +0 -27
  71. data/spec/v8/primitive_spec.rb +0 -9
  72. data/spec/v8/value_spec.rb +0 -215
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- This code is proudly sponsored by [Cubox, Agile Rails Devshop](http://cuboxsa.com)
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
@@ -9,7 +9,7 @@ end
9
9
  begin
10
10
  require 'rake/extensiontask'
11
11
  Rake::ExtensionTask.new("v8") do |ext|
12
- ext.lib_dir = 'lib'
12
+ ext.lib_dir = 'lib/mustang'
13
13
  ext.source_pattern = "*.{cpp,h}"
14
14
  end
15
15
  rescue LoadError
data/TODO.md CHANGED
@@ -6,4 +6,5 @@
6
6
  * specs for support modules
7
7
  * v8 debug stuff
8
8
  * support for ObjectTemplates
9
- * reflecting ruby classes to FunctionTemplates
9
+ * reflecting ruby classes to FunctionTemplates
10
+ * getting entered context
@@ -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')
@@ -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
 
@@ -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
- unwrap(self)->Exit();
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
- * cxt.entered? => true or false
169
+ * V8::Context.exit_all! => nil
149
170
  *
150
- * Returns <code>true</code> when this context is entered.
171
+ * Exits from all entered context.
151
172
  *
152
173
  */
153
- static VALUE rb_v8_context_entered_p(VALUE self)
174
+ static VALUE rb_v8_context_exit_all_bang(VALUE klass)
154
175
  {
155
176
  HandleScope scope;
156
- return unwrap(self) == Context::GetEntered() ? Qtrue : Qfalse;
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);
@@ -28,6 +28,7 @@ Handle<Value> to_v8_date(VALUE value)
28
28
  static VALUE rb_v8_date_new(VALUE klass, VALUE time)
29
29
  {
30
30
  HandleScope scope;
31
+ PREVENT_CREATION_WITHOUT_CONTEXT();
31
32
  return v8_ref_new(klass, to_v8_date(time));
32
33
  }
33
34
 
@@ -29,6 +29,7 @@ Handle<Value> to_v8_external(VALUE value)
29
29
  static VALUE rb_v8_external_new(VALUE klass, VALUE obj)
30
30
  {
31
31
  HandleScope scope;
32
+ PREVENT_CREATION_WITHOUT_CONTEXT();
32
33
  return v8_ref_new(klass, to_v8_external(obj));
33
34
  }
34
35
 
@@ -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;
@@ -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
  }
@@ -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
@@ -46,7 +46,9 @@ static VALUE rb_v8_version(VALUE self)
46
46
  /* V8 module initializer. */
47
47
  void Init_V8()
48
48
  {
49
- rb_mV8 = rb_define_module("V8");
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);
@@ -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
  }
@@ -51,6 +51,8 @@ Handle<Value> to_v8_object(VALUE value)
51
51
  static VALUE rb_v8_object_new(int argc, VALUE *argv, VALUE klass)
52
52
  {
53
53
  HandleScope scope;
54
+ PREVENT_CREATION_WITHOUT_CONTEXT();
55
+
54
56
  VALUE self;
55
57
 
56
58
  switch (argc) {
@@ -61,6 +61,7 @@ Handle<Value> to_v8_regexp(VALUE value)
61
61
  static VALUE rb_v8_regexp_new(int argc, VALUE *argv, VALUE klass)
62
62
  {
63
63
  HandleScope scope;
64
+ PREVENT_CREATION_WITHOUT_CONTEXT();
64
65
 
65
66
  if (argc == 1) {
66
67
  return v8_ref_new(klass, to_v8_regexp(argv[0]));
@@ -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
  }
@@ -21,6 +21,8 @@ UNWRAPPER(Value);
21
21
  */
22
22
  static VALUE rb_v8_value_new(VALUE self, VALUE data)
23
23
  {
24
+ HandleScope scope;
25
+ PREVENT_CREATION_WITHOUT_CONTEXT();
24
26
  return v8_ref_new(self, to_v8(data));
25
27
  }
26
28
 
@@ -1,21 +1,21 @@
1
- require 'v8'
2
- require 'v8/context'
3
- require 'v8/object'
4
- require 'v8/string'
5
- require 'v8/integer'
6
- require 'v8/number'
7
- require 'v8/array'
8
- require 'v8/date'
9
- require 'v8/regexp'
10
- require 'v8/function'
11
- require 'v8/external'
12
- require 'v8/error'
13
-
14
- require 'support/delegated'
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. Appartently just creates new global
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 = GlobalContext.new(*args, &block)
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
@@ -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
@@ -9,6 +9,6 @@ class Class
9
9
  klass = klass.superclass
10
10
  end
11
11
 
12
- result
12
+ result.map { |m| m.to_sym }
13
13
  end
14
14
  end # Class
@@ -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
@@ -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,15 @@
1
+ module Mustang
2
+ module V8
3
+ class Context
4
+ def get(key)
5
+ prototype[key]
6
+ end
7
+ alias_method :[], :get
8
+
9
+ def set(key, value)
10
+ prototype[key] = value
11
+ end
12
+ alias_method :[]=, :set
13
+ end # Context
14
+ end # V8
15
+ 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