* load.c (rb_get_load_path): returns the load path without

touching.

* load.c (rb_feature_provided): new function to return the loading
  path in addition to rb_provided().

* load.c (search_required): sets path if loading.

* variable.c (autoload_provided): load paths are expanded to check
  if loading.

* variable.c (autoload_node): keeps autoload mark while loading.
  [ruby-core:20235]

* variable.c (rb_const_get_0): loops while autoload mark is set.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@20531 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2008-12-04 18:29:20 +00:00
Родитель 0b10c32079
Коммит 8e864d1e86
5 изменённых файлов: 90 добавлений и 47 удалений

Просмотреть файл

@ -1,3 +1,21 @@
Fri Dec 5 03:29:17 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* load.c (rb_get_load_path): returns the load path without
touching.
* load.c (rb_feature_provided): new function to return the loading
path in addition to rb_provided().
* load.c (search_required): sets path if loading.
* variable.c (autoload_provided): load paths are expanded to check
if loading.
* variable.c (autoload_node): keeps autoload mark while loading.
[ruby-core:20235]
* variable.c (rb_const_get_0): loops while autoload mark is set.
Fri Dec 5 01:37:02 2008 NAKAMURA Usaku <usa@ruby-lang.org> Fri Dec 5 01:37:02 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (rb_w32_read): ERROR_BROKEN_PIPE is not a real error * win32/win32.c (rb_w32_read): ERROR_BROKEN_PIPE is not a real error

Просмотреть файл

@ -50,3 +50,12 @@ assert_equal 'ok', %q{
module M; end module M; end
Thread.new{eval('$SAFE=4; ZZZ.new.hoge')}.value Thread.new{eval('$SAFE=4; ZZZ.new.hoge')}.value
} }
assert_equal 'okok', %q{
open("zzz.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
autoload :ZZZ, "./zzz.rb"
t1 = Thread.new {ZZZ.ok}
t2 = Thread.new {ZZZ.ok}
[t1.value, t2.value].join
}

Просмотреть файл

@ -267,6 +267,7 @@ void rb_load(VALUE, int);
void rb_load_protect(VALUE, int, int*); void rb_load_protect(VALUE, int, int*);
NORETURN(void rb_jump_tag(int)); NORETURN(void rb_jump_tag(int));
int rb_provided(const char*); int rb_provided(const char*);
int rb_feature_provided(const char *, const char **);
void rb_provide(const char*); void rb_provide(const char*);
VALUE rb_f_require(VALUE, VALUE); VALUE rb_f_require(VALUE, VALUE);
VALUE rb_require_safe(VALUE, int); VALUE rb_require_safe(VALUE, int);

32
load.c
Просмотреть файл

@ -30,13 +30,7 @@ VALUE
rb_get_load_path(void) rb_get_load_path(void)
{ {
VALUE load_path = GET_VM()->load_path; VALUE load_path = GET_VM()->load_path;
VALUE ary = rb_ary_new2(RARRAY_LEN(load_path)); return load_path;
long i;
for (i = 0; i < RARRAY_LEN(load_path); ++i) {
rb_ary_push(ary, rb_file_expand_path(RARRAY_PTR(load_path)[i], Qnil));
}
return ary;
} }
static VALUE static VALUE
@ -197,6 +191,12 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
int int
rb_provided(const char *feature) rb_provided(const char *feature)
{
return rb_feature_provided(feature, 0);
}
int
rb_feature_provided(const char *feature, const char **loading)
{ {
const char *ext = strrchr(feature, '.'); const char *ext = strrchr(feature, '.');
volatile VALUE fullpath = 0; volatile VALUE fullpath = 0;
@ -208,15 +208,15 @@ rb_provided(const char *feature)
} }
if (ext && !strchr(ext, '/')) { if (ext && !strchr(ext, '/')) {
if (IS_RBEXT(ext)) { if (IS_RBEXT(ext)) {
if (rb_feature_p(feature, ext, Qtrue, Qfalse, 0)) return Qtrue; if (rb_feature_p(feature, ext, Qtrue, Qfalse, loading)) return Qtrue;
return Qfalse; return Qfalse;
} }
else if (IS_SOEXT(ext) || IS_DLEXT(ext)) { else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
if (rb_feature_p(feature, ext, Qfalse, Qfalse, 0)) return Qtrue; if (rb_feature_p(feature, ext, Qfalse, Qfalse, loading)) return Qtrue;
return Qfalse; return Qfalse;
} }
} }
if (rb_feature_p(feature, feature + strlen(feature), Qtrue, Qfalse, 0)) if (rb_feature_p(feature, feature + strlen(feature), Qtrue, Qfalse, loading))
return Qtrue; return Qtrue;
return Qfalse; return Qfalse;
} }
@ -430,9 +430,8 @@ search_required(VALUE fname, volatile VALUE *path)
return 'r'; return 'r';
} }
if ((tmp = rb_find_file(fname)) != 0) { if ((tmp = rb_find_file(fname)) != 0) {
tmp = rb_file_expand_path(tmp, Qnil);
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, Qtrue, Qtrue, 0)) if (!rb_feature_p(ftptr, ext, Qtrue, Qtrue, &loading) || loading)
*path = tmp; *path = tmp;
return 'r'; return 'r';
} }
@ -447,9 +446,8 @@ search_required(VALUE fname, volatile VALUE *path)
#ifdef DLEXT2 #ifdef DLEXT2
OBJ_FREEZE(tmp); OBJ_FREEZE(tmp);
if (rb_find_file_ext(&tmp, loadable_ext + 1)) { if (rb_find_file_ext(&tmp, loadable_ext + 1)) {
tmp = rb_file_expand_path(tmp, Qnil);
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0)) if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, &loading) || loading)
*path = tmp; *path = tmp;
return 's'; return 's';
} }
@ -457,9 +455,8 @@ search_required(VALUE fname, volatile VALUE *path)
rb_str_cat2(tmp, DLEXT); rb_str_cat2(tmp, DLEXT);
OBJ_FREEZE(tmp); OBJ_FREEZE(tmp);
if ((tmp = rb_find_file(tmp)) != 0) { if ((tmp = rb_find_file(tmp)) != 0) {
tmp = rb_file_expand_path(tmp, Qnil);
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0)) if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, &loading) || loading)
*path = tmp; *path = tmp;
return 's'; return 's';
} }
@ -471,9 +468,8 @@ search_required(VALUE fname, volatile VALUE *path)
return 's'; return 's';
} }
if ((tmp = rb_find_file(fname)) != 0) { if ((tmp = rb_find_file(fname)) != 0) {
tmp = rb_file_expand_path(tmp, Qnil);
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, 0)) if (!rb_feature_p(ftptr, ext, Qfalse, Qtrue, &loading) || loading)
*path = tmp; *path = tmp;
return 's'; return 's';
} }

Просмотреть файл

@ -1387,57 +1387,76 @@ autoload_delete(VALUE mod, ID id)
return (NODE *)load; return (NODE *)load;
} }
VALUE static VALUE
rb_autoload_load(VALUE klass, ID id) autoload_provided(VALUE arg)
{ {
VALUE file; const char **p = (const char **)arg;
NODE *load = autoload_delete(klass, id); return rb_feature_provided(*p, p);
if (!load || !(file = load->nd_lit)) {
return Qfalse;
}
return rb_require_safe(file, load->nd_nth);
} }
static VALUE static VALUE
autoload_file(VALUE mod, ID id) reset_safe(VALUE safe)
{
rb_set_safe_level_force((int)safe);
return safe;
}
static NODE *
autoload_node(VALUE mod, ID id, int noload)
{ {
VALUE file; VALUE file;
struct st_table *tbl; struct st_table *tbl;
st_data_t val, load, n = id; st_data_t val;
NODE *load;
const char *loading;
int safe;
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) || if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
!(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, n, &load)) { !(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) {
return Qnil; return 0;
} }
file = ((NODE *)load)->nd_lit; load = (NODE *)val;
file = load->nd_lit;
Check_Type(file, T_STRING); Check_Type(file, T_STRING);
if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) { if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) {
rb_raise(rb_eArgError, "empty file name"); rb_raise(rb_eArgError, "empty file name");
} }
if (!rb_provided(RSTRING_PTR(file))) { loading = RSTRING_PTR(file);
return file; safe = rb_safe_level();
rb_set_safe_level_force(0);
if (!rb_ensure(autoload_provided, (VALUE)&loading, reset_safe, (VALUE)safe)) {
return load;
} }
if (!noload && loading) {
return load;
}
return 0;
}
/* already loaded but not defined */ VALUE
st_delete(tbl, &n, 0); rb_autoload_load(VALUE klass, ID id)
if (!tbl->num_entries) { {
n = autoload; VALUE file;
st_delete(RCLASS_IV_TBL(mod), &n, &val); NODE *load = autoload_node(klass, id, 0);
}
return Qnil; if (!load) return Qfalse;
file = load->nd_lit;
return rb_require_safe(file, load->nd_nth);
} }
VALUE VALUE
rb_autoload_p(VALUE mod, ID id) rb_autoload_p(VALUE mod, ID id)
{ {
struct st_table *tbl = RCLASS_IV_TBL(mod); struct st_table *tbl = RCLASS_IV_TBL(mod);
VALUE val; st_data_t val;
NODE *load;
VALUE file;
if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) { if (!tbl || !st_lookup(tbl, id, &val) || val != Qundef) {
return Qnil; return Qnil;
} }
return autoload_file(mod, id); load = autoload_node(mod, id, 0);
return load && (file = load->nd_lit) ? file : Qnil;
} }
static VALUE static VALUE
@ -1451,7 +1470,7 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse)
while (RTEST(tmp)) { while (RTEST(tmp)) {
while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) { while (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp),id,&value)) {
if (value == Qundef) { if (value == Qundef) {
if (!RTEST(rb_autoload_load(tmp, id))) break; rb_autoload_load(tmp, id);
continue; continue;
} }
if (exclude && tmp == rb_cObject && klass != rb_cObject) { if (exclude && tmp == rb_cObject && klass != rb_cObject) {
@ -1636,7 +1655,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse)
retry: retry:
while (tmp) { while (tmp) {
if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) { if (RCLASS_IV_TBL(tmp) && st_lookup(RCLASS_IV_TBL(tmp), id, &value)) {
if (value == Qundef && NIL_P(autoload_file(klass, id))) if (value == Qundef && !autoload_node(klass, id, 1))
return Qfalse; return Qfalse;
return Qtrue; return Qtrue;
} }
@ -1675,7 +1694,7 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
const char *dest = isconst ? "constant" : "class variable"; const char *dest = isconst ? "constant" : "class variable";
if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4) if (!OBJ_UNTRUSTED(klass) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest); rb_raise(rb_eSecurityError, "Insecure: can't set %s", dest);
if (OBJ_FROZEN(klass)) { if (OBJ_FROZEN(klass)) {
if (BUILTIN_TYPE(klass) == T_MODULE) { if (BUILTIN_TYPE(klass) == T_MODULE) {
rb_error_frozen("module"); rb_error_frozen("module");
@ -1698,7 +1717,7 @@ mod_av_set(VALUE klass, ID id, VALUE val, int isconst)
} }
} }
if(isconst){ if (isconst){
rb_vm_change_state(); rb_vm_change_state();
} }
st_insert(RCLASS_IV_TBL(klass), id, val); st_insert(RCLASS_IV_TBL(klass), id, val);