opal-zeitwerk 0.3.0 → 0.4.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.
@@ -1,21 +1,20 @@
1
- module Zeitwerk::RealModName
2
- UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
3
- private_constant :UNBOUND_METHOD_MODULE_NAME
4
-
5
- # Returns the real name of the class or module, as set after the first
6
- # constant to which it was assigned (or nil).
7
- #
8
- # The name method can be overridden, hence the indirection in this method.
9
- #
10
- # @param mod [Class, Module]
11
- # @return [String, nil]
12
- if UnboundMethod.method_defined?(:bind_call)
13
- def real_mod_name(mod)
14
- UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
15
- end
16
- else
17
- def real_mod_name(mod)
18
- UNBOUND_METHOD_MODULE_NAME.bind(mod).call
19
- end
20
- end
21
- end
1
+ module Zeitwerk::RealModName
2
+ UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
3
+ private_constant :UNBOUND_METHOD_MODULE_NAME
4
+
5
+ # Returns the real name of the class or module, as set after the first
6
+ # constant to which it was assigned (or nil).
7
+ #
8
+ # The name method can be overridden, hence the indirection in this method.
9
+ #
10
+ # @sig (Module) -> String?
11
+ if UnboundMethod.method_defined?(:bind_call)
12
+ def real_mod_name(mod)
13
+ UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
14
+ end
15
+ else
16
+ def real_mod_name(mod)
17
+ UNBOUND_METHOD_MODULE_NAME.bind(mod).call
18
+ end
19
+ end
20
+ end
@@ -1,121 +1,143 @@
1
- module Zeitwerk
2
- module Registry # :nodoc: all
3
- class << self
4
- # Keeps track of all loaders. Useful to broadcast messages and to prevent
5
- # them from being garbage collected.
6
- #
7
- # @private
8
- # @return [<Zeitwerk::Loader>]
9
- attr_reader :loaders
10
-
11
- # Maps real paths to the loaders responsible for them.
12
- #
13
- # This information is used by our decorated `Kernel#require` to be able to
14
- # invoke callbacks and autovivify modules.
15
- #
16
- # @private
17
- # @return [{String => Zeitwerk::Loader}]
18
- attr_reader :autoloads
19
-
20
- # This hash table addresses an edge case in which an autoload is ignored.
21
- #
22
- # For example, let's suppose we want to autoload in a gem like this:
23
- #
24
- # # lib/my_gem.rb
25
- # loader = Zeitwerk::Loader.new
26
- # loader.push_dir(__dir__)
27
- # loader.setup
28
- #
29
- # module MyGem
30
- # end
31
- #
32
- # if you require "my_gem", as Bundler would do, this happens while setting
33
- # up autoloads:
34
- #
35
- # 1. Object.autoload?(:MyGem) returns `nil` because the autoload for
36
- # the constant is issued by Zeitwerk while the same file is being
37
- # required.
38
- # 2. The constant `MyGem` is undefined while setup runs.
39
- #
40
- # Therefore, a directory `lib/my_gem` would autovivify a module according to
41
- # the existing information. But that would be wrong.
42
- #
43
- # To overcome this fundamental limitation, we keep track of the constant
44
- # paths that are in this situation ---in the example above, "MyGem"--- and
45
- # take this collection into account for the autovivification logic.
46
- #
47
- # Note that you cannot generally address this by moving the setup code
48
- # below the constant definition, because we want libraries to be able to
49
- # use managed constants in the module body:
50
- #
51
- # module MyGem
52
- # include MyConcern
53
- # end
54
- #
55
- # @private
56
- # @return [{String => (String, Zeitwerk::Loader)}]
57
- attr_reader :inceptions
58
-
59
- # Registers a loader.
60
- #
61
- # @private
62
- # @param loader [Zeitwerk::Loader]
63
- # @return [void]
64
- def register_loader(loader)
65
- loaders << loader
66
- end
67
-
68
- # @private
69
- # @param loader [Zeitwerk::Loader]
70
- # @param realpath [String]
71
- # @return [void]
72
- def register_autoload(loader, realpath)
73
- autoloads[realpath] = loader
74
- end
75
-
76
- # @private
77
- # @param realpath [String]
78
- # @return [void]
79
- def unregister_autoload(realpath)
80
- autoloads.delete(realpath)
81
- end
82
-
83
- # @private
84
- # @param cpath [String]
85
- # @param realpath [String]
86
- # @param loader [Zeitwerk::Loader]
87
- # @return [void]
88
- def register_inception(cpath, realpath, loader)
89
- inceptions[cpath] = [realpath, loader]
90
- end
91
-
92
- # @private
93
- # @param cpath [String]
94
- # @return [String, nil]
95
- def inception?(cpath)
96
- if pair = inceptions[cpath]
97
- pair.first
98
- end
99
- end
100
-
101
- # @private
102
- # @param path [String]
103
- # @return [Zeitwerk::Loader, nil]
104
- def loader_for(path)
105
- autoloads[path]
106
- end
107
-
108
- # @private
109
- # @param loader [Zeitwerk::Loader]
110
- # @return [void]
111
- def on_unload(loader)
112
- autoloads.delete_if { |_path, object| object == loader }
113
- inceptions.delete_if { |_cpath, (_path, object)| object == loader }
114
- end
115
- end
116
-
117
- @loaders = []
118
- @autoloads = {}
119
- @inceptions = {}
120
- end
121
- end
1
+ module Zeitwerk
2
+ module Registry # :nodoc: all
3
+ class << self
4
+ # Keeps track of all loaders. Useful to broadcast messages and to prevent
5
+ # them from being garbage collected.
6
+ #
7
+ # @private
8
+ # @sig Array[Zeitwerk::Loader]
9
+ attr_reader :loaders
10
+
11
+ # Registers loaders created with `for_gem` to make the method idempotent
12
+ # in case of reload.
13
+ #
14
+ # @private
15
+ # @sig Hash[String, Zeitwerk::Loader]
16
+ attr_reader :loaders_managing_gems
17
+
18
+ # Maps absolute paths to the loaders responsible for them.
19
+ #
20
+ # This information is used by our decorated `Kernel#require` to be able to
21
+ # invoke callbacks and autovivify modules.
22
+ #
23
+ # @private
24
+ # @sig Hash[String, Zeitwerk::Loader]
25
+ attr_reader :autoloads
26
+
27
+ # This hash table addresses an edge case in which an autoload is ignored.
28
+ #
29
+ # For example, let's suppose we want to autoload in a gem like this:
30
+ #
31
+ # # lib/my_gem.rb
32
+ # loader = Zeitwerk::Loader.new
33
+ # loader.push_dir(__dir__)
34
+ # loader.setup
35
+ #
36
+ # module MyGem
37
+ # end
38
+ #
39
+ # if you require "my_gem", as Bundler would do, this happens while setting
40
+ # up autoloads:
41
+ #
42
+ # 1. Object.autoload?(:MyGem) returns `nil` because the autoload for
43
+ # the constant is issued by Zeitwerk while the same file is being
44
+ # required.
45
+ # 2. The constant `MyGem` is undefined while setup runs.
46
+ #
47
+ # Therefore, a directory `lib/my_gem` would autovivify a module according to
48
+ # the existing information. But that would be wrong.
49
+ #
50
+ # To overcome this fundamental limitation, we keep track of the constant
51
+ # paths that are in this situation ---in the example above, "MyGem"--- and
52
+ # take this collection into account for the autovivification logic.
53
+ #
54
+ # Note that you cannot generally address this by moving the setup code
55
+ # below the constant definition, because we want libraries to be able to
56
+ # use managed constants in the module body:
57
+ #
58
+ # module MyGem
59
+ # include MyConcern
60
+ # end
61
+ #
62
+ # @private
63
+ # @sig Hash[String, [String, Zeitwerk::Loader]]
64
+ attr_reader :inceptions
65
+
66
+ # Registers a loader.
67
+ #
68
+ # @private
69
+ # @sig (Zeitwerk::Loader) -> void
70
+ def register_loader(loader)
71
+ loaders << loader
72
+ end
73
+
74
+ # @private
75
+ # @sig (Zeitwerk::Loader) -> void
76
+ def unregister_loader(loader)
77
+ loaders.delete(loader)
78
+ loaders_managing_gems.delete_if { |_, l| l == loader }
79
+ autoloads.delete_if { |_, l| l == loader }
80
+ inceptions.delete_if { |_, (_, l)| l == loader }
81
+ end
82
+
83
+ # This method returns always a loader, the same instance for the same root
84
+ # file. That is how Zeitwerk::Loader.for_gem is idempotent.
85
+ #
86
+ # @private
87
+ # @sig (String) -> Zeitwerk::Loader
88
+ def loader_for_gem(root_file)
89
+ loaders_managing_gems[root_file] ||= begin
90
+ Loader.new.tap do |loader|
91
+ loader.tag = File.basename(root_file, ".rb")
92
+ loader.inflector = GemInflector.new(root_file)
93
+ loader.push_dir(File.dirname(root_file))
94
+ end
95
+ end
96
+ end
97
+
98
+ # @private
99
+ # @sig (Zeitwerk::Loader, String) -> String
100
+ def register_autoload(loader, abspath)
101
+ autoloads[abspath] = loader
102
+ end
103
+
104
+ # @private
105
+ # @sig (String) -> void
106
+ def unregister_autoload(abspath)
107
+ autoloads.delete(abspath)
108
+ end
109
+
110
+ # @private
111
+ # @sig (String, String, Zeitwerk::Loader) -> void
112
+ def register_inception(cpath, abspath, loader)
113
+ inceptions[cpath] = [abspath, loader]
114
+ end
115
+
116
+ # @private
117
+ # @sig (String) -> String?
118
+ def inception?(cpath)
119
+ if pair = inceptions[cpath]
120
+ pair.first
121
+ end
122
+ end
123
+
124
+ # @private
125
+ # @sig (String) -> Zeitwerk::Loader?
126
+ def loader_for(path)
127
+ autoloads[path]
128
+ end
129
+
130
+ # @private
131
+ # @sig (Zeitwerk::Loader) -> void
132
+ def on_unload(loader)
133
+ autoloads.delete_if { |_path, object| object == loader }
134
+ inceptions.delete_if { |_cpath, (_path, object)| object == loader }
135
+ end
136
+ end
137
+
138
+ @loaders = []
139
+ @loaders_managing_gems = {}
140
+ @autoloads = {}
141
+ @inceptions = {}
142
+ end
143
+ end
data/opal/zeitwerk.rb CHANGED
@@ -1,13 +1,14 @@
1
- require 'opal'
2
- require 'corelib/trace_point'
3
- require 'securerandom'
4
-
5
- module Zeitwerk
6
- require_relative "zeitwerk/real_mod_name"
7
- require_relative "zeitwerk/loader"
8
- require_relative "zeitwerk/registry"
9
- require_relative "zeitwerk/explicit_namespace"
10
- require_relative "zeitwerk/inflector"
11
- require_relative "zeitwerk/kernel"
12
- require_relative "zeitwerk/error"
13
- end
1
+ require 'opal'
2
+ require 'corelib/trace_point'
3
+ require 'securerandom'
4
+
5
+ module Zeitwerk
6
+ require_relative "zeitwerk/real_mod_name"
7
+ require_relative "zeitwerk/loader"
8
+ require_relative "zeitwerk/registry"
9
+ require_relative "zeitwerk/explicit_namespace"
10
+ require_relative "zeitwerk/inflector"
11
+ require_relative "zeitwerk/gem_inflector"
12
+ require_relative "zeitwerk/kernel"
13
+ require_relative "zeitwerk/error"
14
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal-zeitwerk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-25 00:00:00.000000000 Z
11
+ date: 2022-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.4.0
19
+ version: 1.4.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.4.0
26
+ version: 1.4.1
27
27
  description: |2
28
28
  A port of the Zeitwerk autoloader to Opal.
29
29
  Zeitwerk implements constant autoloading with Ruby semantics. Each gem
@@ -41,10 +41,13 @@ files:
41
41
  - opal/zeitwerk.rb
42
42
  - opal/zeitwerk/error.rb
43
43
  - opal/zeitwerk/explicit_namespace.rb
44
+ - opal/zeitwerk/gem_inflector.rb
44
45
  - opal/zeitwerk/inflector.rb
45
46
  - opal/zeitwerk/kernel.rb
46
47
  - opal/zeitwerk/loader.rb
47
48
  - opal/zeitwerk/loader/callbacks.rb
49
+ - opal/zeitwerk/loader/config.rb
50
+ - opal/zeitwerk/loader/helpers.rb
48
51
  - opal/zeitwerk/real_mod_name.rb
49
52
  - opal/zeitwerk/registry.rb
50
53
  homepage: https://github.com/isomorfeus/opal-zeitwerk
@@ -67,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
67
70
  - !ruby/object:Gem::Version
68
71
  version: '0'
69
72
  requirements: []
70
- rubygems_version: 3.2.32
73
+ rubygems_version: 3.3.7
71
74
  signing_key:
72
75
  specification_version: 4
73
76
  summary: Opal constant autoloader using Zeitwerk