bootsnap 1.9.0 → 1.9.4
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 +4 -4
- data/CHANGELOG.md +24 -0
- data/lib/bootsnap/cli.rb +1 -1
- data/lib/bootsnap/compile_cache/iseq.rb +29 -4
- data/lib/bootsnap/compile_cache.rb +1 -1
- data/lib/bootsnap/load_path_cache/cache.rb +22 -18
- data/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb +3 -19
- data/lib/bootsnap/load_path_cache/loaded_features_index.rb +15 -2
- data/lib/bootsnap/load_path_cache/store.rb +15 -3
- data/lib/bootsnap/version.rb +1 -1
- data/lib/bootsnap.rb +10 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7602567343afc549df266a1b3def7e8c1e755b03a9ce486d17bba7051e97dfda
|
4
|
+
data.tar.gz: 607abfa5738cb016172bba2eb94af48b80b9e73dddea1090be77b7ca7d9f121d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7effd658adb07d075cfbc883f47382c23f774a872fcfa2daa0b137ff5f903057a1f825a90cd96cd5784a2e72fcb583ce05b4fcf98201a2a2cb6830c90109e096
|
7
|
+
data.tar.gz: ed2f42c2e5e91c373c8882fbe17abfab93c43e6ab39b83a7aa3031d6dba48088da9c3a271b52bbb7bc83ace117d677ec25e4865936972d939a00b08580f5e45e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 1.9.4
|
4
|
+
|
5
|
+
* Ignore absolute paths in the loaded feature index. (#385)
|
6
|
+
This fixes a compatibility issue with Zeitwerk when Zeitwerk is loaded before bootsnap. It also should
|
7
|
+
reduce the memory usage and improve load performance of Zeitwerk managed files.
|
8
|
+
|
9
|
+
* Automatically invalidate the load path cache whenever the Ruby version change. (#387)
|
10
|
+
This is to avoid issues in case the same installation path is re-used for subsequent ruby patch releases.
|
11
|
+
|
12
|
+
# 1.9.3
|
13
|
+
|
14
|
+
* Only disable the compile cache for source files impacted by [Ruby 3.0.3 [Bug 18250]](https://bugs.ruby-lang.org/issues/18250).
|
15
|
+
This should keep the performance loss to a minimum.
|
16
|
+
|
17
|
+
# 1.9.2
|
18
|
+
|
19
|
+
* Disable compile cache if [Ruby 3.0.3's ISeq cache bug](https://bugs.ruby-lang.org/issues/18250) is detected.
|
20
|
+
AKA `iseq.rb:13 to_binary: wrong argument type false (expected Symbol)`
|
21
|
+
* Fix `Kernel.load` behavior: before `load 'a'` would load `a.rb` (and other tried extensions) and wouldn't load `a` unless `development_mode: true`, now only `a` would be loaded and files with extensions wouldn't be.
|
22
|
+
|
23
|
+
# 1.9.1
|
24
|
+
|
25
|
+
* Removed a forgotten debug statement in JSON precompilation.
|
26
|
+
|
3
27
|
# 1.9.0
|
4
28
|
|
5
29
|
* Added a compilation cache for `JSON.load_file`. (#370)
|
data/lib/bootsnap/cli.rb
CHANGED
@@ -161,7 +161,7 @@ module Bootsnap
|
|
161
161
|
|
162
162
|
def precompile_json(*json_files)
|
163
163
|
Array(json_files).each do |json_file|
|
164
|
-
if
|
164
|
+
if CompileCache::JSON.precompile(json_file, cache_dir: cache_dir)
|
165
165
|
STDERR.puts(json_file) if verbose
|
166
166
|
end
|
167
167
|
end
|
@@ -9,10 +9,35 @@ module Bootsnap
|
|
9
9
|
attr_accessor(:cache_dir)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
RubyVM::InstructionSequence
|
14
|
-
|
15
|
-
|
12
|
+
has_ruby_bug_18250 = begin # https://bugs.ruby-lang.org/issues/18250
|
13
|
+
if defined? RubyVM::InstructionSequence
|
14
|
+
RubyVM::InstructionSequence.compile("def foo(*); ->{ super }; end; def foo(**); ->{ super }; end").to_binary
|
15
|
+
end
|
16
|
+
false
|
17
|
+
rescue TypeError
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
if has_ruby_bug_18250
|
22
|
+
def self.input_to_storage(_, path)
|
23
|
+
iseq = begin
|
24
|
+
RubyVM::InstructionSequence.compile_file(path)
|
25
|
+
rescue SyntaxError
|
26
|
+
raise(Uncompilable, 'syntax error')
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
iseq.to_binary
|
31
|
+
rescue TypeError
|
32
|
+
raise(Uncompilable, 'ruby bug #18250')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
def self.input_to_storage(_, path)
|
37
|
+
RubyVM::InstructionSequence.compile_file(path).to_binary
|
38
|
+
rescue SyntaxError
|
39
|
+
raise(Uncompilable, 'syntax error')
|
40
|
+
end
|
16
41
|
end
|
17
42
|
|
18
43
|
def self.storage_to_output(binary, _args)
|
@@ -28,7 +28,7 @@ module Bootsnap
|
|
28
28
|
require_relative('compile_cache/json')
|
29
29
|
Bootsnap::CompileCache::JSON.install!(cache_dir)
|
30
30
|
elsif $VERBOSE
|
31
|
-
warn("[bootsnap/setup]
|
31
|
+
warn("[bootsnap/setup] JSON parsing caching is not supported on this implementation of Ruby")
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -44,14 +44,20 @@ module Bootsnap
|
|
44
44
|
|
45
45
|
# Try to resolve this feature to an absolute path without traversing the
|
46
46
|
# loadpath.
|
47
|
-
def find(feature)
|
47
|
+
def find(feature, try_extensions: true)
|
48
48
|
reinitialize if (@has_relative_paths && dir_changed?) || stale?
|
49
49
|
feature = feature.to_s.freeze
|
50
|
-
|
51
|
-
return
|
50
|
+
|
51
|
+
return feature if Bootsnap.absolute_path?(feature)
|
52
|
+
|
53
|
+
if feature.start_with?('./', '../')
|
54
|
+
return try_extensions ? expand_path(feature) : File.expand_path(feature).freeze
|
55
|
+
end
|
56
|
+
|
52
57
|
@mutex.synchronize do
|
53
|
-
x = search_index(feature)
|
58
|
+
x = search_index(feature, try_extensions: try_extensions)
|
54
59
|
return x if x
|
60
|
+
return unless try_extensions
|
55
61
|
|
56
62
|
# Ruby has some built-in features that require lies about.
|
57
63
|
# For example, 'enumerator' is built in. If you require it, ruby
|
@@ -92,16 +98,6 @@ module Bootsnap
|
|
92
98
|
raise(LoadPathCache::FallbackScan, '', []) if @development_mode
|
93
99
|
end
|
94
100
|
|
95
|
-
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
96
|
-
def absolute_path?(path)
|
97
|
-
path[1] == ':'
|
98
|
-
end
|
99
|
-
else
|
100
|
-
def absolute_path?(path)
|
101
|
-
path.start_with?(SLASH)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
101
|
def unshift_paths(sender, *paths)
|
106
102
|
return unless sender == @path_obj
|
107
103
|
@mutex.synchronize { unshift_paths_locked(*paths) }
|
@@ -177,16 +173,24 @@ module Bootsnap
|
|
177
173
|
end
|
178
174
|
|
179
175
|
if DLEXT2
|
180
|
-
def search_index(f)
|
181
|
-
|
176
|
+
def search_index(f, try_extensions: true)
|
177
|
+
if try_extensions
|
178
|
+
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || try_index(f)
|
179
|
+
else
|
180
|
+
try_index(f)
|
181
|
+
end
|
182
182
|
end
|
183
183
|
|
184
184
|
def maybe_append_extension(f)
|
185
185
|
try_ext(f + DOT_RB) || try_ext(f + DLEXT) || try_ext(f + DLEXT2) || f
|
186
186
|
end
|
187
187
|
else
|
188
|
-
def search_index(f)
|
189
|
-
|
188
|
+
def search_index(f, try_extensions: true)
|
189
|
+
if try_extensions
|
190
|
+
try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f)
|
191
|
+
else
|
192
|
+
try_index(f)
|
193
|
+
end
|
190
194
|
end
|
191
195
|
|
192
196
|
def maybe_append_extension(f)
|
@@ -56,25 +56,9 @@ module Kernel
|
|
56
56
|
|
57
57
|
alias_method(:load_without_bootsnap, :load)
|
58
58
|
def load(path, wrap = false)
|
59
|
-
if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path))
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# load also allows relative paths from pwd even when not in $:
|
64
|
-
if File.exist?(relative = File.expand_path(path).freeze)
|
65
|
-
return load_without_bootsnap(relative, wrap)
|
66
|
-
end
|
67
|
-
|
68
|
-
raise(Bootsnap::LoadPathCache::CoreExt.make_load_error(path))
|
69
|
-
rescue LoadError => e
|
70
|
-
e.instance_variable_set(Bootsnap::LoadPathCache::ERROR_TAG_IVAR, true)
|
71
|
-
raise(e)
|
72
|
-
rescue Bootsnap::LoadPathCache::ReturnFalse
|
73
|
-
false
|
74
|
-
rescue Bootsnap::LoadPathCache::FallbackScan
|
75
|
-
fallback = true
|
76
|
-
ensure
|
77
|
-
if fallback
|
59
|
+
if (resolved = Bootsnap::LoadPathCache.load_path_cache.find(path, try_extensions: false))
|
60
|
+
load_without_bootsnap(resolved, wrap)
|
61
|
+
else
|
78
62
|
load_without_bootsnap(path, wrap)
|
79
63
|
end
|
80
64
|
end
|
@@ -83,11 +83,24 @@ module Bootsnap
|
|
83
83
|
# 2. Inspect $LOADED_FEATURES upon return from yield to find the matching
|
84
84
|
# entry.
|
85
85
|
def register(short, long = nil)
|
86
|
+
# Absolute paths are not a concern.
|
87
|
+
if Bootsnap.absolute_path?(short.to_s)
|
88
|
+
return yield
|
89
|
+
end
|
90
|
+
|
86
91
|
if long.nil?
|
87
|
-
pat = %r{/#{Regexp.escape(short)}(\.[^/]+)?$}
|
88
92
|
len = $LOADED_FEATURES.size
|
89
93
|
ret = yield
|
90
|
-
long = $LOADED_FEATURES[len..-1].detect
|
94
|
+
long = $LOADED_FEATURES[len..-1].detect do |feat|
|
95
|
+
offset = 0
|
96
|
+
while offset = feat.index(short, offset)
|
97
|
+
if feat.index(".", offset + 1) && !feat.index("/", offset + 2)
|
98
|
+
break true
|
99
|
+
else
|
100
|
+
offset += 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
91
104
|
else
|
92
105
|
ret = yield
|
93
106
|
end
|
@@ -7,6 +7,9 @@ Bootsnap::ExplicitRequire.from_rubylibdir('fileutils')
|
|
7
7
|
module Bootsnap
|
8
8
|
module LoadPathCache
|
9
9
|
class Store
|
10
|
+
VERSION_KEY = '__bootsnap_ruby_version__'
|
11
|
+
CURRENT_VERSION = "#{RUBY_REVISION}-#{RUBY_PLATFORM}".freeze
|
12
|
+
|
10
13
|
NestedTransactionError = Class.new(StandardError)
|
11
14
|
SetOutsideTransactionNotAllowed = Class.new(StandardError)
|
12
15
|
|
@@ -62,15 +65,20 @@ module Bootsnap
|
|
62
65
|
|
63
66
|
def load_data
|
64
67
|
@data = begin
|
65
|
-
File.open(@store_path, encoding: Encoding::BINARY) do |io|
|
68
|
+
data = File.open(@store_path, encoding: Encoding::BINARY) do |io|
|
66
69
|
MessagePack.load(io)
|
67
70
|
end
|
71
|
+
if data.is_a?(Hash) && data[VERSION_KEY] == CURRENT_VERSION
|
72
|
+
data
|
73
|
+
else
|
74
|
+
default_data
|
75
|
+
end
|
68
76
|
# handle malformed data due to upgrade incompatibility
|
69
77
|
rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
|
70
|
-
|
78
|
+
default_data
|
71
79
|
rescue ArgumentError => error
|
72
80
|
if error.message =~ /negative array size/
|
73
|
-
|
81
|
+
default_data
|
74
82
|
else
|
75
83
|
raise
|
76
84
|
end
|
@@ -93,6 +101,10 @@ module Bootsnap
|
|
93
101
|
retry
|
94
102
|
rescue SystemCallError
|
95
103
|
end
|
104
|
+
|
105
|
+
def default_data
|
106
|
+
{ VERSION_KEY => CURRENT_VERSION }
|
107
|
+
end
|
96
108
|
end
|
97
109
|
end
|
98
110
|
end
|
data/lib/bootsnap/version.rb
CHANGED
data/lib/bootsnap.rb
CHANGED
@@ -123,4 +123,14 @@ module Bootsnap
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
126
|
+
|
127
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
128
|
+
def self.absolute_path?(path)
|
129
|
+
path[1] == ':'
|
130
|
+
end
|
131
|
+
else
|
132
|
+
def self.absolute_path?(path)
|
133
|
+
path.start_with?('/')
|
134
|
+
end
|
135
|
+
end
|
126
136
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bootsnap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|