lib/bootsnap/load_path_cache/core_ext/active_support.rb
module Bootsnap module LoadPathCache module CoreExt module ActiveSupport def self.with_bootsnap_fallback(error) yield rescue error => e # NoMethodError is a NameError, but we only want to handle actual # NameError instances. raise unless e.class == error without_bootsnap_cache { yield } end def self.without_bootsnap_cache prev = Thread.current[:without_bootsnap_cache] || false Thread.current[:without_bootsnap_cache] = true yield ensure Thread.current[:without_bootsnap_cache] = prev end module ClassMethods def autoload_paths=(o) r = super Bootsnap::LoadPathCache.autoload_paths_cache.reinitialize(o) r end def search_for_file(path) return super if Thread.current[:without_bootsnap_cache] begin Bootsnap::LoadPathCache.autoload_paths_cache.find(path) rescue Bootsnap::LoadPathCache::ReturnFalse nil # doesn't really apply here end end def autoloadable_module?(path_suffix) Bootsnap::LoadPathCache.autoload_paths_cache.has_dir?(path_suffix) end def remove_constant(const) CoreExt::ActiveSupport.without_bootsnap_cache { super } end # If we can't find a constant using the patched implementation of # search_for_file, try again with the default implementation. # # These methods call search_for_file, and we want to modify its # behaviour. The gymnastics here are a bit awkward, but it prevents # 200+ lines of monkeypatches. def load_missing_constant(from_mod, const_name) CoreExt::ActiveSupport.with_bootsnap_fallback(NameError) { super } end # Signature has changed a few times over the years; easiest to not # reiterate it with version polymorphism here... def depend_on(*) CoreExt::ActiveSupport.with_bootsnap_fallback(LoadError) { super } end end end end end end module ActiveSupport module Dependencies class << self prepend Bootsnap::LoadPathCache::CoreExt::ActiveSupport::ClassMethods end end end