h8 0.5.2 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|