mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	* array.c (rb_ary_to_ary): do not use #respond_to? to detect
to_ary. Just call. [ruby-core:23738] * eval.c (rb_check_funcall): new function with method existence check. returns Qundef when the method does not exist. * enumerator.c (enumerator_rewind): just call method, using rb_check_funcall(). [ruby-core:23738] * error.c (exc_equal): ditto. * object.c (convert_type): ditto. * error.c (rb_name_err_mesg_new): export function. * eval.c (make_exception): ditto. * io.c (pop_last_hash): return early when the last argument is nil. * io.c (rb_io_puts): treat T_STRING specially for small optimization. * vm_eval.c (raise_method_missing): skip method call if possible using rb_method_basic_definition_p(). * vm_eval.c (method_missing): ditto. * test/ruby/test_rubyoptions.rb (TestRubyOptions#test_debug): test suites changed to ignore exceptions caused by just-call policy. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25556 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
		
							parent
							
								
									2bb26c118d
								
							
						
					
					
						commit
						0580ba0611
					
				
					 11 changed files with 129 additions and 39 deletions
				
			
		
							
								
								
									
										32
									
								
								ChangeLog
									
										
									
									
									
								
							
							
						
						
									
										32
									
								
								ChangeLog
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,35 @@
 | 
			
		|||
Thu Oct 29 13:53:18 2009  Yukihiro Matsumoto  <matz@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* array.c (rb_ary_to_ary): do not use #respond_to? to detect
 | 
			
		||||
	  to_ary.  Just call.  [ruby-core:23738]
 | 
			
		||||
 | 
			
		||||
	* eval.c (rb_check_funcall): new function with method existence
 | 
			
		||||
	  check.  returns Qundef when the method does not exist.
 | 
			
		||||
 | 
			
		||||
	* enumerator.c (enumerator_rewind): just call method, using
 | 
			
		||||
	  rb_check_funcall().  [ruby-core:23738]
 | 
			
		||||
 | 
			
		||||
	* error.c (exc_equal): ditto.
 | 
			
		||||
 | 
			
		||||
	* object.c (convert_type): ditto.
 | 
			
		||||
 | 
			
		||||
	* error.c (rb_name_err_mesg_new): export function.
 | 
			
		||||
 | 
			
		||||
	* eval.c (make_exception): ditto.
 | 
			
		||||
 | 
			
		||||
	* io.c (pop_last_hash): return early when the last argument is nil.
 | 
			
		||||
 | 
			
		||||
	* io.c (rb_io_puts): treat T_STRING specially for small
 | 
			
		||||
	  optimization. 
 | 
			
		||||
 | 
			
		||||
	* vm_eval.c (raise_method_missing): skip method call if possible
 | 
			
		||||
	  using rb_method_basic_definition_p().
 | 
			
		||||
 | 
			
		||||
	* vm_eval.c (method_missing): ditto.
 | 
			
		||||
 | 
			
		||||
	* test/ruby/test_rubyoptions.rb (TestRubyOptions#test_debug): test
 | 
			
		||||
	  suites changed to ignore exceptions caused by just-call policy.
 | 
			
		||||
 | 
			
		||||
Thu Oct 29 04:41:44 2009  NARUSE, Yui  <naruse@ruby-lang.org>
 | 
			
		||||
 | 
			
		||||
	* ruby.c (process_options): call rb_filesystem_encoding().
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								array.c
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								array.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1223,12 +1223,9 @@ rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
 | 
			
		|||
VALUE
 | 
			
		||||
rb_ary_to_ary(VALUE obj)
 | 
			
		||||
{
 | 
			
		||||
    if (TYPE(obj) == T_ARRAY) {
 | 
			
		||||
	return obj;
 | 
			
		||||
    }
 | 
			
		||||
    if (rb_respond_to(obj, rb_intern("to_ary"))) {
 | 
			
		||||
	return to_ary(obj);
 | 
			
		||||
    }
 | 
			
		||||
    VALUE tmp = rb_check_array_type(obj);
 | 
			
		||||
 | 
			
		||||
    if (!NIL_P(tmp)) return tmp;
 | 
			
		||||
    return rb_ary_new3(1, obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								enum.c
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								enum.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -149,9 +149,10 @@ enum_count(int argc, VALUE *argv, VALUE obj)
 | 
			
		|||
	    func = count_iter_i;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    if (rb_respond_to(obj, id_size)) {
 | 
			
		||||
		return rb_funcall(obj, id_size, 0, 0);
 | 
			
		||||
	    }
 | 
			
		||||
	    VALUE tmp;
 | 
			
		||||
 | 
			
		||||
	    tmp = rb_check_funcall(obj, id_size, 0, 0);
 | 
			
		||||
	    if (tmp != Qundef) return tmp;
 | 
			
		||||
	    func = count_all_i;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -856,8 +856,7 @@ enumerator_rewind(VALUE obj)
 | 
			
		|||
{
 | 
			
		||||
    struct enumerator *e = enumerator_ptr(obj);
 | 
			
		||||
 | 
			
		||||
    if (rb_respond_to(e->obj, id_rewind))
 | 
			
		||||
	rb_funcall(e->obj, id_rewind, 0);
 | 
			
		||||
    rb_check_funcall(e->obj, id_rewind, 0, 0);
 | 
			
		||||
 | 
			
		||||
    e->fib = 0;
 | 
			
		||||
    e->dst = Qnil;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								error.c
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								error.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -608,13 +608,10 @@ exc_equal(VALUE exc, VALUE obj)
 | 
			
		|||
	CONST_ID(id_message, "message");
 | 
			
		||||
	CONST_ID(id_backtrace, "backtrace");
 | 
			
		||||
 | 
			
		||||
	if (rb_respond_to(obj, id_message) && rb_respond_to(obj, id_backtrace)) {
 | 
			
		||||
	    mesg = rb_funcall(obj, id_message, 0, 0);
 | 
			
		||||
	    backtrace = rb_funcall(obj, id_backtrace, 0, 0);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    return Qfalse;
 | 
			
		||||
	}
 | 
			
		||||
	mesg = rb_check_funcall(obj, id_message, 0, 0);
 | 
			
		||||
	if (mesg == Qundef) return Qfalse;
 | 
			
		||||
	backtrace = rb_check_funcall(obj, id_backtrace, 0, 0);
 | 
			
		||||
	if (backtrace == Qundef) return Qfalse;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
	mesg = rb_attr_get(obj, id_mesg);
 | 
			
		||||
| 
						 | 
				
			
			@ -794,8 +791,8 @@ static const rb_data_type_t name_err_mesg_data_type = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
/* :nodoc: */
 | 
			
		||||
static VALUE
 | 
			
		||||
name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method)
 | 
			
		||||
VALUE
 | 
			
		||||
rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method)
 | 
			
		||||
{
 | 
			
		||||
    VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1112,7 +1109,7 @@ Init_Exception(void)
 | 
			
		|||
    rb_define_method(rb_eNameError, "name", name_err_name, 0);
 | 
			
		||||
    rb_define_method(rb_eNameError, "to_s", name_err_to_s, 0);
 | 
			
		||||
    rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
 | 
			
		||||
    rb_define_singleton_method(rb_cNameErrorMesg, "!", name_err_mesg_new, NAME_ERR_MESG_COUNT);
 | 
			
		||||
    rb_define_singleton_method(rb_cNameErrorMesg, "!", rb_name_err_mesg_new, NAME_ERR_MESG_COUNT);
 | 
			
		||||
    rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
 | 
			
		||||
    rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
 | 
			
		||||
    rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_to_str, 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										60
									
								
								eval.c
									
										
									
									
									
								
							
							
						
						
									
										60
									
								
								eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -425,11 +425,13 @@ rb_longjmp(int tag, volatile VALUE mesg)
 | 
			
		|||
    JUMP_TAG(tag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE make_exception(int argc, VALUE *argv, int isstr);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
rb_exc_raise(VALUE mesg)
 | 
			
		||||
{
 | 
			
		||||
    if (!NIL_P(mesg)) {
 | 
			
		||||
	mesg = rb_make_exception(1, &mesg);
 | 
			
		||||
	mesg = make_exception(1, &mesg, Qfalse);
 | 
			
		||||
    }
 | 
			
		||||
    rb_longjmp(TAG_RAISE, mesg);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -438,7 +440,7 @@ void
 | 
			
		|||
rb_exc_fatal(VALUE mesg)
 | 
			
		||||
{
 | 
			
		||||
    if (!NIL_P(mesg)) {
 | 
			
		||||
	mesg = rb_make_exception(1, &mesg);
 | 
			
		||||
	mesg = make_exception(1, &mesg, Qfalse);
 | 
			
		||||
    }
 | 
			
		||||
    rb_longjmp(TAG_FATAL, mesg);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -490,8 +492,40 @@ rb_f_raise(int argc, VALUE *argv)
 | 
			
		|||
    return Qnil;		/* not reached */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct rescue_funcall_args {
 | 
			
		||||
    VALUE obj;
 | 
			
		||||
    ID id;
 | 
			
		||||
    int argc;
 | 
			
		||||
    VALUE *argv;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
check_funcall(struct rescue_funcall_args *args)
 | 
			
		||||
{
 | 
			
		||||
    return rb_funcall2(args->obj, args->id, args->argc, args->argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
check_failed(VALUE data)
 | 
			
		||||
{
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
rb_make_exception(int argc, VALUE *argv)
 | 
			
		||||
rb_check_funcall(VALUE obj, ID id, int argc, VALUE *argv)
 | 
			
		||||
{
 | 
			
		||||
    struct rescue_funcall_args args;
 | 
			
		||||
 | 
			
		||||
    args.obj = obj;
 | 
			
		||||
    args.id = id;
 | 
			
		||||
    args.argc = argc;
 | 
			
		||||
    args.argv = argv;
 | 
			
		||||
    return rb_rescue2(check_funcall, (VALUE)&args, check_failed, Qundef,
 | 
			
		||||
		      rb_eNoMethodError, (VALUE)0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static VALUE
 | 
			
		||||
make_exception(int argc, VALUE *argv, int isstr)
 | 
			
		||||
{
 | 
			
		||||
    VALUE mesg;
 | 
			
		||||
    ID exception;
 | 
			
		||||
| 
						 | 
				
			
			@ -504,10 +538,12 @@ rb_make_exception(int argc, VALUE *argv)
 | 
			
		|||
      case 1:
 | 
			
		||||
	if (NIL_P(argv[0]))
 | 
			
		||||
	    break;
 | 
			
		||||
	mesg = rb_check_string_type(argv[0]);
 | 
			
		||||
	if (!NIL_P(mesg)) {
 | 
			
		||||
	    mesg = rb_exc_new3(rb_eRuntimeError, mesg);
 | 
			
		||||
	    break;
 | 
			
		||||
	if (isstr) {
 | 
			
		||||
	    mesg = rb_check_string_type(argv[0]);
 | 
			
		||||
	    if (!NIL_P(mesg)) {
 | 
			
		||||
		mesg = rb_exc_new3(rb_eRuntimeError, mesg);
 | 
			
		||||
		break;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	n = 0;
 | 
			
		||||
	goto exception_call;
 | 
			
		||||
| 
						 | 
				
			
			@ -517,10 +553,10 @@ rb_make_exception(int argc, VALUE *argv)
 | 
			
		|||
	n = 1;
 | 
			
		||||
      exception_call:
 | 
			
		||||
	CONST_ID(exception, "exception");
 | 
			
		||||
	if (!rb_respond_to(argv[0], exception)) {
 | 
			
		||||
	mesg = rb_check_funcall(argv[0], exception, n, argv+1);
 | 
			
		||||
	if (mesg == Qundef) {
 | 
			
		||||
	    rb_raise(rb_eTypeError, "exception class/object expected");
 | 
			
		||||
	}
 | 
			
		||||
	mesg = rb_funcall(argv[0], exception, n, argv[1]);
 | 
			
		||||
	break;
 | 
			
		||||
      default:
 | 
			
		||||
	rb_raise(rb_eArgError, "wrong number of arguments");
 | 
			
		||||
| 
						 | 
				
			
			@ -536,6 +572,12 @@ rb_make_exception(int argc, VALUE *argv)
 | 
			
		|||
    return mesg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
rb_make_exception(int argc, VALUE *argv)
 | 
			
		||||
{
 | 
			
		||||
    return make_exception(argc, argv, Qtrue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
rb_raise_jump(VALUE mesg)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,6 +203,7 @@ void rb_check_frozen(VALUE);
 | 
			
		|||
/* eval.c */
 | 
			
		||||
int rb_sourceline(void);
 | 
			
		||||
const char *rb_sourcefile(void);
 | 
			
		||||
VALUE rb_check_funcall(VALUE, ID, int, VALUE*);
 | 
			
		||||
 | 
			
		||||
#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								io.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								io.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -5157,6 +5157,7 @@ pop_last_hash(int *argc_p, VALUE *argv)
 | 
			
		|||
    if (*argc_p == 0)
 | 
			
		||||
        return Qnil;
 | 
			
		||||
    last = argv[*argc_p-1];
 | 
			
		||||
    if (NIL_P(last)) return Qnil;
 | 
			
		||||
    tmp = rb_check_convert_type(last, T_HASH, "Hash", "to_hash");
 | 
			
		||||
    if (NIL_P(tmp))
 | 
			
		||||
        return Qnil;
 | 
			
		||||
| 
						 | 
				
			
			@ -6066,12 +6067,17 @@ rb_io_puts(int argc, VALUE *argv, VALUE out)
 | 
			
		|||
	return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    for (i=0; i<argc; i++) {
 | 
			
		||||
	if (TYPE(argv[i]) == T_STRING) {
 | 
			
		||||
	    line = argv[i];
 | 
			
		||||
	    goto string;
 | 
			
		||||
	}
 | 
			
		||||
	line = rb_check_array_type(argv[i]);
 | 
			
		||||
	if (!NIL_P(line)) {
 | 
			
		||||
	    rb_exec_recursive(io_puts_ary, line, out);
 | 
			
		||||
	    continue;
 | 
			
		||||
	}
 | 
			
		||||
	line = rb_obj_as_string(argv[i]);
 | 
			
		||||
      string:
 | 
			
		||||
	rb_io_write(out, line);
 | 
			
		||||
	if (RSTRING_LEN(line) == 0 ||
 | 
			
		||||
            RSTRING_PTR(line)[RSTRING_LEN(line)-1] != '\n') {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								object.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								object.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -2005,6 +2005,8 @@ convert_type(VALUE val, const char *tname, const char *method, int raise)
 | 
			
		|||
{
 | 
			
		||||
    ID m = 0;
 | 
			
		||||
    int i;
 | 
			
		||||
    VALUE args[4];
 | 
			
		||||
    VALUE r;
 | 
			
		||||
 | 
			
		||||
    for (i=0; conv_method_names[i].method; i++) {
 | 
			
		||||
	if (conv_method_names[i].method[0] == method[0] &&
 | 
			
		||||
| 
						 | 
				
			
			@ -2014,7 +2016,12 @@ convert_type(VALUE val, const char *tname, const char *method, int raise)
 | 
			
		|||
	}
 | 
			
		||||
    }
 | 
			
		||||
    if (!m) m = rb_intern(method);
 | 
			
		||||
    if (!rb_respond_to(val, m)) {
 | 
			
		||||
    args[0] = val;
 | 
			
		||||
    args[1] = (VALUE)m;
 | 
			
		||||
    args[2] = (VALUE)raise;
 | 
			
		||||
    args[3] = (VALUE)tname;
 | 
			
		||||
    r = rb_check_funcall(val, m, 0, 0);
 | 
			
		||||
    if (r == Qundef) {
 | 
			
		||||
	if (raise) {
 | 
			
		||||
	    rb_raise(rb_eTypeError, "can't convert %s into %s",
 | 
			
		||||
		     NIL_P(val) ? "nil" :
 | 
			
		||||
| 
						 | 
				
			
			@ -2023,11 +2030,9 @@ convert_type(VALUE val, const char *tname, const char *method, int raise)
 | 
			
		|||
		     rb_obj_classname(val),
 | 
			
		||||
		     tname);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    return Qnil;
 | 
			
		||||
	}
 | 
			
		||||
	return Qnil;
 | 
			
		||||
    }
 | 
			
		||||
    return rb_funcall(val, m, 0);
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
VALUE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,9 +53,9 @@ class TestRubyOptions < Test::Unit::TestCase
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  def test_debug
 | 
			
		||||
    assert_in_out_err(%w(-de) + ["p $DEBUG"], "", %w(true), [])
 | 
			
		||||
    assert_in_out_err(%w(-de) + ["p $DEBUG"], "", %w(true), //)
 | 
			
		||||
 | 
			
		||||
    assert_in_out_err(%w(--debug -e) + ["p $DEBUG"], "", %w(true), [])
 | 
			
		||||
    assert_in_out_err(%w(--debug -e) + ["p $DEBUG"], "", %w(true), //)
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def test_verbose
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										14
									
								
								vm_eval.c
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								vm_eval.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -390,9 +390,16 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
 | 
			
		|||
 | 
			
		||||
    {
 | 
			
		||||
	int n = 0;
 | 
			
		||||
	VALUE mesg;
 | 
			
		||||
	VALUE args[3];
 | 
			
		||||
	args[n++] = rb_funcall(rb_const_get(exc, rb_intern("message")), '!',
 | 
			
		||||
			       3, rb_str_new2(format), obj, argv[0]);
 | 
			
		||||
 | 
			
		||||
	mesg = rb_const_get(exc, rb_intern("message"));
 | 
			
		||||
	if (rb_method_basic_definition_p(CLASS_OF(mesg), '!')) {
 | 
			
		||||
	    args[n++] = rb_name_err_mesg_new(mesg, rb_str_new2(format), obj, argv[0]);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
	    args[n++] = rb_funcall(mesg, '!', 3, rb_str_new2(format), obj, argv[0]);
 | 
			
		||||
	}
 | 
			
		||||
	args[n++] = argv[0];
 | 
			
		||||
	if (exc == rb_eNoMethodError) {
 | 
			
		||||
	    args[n++] = rb_ary_new4(argc - 1, argv + 1);
 | 
			
		||||
| 
						 | 
				
			
			@ -433,6 +440,9 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
 | 
			
		|||
    nargv[0] = ID2SYM(id);
 | 
			
		||||
    MEMCPY(nargv + 1, argv, VALUE, argc);
 | 
			
		||||
 | 
			
		||||
    if (rb_method_basic_definition_p(CLASS_OF(obj) , idMethodMissing)) {
 | 
			
		||||
	raise_method_missing(th, argc+1, nargv, obj, call_status | NOEX_MISSING);
 | 
			
		||||
    }
 | 
			
		||||
    result = rb_funcall2(obj, idMethodMissing, argc + 1, nargv);
 | 
			
		||||
    if (argv_ary) rb_ary_clear(argv_ary);
 | 
			
		||||
    return result;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue