Bug #21330
openNamespace: Class and Module frozen status is not namespaced
Description
File.write("/tmp/test.rb", <<~'RUBY')
Hash.freeze
RUBY
ns = Namespace.new
ns.require("/tmp/test.rb")
class Hash
def monkey_patch
end
end
Expected behavior:
Since the monkey patch is in a different namespace, I'd expect it to not impact code that is running in another namespace.
Actual behavior:
test.rb:9:in '<class:Hash>': can't modify frozen class: Hash (FrozenError)
The class is frozen globally, breaking code in other namespaces.
Is this by design, or does that mean the frozen status need to be moved in the classext_t
as well?
Updated by byroot (Jean Boussier) 23 days ago
- Subject changed from Namespace: Class and Module frozen status is not namespace to Namespace: Class and Module frozen status is not namespaced
Updated by tagomoris (Satoshi Tagomori) 23 days ago
The frozen flag is what I missed. I think we should move the flag to rb_classext_t
.
Updated by ko1 (Koichi Sasada) 2 days ago
I'm afraid that moving frozen flag into class_ext (and each built-in class variants can has each frozen state) makese OBJ_FROZEN
code:
// include/ruby/internal/fl_type.h
static inline VALUE
RB_OBJ_FROZEN_RAW(VALUE obj)
{
return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE);
}
especially, if nobody freeze builtin classes. Any usecases?
Updated by jeremyevans0 (Jeremy Evans) 2 days ago
ko1 (Koichi Sasada) wrote in #note-4:
I'm afraid that moving frozen flag into class_ext (and each built-in class variants can has each frozen state) makese
OBJ_FROZEN
code:// include/ruby/internal/fl_type.h static inline VALUE RB_OBJ_FROZEN_RAW(VALUE obj) { return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE); }
especially, if nobody freeze builtin classes. Any usecases?
roda-sequel-stack (https://github.com/jeremyevans/roda-sequel-stack) supports and recommends freezing all core classes at runtime (after the application is loaded). This is how production Roda applications are commonly run. Freezing core classes is recommended to ensure that no libraries the application is using are modifying the core classes at runtime (they probably aren't, but how can you be sure without freezing them)?
Updated by byroot (Jean Boussier) 2 days ago
I'm afraid that moving frozen flag into class_ext (and each built-in class variants can has each frozen state) makese OBJ_FROZEN code:
It seems like your sentence is missing a word. Did you mean to say that it will make OBJ_FROZEN
slower? If so yes, absolutely, but I thought it was a given. Namespaces are introducing a level of indirection it need to be checked and isn't cheap.
But on this note I'm currently working on two patches that may help with that:
- Moving the frozen bit inside the shape_id: https://github.com/ruby/ruby/pull/13289
- Delegating classes variables handling: https://github.com/ruby/ruby/pull/13411
With those two changes, once finished, I believe I can come up with a RB_OBJ_FROZEN_RAW
that has almost the exact same performance.
Any usecases?
What Jeremy said, but also just consistency? It's very hard to reason about a feature that isn't behaving consistently.