zeitwerk 2.0.0 → 2.1.0
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/lib/zeitwerk/loader.rb +43 -18
- data/lib/zeitwerk/loader/callbacks.rb +16 -20
- data/lib/zeitwerk/version.rb +1 -1
- 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: 2af29bb519da160c83620c23a1f1c119c7b534a3e3db308b2635b344b435dfa1
|
4
|
+
data.tar.gz: ec2dc810c74887befea3550b3305b0b096610cbb06a2983dad0c041c9bed34dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cafd96d9f21546ea8dcb58f8b589d59b5de994492a2f89f6cd4eb2701d673e58c888884b672ddd47580778090f4af918c908e6325d5690ce8297b0e152eb391
|
7
|
+
data.tar.gz: e1fba9ebf4e35fa10c2577bdb4a19124ee26e3d09a85b2382a5bc0c83688130b14a0c8e9900e6572f25efe86c388b54139d9ca82d7053cfc415b39a618d1ec16
|
data/lib/zeitwerk/loader.rb
CHANGED
@@ -68,8 +68,9 @@ module Zeitwerk
|
|
68
68
|
# @return [{String => String}]
|
69
69
|
attr_reader :shadowed_files
|
70
70
|
|
71
|
-
# Maps real absolute paths for which an autoload has been set
|
72
|
-
# corresponding parent class or module and constant
|
71
|
+
# Maps real absolute paths for which an autoload has been set ---and not
|
72
|
+
# executed--- to their corresponding parent class or module and constant
|
73
|
+
# name.
|
73
74
|
#
|
74
75
|
# "/Users/fxn/blog/app/models/user.rb" => [Object, "User"],
|
75
76
|
# "/Users/fxn/blog/app/models/hotel/pricing.rb" => [Hotel, "Pricing"]
|
@@ -84,13 +85,18 @@ module Zeitwerk
|
|
84
85
|
#
|
85
86
|
# Files are removed as they are autoloaded, but directories need to wait due
|
86
87
|
# to concurrency (see why in Zeitwerk::Loader::Callbacks#on_dir_autoloaded).
|
88
|
+
#
|
89
|
+
# @private
|
90
|
+
# @return [<String>]
|
87
91
|
attr_reader :autoloaded_dirs
|
88
92
|
|
89
|
-
#
|
93
|
+
# Constants paths that would be unloaded if you would reload. If reloading
|
94
|
+
# is enabled, this hash is filled as constants are autoloaded or eager
|
95
|
+
# loaded. Otherwise, the collection remains empty.
|
90
96
|
#
|
91
97
|
# @private
|
92
|
-
# @return [
|
93
|
-
attr_reader :
|
98
|
+
# @return [{String => (String, (Module, String))}]
|
99
|
+
attr_reader :to_unload
|
94
100
|
|
95
101
|
# Maps constant paths of namespaces to arrays of corresponding directories.
|
96
102
|
#
|
@@ -137,7 +143,7 @@ module Zeitwerk
|
|
137
143
|
@ignored_paths = Set.new
|
138
144
|
@autoloads = {}
|
139
145
|
@autoloaded_dirs = []
|
140
|
-
@
|
146
|
+
@to_unload = {}
|
141
147
|
@lazy_subdirs = {}
|
142
148
|
@shadowed_files = {}
|
143
149
|
@eager_load_exclusions = Set.new
|
@@ -270,19 +276,21 @@ module Zeitwerk
|
|
270
276
|
|
271
277
|
autoloads.each do |realpath, (parent, cname)|
|
272
278
|
if parent.autoload?(cname)
|
273
|
-
parent
|
274
|
-
log("autoload for #{cpath(parent, cname)} removed") if logger
|
279
|
+
unload_autoload(parent, cname)
|
275
280
|
else
|
276
|
-
if
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
# Already unloaded somehow, that is fine.
|
281
|
-
end
|
281
|
+
# Could happen if loaded with require_relative. require_relative is
|
282
|
+
# not supported, and the cpath would escape `to_unload?`. This is
|
283
|
+
# just defensive code to clean things up as much as we are able to.
|
284
|
+
unload_cref(parent, cname) if cdef?(parent, cname)
|
282
285
|
unloaded_files.add(realpath) if ruby?(realpath)
|
283
286
|
end
|
284
287
|
end
|
285
288
|
|
289
|
+
to_unload.each_value do |(realpath, (parent, cname))|
|
290
|
+
unload_cref(parent, cname) if cdef?(parent, cname)
|
291
|
+
unloaded_files.add(realpath) if ruby?(realpath)
|
292
|
+
end
|
293
|
+
|
286
294
|
unless unloaded_files.empty?
|
287
295
|
# Bootsnap decorates Kernel#require to speed it up using a cache and
|
288
296
|
# this optimization does not check if $LOADED_FEATURES has the file.
|
@@ -300,7 +308,7 @@ module Zeitwerk
|
|
300
308
|
|
301
309
|
autoloads.clear
|
302
310
|
autoloaded_dirs.clear
|
303
|
-
|
311
|
+
to_unload.clear
|
304
312
|
lazy_subdirs.clear
|
305
313
|
shadowed_files.clear
|
306
314
|
|
@@ -369,12 +377,13 @@ module Zeitwerk
|
|
369
377
|
mutex.synchronize { eager_load_exclusions.merge(expand_paths(paths)) }
|
370
378
|
end
|
371
379
|
|
372
|
-
# Says if the given constant path
|
380
|
+
# Says if the given constant path would be unloaded on reload. This
|
381
|
+
# predicate returns `false` if reloading is disabled.
|
373
382
|
#
|
374
383
|
# @param cpath [String]
|
375
384
|
# @return [Boolean]
|
376
|
-
def
|
377
|
-
|
385
|
+
def to_unload?(cpath)
|
386
|
+
to_unload.key?(cpath)
|
378
387
|
end
|
379
388
|
|
380
389
|
# --- Class methods ---------------------------------------------------------------------------
|
@@ -662,5 +671,21 @@ module Zeitwerk
|
|
662
671
|
end
|
663
672
|
end
|
664
673
|
end
|
674
|
+
|
675
|
+
# @param parent [Module]
|
676
|
+
# @param cname [String]
|
677
|
+
# @return [void]
|
678
|
+
def unload_autoload(parent, cname)
|
679
|
+
parent.send(:remove_const, cname)
|
680
|
+
log("autoload for #{cpath(parent, cname)} removed") if logger
|
681
|
+
end
|
682
|
+
|
683
|
+
# @param parent [Module]
|
684
|
+
# @param cname [String]
|
685
|
+
# @return [void]
|
686
|
+
def unload_cref(parent, cname)
|
687
|
+
parent.send(:remove_const, cname)
|
688
|
+
log("#{cpath(parent, cname)} unloaded") if logger
|
689
|
+
end
|
665
690
|
end
|
666
691
|
end
|
@@ -5,10 +5,10 @@ module Zeitwerk::Loader::Callbacks
|
|
5
5
|
# @param file [String]
|
6
6
|
# @return [void]
|
7
7
|
def on_file_autoloaded(file)
|
8
|
-
|
9
|
-
|
8
|
+
cref = autoloads.delete(file)
|
9
|
+
to_unload[cpath(*cref)] = [file, cref] if reloading_enabled?
|
10
10
|
Zeitwerk::Registry.unregister_autoload(file)
|
11
|
-
log("constant #{cpath(
|
11
|
+
log("constant #{cpath(*cref)} loaded from file #{file}") if logger
|
12
12
|
end
|
13
13
|
|
14
14
|
# Invoked from our decorated Kernel#require when a managed directory is
|
@@ -25,23 +25,25 @@ module Zeitwerk::Loader::Callbacks
|
|
25
25
|
# autovivifies the module, and while autoloads for its children are being
|
26
26
|
# set, thread t2 autoloads the same namespace.
|
27
27
|
#
|
28
|
-
# Without the mutex and
|
28
|
+
# Without the mutex and subsequent delete call, t2 would reset the module.
|
29
29
|
# That not only would reassign the constant (undesirable per se) but, worse,
|
30
30
|
# the module object created by t2 wouldn't have any of the autoloads for its
|
31
31
|
# children, since t1 would have correctly deleted its lazy_subdirs entry.
|
32
32
|
mutex2.synchronize do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
# except the first one.
|
37
|
-
break if parent.nil? || loaded_cpaths.include?(cpath(parent, cname))
|
33
|
+
if cref = autoloads.delete(dir)
|
34
|
+
autovivified_module = cref[0].const_set(cref[1], Module.new)
|
35
|
+
log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger
|
38
36
|
|
39
|
-
|
40
|
-
log("module #{autovivified_module.name} autovivified from directory #{dir}") if logger
|
37
|
+
to_unload[autovivified_module.name] = [dir, cref] if reloading_enabled?
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
# We don't unregister `dir` in the registry because concurrent threads
|
40
|
+
# wouldn't find a loader associated to it in Kernel#require and would
|
41
|
+
# try to require the directory. Instead, we are going to keep track of
|
42
|
+
# these to be able to unregister later if eager loading.
|
43
|
+
autoloaded_dirs << dir
|
44
|
+
|
45
|
+
on_namespace_loaded(autovivified_module)
|
46
|
+
end
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
@@ -59,10 +61,4 @@ module Zeitwerk::Loader::Callbacks
|
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
62
|
-
|
63
|
-
# @private
|
64
|
-
# @return [(Module, String)]
|
65
|
-
def cref_autoloaded_from(path)
|
66
|
-
reloading_enabled? ? autoloads[path] : autoloads.delete(path)
|
67
|
-
end
|
68
64
|
end
|
data/lib/zeitwerk/version.rb
CHANGED
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: 2.
|
4
|
+
version: 2.1.0
|
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-04-
|
11
|
+
date: 2019-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |2
|
14
14
|
Zeitwerk implements constant autoloading with Ruby semantics. Each gem
|