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 +4 -4
- data/CHANGELOG +17 -2
- data/README.md +11 -4
- data/ext/mini_racer_extension/mini_racer_extension.cc +77 -17
- data/lib/mini_racer.rb +30 -2
- data/lib/mini_racer/version.rb +1 -1
- data/mini_racer.gemspec +3 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef7d560456c68712a83c6167b76c27fa2f145da2
|
4
|
+
data.tar.gz: f299b830d1df20a115fdc8f63aea4a7c9f0328b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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
|
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/
|
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
|
-
|
434
|
-
|
435
|
-
|
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
|
-
|
438
|
-
|
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
|
-
|
441
|
-
|
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
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
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
|
-
|
450
|
-
|
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
|
-
|
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
|
106
|
+
@functions["#{name}"] = external
|
79
107
|
end
|
80
108
|
end
|
81
109
|
|
data/lib/mini_racer/version.rb
CHANGED
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.
|
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-
|
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
|
- - ">="
|