im 0.1.3 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f60f56fa26101e6aeec8d3a9123f1ce8196a60ff559931ec91418316cef13e2
4
- data.tar.gz: 445bf0961717077dd35e5ab900b1ab235b25a834a0b1123ed6936c2770439872
3
+ metadata.gz: 99d5cc6d355489148cd6f39fee0e50ce1a25d0e770e4f06c4918fdd41b05935b
4
+ data.tar.gz: ec2372445636beac68c84c0249b68e7e454dda3b0c49293bea4e8f14bfa52053
5
5
  SHA512:
6
- metadata.gz: d0c2063a12bc66f6e86565a27d1e58e2079a88466a61c42a9830fbb0705864ee33f1c780f367dbe61e55b1e21a741cd6c05fc2e4cb7c50ee2bca1625096898c1
7
- data.tar.gz: 4ba1c608ba252e26625ddd136fcaddb3ac8b9f6a5f79db80796ce82ebd8b96da1560b946c79d31a8e658c1fbe5e727d6e68c793dd6a8944e6ceb60b62dd01182
6
+ metadata.gz: f9099a8d43b9772952916c21bd84da42da3eeac2541c0b4fe675fd7c373988d00a9522fc7dc2ce662ea7d0f3231ec4aec11941ab8f079350529d6476e535a19f
7
+ data.tar.gz: 764b1d2454d0158deba3cd4244453aab0d194036b0fe4104c0cb40bced64d5a0bdb6099db3f5c0b9d98cf75c1417707949f353524b8061c5db18ef96ea0aad2d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
- ## [0.1.2] - 2022-09-16
3
+ ## [0.1.4] - 2022-09-19
4
+ - Correctly assign constants imported via recursive requires
5
+
6
+ ## [0.1.3] - 2022-09-16
4
7
  - Fix gemspec
5
8
 
6
9
  ## [0.1.1] - 2022-09-16
data/Gemfile CHANGED
@@ -6,3 +6,4 @@ source "https://rubygems.org"
6
6
  gemspec
7
7
 
8
8
  gem "rspec", "~> 3.0"
9
+ gem "rails"
data/Gemfile.lock CHANGED
@@ -1,12 +1,144 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- im (0.1.2)
4
+ im (0.1.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ actioncable (7.0.4)
10
+ actionpack (= 7.0.4)
11
+ activesupport (= 7.0.4)
12
+ nio4r (~> 2.0)
13
+ websocket-driver (>= 0.6.1)
14
+ actionmailbox (7.0.4)
15
+ actionpack (= 7.0.4)
16
+ activejob (= 7.0.4)
17
+ activerecord (= 7.0.4)
18
+ activestorage (= 7.0.4)
19
+ activesupport (= 7.0.4)
20
+ mail (>= 2.7.1)
21
+ net-imap
22
+ net-pop
23
+ net-smtp
24
+ actionmailer (7.0.4)
25
+ actionpack (= 7.0.4)
26
+ actionview (= 7.0.4)
27
+ activejob (= 7.0.4)
28
+ activesupport (= 7.0.4)
29
+ mail (~> 2.5, >= 2.5.4)
30
+ net-imap
31
+ net-pop
32
+ net-smtp
33
+ rails-dom-testing (~> 2.0)
34
+ actionpack (7.0.4)
35
+ actionview (= 7.0.4)
36
+ activesupport (= 7.0.4)
37
+ rack (~> 2.0, >= 2.2.0)
38
+ rack-test (>= 0.6.3)
39
+ rails-dom-testing (~> 2.0)
40
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
41
+ actiontext (7.0.4)
42
+ actionpack (= 7.0.4)
43
+ activerecord (= 7.0.4)
44
+ activestorage (= 7.0.4)
45
+ activesupport (= 7.0.4)
46
+ globalid (>= 0.6.0)
47
+ nokogiri (>= 1.8.5)
48
+ actionview (7.0.4)
49
+ activesupport (= 7.0.4)
50
+ builder (~> 3.1)
51
+ erubi (~> 1.4)
52
+ rails-dom-testing (~> 2.0)
53
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
54
+ activejob (7.0.4)
55
+ activesupport (= 7.0.4)
56
+ globalid (>= 0.3.6)
57
+ activemodel (7.0.4)
58
+ activesupport (= 7.0.4)
59
+ activerecord (7.0.4)
60
+ activemodel (= 7.0.4)
61
+ activesupport (= 7.0.4)
62
+ activestorage (7.0.4)
63
+ actionpack (= 7.0.4)
64
+ activejob (= 7.0.4)
65
+ activerecord (= 7.0.4)
66
+ activesupport (= 7.0.4)
67
+ marcel (~> 1.0)
68
+ mini_mime (>= 1.1.0)
69
+ activesupport (7.0.4)
70
+ concurrent-ruby (~> 1.0, >= 1.0.2)
71
+ i18n (>= 1.6, < 2)
72
+ minitest (>= 5.1)
73
+ tzinfo (~> 2.0)
74
+ builder (3.2.4)
75
+ concurrent-ruby (1.1.10)
76
+ crass (1.0.6)
9
77
  diff-lcs (1.5.0)
78
+ digest (3.1.0)
79
+ erubi (1.11.0)
80
+ globalid (1.0.0)
81
+ activesupport (>= 5.0)
82
+ i18n (1.12.0)
83
+ concurrent-ruby (~> 1.0)
84
+ loofah (2.19.0)
85
+ crass (~> 1.0.2)
86
+ nokogiri (>= 1.5.9)
87
+ mail (2.7.1)
88
+ mini_mime (>= 0.1.1)
89
+ marcel (1.0.2)
90
+ method_source (1.0.0)
91
+ mini_mime (1.1.2)
92
+ mini_portile2 (2.8.0)
93
+ minitest (5.16.3)
94
+ net-imap (0.2.3)
95
+ digest
96
+ net-protocol
97
+ strscan
98
+ net-pop (0.1.1)
99
+ digest
100
+ net-protocol
101
+ timeout
102
+ net-protocol (0.1.3)
103
+ timeout
104
+ net-smtp (0.3.1)
105
+ digest
106
+ net-protocol
107
+ timeout
108
+ nio4r (2.5.8)
109
+ nokogiri (1.13.8)
110
+ mini_portile2 (~> 2.8.0)
111
+ racc (~> 1.4)
112
+ racc (1.6.0)
113
+ rack (2.2.4)
114
+ rack-test (2.0.2)
115
+ rack (>= 1.3)
116
+ rails (7.0.4)
117
+ actioncable (= 7.0.4)
118
+ actionmailbox (= 7.0.4)
119
+ actionmailer (= 7.0.4)
120
+ actionpack (= 7.0.4)
121
+ actiontext (= 7.0.4)
122
+ actionview (= 7.0.4)
123
+ activejob (= 7.0.4)
124
+ activemodel (= 7.0.4)
125
+ activerecord (= 7.0.4)
126
+ activestorage (= 7.0.4)
127
+ activesupport (= 7.0.4)
128
+ bundler (>= 1.15.0)
129
+ railties (= 7.0.4)
130
+ rails-dom-testing (2.0.3)
131
+ activesupport (>= 4.2.0)
132
+ nokogiri (>= 1.6)
133
+ rails-html-sanitizer (1.4.3)
134
+ loofah (~> 2.3)
135
+ railties (7.0.4)
136
+ actionpack (= 7.0.4)
137
+ activesupport (= 7.0.4)
138
+ method_source
139
+ rake (>= 12.2)
140
+ thor (~> 1.0)
141
+ zeitwerk (~> 2.5)
10
142
  rake (13.0.6)
11
143
  rake-compiler (1.2.0)
12
144
  rake
@@ -23,12 +155,22 @@ GEM
23
155
  diff-lcs (>= 1.2.0, < 2.0)
24
156
  rspec-support (~> 3.11.0)
25
157
  rspec-support (3.11.0)
158
+ strscan (3.0.4)
159
+ thor (1.2.1)
160
+ timeout (0.3.0)
161
+ tzinfo (2.0.5)
162
+ concurrent-ruby (~> 1.0)
163
+ websocket-driver (0.7.5)
164
+ websocket-extensions (>= 0.1.0)
165
+ websocket-extensions (0.1.5)
166
+ zeitwerk (2.6.0)
26
167
 
27
168
  PLATFORMS
28
169
  x86_64-linux
29
170
 
30
171
  DEPENDENCIES
31
172
  im!
173
+ rails
32
174
  rake (~> 13.0)
33
175
  rake-compiler
34
176
  rspec (~> 3.0)
data/lib/im/autoload.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Im
4
4
  module Autoload
5
5
  def autoload(name, path)
6
- Im.autoloads[path] = Im.current_import if Im.current_import
6
+ Im.autoloads[path] = Im.current_import if Im.importing?
7
7
  super(name, path)
8
8
  end
9
9
  end
data/lib/im/constants.rb CHANGED
@@ -97,6 +97,7 @@ module Im
97
97
  :UnboundMethod,
98
98
  :UncaughtThrowError,
99
99
  :UnicodeNormalize,
100
+ :URI,
100
101
  :Warning,
101
102
  :ZeroDivisionError,
102
103
  ]
data/lib/im/kernel.rb CHANGED
@@ -5,31 +5,38 @@ module Kernel
5
5
 
6
6
  def require(path)
7
7
  if Im.autoloads.key?(path)
8
- return Im.with_context(Im.autoloads.delete(path)) do |_context|
8
+ return Im.with_import(Im.autoloads.delete(path)) do |_context|
9
9
  !!Im.import(path)
10
10
  end
11
11
  end
12
12
 
13
+ if Im.importing? && (resolved = $LOAD_PATH.resolve_feature_path(path))
14
+ resolved_path = resolved[1]
15
+ Im.registry[resolved_path] ||= Im::Dependency.new(resolved_path, Im.current_import)
16
+ end
17
+
13
18
  loaded = im_original_require(path)
14
- return loaded unless Im.current_import
19
+ return loaded unless Im.importing?
20
+
21
+ if resolved
22
+ dependency = Im.registry[resolved_path]
23
+
24
+ if loaded && Im.registry.key?(location = caller_locations(1, 1).first.path)
25
+ Im.registry[location].dependencies << dependency
26
+ end
15
27
 
16
- if resolved = $LOAD_PATH.resolve_feature_path(path)
17
- if Im.registry.key?(resolved_path = resolved[1])
18
- _, modules = Im.registry[resolved_path]
28
+ dependency.dependencies.each { |d| require d.path }
19
29
 
20
- modules.each do |m|
21
- next unless name = m.name
30
+ dependency.modules.each do |m|
31
+ name = m.name
22
32
 
23
- # Do not assign constants that are aliased to root namespace
24
- root = name.split("::", 2)[0]
25
- next if Object.const_defined?(root) &&
26
- Im.current_import.const_defined?(root, false) &&
27
- Object.const_get(root) == Im.current_import.const_get(root)
33
+ # Do not assign constants that are aliased to root namespace
34
+ root = name.split("::", 2)[0]
35
+ next if Object.const_defined?(root) &&
36
+ Im.current_import.const_defined?(root, false) &&
37
+ Object.const_get(root) == Im.current_import.const_get(root)
28
38
 
29
- Im.current_import.const_set(name, m) unless Im.current_import.const_defined?(name, false)
30
- end
31
- else
32
- Im.registry[resolved_path] ||= [Im.current_import, []] if Im.current_import
39
+ Im.current_import.const_set(name, m) unless Im.current_import.const_defined?(name, false)
33
40
  end
34
41
  end
35
42
 
data/lib/im/module.rb CHANGED
@@ -2,7 +2,7 @@ class Module
2
2
  alias_method :im_original_autoload, :autoload
3
3
 
4
4
  def autoload(name, path)
5
- Im.autoloads[path] = Im.current_import if Im.current_import
5
+ Im.autoloads[path] = Im.current_import if Im.importing?
6
6
  im_original_autoload(name, path)
7
7
  end
8
8
  end
data/lib/im/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Im
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
data/lib/im.rb CHANGED
@@ -7,14 +7,20 @@ module Im
7
7
 
8
8
  class << self
9
9
  attr_reader :current_import
10
- attr_reader :tracer
11
10
 
12
- def with_context(context)
13
- original_context = current_import
14
- @current_import = context
15
- yield(context)
11
+ def with_import(import)
12
+ original_import = current_import
13
+ @current_import = import
14
+
15
+ unless tracer_originally_enabled = @tracer.enabled?
16
+ @tracer.enable
17
+ end
18
+
19
+ yield(import)
20
+
16
21
  ensure
17
- @current_import = original_context
22
+ @current_import = original_import
23
+ @tracer.disable unless tracer_originally_enabled
18
24
  end
19
25
 
20
26
  def registry
@@ -24,6 +30,10 @@ module Im
24
30
  def autoloads
25
31
  @autoloads ||= {}
26
32
  end
33
+
34
+ def importing?
35
+ !!Im.current_import
36
+ end
27
37
  end
28
38
 
29
39
  class Import < Module
@@ -40,6 +50,12 @@ module Im
40
50
  end
41
51
  end
42
52
 
53
+ Dependency = Struct.new(:path, :import, :modules, :dependencies) do
54
+ def initialize(path, import, modules = [], dependencies = [])
55
+ super(path, import, modules, dependencies)
56
+ end
57
+ end
58
+
43
59
  def import(path)
44
60
  if resolved = $LOAD_PATH.resolve_feature_path(path)
45
61
  resolved_path = resolved[1]
@@ -54,23 +70,30 @@ module Im
54
70
 
55
71
  $LOADED_FEATURES << resolved_path
56
72
 
57
- context = Im.current_import || Import.new(path)
58
-
59
- Im.with_context(context) do
60
- originally_enabled = Im.tracer.enabled?
61
- Im.tracer.enable
62
- load resolved_path, context
63
- Im.tracer.disable unless originally_enabled
73
+ import = Im.current_import || Import.new(path)
74
+ (Im.registry[resolved_path] ||= Dependency.new(resolved_path, import)).tap do
75
+ Im.with_import(import) do
76
+ load resolved_path, import
77
+ end
64
78
  end
65
-
66
- Im.registry[resolved_path] ||= [context, []]
67
- end[0]
79
+ end&.import
68
80
  end
69
81
 
82
+ # This is a hack to catch references to top-level constants (`::Foo`) and, if
83
+ # the calling line is a key in the Im registry, replace the toplevel constant
84
+ # reference with its corresponding constant under the import namespace.
85
+ #
86
+ # By doing this, a reference to `::Foo` in an imported file will resolve to
87
+ # `mod::Foo`, where `mod` is the import module. Ideally this should
88
+ # ultimately happen at the Ruby implementation level.
70
89
  module RootNamespaceRedirect
71
90
  def const_missing(name)
72
- if Im.current_import && Im.current_import.const_defined?(name)
73
- Im.current_import.const_get(name)
91
+
92
+ # Take top five locations to allow for other `const_missing` overrides
93
+ # in the backtrace. If there are more than five, then this will no longer
94
+ # work. This is currently very inefficient.
95
+ if location = caller_locations(1, 5).find { |l| Im.registry.key?(l.path) }
96
+ Im.registry[location.path].import.const_get(name)
74
97
  else
75
98
  super
76
99
  end
@@ -78,12 +101,15 @@ module Im
78
101
  end
79
102
 
80
103
  @tracer = TracePoint.new(:class) do |event|
104
+ next unless (name = event.self.name)
105
+ next if Im::CONSTANTS.include?(name.to_sym)
106
+
81
107
  if resolved = $LOAD_PATH.resolve_feature_path(event.path)
82
108
  resolved_path = resolved[1]
83
109
  if Im.registry.key?(resolved_path)
84
- (Im.registry[resolved_path][1] << event.self).uniq!
110
+ (Im.registry[resolved_path].modules << event.self).uniq!
85
111
  else
86
- Im.registry[resolved_path] = [Im.current_import, [event.self]]
112
+ Im.registry[resolved_path] = Dependency.new(resolved_path, Im.current_import, [event.self])
87
113
  end
88
114
  end
89
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: im
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Salzberg
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-16 00:00:00.000000000 Z
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake