h8 0.3.0 → 0.4.0
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 +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
|