h8 0.5.2 → 0.5.4
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 +4 -4
- data/ext/h8/h8.cpp +2 -2
- data/ext/h8/ruby_gate.cpp +54 -1
- data/ext/h8/ruby_gate.h +8 -0
- data/lib/h8/context.rb +51 -1
- data/lib/h8/value.rb +4 -0
- data/lib/h8/version.rb +1 -1
- data/lib/scripts/globals.coffee +3 -0
- data/spec/ruby_gate_spec.rb +50 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 866cc21525fd34d68526f69d2439e6c92b851eb7
|
4
|
+
data.tar.gz: 15517b88b2bf5cc132e57f6313b923f03c71ae14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e4bf6c5081483747ab4bf13bc4869701d6bb96831bec5b7e7419ba340fce4be8d038ae76f7b6c4e5da9152be8a48aa54f4600a6dad94495e74f3f65a430bc0a
|
7
|
+
data.tar.gz: bedab9933c97710834681624d5d97ffd571d986e61f4e8ad7cd3f41cd21bc91e99b05f8a364385949a9b4de40ab4464d864318d67796f8d2af54c2b77ab6b661
|
data/ext/h8/h8.cpp
CHANGED
@@ -64,8 +64,8 @@ void h8::JsTimeoutError::raise() const {
|
|
64
64
|
void h8::H8::SetupGateTemplate(const Local<ObjectTemplate>& templ) {
|
65
65
|
templ->SetInternalFieldCount(2);
|
66
66
|
templ->SetCallAsFunctionHandler(&RubyGate::ObjectCallback);
|
67
|
-
templ->
|
68
|
-
templ->
|
67
|
+
templ->SetIndexedPropertyHandler(RubyGate::indexGet, RubyGate::indexSet,0,0,RubyGate::indexEnumerate);
|
68
|
+
templ->SetNamedPropertyHandler(RubyGate::mapGet, RubyGate::mapSet, RubyGate::mapQuery, RubyGate::mapDelete, RubyGate::mapEnumerate);
|
69
69
|
// templ->SetAccessor(String::NewFromUtf8(isolate, "prototype"),
|
70
70
|
// prototype_cb);
|
71
71
|
}
|
data/ext/h8/ruby_gate.cpp
CHANGED
@@ -76,7 +76,7 @@ h8::RubyGate::RubyGate(H8* _context, Handle<Object> instance, VALUE object) :
|
|
76
76
|
void h8::RubyGate::mapGet(Local<String> name,
|
77
77
|
const PropertyCallbackInfo<Value> &info) {
|
78
78
|
v8::String::Utf8Value val(name);
|
79
|
-
if(
|
79
|
+
if (strcmp(*val, "prototype") == 0) {
|
80
80
|
info.GetReturnValue().Set(info.This()->GetPrototype());
|
81
81
|
return;
|
82
82
|
}
|
@@ -105,6 +105,19 @@ void h8::RubyGate::mapDelete(Local<String> name,
|
|
105
105
|
rg->deleteProperty(name, info);
|
106
106
|
}
|
107
107
|
|
108
|
+
void h8::RubyGate::mapQuery(Local<String> name,
|
109
|
+
const PropertyCallbackInfo<Integer>& info) {
|
110
|
+
RubyGate *rg = RubyGate::unwrap(info.This());
|
111
|
+
assert(rg != 0);
|
112
|
+
rg->queryProperty(name, info);
|
113
|
+
}
|
114
|
+
|
115
|
+
void h8::RubyGate::mapEnumerate(const PropertyCallbackInfo<Array> &info) {
|
116
|
+
RubyGate *rg = RubyGate::unwrap(info.This());
|
117
|
+
assert(rg != 0);
|
118
|
+
rg->enumerateProperties(info);
|
119
|
+
}
|
120
|
+
|
108
121
|
void h8::RubyGate::indexGet(uint32_t index,
|
109
122
|
const PropertyCallbackInfo<Value> &info) {
|
110
123
|
RubyGate *rg = RubyGate::unwrap(info.This());
|
@@ -119,6 +132,12 @@ void h8::RubyGate::indexSet(uint32_t index, Local<Value> value,
|
|
119
132
|
rg->setIndex(index, value, info);
|
120
133
|
}
|
121
134
|
|
135
|
+
void h8::RubyGate::indexEnumerate(const PropertyCallbackInfo<Array>& info) {
|
136
|
+
RubyGate *rg = RubyGate::unwrap(info.This());
|
137
|
+
assert(rg != 0);
|
138
|
+
rg->enumerateProperties(info);
|
139
|
+
}
|
140
|
+
|
122
141
|
void h8::RubyGate::ObjectCallback(
|
123
142
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
124
143
|
v8::HandleScope scope(args.GetIsolate());
|
@@ -250,6 +269,40 @@ void h8::RubyGate::deleteProperty(Local<String> name,
|
|
250
269
|
});
|
251
270
|
}
|
252
271
|
|
272
|
+
void h8::RubyGate::enumerateProperties(
|
273
|
+
const PropertyCallbackInfo<Array>& info) {
|
274
|
+
with_gvl(this,
|
275
|
+
[&] {
|
276
|
+
VALUE rb_args = rb_ary_new2(2);
|
277
|
+
rb_ary_push(rb_args, ruby_object);
|
278
|
+
rb_ary_push(rb_args, rb_str_new2("__js_enumerate"));
|
279
|
+
rescued_call(rb_args, secure_call, [&] (VALUE res) {
|
280
|
+
int len = (int) RARRAY_LEN(res);
|
281
|
+
v8::Handle<Array> a = v8::Array::New(context->getIsolate(), len);
|
282
|
+
for(int i=0; i<len; i++) {
|
283
|
+
a->Set(i, context->to_js(rb_ary_entry(res, i)));
|
284
|
+
}
|
285
|
+
info.GetReturnValue().Set(a);
|
286
|
+
});
|
287
|
+
});
|
288
|
+
}
|
289
|
+
|
290
|
+
void h8::RubyGate::queryProperty(Local<String> name,
|
291
|
+
const PropertyCallbackInfo<Integer>& info) {
|
292
|
+
with_gvl(this,
|
293
|
+
[&] {
|
294
|
+
VALUE rb_args = rb_ary_new2(2);
|
295
|
+
rb_ary_push(rb_args, context->to_ruby(name));
|
296
|
+
rb_ary_push(rb_args, ruby_object);
|
297
|
+
rb_ary_push(rb_args, rb_str_new2("!__js_has_property"));
|
298
|
+
rescued_call(rb_args, secure_call, [&] (VALUE res) {
|
299
|
+
if( res != Qnil && res != Qfalse) {
|
300
|
+
info.GetReturnValue().Set(Integer::New(context->getIsolate(), v8::None));
|
301
|
+
}
|
302
|
+
});
|
303
|
+
});
|
304
|
+
}
|
305
|
+
|
253
306
|
void h8::RubyGate::getIndex(uint32_t index,
|
254
307
|
const PropertyCallbackInfo<Value> &info) {
|
255
308
|
with_gvl(this, [&] {
|
data/ext/h8/ruby_gate.h
CHANGED
@@ -117,10 +117,14 @@ protected:
|
|
117
117
|
const PropertyCallbackInfo<Value> &info);
|
118
118
|
void setProperty(Local<String> name, Local<Value> value,
|
119
119
|
const PropertyCallbackInfo<Value> &info);
|
120
|
+
void queryProperty(Local<String> name,
|
121
|
+
const PropertyCallbackInfo<Integer> &info);
|
120
122
|
|
121
123
|
void deleteProperty(Local<String> name,
|
122
124
|
const PropertyCallbackInfo<Boolean> &info);
|
123
125
|
|
126
|
+
void enumerateProperties(const PropertyCallbackInfo<Array>& info);
|
127
|
+
|
124
128
|
void getIndex(uint32_t index, const PropertyCallbackInfo<Value> &info);
|
125
129
|
void setIndex(uint32_t index, Local<Value> value,
|
126
130
|
const PropertyCallbackInfo<Value> &info);
|
@@ -138,13 +142,17 @@ private:
|
|
138
142
|
const PropertyCallbackInfo<Value> &info);
|
139
143
|
static void mapSet(Local<String> name, Local<Value> value,
|
140
144
|
const PropertyCallbackInfo<Value> &info);
|
145
|
+
static void mapQuery(Local<String> name,
|
146
|
+
const PropertyCallbackInfo<Integer> &info);
|
141
147
|
static void mapDelete(Local<String> name,
|
142
148
|
const PropertyCallbackInfo<Boolean> &info);
|
149
|
+
static void mapEnumerate(const PropertyCallbackInfo<Array>& info);
|
143
150
|
|
144
151
|
static void indexGet(uint32_t index,
|
145
152
|
const PropertyCallbackInfo<Value> &info);
|
146
153
|
static void indexSet(uint32_t index, Local<Value> value,
|
147
154
|
const PropertyCallbackInfo<Value> &info);
|
155
|
+
static void indexEnumerate(const PropertyCallbackInfo<Array>& info);
|
148
156
|
|
149
157
|
void throw_js();
|
150
158
|
|
data/lib/h8/context.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'h8'
|
3
3
|
require 'json'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'hashie'
|
4
6
|
|
5
7
|
class Array
|
6
8
|
def _select_js callable
|
@@ -12,6 +14,12 @@ class Array
|
|
12
14
|
def indexOf item
|
13
15
|
index(item) || -1
|
14
16
|
end
|
17
|
+
|
18
|
+
def splice(start, len, *replace)
|
19
|
+
ret = self[start, len]
|
20
|
+
self[start, len] = replace
|
21
|
+
ret
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
25
|
class String
|
@@ -20,10 +28,46 @@ class String
|
|
20
28
|
end
|
21
29
|
end
|
22
30
|
|
31
|
+
class OpenStruct
|
32
|
+
|
33
|
+
def __to_json
|
34
|
+
JSON.unparse to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
def __js_enumerate
|
38
|
+
to_h.keys.map(&:to_s)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def Hashie::Mash
|
44
|
+
def __to_json
|
45
|
+
JSON.unparse self
|
46
|
+
end
|
47
|
+
|
48
|
+
def __js_enumerate
|
49
|
+
to_h.keys.map(&:to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
23
54
|
class Object
|
24
55
|
def __to_json
|
25
56
|
JSON.unparse self
|
26
57
|
end
|
58
|
+
|
59
|
+
def __js_has_property name
|
60
|
+
__js_enumerate.include?(name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def __js_enumerate
|
64
|
+
if respond_to?(:keys)
|
65
|
+
self.keys.map(&:to_s)
|
66
|
+
else
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
27
71
|
end
|
28
72
|
|
29
73
|
module H8
|
@@ -102,12 +146,18 @@ module H8
|
|
102
146
|
if instance.is_a?(Array)
|
103
147
|
method == 'select' and method = '_select_js'
|
104
148
|
end
|
149
|
+
immediate_call = if method[0] == '!'
|
150
|
+
method = method[1..-1]
|
151
|
+
true
|
152
|
+
else
|
153
|
+
false
|
154
|
+
end
|
105
155
|
method = method.to_sym
|
106
156
|
begin
|
107
157
|
m = instance.public_method(method)
|
108
158
|
owner = m.owner
|
109
159
|
if can_access?(owner)
|
110
|
-
return m.call(*args) if method[0] == '[' || method[-1] == '='
|
160
|
+
return m.call(*args) if method[0] == '[' || method[-1] == '=' || immediate_call
|
111
161
|
if m.arity != 0
|
112
162
|
return ProcGate.new( -> (*args) { m.call *args } )
|
113
163
|
else
|
data/lib/h8/value.rb
CHANGED
data/lib/h8/version.rb
CHANGED
data/lib/scripts/globals.coffee
CHANGED
data/spec/ruby_gate_spec.rb
CHANGED
@@ -394,16 +394,64 @@ describe 'ruby gate' do
|
|
394
394
|
end
|
395
395
|
end
|
396
396
|
|
397
|
+
it 'should enumerate hashes' do
|
398
|
+
begin
|
399
|
+
cxt = H8::Context.new
|
400
|
+
src = cxt[:h] = { "the" => "test", "value" => 121 }
|
401
|
+
res = cxt.coffee <<-End
|
402
|
+
res = {}
|
403
|
+
for own k,v of h
|
404
|
+
res[k] = v
|
405
|
+
return res
|
406
|
+
End
|
407
|
+
res.should == src
|
408
|
+
src1 = cxt[:h] = OpenStruct.new
|
409
|
+
src1.the = "test"
|
410
|
+
src1.value = 121
|
411
|
+
res = cxt.coffee <<-End
|
412
|
+
res = {}
|
413
|
+
for own k,v of h
|
414
|
+
res[k] = v
|
415
|
+
return res
|
416
|
+
End
|
417
|
+
res.should == src
|
418
|
+
cxt = H8::Context.new
|
419
|
+
src = cxt[:h] = Hashie::Mash.new "the" => "test", "value" => 121
|
420
|
+
res = cxt.coffee <<-End
|
421
|
+
res = {}
|
422
|
+
for own k,v of h
|
423
|
+
res[k] = v
|
424
|
+
return res
|
425
|
+
End
|
426
|
+
res.should == src
|
427
|
+
rescue H8::NestedError => e
|
428
|
+
puts e.ruby_error.backtrace.join("\n")
|
429
|
+
raise
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
|
397
434
|
it 'should process to_json' do
|
398
435
|
begin
|
399
436
|
cxt = H8::Context.new
|
400
|
-
src = cxt[:h] = { 'hello' => { 'my' => 'world', 'arr' => [1,2,'tre'] } }
|
437
|
+
src = cxt[:h] = { 'hello' => { 'my' => 'world', 'arr' => [1, 2, 'tre'] } }
|
401
438
|
JSON[cxt.eval("JSON.stringify(h)")].should == src
|
439
|
+
src = cxt[:h] = [-1, -2, { 'hello' => { 'my' => 'world', 'arr' => [1, 2, 'tre'] } }]
|
440
|
+
JSON[cxt.eval("JSON.stringify(h)")].should == src
|
441
|
+
|
442
|
+
src = cxt[:h] = { 'one' => cxt.eval("[ 'hello', { wor: 'ld'} ]") }
|
443
|
+
JSON[cxt.eval("JSON.stringify(h)")].should == src
|
444
|
+
|
445
|
+
src = cxt[:h] = Hashie::Mash.new
|
446
|
+
res = cxt.coffee <<-End
|
447
|
+
h.arr = (c*10 for c in [-1, +1]);
|
448
|
+
return JSON.stringify(h)
|
449
|
+
End
|
450
|
+
res.should == "{\"arr\":[-10,10]}"
|
402
451
|
rescue H8::NestedError => e
|
403
452
|
puts e.ruby_error.backtrace.join("\n")
|
404
453
|
raise
|
405
454
|
end
|
406
|
-
|
407
455
|
end
|
408
456
|
|
409
457
|
it 'should pass varargs' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: h8
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sergeych
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|