diff --git a/include/natalie/class_object.hpp b/include/natalie/class_object.hpp index 67f6ef66d..b9c8c06de 100644 --- a/include/natalie/class_object.hpp +++ b/include/natalie/class_object.hpp @@ -56,6 +56,10 @@ class ClassObject : public ModuleObject { Value initialize(Env *, Optional, Block *); + using AllocFunc = Value (*)(Env *, Value); + AllocFunc alloc_func() const { return m_alloc_func; } + void set_alloc_func(AllocFunc func) { m_alloc_func = func; } + bool is_singleton() const { return m_is_singleton; } void set_is_singleton(bool is_singleton) { m_is_singleton = is_singleton; } @@ -82,6 +86,7 @@ class ClassObject : public ModuleObject { Type m_object_type { Type::Object }; bool m_is_singleton { false }; bool m_is_initialized { false }; + AllocFunc m_alloc_func { nullptr }; }; } diff --git a/lib/natalie/compiler/instructions/inline_cpp_instruction.rb b/lib/natalie/compiler/instructions/inline_cpp_instruction.rb index 92bc06fdd..e97ee1363 100644 --- a/lib/natalie/compiler/instructions/inline_cpp_instruction.rb +++ b/lib/natalie/compiler/instructions/inline_cpp_instruction.rb @@ -45,6 +45,12 @@ def generate_bind_method(transform, ruby_name, cpp_name = ruby_name, arity = -1) ) end + def generate_alloc_func(transform, cpp_name) + cpp_name = comptime_symbol(cpp_name) + transform.exec("self.as_class()->set_alloc_func(#{cpp_name});") + transform.push_nil + end + def generate_bind_static_method(transform, ruby_name, cpp_name = ruby_name, arity = -1) ruby_name = comptime_symbol(ruby_name) cpp_name = comptime_symbol(cpp_name) diff --git a/lib/natalie/compiler/pass1.rb b/lib/natalie/compiler/pass1.rb index a6697d907..b3e617d3a 100644 --- a/lib/natalie/compiler/pass1.rb +++ b/lib/natalie/compiler/pass1.rb @@ -61,6 +61,7 @@ def initialize( attr_reader :file INLINE_CPP_MACROS = %i[ + __alloc_func__ __bind_method__ __bind_static_method__ __call__ diff --git a/lib/openssl.cpp b/lib/openssl.cpp index 1b3fe4865..fe6da29a6 100644 --- a/lib/openssl.cpp +++ b/lib/openssl.cpp @@ -379,12 +379,11 @@ Value OpenSSL_HMAC_digest(Env *env, Value self, Args &&args, Block *) { return StringObject::create(reinterpret_cast(md), md_len, Encoding::ASCII_8BIT); } -Value OpenSSL_SSL_SSLContext_initialize(Env *env, Value self, Args &&args, Block *) { - args.ensure_argc_is(env, 0); // NATFIXME: Add deprecated version argument +Value OpenSSL_SSL_SSLContext_alloc(Env *env, Value self) { SSL_CTX *ctx = SSL_CTX_new(TLS_method()); - SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT); if (!ctx) OpenSSL_SSL_raise_error(env, "SSL_CTX_new"); + SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT); self->ivar_set(env, "@ctx"_s, VoidPObject::create(ctx, OpenSSL_SSL_CTX_cleanup)); self->ivar_set(env, "@verify_hostname"_s, Value::False()); self->ivar_set(env, "@verify_mode"_s, Value::integer(0)); diff --git a/lib/openssl.rb b/lib/openssl.rb index 45c14ba66..f21796a90 100644 --- a/lib/openssl.rb +++ b/lib/openssl.rb @@ -320,7 +320,7 @@ class SSLContext (OpenSSL::SSL::OP_ALL & ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS) | OpenSSL::SSL::OP_NO_COMPRESSION, }.freeze - __bind_method__ :initialize, :OpenSSL_SSL_SSLContext_initialize + __alloc_func__ :OpenSSL_SSL_SSLContext_alloc __bind_method__ :max_version=, :OpenSSL_SSL_SSLContext_set_max_version __bind_method__ :min_version=, :OpenSSL_SSL_SSLContext_set_min_version __bind_method__ :options, :OpenSSL_SSL_SSLContext_options, 0 @@ -331,7 +331,7 @@ class SSLContext __bind_method__ :session_cache_mode=, :OpenSSL_SSL_SSLContext_set_session_cache_mode, 1 __bind_method__ :setup, :OpenSSL_SSL_SSLContext_setup - attr_accessor :cert_store, :verify_hostname, :verify_mode + attr_accessor :cert_store, :session_new_cb, :verify_hostname, :verify_mode alias freeze setup diff --git a/src/object.cpp b/src/object.cpp index 51eb761db..8825a3889 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -156,10 +156,14 @@ Optional Object::create(Env *env, ClassObject *klass) { } Value Object::_new(Env *env, Value klass_value, Args &&args, Block *block) { - auto obj = create(env, klass_value.as_class()); + auto klass = klass_value.as_class(); + auto obj = create(env, klass); if (!obj) NAT_UNREACHABLE(); + if (auto func = klass->alloc_func()) + func(env, obj.value()); + obj->send(env, "initialize"_s, std::move(args), block); return obj.value(); } @@ -182,6 +186,9 @@ Value Object::allocate(Env *env, Value klass_value, Args &&args, Block *block) { if (!obj) env->raise("TypeError", "allocator undefined for {}", klass->inspect_module()); + if (auto func = klass->alloc_func()) + func(env, obj.value()); + return obj.value(); }