Module: RequireHooks::Bootsnap

Defined in:
lib/require-hooks/mode/bootsnap.rb

Defined Under Namespace

Modules: CompileCacheExt, LegacyCacheExt, LoadIseqExt Classes: VersionedCompiler

Constant Summary collapse

EMPTY_ISEQ =
RubyVM::InstructionSequence.compile("").freeze

Class Method Summary collapse

Class Method Details

.add_version_hash(value = nil, &block) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/require-hooks/mode/bootsnap.rb', line 131

def add_version_hash(value = nil, &block)
  contributor = block || value
  unless contributor.is_a?(String) || contributor.respond_to?(:call)
    raise ArgumentError, "version hash contribution must be a String or callable"
  end

  @version_hash_contributors ||= []
  @version_hash_contributors << (contributor.is_a?(String) ? contributor.dup.freeze : contributor)
  @compilers&.clear
  contributor
end

.compiler_for(path) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/require-hooks/mode/bootsnap.rb', line 119

def compiler_for(path)
  iseq = ::Bootsnap::CompileCache::ISeq
  compiler = @original_compiler_selector&.call(path) || iseq.default_compiler
  return compiler if RequireHooks.context_for(path).empty?

  version_hash = RequireHooks::Bootsnap.version_hash
  cached = @compilers[compiler]
  return cached if cached&.version_hash == version_hash

  @compilers[compiler] = VersionedCompiler.new(compiler, version_hash)
end

.install_compiler_selectorObject



112
113
114
115
116
117
# File 'lib/require-hooks/mode/bootsnap.rb', line 112

def install_compiler_selector
  iseq = ::Bootsnap::CompileCache::ISeq
  @original_compiler_selector = iseq.compiler_selector
  @compilers = {}.compare_by_identity
  iseq.compiler_selector = method(:compiler_for)
end

.version_hashObject



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/require-hooks/mode/bootsnap.rb', line 143

def version_hash
  return @version_hash unless @version_hash.nil?

  context_keys = RequireHooks.contexts.values.map(&:to_cache_key)
  contribution_keys = Array(@version_hash_contributors).map do |contributor|
    value = contributor.respond_to?(:call) ? contributor.call : contributor
    raise TypeError, "version hash contribution must return a String" unless value.is_a?(String)

    Zlib.crc32(value).to_s
  end.sort

  (context_keys + contribution_keys).join("-")
end

.version_hash=(version_hash) ⇒ Object



157
158
159
160
# File 'lib/require-hooks/mode/bootsnap.rb', line 157

def version_hash=(version_hash)
  @version_hash = version_hash
  @compilers&.clear
end