mini-max-rb 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bootsnap-1.24.6/CHANGELOG.md +473 -0
- data/bootsnap-1.24.6/LICENSE.txt +22 -0
- data/bootsnap-1.24.6/README.md +391 -0
- data/bootsnap-1.24.6/exe/bootsnap +5 -0
- data/bootsnap-1.24.6/ext/bootsnap/bootsnap.c +1235 -0
- data/bootsnap-1.24.6/ext/bootsnap/extconf.rb +34 -0
- data/bootsnap-1.24.6/lib/bootsnap/bundler.rb +16 -0
- data/bootsnap-1.24.6/lib/bootsnap/cli/worker_pool.rb +208 -0
- data/bootsnap-1.24.6/lib/bootsnap/cli.rb +258 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/iseq.rb +229 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/ruby_bug_22023_canary.rb +1 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache/yaml.rb +344 -0
- data/bootsnap-1.24.6/lib/bootsnap/compile_cache.rb +47 -0
- data/bootsnap-1.24.6/lib/bootsnap/explicit_require.rb +56 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/cache.rb +241 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/change_observer.rb +84 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +42 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +19 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/loaded_features_index.rb +159 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/path.rb +143 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/path_scanner.rb +127 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache/store.rb +132 -0
- data/bootsnap-1.24.6/lib/bootsnap/load_path_cache.rb +80 -0
- data/bootsnap-1.24.6/lib/bootsnap/rake.rb +14 -0
- data/bootsnap-1.24.6/lib/bootsnap/setup.rb +5 -0
- data/bootsnap-1.24.6/lib/bootsnap/version.rb +5 -0
- data/bootsnap-1.24.6/lib/bootsnap.rb +202 -0
- data/mini-max-rb.gemspec +12 -0
- metadata +69 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bootsnap/bootsnap"
|
|
4
|
+
require "zlib"
|
|
5
|
+
|
|
6
|
+
module Bootsnap
|
|
7
|
+
module CompileCache
|
|
8
|
+
module ISeq
|
|
9
|
+
class << self
|
|
10
|
+
attr_reader :cache_dir
|
|
11
|
+
attr_accessor :compiler_selector, :default_compiler
|
|
12
|
+
|
|
13
|
+
def cache_dir=(cache_dir)
|
|
14
|
+
@cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}iseq" : "#{cache_dir}-iseq"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def supported?
|
|
18
|
+
CompileCache.supported? && defined?(RubyVM)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
if supported?
|
|
23
|
+
class Compiler
|
|
24
|
+
attr_reader :namespace
|
|
25
|
+
|
|
26
|
+
def initialize(namespace = nil, compile_options = nil)
|
|
27
|
+
@namespace = namespace
|
|
28
|
+
@options = compile_options.freeze
|
|
29
|
+
update_options
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def update_options
|
|
33
|
+
@compile_options = if @options.nil? || @options < RubyVM::InstructionSequence.compile_option
|
|
34
|
+
nil
|
|
35
|
+
else
|
|
36
|
+
RubyVM::InstructionSequence.compile_option.merge(@options).freeze
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
has_ruby_bug_18250 = RUBY_VERSION.start_with?("3.0.") && begin # https://bugs.ruby-lang.org/issues/18250
|
|
41
|
+
if defined? RubyVM::InstructionSequence
|
|
42
|
+
RubyVM::InstructionSequence.compile(<<~RUBY).to_binary
|
|
43
|
+
def foo(*); ->{ super }; end; def foo(**); ->{ super }; end
|
|
44
|
+
RUBY
|
|
45
|
+
end
|
|
46
|
+
false
|
|
47
|
+
rescue TypeError
|
|
48
|
+
true
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
has_ruby_bug_22023 = case RUBY_VERSION
|
|
52
|
+
when /^3\.3\./
|
|
53
|
+
true
|
|
54
|
+
when /^3\.4\.(\d+)/
|
|
55
|
+
$1.to_i < 10
|
|
56
|
+
when /^4\.0\.(\d+)/
|
|
57
|
+
$1.to_i < 4
|
|
58
|
+
else
|
|
59
|
+
false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
if has_ruby_bug_22023 && RUBY_DESCRIPTION.include?("+PRISM")
|
|
63
|
+
module PatchRubyBug22023
|
|
64
|
+
def compile_file(path, options = nil)
|
|
65
|
+
compile_file_prism(path, options)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
has_ruby_bug_22023_bis = !RubyVM::InstructionSequence.compile_file_prism(
|
|
69
|
+
File.expand_path("../ruby_bug_22023_canary.rb", __FILE__),
|
|
70
|
+
{frozen_string_literal: true},
|
|
71
|
+
).eval.frozen?
|
|
72
|
+
|
|
73
|
+
if has_ruby_bug_22023_bis
|
|
74
|
+
def compile_file_prism(path, options = nil)
|
|
75
|
+
compile_prism(::File.read(path, encoding: Encoding::UTF_8), path, path, nil, options)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
RubyVM::InstructionSequence.singleton_class.prepend(PatchRubyBug22023)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
if has_ruby_bug_18250
|
|
83
|
+
def input_to_storage(_, path)
|
|
84
|
+
iseq = RubyVM::InstructionSequence.compile_file(path, @compile_options)
|
|
85
|
+
iseq.to_binary
|
|
86
|
+
rescue TypeError, SyntaxError # Ruby [Bug #18250] & [Bug #22023]
|
|
87
|
+
UNCOMPILABLE
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
def input_to_storage(_, path)
|
|
91
|
+
RubyVM::InstructionSequence.compile_file(path, @compile_options).to_binary
|
|
92
|
+
rescue SyntaxError # Ruby [Bug #22023]
|
|
93
|
+
UNCOMPILABLE
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def storage_to_output(binary, _args)
|
|
98
|
+
iseq = RubyVM::InstructionSequence.load_from_binary(binary)
|
|
99
|
+
binary.clear
|
|
100
|
+
iseq
|
|
101
|
+
rescue RuntimeError => error
|
|
102
|
+
if error.message == "broken binary format"
|
|
103
|
+
$stderr.puts("[Bootsnap::CompileCache] warning: rejecting broken binary")
|
|
104
|
+
nil
|
|
105
|
+
else
|
|
106
|
+
raise
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def input_to_output(source, path, _kwargs)
|
|
111
|
+
if @compile_options
|
|
112
|
+
if source
|
|
113
|
+
RubyVM::InstructionSequence.compile(
|
|
114
|
+
source.force_encoding(Encoding.default_external),
|
|
115
|
+
path,
|
|
116
|
+
path,
|
|
117
|
+
nil,
|
|
118
|
+
@compile_options,
|
|
119
|
+
)
|
|
120
|
+
else
|
|
121
|
+
RubyVM::InstructionSequence.compile_file(path, @compile_options)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
DEFAULT = Compiler.new
|
|
128
|
+
FROZEN_STRING_LITERAL = Compiler.new("-fstr", {frozen_string_literal: true}.freeze)
|
|
129
|
+
COVERAGE_SUPPORTED = RUBY_VERSION >= "4.0.4"
|
|
130
|
+
|
|
131
|
+
@default_compiler = DEFAULT
|
|
132
|
+
@coverage_support_warning_emitted = false
|
|
133
|
+
|
|
134
|
+
def self.fetch(path, cache_dir: ISeq.cache_dir)
|
|
135
|
+
compiler = compiler_selector&.call(path) || default_compiler
|
|
136
|
+
|
|
137
|
+
# Having coverage enabled prevents iseq dumping/loading.
|
|
138
|
+
if coverage_on?
|
|
139
|
+
return nil if compiler.equal?(DEFAULT)
|
|
140
|
+
|
|
141
|
+
if COVERAGE_SUPPORTED
|
|
142
|
+
return compiler.input_to_output(nil, path.to_s, nil)
|
|
143
|
+
elsif !@coverage_support_warning_emitted
|
|
144
|
+
@coverage_support_warning_emitted = true
|
|
145
|
+
warn(<<~MSG)
|
|
146
|
+
Using `Bootsnap.enable_frozen_string_literal` with code coverage enabled is only supported on Ruby 4.0.4+.
|
|
147
|
+
Files loaded while coverage is on, will have mutable string literals.
|
|
148
|
+
MSG
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
return nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
Bootsnap::CompileCache::Native.fetch(
|
|
155
|
+
cache_dir,
|
|
156
|
+
compiler.namespace,
|
|
157
|
+
path.to_s,
|
|
158
|
+
compiler,
|
|
159
|
+
nil,
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def self.precompile(path)
|
|
164
|
+
compiler = compiler_selector&.call(path) || default_compiler
|
|
165
|
+
Bootsnap::CompileCache::Native.precompile(
|
|
166
|
+
cache_dir,
|
|
167
|
+
compiler.namespace,
|
|
168
|
+
path.to_s,
|
|
169
|
+
compiler,
|
|
170
|
+
)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if RUBY_VERSION < "3.1."
|
|
174
|
+
def self.coverage_on?
|
|
175
|
+
defined?(Coverage) && Coverage.running?
|
|
176
|
+
end
|
|
177
|
+
else
|
|
178
|
+
def self.coverage_on?
|
|
179
|
+
defined?(Coverage) && Coverage.state != :idle
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
module InstructionSequenceMixin
|
|
184
|
+
def load_iseq(path)
|
|
185
|
+
Bootsnap::CompileCache::ISeq.fetch(path.to_s)
|
|
186
|
+
rescue RuntimeError => error
|
|
187
|
+
if error.message.include?("unmatched platform")
|
|
188
|
+
puts("unmatched platform for file #{path}")
|
|
189
|
+
end
|
|
190
|
+
raise
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def compile_option=(hash)
|
|
194
|
+
super
|
|
195
|
+
Bootsnap::CompileCache::ISeq.compile_option_updated
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def self.compile_option_updated
|
|
200
|
+
option = RubyVM::InstructionSequence.compile_option
|
|
201
|
+
crc = Zlib.crc32(option.inspect)
|
|
202
|
+
Bootsnap::CompileCache::Native.compile_option_crc32 = crc
|
|
203
|
+
FROZEN_STRING_LITERAL.update_options
|
|
204
|
+
end
|
|
205
|
+
compile_option_updated if supported?
|
|
206
|
+
|
|
207
|
+
def self.install!(cache_dir)
|
|
208
|
+
Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
|
|
209
|
+
|
|
210
|
+
return unless supported?
|
|
211
|
+
|
|
212
|
+
Bootsnap::CompileCache::ISeq.compile_option_updated
|
|
213
|
+
|
|
214
|
+
class << RubyVM::InstructionSequence
|
|
215
|
+
prepend(InstructionSequenceMixin)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
else
|
|
219
|
+
def self.install!(...)
|
|
220
|
+
# noop
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def self.precompile(...)
|
|
224
|
+
# noop
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
_ = "test"
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bootsnap/bootsnap"
|
|
4
|
+
|
|
5
|
+
module Bootsnap
|
|
6
|
+
module CompileCache
|
|
7
|
+
module YAML
|
|
8
|
+
Uncompilable = Class.new(StandardError)
|
|
9
|
+
UnsupportedTags = Class.new(Uncompilable)
|
|
10
|
+
|
|
11
|
+
SUPPORTED_INTERNAL_ENCODINGS = [
|
|
12
|
+
nil, # UTF-8
|
|
13
|
+
Encoding::UTF_8,
|
|
14
|
+
Encoding::ASCII,
|
|
15
|
+
Encoding::BINARY,
|
|
16
|
+
].freeze
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
attr_accessor(:msgpack_factory, :supported_options)
|
|
20
|
+
attr_reader(:implementation, :cache_dir)
|
|
21
|
+
|
|
22
|
+
def cache_dir=(cache_dir)
|
|
23
|
+
@cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}yaml" : "#{cache_dir}-yaml"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def precompile(path)
|
|
27
|
+
return false unless CompileCache::YAML.supported_internal_encoding?
|
|
28
|
+
|
|
29
|
+
CompileCache::Native.precompile(
|
|
30
|
+
cache_dir,
|
|
31
|
+
nil,
|
|
32
|
+
path.to_s,
|
|
33
|
+
@implementation,
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def install!(cache_dir)
|
|
38
|
+
self.cache_dir = cache_dir
|
|
39
|
+
init!
|
|
40
|
+
::YAML.singleton_class.prepend(@implementation::Patch)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Psych coerce strings to `Encoding.default_internal` but Message Pack only support
|
|
44
|
+
# UTF-8, US-ASCII and BINARY. So if Encoding.default_internal is set to anything else
|
|
45
|
+
# we can't safely use the cache
|
|
46
|
+
def supported_internal_encoding?
|
|
47
|
+
SUPPORTED_INTERNAL_ENCODINGS.include?(Encoding.default_internal)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
module EncodingAwareSymbols
|
|
51
|
+
extend self
|
|
52
|
+
|
|
53
|
+
def unpack(payload)
|
|
54
|
+
(+payload).force_encoding(Encoding::UTF_8).to_sym
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def init!
|
|
59
|
+
require "yaml"
|
|
60
|
+
require "msgpack"
|
|
61
|
+
require "date"
|
|
62
|
+
|
|
63
|
+
@implementation = ::YAML::VERSION >= "4" ? Psych4 : Psych3
|
|
64
|
+
if @implementation::Patch.method_defined?(:unsafe_load_file) && !::YAML.respond_to?(:unsafe_load_file)
|
|
65
|
+
@implementation::Patch.send(:remove_method, :unsafe_load_file)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
unless const_defined?(:NoTagsVisitor)
|
|
69
|
+
visitor = Class.new(Psych::Visitors::NoAliasRuby) do
|
|
70
|
+
def visit(target)
|
|
71
|
+
if target.tag
|
|
72
|
+
raise UnsupportedTags, "YAML tags are not supported: #{target.tag}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
super
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
const_set(:NoTagsVisitor, visitor)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# MessagePack serializes symbols as strings by default.
|
|
82
|
+
# We want them to roundtrip cleanly, so we use a custom factory.
|
|
83
|
+
# see: https://github.com/msgpack/msgpack-ruby/pull/122
|
|
84
|
+
factory = MessagePack::Factory.new
|
|
85
|
+
factory.register_type(
|
|
86
|
+
0x00,
|
|
87
|
+
Symbol,
|
|
88
|
+
packer: :to_msgpack_ext,
|
|
89
|
+
unpacker: EncodingAwareSymbols.method(:unpack).to_proc,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if defined? MessagePack::Timestamp
|
|
93
|
+
factory.register_type(
|
|
94
|
+
MessagePack::Timestamp::TYPE, # or just -1
|
|
95
|
+
Time,
|
|
96
|
+
packer: MessagePack::Time::Packer,
|
|
97
|
+
unpacker: MessagePack::Time::Unpacker,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
marshal_fallback = {
|
|
101
|
+
packer: ->(value) { Marshal.dump(value) },
|
|
102
|
+
unpacker: ->(payload) { Marshal.load(payload) },
|
|
103
|
+
}
|
|
104
|
+
{
|
|
105
|
+
Date => 0x01,
|
|
106
|
+
Regexp => 0x02,
|
|
107
|
+
}.each do |type, code|
|
|
108
|
+
factory.register_type(code, type, marshal_fallback)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
self.msgpack_factory = factory
|
|
113
|
+
|
|
114
|
+
self.supported_options = []
|
|
115
|
+
params = ::YAML.method(:load).parameters
|
|
116
|
+
if params.include?([:key, :symbolize_names])
|
|
117
|
+
supported_options << :symbolize_names
|
|
118
|
+
end
|
|
119
|
+
if params.include?([:key, :freeze]) && factory.load(factory.dump("yaml"), freeze: true).frozen?
|
|
120
|
+
supported_options << :freeze
|
|
121
|
+
end
|
|
122
|
+
supported_options.freeze
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def patch
|
|
126
|
+
@implementation::Patch
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def strict_load(payload)
|
|
130
|
+
ast = ::YAML.parse(payload)
|
|
131
|
+
return ast unless ast
|
|
132
|
+
|
|
133
|
+
loader = ::Psych::ClassLoader::Restricted.new(["Symbol"], [])
|
|
134
|
+
scanner = ::Psych::ScalarScanner.new(loader)
|
|
135
|
+
|
|
136
|
+
NoTagsVisitor.new(scanner, loader).visit(ast)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
module Psych4
|
|
141
|
+
extend self
|
|
142
|
+
|
|
143
|
+
def input_to_storage(contents, _)
|
|
144
|
+
obj = SafeLoad.input_to_storage(contents, nil)
|
|
145
|
+
if UNCOMPILABLE.equal?(obj)
|
|
146
|
+
obj = UnsafeLoad.input_to_storage(contents, nil)
|
|
147
|
+
end
|
|
148
|
+
obj
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
module UnsafeLoad
|
|
152
|
+
extend self
|
|
153
|
+
|
|
154
|
+
def input_to_storage(contents, _)
|
|
155
|
+
obj = ::YAML.unsafe_load(contents)
|
|
156
|
+
packer = CompileCache::YAML.msgpack_factory.packer
|
|
157
|
+
packer.pack(false) # not safe loaded
|
|
158
|
+
begin
|
|
159
|
+
packer.pack(obj)
|
|
160
|
+
rescue NoMethodError, RangeError
|
|
161
|
+
return UNCOMPILABLE # The object included things that we can't serialize
|
|
162
|
+
end
|
|
163
|
+
packer.to_s
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def storage_to_output(data, kwargs)
|
|
167
|
+
if kwargs&.key?(:symbolize_names)
|
|
168
|
+
kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
|
|
172
|
+
unpacker.feed(data)
|
|
173
|
+
_safe_loaded = unpacker.unpack
|
|
174
|
+
result = unpacker.unpack
|
|
175
|
+
data.clear
|
|
176
|
+
result
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def input_to_output(data, _path, kwargs)
|
|
180
|
+
::YAML.unsafe_load(data, **(kwargs || {}))
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
module SafeLoad
|
|
185
|
+
extend self
|
|
186
|
+
|
|
187
|
+
def input_to_storage(contents, _)
|
|
188
|
+
obj = begin
|
|
189
|
+
CompileCache::YAML.strict_load(contents)
|
|
190
|
+
rescue Psych::DisallowedClass, Psych::BadAlias, Uncompilable
|
|
191
|
+
return UNCOMPILABLE
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
packer = CompileCache::YAML.msgpack_factory.packer
|
|
195
|
+
packer.pack(true) # safe loaded
|
|
196
|
+
begin
|
|
197
|
+
packer.pack(obj)
|
|
198
|
+
rescue NoMethodError, RangeError
|
|
199
|
+
return UNCOMPILABLE
|
|
200
|
+
end
|
|
201
|
+
packer.to_s
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def storage_to_output(data, kwargs)
|
|
205
|
+
if kwargs&.key?(:symbolize_names)
|
|
206
|
+
kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
|
|
210
|
+
unpacker.feed(data)
|
|
211
|
+
safe_loaded = unpacker.unpack
|
|
212
|
+
if safe_loaded
|
|
213
|
+
unpacker.unpack
|
|
214
|
+
else
|
|
215
|
+
UNCOMPILABLE
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def input_to_output(data, _path, kwargs)
|
|
220
|
+
::YAML.load(data, **(kwargs || {}))
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
module Patch
|
|
225
|
+
def load_file(path, *args)
|
|
226
|
+
return super unless CompileCache::YAML.supported_internal_encoding?
|
|
227
|
+
|
|
228
|
+
return super if args.size > 1
|
|
229
|
+
|
|
230
|
+
if (kwargs = args.first)
|
|
231
|
+
return super unless kwargs.is_a?(Hash)
|
|
232
|
+
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
CompileCache::Native.fetch(
|
|
236
|
+
CompileCache::YAML.cache_dir,
|
|
237
|
+
nil,
|
|
238
|
+
File.realpath(path),
|
|
239
|
+
CompileCache::YAML::Psych4::SafeLoad,
|
|
240
|
+
kwargs,
|
|
241
|
+
)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
|
|
245
|
+
|
|
246
|
+
def unsafe_load_file(path, *args)
|
|
247
|
+
return super unless CompileCache::YAML.supported_internal_encoding?
|
|
248
|
+
|
|
249
|
+
return super if args.size > 1
|
|
250
|
+
|
|
251
|
+
if (kwargs = args.first)
|
|
252
|
+
return super unless kwargs.is_a?(Hash)
|
|
253
|
+
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
CompileCache::Native.fetch(
|
|
257
|
+
CompileCache::YAML.cache_dir,
|
|
258
|
+
nil,
|
|
259
|
+
File.realpath(path),
|
|
260
|
+
CompileCache::YAML::Psych4::UnsafeLoad,
|
|
261
|
+
kwargs,
|
|
262
|
+
)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
module Psych3
|
|
270
|
+
extend self
|
|
271
|
+
|
|
272
|
+
def input_to_storage(contents, _)
|
|
273
|
+
obj = ::YAML.load(contents)
|
|
274
|
+
packer = CompileCache::YAML.msgpack_factory.packer
|
|
275
|
+
packer.pack(false) # not safe loaded
|
|
276
|
+
begin
|
|
277
|
+
packer.pack(obj)
|
|
278
|
+
rescue NoMethodError, RangeError
|
|
279
|
+
return UNCOMPILABLE # The object included things that we can't serialize
|
|
280
|
+
end
|
|
281
|
+
packer.to_s
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def storage_to_output(data, kwargs)
|
|
285
|
+
if kwargs&.key?(:symbolize_names)
|
|
286
|
+
kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
|
|
287
|
+
end
|
|
288
|
+
unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
|
|
289
|
+
unpacker.feed(data)
|
|
290
|
+
_safe_loaded = unpacker.unpack
|
|
291
|
+
unpacker.unpack
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def input_to_output(data, _path, kwargs)
|
|
295
|
+
::YAML.load(data, **(kwargs || {}))
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
module Patch
|
|
299
|
+
def load_file(path, *args)
|
|
300
|
+
return super unless CompileCache::YAML.supported_internal_encoding?
|
|
301
|
+
|
|
302
|
+
return super if args.size > 1
|
|
303
|
+
|
|
304
|
+
if (kwargs = args.first)
|
|
305
|
+
return super unless kwargs.is_a?(Hash)
|
|
306
|
+
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
CompileCache::Native.fetch(
|
|
310
|
+
CompileCache::YAML.cache_dir,
|
|
311
|
+
nil,
|
|
312
|
+
File.realpath(path),
|
|
313
|
+
CompileCache::YAML::Psych3,
|
|
314
|
+
kwargs,
|
|
315
|
+
)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
|
|
319
|
+
|
|
320
|
+
def unsafe_load_file(path, *args)
|
|
321
|
+
return super unless CompileCache::YAML.supported_internal_encoding?
|
|
322
|
+
|
|
323
|
+
return super if args.size > 1
|
|
324
|
+
|
|
325
|
+
if (kwargs = args.first)
|
|
326
|
+
return super unless kwargs.is_a?(Hash)
|
|
327
|
+
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
CompileCache::Native.fetch(
|
|
331
|
+
CompileCache::YAML.cache_dir,
|
|
332
|
+
nil,
|
|
333
|
+
File.realpath(path),
|
|
334
|
+
CompileCache::YAML::Psych3,
|
|
335
|
+
kwargs,
|
|
336
|
+
)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
end
|
|
344
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bootsnap
|
|
4
|
+
module CompileCache
|
|
5
|
+
UNCOMPILABLE = BasicObject.new
|
|
6
|
+
def UNCOMPILABLE.inspect
|
|
7
|
+
"<Bootsnap::UNCOMPILABLE>"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
Error = Class.new(StandardError)
|
|
11
|
+
|
|
12
|
+
def self.setup(cache_dir:, iseq:, yaml:, json: (json_unset = true), readonly: false, revalidation: false)
|
|
13
|
+
unless json_unset
|
|
14
|
+
warn("Bootsnap::CompileCache.setup `json` argument is deprecated and has no effect")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
if iseq
|
|
18
|
+
if supported?
|
|
19
|
+
require_relative "compile_cache/iseq"
|
|
20
|
+
Bootsnap::CompileCache::ISeq.install!(cache_dir)
|
|
21
|
+
elsif $VERBOSE
|
|
22
|
+
warn("[bootsnap/setup] bytecode caching is not supported on this implementation of Ruby")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
if yaml
|
|
27
|
+
if supported?
|
|
28
|
+
require_relative "compile_cache/yaml"
|
|
29
|
+
Bootsnap::CompileCache::YAML.install!(cache_dir)
|
|
30
|
+
elsif $VERBOSE
|
|
31
|
+
warn("[bootsnap/setup] YAML parsing caching is not supported on this implementation of Ruby")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if supported? && defined?(Bootsnap::CompileCache::Native)
|
|
36
|
+
Bootsnap::CompileCache::Native.readonly = readonly
|
|
37
|
+
Bootsnap::CompileCache::Native.revalidation = revalidation
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.supported?
|
|
42
|
+
# only enable on 'ruby' (MRI) and TruffleRuby for POSIX (darwin, linux, *bsd), Windows (RubyInstaller2)
|
|
43
|
+
%w[ruby truffleruby].include?(RUBY_ENGINE) &&
|
|
44
|
+
RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Bootsnap
|
|
4
|
+
module ExplicitRequire
|
|
5
|
+
ARCHDIR = RbConfig::CONFIG["archdir"]
|
|
6
|
+
RUBYLIBDIR = RbConfig::CONFIG["rubylibdir"]
|
|
7
|
+
DLEXT = RbConfig::CONFIG["DLEXT"]
|
|
8
|
+
|
|
9
|
+
def self.from_self(feature)
|
|
10
|
+
require_relative("../#{feature}")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.from_rubylibdir(feature)
|
|
14
|
+
require(File.join(RUBYLIBDIR, "#{feature}.rb"))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.from_archdir(feature)
|
|
18
|
+
require(File.join(ARCHDIR, "#{feature}.#{DLEXT}"))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Given a set of gems, run a block with the LOAD_PATH narrowed to include
|
|
22
|
+
# only core ruby source paths and these gems -- that is, roughly,
|
|
23
|
+
# temporarily remove all gems not listed in this call from the LOAD_PATH.
|
|
24
|
+
#
|
|
25
|
+
# This is useful before bootsnap is fully-initialized to load gems that it
|
|
26
|
+
# depends on, without forcing full LOAD_PATH traversals.
|
|
27
|
+
def self.with_gems(*gems)
|
|
28
|
+
# Ensure the gems are activated (their paths are in $LOAD_PATH)
|
|
29
|
+
gems.each do |gem_name|
|
|
30
|
+
gem gem_name
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
orig = $LOAD_PATH.dup
|
|
34
|
+
$LOAD_PATH.clear
|
|
35
|
+
gems.each do |gem|
|
|
36
|
+
pat = %r{
|
|
37
|
+
/
|
|
38
|
+
(gems|extensions/[^/]+/[^/]+) # "gems" or "extensions/x64_64-darwin16/2.3.0"
|
|
39
|
+
/
|
|
40
|
+
#{Regexp.escape(gem)}-(\h{12}|(\d+\.)) # msgpack-1.2.3 or msgpack-1234567890ab
|
|
41
|
+
}x
|
|
42
|
+
$LOAD_PATH.concat(orig.grep(pat))
|
|
43
|
+
end
|
|
44
|
+
$LOAD_PATH << ARCHDIR
|
|
45
|
+
$LOAD_PATH << RUBYLIBDIR
|
|
46
|
+
begin
|
|
47
|
+
yield
|
|
48
|
+
rescue LoadError
|
|
49
|
+
$LOAD_PATH.replace(orig)
|
|
50
|
+
yield
|
|
51
|
+
end
|
|
52
|
+
ensure
|
|
53
|
+
$LOAD_PATH.replace(orig)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|