Esempio n. 1
0
void
rb_undef(VALUE klass, ID id)
{
    if (NIL_P(klass)) {
	rb_raise(rb_eTypeError, "no class to undef method");
    }
    if (klass == rb_cObject) {
	rb_secure(4);
    }
    if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(klass)) {
	rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
		rb_id2name(id));
    }
    rb_frozen_class_p(klass);
    if (id == object_id || id == __send__ || id == idInitialize) {
	rb_warn("undefining `%s' may cause serious problem", rb_id2name(id));
    }

    rb_vm_undef_method((Class)klass, id, true);
}
Esempio n. 2
0
static VALUE
mod_async(VALUE klass, VALUE method_name)
{
    VALUE umethod;
    struct METHOD *data;
    rb_iseq_t *niseq;

    rb_frozen_class_p(klass);

    umethod = rb_funcall(klass, rb_intern("instance_method"), 1, method_name);
    data = (struct METHOD *)DATA_PTR(umethod); // UnboundMethod's DATA_PTR is (struct METHOD *)
    if (data->me->def->type != VM_METHOD_TYPE_ISEQ) {
        rb_raise(rb_eTypeError, "unsupported method type (only iseq supported)");
    }

    // 元の iseqptr が消えなかったり nseq が消えたりするような気もするけど知らない
    niseq = transform(umethod);
    *((rb_iseq_t **)&data->me->def->body.iseq.iseqptr) = niseq;

    return method_name;
}
Esempio n. 3
0
void
rb_alias(VALUE klass, ID name, ID def)
{
    rb_method_entry_t *orig_me;

    rb_frozen_class_p(klass);
    if (klass == rb_cObject) {
	rb_secure(4);
    }

    orig_me = search_method(klass, def);

    if (UNDEFINED_METHOD_ENTRY_P(orig_me)) {
	if ((TYPE(klass) != T_MODULE) ||
	    (orig_me = search_method(rb_cObject, def), UNDEFINED_METHOD_ENTRY_P(orig_me))) {
	    rb_print_undef(klass, def, 0);
	}
    }

    rb_add_method_me(klass, name, orig_me, orig_me->flag);
}
Esempio n. 4
0
void
rb_alias(VALUE klass, ID name, ID def)
{
    VALUE target_klass = klass;
    VALUE defined_class;
    rb_method_entry_t *orig_me;
    rb_method_flag_t flag = NOEX_UNDEF;

    if (NIL_P(klass)) {
	rb_raise(rb_eTypeError, "no class to make alias");
    }

    rb_frozen_class_p(klass);

  again:
    orig_me = search_method(klass, def, &defined_class);

    if (UNDEFINED_METHOD_ENTRY_P(orig_me) ||
	UNDEFINED_REFINED_METHOD_P(orig_me->def)) {
	if ((!RB_TYPE_P(klass, T_MODULE)) ||
	    (orig_me = search_method(rb_cObject, def, 0),
	     UNDEFINED_METHOD_ENTRY_P(orig_me))) {
	    rb_print_undef(klass, def, 0);
	}
    }
    if (orig_me->def->type == VM_METHOD_TYPE_ZSUPER) {
	klass = RCLASS_SUPER(klass);
	def = orig_me->def->original_id;
	flag = orig_me->flag;
	goto again;
    }
    if (RB_TYPE_P(defined_class, T_ICLASS)) {
	VALUE real_class = RBASIC_CLASS(defined_class);
	if (real_class && RCLASS_ORIGIN(real_class) == defined_class)
	    defined_class = real_class;
    }

    if (flag == NOEX_UNDEF) flag = orig_me->flag;
    method_entry_set(target_klass, name, orig_me, flag, defined_class);
}
Esempio n. 5
0
void
rb_undef(VALUE klass, ID id)
{
    rb_method_entry_t *me;

    if (NIL_P(klass)) {
	rb_raise(rb_eTypeError, "no class to undef method");
    }
    rb_frozen_class_p(klass);
    if (id == object_id || id == id__send__ || id == idInitialize) {
	rb_warn("undefining `%s' may cause serious problems", rb_id2name(id));
    }

    me = search_method(klass, id, 0);

    if (UNDEFINED_METHOD_ENTRY_P(me) ||
	UNDEFINED_REFINED_METHOD_P(me->def)) {
	const char *s0 = " class";
	VALUE c = klass;

	if (FL_TEST(c, FL_SINGLETON)) {
	    VALUE obj = rb_ivar_get(klass, attached);

	    if (RB_TYPE_P(obj, T_MODULE) || RB_TYPE_P(obj, T_CLASS)) {
		c = obj;
		s0 = "";
	    }
	}
	else if (RB_TYPE_P(c, T_MODULE)) {
	    s0 = " module";
	}
	rb_name_error(id, "undefined method `%"PRIsVALUE"' for%s `%"PRIsVALUE"'",
		      QUOTE_ID(id), s0, rb_class_name(c));
    }

    rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC);

    CALL_METHOD_HOOK(klass, undefined, id);
}
Esempio n. 6
0
File: class.c Progetto: MSch/MacRuby
void
rb_include_module2(VALUE klass, VALUE orig_klass, VALUE module, bool check,
	bool add_methods)
{
    if (check) {
	rb_frozen_class_p(klass);
	if (!OBJ_TAINTED(klass)) {
	    rb_secure(4);
	}
	Check_Type(module, T_MODULE);
    }

    // Register the module as included in the class.
    VALUE ary = rb_attr_get(klass, idIncludedModules);
    if (ary == Qnil) {
	ary = rb_ary_new();
	rb_ivar_set(klass, idIncludedModules, ary);
    }
    else {
	if (rb_ary_includes(ary, module)) {
	    return;
	}
    }
    rb_ary_insert(ary, 0, module);

    // Mark the module as included somewhere.
    const long v = RCLASS_VERSION(module) | RCLASS_IS_INCLUDED;
    RCLASS_SET_VERSION(module, v);

    // Register the class as included in the module.
    ary = rb_attr_get(module, idIncludedInClasses);
    if (ary == Qnil) {
	ary = rb_ary_new();
	rb_ivar_set(module, idIncludedInClasses, ary);
    }
    rb_ary_push(ary, klass);

    // Delete the ancestors array if it exists, since we just changed it.
    CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(klass);
    if (iv_dict != NULL) {
	CFDictionaryRemoveValue(iv_dict, (const void *)idAncestors);
    }

    if (add_methods) {
	// Copy methods. If original class has the basic -initialize and if the
	// module has a customized -initialize, we must copy the customized
	// version to the original class too.
	rb_vm_copy_methods((Class)module, (Class)klass);

	// When including into the class Class, also copy the methods to the
	// singleton class of NSObject.
	if (klass == rb_cClass || klass == rb_cModule) {
            rb_vm_copy_methods((Class)module, *(Class *)rb_cNSObject);
	}

	if (orig_klass != 0 && orig_klass != klass) {
	    Method m = class_getInstanceMethod((Class)orig_klass,
		    selInitialize);
	    Method m2 = class_getInstanceMethod((Class)klass, selInitialize);
	    if (m != NULL && m2 != NULL
		&& method_getImplementation(m) == (IMP)rb_objc_init
		&& method_getImplementation(m2) != (IMP)rb_objc_init) {
		rb_vm_copy_method((Class)orig_klass, m2);
	    }
	}
    }
}
Esempio n. 7
0
static rb_method_entry_t *
rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
		     rb_method_definition_t *def, rb_method_flag_t noex,
		     VALUE defined_class)
{
    rb_method_entry_t *me;
#if NOEX_NOREDEF
    VALUE rklass;
#endif
    st_table *mtbl;
    st_data_t data;
    int make_refined = 0;

    if (NIL_P(klass)) {
	klass = rb_cObject;
    }
    if (!FL_TEST(klass, FL_SINGLETON) &&
	type != VM_METHOD_TYPE_NOTIMPLEMENTED &&
	type != VM_METHOD_TYPE_ZSUPER) {
	switch (mid) {
	  case idInitialize:
	  case idInitialize_copy:
	  case idInitialize_clone:
	  case idInitialize_dup:
	  case idRespond_to_missing:
	    noex |= NOEX_PRIVATE;
	}
    }

    rb_frozen_class_p(klass);
#if NOEX_NOREDEF
    rklass = klass;
#endif
    if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
	VALUE refined_class =
	    rb_refinement_module_get_refined_class(klass);

	rb_add_refined_method_entry(refined_class, mid);
    }
    if (type == VM_METHOD_TYPE_REFINED) {
	rb_method_entry_t *old_me =
	    lookup_method_table(RCLASS_ORIGIN(klass), mid);
	if (old_me) rb_vm_check_redefinition_opt_method(old_me, klass);
    }
    else {
	klass = RCLASS_ORIGIN(klass);
    }
    mtbl = RCLASS_M_TBL(klass);

    /* check re-definition */
    if (st_lookup(mtbl, mid, &data)) {
	rb_method_entry_t *old_me = (rb_method_entry_t *)data;
	rb_method_definition_t *old_def = old_me->def;

	if (rb_method_definition_eq(old_def, def)) return old_me;
#if NOEX_NOREDEF
	if (old_me->flag & NOEX_NOREDEF) {
	    rb_raise(rb_eTypeError, "cannot redefine %"PRIsVALUE"#%"PRIsVALUE,
		     rb_class_name(rklass), rb_id2str(mid));
	}
#endif
	rb_vm_check_redefinition_opt_method(old_me, klass);
	if (old_def->type == VM_METHOD_TYPE_REFINED)
	    make_refined = 1;

	if (RTEST(ruby_verbose) &&
	    type != VM_METHOD_TYPE_UNDEF &&
	    old_def->alias_count == 0 &&
	    old_def->type != VM_METHOD_TYPE_UNDEF &&
	    old_def->type != VM_METHOD_TYPE_ZSUPER) {
	    rb_iseq_t *iseq = 0;

	    rb_warning("method redefined; discarding old %"PRIsVALUE, rb_id2str(mid));
	    switch (old_def->type) {
	      case VM_METHOD_TYPE_ISEQ:
		iseq = old_def->body.iseq;
		break;
	      case VM_METHOD_TYPE_BMETHOD:
		iseq = rb_proc_get_iseq(old_def->body.proc, 0);
		break;
	      default:
		break;
	    }
	    if (iseq && !NIL_P(iseq->location.path)) {
		int line = iseq->line_info_table ? FIX2INT(rb_iseq_first_lineno(iseq->self)) : 0;
		rb_compile_warning(RSTRING_PTR(iseq->location.path), line,
				   "previous definition of %"PRIsVALUE" was here",
				   rb_id2str(old_def->original_id));
	    }
	}

	rb_unlink_method_entry(old_me);
    }

    me = ALLOC(rb_method_entry_t);

    rb_clear_method_cache_by_class(klass);

    me->flag = NOEX_WITH_SAFE(noex);
    me->mark = 0;
    me->called_id = mid;
    RB_OBJ_WRITE(klass, &me->klass, defined_class);
    me->def = def;

    if (def) {
	def->alias_count++;

	switch(def->type) {
	  case VM_METHOD_TYPE_ISEQ:
	    RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq->self);
	    break;
	  case VM_METHOD_TYPE_IVAR:
	    RB_OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
	    break;
	  case VM_METHOD_TYPE_BMETHOD:
	    RB_OBJ_WRITTEN(klass, Qundef, def->body.proc);
	    break;
	  default:;
	    /* ignore */
	}
    }

    /* check mid */
    if (klass == rb_cObject && mid == idInitialize) {
	rb_warn("redefining Object#initialize may cause infinite loop");
    }
    /* check mid */
    if (mid == object_id || mid == id__send__) {
	if (type == VM_METHOD_TYPE_ISEQ && search_method(klass, mid, 0)) {
	    rb_warn("redefining `%s' may cause serious problems", rb_id2name(mid));
	}
    }

    if (make_refined) {
	make_method_entry_refined(me);
    }

    st_insert(mtbl, mid, (st_data_t) me);

    return me;
}