@@ -166,6 +166,80 @@ is_constant_path(VALUE name)
166
166
return true;
167
167
}
168
168
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
+
169
243
/*
170
244
* call-seq:
171
245
* mod.set_temporary_name(string) -> self
@@ -224,7 +298,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
224
298
225
299
if (NIL_P (name )) {
226
300
// 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 ();
228
304
}
229
305
else {
230
306
// Ensure the name is a string:
@@ -241,7 +317,9 @@ rb_mod_set_temporary_name(VALUE mod, VALUE name)
241
317
name = rb_str_new_frozen (name );
242
318
243
319
// 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 ();
245
323
}
246
324
247
325
return mod ;
0 commit comments