File: //lib/ruby/vendor_ruby/bootsnap/load_path_cache/change_observer.rb
# frozen_string_literal: true
module Bootsnap
module LoadPathCache
module ChangeObserver
module ArrayMixin
# For each method that adds items to one end or another of the array
# (<<, push, unshift, concat), override that method to also notify the
# observer of the change.
def <<(entry)
@lpc_observer.push_paths(self, entry.to_s)
super
end
def push(*entries)
@lpc_observer.push_paths(self, *entries.map(&:to_s))
super
end
alias_method :append, :push
def unshift(*entries)
@lpc_observer.unshift_paths(self, *entries.map(&:to_s))
super
end
alias_method :prepend, :unshift
def concat(entries)
@lpc_observer.push_paths(self, *entries.map(&:to_s))
super
end
# uniq! keeps the first occurrence of each path, otherwise preserving
# order, preserving the effective load path
def uniq!(*args)
ret = super
@lpc_observer.reinitialize if block_given? || !args.empty?
ret
end
# For each method that modifies the array more aggressively, override
# the method to also have the observer completely reconstruct its state
# after the modification. Many of these could be made to modify the
# internal state of the LoadPathCache::Cache more efficiently, but the
# accounting cost would be greater than the hit from these, since we
# actively discourage calling them.
%i(
[]= clear collect! compact! delete delete_at delete_if fill flatten!
insert keep_if map! pop reject! replace reverse! rotate! select!
shift shuffle! slice! sort! sort_by!
).each do |method_name|
define_method(method_name) do |*args, &block|
ret = super(*args, &block)
@lpc_observer.reinitialize
ret
end
end
end
def self.register(observer, arr)
return if arr.frozen? # can't register observer, but no need to.
arr.instance_variable_set(:@lpc_observer, observer)
arr.extend(ArrayMixin)
end
end
end
end