mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* Revert r33078. It caused a Rails application NoMethodError.
/home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/utils.rb:157: warning: toplevel constant ScanError referenced by Regin::Parser::ScanError /home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/vendor/regin/regin/parser.rb:17:in `parse_regexp': undefined method `scan_str' for #<Regin::Parser:0x00000002344548> (NoMethodError) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33093 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
80d6bf2291
commit
4d033a11c5
4 changed files with 39 additions and 275 deletions
|
@ -1,3 +1,10 @@
|
|||
Sat Aug 27 11:18:12 2011 Hiroshi Nakamura <nahi@ruby-lang.org>
|
||||
|
||||
* Revert r33078. It caused a Rails application NoMethodError.
|
||||
|
||||
/home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/utils.rb:157: warning: toplevel constant ScanError referenced by Regin::Parser::ScanError
|
||||
/home/nahi/git/emptyApp/ruby/1.9.1/gems/rack-mount-0.6.14/lib/rack/mount/vendor/regin/regin/parser.rb:17:in `parse_regexp': undefined method `scan_str' for #<Regin::Parser:0x00000002344548> (NoMethodError)
|
||||
|
||||
Sat Aug 27 08:44:58 2011 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* lib/rdoc: Import RDoc 3.9.4. Typo and grammar fixes by Luke Gruber.
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
require 'test/unit'
|
||||
require 'tempfile'
|
||||
require 'thread'
|
||||
require_relative 'envutil'
|
||||
|
||||
class TestAutoload < Test::Unit::TestCase
|
||||
|
@ -55,112 +53,4 @@ p Foo::Bar
|
|||
assert_equal(tmpfile, b.autoload?(:X), bug4565)
|
||||
}
|
||||
end
|
||||
|
||||
def test_require_explicit
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts 'class Object; AutoloadTest = 1; end'
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
assert_nothing_raised do
|
||||
assert(require file.path)
|
||||
assert_equal(1, ::AutoloadTest)
|
||||
end
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def test_threaded_accessing_constant
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts 'sleep 0.5; class AutoloadTest; X = 1; end'
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
assert_nothing_raised do
|
||||
t1 = Thread.new { ::AutoloadTest::X }
|
||||
t2 = Thread.new { ::AutoloadTest::X }
|
||||
[t1, t2].each(&:join)
|
||||
end
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def test_threaded_accessing_inner_constant
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts 'class AutoloadTest; sleep 0.5; X = 1; end'
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
assert_nothing_raised do
|
||||
t1 = Thread.new { ::AutoloadTest::X }
|
||||
t2 = Thread.new { ::AutoloadTest::X }
|
||||
[t1, t2].each(&:join)
|
||||
end
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def test_nameerror_when_autoload_did_not_define_the_constant
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts ''
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
assert_raise(NameError) do
|
||||
AutoloadTest
|
||||
end
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def test_override_autoload
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts ''
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
eval %q(class AutoloadTest; end)
|
||||
assert_equal(Class, AutoloadTest.class)
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def test_override_while_autoloading
|
||||
file = Tempfile.open(['autoload', '.rb'])
|
||||
file.puts 'class AutoloadTest; sleep 0.5; end'
|
||||
file.close
|
||||
add_autoload(file.path)
|
||||
begin
|
||||
# while autoloading...
|
||||
t = Thread.new { AutoloadTest }
|
||||
sleep 0.1
|
||||
# override it
|
||||
eval %q(AutoloadTest = 1)
|
||||
t.join
|
||||
assert_equal(1, AutoloadTest)
|
||||
ensure
|
||||
remove_autoload_constant
|
||||
end
|
||||
end
|
||||
|
||||
def add_autoload(path)
|
||||
eval <<-END
|
||||
class ::Object
|
||||
autoload :AutoloadTest, #{path.dump}
|
||||
end
|
||||
END
|
||||
end
|
||||
|
||||
def remove_autoload_constant
|
||||
eval <<-END
|
||||
class ::Object
|
||||
remove_const(:AutoloadTest)
|
||||
end
|
||||
END
|
||||
end
|
||||
end
|
||||
|
|
194
variable.c
194
variable.c
|
@ -1445,63 +1445,12 @@ static const rb_data_type_t autoload_data_type = {
|
|||
#define check_autoload_table(av) \
|
||||
(struct st_table *)rb_check_typeddata((av), &autoload_data_type)
|
||||
|
||||
static VALUE
|
||||
autoload_data(VALUE mod, ID id)
|
||||
{
|
||||
struct st_table *tbl;
|
||||
st_data_t val;
|
||||
|
||||
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
|
||||
!(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) {
|
||||
return 0;
|
||||
}
|
||||
return (VALUE)val;
|
||||
}
|
||||
|
||||
struct autoload_data_i {
|
||||
VALUE feature;
|
||||
int safe_level;
|
||||
VALUE thread;
|
||||
VALUE value;
|
||||
};
|
||||
|
||||
static void
|
||||
autoload_i_mark(void *ptr)
|
||||
{
|
||||
struct autoload_data_i *p = ptr;
|
||||
rb_gc_mark(p->feature);
|
||||
rb_gc_mark(p->thread);
|
||||
rb_gc_mark(p->value);
|
||||
}
|
||||
|
||||
static void
|
||||
autoload_i_free(void *ptr)
|
||||
{
|
||||
struct autoload_data_i *p = ptr;
|
||||
xfree(p);
|
||||
}
|
||||
|
||||
static size_t
|
||||
autoload_i_memsize(const void *ptr)
|
||||
{
|
||||
return sizeof(struct autoload_data_i);
|
||||
}
|
||||
|
||||
static const rb_data_type_t autoload_data_i_type = {
|
||||
"autoload_i",
|
||||
{autoload_i_mark, autoload_i_free, autoload_i_memsize,},
|
||||
};
|
||||
|
||||
#define check_autoload_data(av) \
|
||||
(struct autoload_data_i *)rb_check_typeddata((av), &autoload_data_i_type)
|
||||
|
||||
void
|
||||
rb_autoload(VALUE mod, ID id, const char *file)
|
||||
{
|
||||
st_data_t av;
|
||||
VALUE ad, fn;
|
||||
VALUE fn;
|
||||
struct st_table *tbl;
|
||||
struct autoload_data_i *ele;
|
||||
|
||||
if (!rb_is_const_id(id)) {
|
||||
rb_raise(rb_eNameError, "autoload must be constant name: %s", rb_id2name(id));
|
||||
|
@ -1524,20 +1473,13 @@ rb_autoload(VALUE mod, ID id, const char *file)
|
|||
st_add_direct(tbl, (st_data_t)autoload, av);
|
||||
DATA_PTR(av) = tbl = st_init_numtable();
|
||||
}
|
||||
ad = TypedData_Wrap_Struct(0, &autoload_data_i_type, 0);
|
||||
st_insert(tbl, (st_data_t)id, (st_data_t)ad);
|
||||
DATA_PTR(ad) = ele = ALLOC(struct autoload_data_i);
|
||||
|
||||
fn = rb_str_new2(file);
|
||||
FL_UNSET(fn, FL_TAINT);
|
||||
OBJ_FREEZE(fn);
|
||||
ele->feature = fn;
|
||||
ele->safe_level = rb_safe_level();
|
||||
ele->thread = Qnil;
|
||||
ele->value = Qundef;
|
||||
st_insert(tbl, (st_data_t)id, (st_data_t)rb_node_newnode(NODE_MEMO, fn, rb_safe_level(), 0));
|
||||
}
|
||||
|
||||
static void
|
||||
static NODE*
|
||||
autoload_delete(VALUE mod, ID id)
|
||||
{
|
||||
st_data_t val, load = 0, n = id;
|
||||
|
@ -1556,6 +1498,8 @@ autoload_delete(VALUE mod, ID id)
|
|||
st_delete(RCLASS_IV_TBL(mod), &n, &val);
|
||||
}
|
||||
}
|
||||
|
||||
return (NODE *)load;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1572,18 +1516,22 @@ reset_safe(VALUE safe)
|
|||
return safe;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
check_autoload_required(VALUE mod, ID id, const char **loadingpath)
|
||||
static NODE *
|
||||
autoload_node(VALUE mod, ID id, const char **loadingpath)
|
||||
{
|
||||
VALUE file, load;
|
||||
struct autoload_data_i *ele;
|
||||
VALUE file;
|
||||
struct st_table *tbl;
|
||||
st_data_t val;
|
||||
NODE *load;
|
||||
const char *loading;
|
||||
int safe;
|
||||
|
||||
if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) {
|
||||
if (!st_lookup(RCLASS_IV_TBL(mod), autoload, &val) ||
|
||||
!(tbl = check_autoload_table((VALUE)val)) || !st_lookup(tbl, (st_data_t)id, &val)) {
|
||||
return 0;
|
||||
}
|
||||
file = ele->feature;
|
||||
load = (NODE *)val;
|
||||
file = load->nd_lit;
|
||||
Check_Type(file, T_STRING);
|
||||
if (!RSTRING_PTR(file) || !*RSTRING_PTR(file)) {
|
||||
rb_raise(rb_eArgError, "empty file name");
|
||||
|
@ -1602,7 +1550,7 @@ check_autoload_required(VALUE mod, ID id, const char **loadingpath)
|
|||
}
|
||||
|
||||
static int
|
||||
autoload_defined_p(VALUE mod, ID id)
|
||||
autoload_node_id(VALUE mod, ID id)
|
||||
{
|
||||
struct st_table *tbl = RCLASS_CONST_TBL(mod);
|
||||
st_data_t val;
|
||||
|
@ -1613,109 +1561,42 @@ autoload_defined_p(VALUE mod, ID id)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rb_autoloading_value(VALUE mod, ID id, VALUE* value)
|
||||
{
|
||||
VALUE load;
|
||||
struct autoload_data_i *ele;
|
||||
|
||||
if (!(load = autoload_data(mod, id)) || !(ele = check_autoload_data(load))) {
|
||||
return 0;
|
||||
}
|
||||
if (ele->thread == rb_thread_current()) {
|
||||
if (ele->value != Qundef) {
|
||||
if (value) {
|
||||
*value = ele->value;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct autoload_const_set_args {
|
||||
VALUE mod;
|
||||
ID id;
|
||||
VALUE value;
|
||||
};
|
||||
|
||||
static void
|
||||
autoload_const_set(struct autoload_const_set_args* args)
|
||||
{
|
||||
autoload_delete(args->mod, args->id);
|
||||
rb_const_set(args->mod, args->id, args->value);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
autoload_require(struct autoload_data_i *ele)
|
||||
{
|
||||
return rb_require_safe(ele->feature, ele->safe_level);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_autoload_load(VALUE mod, ID id)
|
||||
{
|
||||
VALUE load, result;
|
||||
VALUE file;
|
||||
NODE *load;
|
||||
const char *loading = 0, *src;
|
||||
struct autoload_data_i *ele;
|
||||
int state = 0;
|
||||
|
||||
if (!autoload_defined_p(mod, id)) return Qfalse;
|
||||
load = check_autoload_required(mod, id, &loading);
|
||||
if (!autoload_node_id(mod, id)) return Qfalse;
|
||||
load = autoload_node(mod, id, &loading);
|
||||
if (!load) return Qfalse;
|
||||
src = rb_sourcefile();
|
||||
if (src && loading && strcmp(src, loading) == 0) return Qfalse;
|
||||
|
||||
/* set ele->thread for a marker of autoloading thread */
|
||||
if (!(ele = check_autoload_data(load))) {
|
||||
return Qfalse;
|
||||
}
|
||||
if (ele->thread == Qnil) {
|
||||
ele->thread = rb_thread_current();
|
||||
}
|
||||
/* autoload_data_i can be deleted by another thread while require */
|
||||
RB_GC_GUARD(load);
|
||||
result = rb_protect((VALUE(*)(VALUE))autoload_require, (VALUE)ele, &state);
|
||||
if (ele->thread == rb_thread_current()) {
|
||||
ele->thread = Qnil;
|
||||
}
|
||||
if (state) rb_jump_tag(state);
|
||||
|
||||
if (RTEST(result)) {
|
||||
/* At the last, move a value defined in autoload to constant table */
|
||||
if (ele->value != Qundef) {
|
||||
int safe_backup;
|
||||
struct autoload_const_set_args args;
|
||||
args.mod = mod;
|
||||
args.id = id;
|
||||
args.value = ele->value;
|
||||
safe_backup = rb_safe_level();
|
||||
rb_set_safe_level_force(ele->safe_level);
|
||||
rb_ensure((VALUE(*)(VALUE))autoload_const_set, (VALUE)&args, reset_safe, (VALUE)safe_backup);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
file = load->nd_lit;
|
||||
return rb_require_safe(file, (int)load->nd_nth);
|
||||
}
|
||||
|
||||
VALUE
|
||||
rb_autoload_p(VALUE mod, ID id)
|
||||
{
|
||||
VALUE load;
|
||||
struct autoload_data_i *ele;
|
||||
VALUE file;
|
||||
NODE *load;
|
||||
const char *loading = 0;
|
||||
|
||||
while (!autoload_defined_p(mod, id)) {
|
||||
while (!autoload_node_id(mod, id)) {
|
||||
mod = RCLASS_SUPER(mod);
|
||||
if (!mod) return Qnil;
|
||||
}
|
||||
load = check_autoload_required(mod, id, 0);
|
||||
load = autoload_node(mod, id, &loading);
|
||||
if (!load) return Qnil;
|
||||
return (ele = check_autoload_data(load)) ? ele->feature : Qnil;
|
||||
return load && (file = load->nd_lit) ? file : Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
||||
{
|
||||
VALUE value, tmp, av;
|
||||
VALUE value, tmp;
|
||||
int mod_retry = 0;
|
||||
|
||||
tmp = klass;
|
||||
|
@ -1732,7 +1613,6 @@ rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
|||
if (value == Qundef) {
|
||||
if (am == tmp) break;
|
||||
am = tmp;
|
||||
if (rb_autoloading_value(tmp, id, &av)) return av;
|
||||
rb_autoload_load(tmp, id);
|
||||
continue;
|
||||
}
|
||||
|
@ -1963,7 +1843,7 @@ rb_const_defined_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
|
|||
if (visibility && ce->flag == CONST_PRIVATE) {
|
||||
return (int)Qfalse;
|
||||
}
|
||||
if (ce->value == Qundef && !check_autoload_required(tmp, id, 0) && !rb_autoloading_value(tmp, id, 0))
|
||||
if (ce->value == Qundef && !autoload_node(tmp, id, 0))
|
||||
return (int)Qfalse;
|
||||
return (int)Qtrue;
|
||||
}
|
||||
|
@ -2042,20 +1922,8 @@ rb_const_set(VALUE klass, ID id, VALUE val)
|
|||
|
||||
if (st_lookup(RCLASS_CONST_TBL(klass), (st_data_t)id, &value)) {
|
||||
rb_const_entry_t *ce = (rb_const_entry_t*)value;
|
||||
if (ce->value == Qundef) {
|
||||
VALUE load;
|
||||
struct autoload_data_i *ele;
|
||||
|
||||
load = autoload_data(klass, id);
|
||||
/* for autoloading thread, keep the defined value to autoloading storage */
|
||||
if (load && (ele = check_autoload_data(load)) && (ele->thread == rb_thread_current())) {
|
||||
rb_vm_change_state();
|
||||
ele->value = val;
|
||||
return;
|
||||
}
|
||||
/* otherwise, allow to override */
|
||||
if (ce->value == Qundef)
|
||||
autoload_delete(klass, id);
|
||||
}
|
||||
else {
|
||||
visibility = ce->flag;
|
||||
rb_warn("already initialized constant %s", rb_id2name(id));
|
||||
|
|
|
@ -1178,7 +1178,7 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
|
|||
cref = cref->nd_next;
|
||||
|
||||
if (!NIL_P(klass)) {
|
||||
VALUE av, am = 0;
|
||||
VALUE am = 0;
|
||||
st_data_t data;
|
||||
search_continue:
|
||||
if (RCLASS_CONST_TBL(klass) &&
|
||||
|
@ -1188,7 +1188,6 @@ vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
|
|||
if (am == klass) break;
|
||||
am = klass;
|
||||
if (is_defined) return 1;
|
||||
if (rb_autoloading_value(klass, id, &av)) return av;
|
||||
rb_autoload_load(klass, id);
|
||||
goto search_continue;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue