Mark RClass instance that may be namespaced with RCLASS_NAMESPACEABLE

This commit is contained in:
Jean Boussier 2025-06-18 10:55:05 +01:00
parent 393e9a5f3e
commit 96a0c2065a
6 changed files with 24 additions and 5 deletions

10
class.c
View file

@ -44,6 +44,8 @@
* If unset, the prime classext is writable only from the root namespace. * If unset, the prime classext is writable only from the root namespace.
* 3: RCLASS_IS_INITIALIZED * 3: RCLASS_IS_INITIALIZED
* Class has been initialized. * Class has been initialized.
* 4: RCLASS_NAMESPACEABLE
* Is a builtin class that may be namespaced. It larger than a normal class.
*/ */
/* Flags of T_ICLASS /* Flags of T_ICLASS
@ -51,6 +53,8 @@
* 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
* This module's prime classext is the only classext and writable from any namespaces. * This module's prime classext is the only classext and writable from any namespaces.
* If unset, the prime classext is writable only from the root namespace. * If unset, the prime classext is writable only from the root namespace.
* 4: RCLASS_NAMESPACEABLE
* Is a builtin class that may be namespaced. It larger than a normal class.
*/ */
/* Flags of T_MODULE /* Flags of T_MODULE
@ -65,6 +69,8 @@
* If unset, the prime classext is writable only from the root namespace. * If unset, the prime classext is writable only from the root namespace.
* 3: RCLASS_IS_INITIALIZED * 3: RCLASS_IS_INITIALIZED
* Module has been initialized. * Module has been initialized.
* 4: RCLASS_NAMESPACEABLE
* Is a builtin class that may be namespaced. It larger than a normal class.
*/ */
#define METACLASS_OF(k) RBASIC(k)->klass #define METACLASS_OF(k) RBASIC(k)->klass
@ -662,6 +668,8 @@ class_alloc(enum ruby_value_type type, VALUE klass)
VALUE flags = type; VALUE flags = type;
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED; if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
if (!ruby_namespace_init_done) flags |= RCLASS_NAMESPACEABLE;
NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0); NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0);
memset(RCLASS_EXT_PRIME(obj), 0, sizeof(rb_classext_t)); memset(RCLASS_EXT_PRIME(obj), 0, sizeof(rb_classext_t));
@ -676,7 +684,7 @@ class_alloc(enum ruby_value_type type, VALUE klass)
RCLASS_PRIME_NS((VALUE)obj) = ns; RCLASS_PRIME_NS((VALUE)obj) = ns;
// Classes/Modules defined in user namespaces are // Classes/Modules defined in user namespaces are
// writable directly because it exists only in a namespace. // writable directly because it exists only in a namespace.
RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, !rb_namespace_available() || NAMESPACE_USER_P(ns) ? true : false); RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, ruby_namespace_init_done || NAMESPACE_USER_P(ns));
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj); RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil); RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil);

View file

@ -293,6 +293,7 @@ static inline void RCLASS_WRITE_CLASSPATH(VALUE klass, VALUE classpath, bool per
#define RCLASS_PRIME_CLASSEXT_WRITABLE FL_USER2 #define RCLASS_PRIME_CLASSEXT_WRITABLE FL_USER2
#define RCLASS_IS_INITIALIZED FL_USER3 #define RCLASS_IS_INITIALIZED FL_USER3
// 3 is RMODULE_IS_REFINEMENT for RMODULE // 3 is RMODULE_IS_REFINEMENT for RMODULE
#define RCLASS_NAMESPACEABLE FL_USER4
/* class.c */ /* class.c */
rb_classext_t * rb_class_duplicate_classext(rb_classext_t *orig, VALUE obj, const rb_namespace_t *ns); rb_classext_t * rb_class_duplicate_classext(rb_classext_t *orig, VALUE obj, const rb_namespace_t *ns);

View file

@ -52,6 +52,7 @@ typedef struct rb_namespace_struct rb_namespace_t;
#define NAMESPACE_CC_ENTRIES(ccs) (ccs ? NAMESPACE_METHOD_ENTRY(ccs->cme) : NULL) #define NAMESPACE_CC_ENTRIES(ccs) (ccs ? NAMESPACE_METHOD_ENTRY(ccs->cme) : NULL)
RUBY_EXTERN bool ruby_namespace_enabled; RUBY_EXTERN bool ruby_namespace_enabled;
RUBY_EXTERN bool ruby_namespace_init_done;
static inline bool static inline bool
rb_namespace_available(void) rb_namespace_available(void)
@ -81,5 +82,5 @@ VALUE rb_namespace_exec(const rb_namespace_t *ns, namespace_exec_func *func, VAL
VALUE rb_namespace_local_extension(VALUE namespace, VALUE fname, VALUE path); VALUE rb_namespace_local_extension(VALUE namespace, VALUE fname, VALUE path);
void rb_initialize_main_namespace(void); void rb_initialize_main_namespace(void);
void rb_namespace_init_done(void);
#endif /* INTERNAL_NAMESPACE_H */ #endif /* INTERNAL_NAMESPACE_H */

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true # frozen_string_literal: true
#-- #--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others. # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved. # All rights reserved.

View file

@ -48,12 +48,19 @@ static bool tmp_dir_has_dirsep;
#endif #endif
bool ruby_namespace_enabled = false; // extern bool ruby_namespace_enabled = false; // extern
bool ruby_namespace_init_done = false; // extern
VALUE rb_resolve_feature_path(VALUE klass, VALUE fname); VALUE rb_resolve_feature_path(VALUE klass, VALUE fname);
static VALUE rb_namespace_inspect(VALUE obj); static VALUE rb_namespace_inspect(VALUE obj);
static void namespace_push(rb_thread_t *th, VALUE namespace); static void namespace_push(rb_thread_t *th, VALUE namespace);
static VALUE namespace_pop(VALUE th_value); static VALUE namespace_pop(VALUE th_value);
void
rb_namespace_init_done(void)
{
ruby_namespace_init_done = true;
}
void void
rb_namespace_enable_builtin(void) rb_namespace_enable_builtin(void)
{ {
@ -1019,6 +1026,9 @@ Init_enable_namespace(void)
if (env && strlen(env) == 1 && env[0] == '1') { if (env && strlen(env) == 1 && env[0] == '1') {
ruby_namespace_enabled = true; ruby_namespace_enabled = true;
} }
else {
ruby_namespace_init_done = true;
}
} }
void void

4
ruby.c
View file

@ -1822,8 +1822,6 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
GET_VM()->running = 1; GET_VM()->running = 1;
memset(ruby_vm_redefined_flag, 0, sizeof(ruby_vm_redefined_flag)); memset(ruby_vm_redefined_flag, 0, sizeof(ruby_vm_redefined_flag));
ruby_init_prelude();
if (rb_namespace_available()) if (rb_namespace_available())
rb_initialize_main_namespace(); rb_initialize_main_namespace();
@ -1844,6 +1842,8 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
Init_builtin_yjit_hook(); Init_builtin_yjit_hook();
#endif #endif
rb_namespace_init_done();
ruby_init_prelude();
ruby_set_script_name(opt->script_name); ruby_set_script_name(opt->script_name);
require_libraries(&opt->req_list); require_libraries(&opt->req_list);
} }