@@ -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,14 @@ 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 (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+
60+ return Value (info->GetIsolate (), data);
9561 }
9662
9763 static VALUE GetIsolate (VALUE self) {
@@ -117,8 +83,61 @@ namespace rr {
11783 defineMethod (" GetReturnValue" , &GetReturnValue).
11884 store (&Class);
11985 }
86+ };
87+
88+ class FunctionCallback {
89+ public:
90+ FunctionCallback (v8::Isolate* i, VALUE c, VALUE d) : isolate(i), code(c), data(d) {}
91+
92+ /* *
93+ * Package up the callback data for this function so that it can
94+ * invoke a Ruby callable.
95+ *
96+ * Each `v8::Function` can have one `v8::Value` associated with it
97+ * that is passed to its `v8::FunctionCallback`. To support this
98+ * same API from ruby, we take the `Value` passed into the
99+ * Function constructor *and* the callback and store them *both*
100+ * in a single `v8::Object` which we use for the C++ level
101+ * callback data.
102+ */
103+ inline operator v8::Local<v8::Value>() {
104+ v8::Local<v8::Object> holder = v8::Object::New (isolate);
105+ v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
106+ v8::Local<v8::String> data_key = v8::String::NewFromUtf8 (isolate, " rr::data" );
107+ holder->SetHiddenValue (callback_key, External::wrap (isolate, code));
108+ holder->SetHiddenValue (data_key, Value (data));
109+ return holder;
110+ }
111+
112+ /* *
113+ * Call the Ruby code associated with this callback.
114+ *
115+ * Unpack the Ruby code, and the callback data from the C++
116+ * callback data, and then invoke that code.
117+ *
118+ * Note: This function implements the `v8::FunctionCallback` API.
119+ */
120+ static void invoke (const v8::FunctionCallbackInfo<v8::Value>& info) {
121+ v8::Isolate* isolate = info.GetIsolate ();
122+ v8::Local<v8::Object> holder = v8::Local<v8::Object>::Cast<v8::Value>(info.Data ());
123+ v8::Local<v8::String> callback_key = v8::String::NewFromUtf8 (isolate, " rr::callback" );
124+
125+ VALUE code (External::unwrap (holder->GetHiddenValue (callback_key)));
126+ Unlocker unlock (info.GetIsolate ());
127+ rb_funcall (code, rb_intern (" call" ), 1 , (VALUE)FunctionCallbackInfo (info));
128+ }
129+
130+ inline operator v8::FunctionCallback () {
131+ if (RTEST (code)) {
132+ return &invoke;
133+ } else {
134+ return 0 ;
135+ }
136+ }
120137
121- v8::Local<v8::Value> data;
138+ v8::Isolate* isolate;
139+ VALUE code;
140+ VALUE data;
122141 };
123142}
124143
0 commit comments