ed-precompiled_bootsnap 1.18.6-x86_64-linux

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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +401 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +358 -0
  5. data/exe/bootsnap +5 -0
  6. data/ext/bootsnap/bootsnap.c +1135 -0
  7. data/ext/bootsnap/bootsnap.h +6 -0
  8. data/ext/bootsnap/extconf.rb +33 -0
  9. data/lib/bootsnap/3.0/bootsnap.so +0 -0
  10. data/lib/bootsnap/3.1/bootsnap.so +0 -0
  11. data/lib/bootsnap/3.2/bootsnap.so +0 -0
  12. data/lib/bootsnap/3.3/bootsnap.so +0 -0
  13. data/lib/bootsnap/3.4/bootsnap.so +0 -0
  14. data/lib/bootsnap/bootsnap.so +0 -0
  15. data/lib/bootsnap/bootsnap_ext.rb +7 -0
  16. data/lib/bootsnap/bundler.rb +16 -0
  17. data/lib/bootsnap/cli/worker_pool.rb +208 -0
  18. data/lib/bootsnap/cli.rb +285 -0
  19. data/lib/bootsnap/compile_cache/iseq.rb +123 -0
  20. data/lib/bootsnap/compile_cache/json.rb +89 -0
  21. data/lib/bootsnap/compile_cache/yaml.rb +337 -0
  22. data/lib/bootsnap/compile_cache.rb +52 -0
  23. data/lib/bootsnap/explicit_require.rb +56 -0
  24. data/lib/bootsnap/load_path_cache/cache.rb +244 -0
  25. data/lib/bootsnap/load_path_cache/change_observer.rb +84 -0
  26. data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +37 -0
  27. data/lib/bootsnap/load_path_cache/core_ext/loaded_features.rb +19 -0
  28. data/lib/bootsnap/load_path_cache/loaded_features_index.rb +159 -0
  29. data/lib/bootsnap/load_path_cache/path.rb +136 -0
  30. data/lib/bootsnap/load_path_cache/path_scanner.rb +81 -0
  31. data/lib/bootsnap/load_path_cache/store.rb +132 -0
  32. data/lib/bootsnap/load_path_cache.rb +80 -0
  33. data/lib/bootsnap/setup.rb +5 -0
  34. data/lib/bootsnap/version.rb +5 -0
  35. data/lib/bootsnap.rb +164 -0
  36. metadata +96 -0
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bootsnap/bootsnap_ext"
4
+
5
+ module Bootsnap
6
+ module CompileCache
7
+ module JSON
8
+ class << self
9
+ attr_accessor(:msgpack_factory, :supported_options)
10
+ attr_reader(:cache_dir)
11
+
12
+ def cache_dir=(cache_dir)
13
+ @cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}json" : "#{cache_dir}-json"
14
+ end
15
+
16
+ def input_to_storage(payload, _)
17
+ obj = ::JSON.parse(payload)
18
+ msgpack_factory.dump(obj)
19
+ end
20
+
21
+ def storage_to_output(data, kwargs)
22
+ if kwargs&.key?(:symbolize_names)
23
+ kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
24
+ end
25
+ msgpack_factory.load(data, kwargs)
26
+ end
27
+
28
+ def input_to_output(data, kwargs)
29
+ ::JSON.parse(data, **(kwargs || {}))
30
+ end
31
+
32
+ def precompile(path)
33
+ Bootsnap::CompileCache::Native.precompile(
34
+ cache_dir,
35
+ path.to_s,
36
+ self,
37
+ )
38
+ end
39
+
40
+ def install!(cache_dir)
41
+ self.cache_dir = cache_dir
42
+ init!
43
+ if ::JSON.respond_to?(:load_file)
44
+ ::JSON.singleton_class.prepend(Patch)
45
+ end
46
+ end
47
+
48
+ def init!
49
+ require "json"
50
+ require "msgpack"
51
+
52
+ self.msgpack_factory = MessagePack::Factory.new
53
+ self.supported_options = [:symbolize_names]
54
+ if supports_freeze?
55
+ self.supported_options = [:freeze]
56
+ end
57
+ supported_options.freeze
58
+ end
59
+
60
+ private
61
+
62
+ def supports_freeze?
63
+ ::JSON.parse('["foo"]', freeze: true).first.frozen? &&
64
+ MessagePack.load(MessagePack.dump("foo"), freeze: true).frozen?
65
+ end
66
+ end
67
+
68
+ module Patch
69
+ def load_file(path, *args)
70
+ return super if args.size > 1
71
+
72
+ if (kwargs = args.first)
73
+ return super unless kwargs.is_a?(Hash)
74
+ return super unless (kwargs.keys - ::Bootsnap::CompileCache::JSON.supported_options).empty?
75
+ end
76
+
77
+ ::Bootsnap::CompileCache::Native.fetch(
78
+ Bootsnap::CompileCache::JSON.cache_dir,
79
+ File.realpath(path),
80
+ ::Bootsnap::CompileCache::JSON,
81
+ kwargs,
82
+ )
83
+ end
84
+
85
+ ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,337 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bootsnap/bootsnap_ext"
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
+ path.to_s,
32
+ @implementation,
33
+ )
34
+ end
35
+
36
+ def install!(cache_dir)
37
+ self.cache_dir = cache_dir
38
+ init!
39
+ ::YAML.singleton_class.prepend(@implementation::Patch)
40
+ end
41
+
42
+ # Psych coerce strings to `Encoding.default_internal` but Message Pack only support
43
+ # UTF-8, US-ASCII and BINARY. So if Encoding.default_internal is set to anything else
44
+ # we can't safely use the cache
45
+ def supported_internal_encoding?
46
+ SUPPORTED_INTERNAL_ENCODINGS.include?(Encoding.default_internal)
47
+ end
48
+
49
+ module EncodingAwareSymbols
50
+ extend self
51
+
52
+ def unpack(payload)
53
+ (+payload).force_encoding(Encoding::UTF_8).to_sym
54
+ end
55
+ end
56
+
57
+ def init!
58
+ require "yaml"
59
+ require "msgpack"
60
+ require "date"
61
+
62
+ @implementation = ::YAML::VERSION >= "4" ? Psych4 : Psych3
63
+ if @implementation::Patch.method_defined?(:unsafe_load_file) && !::YAML.respond_to?(:unsafe_load_file)
64
+ @implementation::Patch.send(:remove_method, :unsafe_load_file)
65
+ end
66
+
67
+ unless const_defined?(:NoTagsVisitor)
68
+ visitor = Class.new(Psych::Visitors::NoAliasRuby) do
69
+ def visit(target)
70
+ if target.tag
71
+ raise UnsupportedTags, "YAML tags are not supported: #{target.tag}"
72
+ end
73
+
74
+ super
75
+ end
76
+ end
77
+ const_set(:NoTagsVisitor, visitor)
78
+ end
79
+
80
+ # MessagePack serializes symbols as strings by default.
81
+ # We want them to roundtrip cleanly, so we use a custom factory.
82
+ # see: https://github.com/msgpack/msgpack-ruby/pull/122
83
+ factory = MessagePack::Factory.new
84
+ factory.register_type(
85
+ 0x00,
86
+ Symbol,
87
+ packer: :to_msgpack_ext,
88
+ unpacker: EncodingAwareSymbols.method(:unpack).to_proc,
89
+ )
90
+
91
+ if defined? MessagePack::Timestamp
92
+ factory.register_type(
93
+ MessagePack::Timestamp::TYPE, # or just -1
94
+ Time,
95
+ packer: MessagePack::Time::Packer,
96
+ unpacker: MessagePack::Time::Unpacker,
97
+ )
98
+
99
+ marshal_fallback = {
100
+ packer: ->(value) { Marshal.dump(value) },
101
+ unpacker: ->(payload) { Marshal.load(payload) },
102
+ }
103
+ {
104
+ Date => 0x01,
105
+ Regexp => 0x02,
106
+ }.each do |type, code|
107
+ factory.register_type(code, type, marshal_fallback)
108
+ end
109
+ end
110
+
111
+ self.msgpack_factory = factory
112
+
113
+ self.supported_options = []
114
+ params = ::YAML.method(:load).parameters
115
+ if params.include?([:key, :symbolize_names])
116
+ supported_options << :symbolize_names
117
+ end
118
+ if params.include?([:key, :freeze]) && factory.load(factory.dump("yaml"), freeze: true).frozen?
119
+ supported_options << :freeze
120
+ end
121
+ supported_options.freeze
122
+ end
123
+
124
+ def patch
125
+ @implementation::Patch
126
+ end
127
+
128
+ def strict_load(payload)
129
+ ast = ::YAML.parse(payload)
130
+ return ast unless ast
131
+
132
+ loader = ::Psych::ClassLoader::Restricted.new(["Symbol"], [])
133
+ scanner = ::Psych::ScalarScanner.new(loader)
134
+
135
+ NoTagsVisitor.new(scanner, loader).visit(ast)
136
+ end
137
+ end
138
+
139
+ module Psych4
140
+ extend self
141
+
142
+ def input_to_storage(contents, _)
143
+ obj = SafeLoad.input_to_storage(contents, nil)
144
+ if UNCOMPILABLE.equal?(obj)
145
+ obj = UnsafeLoad.input_to_storage(contents, nil)
146
+ end
147
+ obj
148
+ end
149
+
150
+ module UnsafeLoad
151
+ extend self
152
+
153
+ def input_to_storage(contents, _)
154
+ obj = ::YAML.unsafe_load(contents)
155
+ packer = CompileCache::YAML.msgpack_factory.packer
156
+ packer.pack(false) # not safe loaded
157
+ begin
158
+ packer.pack(obj)
159
+ rescue NoMethodError, RangeError
160
+ return UNCOMPILABLE # The object included things that we can't serialize
161
+ end
162
+ packer.to_s
163
+ end
164
+
165
+ def storage_to_output(data, kwargs)
166
+ if kwargs&.key?(:symbolize_names)
167
+ kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
168
+ end
169
+
170
+ unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
171
+ unpacker.feed(data)
172
+ _safe_loaded = unpacker.unpack
173
+ unpacker.unpack
174
+ end
175
+
176
+ def input_to_output(data, kwargs)
177
+ ::YAML.unsafe_load(data, **(kwargs || {}))
178
+ end
179
+ end
180
+
181
+ module SafeLoad
182
+ extend self
183
+
184
+ def input_to_storage(contents, _)
185
+ obj = begin
186
+ CompileCache::YAML.strict_load(contents)
187
+ rescue Psych::DisallowedClass, Psych::BadAlias, Uncompilable
188
+ return UNCOMPILABLE
189
+ end
190
+
191
+ packer = CompileCache::YAML.msgpack_factory.packer
192
+ packer.pack(true) # safe loaded
193
+ begin
194
+ packer.pack(obj)
195
+ rescue NoMethodError, RangeError
196
+ return UNCOMPILABLE
197
+ end
198
+ packer.to_s
199
+ end
200
+
201
+ def storage_to_output(data, kwargs)
202
+ if kwargs&.key?(:symbolize_names)
203
+ kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
204
+ end
205
+
206
+ unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
207
+ unpacker.feed(data)
208
+ safe_loaded = unpacker.unpack
209
+ if safe_loaded
210
+ unpacker.unpack
211
+ else
212
+ UNCOMPILABLE
213
+ end
214
+ end
215
+
216
+ def input_to_output(data, kwargs)
217
+ ::YAML.load(data, **(kwargs || {}))
218
+ end
219
+ end
220
+
221
+ module Patch
222
+ def load_file(path, *args)
223
+ return super unless CompileCache::YAML.supported_internal_encoding?
224
+
225
+ return super if args.size > 1
226
+
227
+ if (kwargs = args.first)
228
+ return super unless kwargs.is_a?(Hash)
229
+ return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
230
+ end
231
+
232
+ CompileCache::Native.fetch(
233
+ CompileCache::YAML.cache_dir,
234
+ File.realpath(path),
235
+ CompileCache::YAML::Psych4::SafeLoad,
236
+ kwargs,
237
+ )
238
+ end
239
+
240
+ ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
241
+
242
+ def unsafe_load_file(path, *args)
243
+ return super unless CompileCache::YAML.supported_internal_encoding?
244
+
245
+ return super if args.size > 1
246
+
247
+ if (kwargs = args.first)
248
+ return super unless kwargs.is_a?(Hash)
249
+ return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
250
+ end
251
+
252
+ CompileCache::Native.fetch(
253
+ CompileCache::YAML.cache_dir,
254
+ File.realpath(path),
255
+ CompileCache::YAML::Psych4::UnsafeLoad,
256
+ kwargs,
257
+ )
258
+ end
259
+
260
+ ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
261
+ end
262
+ end
263
+
264
+ module Psych3
265
+ extend self
266
+
267
+ def input_to_storage(contents, _)
268
+ obj = ::YAML.load(contents)
269
+ packer = CompileCache::YAML.msgpack_factory.packer
270
+ packer.pack(false) # not safe loaded
271
+ begin
272
+ packer.pack(obj)
273
+ rescue NoMethodError, RangeError
274
+ return UNCOMPILABLE # The object included things that we can't serialize
275
+ end
276
+ packer.to_s
277
+ end
278
+
279
+ def storage_to_output(data, kwargs)
280
+ if kwargs&.key?(:symbolize_names)
281
+ kwargs[:symbolize_keys] = kwargs.delete(:symbolize_names)
282
+ end
283
+ unpacker = CompileCache::YAML.msgpack_factory.unpacker(kwargs)
284
+ unpacker.feed(data)
285
+ _safe_loaded = unpacker.unpack
286
+ unpacker.unpack
287
+ end
288
+
289
+ def input_to_output(data, kwargs)
290
+ ::YAML.load(data, **(kwargs || {}))
291
+ end
292
+
293
+ module Patch
294
+ def load_file(path, *args)
295
+ return super unless CompileCache::YAML.supported_internal_encoding?
296
+
297
+ return super if args.size > 1
298
+
299
+ if (kwargs = args.first)
300
+ return super unless kwargs.is_a?(Hash)
301
+ return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
302
+ end
303
+
304
+ CompileCache::Native.fetch(
305
+ CompileCache::YAML.cache_dir,
306
+ File.realpath(path),
307
+ CompileCache::YAML::Psych3,
308
+ kwargs,
309
+ )
310
+ end
311
+
312
+ ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
313
+
314
+ def unsafe_load_file(path, *args)
315
+ return super unless CompileCache::YAML.supported_internal_encoding?
316
+
317
+ return super if args.size > 1
318
+
319
+ if (kwargs = args.first)
320
+ return super unless kwargs.is_a?(Hash)
321
+ return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
322
+ end
323
+
324
+ CompileCache::Native.fetch(
325
+ CompileCache::YAML.cache_dir,
326
+ File.realpath(path),
327
+ CompileCache::YAML::Psych3,
328
+ kwargs,
329
+ )
330
+ end
331
+
332
+ ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end
@@ -0,0 +1,52 @@
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:, readonly: false, revalidation: false)
13
+ if iseq
14
+ if supported?
15
+ require_relative "compile_cache/iseq"
16
+ Bootsnap::CompileCache::ISeq.install!(cache_dir)
17
+ elsif $VERBOSE
18
+ warn("[bootsnap/setup] bytecode caching is not supported on this implementation of Ruby")
19
+ end
20
+ end
21
+
22
+ if yaml
23
+ if supported?
24
+ require_relative "compile_cache/yaml"
25
+ Bootsnap::CompileCache::YAML.install!(cache_dir)
26
+ elsif $VERBOSE
27
+ warn("[bootsnap/setup] YAML parsing caching is not supported on this implementation of Ruby")
28
+ end
29
+ end
30
+
31
+ if json
32
+ if supported?
33
+ require_relative "compile_cache/json"
34
+ Bootsnap::CompileCache::JSON.install!(cache_dir)
35
+ elsif $VERBOSE
36
+ warn("[bootsnap/setup] JSON parsing caching is not supported on this implementation of Ruby")
37
+ end
38
+ end
39
+
40
+ if supported? && defined?(Bootsnap::CompileCache::Native)
41
+ Bootsnap::CompileCache::Native.readonly = readonly
42
+ Bootsnap::CompileCache::Native.revalidation = revalidation
43
+ end
44
+ end
45
+
46
+ def self.supported?
47
+ # only enable on 'ruby' (MRI) and TruffleRuby for POSIX (darwin, linux, *bsd), Windows (RubyInstaller2)
48
+ %w[ruby truffleruby].include?(RUBY_ENGINE) &&
49
+ RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
50
+ end
51
+ end
52
+ 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