lib/zeitwerk/loader/callbacks.rb in zeitwerk-2.6.11 vs lib/zeitwerk/loader/callbacks.rb in zeitwerk-2.6.12

- old
+ new

@@ -1,15 +1,15 @@ # frozen_string_literal: true module Zeitwerk::Loader::Callbacks include Zeitwerk::RealModName + extend Zeitwerk::Internal # Invoked from our decorated Kernel#require when a managed file is autoloaded. # - # @private # @sig (String) -> void - def on_file_autoloaded(file) + internal def on_file_autoloaded(file) cref = autoloads.delete(file) cpath = cpath(*cref) Zeitwerk::Registry.unregister_autoload(file) @@ -18,22 +18,29 @@ to_unload[cpath] = [file, cref] if reloading_enabled? run_on_load_callbacks(cpath, cget(*cref), file) unless on_load_callbacks.empty? else msg = "expected file #{file} to define constant #{cpath}, but didn't" log(msg) if logger + + # Ruby still keeps the autoload defined, but we remove it because the + # contract in Zeitwerk is more strict. crem(*cref) + + # Since the expected constant was not defined, there is nothing to unload. + # However, if the exception is rescued and reloading is enabled, we still + # need to deleted the file from $LOADED_FEATURES. to_unload[cpath] = [file, cref] if reloading_enabled? + raise Zeitwerk::NameError.new(msg, cref.last) end end # Invoked from our decorated Kernel#require when a managed directory is # autoloaded. # - # @private # @sig (String) -> void - def on_dir_autoloaded(dir) + internal def on_dir_autoloaded(dir) # Module#autoload does not serialize concurrent requires in CRuby < 3.2, and # we handle directories ourselves without going through Kernel#require, so # the callback needs to account for concurrency. # # Multi-threading would introduce a race condition here in which thread t1 @@ -72,10 +79,10 @@ # @private # @sig (Module) -> void def on_namespace_loaded(namespace) if dirs = namespace_dirs.delete(real_mod_name(namespace)) dirs.each do |dir| - set_autoloads_in_dir(dir, namespace) + define_autoloads_for_dir(dir, namespace) end end end private