h8 0.3.0 → 0.4.0
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 +63 -2
- data/ext/h8/h8.h +8 -14
- data/ext/h8/main.cpp +9 -0
- data/ext/h8/ruby_gate.cpp +65 -24
- data/ext/h8/ruby_gate.h +5 -2
- data/lib/h8/context.rb +3 -9
- data/lib/h8/version.rb +1 -1
- data/spec/ruby_gate_spec.rb +35 -10
- 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: 62539324e412e959064c165f17099c2f688eca44
|
4
|
+
data.tar.gz: bfcbcf2ed6018b7a6704f5dcf70a57bcb9482b66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bee24241453a7b41afda2cef2ae636abf2fb4290697d5c9bb1e11f8092e07a0da59387ca6f41a3f8c48df4b349c64bd27a768348714c0b0191c1cd75a6c93ffa
|
7
|
+
data.tar.gz: 0f7ced45565b634b5e7f3a67819ec390fa6960f14d5004c9a298891be7d6d53f91cda8831d47f5902bddf61ee5205ca05a30709156bf89ef229d2236bfdc1ea2
|
data/ext/h8/h8.cpp
CHANGED
@@ -47,6 +47,39 @@ void h8::JsTimeoutError::raise() const {
|
|
47
47
|
rb_raise(js_timeout_exception, "timeout expired");
|
48
48
|
}
|
49
49
|
|
50
|
+
h8::H8::H8()
|
51
|
+
: self(Qnil)
|
52
|
+
{
|
53
|
+
isolate = Isolate::New();
|
54
|
+
Locker l(isolate);
|
55
|
+
Isolate::Scope isolate_scope(isolate);
|
56
|
+
HandleScope handle_scope(isolate);
|
57
|
+
isolate->SetCaptureStackTraceForUncaughtExceptions(true);
|
58
|
+
|
59
|
+
isolate->SetData(0, this);
|
60
|
+
|
61
|
+
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(
|
62
|
+
isolate);
|
63
|
+
|
64
|
+
// Set up RubyGate in JS context
|
65
|
+
Local<FunctionTemplate> ft = v8::FunctionTemplate::New(isolate,RubyGate::GateConstructor);
|
66
|
+
ft->SetClassName(js("RubyGate"));
|
67
|
+
Local<ObjectTemplate> templ = ft->InstanceTemplate();
|
68
|
+
|
69
|
+
templ->SetInternalFieldCount(2);
|
70
|
+
templ->SetCallAsFunctionHandler(&RubyGate::ObjectCallback);
|
71
|
+
templ->SetNamedPropertyHandler(RubyGate::mapGet, RubyGate::mapSet);
|
72
|
+
templ->SetIndexedPropertyHandler(RubyGate::indexGet, RubyGate::indexSet);
|
73
|
+
|
74
|
+
global->Set(isolate, "RubyGate", ft);
|
75
|
+
|
76
|
+
v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL,
|
77
|
+
global);
|
78
|
+
persistent_context.Reset(isolate, context);
|
79
|
+
gate_function.Reset(isolate,ft);
|
80
|
+
}
|
81
|
+
|
82
|
+
|
50
83
|
Local<Value> h8::H8::gateObject(VALUE ruby_value) {
|
51
84
|
if ( Qtrue == rb_funcall(ruby_value, id_is_a, 1, value_class)) {
|
52
85
|
JsGate *gate;
|
@@ -59,8 +92,35 @@ Local<Value> h8::H8::gateObject(VALUE ruby_value) {
|
|
59
92
|
if( ruby_value == Rundefined )
|
60
93
|
return v8::Undefined(isolate);
|
61
94
|
// Generic Ruby object
|
62
|
-
RubyGate *gate = new RubyGate(this, ruby_value);
|
63
|
-
return gate->handle(isolate);
|
95
|
+
// RubyGate *gate = new RubyGate(this, ruby_value);
|
96
|
+
// return gate->handle(isolate);
|
97
|
+
// Generic ruby object - new logic
|
98
|
+
assert( sizeof(VALUE) <= sizeof(void*) );
|
99
|
+
Local<Value> wrapped_ruby_value = External::New(isolate, (void*)ruby_value);
|
100
|
+
return getGateFunction()->GetFunction()->CallAsConstructor(1, &wrapped_ruby_value);
|
101
|
+
}
|
102
|
+
|
103
|
+
void h8::H8::gate_class(VALUE name,VALUE callable) {
|
104
|
+
Scope scope(this);
|
105
|
+
|
106
|
+
Local<Object> global = getContext()->Global();
|
107
|
+
|
108
|
+
Local<FunctionTemplate> ft = v8::FunctionTemplate::New(isolate,
|
109
|
+
RubyGate::ClassGateConstructor,
|
110
|
+
to_js(callable)
|
111
|
+
);
|
112
|
+
Local<String> class_name = js(name);
|
113
|
+
ft->SetClassName(class_name);
|
114
|
+
ft->Inherit(getGateFunction());
|
115
|
+
|
116
|
+
Local<ObjectTemplate> templ = ft->InstanceTemplate();
|
117
|
+
|
118
|
+
templ->SetInternalFieldCount(2);
|
119
|
+
templ->SetCallAsFunctionHandler(&RubyGate::ObjectCallback);
|
120
|
+
templ->SetNamedPropertyHandler(RubyGate::mapGet, RubyGate::mapSet);
|
121
|
+
templ->SetIndexedPropertyHandler(RubyGate::indexGet, RubyGate::indexSet);
|
122
|
+
|
123
|
+
global->Set(class_name, ft->GetFunction());
|
64
124
|
}
|
65
125
|
|
66
126
|
void h8::H8::ruby_mark_gc() const {
|
@@ -152,6 +212,7 @@ h8::H8::~H8() {
|
|
152
212
|
resources.peek_first<AllocatedResource>()->free();
|
153
213
|
}
|
154
214
|
persistent_context.Reset();
|
215
|
+
gate_function.Reset();
|
155
216
|
}
|
156
217
|
isolate->Dispose();
|
157
218
|
}
|
data/ext/h8/h8.h
CHANGED
@@ -103,20 +103,7 @@ public:
|
|
103
103
|
|
104
104
|
static void init();
|
105
105
|
|
106
|
-
H8()
|
107
|
-
self(Qnil) {
|
108
|
-
isolate = Isolate::New();
|
109
|
-
Locker l(isolate);
|
110
|
-
Isolate::Scope isolate_scope(isolate);
|
111
|
-
HandleScope handle_scope(isolate);
|
112
|
-
isolate->SetCaptureStackTraceForUncaughtExceptions(true);
|
113
|
-
|
114
|
-
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(
|
115
|
-
isolate);
|
116
|
-
v8::Handle<v8::Context> context = v8::Context::New(isolate, NULL,
|
117
|
-
global);
|
118
|
-
persistent_context.Reset(isolate, context);
|
119
|
-
}
|
106
|
+
H8();
|
120
107
|
|
121
108
|
/**
|
122
109
|
* Evaluate javascript.
|
@@ -139,6 +126,10 @@ public:
|
|
139
126
|
return Local<Context>::New(isolate, persistent_context);
|
140
127
|
}
|
141
128
|
|
129
|
+
Handle<FunctionTemplate> getGateFunction() {
|
130
|
+
return Local<FunctionTemplate>::New(isolate, gate_function);
|
131
|
+
}
|
132
|
+
|
142
133
|
bool isError() const {
|
143
134
|
return is_error;
|
144
135
|
}
|
@@ -147,6 +138,8 @@ public:
|
|
147
138
|
return isolate;
|
148
139
|
}
|
149
140
|
|
141
|
+
void gate_class(VALUE name, VALUE proc);
|
142
|
+
|
150
143
|
VALUE to_ruby(Handle<Value> value);
|
151
144
|
|
152
145
|
v8::Local<v8::String> js(VALUE val) const {
|
@@ -236,6 +229,7 @@ private:
|
|
236
229
|
VALUE self;
|
237
230
|
|
238
231
|
Persistent<Context> persistent_context;
|
232
|
+
Persistent<FunctionTemplate> gate_function;
|
239
233
|
|
240
234
|
bool is_error = false;
|
241
235
|
bool gvl_released = false;
|
data/ext/h8/main.cpp
CHANGED
@@ -148,6 +148,13 @@ static VALUE context_set_var(VALUE self, VALUE name, VALUE value) {
|
|
148
148
|
});
|
149
149
|
}
|
150
150
|
|
151
|
+
static VALUE context_gate_class(VALUE self, VALUE name, VALUE lambda) {
|
152
|
+
return protect_ruby([&] {
|
153
|
+
rc(self)->gate_class(name, lambda);
|
154
|
+
return Qnil;
|
155
|
+
});
|
156
|
+
}
|
157
|
+
|
151
158
|
static VALUE context_force_gc(VALUE self) {
|
152
159
|
rc(self)->gc();
|
153
160
|
return Qnil;
|
@@ -191,6 +198,8 @@ void Init_h8(void) {
|
|
191
198
|
rb_define_method(context_class, "_eval", (ruby_method) context_eval, 3);
|
192
199
|
rb_define_method(context_class, "_set_var", (ruby_method) context_set_var,
|
193
200
|
2);
|
201
|
+
rb_define_method(context_class, "_gate_class", (ruby_method) context_gate_class,
|
202
|
+
2);
|
194
203
|
rb_define_method(context_class, "javascript_gc",
|
195
204
|
(ruby_method) context_force_gc, 0);
|
196
205
|
|
data/ext/h8/ruby_gate.cpp
CHANGED
@@ -13,8 +13,7 @@ static void* unblock_caller(void *param) {
|
|
13
13
|
return NULL;
|
14
14
|
}
|
15
15
|
|
16
|
-
static void with_gvl(
|
17
|
-
H8 *h8 = gate->getH8();
|
16
|
+
static void with_gvl(H8 *h8, const std::function<void(void)> &block) {
|
18
17
|
if (h8->isGvlReleased()) {
|
19
18
|
h8->setGvlReleased(false);
|
20
19
|
rb_thread_call_with_gvl(unblock_caller, (void*) &block);
|
@@ -23,22 +22,65 @@ static void with_gvl(RubyGate *gate, const std::function<void(void)> &block) {
|
|
23
22
|
block();
|
24
23
|
}
|
25
24
|
|
26
|
-
|
25
|
+
static void with_gvl(RubyGate *gate, const std::function<void(void)> &block) {
|
26
|
+
with_gvl(gate->getH8(), block);
|
27
|
+
}
|
28
|
+
|
29
|
+
void h8::RubyGate::ClassGateConstructor(
|
30
|
+
const v8::FunctionCallbackInfo<Value>& args) {
|
31
|
+
Isolate *isolate = args.GetIsolate();
|
32
|
+
H8* h8 = (H8*) isolate->GetData(0);
|
33
|
+
assert(!args.Data().IsEmpty());
|
34
|
+
|
35
|
+
RubyGate *lambda = RubyGate::unwrap(args.Data().As<Object>());
|
36
|
+
assert(lambda != 0);
|
37
|
+
|
38
|
+
with_gvl(h8, [&] {
|
39
|
+
VALUE rb_args = ruby_args(h8, args, 1);
|
40
|
+
rb_ary_push(rb_args, lambda->ruby_object);
|
41
|
+
// Object creating ruby code can raise exceptions:
|
42
|
+
lambda->rescued_call(
|
43
|
+
rb_args,
|
44
|
+
call,
|
45
|
+
[&] (VALUE res) {
|
46
|
+
new RubyGate(h8, args.This(), res);
|
47
|
+
});
|
48
|
+
});
|
49
|
+
args.GetReturnValue().Set(args.This());
|
50
|
+
}
|
51
|
+
|
52
|
+
void h8::RubyGate::GateConstructor(
|
53
|
+
const v8::FunctionCallbackInfo<Value>& args) {
|
54
|
+
Isolate *isolate = args.GetIsolate();
|
55
|
+
H8* h8 = (H8*) isolate->GetData(0);
|
56
|
+
assert(args.Length() == 1);
|
57
|
+
Local<Value> val = args[0];
|
58
|
+
VALUE ruby_object = Qnil;
|
59
|
+
|
60
|
+
if (val->IsExternal())
|
61
|
+
ruby_object = (VALUE) val.As<External>()->Value(); // External::Cast(*val)->Value();
|
62
|
+
else {
|
63
|
+
assert(val->IsObject());
|
64
|
+
puts("val is object");
|
65
|
+
RubyGate *rg = RubyGate::unwrap(val.As<Object>());
|
66
|
+
puts("Hurray - unwrap");
|
67
|
+
assert(rg != 0);
|
68
|
+
puts("Hurray - not 0");
|
69
|
+
ruby_object = rg->ruby_object;
|
70
|
+
char* ss = StringValueCStr(ruby_object);
|
71
|
+
rb_warn("Object passed %s\n", ss);
|
72
|
+
}
|
73
|
+
|
74
|
+
new RubyGate(h8, args.This(), ruby_object);
|
75
|
+
args.GetReturnValue().Set(args.This());
|
76
|
+
}
|
77
|
+
|
78
|
+
h8::RubyGate::RubyGate(H8* _context, Handle<Object> instance, VALUE object) :
|
27
79
|
context(_context), ruby_object(object), next(0), prev(0) {
|
28
80
|
v8::HandleScope scope(context->getIsolate());
|
29
|
-
// printf("Ruby object gate constructor\n");
|
30
81
|
context->add_resource(this);
|
31
|
-
|
32
|
-
|
33
|
-
templ->SetInternalFieldCount(2);
|
34
|
-
templ->SetCallAsFunctionHandler(&ObjectCallback);
|
35
|
-
|
36
|
-
templ->SetNamedPropertyHandler(RubyGate::mapGet, RubyGate::mapSet);
|
37
|
-
templ->SetIndexedPropertyHandler(RubyGate::indexGet, RubyGate::indexSet);
|
38
|
-
|
39
|
-
v8::Handle<v8::Object> handle = templ->NewInstance();
|
40
|
-
handle->SetAlignedPointerInInternalField(1, RUBYGATE_ID);
|
41
|
-
Wrap(handle);
|
82
|
+
instance->SetAlignedPointerInInternalField(1, RUBYGATE_ID);
|
83
|
+
Wrap(instance);
|
42
84
|
}
|
43
85
|
|
44
86
|
void h8::RubyGate::mapGet(Local<String> name,
|
@@ -118,26 +160,25 @@ void h8::RubyGate::rescued_call(VALUE rb_args, VALUE (*call)(VALUE),
|
|
118
160
|
// exceptions...
|
119
161
|
try {
|
120
162
|
block(res);
|
121
|
-
}
|
122
|
-
catch(JsError& e) {
|
163
|
+
} catch (JsError& e) {
|
123
164
|
Local<v8::Object> error = v8::Exception::Error(
|
124
165
|
context->js(e.what())).As<v8::Object>();
|
125
166
|
context->getIsolate()->ThrowException(error);
|
126
|
-
}
|
127
|
-
|
128
|
-
|
129
|
-
|
167
|
+
} catch (...) {
|
168
|
+
Local<v8::Object> error =
|
169
|
+
v8::Exception::Error(
|
170
|
+
context->js("unknown exception (inner bug)")).As<
|
171
|
+
v8::Object>();
|
130
172
|
context->getIsolate()->ThrowException(error);
|
131
173
|
}
|
132
|
-
}
|
133
|
-
else
|
174
|
+
} else
|
134
175
|
throw_js();
|
135
176
|
}
|
136
177
|
|
137
178
|
void h8::RubyGate::doObjectCallback(
|
138
179
|
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
139
180
|
with_gvl(this, [&] {
|
140
|
-
VALUE rb_args = ruby_args(args, 1);
|
181
|
+
VALUE rb_args = ruby_args(context, args, 1);
|
141
182
|
rb_ary_push(rb_args, ruby_object);
|
142
183
|
rescued_call(rb_args, call, [&] (VALUE res) {
|
143
184
|
args.GetReturnValue().Set(context->to_js(res));
|
data/ext/h8/ruby_gate.h
CHANGED
@@ -18,7 +18,7 @@ namespace h8 {
|
|
18
18
|
*/
|
19
19
|
class RubyGate: public ObjectWrap, public AllocatedResource {
|
20
20
|
public:
|
21
|
-
RubyGate(H8* _context, VALUE object);
|
21
|
+
RubyGate(H8* _context, Handle<Object> instance, VALUE object);
|
22
22
|
|
23
23
|
/**
|
24
24
|
* Check the handle and unwrap the RubyGate if it is wrapped
|
@@ -77,7 +77,7 @@ protected:
|
|
77
77
|
* extra slots in array if need
|
78
78
|
*/
|
79
79
|
template<class T>
|
80
|
-
VALUE ruby_args(const T& args, unsigned extras = 0) {
|
80
|
+
static VALUE ruby_args(H8* context,const T& args, unsigned extras = 0) {
|
81
81
|
unsigned n = args.Length();
|
82
82
|
VALUE rb_args = rb_ary_new2(n + extras);
|
83
83
|
for (unsigned i = 0; i < n; i++)
|
@@ -110,6 +110,9 @@ protected:
|
|
110
110
|
void getIndex(uint32_t index, const PropertyCallbackInfo<Value> &info);
|
111
111
|
void setIndex(uint32_t index, Local<Value> value,
|
112
112
|
const PropertyCallbackInfo<Value> &info);
|
113
|
+
|
114
|
+
static void GateConstructor(const v8::FunctionCallbackInfo<Value>& args);
|
115
|
+
static void ClassGateConstructor(const v8::FunctionCallbackInfo<Value>& args);
|
113
116
|
private:
|
114
117
|
|
115
118
|
void doObjectCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
|
data/lib/h8/context.rb
CHANGED
@@ -7,7 +7,7 @@ module H8
|
|
7
7
|
@idcount = 0
|
8
8
|
set_all **kwargs
|
9
9
|
_set_var '___create_ruby_class', -> (cls, args) {
|
10
|
-
|
10
|
+
_do_create_ruby_class cls, args
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
@@ -102,13 +102,7 @@ module H8
|
|
102
102
|
# in which case constructor function will be created
|
103
103
|
def set_var name, value
|
104
104
|
if value.is_a?(Class)
|
105
|
-
|
106
|
-
_set_var clsid, value
|
107
|
-
eval <<-End
|
108
|
-
function #{name.to_s}() {
|
109
|
-
return ___create_ruby_class(#{clsid}, arguments);
|
110
|
-
}
|
111
|
-
End
|
105
|
+
_gate_class name.to_s, -> (*args) { value.new *args }
|
112
106
|
else
|
113
107
|
_set_var name, value
|
114
108
|
end
|
@@ -116,7 +110,7 @@ module H8
|
|
116
110
|
|
117
111
|
# create class instance passing it arguments stored in javascript 'arguments' object
|
118
112
|
# (so it repacks them first)
|
119
|
-
def
|
113
|
+
def _do_create_ruby_class(klass, arguments)
|
120
114
|
klass.new *H8::arguments_to_a(arguments.to_ruby.values)
|
121
115
|
end
|
122
116
|
end
|
data/lib/h8/version.rb
CHANGED
data/spec/ruby_gate_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe 'ruby gate' do
|
|
5
5
|
|
6
6
|
it 'should gate callables' do
|
7
7
|
cxt = H8::Context.new
|
8
|
-
count
|
8
|
+
count = 0
|
9
9
|
cxt[:fn] = -> (a, b) {
|
10
10
|
count += 1
|
11
11
|
a + b
|
@@ -44,8 +44,8 @@ describe 'ruby gate' do
|
|
44
44
|
cxt[:fn] = -> (a, b) {
|
45
45
|
a + b
|
46
46
|
}
|
47
|
-
res
|
48
|
-
cxt[:fn] = -> (a,b) { a - b }
|
47
|
+
res = cxt.eval("fn(11, 22);") { |cxt|
|
48
|
+
cxt[:fn] = -> (a, b) { a - b }
|
49
49
|
}
|
50
50
|
res.to_i.should == -11
|
51
51
|
end
|
@@ -62,7 +62,7 @@ describe 'ruby gate' do
|
|
62
62
|
|
63
63
|
it 'should convert nil, true, false and undefined' do
|
64
64
|
cxt = H8::Context.new
|
65
|
-
value
|
65
|
+
value = false
|
66
66
|
cxt[:fn] = -> {
|
67
67
|
[nil, true, false, value, H8::Undefined]
|
68
68
|
}
|
@@ -82,9 +82,9 @@ describe 'ruby gate' do
|
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'should convert strings to native string' do
|
85
|
-
cxt
|
85
|
+
cxt = H8::Context.new
|
86
86
|
cxt[:str] = src = "Пример строки"
|
87
|
-
res
|
87
|
+
res = 'ПРИМЕР СТРОКИ'
|
88
88
|
cxt.eval('str.toLocaleUpperCase()').should == res
|
89
89
|
up = cxt.eval('fn = function(t) { return t.toLocaleUpperCase(); }')
|
90
90
|
up.call(src).should == res
|
@@ -151,6 +151,7 @@ describe 'ruby gate' do
|
|
151
151
|
expect(-> {
|
152
152
|
res = cxt.eval <<-End
|
153
153
|
result = fn(11, 22);
|
154
|
+
throw Error("It should not happen");
|
154
155
|
End
|
155
156
|
}).to raise_error(MyException) { |e|
|
156
157
|
e.message.should == 'Shit happens'
|
@@ -174,7 +175,7 @@ describe 'ruby gate' do
|
|
174
175
|
End
|
175
176
|
fail 'did not raise error'
|
176
177
|
rescue H8::JsError => e
|
177
|
-
x
|
178
|
+
x = e.javascript_error
|
178
179
|
e.name.should == 'Error'
|
179
180
|
e.message.should =~ /test/
|
180
181
|
e.javascript_backtrace.should =~ /at bad \(eval\:4\:17\)/
|
@@ -251,6 +252,7 @@ describe 'ruby gate' do
|
|
251
252
|
cxt.eval('foo.priv_method').should == H8::Undefined
|
252
253
|
cxt.eval('foo.test_args').should be_kind_of(Proc)
|
253
254
|
cxt.eval('foo.test_args("hi", "you")').should == 'hi-you'
|
255
|
+
cxt.eval('foo instanceof RubyGate').should == true
|
254
256
|
end
|
255
257
|
|
256
258
|
it 'should set ruby properties' do
|
@@ -342,12 +344,12 @@ describe 'ruby gate' do
|
|
342
344
|
end
|
343
345
|
|
344
346
|
it 'should pass varargs' do
|
345
|
-
cxt
|
347
|
+
cxt = H8::Context.new
|
346
348
|
cxt[:test] = -> (args) {
|
347
349
|
# Sample how to deal with javascript 'arguments' vararg object:
|
348
350
|
H8::arguments_to_a(args).join(',')
|
349
351
|
}
|
350
|
-
res
|
352
|
+
res = cxt.eval <<-End
|
351
353
|
function test2() {
|
352
354
|
return test(arguments);
|
353
355
|
}
|
@@ -356,6 +358,19 @@ describe 'ruby gate' do
|
|
356
358
|
res.should == '1,2,ho'
|
357
359
|
end
|
358
360
|
|
361
|
+
it 'should gate classes through API' do
|
362
|
+
c = H8::Context.new
|
363
|
+
la = -> (*args) {
|
364
|
+
{ 'hello' => 'world'}
|
365
|
+
}
|
366
|
+
c._gate_class 'Tec', la
|
367
|
+
c.eval("var res = new Tec()")
|
368
|
+
c.eval('res').should == { 'hello' => 'world' }
|
369
|
+
c.eval("res['hello']").should == 'world'
|
370
|
+
c.eval('res instanceof Tec').should == true
|
371
|
+
c.eval('res instanceof RubyGate').should == true
|
372
|
+
end
|
373
|
+
|
359
374
|
it 'should gate classes' do
|
360
375
|
class Gated
|
361
376
|
attr :init_args
|
@@ -363,15 +378,25 @@ describe 'ruby gate' do
|
|
363
378
|
def initialize *args
|
364
379
|
@init_args = args
|
365
380
|
end
|
381
|
+
|
382
|
+
def inspect
|
383
|
+
"Gated<#{@init_args.inspect}>"
|
384
|
+
end
|
385
|
+
|
386
|
+
def to_str
|
387
|
+
inspect
|
388
|
+
end
|
366
389
|
end
|
367
390
|
|
368
391
|
cxt = H8::Context.new RClass: Gated
|
369
|
-
c
|
392
|
+
c = cxt.eval 'new RClass()'
|
370
393
|
c.should be_a(Gated)
|
371
394
|
c.init_args.should == []
|
372
395
|
|
373
396
|
c = cxt.eval 'rc = new RClass("hello", "world")'
|
374
397
|
c.should be_a(Gated)
|
398
|
+
cxt.eval('rc instanceof RubyGate').should == true
|
399
|
+
cxt.eval('new RClass() instanceof RClass').should == true
|
375
400
|
c.init_args.should == ['hello', 'world']
|
376
401
|
cxt.eval('rc.init_args').should == ['hello', 'world']
|
377
402
|
end
|
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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sergeych
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|