Skip to content

Commit 195ee23

Browse files
committed
🔧 ResponseParser config is mutable and non-global
When ResponseParser was initialized without any explicit config, it used Config.global directly. This meant that changes to `parser.config` were also changes to the _global_ config! When ResponseParser is initialized with a config hash, that creates a frozen config object. This meant that changes to `parser.config` were impossible. So, when the given config is global or frozen, we create a new config and inherit from the given config. We want to continue using the given config as-is in other cases, so the client and its parser can share the same exact config.
1 parent d11c8b6 commit 195ee23

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/net/imap/response_parser.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,17 @@ class ResponseParser
1313

1414
attr_reader :config
1515

16-
# :call-seq: Net::IMAP::ResponseParser.new -> Net::IMAP::ResponseParser
16+
# Creates a new ResponseParser.
17+
#
18+
# When +config+ is frozen or global, the parser #config inherits from it.
19+
# Otherwise, +config+ will be used directly.
1720
def initialize(config: Config.global)
1821
@str = nil
1922
@pos = nil
2023
@lex_state = nil
2124
@token = nil
2225
@config = Config[config]
26+
@config = @config.new if @config == Config.global || @config.frozen?
2327
end
2428

2529
# :call-seq:

test/net/imap/test_imap_response_parser.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,41 @@ def teardown
109109
# response data, should still use normal tests, below
110110
############################################################################
111111

112+
test "default config inherits from Config.global" do
113+
parser = Net::IMAP::ResponseParser.new
114+
refute parser.config.frozen?
115+
refute_equal Net::IMAP::Config.global, parser.config
116+
assert_same Net::IMAP::Config.global, parser.config.parent
117+
end
118+
119+
test "config can be passed in to #initialize" do
120+
config = Net::IMAP::Config.global.new
121+
parser = Net::IMAP::ResponseParser.new config: config
122+
assert_same config, parser.config
123+
end
124+
125+
test "passing in global config inherits from Config.global" do
126+
parser = Net::IMAP::ResponseParser.new config: Net::IMAP::Config.global
127+
refute parser.config.frozen?
128+
refute_equal Net::IMAP::Config.global, parser.config
129+
assert_same Net::IMAP::Config.global, parser.config.parent
130+
end
131+
132+
test "config will inherits from passed in frozen config" do
133+
parser = Net::IMAP::ResponseParser.new config: {debug: true}
134+
refute_equal Net::IMAP::Config.global, parser.config.parent
135+
refute parser.config.frozen?
136+
137+
assert parser.config.parent.frozen?
138+
assert parser.config.debug?
139+
assert parser.config.inherited?(:debug)
140+
141+
config = Net::IMAP::Config[debug: true]
142+
parser = Net::IMAP::ResponseParser.new(config: config)
143+
refute_equal Net::IMAP::Config.global, parser.config.parent
144+
assert_same config, parser.config.parent
145+
end
146+
112147
# Strangly, there are no example responses for BINARY[section] in either
113148
# RFC3516 or RFC9051! The closest I found was RFC5259, and those examples
114149
# aren't FETCH responses.

0 commit comments

Comments
 (0)