/*
* call-seq:
* Module.load(String) => Module
*
* Load a module from a string.
*/
static VALUE module_load(VALUE klass, VALUE str)
{
VALUE arr, class_name, metaclass_str, metaclass, superclass_name,
included_modules, class_variables_str, class_variables,
instance_methods_str, instance_methods, flags, module;
if( ruby_safe_level >= 4
|| (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
{
/* no playing with knives in the sandbox */
rb_raise(rb_eSecurityError, "Insecure: can't load module");
}
arr = marshal_load(str);
class_name = rb_ary_pop(arr);
metaclass_str = rb_ary_pop(arr);
superclass_name = rb_ary_pop(arr);
included_modules = rb_ary_pop(arr);
class_variables_str = rb_ary_pop(arr);
instance_methods_str = rb_ary_pop(arr);
flags = rb_ary_pop(arr);
if(RTEST(superclass_name))
{
VALUE superclass;
rb_check_type(superclass_name, T_STRING);
superclass = rb_funcall(
lookup_module_proc,
rb_intern("call"),
1,
superclass_name);
#if RUBY_VERSION_CODE >= 180
/* Can't make subclass of Class on 1.8.x */
module = rb_class_boot(superclass);
rb_define_alloc_func(module, module_instance_allocate);
#else
module = rb_class_new(superclass);
#endif
}
else
{
module = rb_module_new();
}
if(!NIL_P(class_name))
{
VALUE outer_module = rb_funcall(outer_module_proc, rb_intern("call"), 1, class_name);
VALUE module_name = rb_funcall(module_name_proc, rb_intern("call"), 1, class_name);
rb_const_set(outer_module, SYM2ID(module_name), module);
}
RBASIC(module)->flags = NUM2INT(flags);
include_modules(module, included_modules);
class_variables = marshal_load(class_variables_str);
add_class_variables(module, class_variables);
instance_methods = marshal_load(instance_methods_str);
add_methods(module, instance_methods);
metaclass = marshal_load(metaclass_str);
if(RTEST(metaclass))
{
rb_singleton_class_attached(metaclass, module);
RBASIC(module)->klass = metaclass;
}
return module;
}