зеркало из https://github.com/github/ruby.git
* 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:
Родитель
0b10c32079
Коммит
8e864d1e86
18
ChangeLog
18
ChangeLog
|
@ -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
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';
|
||||||
}
|
}
|
||||||
|
|
77
variable.c
77
variable.c
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче