bootsnap 1.9.0 → 1.9.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40e9beab427c546339a38041cdc59b826389b30d1976fb9586b6782daf728ed3
4
- data.tar.gz: 1cfa891e84615fe3ed6d76a8c222420568c9ddb09077378199f6ba8862789d9f
3
+ metadata.gz: 7602567343afc549df266a1b3def7e8c1e755b03a9ce486d17bba7051e97dfda
4
+ data.tar.gz: 607abfa5738cb016172bba2eb94af48b80b9e73dddea1090be77b7ca7d9f121d
5
5
  SHA512:
6
- metadata.gz: 5d74ccbd9cadf8fa00e6cef7c4159a34448a2f5e8fb0b94b6e63ee3b0032f1555ca613706821236965ad6f005f00eb305727e6eb62a6125c449a419bbb1db34a
7
- data.tar.gz: 5a2e9d7e599797747370bbf3733ed442a795f69f040f2fa5db0736132de815a4c6a82254cf988602aec47c10fbfb73e696bf752581723a83b241a22f5d08b2c2
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 p(CompileCache::JSON.precompile(json_file, cache_dir: cache_dir))
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
- def self.input_to_storage(_, path)
13
- RubyVM::InstructionSequence.compile_file(path).to_binary
14
- rescue SyntaxError
15
- raise(Uncompilable, 'syntax error')
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] YAML parsing caching is not supported on this implementation of Ruby")
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
- return feature if absolute_path?(feature)
51
- return expand_path(feature) if feature.start_with?('./')
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
- try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f + DLEXT2) || try_index(f)
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
- try_index(f + DOT_RB) || try_index(f + DLEXT) || try_index(f)
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
- return load_without_bootsnap(resolved, wrap)
61
- end
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 { |feat| feat =~ pat }
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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Bootsnap
3
- VERSION = "1.9.0"
3
+ VERSION = "1.9.4"
4
4
  end
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.0
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: 2021-09-16 00:00:00.000000000 Z
11
+ date: 2022-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler