@@ -9,55 +9,15 @@ namespace rr {
99 class FunctionCallbackInfo : public FunctionCallbackInfoWrapper {
1010 public:
1111
12- inline FunctionCallbackInfo (v8::FunctionCallbackInfo<v8::Value> info, v8::Local<v8::Value> data_ ) :
13- FunctionCallbackInfoWrapper(info), data(data_) {}
12+ inline FunctionCallbackInfo (v8::FunctionCallbackInfo<v8::Value> info) :
13+ FunctionCallbackInfoWrapper(info) {}
1414
1515 inline FunctionCallbackInfo (VALUE self) : FunctionCallbackInfoWrapper(self) {}
1616
1717 inline v8::Local<v8::Value> operator [](int i) {
1818 return this ->container ->content [i];
1919 }
2020
21- /* *
22- * Package up the callback data for this function so that it can
23- * invoke a Ruby callable.
24- *
25- * Each `v8::Function` can have one `v8::Value` associated with it
26- * that is passed to its `v8::FunctionCallback`. To support this
27- * same API from ruby, we take the `Value` passed into the
28- * Function constructor *and* the callback and store them *both*
29- * in a single `v8::Object` which we use for the C++ level
30- * callback data.
31- */
32- static v8::Local<v8::Value> wrapData (v8::Isolate* isolate, VALUE r_callback, VALUE r_data) {
33- v8::Local<v8::Object> holder = v8::Object::New (isolate);
34- v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
35- v8::Local<v8::String> data_key = v8::String::NewFromUtf8 (isolate, " rr::data" );
36- holder->SetHiddenValue (callback_key, External::wrap (isolate, r_callback));
37- holder->SetHiddenValue (data_key, Value (r_data));
38- return holder;
39- }
40-
41- /* *
42- * Call the Ruby code associated with this callback.
43- *
44- * Unpack the Ruby code, and the callback data from the C++
45- * callback data, and then invoke that code.
46- *
47- * Note: This function implements the `v8::FunctionCallback` API.
48- */
49- static void invoke (const v8::FunctionCallbackInfo<v8::Value>& info) {
50- v8::Isolate* isolate = info.GetIsolate ();
51- v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info.Data ());
52- v8::Local<v8::String> data_key = v8::String::NewFromUtf8 (isolate, " rr::data" );
53- v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
54- v8::Local<v8::Value> data (holder->GetHiddenValue (data_key));
55-
56- VALUE code (External::unwrap (holder->GetHiddenValue (callback_key)));
57- Unlocker unlock (info.GetIsolate ());
58- rb_funcall (code, rb_intern (" call" ), 1 , (VALUE)FunctionCallbackInfo (info, data));
59- }
60-
6121 static VALUE Length (VALUE self) {
6222 FunctionCallbackInfo info (self);
6323 Locker lock (info->GetIsolate ());
@@ -90,8 +50,13 @@ namespace rr {
9050
9151 static VALUE Data (VALUE self) {
9252 FunctionCallbackInfo info (self);
53+ Isolate isolate (info->GetIsolate ());
9354 Locker lock (info->GetIsolate ());
94- return Value::handleToRubyObject (info->GetIsolate (), info.data );
55+
56+ v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info->Data ());
57+ v8::Local<v8::String> data_key = v8::String::NewFromUtf8 (isolate, " rr::data" );
58+ v8::Local<v8::Value> data (holder->GetHiddenValue (data_key));
59+ return Value::handleToRubyObject (isolate, data);
9560 }
9661
9762 static VALUE GetIsolate (VALUE self) {
@@ -117,8 +82,61 @@ namespace rr {
11782 defineMethod (" GetReturnValue" , &GetReturnValue).
11883 store (&Class);
11984 }
85+ };
86+
87+ class FunctionCallback {
88+ public:
89+ FunctionCallback (v8::Isolate* i, VALUE c, VALUE d) : isolate(i), code(c), data(d) {}
90+
91+ /* *
92+ * Package up the callback data for this function so that it can
93+ * invoke a Ruby callable.
94+ *
95+ * Each `v8::Function` can have one `v8::Value` associated with it
96+ * that is passed to its `v8::FunctionCallback`. To support this
97+ * same API from ruby, we take the `Value` passed into the
98+ * Function constructor *and* the callback and store them *both*
99+ * in a single `v8::Object` which we use for the C++ level
100+ * callback data.
101+ */
102+ inline operator v8::Local<v8::Value>() {
103+ v8::Local<v8::Object> holder = v8::Object::New (isolate);
104+ v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
105+ v8::Local<v8::String> data_key = v8::String::NewFromUtf8 (isolate, " rr::data" );
106+ holder->SetHiddenValue (callback_key, External::wrap (isolate, code));
107+ holder->SetHiddenValue (data_key, Value (data));
108+ return holder;
109+ }
110+
111+ /* *
112+ * Call the Ruby code associated with this callback.
113+ *
114+ * Unpack the Ruby code, and the callback data from the C++
115+ * callback data, and then invoke that code.
116+ *
117+ * Note: This function implements the `v8::FunctionCallback` API.
118+ */
119+ static void invoke (const v8::FunctionCallbackInfo<v8::Value>& info) {
120+ v8::Isolate* isolate = info.GetIsolate ();
121+ v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info.Data ());
122+ v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
123+
124+ VALUE code (External::unwrap (holder->GetHiddenValue (callback_key)));
125+ Unlocker unlock (info.GetIsolate ());
126+ rb_funcall (code, rb_intern (" call" ), 1 , (VALUE)FunctionCallbackInfo (info));
127+ }
128+
129+ inline operator v8::FunctionCallback () {
130+ if (RTEST (code)) {
131+ return &invoke;
132+ } else {
133+ return 0 ;
134+ }
135+ }
120136
121- v8::Local<v8::Value> data;
137+ v8::Isolate* isolate;
138+ VALUE code;
139+ VALUE data;
122140 };
123141}
124142
0 commit comments