14 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::V8ClassWrapper(v8::Isolate * isolate) :
18 this->isolate_about_to_be_destroyed(this->isolate);
20 this->isolate_to_wrapper_map.emplace(isolate,
this);
23 template<
class T>
void 24 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::call_callbacks(
v8::Local<v8::Object> object,
27 for (
auto &callback : property_changed_callbacks) {
28 callback(isolate,
object, property_name, value);
33 template<
class T>
void 34 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::check_if_name_used(
const std::string & name) {
36 if (std::find(used_attribute_name_list.begin(),
37 used_attribute_name_list.end(),
38 name) != used_attribute_name_list.end()) {
40 throw DuplicateNameException(fmt::format(
"Cannot add method/member named '{}' to class '{}', name already in use", name, class_name));
44 used_attribute_name_list.push_back(name);
48 template<
class T>
void 49 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::check_if_static_name_used(
const std::string & name) {
50 if (std::find(used_static_attribute_name_list.begin(),
51 used_static_attribute_name_list.end(),
52 name) != used_static_attribute_name_list.end()) {
54 throw DuplicateNameException(fmt::format(
"Cannot add static method named '{}' to class '{}', name already in use", name, class_name));
56 used_static_attribute_name_list.push_back(name);
59 template<
class T>
void 60 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::check_if_constructor_name_used(
const std::string & name) {
66 if (std::find(used_constructor_name_list.begin(),
67 used_constructor_name_list.end(),
68 name) != used_constructor_name_list.end()) {
70 throw DuplicateNameException(fmt::format(
"Cannot add constructor named '{}' to class '{}', name already in use (or built-in JavaScript type", name, class_name));
72 used_constructor_name_list.push_back(name);
80 template<
class T>
void 81 V8ClassWrapper<T, V8TOOLKIT_V8CLASSWRAPPER_USE_REAL_TEMPLATE_SFINAE>::callback_helper(
const v8::FunctionCallbackInfo<v8::Value>& args) {
83 (*callback_lambda)(args);
87 template<
class T>
void 89 property_changed_callbacks.push_back(callback);
103 assert(this->finalized ==
true);
107 auto function_template = v8::FunctionTemplate::New(isolate, callback, data);
108 init_instance_object_template(function_template->InstanceTemplate());
109 init_prototype_object_template(function_template->PrototypeTemplate());
110 for (
auto &adder : this->static_method_adders) {
111 adder(function_template);
114 function_template->SetClassName(v8::String::NewFromUtf8(isolate, class_name.c_str()));
119 auto parent_function_template = global_parent_function_template.Get(isolate);
120 if (!parent_function_template.IsEmpty()) {
122 function_template->Inherit(parent_function_template);
125 for (
auto callback : this->function_template_callbacks) {
126 callback(function_template);
130 this_class_function_templates.emplace_back(v8::Global<v8::FunctionTemplate>(isolate, function_template));
131 return function_template;
143 if (this_class_function_templates.empty()){
146 return make_wrapping_function_template();
150 return this_class_function_templates[0].Get(isolate);
161 if (object->InternalFieldCount() == 0) {
163 }
else if (object->InternalFieldCount() > 1) {
165 fmt::format(
"Tried to get internal field from object with more than one internal fields - this is not supported by v8toolkit: {}", demangle<T>()));
170 V8TOOLKIT_DEBUG(
"uncasted internal field: %p\n", wrapped_data->native_object);
171 if (wrapped_data ==
nullptr) {
174 T * result = this->cast(wrapped_data->native_object);
184 template<
class T> T *
187 V8TOOLKIT_DEBUG(
"In ClassWrapper::cast for type %s\n", demangle<T>().c_str());
188 if (type_checker !=
nullptr) {
190 return type_checker->check(any_base);
193 else if (
dynamic_cast<AnyPtr<T>*
>(any_base)) {
195 V8TOOLKIT_DEBUG(
"No explicit compatible types, but successfully cast to self-type\n");
196 return static_cast<AnyPtr<T>*
>(any_base)->
get();
203 throw CastException(
"Could not determine type of object in V8ClassWrapper::cast(). Define ANYBASE_DEBUG for more information");
207 template<
class T>
void 209 object_template->SetInternalFieldCount(1);
211 for (
auto &adder : this->member_adders) {
212 adder(object_template);
216 if (callable_adder.callback) {
217 object_template->SetCallAsFunctionHandler(callback_helper,
218 v8::External::New(this->isolate, &callable_adder.callback));
226 for (
auto &adder : this->method_adders) {
231 auto function_template = v8::FunctionTemplate::New(this->isolate);
232 function_template->SetCallHandler(callback_helper, v8::External::New(this->isolate, &adder.callback));
235 object_template->Set(v8::String::NewFromUtf8(isolate, adder.method_name.c_str()), function_template);
237 for (
auto &adder : this->fake_method_adders) {
238 adder(object_template);
241 if (this->indexed_property_getter) {
242 object_template->SetIndexedPropertyHandler(this->indexed_property_getter);
261 template<
class T>
void 263 assert(!this->finalized);
264 this->class_name = name;
274 template<
class T>
void 276 if (this->finalized) {
277 throw V8Exception(this->isolate, fmt::format(
"Called ::finalize on wrapper that was already finalized: {}", demangle<T>()));
279 if (!std::is_const<T>::value) {
282 this->wrap_as_most_derived_flag = wrap_as_most_derived_flag;
283 this->finalized =
true;
284 get_function_template();
#define V8TOOLKIT_DEBUG(format_string,...)