Skip to content

Commit 2b01882

Browse files
committed
refactor: stop modifying Ruby::Box#require and use box.require for file detection
1 parent 78b2503 commit 2b01882

1 file changed

Lines changed: 21 additions & 47 deletions

File tree

lib/irb/reloadable_require.rb

Lines changed: 21 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,53 +9,18 @@
99
module IRB
1010
# Provides reload-aware require functionality for IRB.
1111
#
12+
# This feature is experimental and requires Ruby::Box (Ruby 4.0+).
13+
#
1214
# Limitations:
1315
# - Native extensions cannot be reloaded (load doesn't support them)
14-
# - Files loaded via box.require are not tracked
1516
# - Constant redefinition warnings will appear on reload (uses load internally)
16-
# - Context mode 5 (running IRB inside a Ruby::Box) is not supported
17-
#
18-
# This feature requires Ruby::Box (Ruby 4.0+).
19-
20-
unless Ruby::Box.method_defined?(:__irb_original_require__)
21-
Ruby::Box.class_eval do
22-
alias_method :__irb_original_require__, :require
23-
alias_method :__irb_original_require_relative__, :require_relative
24-
end
25-
end
26-
27-
Ruby::Box.class_eval do
28-
def __irb_reloadable_require__(feature)
29-
unless IRB::ReloadableRequire.autoload_files.include?(feature)
30-
return __irb_original_require__(feature)
31-
end
32-
33-
IRB::ReloadableRequire.autoload_files.delete(feature)
34-
IRB::ReloadableRequire.track_and_load_files($LOADED_FEATURES, Ruby::Box.main) { __irb_original_require__(feature) }
35-
end
36-
37-
def __irb_reloadable_require_relative__(feature)
38-
__irb_original_require_relative__(feature)
39-
end
40-
end
4117

4218
module ReloadableRequire
4319
@reloadable_files = Set.new
44-
@autoload_files = Set.new
20+
@autoload_features = {}
4521

4622
class << self
47-
attr_reader :reloadable_files, :autoload_files
48-
49-
def extended(base)
50-
apply_autoload_hook
51-
end
52-
53-
def apply_autoload_hook
54-
Ruby::Box.class_eval do
55-
alias_method :require, :__irb_reloadable_require__
56-
alias_method :require_relative, :__irb_reloadable_require_relative__
57-
end
58-
end
23+
attr_reader :reloadable_files, :autoload_features
5924

6025
def track_and_load_files(source, current_box)
6126
before = source.dup
@@ -76,6 +41,15 @@ def track_and_load_files(source, current_box)
7641

7742
result
7843
end
44+
45+
def collect_autoloaded_files
46+
@autoload_features.each_value do |feature|
47+
resolved = $LOAD_PATH.resolve_feature_path(feature) rescue nil
48+
next unless resolved && resolved.first == :rb
49+
path = resolved[1]
50+
@reloadable_files << path if $LOADED_FEATURES.include?(path)
51+
end
52+
end
7953
end
8054

8155
private
@@ -85,18 +59,16 @@ def reloadable_require_internal(feature, caller_box)
8559
box.eval("$LOAD_PATH.concat(#{caller_box.eval('$LOAD_PATH')})")
8660
box.eval("$LOADED_FEATURES.concat(#{caller_box.eval('$LOADED_FEATURES')})")
8761

88-
ReloadableRequire.track_and_load_files(box.eval('$LOADED_FEATURES'), caller_box) { box.__irb_original_require__(feature) }
62+
ReloadableRequire.track_and_load_files(box.eval('$LOADED_FEATURES'), caller_box) { box.require(feature) }
8963
end
9064

9165
def require(feature)
9266
caller_loc = caller_locations(1, 1).first
93-
current_box = Ruby::Box.main
94-
return current_box.__irb_original_require__(feature) unless caller_loc.path.end_with?("(irb)")
95-
96-
resolved = current_box.eval("$LOAD_PATH.resolve_feature_path(#{feature.dump})")
97-
return current_box.__irb_original_require__(feature) unless resolved&.first == :rb
67+
return super unless caller_loc.path.end_with?("(irb)")
9868

99-
reloadable_require_internal(feature, current_box)
69+
reloadable_require_internal(feature, Ruby::Box.main)
70+
rescue LoadError
71+
super
10072
end
10173

10274
def require_relative(feature)
@@ -109,10 +81,12 @@ def require_relative(feature)
10981
end
11082

11183
reloadable_require_internal(File.expand_path(feature, Dir.pwd), current_box)
84+
rescue LoadError
85+
super
11286
end
11387

11488
def autoload(const, feature)
115-
ReloadableRequire.autoload_files << feature
89+
ReloadableRequire.autoload_features[const.to_s] = feature
11690
Ruby::Box.main.eval("Kernel.autoload(:#{const}, #{feature.dump})")
11791
end
11892
end

0 commit comments

Comments
 (0)