zeitwerk 1.4.0 → 1.4.1

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: a7e867060d3bf347938f153335a463ddbb48995f70f3aed8472a6641e2592a71
4
- data.tar.gz: af10438f14e119bf184133b1c1734e01fbe61954ce2128805a1ab941125dc4cf
3
+ metadata.gz: d3e5a11bbda38b569f50eabcaf7dd6e53ce209120b5d1b4f2a933edae9230d14
4
+ data.tar.gz: 52107af4754d7cc305c1978172920eb7b8c180b4d8660080902143a422287ad2
5
5
  SHA512:
6
- metadata.gz: a744a32914b0bd02c07842b448770512d6a8aad66b5524bbe9bb6ef854faeea1ce11e2090bc9a968aebb3501d54de54f65f7927f9d26d4f365a13ad806920e38
7
- data.tar.gz: 032c50fd06d88be03ee5fae4d7fd6bdbd34780b5dc1f978a8a63a3a9bdda960d417dcb91b40bb82865d3c58b6751cf58506c1bed2454c65c14c6c1d2b5f7bdc7
6
+ metadata.gz: 8133b49d1231e2f2c797c02151787b0fbb95eba0c9a573ae90ea2e722a736f583876820296536e6206bd711f2d23789fc867e55e34771968a005e74352df43c2
7
+ data.tar.gz: 243a54e0a4e5c947851271c196617cfd113cdcc2795de00dc9c5d6909351825a92e15f868880584d1ce84d6e0168219c109bad1d83a64b82c25af9a18beeb903
data/README.md CHANGED
@@ -295,9 +295,9 @@ class MyInflector < Zeitwerk::Inflector
295
295
  end
296
296
  ```
297
297
 
298
- The first argument, `basename`, is a string with the basename of the file or directory to be inflected. In the case of a file, without extension. The inflector needs to return this basename inflected. Therefore, a simple constant name without colons.
298
+ The first argument, `basename`, is a string with the basename of the file or directory to be inflected. In the case of a file, without extension. In the case of a directory, without trailing slash. The inflector needs to return this basename inflected. Therefore, a simple constant name without colons.
299
299
 
300
- The second argument, `abspath`, is a string with the absolute path to the file or directory in case you need it to decide how to inflect the basename.
300
+ The second argument, `abspath`, is a string with the absolute path to the file or directory in case you need it to decide how to inflect the basename. Paths to directories don't have trailing slashes.
301
301
 
302
302
  Then, assign the inflector:
303
303
 
@@ -113,6 +113,10 @@ module Zeitwerk
113
113
  # @return [Mutex]
114
114
  attr_reader :mutex
115
115
 
116
+ # @private
117
+ # @return [Mutex]
118
+ attr_reader :mutex2
119
+
116
120
  def initialize
117
121
  @initialized_at = Time.now
118
122
 
@@ -130,7 +134,9 @@ module Zeitwerk
130
134
  @shadowed_files = {}
131
135
  @eager_load_exclusions = Set.new
132
136
 
137
+ # TODO: find a better name for these mutexes.
133
138
  @mutex = Mutex.new
139
+ @mutex2 = Mutex.new
134
140
  @setup = false
135
141
  @eager_loaded = false
136
142
 
@@ -17,13 +17,28 @@ module Zeitwerk::Loader::Callbacks
17
17
  # @param dir [String]
18
18
  # @return [void]
19
19
  def on_dir_autoloaded(dir)
20
- parent, cname = autoloads[dir]
20
+ # Module#autoload does not serialize concurrent requires, and we handle
21
+ # directories ourselves.
22
+ #
23
+ # That introduces a race condition here in which thread t1 autovivifies the
24
+ # module, and while autoloads are being set on that module object, thread t2
25
+ # autoloads the same namespace.
26
+ #
27
+ # In that situation, t2 resets the constant to store a new module. That not
28
+ # only sets the constant twice (undesirable per se), but it gets worse,
29
+ # because the module object created by t2 won't have any of the autoloads
30
+ # for child constants set, since t1 correctly deleted the lazy_dirs entry,
31
+ # thus resulting in NameErrors when client code tries to reach them.
32
+ mutex2.synchronize do
33
+ parent, cname = autoloads[dir]
34
+ break if loaded_cpaths.include?(cpath(parent, cname))
21
35
 
22
- autovivified_module = parent.const_set(cname, Module.new)
23
- log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger
36
+ autovivified_module = parent.const_set(cname, Module.new)
37
+ log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger
24
38
 
25
- loaded_cpaths.add(autovivified_module.name)
26
- on_namespace_loaded(autovivified_module)
39
+ loaded_cpaths.add(autovivified_module.name)
40
+ on_namespace_loaded(autovivified_module)
41
+ end
27
42
  end
28
43
 
29
44
  # Invoked when a class or module is created or reopened, either from the
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zeitwerk
4
- VERSION = "1.4.0"
4
+ VERSION = "1.4.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zeitwerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xavier Noria
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-19 00:00:00.000000000 Z
11
+ date: 2019-03-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |2
14
14
  Zeitwerk implements constant autoloading with Ruby semantics. Each gem