expect-pty 0.9.1 → 0.9.2
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/CHANGELOG.md +5 -0
- data/lib/expect/interaction.rb +2 -1
- data/lib/expect/pattern.rb +4 -1
- data/lib/expect/redactor.rb +4 -3
- data/lib/expect/relay/writer.rb +12 -4
- data/lib/expect/relay.rb +4 -1
- data/lib/expect/session.rb +2 -1
- data/lib/expect/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9d6ae394cf13d882d00a78b0684c158551e08896bf572272790d68cc7850d804
|
|
4
|
+
data.tar.gz: 2cada03b8804a8402bec3dfdbc54f705650d1b47d57b410e3e6c83d35af4cd9c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 64dbb1fbbed803a50dedda414a59f662121adcfee88de614f563e1de1d2f7c195f82d77f415a3a0fc545b420f5158e252637dada211c8ac35a98fa1728868748
|
|
7
|
+
data.tar.gz: d060fd85a2344e4e18d15257506844908f332100538517edbf6b5395e2a6bef0c98e0c12c44d21d26074eccb690ef6d1f81b4508056e85107239c84de3d7a09e
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.9.2 - 2026-10-18
|
|
6
|
+
|
|
7
|
+
- 减少显式搜索窗口下字面量匹配的内存分配,保留原始字节偏移、声明优先级和正则窗口语义。
|
|
8
|
+
- 修复脱敏尾部、匹配缓冲上限、转接历史及失败后的待写数据仍保留大块底层存储的问题,释放已丢弃或交付的字节并保留恢复进度。
|
|
9
|
+
|
|
5
10
|
## 0.9.1 - 2026-10-18
|
|
6
11
|
|
|
7
12
|
- 修复自定义 Numeric 转换失败时泄漏常规异常的问题;时间参数统一抛出 ArgumentError 并保留 cause,Interrupt/SystemExit 仍原样传播。
|
data/lib/expect/interaction.rb
CHANGED
|
@@ -192,7 +192,8 @@ module Expect
|
|
|
192
192
|
limit = [limit, 3].max if utf8
|
|
193
193
|
return unless history.bytesize > limit
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
# 保留历史对象身份,但独立复制尾部,释放已经转发的大前缀存储。
|
|
196
|
+
history.replace(history.unpack1("a*", offset: history.bytesize - limit))
|
|
196
197
|
return unless utf8
|
|
197
198
|
|
|
198
199
|
history.slice!(0) while (byte = history.getbyte(0)) && (0x80..0xBF).cover?(byte)
|
data/lib/expect/pattern.rb
CHANGED
|
@@ -52,9 +52,12 @@ module Expect
|
|
|
52
52
|
|
|
53
53
|
private
|
|
54
54
|
|
|
55
|
-
#
|
|
55
|
+
# 只匹配显式尾部窗口内的候选,返回偏移仍属于原始缓冲;字节协议不做转码。
|
|
56
56
|
def locate_window(buffer, size, final:, captures:)
|
|
57
57
|
start = buffer.bytesize - size
|
|
58
|
+
# 字面匹配没有锚点或回看,直接限制候选起点,复用原缓冲而不复制尾窗。
|
|
59
|
+
return locate(buffer, offset: start, final:, captures:) if value.is_a?(String)
|
|
60
|
+
|
|
58
61
|
start = utf8_window_start(buffer, start, final:) if value.is_a?(Regexp) && value.fixed_encoding? &&
|
|
59
62
|
value.encoding == Encoding::UTF_8
|
|
60
63
|
return nil unless start
|
data/lib/expect/redactor.rb
CHANGED
|
@@ -146,12 +146,13 @@ module Expect
|
|
|
146
146
|
cursor = ending
|
|
147
147
|
end
|
|
148
148
|
remaining = @pending.bytesize - length
|
|
149
|
-
|
|
150
|
-
@
|
|
149
|
+
# 尾部必须独占存储;共享切片会让几 KiB 的保留窗口继续持有整块输入及掩码。
|
|
150
|
+
@pending = @pending.unpack1("a*", offset: length)
|
|
151
|
+
@hidden = @hidden.unpack1("a*", offset: length)
|
|
151
152
|
if @suppressed
|
|
152
153
|
# 只追踪最后一个抑制字节的排空边界,避免每轮扫描字节图;跨块秘密掩码不受影响。
|
|
153
154
|
@suppressed_until -= length
|
|
154
|
-
@suppressed = @suppressed_until.positive? ? @suppressed.
|
|
155
|
+
@suppressed = @suppressed_until.positive? ? @suppressed.unpack1("a*", offset: length) : nil
|
|
155
156
|
end
|
|
156
157
|
@scanned_bytes = remaining
|
|
157
158
|
output
|
data/lib/expect/relay/writer.rb
CHANGED
|
@@ -13,6 +13,7 @@ module Expect
|
|
|
13
13
|
def initialize(target, data)
|
|
14
14
|
@target = target
|
|
15
15
|
@data = data
|
|
16
|
+
@data_start = 0
|
|
16
17
|
@offset = 0
|
|
17
18
|
@flushed = false
|
|
18
19
|
restart_timeout
|
|
@@ -33,7 +34,14 @@ module Expect
|
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
# 数据交付完但 flush 失败仍未完成;重试只补 flush,不重新发送已接受的数据。
|
|
36
|
-
def done? = @offset == @data.bytesize && @flushed
|
|
37
|
+
def done? = @offset == @data_start + @data.bytesize && @flushed
|
|
38
|
+
|
|
39
|
+
# 退出共同循环后只保留未交付字节,解除小切片与原始大输入的共享存储。
|
|
40
|
+
# offset 始终累计本排队块的确认进度;data_start 记录当前独立后缀在原块中的起点。
|
|
41
|
+
def detach_pending_data
|
|
42
|
+
@data = @data.unpack1("a*", offset: @offset - @data_start)
|
|
43
|
+
@data_start = @offset
|
|
44
|
+
end
|
|
37
45
|
|
|
38
46
|
# 每轮每目标至多一次写入;真实 IO 永不在此等待,交给 Relay 的共同 select。
|
|
39
47
|
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity -- 游标、短写、flush 和期限按单个目标推进。
|
|
@@ -41,8 +49,8 @@ module Expect
|
|
|
41
49
|
return false if done?
|
|
42
50
|
raise IOError, "closed Expect session" if target.is_a?(Session) && target.closed?
|
|
43
51
|
|
|
44
|
-
if @offset < @data.bytesize
|
|
45
|
-
bytes = @data.byteslice(@offset, READ_SIZE)
|
|
52
|
+
if @offset < @data_start + @data.bytesize
|
|
53
|
+
bytes = @data.byteslice(@offset - @data_start, READ_SIZE)
|
|
46
54
|
count = io ? io.write_nonblock(bytes, exception: false) : target.write(bytes)
|
|
47
55
|
if io && count == :wait_writable
|
|
48
56
|
check_timeout! if check_timeout
|
|
@@ -56,7 +64,7 @@ module Expect
|
|
|
56
64
|
# 先登记底层已接受的进度,再通知诊断;logger 失败后恢复只补未发送后缀。
|
|
57
65
|
trace_delivery(bytes.byteslice(0, count)) if target.is_a?(Session)
|
|
58
66
|
end
|
|
59
|
-
if @offset == @data.bytesize
|
|
67
|
+
if @offset == @data_start + @data.bytesize
|
|
60
68
|
# write_nonblock 已直接写到底层;普通 write 对象仍遵守自身 flush 协议。
|
|
61
69
|
target.flush if !io && target.respond_to?(:flush)
|
|
62
70
|
@flushed = true
|
data/lib/expect/relay.rb
CHANGED
|
@@ -159,7 +159,10 @@ module Expect
|
|
|
159
159
|
# 归还多来源缓冲和释放 token 属于同一交接,不能只恢复前几个来源就响应取消。
|
|
160
160
|
Thread.handle_interrupt(Object => :never) do
|
|
161
161
|
@previous.each { |session, buffer| session.interaction_buffer = buffer }
|
|
162
|
-
@buffers.each
|
|
162
|
+
@buffers.each do |session, buffer|
|
|
163
|
+
session.restore_relay_buffer(buffer)
|
|
164
|
+
session.pending_writes.each(&:detach_pending_data)
|
|
165
|
+
end
|
|
163
166
|
ensure
|
|
164
167
|
OWNERSHIP_MUTEX.synchronize do
|
|
165
168
|
@sessions.each do |session|
|
data/lib/expect/session.rb
CHANGED
|
@@ -549,7 +549,8 @@ module Expect
|
|
|
549
549
|
|
|
550
550
|
# 只累计匹配窗口裁剪,消费、清空及转接交接不算丢弃;关闭后仍可读取累计值。
|
|
551
551
|
@buffer_discarded_bytes += @buffer.bytesize - limit
|
|
552
|
-
|
|
552
|
+
# 小尾部不共享已丢弃前缀的底层存储,使上限同时约束长期保留的字节。
|
|
553
|
+
@buffer = @buffer.unpack1("a*", offset: @buffer.bytesize - limit)
|
|
553
554
|
@buffer_generation += 1
|
|
554
555
|
# 丢弃的前缀使当前窗口与已转发历史之间不再连续。
|
|
555
556
|
@relay_history.clear
|
data/lib/expect/version.rb
CHANGED