Skip to content
This repository was archived by the owner on Dec 4, 2023. It is now read-only.

Commit 99f9ad3

Browse files
committed
Merge branch 'upgrade-to-v8-4.5' of github.com:cowboyd/therubyracer into 4.5/object-template
2 parents 03f2f28 + 9ab2d8b commit 99f9ad3

31 files changed

Lines changed: 865 additions & 78 deletions

ext/v8/array.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ namespace rr {
2727
Array array(self);
2828
Locker lock(array.getIsolate());
2929

30-
return UInt32(array->Length());
30+
return Uint32_t(array->Length());
3131
}
3232

3333
VALUE Array::CloneElementAt(VALUE self, VALUE index) {
3434
Array array(self);
3535
Locker lock(array.getIsolate());
3636

37-
return Object(array.getIsolate(), array->CloneElementAt(UInt32(index)));
37+
return Object(array.getIsolate(), array->CloneElementAt(Uint32_t(index)));
3838
}
3939

4040
}

ext/v8/bool.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ namespace rr {
2323
*/
2424
class Bool : public Equiv {
2525
public:
26+
/**
27+
* Use to convert methods that return Maybe<bool> to a Ruby
28+
* VALUE, Such as `Maybe<bool> v8::Object::Get()`:
29+
*
30+
* return Bool::Maybe(object->Get(context, key));
31+
*/
32+
typedef Equiv::Maybe<bool, Bool> Maybe;
33+
2634
/**
2735
* Construct a Bool from a Ruby VALUE
2836
*/

ext/v8/equiv.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ namespace rr {
4040
*/
4141
inline operator VALUE() { return value; }
4242

43+
44+
/**
45+
* A Maybe class for primitive conversions. Specify the primitive
46+
* type and the covversion type, and it will be wrapped in a
47+
* Maybe. E.g.
48+
*
49+
* v8::Maybe<bool> maybe = methodReturningMaybeBool();
50+
* return Equiv::Maybe<bool, Bool>(maybe);
51+
*
52+
* will yield a V8::C::Maybe wrapping the underlying maybe value.
53+
*/
54+
template <class T, class S>
55+
class Maybe : public rr::Maybe {
56+
public:
57+
Maybe(v8::Maybe<T> maybe) {
58+
if (maybe.IsJust()) {
59+
just(S(maybe.FromJust()));
60+
}
61+
}
62+
};
63+
4364
protected:
4465
VALUE value;
4566
};

ext/v8/external.cc

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,14 @@ namespace rr {
1313

1414
VALUE External::New(VALUE self, VALUE r_isolate, VALUE object) {
1515
Isolate isolate(r_isolate);
16-
17-
// as long as this external is alive within JavaScript, it should not be
18-
// garbage collected by Ruby.
19-
isolate.retainObject(object);
20-
2116
Locker lock(isolate);
2217

23-
// create the external.
24-
Container* container = new Container(object);
25-
v8::Local<v8::External> external(v8::External::New(isolate, (void*)container));
26-
27-
// next, we create a weak reference to this external so that we can be
28-
// notified when V8 is done with it. At that point, we can let Ruby know
29-
// that this external is done with it.
30-
v8::Global<v8::External>* global(new v8::Global<v8::External>(isolate, external));
31-
global->SetWeak<Container>(container, &release, v8::WeakCallbackType::kParameter);
32-
container->global = global;
33-
34-
return External(isolate, external);
18+
return External(isolate, wrap(isolate, object));
3519
}
3620

3721
VALUE External::Value(VALUE self) {
3822
External external(self);
3923
Locker lock(external);
40-
Container* container((Container*)external->Value());
41-
return container->object;
24+
return unwrap(external);
4225
}
4326
}

ext/v8/external.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,33 @@ namespace rr {
1616
inline External(v8::Isolate* isolate, v8::Handle<v8::Value> value) :
1717
External(isolate, v8::Handle<v8::External>::Cast<v8::Value>(value)) {}
1818

19+
static inline v8::Local<v8::External> wrap(Isolate isolate, VALUE object) {
20+
// as long as this external is alive within JavaScript, it should not be
21+
// garbage collected by Ruby.
22+
isolate.retainObject(object);
23+
24+
// create the external.
25+
Container* container = new Container(object);
26+
v8::Local<v8::External> external(v8::External::New(isolate, (void*)container));
27+
28+
// next, we create a weak reference to this external so that we can be
29+
// notified when V8 is done with it. At that point, we can let Ruby know
30+
// that this external is done with it.
31+
v8::Global<v8::External>* global(new v8::Global<v8::External>(isolate, external));
32+
global->SetWeak<Container>(container, &release, v8::WeakCallbackType::kParameter);
33+
container->global = global;
34+
35+
return External(isolate, external);
36+
}
37+
static inline VALUE unwrap(v8::Local<v8::External> external) {
38+
Container* container = (Container*)external->Value();
39+
return container->object;
40+
};
41+
42+
static inline VALUE unwrap(v8::Local<v8::Value> external) {
43+
return unwrap(v8::Local<v8::External>::Cast<v8::Value>(external));
44+
}
45+
1946
struct Container {
2047
Container(VALUE v) : object(v) {}
2148

ext/v8/function-callback.h

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// -*- mode: c++ -*-
2+
#ifndef RR_FUNCTION_CALLBACK_H
3+
#define RR_FUNCTION_CALLBACK_H
4+
5+
namespace rr {
6+
7+
typedef Wrapper<v8::FunctionCallbackInfo<v8::Value>> FunctionCallbackInfoWrapper;
8+
9+
class FunctionCallbackInfo : public FunctionCallbackInfoWrapper {
10+
public:
11+
12+
inline FunctionCallbackInfo(v8::FunctionCallbackInfo<v8::Value> info, v8::Local<v8::Value> data_) :
13+
FunctionCallbackInfoWrapper(info), data(data_) {}
14+
15+
inline FunctionCallbackInfo(VALUE self) : FunctionCallbackInfoWrapper(self) {}
16+
17+
inline v8::Local<v8::Value> operator [](int i) {
18+
return this->container->content[i];
19+
}
20+
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+
61+
static VALUE Length(VALUE self) {
62+
FunctionCallbackInfo info(self);
63+
Locker lock(info->GetIsolate());
64+
return INT2FIX(info->Length());
65+
}
66+
67+
static VALUE at(VALUE self, VALUE i) {
68+
FunctionCallbackInfo info(self);
69+
Locker lock(info->GetIsolate());
70+
return Value::handleToRubyObject(info->GetIsolate(), info[NUM2INT(i)]);
71+
}
72+
73+
static VALUE Callee(VALUE self) {
74+
FunctionCallbackInfo info(self);
75+
Locker lock(info->GetIsolate());
76+
return Function(info->GetIsolate(), info->Callee());
77+
}
78+
79+
static VALUE This(VALUE self) {
80+
FunctionCallbackInfo info(self);
81+
Locker lock(info->GetIsolate());
82+
return Object(info->GetIsolate(), info->This());
83+
}
84+
85+
static VALUE IsConstructCall(VALUE self) {
86+
FunctionCallbackInfo info(self);
87+
Locker lock(info->GetIsolate());
88+
return Bool(info->IsConstructCall());
89+
}
90+
91+
static VALUE Data(VALUE self) {
92+
FunctionCallbackInfo info(self);
93+
Locker lock(info->GetIsolate());
94+
return Value::handleToRubyObject(info->GetIsolate(), info.data);
95+
}
96+
97+
static VALUE GetIsolate(VALUE self) {
98+
FunctionCallbackInfo info(self);
99+
return Isolate(info->GetIsolate());
100+
}
101+
102+
static VALUE GetReturnValue(VALUE self) {
103+
FunctionCallbackInfo info(self);
104+
Locker lock(info->GetIsolate());
105+
return ReturnValue(info->GetReturnValue());
106+
}
107+
108+
static inline void Init() {
109+
ClassBuilder("FunctionCallbackInfo").
110+
defineMethod("Length", &Length).
111+
defineMethod("[]", &at).
112+
defineMethod("Callee", &Callee).
113+
defineMethod("This", &This).
114+
defineMethod("IsConstructCall", &IsConstructCall).
115+
defineMethod("Data", &Data).
116+
defineMethod("GetIsolate", &GetIsolate).
117+
defineMethod("GetReturnValue", &GetReturnValue).
118+
store(&Class);
119+
}
120+
121+
v8::Local<v8::Value> data;
122+
};
123+
}
124+
125+
#endif /* RR_FUNCTION_CALLBACK_H */

ext/v8/function.cc

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace rr {
44

55
void Function::Init() {
66
ClassBuilder("Function", Object::Class).
7-
7+
defineSingletonMethod("New", &New).
88
defineMethod("NewInstance", &NewInstance).
99
defineMethod("Call", &Call).
1010
defineMethod("SetName", &SetName).
@@ -20,6 +20,23 @@ namespace rr {
2020
store(&Class);
2121
}
2222

23+
VALUE Function::New(int argc, VALUE argv[], VALUE self) {
24+
VALUE r_isolate, r_callback, r_data, r_length;
25+
rb_scan_args(argc, argv, "22", &r_isolate, &r_callback, &r_data, &r_length);
26+
Isolate isolate(r_isolate);
27+
Locker lock(isolate);
28+
29+
// package up the function's callback data to have bot the code and the data
30+
// parameter.
31+
v8::Local<v8::Value> data(FunctionCallbackInfo::wrapData(isolate, r_callback, r_data));
32+
33+
int length = RTEST(r_length) ? NUM2INT(r_length) : 0;
34+
35+
v8::FunctionCallback callback = &FunctionCallbackInfo::invoke;
36+
37+
return Function(isolate, v8::Function::New(isolate, callback, data, length));
38+
}
39+
2340
VALUE Function::NewInstance(int argc, VALUE argv[], VALUE self) {
2441
VALUE args;
2542
rb_scan_args(argc, argv, "01", &args);

ext/v8/function.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// -*- mode: c++ -*-
12
#ifndef RR_FUNCTION
23
#define RR_FUNCTION
34

@@ -7,8 +8,9 @@ namespace rr {
78
public:
89
static void Init();
910

11+
static VALUE New(int argc, VALUE argv[], VALUE self);
1012
static VALUE NewInstance(int argc, VALUE argv[], VALUE self);
11-
static VALUE Call(VALUE self, VALUE receiver, VALUE argv);
13+
static VALUE Call(VALUE self, VALUE receiver, VALUE arguments);
1214
static VALUE SetName(VALUE self, VALUE name);
1315
static VALUE GetName(VALUE self);
1416
static VALUE GetInferredName(VALUE self);
@@ -23,7 +25,6 @@ namespace rr {
2325
inline Function(VALUE value) : Ref<v8::Function>(value) {}
2426
inline Function(v8::Isolate* isolate, v8::Handle<v8::Function> function) : Ref<v8::Function>(isolate, function) {}
2527
};
26-
2728
}
2829

2930
#endif

ext/v8/init.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ extern "C" {
1313
Handles::Init();
1414
Context::Init();
1515
Backref::Init();
16+
Maybe::Init();
1617
Value::Init();
1718
Object::Init();
1819
Primitive::Init();
20+
Number::Init();
21+
Integer::Init();
1922
Name::Init();
2023
String::Init();
2124
Symbol::Init();
2225
Function::Init();
26+
FunctionCallbackInfo::Init();
27+
ReturnValue::Init();
2328
Script::Init();
2429
ScriptOrigin::Init();
2530
Array::Init();

0 commit comments

Comments
 (0)