@@ -166,6 +166,80 @@ is_constant_path(VALUE name)
166166 return true;
167167}
168168
169+ struct sub_temporary_name_args {
170+ VALUE names ;
171+ ID last ;
172+ };
173+
174+ static VALUE build_const_path (VALUE head , ID tail );
175+ static void set_sub_temporary_name_foreach (VALUE mod , struct sub_temporary_name_args * args , VALUE name );
176+
177+ static VALUE
178+ set_sub_temporary_name_recursive (VALUE mod , VALUE data , int recursive )
179+ {
180+ if (recursive ) return Qfalse ;
181+
182+ struct sub_temporary_name_args * args = (void * )data ;
183+ VALUE name = 0 ;
184+ if (args -> names ) {
185+ name = build_const_path (rb_ary_last (0 , 0 , args -> names ), args -> last );
186+ }
187+ set_sub_temporary_name_foreach (mod , args , name );
188+ return Qtrue ;
189+ }
190+
191+ static VALUE
192+ set_sub_temporary_name_topmost (VALUE mod , VALUE data , int recursive )
193+ {
194+ if (recursive ) return Qfalse ;
195+
196+ struct sub_temporary_name_args * args = (void * )data ;
197+ VALUE name = args -> names ;
198+ if (name ) {
199+ args -> names = rb_ary_hidden_new (0 );
200+ }
201+ set_sub_temporary_name_foreach (mod , args , name );
202+ return Qtrue ;
203+ }
204+
205+ static enum rb_id_table_iterator_result
206+ set_sub_temporary_name_i (ID id , VALUE val , void * data )
207+ {
208+ val = ((rb_const_entry_t * )val )-> value ;
209+ if (rb_namespace_p (val ) && !RCLASS_EXT (val )-> permanent_classpath ) {
210+ VALUE arg = (VALUE )data ;
211+ struct sub_temporary_name_args * args = data ;
212+ args -> last = id ;
213+ rb_exec_recursive_paired (set_sub_temporary_name_recursive , val , arg , arg );
214+ }
215+ return ID_TABLE_CONTINUE ;
216+ }
217+
218+ static void
219+ set_sub_temporary_name_foreach (VALUE mod , struct sub_temporary_name_args * args , VALUE name )
220+ {
221+ RCLASS_SET_CLASSPATH (mod , name , FALSE);
222+ struct rb_id_table * tbl = RCLASS_CONST_TBL (mod );
223+ if (!tbl ) return ;
224+ if (!name ) {
225+ rb_id_table_foreach (tbl , set_sub_temporary_name_i , args );
226+ }
227+ else {
228+ long names_len = RARRAY_LEN (args -> names ); // paranoiac check?
229+ rb_ary_push (args -> names , name );
230+ rb_id_table_foreach (tbl , set_sub_temporary_name_i , args );
231+ rb_ary_set_len (args -> names , names_len );
232+ }
233+ }
234+
235+ static void
236+ set_sub_temporary_name (VALUE mod , VALUE name )
237+ {
238+ struct sub_temporary_name_args args = {name };
239+ VALUE arg = (VALUE )& args ;
240+ rb_exec_recursive_paired (set_sub_temporary_name_topmost , mod , arg , arg );
241+ }
242+
169243/*
170244 * call-seq:
171245 * mod.set_temporary_name(string) -> self
@@ -224,7 +298,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
224298
225299 if (NIL_P (name )) {
226300 // Set the temporary classpath to NULL (anonymous):
227- RCLASS_SET_CLASSPATH (mod , 0 , FALSE);
301+ RB_VM_LOCK_ENTER ();
302+ set_sub_temporary_name (mod , 0 );
303+ RB_VM_LOCK_LEAVE ();
228304 }
229305 else {
230306 // Ensure the name is a string:
@@ -241,7 +317,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
241317 name = rb_str_new_frozen (name );
242318
243319 // Set the temporary classpath to the given name:
244- RCLASS_SET_CLASSPATH (mod , name , FALSE);
320+ RB_VM_LOCK_ENTER ();
321+ set_sub_temporary_name (mod , name );
322+ RB_VM_LOCK_LEAVE ();
245323 }
246324
247325 return mod ;
0 commit comments