module Zeitwerk::Loader::Callbacks
def on_dir_autoloaded(dir)
autoloaded.
Invoked from our decorated Kernel#require when a managed directory is
def on_dir_autoloaded(dir) e#autoload does not serialize concurrent requires in CRuby < 3.2, and ndle directories ourselves without going through Kernel#require, so allback needs to account for concurrency. -threading would introduce a race condition here in which thread t1 ivifies the module, and while autoloads for its children are being thread t2 autoloads the same namespace. ut the mutex and subsequent delete call, t2 would reset the module. not only would reassign the constant (undesirable per se) but, worse, odule object created by t2 wouldn't have any of the autoloads for its ren, since t1 would have correctly deleted its namespace_dirs entry. toload_monitor.synchronize do ef = autoloads.delete(dir) licit_namespace = cref.set(Module.new) th = implicit_namespace.name ("module #{cpath} autovivified from directory #{dir}") if logger unload[cpath] = [dir, cref] if reloading_enabled? e don't unregister `dir` in the registry because concurrent threads ouldn't find a loader associated to it in Kernel#require and would ry to require the directory. Instead, we are going to keep track of hese to be able to unregister later if eager loading. oloaded_dirs << dir namespace_loaded(implicit_namespace) _on_load_callbacks(cpath, implicit_namespace, dir) unless on_load_callbacks.empty?
def on_file_autoloaded(file)
Invoked from our decorated Kernel#require when a managed file is autoloaded.
def on_file_autoloaded(file) autoloads.delete(file) k::Registry.unregister_autoload(file) .defined? constant #{cref.path} loaded from file #{file}") if logger load[cref.path] = [file, cref] if reloading_enabled? n_load_callbacks(cref.path, cref.get, file) unless on_load_callbacks.empty? "expected file #{file} to define constant #{cref.path}, but didn't" sg) if logger y still keeps the autoload defined, but we remove it because the tract in Zeitwerk is more strict. remove ce the expected constant was not defined, there is nothing to unload. ever, if the exception is rescued and reloading is enabled, we still d to deleted the file from $LOADED_FEATURES. load[cref.path] = [file, cref] if reloading_enabled? Zeitwerk::NameError.new(msg, cref.cname)
def on_namespace_loaded(namespace)
- Private: -
def on_namespace_loaded(namespace) if dirs = namespace_dirs.delete(real_mod_name(namespace)) dirs.each do |dir| define_autoloads_for_dir(dir, namespace) end end end
def run_on_load_callbacks(cpath, value, abspath)
def run_on_load_callbacks(cpath, value, abspath) # Order matters. If present, run the most specific one. callbacks = reloading_enabled? ? on_load_callbacks[cpath] : on_load_callbacks.delete(cpath) callbacks&.each { |c| c.call(value, abspath) } callbacks = on_load_callbacks[:ANY] callbacks&.each { |c| c.call(cpath, value, abspath) } end