bootsnap 1.16.0 → 1.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +6 -4
- data/ext/bootsnap/bootsnap.c +37 -23
- data/ext/bootsnap/extconf.rb +1 -1
- data/lib/bootsnap/compile_cache/iseq.rb +9 -3
- data/lib/bootsnap/compile_cache/json.rb +6 -10
- data/lib/bootsnap/compile_cache/yaml.rb +24 -40
- data/lib/bootsnap/compile_cache.rb +3 -12
- data/lib/bootsnap/load_path_cache/cache.rb +8 -0
- data/lib/bootsnap/load_path_cache/change_observer.rb +6 -0
- data/lib/bootsnap/load_path_cache/path_scanner.rb +1 -1
- data/lib/bootsnap/load_path_cache.rb +13 -4
- data/lib/bootsnap/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a17ea0a302554fd131e2941fa8b97b1ff9441750fb4182247bb44d91aa1174e8
|
4
|
+
data.tar.gz: 9ba8386281c2dbb6896b1032e4b6a6c949b81164d54848beac032a977ee43e44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1653ddc2779d492f3e5c50719c07a0cdc7a9fab27748dd82096ec923232f9c8b04ddbee738325d13a3aa8c87a38825581677408512437e12933fe18434bcdce
|
7
|
+
data.tar.gz: 9c0f5d4fe058c13577d97011083b7bab23b290cd16b955937b00aaafb5a62239532df4e0d090e576c85dae45dcf504ffa63f9fedd5b2c5dca67afc4457cdbb59
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 1.17.0
|
4
|
+
|
5
|
+
* Ensure `$LOAD_PATH.dup` is Ractor shareable to fix an conflit with `did_you_mean`.
|
6
|
+
* Allow to ignore direcotries using absolute paths.
|
7
|
+
* Support YAML and JSON CompileCache on TruffleRuby.
|
8
|
+
* Support LoadPathCache on TruffleRuby.
|
9
|
+
|
3
10
|
# 1.16.0
|
4
11
|
|
5
12
|
* Use `RbConfig::CONFIG["rubylibdir"]` instead of `RbConfig::CONFIG["libdir"]` to check for stdlib files. See #431.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Bootsnap [![Actions Status](https://github.com/Shopify/bootsnap/workflows/ci/badge.svg)](https://github.com/Shopify/bootsnap/actions)
|
2
2
|
|
3
|
-
Bootsnap is a library that plugs into Ruby, with optional support for `YAML`,
|
3
|
+
Bootsnap is a library that plugs into Ruby, with optional support for `YAML` and `JSON`,
|
4
4
|
to optimize and cache expensive computations. See [How Does This Work](#how-does-this-work).
|
5
5
|
|
6
6
|
#### Performance
|
@@ -57,6 +57,7 @@ Bootsnap.setup(
|
|
57
57
|
load_path_cache: true, # Optimize the LOAD_PATH with a cache
|
58
58
|
compile_cache_iseq: true, # Compile Ruby code into ISeq cache, breaks coverage reporting.
|
59
59
|
compile_cache_yaml: true, # Compile YAML into a cache
|
60
|
+
compile_cache_json: true, # Compile JSON into a cache
|
60
61
|
readonly: true, # Use the caches but don't update them on miss or stale entries.
|
61
62
|
)
|
62
63
|
```
|
@@ -119,6 +120,7 @@ into two broad categories:
|
|
119
120
|
compilation.
|
120
121
|
* `YAML.load_file` is modified to cache the result of loading a YAML object in MessagePack format
|
121
122
|
(or Marshal, if the message uses types unsupported by MessagePack).
|
123
|
+
* `JSON.load_file` is modified to cache the result of loading a JSON object in MessagePack format
|
122
124
|
|
123
125
|
### Path Pre-Scanning
|
124
126
|
|
@@ -189,9 +191,9 @@ translated ruby source to an internal bytecode format, which is then executed by
|
|
189
191
|
allows caching that bytecode. This allows us to bypass the relatively-expensive compilation step on
|
190
192
|
subsequent loads of the same file.
|
191
193
|
|
192
|
-
We also noticed that we spend a lot of time loading YAML documents during our application boot, and
|
193
|
-
that MessagePack and Marshal are *much* faster at deserialization than YAML, even with a fast
|
194
|
-
implementation. We use the same strategy of compilation caching for YAML documents, with the
|
194
|
+
We also noticed that we spend a lot of time loading YAML and JSON documents during our application boot, and
|
195
|
+
that MessagePack and Marshal are *much* faster at deserialization than YAML and JSON, even with a fast
|
196
|
+
implementation. We use the same strategy of compilation caching for YAML and JSON documents, with the
|
195
197
|
equivalent of Ruby's "bytecode" format being a MessagePack document (or, in the case of YAML
|
196
198
|
documents with types unsupported by MessagePack, a Marshal stream).
|
197
199
|
|
data/ext/bootsnap/bootsnap.c
CHANGED
@@ -377,7 +377,9 @@ open_current_file(char * path, struct bs_cache_key * key, const char ** errno_pr
|
|
377
377
|
|
378
378
|
if (fstat(fd, &statbuf) < 0) {
|
379
379
|
*errno_provenance = "bs_fetch:open_current_file:fstat";
|
380
|
+
int previous_errno = errno;
|
380
381
|
close(fd);
|
382
|
+
errno = previous_errno;
|
381
383
|
return -1;
|
382
384
|
}
|
383
385
|
|
@@ -467,7 +469,6 @@ open_cache_file(const char * path, struct bs_cache_key * key, const char ** errn
|
|
467
469
|
static int
|
468
470
|
fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE * output_data, int * exception_tag, const char ** errno_provenance)
|
469
471
|
{
|
470
|
-
char * data = NULL;
|
471
472
|
ssize_t nread;
|
472
473
|
int ret;
|
473
474
|
|
@@ -479,8 +480,8 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
|
|
479
480
|
ret = ERROR_WITH_ERRNO;
|
480
481
|
goto done;
|
481
482
|
}
|
482
|
-
|
483
|
-
nread = read(fd,
|
483
|
+
storage_data = rb_str_buf_new(data_size);
|
484
|
+
nread = read(fd, RSTRING_PTR(storage_data), data_size);
|
484
485
|
if (nread < 0) {
|
485
486
|
*errno_provenance = "bs_fetch:fetch_cached_data:read";
|
486
487
|
ret = ERROR_WITH_ERRNO;
|
@@ -491,7 +492,7 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
|
|
491
492
|
goto done;
|
492
493
|
}
|
493
494
|
|
494
|
-
storage_data
|
495
|
+
rb_str_set_len(storage_data, nread);
|
495
496
|
|
496
497
|
*exception_tag = bs_storage_to_output(handler, args, storage_data, output_data);
|
497
498
|
if (*output_data == rb_cBootsnap_CompileCache_UNCOMPILABLE) {
|
@@ -500,7 +501,6 @@ fetch_cached_data(int fd, ssize_t data_size, VALUE handler, VALUE args, VALUE *
|
|
500
501
|
}
|
501
502
|
ret = 0;
|
502
503
|
done:
|
503
|
-
if (data != NULL) xfree(data);
|
504
504
|
return ret;
|
505
505
|
}
|
506
506
|
|
@@ -607,17 +607,22 @@ atomic_write_cache_file(char * path, struct bs_cache_key * key, VALUE data, cons
|
|
607
607
|
|
608
608
|
|
609
609
|
/* Read contents from an fd, whose contents are asserted to be +size+ bytes
|
610
|
-
* long,
|
611
|
-
static
|
612
|
-
bs_read_contents(int fd, size_t size,
|
610
|
+
* long, returning a Ruby string on success and Qfalse on failure */
|
611
|
+
static VALUE
|
612
|
+
bs_read_contents(int fd, size_t size, const char ** errno_provenance)
|
613
613
|
{
|
614
|
+
VALUE contents;
|
614
615
|
ssize_t nread;
|
615
|
-
|
616
|
-
nread = read(fd,
|
616
|
+
contents = rb_str_buf_new(size);
|
617
|
+
nread = read(fd, RSTRING_PTR(contents), size);
|
618
|
+
|
617
619
|
if (nread < 0) {
|
618
620
|
*errno_provenance = "bs_fetch:bs_read_contents:read";
|
621
|
+
return Qfalse;
|
622
|
+
} else {
|
623
|
+
rb_str_set_len(contents, nread);
|
624
|
+
return contents;
|
619
625
|
}
|
620
|
-
return nread;
|
621
626
|
}
|
622
627
|
|
623
628
|
/*
|
@@ -668,7 +673,6 @@ static VALUE
|
|
668
673
|
bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args)
|
669
674
|
{
|
670
675
|
struct bs_cache_key cached_key, current_key;
|
671
|
-
char * contents = NULL;
|
672
676
|
int cache_fd = -1, current_fd = -1;
|
673
677
|
int res, valid_cache = 0, exception_tag = 0;
|
674
678
|
const char * errno_provenance = NULL;
|
@@ -678,10 +682,14 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
678
682
|
VALUE output_data; /* return data, e.g. ruby hash or loaded iseq */
|
679
683
|
|
680
684
|
VALUE exception; /* ruby exception object to raise instead of returning */
|
685
|
+
VALUE exception_message; /* ruby exception string to use instead of errno_provenance */
|
681
686
|
|
682
687
|
/* Open the source file and generate a cache key for it */
|
683
688
|
current_fd = open_current_file(path, ¤t_key, &errno_provenance);
|
684
|
-
if (current_fd < 0)
|
689
|
+
if (current_fd < 0) {
|
690
|
+
exception_message = path_v;
|
691
|
+
goto fail_errno;
|
692
|
+
}
|
685
693
|
|
686
694
|
/* Open the cache key if it exists, and read its cache key in */
|
687
695
|
cache_fd = open_cache_file(cache_path, &cached_key, &errno_provenance);
|
@@ -691,6 +699,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
691
699
|
rb_funcall(rb_mBootsnap, instrumentation_method, 2, cache_fd == CACHE_MISS ? sym_miss : sym_stale, path_v);
|
692
700
|
}
|
693
701
|
} else if (cache_fd < 0) {
|
702
|
+
exception_message = rb_str_new_cstr(cache_path);
|
694
703
|
goto fail_errno;
|
695
704
|
} else {
|
696
705
|
/* True if the cache existed and no invalidating changes have occurred since
|
@@ -713,13 +722,18 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
713
722
|
else if (res == CACHE_UNCOMPILABLE) {
|
714
723
|
/* If fetch_cached_data returned `Uncompilable` we fallback to `input_to_output`
|
715
724
|
This happens if we have say, an unsafe YAML cache, but try to load it in safe mode */
|
716
|
-
if (bs_read_contents(current_fd, current_key.size, &
|
717
|
-
|
725
|
+
if ((input_data = bs_read_contents(current_fd, current_key.size, &errno_provenance)) == Qfalse){
|
726
|
+
exception_message = path_v;
|
727
|
+
goto fail_errno;
|
728
|
+
}
|
718
729
|
bs_input_to_output(handler, args, input_data, &output_data, &exception_tag);
|
719
730
|
if (exception_tag != 0) goto raise;
|
720
731
|
goto succeed;
|
721
732
|
} else if (res == CACHE_MISS || res == CACHE_STALE) valid_cache = 0;
|
722
|
-
else if (res == ERROR_WITH_ERRNO)
|
733
|
+
else if (res == ERROR_WITH_ERRNO){
|
734
|
+
exception_message = rb_str_new_cstr(cache_path);
|
735
|
+
goto fail_errno;
|
736
|
+
}
|
723
737
|
else if (!NIL_P(output_data)) goto succeed; /* fast-path, goal */
|
724
738
|
}
|
725
739
|
close(cache_fd);
|
@@ -727,8 +741,10 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
727
741
|
/* Cache is stale, invalid, or missing. Regenerate and write it out. */
|
728
742
|
|
729
743
|
/* Read the contents of the source file into a buffer */
|
730
|
-
if (bs_read_contents(current_fd, current_key.size, &
|
731
|
-
|
744
|
+
if ((input_data = bs_read_contents(current_fd, current_key.size, &errno_provenance)) == Qfalse){
|
745
|
+
exception_message = path_v;
|
746
|
+
goto fail_errno;
|
747
|
+
}
|
732
748
|
|
733
749
|
/* Try to compile the input_data using input_to_storage(input_data) */
|
734
750
|
exception_tag = bs_input_to_storage(handler, args, input_data, path_v, &storage_data);
|
@@ -765,6 +781,7 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
765
781
|
* No point raising an error */
|
766
782
|
if (errno != ENOENT) {
|
767
783
|
errno_provenance = "bs_fetch:unlink";
|
784
|
+
exception_message = rb_str_new_cstr(cache_path);
|
768
785
|
goto fail_errno;
|
769
786
|
}
|
770
787
|
}
|
@@ -775,7 +792,6 @@ bs_fetch(char * path, VALUE path_v, char * cache_path, VALUE handler, VALUE args
|
|
775
792
|
goto succeed; /* output_data is now the correct return. */
|
776
793
|
|
777
794
|
#define CLEANUP \
|
778
|
-
if (contents != NULL) xfree(contents); \
|
779
795
|
if (current_fd >= 0) close(current_fd); \
|
780
796
|
if (cache_fd >= 0) close(cache_fd);
|
781
797
|
|
@@ -784,7 +800,7 @@ succeed:
|
|
784
800
|
return output_data;
|
785
801
|
fail_errno:
|
786
802
|
CLEANUP;
|
787
|
-
exception =
|
803
|
+
exception = rb_syserr_new_str(errno, exception_message);
|
788
804
|
rb_exc_raise(exception);
|
789
805
|
__builtin_unreachable();
|
790
806
|
raise:
|
@@ -836,8 +852,7 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
836
852
|
/* Cache is stale, invalid, or missing. Regenerate and write it out. */
|
837
853
|
|
838
854
|
/* Read the contents of the source file into a buffer */
|
839
|
-
if (bs_read_contents(current_fd, current_key.size, &
|
840
|
-
input_data = rb_str_new(contents, current_key.size);
|
855
|
+
if ((input_data = bs_read_contents(current_fd, current_key.size, &errno_provenance)) == Qfalse) goto fail;
|
841
856
|
|
842
857
|
/* Try to compile the input_data using input_to_storage(input_data) */
|
843
858
|
exception_tag = bs_input_to_storage(handler, Qnil, input_data, path_v, &storage_data);
|
@@ -858,7 +873,6 @@ bs_precompile(char * path, VALUE path_v, char * cache_path, VALUE handler)
|
|
858
873
|
goto succeed;
|
859
874
|
|
860
875
|
#define CLEANUP \
|
861
|
-
if (contents != NULL) xfree(contents); \
|
862
876
|
if (current_fd >= 0) close(current_fd); \
|
863
877
|
if (cache_fd >= 0) close(cache_fd);
|
864
878
|
|
data/ext/bootsnap/extconf.rb
CHANGED
@@ -12,6 +12,10 @@ module Bootsnap
|
|
12
12
|
def cache_dir=(cache_dir)
|
13
13
|
@cache_dir = cache_dir.end_with?("/") ? "#{cache_dir}iseq" : "#{cache_dir}-iseq"
|
14
14
|
end
|
15
|
+
|
16
|
+
def supported?
|
17
|
+
CompileCache.supported? && defined?(RubyVM)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
has_ruby_bug_18250 = begin # https://bugs.ruby-lang.org/issues/18250
|
@@ -83,8 +87,6 @@ module Bootsnap
|
|
83
87
|
return nil if defined?(Coverage) && Bootsnap::CompileCache::Native.coverage_running?
|
84
88
|
|
85
89
|
Bootsnap::CompileCache::ISeq.fetch(path.to_s)
|
86
|
-
rescue Errno::EACCES
|
87
|
-
Bootsnap::CompileCache.permission_error(path)
|
88
90
|
rescue RuntimeError => error
|
89
91
|
if error.message =~ /unmatched platform/
|
90
92
|
puts("unmatched platform for file #{path}")
|
@@ -103,11 +105,15 @@ module Bootsnap
|
|
103
105
|
crc = Zlib.crc32(option.inspect)
|
104
106
|
Bootsnap::CompileCache::Native.compile_option_crc32 = crc
|
105
107
|
end
|
106
|
-
compile_option_updated
|
108
|
+
compile_option_updated if supported?
|
107
109
|
|
108
110
|
def self.install!(cache_dir)
|
109
111
|
Bootsnap::CompileCache::ISeq.cache_dir = cache_dir
|
112
|
+
|
113
|
+
return unless supported?
|
114
|
+
|
110
115
|
Bootsnap::CompileCache::ISeq.compile_option_updated
|
116
|
+
|
111
117
|
class << RubyVM::InstructionSequence
|
112
118
|
prepend(InstructionSequenceMixin)
|
113
119
|
end
|
@@ -74,16 +74,12 @@ module Bootsnap
|
|
74
74
|
return super unless (kwargs.keys - ::Bootsnap::CompileCache::JSON.supported_options).empty?
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
)
|
84
|
-
rescue Errno::EACCES
|
85
|
-
::Bootsnap::CompileCache.permission_error(path)
|
86
|
-
end
|
77
|
+
::Bootsnap::CompileCache::Native.fetch(
|
78
|
+
Bootsnap::CompileCache::JSON.cache_dir,
|
79
|
+
File.realpath(path),
|
80
|
+
::Bootsnap::CompileCache::JSON,
|
81
|
+
kwargs,
|
82
|
+
)
|
87
83
|
end
|
88
84
|
|
89
85
|
ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
|
@@ -229,16 +229,12 @@ module Bootsnap
|
|
229
229
|
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
230
230
|
end
|
231
231
|
|
232
|
-
|
233
|
-
CompileCache::
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
)
|
239
|
-
rescue Errno::EACCES
|
240
|
-
CompileCache.permission_error(path)
|
241
|
-
end
|
232
|
+
CompileCache::Native.fetch(
|
233
|
+
CompileCache::YAML.cache_dir,
|
234
|
+
File.realpath(path),
|
235
|
+
CompileCache::YAML::Psych4::SafeLoad,
|
236
|
+
kwargs,
|
237
|
+
)
|
242
238
|
end
|
243
239
|
|
244
240
|
ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
|
@@ -253,16 +249,12 @@ module Bootsnap
|
|
253
249
|
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
254
250
|
end
|
255
251
|
|
256
|
-
|
257
|
-
CompileCache::
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
)
|
263
|
-
rescue Errno::EACCES
|
264
|
-
CompileCache.permission_error(path)
|
265
|
-
end
|
252
|
+
CompileCache::Native.fetch(
|
253
|
+
CompileCache::YAML.cache_dir,
|
254
|
+
File.realpath(path),
|
255
|
+
CompileCache::YAML::Psych4::UnsafeLoad,
|
256
|
+
kwargs,
|
257
|
+
)
|
266
258
|
end
|
267
259
|
|
268
260
|
ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
|
@@ -309,16 +301,12 @@ module Bootsnap
|
|
309
301
|
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
310
302
|
end
|
311
303
|
|
312
|
-
|
313
|
-
CompileCache::
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
)
|
319
|
-
rescue Errno::EACCES
|
320
|
-
CompileCache.permission_error(path)
|
321
|
-
end
|
304
|
+
CompileCache::Native.fetch(
|
305
|
+
CompileCache::YAML.cache_dir,
|
306
|
+
File.realpath(path),
|
307
|
+
CompileCache::YAML::Psych3,
|
308
|
+
kwargs,
|
309
|
+
)
|
322
310
|
end
|
323
311
|
|
324
312
|
ruby2_keywords :load_file if respond_to?(:ruby2_keywords, true)
|
@@ -333,16 +321,12 @@ module Bootsnap
|
|
333
321
|
return super unless (kwargs.keys - CompileCache::YAML.supported_options).empty?
|
334
322
|
end
|
335
323
|
|
336
|
-
|
337
|
-
CompileCache::
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
)
|
343
|
-
rescue Errno::EACCES
|
344
|
-
CompileCache.permission_error(path)
|
345
|
-
end
|
324
|
+
CompileCache::Native.fetch(
|
325
|
+
CompileCache::YAML.cache_dir,
|
326
|
+
File.realpath(path),
|
327
|
+
CompileCache::YAML::Psych3,
|
328
|
+
kwargs,
|
329
|
+
)
|
346
330
|
end
|
347
331
|
|
348
332
|
ruby2_keywords :unsafe_load_file if respond_to?(:ruby2_keywords, true)
|
@@ -8,7 +8,6 @@ module Bootsnap
|
|
8
8
|
end
|
9
9
|
|
10
10
|
Error = Class.new(StandardError)
|
11
|
-
PermissionError = Class.new(Error)
|
12
11
|
|
13
12
|
def self.setup(cache_dir:, iseq:, yaml:, json:, readonly: false)
|
14
13
|
if iseq
|
@@ -43,18 +42,10 @@ module Bootsnap
|
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
46
|
-
def self.permission_error(path)
|
47
|
-
cpath = Bootsnap::CompileCache::ISeq.cache_dir
|
48
|
-
raise(
|
49
|
-
PermissionError,
|
50
|
-
"bootsnap doesn't have permission to write cache entries in '#{cpath}' " \
|
51
|
-
"(or, less likely, doesn't have permission to read '#{path}')",
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
45
|
def self.supported?
|
56
|
-
# only enable on 'ruby' (MRI)
|
57
|
-
|
46
|
+
# only enable on 'ruby' (MRI) and TruffleRuby for POSIX (darwin, linux, *bsd), Windows (RubyInstaller2)
|
47
|
+
%w[ruby truffleruby].include?(RUBY_ENGINE) &&
|
48
|
+
RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
|
58
49
|
end
|
59
50
|
end
|
60
51
|
end
|
@@ -24,8 +24,16 @@ module Bootsnap
|
|
24
24
|
@mutex.synchronize { @dirs[dir] }
|
25
25
|
end
|
26
26
|
|
27
|
+
TRUFFLERUBY_LIB_DIR_PREFIX = if RUBY_ENGINE == "truffleruby"
|
28
|
+
"#{File.join(RbConfig::CONFIG['libdir'], 'truffle')}#{File::SEPARATOR}"
|
29
|
+
end
|
30
|
+
|
27
31
|
# { 'enumerator' => nil, 'enumerator.so' => nil, ... }
|
28
32
|
BUILTIN_FEATURES = $LOADED_FEATURES.each_with_object({}) do |feat, features|
|
33
|
+
if TRUFFLERUBY_LIB_DIR_PREFIX && feat.start_with?(TRUFFLERUBY_LIB_DIR_PREFIX)
|
34
|
+
feat = feat.byteslice(TRUFFLERUBY_LIB_DIR_PREFIX.bytesize..-1)
|
35
|
+
end
|
36
|
+
|
29
37
|
# Builtin features are of the form 'enumerator.so'.
|
30
38
|
# All others include paths.
|
31
39
|
next unless feat.size < 20 && !feat.include?("/")
|
@@ -54,7 +54,7 @@ module Bootsnap
|
|
54
54
|
|
55
55
|
absolute_path = "#{absolute_dir_path}/#{name}"
|
56
56
|
if File.directory?(absolute_path)
|
57
|
-
next if ignored_directories.include?(name)
|
57
|
+
next if ignored_directories.include?(name) || ignored_directories.include?(absolute_path)
|
58
58
|
|
59
59
|
if yield relative_path, absolute_path, true
|
60
60
|
walk(absolute_path, relative_path, &block)
|
@@ -38,8 +38,8 @@ module Bootsnap
|
|
38
38
|
|
39
39
|
@loaded_features_index = LoadedFeaturesIndex.new
|
40
40
|
|
41
|
-
@load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
|
42
41
|
PathScanner.ignored_directories = ignore_directories if ignore_directories
|
42
|
+
@load_path_cache = Cache.new(store, $LOAD_PATH, development_mode: development_mode)
|
43
43
|
@enabled = true
|
44
44
|
require_relative("load_path_cache/core_ext/kernel_require")
|
45
45
|
require_relative("load_path_cache/core_ext/loaded_features")
|
@@ -50,12 +50,21 @@ module Bootsnap
|
|
50
50
|
@loaded_features_index = nil
|
51
51
|
@realpath_cache = nil
|
52
52
|
@load_path_cache = nil
|
53
|
-
ChangeObserver.unregister($LOAD_PATH)
|
53
|
+
ChangeObserver.unregister($LOAD_PATH) if supported?
|
54
54
|
end
|
55
55
|
|
56
56
|
def supported?
|
57
|
-
|
58
|
-
|
57
|
+
if RUBY_PLATFORM.match?(/darwin|linux|bsd|mswin|mingw|cygwin/)
|
58
|
+
case RUBY_ENGINE
|
59
|
+
when "truffleruby"
|
60
|
+
# https://github.com/oracle/truffleruby/issues/3131
|
61
|
+
RUBY_ENGINE_VERSION >= "23.1.0"
|
62
|
+
when "ruby"
|
63
|
+
true
|
64
|
+
else
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
data/lib/bootsnap/version.rb
CHANGED
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.
|
4
|
+
version: 1.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Burke Libbey
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: msgpack
|
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: '0'
|
85
85
|
requirements: []
|
86
|
-
rubygems_version: 3.
|
86
|
+
rubygems_version: 3.4.21
|
87
87
|
signing_key:
|
88
88
|
specification_version: 4
|
89
89
|
summary: Boot large ruby/rails apps faster
|