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

Implement methods for Template, FunctionTemplate & ObjectTemplate #385

Open
wants to merge 5 commits into
base: upgrade-to-v8-4.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions ext/v8/accessor-signature.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "rr.h"

namespace rr {
VALUE AccessorSignature::New(int argc, VALUE argv[], VALUE self) {
VALUE r_isolate;
VALUE r_receiver;
rb_scan_args(argc, argv, "11", &r_isolate, &r_receiver);

Isolate isolate(r_isolate);
Locker lock(isolate);
return AccessorSignature(isolate, v8::AccessorSignature::New(isolate, FunctionTemplate(r_receiver)));
}
}
22 changes: 22 additions & 0 deletions ext/v8/accessor-signature.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// -*- mode: c++ -*-
#ifndef RR_ACCESSOR_SIGNATURE_H
#define RR_ACCESSOR_SIGNATURE_H

namespace rr {
class AccessorSignature : public Ref<v8::AccessorSignature> {
public:
AccessorSignature(VALUE self) : Ref<v8::AccessorSignature>(self) {}
AccessorSignature(v8::Isolate* i, v8::Local<v8::AccessorSignature> s) :
Ref<v8::AccessorSignature>(i, s) {}

static void Init() {
ClassBuilder("AccessorSignature").
defineSingletonMethod("New", &New).
store(&Class);
}

static VALUE New(int argc, VALUE argv[], VALUE self);
};
}

#endif /* RR_ACCESSOR_SIGNATURE_H */
109 changes: 107 additions & 2 deletions ext/v8/function-template.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,21 @@ namespace rr {
FunctionTemplate(VALUE self) : Ref<v8::FunctionTemplate>(self) {}
FunctionTemplate(v8::Isolate* isolate, v8::Local<v8::FunctionTemplate> t) :
Ref<v8::FunctionTemplate>(isolate, t) {}

static inline void Init() {
ClassBuilder("FunctionTemplate", Template::Class).
defineSingletonMethod("New", &New).
defineMethod("GetFunction", &GetFunction).
defineMethod("SetCallHandler", &SetCallHandler).
defineMethod("SetLength", &SetLength).
defineMethod("InstanceTemplate", &InstanceTemplate).
defineMethod("PrototypeTemplate", &PrototypeTemplate).
defineMethod("SetClassName", &SetClassName).
defineMethod("SetAcceptAnyReceiver", &SetAcceptAnyReceiver).
defineMethod("SetHiddenPrototype", &SetHiddenPrototype).
defineMethod("ReadOnlyPrototype", &ReadOnlyPrototype).
defineMethod("RemovePrototype", &RemovePrototype).
defineMethod("HasInstance", &HasInstance).
store(&Class);
}

Expand All @@ -26,9 +37,8 @@ namespace rr {

FunctionCallback callback(isolate, r_callback, r_data);
Signature signature(r_signature);
int length(RTEST(r_length) ? NUM2INT(r_length) : 0);

return FunctionTemplate(isolate, v8::FunctionTemplate::New(isolate, callback, callback, v8::Local<v8::Signature>(), length));
return FunctionTemplate(isolate, v8::FunctionTemplate::New(isolate, callback, callback, v8::Local<v8::Signature>(), Int(r_length)));
}

static VALUE GetFunction(VALUE self, VALUE context) {
Expand All @@ -38,6 +48,101 @@ namespace rr {

return Function::Maybe(isolate, t->GetFunction(Context(context)));
}

static VALUE SetCallHandler(VALUE self, VALUE r_callback, VALUE r_data) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);
FunctionCallback callback(isolate, r_callback, r_data);

t->SetCallHandler(callback, callback);

return Qnil;
}

static VALUE SetLength(VALUE self, VALUE r_length) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->SetLength(Int(r_length));

return Qnil;
}

static VALUE InstanceTemplate(VALUE self) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

return ObjectTemplate(isolate, t->InstanceTemplate());
}

static VALUE PrototypeTemplate(VALUE self) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

return ObjectTemplate(isolate, t->PrototypeTemplate());
}

static VALUE SetClassName(VALUE self, VALUE name) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->SetClassName(String(name));

return Qnil;
}

static VALUE SetAcceptAnyReceiver(VALUE self, VALUE value) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->SetAcceptAnyReceiver(Bool(value));

return Qnil;
}

static VALUE SetHiddenPrototype(VALUE self, VALUE value) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->SetHiddenPrototype(Bool(value));

return Qnil;
}

static VALUE ReadOnlyPrototype(VALUE self) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->ReadOnlyPrototype();

return Qnil;
}

static VALUE RemovePrototype(VALUE self) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

t->ReadOnlyPrototype();

return Qnil;
}

static VALUE HasInstance(VALUE self, VALUE object) {
FunctionTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

return Bool(t->HasInstance(Value(object)));
}
};
}

Expand Down
1 change: 1 addition & 0 deletions ext/v8/init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ extern "C" {
ScriptOrigin::Init();
Array::Init();
External::Init();
AccessorSignature::Init();
Template::Init();
ObjectTemplate::Init();
FunctionTemplate::Init();
Expand Down
102 changes: 101 additions & 1 deletion ext/v8/object-template.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#define RR_OBJECT_TEMPLATE_H

namespace rr {
class ObjectTemplate : Ref<v8::ObjectTemplate> {
class ObjectTemplate : public Ref<v8::ObjectTemplate> {
public:
ObjectTemplate(VALUE self) : Ref<v8::ObjectTemplate>(self) {}
ObjectTemplate(v8::Isolate* isolate, v8::Handle<v8::ObjectTemplate> tmpl) :
Expand All @@ -13,6 +13,11 @@ namespace rr {
ClassBuilder("ObjectTemplate", Template::Class).
defineSingletonMethod("New", &New).
defineMethod("NewInstance", &NewInstance).
defineMethod("SetAccessor", &SetAccessor).
defineMethod("SetNamedPropertyHandler", &SetNamedPropertyHandler).
defineMethod("SetIndexedPropertyHandler", &SetIndexedPropertyHandler).
defineMethod("SetCallAsFunctionHandler", &SetCallAsFunctionHandler).
defineMethod("InternalFieldCount", &InternalFieldCount).
defineMethod("SetInternalFieldCount", &SetInternalFieldCount).
store(&Class);
}
Expand All @@ -35,6 +40,13 @@ namespace rr {
return Object::Maybe(isolate, t->NewInstance(context));
}

static VALUE InternalFieldCount(VALUE self) {
ObjectTemplate t(self);
Locker lock(t);

return INT2NUM(t->InternalFieldCount());
}

static VALUE SetInternalFieldCount(VALUE self, VALUE value) {
ObjectTemplate t(self);
Locker lock(t);
Expand All @@ -43,6 +55,94 @@ namespace rr {

return Qnil;
}

static VALUE SetAccessor(int argc, VALUE argv[], VALUE self) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused about which method we're going to call here and why. The way it is written it looks like it will invoke the C++ method that takes Local<Name> instead of Local<String> This seems fair since string is always a name, but will it make a difference at runtime? I.e. is there a different codepath that V8 is executing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, The "Name" one seemed like a better choice because we already have these types of accessor callbacks implemented and it is more generic. The documentation doesn't seem to suggest they have different codepaths and I think the String one may be the older of the two.

VALUE r_name, r_getter, r_setter, r_data, r_settings, r_attribute, r_signature;
rb_scan_args(
argc, argv, "25",
&r_name, &r_getter, &r_setter, &r_data, &r_settings, &r_attribute, &r_signature
);

ObjectTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

PropertyCallback callback(isolate, r_getter, r_setter, r_data);

t->SetAccessor(
*Name(r_name),
callback.getter(),
callback.setter(),
callback,
Enum<v8::AccessControl>(r_settings, v8::DEFAULT),
Enum<v8::PropertyAttribute>(r_attribute, v8::None),
AccessorSignature(r_signature)
);

return Qnil;
}

static VALUE SetNamedPropertyHandler(int argc, VALUE argv[], VALUE self) {
VALUE r_getter, r_setter, r_query, r_deleter, r_enumerator, r_data;
rb_scan_args(
argc, argv, "15",
&r_getter, &r_setter, &r_query, &r_deleter, &r_enumerator, &r_data
);

ObjectTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

PropertyCallback callback(isolate, r_getter, r_setter, r_query, r_deleter, r_enumerator, r_data);

t->SetNamedPropertyHandler(
callback.propertyGetter(),
callback.propertySetter(),
callback.propertyQuery(),
callback.propertyDeleter(),
callback.enumerator(),
callback
);

return Qnil;
}

static VALUE SetIndexedPropertyHandler(int argc, VALUE argv[], VALUE self) {
VALUE r_getter, r_setter, r_query, r_deleter, r_enumerator, r_data;
rb_scan_args(
argc, argv, "15",
&r_getter, &r_setter, &r_query, &r_deleter, &r_enumerator, &r_data
);

ObjectTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

PropertyCallback callback(isolate, r_getter, r_setter, r_query, r_deleter, r_enumerator, r_data);

t->SetIndexedPropertyHandler(
callback.indexedGetter(),
callback.indexedSetter(),
callback.indexedQuery(),
callback.indexedDeleter(),
callback.enumerator(),
callback
);

return Qnil;
}

static VALUE SetCallAsFunctionHandler(VALUE self, VALUE r_callback, VALUE r_data) {
ObjectTemplate t(self);
Isolate isolate(t.getIsolate());
Locker lock(isolate);

FunctionCallback callback(isolate, r_callback, r_data);

t->SetCallAsFunctionHandler(callback, callback);

return Qnil;
}
};
}

Expand Down
8 changes: 5 additions & 3 deletions ext/v8/object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,14 @@ namespace rr {
Isolate isolate(object.getIsolate());
Locker lock(isolate);

PropertyCallback callback(isolate, getter, setter, data);

return Bool::Maybe(object->SetAccessor(
context,
Name(name),
&PropertyCallback::invokeGetter,
RTEST(setter) ? &PropertyCallback::invokeSetter : 0,
v8::MaybeLocal<v8::Value>(PropertyCallback::wrapData(isolate, getter, setter, data)),
callback.getter(),
callback.setter(),
callback,
Enum<v8::AccessControl>(settings, v8::DEFAULT),
Enum<v8::PropertyAttribute>(attribute, v8::None)
));
Expand Down
Loading