mini_racer 0.1.0 → 0.1.3

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 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
  - - ">="