Module: RequireHooks
- Defined in:
- lib/require-hooks/api.rb,
lib/require-hooks/version.rb,
lib/require-hooks/mode/bootsnap.rb,
lib/require-hooks/mode/load_iseq.rb,
lib/require-hooks/mode/kernel_patch.rb
Defined Under Namespace
Modules: Bootsnap, KernelPatch, LoadIseq Classes: Context
Constant Summary collapse
- VERSION =
"0.3.0"- EMPTY_ISEQ =
RubyVM::InstructionSequence.compile("").freeze
- @@default_context =
Context.new
- @@noop_context =
Context.new
- @@contexts =
{}
Class Attribute Summary collapse
-
.print_warnings ⇒ Object
Returns the value of attribute print_warnings.
Class Method Summary collapse
-
.around_load(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
Define a block to wrap the code loading.
- .context_for(path) ⇒ Object
-
.hijack_load(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
This hook should be used to manually compile byte code to be loaded by the VM.
-
.source_transform(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
Define hooks to perform source-to-source transformations.
Class Attribute Details
.print_warnings ⇒ Object
Returns the value of attribute print_warnings.
80 81 82 |
# File 'lib/require-hooks/api.rb', line 80 def print_warnings @print_warnings end |
Class Method Details
.around_load(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
Define a block to wrap the code loading. The return value MUST be a result of calling the passed block. For example, you can use such hooks for instrumentation, debugging purposes.
RequireHooks.around_load do |path, &block|
puts "Loading #{path}"
block.call.tap { puts "Loaded #{path}" }
end
90 91 92 93 94 95 96 97 98 |
# File 'lib/require-hooks/api.rb', line 90 def around_load(patterns: nil, exclude_patterns: nil, &block) @@default_context = nil ctx = Context.new(patterns: patterns, exclude_patterns: exclude_patterns) @@contexts[ctx.to_key] ||= ctx @@contexts[ctx.to_key].around_load << block @@default_context = @@contexts.values.first if @@contexts.size == 1 end |
.context_for(path) ⇒ Object
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/require-hooks/api.rb', line 144 def context_for(path) # Fast-track in case we have just a single context defined if @@default_context return @@noop_context unless @@default_context.match?(path) return @@default_context end matching = @@contexts.values.select { |ctx| ctx.match?(path) } return matching[0] || @@noop_context if matching.size < 2 ctx = Context.new matching.each do |mctx| ctx.around_load.concat(mctx.around_load) ctx.source_transform.concat(mctx.source_transform) ctx.hijack_load.concat(mctx.hijack_load) end ctx end |
.hijack_load(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
This hook should be used to manually compile byte code to be loaded by the VM. The arguments are (path, source = nil), where source is only defined if transformations took place. Otherwise, you MUST read the source code from the file yourself.
The return value MUST be either nil (continue to the next hook or default behavior) or a platform-specific bytecode object (e.g., RubyVM::InstructionSequence).
RequireHooks.hijack_load do |path, source|
source ||= File.read(path)
if defined?(RubyVM::InstructionSequence)
RubyVM::InstructionSequence.compile(source)
elsif defined?(JRUBY_VERSION)
JRuby.compile(source)
end
end
134 135 136 137 138 139 140 141 142 |
# File 'lib/require-hooks/api.rb', line 134 def hijack_load(patterns: nil, exclude_patterns: nil, &block) @@default_context = nil ctx = Context.new(patterns: patterns, exclude_patterns: exclude_patterns) @@contexts[ctx.to_key] ||= ctx @@contexts[ctx.to_key].hijack_load << block @@default_context = @@contexts.values.first if @@contexts.size == 1 end |
.source_transform(patterns: nil, exclude_patterns: nil, &block) ⇒ Object
Define hooks to perform source-to-source transformations. The return value MUST be either String (new source code) or nil (indicating that no transformations were performed).
NOTE: The second argument (‘source`) MAY be nil, indicating that no transformer tried to transform the source code.
For example, you can prepend each file with ‘# frozen_string_literal: true` pragma:
RequireHooks.source_transform do |path, source|
"# frozen_string_literal: true\n#{source}"
end
110 111 112 113 114 115 116 117 118 |
# File 'lib/require-hooks/api.rb', line 110 def source_transform(patterns: nil, exclude_patterns: nil, &block) @@default_context = nil ctx = Context.new(patterns: patterns, exclude_patterns: exclude_patterns) @@contexts[ctx.to_key] ||= ctx @@contexts[ctx.to_key].source_transform << block @@default_context = @@contexts.values.first if @@contexts.size == 1 end |