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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -20
- data/README.md +1073 -466
- data/lib/opal/zeitwerk/version.rb +6 -6
- data/lib/opal-zeitwerk.rb +4 -4
- data/opal/zeitwerk/error.rb +10 -10
- data/opal/zeitwerk/explicit_namespace.rb +78 -71
- data/opal/zeitwerk/gem_inflector.rb +15 -0
- data/opal/zeitwerk/inflector.rb +44 -47
- data/opal/zeitwerk/kernel.rb +64 -32
- data/opal/zeitwerk/loader/callbacks.rb +88 -58
- data/opal/zeitwerk/loader/config.rb +301 -0
- data/opal/zeitwerk/loader/helpers.rb +115 -0
- data/opal/zeitwerk/loader.rb +170 -435
- data/opal/zeitwerk/real_mod_name.rb +20 -21
- data/opal/zeitwerk/registry.rb +143 -121
- data/opal/zeitwerk.rb +14 -13
- metadata +8 -5
@@ -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
|
-
# @
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
data/opal/zeitwerk/registry.rb
CHANGED
@@ -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
|
-
# @
|
9
|
-
attr_reader :loaders
|
10
|
-
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# This
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
# @
|
63
|
-
# @
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
# @private
|
69
|
-
# @
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
# @
|
87
|
-
# @
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# @
|
111
|
-
|
112
|
-
|
113
|
-
inceptions
|
114
|
-
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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/
|
12
|
-
require_relative "zeitwerk/
|
13
|
-
|
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.
|
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:
|
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.
|
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.
|
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.
|
73
|
+
rubygems_version: 3.3.7
|
71
74
|
signing_key:
|
72
75
|
specification_version: 4
|
73
76
|
summary: Opal constant autoloader using Zeitwerk
|