mini_racer 0.1.0 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 365bb5119d8c0f9fef1a0014571bb0e2a1cde1cc
4
- data.tar.gz: 9ba16c2f09d9fe6866f241e48799e4dbb98f7595
3
+ metadata.gz: ef7d560456c68712a83c6167b76c27fa2f145da2
4
+ data.tar.gz: f299b830d1df20a115fdc8f63aea4a7c9f0328b3
5
5
  SHA512:
6
- metadata.gz: af0228ed94c7145c9847c5106b1c8a5d6b71e419e42d778f1945a8bd94d18763c19da2975a6e68300b02ed6ea9ab52193a62304b8517a48a379938375a440325
7
- data.tar.gz: 63f0160dec7e7e5583486be942d1cee07ebb3af30f4ae9ed88db231986918332bf8b343335376a69a30c890bb2c014954d9b84f60818d354fad2bb5596f7ac58
6
+ metadata.gz: 007738356ef3475876ea8c125cc4ccd487df22c6cbdd1ae5a793865825ffdae79c6b578e9f038845462314ca9fcf1745c75f97818fc36ff4186f58ed202cafa7
7
+ data.tar.gz: 6f3da0e1c5a6898f63fa625499704a0ed4e31d47af042e90c796dd99d635723522357c7f36e1cf530844b7ff7a8f97ee13efa0d135aca3b53665b82755b6264b
data/CHANGELOG CHANGED
@@ -1,11 +1,26 @@
1
+ 19-05-2016
2
+
3
+ - 0.1.3
4
+
5
+ - Support more conversions from Ruby back to JS (Hash, Symbol, Array)
6
+ - Support attaching nested objects
7
+
8
+
9
+ 17-05-2016
10
+
11
+ - 0.1.2
12
+
13
+ - Gemspec specifies minimal version of Ruby (2.0)
14
+ - Implement #load on Context to load files
15
+
1
16
  17-05-2016
2
17
 
3
- - 0.0.1
18
+ - 0.1.1
4
19
 
5
20
  - Added unblock function so SIGINT does not lead to a crash
6
21
 
7
22
  14-05-2016
8
23
 
9
- - 0.0.1.beta.1
24
+ - 0.1.1.beta.1
10
25
 
11
26
  - First release
data/README.md CHANGED
@@ -29,11 +29,18 @@ You can attach one or many ruby proc that can be accessed via JavaScript
29
29
 
30
30
  ```ruby
31
31
  context = MiniRacer::Context.new
32
- context.attach("adder", proc{|a,b| a+b})
33
- puts context.eval 'adder(20,22)'
32
+ context.attach("math.adder", proc{|a,b| a+b})
33
+ puts context.eval 'math.adder(20,22)'
34
34
  # => 42
35
35
  ```
36
36
 
37
+ ```ruby
38
+ context = MiniRacer::Context.new
39
+ context.attach("array_and_hash", proc{{a: 1, b: [1, {a: 1}]}})
40
+ puts context.eval 'array_and_hash()'
41
+ # => {"a" => 1, "b" => [1, {"a" => 1}]}
42
+ ```
43
+
37
44
  ### GIL free JavaScript execution
38
45
 
39
46
  The Ruby Global interpreter lock is released when scripts are executing
@@ -87,7 +94,7 @@ The `bench` folder contains benchmark.
87
94
 
88
95
  ### Benchmark minification of Discourse application.js (both minified and unminified)
89
96
 
90
- - MiniRacer version 0.1 (unreleased)
97
+ - MiniRacer version 0.1
91
98
  - therubyracer version 0.12.2
92
99
 
93
100
  ```
@@ -173,7 +180,7 @@ Or install it yourself as:
173
180
 
174
181
  ## Contributing
175
182
 
176
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
183
+ Bug reports and pull requests are welcome on GitHub at https://github.com/discourse/mini_racer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
177
184
 
178
185
 
179
186
  ## License
@@ -197,6 +197,12 @@ static VALUE convert_v8_to_ruby(Isolate* isolate, Handle<Value> &value) {
197
197
  static Handle<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
198
198
  EscapableHandleScope scope(isolate);
199
199
 
200
+ Local<Array> array;
201
+ Local<Object> object;
202
+ VALUE hash_as_array;
203
+ VALUE pair;
204
+ int length,i;
205
+
200
206
  switch (TYPE(value)) {
201
207
  case T_FIXNUM:
202
208
  return scope.Escape(Integer::New(isolate, NUM2INT(value)));
@@ -210,6 +216,26 @@ static Handle<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
210
216
  return scope.Escape(True(isolate));
211
217
  case T_FALSE:
212
218
  return scope.Escape(False(isolate));
219
+ case T_ARRAY:
220
+ length = RARRAY_LEN(value);
221
+ array = Array::New(isolate, length);
222
+ for(i=0; i<length; i++) {
223
+ array->Set(i, convert_ruby_to_v8(isolate, rb_ary_entry(value, i)));
224
+ }
225
+ return scope.Escape(array);
226
+ case T_HASH:
227
+ object = Object::New(isolate);
228
+ hash_as_array = rb_funcall(value, rb_intern("to_a"), 0);
229
+ length = RARRAY_LEN(hash_as_array);
230
+ for(i=0; i<length; i++) {
231
+ pair = rb_ary_entry(hash_as_array, i);
232
+ object->Set(convert_ruby_to_v8(isolate, rb_ary_entry(pair, 0)),
233
+ convert_ruby_to_v8(isolate, rb_ary_entry(pair, 1)));
234
+ }
235
+ return scope.Escape(object);
236
+ case T_SYMBOL:
237
+ value = rb_funcall(value, rb_intern("to_s"), 0);
238
+ return scope.Escape(String::NewFromUtf8(isolate, RSTRING_PTR(value), NewStringType::kNormal, (int)RSTRING_LEN(value)).ToLocalChecked());
213
239
  case T_DATA:
214
240
  case T_OBJECT:
215
241
  case T_CLASS:
@@ -217,16 +243,12 @@ static Handle<Value> convert_ruby_to_v8(Isolate* isolate, VALUE value) {
217
243
  case T_MODULE:
218
244
  case T_REGEXP:
219
245
  case T_MATCH:
220
- case T_ARRAY:
221
- case T_HASH:
222
246
  case T_STRUCT:
223
247
  case T_BIGNUM:
224
248
  case T_FILE:
225
- case T_SYMBOL:
226
249
  case T_UNDEF:
227
250
  case T_NODE:
228
251
  default:
229
- // rb_warn("unknown conversion to V8 for: %s", RSTRING_PTR(rb_inspect(value)));
230
252
  return scope.Escape(String::NewFromUtf8(isolate, "Undefined Conversion"));
231
253
  }
232
254
 
@@ -427,27 +449,65 @@ static VALUE rb_external_function_notify_v8(VALUE self) {
427
449
 
428
450
  VALUE parent = rb_iv_get(self, "@parent");
429
451
  VALUE name = rb_iv_get(self, "@name");
452
+ VALUE parent_object = rb_iv_get(self, "@parent_object");
453
+ VALUE parent_object_eval = rb_iv_get(self, "@parent_object_eval");
454
+
455
+ bool parse_error = false;
456
+ bool attach_error = false;
430
457
 
431
458
  Data_Get_Struct(parent, ContextInfo, context_info);
432
459
 
433
- Locker lock(context_info->isolate);
434
- Isolate::Scope isolate_scope(context_info->isolate);
435
- HandleScope handle_scope(context_info->isolate);
460
+ {
461
+ Locker lock(context_info->isolate);
462
+ Isolate::Scope isolate_scope(context_info->isolate);
463
+ HandleScope handle_scope(context_info->isolate);
436
464
 
437
- Local<Context> context = context_info->context->Get(context_info->isolate);
438
- Context::Scope context_scope(context);
465
+ Local<Context> context = context_info->context->Get(context_info->isolate);
466
+ Context::Scope context_scope(context);
467
+
468
+ Local<String> v8_str = String::NewFromUtf8(context_info->isolate, RSTRING_PTR(name),
469
+ NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
439
470
 
440
- Local<String> v8_str = String::NewFromUtf8(context_info->isolate, RSTRING_PTR(name),
441
- NewStringType::kNormal, (int)RSTRING_LEN(name)).ToLocalChecked();
471
+ // copy self so we can access from v8 external
472
+ VALUE* self_copy;
473
+ Data_Get_Struct(self, VALUE, self_copy);
474
+ *self_copy = self;
442
475
 
476
+ Local<Value> external = External::New(context_info->isolate, self_copy);
443
477
 
444
- // copy self so we can access from v8 external
445
- VALUE* self_copy;
446
- Data_Get_Struct(self, VALUE, self_copy);
447
- *self_copy = self;
478
+ if (parent_object == Qnil) {
479
+ context->Global()->Set(v8_str, FunctionTemplate::New(context_info->isolate, ruby_callback, external)->GetFunction());
480
+ } else {
481
+
482
+ Local<String> eval = String::NewFromUtf8(context_info->isolate, RSTRING_PTR(parent_object_eval),
483
+ NewStringType::kNormal, (int)RSTRING_LEN(parent_object_eval)).ToLocalChecked();
448
484
 
449
- Local<Value> external = External::New(context_info->isolate, self_copy);
450
- context->Global()->Set(v8_str, FunctionTemplate::New(context_info->isolate, ruby_callback, external)->GetFunction());
485
+ MaybeLocal<Script> parsed_script = Script::Compile(context, eval);
486
+ if (parsed_script.IsEmpty()) {
487
+ parse_error = true;
488
+ } else {
489
+ MaybeLocal<Value> maybe_value = parsed_script.ToLocalChecked()->Run(context);
490
+ attach_error = true;
491
+
492
+ if (!maybe_value.IsEmpty()) {
493
+ Local<Value> value = maybe_value.ToLocalChecked();
494
+ if (value->IsObject()){
495
+ value.As<Object>()->Set(v8_str, FunctionTemplate::New(context_info->isolate, ruby_callback, external)->GetFunction());
496
+ attach_error = false;
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+
503
+ // always raise out of V8 context
504
+ if (parse_error) {
505
+ rb_raise(rb_eParseError, "Invalid object %s", RSTRING_PTR(parent_object));
506
+ }
507
+
508
+ if (attach_error) {
509
+ rb_raise(rb_eParseError, "Was expecting %s to be an object", RSTRING_PTR(parent_object));
510
+ }
451
511
 
452
512
  return Qnil;
453
513
  }
data/lib/mini_racer.rb CHANGED
@@ -46,9 +46,33 @@ module MiniRacer
46
46
 
47
47
  class ExternalFunction
48
48
  def initialize(name, callback, parent)
49
- @name = name
49
+ unless String === name
50
+ raise ArgumentError, "parent_object must be a String"
51
+ end
52
+ parent_object, _ , @name = name.rpartition(".")
50
53
  @callback = callback
51
54
  @parent = parent
55
+ @parent_object_eval = nil
56
+ @parent_object = nil
57
+
58
+ unless parent_object.empty?
59
+ @parent_object = parent_object
60
+
61
+ @parent_object_eval = ""
62
+ prev = ""
63
+ first = true
64
+ parent_object.split(".").each do |obj|
65
+ prev << obj
66
+ if first
67
+ @parent_object_eval << "if (typeof #{prev} === 'undefined') { #{prev} = {} };\n"
68
+ else
69
+ @parent_object_eval << "#{prev} = #{prev} || {};\n"
70
+ end
71
+ prev << "."
72
+ first = false
73
+ end
74
+ @parent_object_eval << "#{parent_object};"
75
+ end
52
76
  notify_v8
53
77
  end
54
78
  end
@@ -62,7 +86,11 @@ module MiniRacer
62
86
  if options
63
87
  @timeout = options[:timeout]
64
88
  end
89
+ end
65
90
 
91
+ def load(filename)
92
+ # TODO do this native cause no need to allocate VALUE here
93
+ eval(File.read(filename))
66
94
  end
67
95
 
68
96
  def eval(str)
@@ -75,7 +103,7 @@ module MiniRacer
75
103
  def attach(name, callback)
76
104
  @lock.synchronize do
77
105
  external = ExternalFunction.new(name, callback, self)
78
- @functions[name.to_s] = external
106
+ @functions["#{name}"] = external
79
107
  end
80
108
  end
81
109
 
@@ -1,3 +1,3 @@
1
1
  module MiniRacer
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.3"
3
3
  end
data/mini_racer.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = %q{Minimal embedded v8 for Ruby}
13
13
  spec.description = %q{Minimal embedded v8 engine for Ruby}
14
- spec.homepage = ""
14
+ spec.homepage = "https://github.com/discourse/mini_racer"
15
15
  spec.license = "MIT"
16
16
 
17
17
 
@@ -30,4 +30,6 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.extensions = ["ext/mini_racer_extension/extconf.rb"]
32
32
 
33
+ spec.required_ruby_version = '>= 2.0'
34
+
33
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_racer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Saffron
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-16 00:00:00.000000000 Z
11
+ date: 2016-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -103,7 +103,7 @@ files:
103
103
  - lib/mini_racer.rb
104
104
  - lib/mini_racer/version.rb
105
105
  - mini_racer.gemspec
106
- homepage: ''
106
+ homepage: https://github.com/discourse/mini_racer
107
107
  licenses:
108
108
  - MIT
109
109
  metadata: {}
@@ -116,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
116
116
  requirements:
117
117
  - - ">="
118
118
  - !ruby/object:Gem::Version
119
- version: '0'
119
+ version: '2.0'
120
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="