Exemple #1
0
void
rb_alias(VALUE klass, ID name, ID def)
{
    NODE *orig_fbody, *node, *method;
    VALUE singleton = 0;
    st_data_t data;

    rb_frozen_class_p(klass);
    if (klass == rb_cObject) {
	rb_secure(4);
    }
    orig_fbody = search_method(klass, def, 0);
    if (!orig_fbody || !orig_fbody->nd_body) {
	if (TYPE(klass) == T_MODULE) {
	    orig_fbody = search_method(rb_cObject, def, 0);
	}
    }
    if (!orig_fbody || !orig_fbody->nd_body) {
	rb_print_undef(klass, def, 0);
    }
    if (FL_TEST(klass, FL_SINGLETON)) {
	singleton = rb_iv_get(klass, "__attached__");
    }

    orig_fbody->nd_cnt++;

    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
	node = (NODE *)data;
	if (node) {
	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
		rb_warning("discarding old %s", rb_id2name(name));
	    }
	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
		rb_vm_check_redefinition_opt_method(node);
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), name,
	      (st_data_t) NEW_FBODY(
		  method = NEW_METHOD(orig_fbody->nd_body->nd_body,
			     orig_fbody->nd_body->nd_clss,
			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
    method->nd_file = (void *)def;

    rb_clear_cache_by_id(name);

    if (!ruby_running) return;

    if (singleton) {
	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
    }
    else {
	rb_funcall(klass, added, 1, ID2SYM(name));
    }
}
Exemple #2
0
static int
clone_method(ID mid, NODE *body, struct clone_method_data *data)
{
    if (body == 0) {
	st_insert(data->tbl, mid, 0);
    }
    else {
	st_insert(data->tbl, mid,
		  (st_data_t)
		  NEW_FBODY(
		      NEW_METHOD(body->nd_body->nd_body,
				 data->klass, /* TODO */
				 body->nd_body->nd_noex),
		      0));
    }
    return ST_CONTINUE;
}
Exemple #3
0
void
rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
{
    NODE *body;

    if (NIL_P(klass)) {
	klass = rb_cObject;
    }
    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
	rb_raise(rb_eSecurityError, "Insecure: can't define method");
    }
    if (!FL_TEST(klass, FL_SINGLETON) &&
	node && nd_type(node) != NODE_ZSUPER &&
	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
	noex = NOEX_PRIVATE | noex;
    }
    else if (FL_TEST(klass, FL_SINGLETON) && node
	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
	rb_warn
	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
	     rb_class2name(rb_iv_get(klass, "__attached__")));
	mid = ID_ALLOCATOR;
    }
    if (OBJ_FROZEN(klass)) {
	rb_error_frozen("class/module");
    }
    rb_clear_cache_by_id(mid);

    /*
     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
     *   nd_body : method body   // (2) // mark
     *   nd_clss : klass         // (1) // mark
     *   nd_noex : visibility    // (3)
     *
     * NODE_FBODY (NEW_FBODY(method, alias)):
     *   nd_body : method (NODE_METHOD)  // (2) // mark
     *   nd_oid  : original id           // (1)
     *   nd_cnt  : alias count           // (3)
     */
    if (node) {
	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
    }
    else {
	body = 0;
    }

    {
	/* check re-definition */
	st_data_t data;
	NODE *old_node;

	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
	    old_node = (NODE *)data;
	    if (old_node) {
		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
		    rb_vm_check_redefinition_opt_method(old_node);
		}
		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
		}
	    }
	}
	if (klass == rb_cObject && node && mid == idInitialize) {
	    rb_warn("redefining Object#initialize may cause infinite loop");
	}

	if (mid == object_id || mid == __send__) {
	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
		rb_warn("redefining `%s' may cause serious problem",
			rb_id2name(mid));
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);

    if (node && mid != ID_ALLOCATOR && ruby_running) {
	if (FL_TEST(klass, FL_SINGLETON)) {
	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
		       ID2SYM(mid));
	}
	else {
	    rb_funcall(klass, added, 1, ID2SYM(mid));
	}
    }
}