99module 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