Skip to content

Bump httpx from 1.7.8 to 1.8.0#1004

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/httpx-1.8.0
Open

Bump httpx from 1.7.8 to 1.8.0#1004
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/bundler/httpx-1.8.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jun 17, 2026

Copy link
Copy Markdown
Contributor

Bumps httpx from 1.7.8 to 1.8.0.

Commits
  • c35a340 bump version to 1.8.0
  • 8c220c7 proxy: unescape user/password values for proxy options
  • 7a6aeb5 set minimum version of http-2 to 1.2.0
  • 87f036c Merge branch 'ping-timeout' into 'master'
  • bd3a58f Merge branch 'issue-383' into 'master'
  • 8b03569 new option: :ping_timeout
  • 54038bb new options: max_response_body_size, max_response_headers,
  • fa18331 Merge branch 'sse' into 'master'
  • 56840e1 test against incoming http-2 changes
  • faf50b7 fix sig for SSRFFilter.unsafe_ip_address?
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [httpx](https://gitlab.com/os85/httpx) from 1.7.8 to 1.8.0.
- [Commits](https://gitlab.com/os85/httpx/compare/v1.7.8...v1.8.0)

---
updated-dependencies:
- dependency-name: httpx
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies ruby Pull requests that update Ruby code labels Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

3 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

gem compare http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT version:
    1.1.3: 1.1.3
    1.2.0: 1.2.0
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
            lib/http/2/settings.rb +42/-0
      * Changed:
            lib/http/2/client.rb +1/-1
            lib/http/2/connection.rb +79/-62
            lib/http/2/extensions.rb +16/-10
            lib/http/2/flow_buffer.rb +7/-7
            lib/http/2/framer.rb +98/-98
            lib/http/2/header/compressor.rb +15/-4
            lib/http/2/header/decompressor.rb +11/-10
            lib/http/2/header/encoding_context.rb +18/-6
            lib/http/2/header/huffman.rb +6/-4
            lib/http/2/server.rb +12/-18
            lib/http/2/stream.rb +19/-12
            lib/http/2/version.rb +1/-1
            sig/2.rbs +64/-15
            sig/connection.rbs +11/-9
            sig/flow_buffer.rbs +2/-2
            sig/frame_buffer.rbs +4/-2
            sig/framer.rbs +8/-4
            sig/header/compressor.rbs +1/-0
            sig/header/encoding_context.rbs +4/-0
            sig/header/huffman.rbs +2/-0
            sig/server.rbs +1/-1
            sig/stream.rbs +7/-8

3 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

gem compare http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT version:
    1.1.3: 1.1.3
    1.2.0: 1.2.0
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
            lib/http/2/settings.rb +42/-0
      * Changed:
            lib/http/2/client.rb +1/-1
            lib/http/2/connection.rb +79/-62
            lib/http/2/extensions.rb +16/-10
            lib/http/2/flow_buffer.rb +7/-7
            lib/http/2/framer.rb +98/-98
            lib/http/2/header/compressor.rb +15/-4
            lib/http/2/header/decompressor.rb +11/-10
            lib/http/2/header/encoding_context.rb +18/-6
            lib/http/2/header/huffman.rb +6/-4
            lib/http/2/server.rb +12/-18
            lib/http/2/stream.rb +19/-12
            lib/http/2/version.rb +1/-1
            sig/2.rbs +64/-15
            sig/connection.rbs +11/-9
            sig/flow_buffer.rbs +2/-2
            sig/frame_buffer.rbs +4/-2
            sig/framer.rbs +8/-4
            sig/header/compressor.rbs +1/-0
            sig/header/encoding_context.rbs +4/-0
            sig/header/huffman.rbs +2/-0
            sig/server.rbs +1/-1
            sig/stream.rbs +7/-8

@github-actions

Copy link
Copy Markdown
Contributor

gem compare http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT version:
    1.1.3: 1.1.3
    1.2.0: 1.2.0
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
            lib/http/2/settings.rb +42/-0
      * Changed:
            lib/http/2/client.rb +1/-1
            lib/http/2/connection.rb +79/-62
            lib/http/2/extensions.rb +16/-10
            lib/http/2/flow_buffer.rb +7/-7
            lib/http/2/framer.rb +98/-98
            lib/http/2/header/compressor.rb +15/-4
            lib/http/2/header/decompressor.rb +11/-10
            lib/http/2/header/encoding_context.rb +18/-6
            lib/http/2/header/huffman.rb +6/-4
            lib/http/2/server.rb +12/-18
            lib/http/2/stream.rb +19/-12
            lib/http/2/version.rb +1/-1
            sig/2.rbs +64/-15
            sig/connection.rbs +11/-9
            sig/flow_buffer.rbs +2/-2
            sig/frame_buffer.rbs +4/-2
            sig/framer.rbs +8/-4
            sig/header/compressor.rbs +1/-0
            sig/header/encoding_context.rbs +4/-0
            sig/header/huffman.rbs +2/-0
            sig/server.rbs +1/-1
            sig/stream.rbs +7/-8

@github-actions

Copy link
Copy Markdown
Contributor

gem compare http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT version:
    1.1.3: 1.1.3
    1.2.0: 1.2.0
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
            lib/http/2/settings.rb +42/-0
      * Changed:
            lib/http/2/client.rb +1/-1
            lib/http/2/connection.rb +79/-62
            lib/http/2/extensions.rb +16/-10
            lib/http/2/flow_buffer.rb +7/-7
            lib/http/2/framer.rb +98/-98
            lib/http/2/header/compressor.rb +15/-4
            lib/http/2/header/decompressor.rb +11/-10
            lib/http/2/header/encoding_context.rb +18/-6
            lib/http/2/header/huffman.rb +6/-4
            lib/http/2/server.rb +12/-18
            lib/http/2/stream.rb +19/-12
            lib/http/2/version.rb +1/-1
            sig/2.rbs +64/-15
            sig/connection.rbs +11/-9
            sig/flow_buffer.rbs +2/-2
            sig/frame_buffer.rbs +4/-2
            sig/framer.rbs +8/-4
            sig/header/compressor.rbs +1/-0
            sig/header/encoding_context.rbs +4/-0
            sig/header/huffman.rbs +2/-0
            sig/server.rbs +1/-1
            sig/stream.rbs +7/-8

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
        lib/http/2/settings.rb
                --- /tmp/20260617-488-nbl71w	2026-06-17 02:34:11.859641898 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/settings.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -0,0 +1,42 @@
                +# frozen_string_literal: true
                +
                +module HTTP2
                +  # Default values for SETTINGS frame, as defined by the spec.
                +  SPEC_DEFAULT_CONNECTION_SETTINGS = {
                +    settings_header_table_size: 4096,
                +    settings_enable_push: 1, # enabled for servers
                +    settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
                +    settings_initial_window_size: 65_535,
                +    settings_max_frame_size: 16_384,
                +    settings_max_header_list_size: (2 << 30) - 1 # unlimited
                +  }.freeze
                +
                +  Settings = Struct.new(
                +    :settings_header_table_size,
                +    :settings_enable_push,
                +    :settings_max_concurrent_streams,
                +    :settings_initial_window_size,
                +    :settings_max_frame_size,
                +    :settings_max_header_list_size,
                +    keyword_init: true
                +  ) do
                +    def initialize(
                +      settings_header_table_size: 4096,
                +      settings_enable_push: 1,
                +      settings_max_concurrent_streams: 100,
                +      settings_initial_window_size: 65_535,
                +      settings_max_frame_size: 16_384,
                +      settings_max_header_list_size: (2 << 30) - 1
                +    )
                +      super
                +    end
                +
                +    def each_setting
                +      each_pair do |k, v|
                +        next if v == SPEC_DEFAULT_CONNECTION_SETTINGS[k]
                +
                +        yield k, v
                +      end
                +    end
                +  end
                +end
      * Changed:
        lib/http/2/client.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/client.rb	2026-06-17 02:34:11.851641922 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/client.rb	2026-06-17 02:34:11.856641907 +0000
                @@ -72 +72 @@
                -      frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
                +      frame = Framer.new.generate(type: :settings, stream: 0, flags: 0, payload: settings)
        lib/http/2/connection.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/connection.rb	2026-06-17 02:34:11.851641922 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/connection.rb	2026-06-17 02:34:11.856641907 +0000
                @@ -44,2 +43,0 @@
                -  HEADERS_FRAME_TYPES = %i[headers push_promise].freeze
                -
                @@ -93,0 +92 @@
                +      @oldest_stream_recently_closed = nil
                @@ -104,0 +104 @@
                +      @continuation_size = 0
                @@ -159 +159 @@
                -      send(type: :goaway, last_stream: @last_stream_id,
                +      send(type: :goaway, stream: 0, last_stream: @last_stream_id,
                @@ -181 +180,0 @@
                -      @pending_settings << payload
                @@ -215,3 +214,2 @@
                -        # @type var stream_id: Integer
                -        stream_id = frame[:stream]
                -        frame_type = frame[:type]
                +        stream_id = frame[:stream] #: Integer
                +        frame_type = frame[:type] #: Symbol?
                @@ -239,0 +238 @@
                +          # @type var frame: continuation_frame
                @@ -243,2 +242,2 @@
                -          unless frame[:flags].include? :end_headers
                -            buffered_payload = @continuation.sum { |f| f[:payload].bytesize }
                +          @continuation_size += frame[:payload].bytesize
                +          unless frame[:flags].anybits?(END_HEADERS)
                @@ -248 +247 @@
                -            unless buffered_payload < @local_settings[:settings_max_frame_size]
                +            unless @continuation_size < @local_settings[:settings_max_frame_size]
                @@ -261,0 +261 @@
                +          @continuation_size = 0
                @@ -265 +265 @@
                -          frame[:flags] << :end_headers
                +          frame[:flags] |= END_HEADERS
                @@ -273,0 +274 @@
                +          # @type var frame: connection_frame
                @@ -278,0 +280 @@
                +            # @type var frame: headers_frame
                @@ -285 +287 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -314,0 +317 @@
                +            # @type var frame: push_promise_frame
                @@ -317 +320 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -437,2 +439,0 @@
                -      frame_type = frame[:type]
                -
                @@ -440,2 +440,0 @@
                -      if frame_type == :data
                -        send_data(frame, true)
                @@ -443,3 +442 @@
                -      elsif frame_type == :rst_stream && frame[:error] == :protocol_error
                -        # An endpoint can end a connection at any time. In particular, an
                -        # endpoint MAY choose to treat a stream error as a connection error.
                +      frame_type = frame[:type] #: Symbol
                @@ -447,2 +444,5 @@
                -        goaway(:protocol_error)
                -      else
                +      case frame_type
                +      when :data
                +        #: @type var frame: data_frame
                +        send_data(frame, true)
                +      when :headers, :push_promise
                @@ -450,0 +451,10 @@
                +        #: @type var frame: headers_frame | push_promise_frame
                +        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                +      else
                +        if frame_type == :rst_stream && frame[:error] == :protocol_error
                +          # An endpoint can end a connection at any time. In particular, an
                +          # endpoint MAY choose to treat a stream error as a connection error.
                +
                +          goaway(:protocol_error)
                +        end
                +        #: @type var frame: connection_frame
                @@ -459,5 +469 @@
                -      if HEADERS_FRAME_TYPES.include?(frame[:type])
                -        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                -      else
                -        emit(:frame, @framer.generate(frame))
                -      end
                +      emit(:frame, @framer.generate(frame))
                @@ -495,0 +502 @@
                +          # @type var frame: settings_frame
                @@ -497,0 +505 @@
                +          # @type var frame: window_update_frame
                @@ -501,0 +510 @@
                +          # @type var frame: goaway_frame
                @@ -508,0 +518 @@
                +          # @type var frame: altsvc_frame
                @@ -515 +525,2 @@
                -          return if @h2c_upgrade || !frame[:flags].empty?
                +          # @type var frame: origin_frame
                +          return if @h2c_upgrade || !frame[:flags].zero?
                @@ -520,2 +530,0 @@
                -        when :blocked
                -          emit(:blocked, frame)
                @@ -541 +550 @@
                -      if frame[:flags].include? :ack
                +      if frame[:flags].anybits?(ACK)
                @@ -544,2 +553 @@
                -        send(type: :ping, stream: 0,
                -             flags: [:ack], payload: frame[:payload])
                +        send(type: :ping, stream: 0, flags: ACK, payload: frame[:payload])
                @@ -608 +616 @@
                -      if frame[:flags].include?(:ack)
                +      if frame[:flags].anybits?(ACK)
                @@ -613 +620,0 @@
                -        validate_settings(@remote_role, frame[:payload])
                @@ -614,0 +622 @@
                +        validate_settings(@remote_role, settings)
                @@ -684 +692 @@
                -          send(type: :settings, stream: 0, payload: [], flags: [:ack])
                +          send(type: :settings, stream: 0, payload: EMPTY, flags: ACK)
                @@ -714 +722 @@
                -      payload = headers_frame[:payload]
                +      headers_payload = headers_frame[:payload]
                @@ -716 +724 @@
                -        payload = headers_frame[:payload] = @compressor.encode(payload) unless payload.is_a?(String)
                +        payload = headers_payload.is_a?(String) ? headers_payload : @compressor.encode(headers_payload)
                @@ -720,0 +729,3 @@
                +      #: @type var payload: String
                +      headers_frame[:payload] = payload
                +
                @@ -725 +736 @@
                -        emit(:frame, @framer.generate(headers_frame))
                +        encode(headers_frame)
                @@ -730 +741,2 @@
                -      headers_frame[:flags].delete(:end_headers)
                +      total = payload.bytesize
                +      headers_frame[:flags] ^= END_HEADERS
                @@ -732 +744,2 @@
                -      payload = payload.byteslice(max_frame_size..-1)
                +      # payload = payload.byteslice(max_frame_size..-1)
                +      offset = max_frame_size
                @@ -735 +748 @@
                -      emit(:frame, @framer.generate(headers_frame))
                +      encode(headers_frame)
                @@ -737,6 +750 @@
                -      loop do
                -        continuation_frame = headers_frame.merge(
                -          type: :continuation,
                -          flags: EMPTY,
                -          payload: payload.byteslice(0, max_frame_size)
                -        )
                +      stream_id = headers_frame[:stream]
                @@ -744 +752,3 @@
                -        payload = payload.byteslice(max_frame_size..-1)
                +      while offset < total
                +        chunk_end = offset + max_frame_size
                +        is_last = chunk_end >= total
                @@ -746,5 +756,6 @@
                -        if payload.nil? || payload.empty?
                -          continuation_frame[:flags] = [:end_headers]
                -          emit(:frame, @framer.generate(continuation_frame))
                -          break
                -        end
                +        continuation_frame = {
                +          type: :continuation,
                +          flags: is_last ? END_HEADERS : 0,
                +          stream: stream_id,
                +          payload: payload.byteslice(offset, max_frame_size)
                +        } #: continuation_frame
                @@ -752 +763,2 @@
                -        emit(:frame, @framer.generate(continuation_frame))
                +        encode(continuation_frame)
                +        offset = chunk_end
                @@ -779,2 +790,0 @@
                -        _, closed_since = @streams_recently_closed.first
                -
                @@ -783 +793,2 @@
                -        if closed_since && (now - closed_since) > 15
                +        if @oldest_stream_recently_closed && (now - @oldest_stream_recently_closed) > 15
                +          new_oldest = nil
                @@ -786,3 +797,9 @@
                -          @streams_recently_closed = @streams_recently_closed.drop_while do |_, since|
                -            (now - since) > 15
                -          end.to_h
                +          @streams_recently_closed.delete_if do |_, since|
                +            unless (now - since) > 15
                +              new_oldest ||= since
                +              break
                +            end
                +
                +            true
                +          end
                +          @oldest_stream_recently_closed = new_oldest
                @@ -791 +808 @@
                -        @streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
                +        @streams_recently_closed[id] = now
        lib/http/2/extensions.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/extensions.rb	2026-06-17 02:34:11.851641922 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/extensions.rb	2026-06-17 02:34:11.856641907 +0000
                @@ -25,2 +25,3 @@
                -    def read_str(str, n)
                -      return "".b if n == 0
                +    if String.method_defined?(:bytesplice)
                +      def read_str(str, n)
                +        return "".b if n == 0
                @@ -28,4 +29,13 @@
                -      chunk = str.byteslice(0..(n - 1))
                -      remaining = str.byteslice(n..-1)
                -      remaining ? str.replace(remaining) : str.clear
                -      chunk
                +        chunk = str.byteslice(0, n)
                +        str.bytesplice(0, chunk.length, "")
                +        chunk
                +      end
                +    else
                +      def read_str(str, n)
                +        return "".b if n == 0
                +
                +        chunk = str.byteslice(0, n)
                +        remaining = str.byteslice(n, str.size - n)
                +        remaining ? str.replace(remaining) : str.clear
                +        chunk
                +      end
                @@ -36,4 +45,0 @@
                -    end
                -
                -    def shift_byte(str)
                -      read_str(str, 1).ord
        lib/http/2/flow_buffer.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/flow_buffer.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/flow_buffer.rb	2026-06-17 02:34:11.856641907 +0000
                @@ -73 +73 @@
                -          end_stream = frame[:flags].include?(:end_stream)
                +          end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -117,0 +118,2 @@
                +    include BufferUtils
                +
                @@ -143 +145 @@
                -      end_stream = frame[:flags].include?(:end_stream)
                +      end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -151,2 +153 @@
                -        chunk   = frame.dup
                -        payload = frame[:payload]
                +        chunk = frame.dup
                @@ -157 +158 @@
                -        chunk[:payload] = payload.byteslice(0, window_size)
                +        chunk[:payload] = read_str(frame[:payload], window_size) # mutates frame[:payload]
                @@ -159 +159,0 @@
                -        frame[:payload] = payload.byteslice(window_size..-1)
                @@ -163 +163 @@
                -        chunk[:flags] -= [:end_stream] if end_stream
                +        chunk[:flags] ^= END_STREAM if end_stream
        lib/http/2/framer.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/framer.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/framer.rb	2026-06-17 02:34:11.856641907 +0000
                @@ -3,0 +4,19 @@
                +  # Frame flags as defined by the spec (max 255 bits)
                +  # DATA:          ( X X COMPRESSED X PADDED X X END_STREAM )
                +  # HEADERS:       ( X X PRIORITY X PADDED END_HEADERS X END_STREAM )
                +  # PRIORITY:      ( X X X X X X X X )
                +  # RST_STREAM:    ( X X X X X X X X )
                +  # SETTINGS:      ( X X X X X X X ACK )
                +  # PUSH_PROMISE:  ( X X X X PADDED END_HEADERS X X )
                +  # PING:          ( X X X X X X X ACK )
                +  # GOAWAY:        ( X X X X X X X X )
                +  # WINDOW_UPDATE: ( X X X X X X X X )
                +  # CONTINUATION:  ( X X X X X END_HEADERS X X )
                +  # ALTSVC:        ( X X X X X X X X )
                +  # ORIGIN:        ( RESERVED4 X X RESERVED3 X RESERVED2 RESERVED X )
                +  END_STREAM = ACK = 0b0001 # 1
                +  RESERVED = 0b0010 # 2
                +  END_HEADERS = 0b0100 # 4
                +  PADDED = 0b1000 # 8
                +  PRIORITY = 0b0010_0000 # 32
                +
                @@ -43,33 +61,0 @@
                -    # Per frame flags as defined by the spec
                -    FRAME_FLAGS = {
                -      data: {
                -        end_stream: 0,
                -        padded: 3,
                -        compressed: 5
                -      },
                -      headers: {
                -        end_stream: 0,
                -        end_headers: 2,
                -        padded: 3,
                -        priority: 5
                -      },
                -      priority: {},
                -      rst_stream: {},
                -      settings: { ack: 0 },
                -      push_promise: {
                -        end_headers: 2,
                -        padded: 3
                -      },
                -      ping: { ack: 0 },
                -      goaway: {},
                -      window_update: {},
                -      continuation: { end_headers: 2 },
                -      altsvc: {},
                -      origin: {
                -        reserved: 1,
                -        reserved2: 2,
                -        reserved3: 4,
                -        reserved4: 8
                -      }
                -    }.each_value(&:freeze).freeze
                -
                @@ -86,17 +72,19 @@
                -    # Default error types as defined by the spec
                -    DEFINED_ERRORS = {
                -      no_error: 0,
                -      protocol_error: 1,
                -      internal_error: 2,
                -      flow_control_error: 3,
                -      settings_timeout: 4,
                -      stream_closed: 5,
                -      frame_size_error: 6,
                -      refused_stream: 7,
                -      cancel: 8,
                -      compression_error: 9,
                -      connect_error: 10,
                -      enhance_your_calm: 11,
                -      inadequate_security: 12,
                -      http_1_1_required: 13
                -    }.freeze
                +    DEFINED_SETTINGS_BY_ID = DEFINED_SETTINGS.invert.freeze
                +
                +    # Default error types as defined by the spec (the code is the array index)
                +    DEFINED_ERRORS = %i[
                +      no_error
                +      protocol_error
                +      internal_error
                +      flow_control_error
                +      settings_timeout
                +      stream_closed
                +      frame_size_error
                +      refused_stream
                +      cancel
                +      compression_error
                +      connect_error
                +      enhance_your_calm
                +      inadequate_security
                +      http_1_1_required
                +    ].freeze
                @@ -110,0 +99,2 @@
                +    PRIORITYPACK = (UINT32 + UINT8).freeze
                +    ALTSVCPACK = (UINT32 + UINT16).freeze
                @@ -114 +104 @@
                -    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :UINT32, :UINT16, :UINT8
                +    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :PRIORITYPACK, :UINT32, :UINT16, :UINT8
                @@ -148,0 +139,4 @@
                +      flags = frame[:flags]
                +
                +      raise CompressionError, "Invalid frame flag (#{flags}) for #{type}" unless flags.between?(0, 255)
                +
                @@ -163,6 +157 @@
                -             frame[:flags].reduce(0) do |acc, f|
                -               position = FRAME_FLAGS[type][f]
                -               raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
                -
                -               acc | (1 << position)
                -             end,
                +             flags,
                @@ -187,3 +176 @@
                -        flags: FRAME_FLAGS[type].filter_map do |name, pos|
                -          name if flags.anybits?(1 << pos)
                -        end,
                +        flags: flags,
                @@ -201 +188 @@
                -      frame[:flags] ||= EMPTY
                +      frame[:flags] ||= 0
                @@ -204,0 +192 @@
                +        # @type var frame: data_frame | continuation_frame
                @@ -216 +204 @@
                -          frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
                +          frame[:flags] |= PRIORITY
                @@ -219 +207 @@
                -        if frame[:flags].include?(:priority)
                +        if frame[:flags].anybits?(PRIORITY)
                @@ -222,2 +210,4 @@
                -          pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -          pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +          pack(
                +            [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +            PRIORITYPACK, buffer: bytes
                +          )
                @@ -237,2 +227,4 @@
                -        pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -        pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +        pack(
                +          [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +          PRIORITYPACK, buffer: bytes
                +        )
                @@ -251 +242,0 @@
                -        bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
                @@ -253,5 +244,6 @@
                -        settings.each do |(k, v)|
                -          if k.is_a? Integer # rubocop:disable Style/GuardClause
                -            DEFINED_SETTINGS.value?(k) || next
                -          else
                -            k = DEFINED_SETTINGS[k]
                +        case settings
                +        when String
                +          length = settings.bytesize
                +          bytes = settings
                +        else
                +          bytes = String.new("", encoding: Encoding::BINARY, capacity: settings.size * 6)
                @@ -259 +251,12 @@
                -            raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +          settings.each do |(k, v)|
                +            if k.is_a? Integer # rubocop:disable Style/GuardClause
                +              DEFINED_SETTINGS.value?(k) || next
                +            else
                +              k = DEFINED_SETTINGS[k]
                +
                +              raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +            end
                +
                +            pack([k], UINT16, buffer: bytes)
                +            pack([v], UINT32, buffer: bytes)
                +            length += 6
                @@ -261,4 +263,0 @@
                -
                -          pack([k], UINT16, buffer: bytes)
                -          pack([v], UINT32, buffer: bytes)
                -          length += 6
                @@ -298 +297 @@
                -        pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
                +        pack([frame[:max_age], frame[:port]], ALTSVCPACK, buffer: bytes)
                @@ -357 +356 @@
                -        frame[:flags] += [:padded]
                +        frame[:flags] |= PADDED
                @@ -378,3 +377,3 @@
                -      type = frame[:type]
                -      length = frame[:length]
                -      flags = frame[:flags]
                +      type = frame[:type] #: Symbol
                +      length = frame[:length] #: Integer
                +      flags = frame[:flags] #: Integer
                @@ -397 +396 @@
                -        padded = flags.include?(:padded)
                +        padded = flags.anybits?(PADDED)
                @@ -400 +398,0 @@
                -          frame[:padding] = padlen + 1
                @@ -402,0 +401,2 @@
                +          frame[:padding] = padlen + 1
                +
                @@ -405 +405 @@
                -          flags.delete(:padded)
                +          frame[:flags] ^= PADDED
                @@ -413 +413 @@
                -        if flags.include?(:priority)
                +        if flags.anybits?(PRIORITY)
                @@ -417 +417 @@
                -          weight = payload.byteslice(0, 1).ord + 1
                +          weight = payload.getbyte(0) + 1
                @@ -428 +428 @@
                -        weight = payload.byteslice(0, 1).ord + 1
                +        weight = payload.getbyte(0) + 1
                @@ -439 +438,0 @@
                -        frame[:payload] = []
                @@ -444 +443 @@
                -        (frame[:length] / 6).times do
                +        frame[:payload] = (frame[:length] / 6).times.filter_map do
                @@ -450,2 +449,3 @@
                -          name, = DEFINED_SETTINGS.find { |_name, v| v == id }
                -          frame[:payload] << [name, val] if name
                +          if (name = DEFINED_SETTINGS_BY_ID[id])
                +            [name, val]
                +          end
                @@ -467 +467 @@
                -        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
                +        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(ALTSVCPACK)
                @@ -469 +469 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -473 +473 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -498 +498 @@
                -        error = DEFINED_ERRORS[error]
                +        error = DEFINED_ERRORS.index(error)
                @@ -507 +507 @@
                -      DEFINED_ERRORS.key(error) || error
                +      DEFINED_ERRORS.fetch(error, error)
        lib/http/2/header/compressor.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/header/compressor.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/header/compressor.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -85,0 +86,2 @@
                +            integer(huffman.bytesize, 7, buffer: buffer)
                +            buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
                @@ -87 +89 @@
                -            set_huffman_size(buffer, huffman_offset)
                +            buffer
                @@ -122 +124 @@
                -        fb = buffer[offset].ord | rep[:pattern]
                +        fb = buffer.getbyte(offset) | rep[:pattern]
                @@ -149,0 +152 @@
                +        buffer << "\x00".b
                @@ -151 +154,9 @@
                -        set_huffman_size(buffer, huffman_offset)
                +        size = buffer.bytesize - huffman_offset - 1
                +
                +        if size < 127
                +          buffer.setbyte(huffman_offset, 0x80 | size)
                +        else
                +          buffer.slice!(huffman_offset, 1)
                +          set_huffman_size(buffer, huffman_offset)
                +        end
                +        buffer
                @@ -168 +179 @@
                -        buffer.setbyte(huffman_offset, buffer[huffman_offset].ord | 0x80)
                +        buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
        lib/http/2/header/decompressor.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/header/decompressor.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/header/decompressor.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -36 +36,7 @@
                -        i = n.zero? ? 0 : (shift_byte(buf) & limit)
                +        if n.zero?
                +          i = 0
                +          consumed = 0
                +        else
                +          i = buf.getbyte(0) & limit
                +          consumed = 1
                +        end
                @@ -38 +43,0 @@
                -        m = 0
                @@ -40,5 +45,2 @@
                -          offset = 0
                -
                -          buf.each_byte.with_index do |byte, idx|
                -            offset = idx
                -            # while (byte = shift_byte(buf))
                +          m = 0
                +          while (byte = buf.getbyte(consumed))
                @@ -47 +49 @@
                -
                +            consumed += 1
                @@ -50,2 +51,0 @@
                -
                -          read_str(buf, offset + 1)
                @@ -53,0 +54 @@
                +        read_str(buf, consumed)
        lib/http/2/header/encoding_context.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -120,0 +121,2 @@
                +        @table_by_field = Hash.new { |hs, k| hs[k] = [] }
                +        @unshifts = 0
                @@ -131,0 +134,2 @@
                +        tbf = @table_by_field.transform_values(&:dup)
                +        unshifts = @unshifts
                @@ -134,0 +139,2 @@
                +          @table_by_field = tbf
                +          @unshifts = unshifts
                @@ -215,0 +222,2 @@
                +            @unshifts += 1
                +            @table_by_field[name].unshift([value, @unshifts])
                @@ -282,2 +290 @@
                -          @table.each_with_index do |(hfield, hvalue), i|
                -            next unless field == hfield
                +          field_entries = @table_by_field[field]
                @@ -284,0 +292,3 @@
                +          field_entries&.each do |hvalue, unshift_id|
                +            abs_index = (@unshifts - unshift_id) + STATIC_TABLE_SIZE
                +            name_only ||= abs_index
                @@ -286 +296 @@
                -              exact = i + STATIC_TABLE_SIZE
                +              exact = abs_index
                @@ -288,2 +297,0 @@
                -            else
                -              name_only ||= i + STATIC_TABLE_SIZE
                @@ -320 +327,0 @@
                -
                @@ -322,0 +330,5 @@
                +
                +          field_arr = @table_by_field[name]
                +          field_arr.pop
                +          @table_by_field.delete(name) if field_arr.empty?
                +
        lib/http/2/header/huffman.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/header/huffman.rb	2026-06-17 02:34:11.852641919 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/header/huffman.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -22,0 +23,2 @@
                +      EOS_PADDING = (0..7).map { |n| ("1" * n).b.freeze }.freeze
                +
                @@ -32 +34 @@
                -        append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
                +        append_str(bitstring, EOS_PADDING[(8 - bitstring.size) % 8])
                @@ -57 +59 @@
                -            append_str(emit, first.chr) if first
                +            emit << first if first
                @@ -63 +65 @@
                -        emit.force_encoding(Encoding::BINARY)
                +        emit
                @@ -328 +330 @@
                -      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1] }.each(&:freeze).freeze
                +      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1].b.freeze }.freeze
        lib/http/2/server.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/server.rb	2026-06-17 02:34:11.853641916 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/server.rb	2026-06-17 02:34:11.857641904 +0000
                @@ -81,12 +81,6 @@
                -      buf = "".b
                -      append_str(buf, Base64.urlsafe_decode64(settings.to_s))
                -      @framer.common_header(
                -        {
                -          length: buf.bytesize,
                -          type: :settings,
                -          stream: 0,
                -          flags: []
                -        },
                -        buffer: buf
                -      )
                -      receive(buf)
                +      receive(@framer.generate(
                +                type: :settings,
                +                stream: 0,
                +                flags: 0,
                +                payload: Base64.urlsafe_decode64(settings.to_s)
                +              ))
                @@ -100 +94 @@
                -        flags: [:end_headers],
                +        flags: END_HEADERS,
                @@ -109 +103 @@
                -        headers_frame[:flags] << [:end_stream]
                +        headers_frame[:flags] |= END_HEADERS
                @@ -113 +107 @@
                -        stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
                +        stream << { type: :data, stream: 1, payload: body, flags: END_STREAM }
                @@ -138 +132 @@
                -      return unless frame[:flags].include?(:ack) && !@origins_sent
                +      return unless frame[:flags].anybits?(ACK) && !@origins_sent
                @@ -151 +145 @@
                -    # @param flags [Array[Symbol]]
                +    # @param flags Integer
                @@ -160 +154 @@
                -        payload: headers.to_a
                +        payload: headers
        lib/http/2/stream.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/stream.rb	2026-06-17 02:34:11.853641916 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/stream.rb	2026-06-17 02:34:11.858641901 +0000
                @@ -117 +117,2 @@
                -      case frame[:type]
                +      frame_type = frame[:type] #: Symbol
                +      case frame_type
                @@ -118,0 +120 @@
                +        # @type var frame: data_frame
                @@ -131,0 +134 @@
                +        # @type var frame: headers_frame
                @@ -153,0 +157 @@
                +        # @type var frame: priority_frame
                @@ -155,0 +160 @@
                +        # @type var frame: window_update_frame
                @@ -157,0 +163 @@
                +        # @type var frame: origin_frame
                @@ -162,3 +168 @@
                -        emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty?
                -      when :blocked
                -        emit(frame[:type], frame)
                +        emit(frame_type, frame) if !frame[:origin] || frame[:origin].empty?
                @@ -201,0 +206 @@
                +        # @type var frame: data_frame
                @@ -204,0 +210 @@
                +        # @type var frame: window_update_frame
                @@ -206,0 +213 @@
                +        # @type var frame: priority_frame
                @@ -222,3 +229,2 @@
                -      flags = []
                -      flags << :end_headers if end_headers
                -      flags << :end_stream  if end_stream || @_method == "HEAD"
                +      flags = end_headers ? END_HEADERS : 0
                +      flags |= END_STREAM  if end_stream || @_method == "HEAD"
                @@ -232 +238 @@
                -      flags = end_headers ? [:end_headers] : []
                +      flags = end_headers ? END_HEADERS : 0
                @@ -257 +263 @@
                -          send(type: :data, flags: [], payload: chunk)
                +          send(type: :data, flags: 0, payload: chunk)
                @@ -261,2 +267,2 @@
                -      flags = []
                -      flags << :end_stream if end_stream
                +      flags = 0
                +      flags |= END_STREAM if end_stream
                @@ -666 +672,2 @@
                -        frame[:flags] && frame[:flags].include?(:end_stream)
                +        # @type var frame: data_frame | headers_frame | continuation_frame
                +        frame[:flags] && frame[:flags].anybits?(END_STREAM)
        lib/http/2/version.rb
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/lib/http/2/version.rb	2026-06-17 02:34:11.853641916 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/lib/http/2/version.rb	2026-06-17 02:34:11.858641901 +0000
                @@ -4 +4 @@
                -  VERSION = "1.1.3"
                +  VERSION = "1.2.0"
        sig/2.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/2.rbs	2026-06-17 02:34:11.853641916 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/2.rbs	2026-06-17 02:34:11.858641901 +0000
                @@ -38,0 +39,8 @@
                +  # Frame flags
                +  END_STREAM: Integer
                +  ACK: Integer
                +  RESERVED: Integer
                +  END_HEADERS: Integer
                +  PADDED: Integer
                +  PRIORITY: Integer
                +
                @@ -42 +50,3 @@
                -  type frame_control_flags = Array[:end_headers | :end_stream]
                +  type frame_control_flags = Integer
                +
                +  type common_frame = { stream: Integer, flags: frame_control_flags, ?length: Integer, ?ignore: bool }
                @@ -44 +54 @@
                -  type common_frame = { stream: Integer }
                +  type connection_frame = settings_frame | ping_frame | goaway_frame | window_update_frame | altsvc_frame | origin_frame
                @@ -47,2 +57,2 @@
                -  type headers_frame = common_frame & {
                -    type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
                +  type headers_frame_props = {
                +    type: :headers, payload: Enumerable[header_pair] | String,
                @@ -50,0 +61,5 @@
                +  type headers_frame = common_frame & headers_frame_props
                +
                +  type continuation_frame_props = headers_frame_props | { type: :continuation }
                +
                +  type continuation_frame = common_frame & continuation_frame_props
                @@ -53 +68,3 @@
                -  type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
                +  type data_frame_props = { type: :data, ?length: Integer, payload: String, ?padding: Integer }
                +
                +  type data_frame = common_frame & data_frame_props
                @@ -56 +73,3 @@
                -  type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
                +  type push_promise_frame_props = { promise_stream: Integer, ?length: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair] | String, ?padding: Integer }
                +
                +  type push_promise_frame = common_frame & push_promise_frame_props
                @@ -59 +78,3 @@
                -  type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
                +  type settings_frame_props = { type: :settings, payload: (Enumerable[[Symbol | Integer, Integer]] | String) }
                +
                +  type settings_frame = common_frame & settings_frame_props
                @@ -62 +83,3 @@
                -  type window_update_frame = { type: :window_update, increment: Integer }
                +  type window_update_frame_props = { type: :window_update, increment: Integer }
                +
                +  type window_update_frame = common_frame & window_update_frame_props
                @@ -65 +88,5 @@
                -  type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
                +  type priority_frame_inner_props = { dependency: Integer, exclusive: bool, weight: Integer }
                +
                +  type priority_frame_props = { type: :priority } & priority_frame_inner_props
                +
                +  type priority_frame = common_frame & priority_frame_props
                @@ -68 +95,3 @@
                -  type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
                +  type altsvc_frame_props = { type: :altsvc, max_age: Integer, port: Integer, proto: String, host: String }
                +
                +  type altsvc_frame = common_frame & altsvc_frame_props
                @@ -71 +100,3 @@
                -  type origin_frame = { type: :origin, origin: Array[String] }
                +  type origin_frame_props = { type: :origin, payload: Array[String] }
                +
                +  type origin_frame = common_frame & origin_frame_props
                @@ -74 +105,3 @@
                -  type ping_frame = { type: :ping, payload: String, length: Integer }
                +  type ping_frame_props = { type: :ping, payload: String }
                +
                +  type ping_frame = common_frame & ping_frame_props
                @@ -77 +110,3 @@
                -  type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
                +  type goaway_frame_props = { type: :goaway, last_stream: Integer, error: (Symbol | Integer)? }
                +
                +  type goaway_frame = common_frame & goaway_frame_props
                @@ -79 +114,6 @@
                -  # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
                +  # # RST_STREAM
                +  type rst_stream_frame_props = { type: :rst_stream, error: (Symbol | Integer)? }
                +
                +  type rst_stream_frame = common_frame & rst_stream_frame_props
                +
                +  # type frame = headers_frame | continuation_frame | push_promise_frame | data_frame |
                @@ -81 +121,8 @@
                -  #              origin_frame | ping_frame | goaway_frame)
                +  #              origin_frame | ping_frame | goaway_frame | rst_stream_frame
                +
                +  # type connection_frame_props = rst_stream_frame_props | ping_frame_props | goaway_frame_props
                +  #                             | window_update_frame_props | settings_frame_props
                +
                +  # type stream_frame_props = headers_frame_props | continuation_frame_props | push_promise_frame_props
                +  #                         | data_frame_props  | rst_stream_frame_props | priority_frame_props
                +  #                         | window_update_frame_props | origin_frame_props | altsvc_frame_props
                @@ -111,0 +159,2 @@
                +  type connection_frame_props = Hash[frame_key, frame_value]
                +  type stream_frame_props = Hash[frame_key, frame_value]
        sig/connection.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/connection.rbs	2026-06-17 02:34:11.853641916 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/connection.rbs	2026-06-17 02:34:11.858641901 +0000
                @@ -35,0 +36 @@
                +    @oldest_stream_recently_closed: Numeric
                @@ -52,0 +54 @@
                +    @continuation_size: Integer
                @@ -71 +73 @@
                -    def receive: (string data) -> void
                +    def receive: (String data) -> void
                @@ -78 +80 @@
                -    def send: (frame frame) -> void
                +    def send: (connection_frame_props | stream_frame_props frame) -> void
                @@ -84 +86 @@
                -    def connection_management: (frame) -> void
                +    def connection_management: (connection_frame frame) -> void
                @@ -90 +92 @@
                -    def connection_settings: (frame) -> void
                +    def connection_settings: (settings_frame) -> void
                @@ -92 +94 @@
                -    def decode_headers: (frame) -> void
                +    def decode_headers: (headers_frame | push_promise_frame) -> void
                @@ -94 +96 @@
                -    def encode_headers: (frame headers_frame) -> void
                +    def encode_headers: (headers_frame | push_promise_frame) -> void
                @@ -100 +102 @@
                -    def verify_pseudo_headers: (frame) -> void
                +    def verify_pseudo_headers: (headers_frame | push_promise_frame) -> void
                @@ -102 +104 @@
                -    def _verify_pseudo_headers: (frame, Array[String]) -> void
                +    def _verify_pseudo_headers: (headers_frame | push_promise_frame, Array[String]) -> void
                @@ -106 +108 @@
                -end
                \ No newline at end of file
                +end
        sig/flow_buffer.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/flow_buffer.rbs	2026-06-17 02:34:11.854641913 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/flow_buffer.rbs	2026-06-17 02:34:11.858641901 +0000
                @@ -17 +17 @@
                -    def send_data: (?data_frame? frame, ?bool encode) -> void
                +    def send_data: (?data_frame_props? frame, ?bool encode) -> void
                @@ -19 +19 @@
                -    def send_frame: (data_frame frame, bool encode) -> void
                +    def send_frame: (data_frame_props frame, bool encode) -> void
        sig/frame_buffer.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/frame_buffer.rbs	2026-06-17 02:34:11.854641913 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/frame_buffer.rbs	2026-06-17 02:34:11.858641901 +0000
                @@ -2,0 +3,2 @@
                +    include BufferUtils
                +
                @@ -9 +11 @@
                -    def <<: (data_frame frame) -> void
                +    def <<: (data_frame_props frame) -> void
                @@ -13 +15 @@
                -    def retrieve: (Integer) -> data_frame?
                +    def retrieve: (Integer) -> data_frame_props?
        sig/framer.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/framer.rbs	2026-06-17 02:34:11.854641913 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/framer.rbs	2026-06-17 02:34:11.858641901 +0000
                @@ -23 +23,3 @@
                -    DEFINED_ERRORS: Hash[Symbol, Integer]
                +    DEFINED_SETTINGS_BY_ID: Hash[Integer, Symbol]
                +
                +    DEFINED_ERRORS: Array[Symbol]
                @@ -31,0 +34,2 @@
                +    PRIORITYPACK: String
                +    ALTSVCPACK: String
                @@ -44 +48 @@
                -    def read_common_header: (String buf) -> frame
                +    def read_common_header: (String buf) -> (common_frame | { length: Integer })
                @@ -50 +54 @@
                -    def parse: (String) -> frame?
                +    def parse: (String) -> (frame | { length: Integer })?
                @@ -56 +60 @@
                -    def pack_error: (Integer | Symbol error, buffer: String) -> String
                +    def pack_error: (Symbol | Integer error, buffer: String) -> String
        sig/header/compressor.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/header/compressor.rbs	2026-06-17 02:34:11.854641913 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/header/compressor.rbs	2026-06-17 02:34:11.859641898 +0000
                @@ -4,0 +5 @@
                +      include BufferUtils
        sig/header/encoding_context.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/header/encoding_context.rbs	2026-06-17 02:34:11.855641910 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/header/encoding_context.rbs	2026-06-17 02:34:11.859641898 +0000
                @@ -24,0 +25,4 @@
                +      @table_by_field: Hash[string, Array[[string, Integer]]]
                +
                +      @unshifts: Integer
                +
        sig/header/huffman.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/header/huffman.rbs	2026-06-17 02:34:11.855641910 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/header/huffman.rbs	2026-06-17 02:34:11.859641898 +0000
                @@ -11,0 +12,2 @@
                +      EOS_PADDING: Array[String]
                +
        sig/server.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/server.rbs	2026-06-17 02:34:11.855641910 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/server.rbs	2026-06-17 02:34:11.859641898 +0000
                @@ -10 +10 @@
                -    def promise: (Stream parent, Enumerable[header_pair] headers, Array[Symbol] flags) { (Stream) -> void } -> void
                +    def promise: (Stream parent, Enumerable[header_pair] headers, frame_control_flags flags) { (Stream) -> void } -> void
        sig/stream.rbs
                --- /tmp/d20260617-488-gyrnqn/http-2-1.1.3/sig/stream.rbs	2026-06-17 02:34:11.855641910 +0000
                +++ /tmp/d20260617-488-gyrnqn/http-2-1.2.0/sig/stream.rbs	2026-06-17 02:34:11.859641898 +0000
                @@ -40 +40 @@
                -    def send: (frame frame) -> void
                +    def send: (stream_frame_props frame) -> void
                @@ -73 +73 @@
                -    def transition: (frame, bool sending) -> void
                +    def transition: (stream_frame_props frame, bool sending) -> void
                @@ -83 +83 @@
                -    def process_priority: (priority_frame frame) -> void
                +    def process_priority: (priority_frame_inner_props frame) -> void
                @@ -85 +85 @@
                -    def end_stream?: (frame frame) -> boolish
                +    def end_stream?: (stream_frame_props frame) -> boolish
                @@ -87,2 +87 @@
                -    def stream_error: (Symbol error, ?msg: String?) -> void
                -                    | () -> void
                +    def stream_error: (?Symbol error, ?msg: String?) -> void
                @@ -92 +91 @@
                -    def manage_state: (frame) { () -> void } -> void
                +    def manage_state: (stream_frame_props frame) { () -> void } -> void
                @@ -94 +93 @@
                -end
                \ No newline at end of file
                +end

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
        lib/http/2/settings.rb
                --- /tmp/20260617-525-72ejs	2026-06-17 02:34:12.823525970 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/settings.rb	2026-06-17 02:34:12.821525941 +0000
                @@ -0,0 +1,42 @@
                +# frozen_string_literal: true
                +
                +module HTTP2
                +  # Default values for SETTINGS frame, as defined by the spec.
                +  SPEC_DEFAULT_CONNECTION_SETTINGS = {
                +    settings_header_table_size: 4096,
                +    settings_enable_push: 1, # enabled for servers
                +    settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
                +    settings_initial_window_size: 65_535,
                +    settings_max_frame_size: 16_384,
                +    settings_max_header_list_size: (2 << 30) - 1 # unlimited
                +  }.freeze
                +
                +  Settings = Struct.new(
                +    :settings_header_table_size,
                +    :settings_enable_push,
                +    :settings_max_concurrent_streams,
                +    :settings_initial_window_size,
                +    :settings_max_frame_size,
                +    :settings_max_header_list_size,
                +    keyword_init: true
                +  ) do
                +    def initialize(
                +      settings_header_table_size: 4096,
                +      settings_enable_push: 1,
                +      settings_max_concurrent_streams: 100,
                +      settings_initial_window_size: 65_535,
                +      settings_max_frame_size: 16_384,
                +      settings_max_header_list_size: (2 << 30) - 1
                +    )
                +      super
                +    end
                +
                +    def each_setting
                +      each_pair do |k, v|
                +        next if v == SPEC_DEFAULT_CONNECTION_SETTINGS[k]
                +
                +        yield k, v
                +      end
                +    end
                +  end
                +end
      * Changed:
        lib/http/2/client.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/client.rb	2026-06-17 02:34:12.814525841 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/client.rb	2026-06-17 02:34:12.819525913 +0000
                @@ -72 +72 @@
                -      frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
                +      frame = Framer.new.generate(type: :settings, stream: 0, flags: 0, payload: settings)
        lib/http/2/connection.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/connection.rb	2026-06-17 02:34:12.814525841 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/connection.rb	2026-06-17 02:34:12.819525913 +0000
                @@ -44,2 +43,0 @@
                -  HEADERS_FRAME_TYPES = %i[headers push_promise].freeze
                -
                @@ -93,0 +92 @@
                +      @oldest_stream_recently_closed = nil
                @@ -104,0 +104 @@
                +      @continuation_size = 0
                @@ -159 +159 @@
                -      send(type: :goaway, last_stream: @last_stream_id,
                +      send(type: :goaway, stream: 0, last_stream: @last_stream_id,
                @@ -181 +180,0 @@
                -      @pending_settings << payload
                @@ -215,3 +214,2 @@
                -        # @type var stream_id: Integer
                -        stream_id = frame[:stream]
                -        frame_type = frame[:type]
                +        stream_id = frame[:stream] #: Integer
                +        frame_type = frame[:type] #: Symbol?
                @@ -239,0 +238 @@
                +          # @type var frame: continuation_frame
                @@ -243,2 +242,2 @@
                -          unless frame[:flags].include? :end_headers
                -            buffered_payload = @continuation.sum { |f| f[:payload].bytesize }
                +          @continuation_size += frame[:payload].bytesize
                +          unless frame[:flags].anybits?(END_HEADERS)
                @@ -248 +247 @@
                -            unless buffered_payload < @local_settings[:settings_max_frame_size]
                +            unless @continuation_size < @local_settings[:settings_max_frame_size]
                @@ -261,0 +261 @@
                +          @continuation_size = 0
                @@ -265 +265 @@
                -          frame[:flags] << :end_headers
                +          frame[:flags] |= END_HEADERS
                @@ -273,0 +274 @@
                +          # @type var frame: connection_frame
                @@ -278,0 +280 @@
                +            # @type var frame: headers_frame
                @@ -285 +287 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -314,0 +317 @@
                +            # @type var frame: push_promise_frame
                @@ -317 +320 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -437,2 +439,0 @@
                -      frame_type = frame[:type]
                -
                @@ -440,2 +440,0 @@
                -      if frame_type == :data
                -        send_data(frame, true)
                @@ -443,3 +442 @@
                -      elsif frame_type == :rst_stream && frame[:error] == :protocol_error
                -        # An endpoint can end a connection at any time. In particular, an
                -        # endpoint MAY choose to treat a stream error as a connection error.
                +      frame_type = frame[:type] #: Symbol
                @@ -447,2 +444,5 @@
                -        goaway(:protocol_error)
                -      else
                +      case frame_type
                +      when :data
                +        #: @type var frame: data_frame
                +        send_data(frame, true)
                +      when :headers, :push_promise
                @@ -450,0 +451,10 @@
                +        #: @type var frame: headers_frame | push_promise_frame
                +        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                +      else
                +        if frame_type == :rst_stream && frame[:error] == :protocol_error
                +          # An endpoint can end a connection at any time. In particular, an
                +          # endpoint MAY choose to treat a stream error as a connection error.
                +
                +          goaway(:protocol_error)
                +        end
                +        #: @type var frame: connection_frame
                @@ -459,5 +469 @@
                -      if HEADERS_FRAME_TYPES.include?(frame[:type])
                -        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                -      else
                -        emit(:frame, @framer.generate(frame))
                -      end
                +      emit(:frame, @framer.generate(frame))
                @@ -495,0 +502 @@
                +          # @type var frame: settings_frame
                @@ -497,0 +505 @@
                +          # @type var frame: window_update_frame
                @@ -501,0 +510 @@
                +          # @type var frame: goaway_frame
                @@ -508,0 +518 @@
                +          # @type var frame: altsvc_frame
                @@ -515 +525,2 @@
                -          return if @h2c_upgrade || !frame[:flags].empty?
                +          # @type var frame: origin_frame
                +          return if @h2c_upgrade || !frame[:flags].zero?
                @@ -520,2 +530,0 @@
                -        when :blocked
                -          emit(:blocked, frame)
                @@ -541 +550 @@
                -      if frame[:flags].include? :ack
                +      if frame[:flags].anybits?(ACK)
                @@ -544,2 +553 @@
                -        send(type: :ping, stream: 0,
                -             flags: [:ack], payload: frame[:payload])
                +        send(type: :ping, stream: 0, flags: ACK, payload: frame[:payload])
                @@ -608 +616 @@
                -      if frame[:flags].include?(:ack)
                +      if frame[:flags].anybits?(ACK)
                @@ -613 +620,0 @@
                -        validate_settings(@remote_role, frame[:payload])
                @@ -614,0 +622 @@
                +        validate_settings(@remote_role, settings)
                @@ -684 +692 @@
                -          send(type: :settings, stream: 0, payload: [], flags: [:ack])
                +          send(type: :settings, stream: 0, payload: EMPTY, flags: ACK)
                @@ -714 +722 @@
                -      payload = headers_frame[:payload]
                +      headers_payload = headers_frame[:payload]
                @@ -716 +724 @@
                -        payload = headers_frame[:payload] = @compressor.encode(payload) unless payload.is_a?(String)
                +        payload = headers_payload.is_a?(String) ? headers_payload : @compressor.encode(headers_payload)
                @@ -720,0 +729,3 @@
                +      #: @type var payload: String
                +      headers_frame[:payload] = payload
                +
                @@ -725 +736 @@
                -        emit(:frame, @framer.generate(headers_frame))
                +        encode(headers_frame)
                @@ -730 +741,2 @@
                -      headers_frame[:flags].delete(:end_headers)
                +      total = payload.bytesize
                +      headers_frame[:flags] ^= END_HEADERS
                @@ -732 +744,2 @@
                -      payload = payload.byteslice(max_frame_size..-1)
                +      # payload = payload.byteslice(max_frame_size..-1)
                +      offset = max_frame_size
                @@ -735 +748 @@
                -      emit(:frame, @framer.generate(headers_frame))
                +      encode(headers_frame)
                @@ -737,6 +750 @@
                -      loop do
                -        continuation_frame = headers_frame.merge(
                -          type: :continuation,
                -          flags: EMPTY,
                -          payload: payload.byteslice(0, max_frame_size)
                -        )
                +      stream_id = headers_frame[:stream]
                @@ -744 +752,3 @@
                -        payload = payload.byteslice(max_frame_size..-1)
                +      while offset < total
                +        chunk_end = offset + max_frame_size
                +        is_last = chunk_end >= total
                @@ -746,5 +756,6 @@
                -        if payload.nil? || payload.empty?
                -          continuation_frame[:flags] = [:end_headers]
                -          emit(:frame, @framer.generate(continuation_frame))
                -          break
                -        end
                +        continuation_frame = {
                +          type: :continuation,
                +          flags: is_last ? END_HEADERS : 0,
                +          stream: stream_id,
                +          payload: payload.byteslice(offset, max_frame_size)
                +        } #: continuation_frame
                @@ -752 +763,2 @@
                -        emit(:frame, @framer.generate(continuation_frame))
                +        encode(continuation_frame)
                +        offset = chunk_end
                @@ -779,2 +790,0 @@
                -        _, closed_since = @streams_recently_closed.first
                -
                @@ -783 +793,2 @@
                -        if closed_since && (now - closed_since) > 15
                +        if @oldest_stream_recently_closed && (now - @oldest_stream_recently_closed) > 15
                +          new_oldest = nil
                @@ -786,3 +797,9 @@
                -          @streams_recently_closed = @streams_recently_closed.drop_while do |_, since|
                -            (now - since) > 15
                -          end.to_h
                +          @streams_recently_closed.delete_if do |_, since|
                +            unless (now - since) > 15
                +              new_oldest ||= since
                +              break
                +            end
                +
                +            true
                +          end
                +          @oldest_stream_recently_closed = new_oldest
                @@ -791 +808 @@
                -        @streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
                +        @streams_recently_closed[id] = now
        lib/http/2/extensions.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/extensions.rb	2026-06-17 02:34:12.814525841 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/extensions.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -25,2 +25,3 @@
                -    def read_str(str, n)
                -      return "".b if n == 0
                +    if String.method_defined?(:bytesplice)
                +      def read_str(str, n)
                +        return "".b if n == 0
                @@ -28,4 +29,13 @@
                -      chunk = str.byteslice(0..(n - 1))
                -      remaining = str.byteslice(n..-1)
                -      remaining ? str.replace(remaining) : str.clear
                -      chunk
                +        chunk = str.byteslice(0, n)
                +        str.bytesplice(0, chunk.length, "")
                +        chunk
                +      end
                +    else
                +      def read_str(str, n)
                +        return "".b if n == 0
                +
                +        chunk = str.byteslice(0, n)
                +        remaining = str.byteslice(n, str.size - n)
                +        remaining ? str.replace(remaining) : str.clear
                +        chunk
                +      end
                @@ -36,4 +45,0 @@
                -    end
                -
                -    def shift_byte(str)
                -      read_str(str, 1).ord
        lib/http/2/flow_buffer.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/flow_buffer.rb	2026-06-17 02:34:12.814525841 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/flow_buffer.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -73 +73 @@
                -          end_stream = frame[:flags].include?(:end_stream)
                +          end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -117,0 +118,2 @@
                +    include BufferUtils
                +
                @@ -143 +145 @@
                -      end_stream = frame[:flags].include?(:end_stream)
                +      end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -151,2 +153 @@
                -        chunk   = frame.dup
                -        payload = frame[:payload]
                +        chunk = frame.dup
                @@ -157 +158 @@
                -        chunk[:payload] = payload.byteslice(0, window_size)
                +        chunk[:payload] = read_str(frame[:payload], window_size) # mutates frame[:payload]
                @@ -159 +159,0 @@
                -        frame[:payload] = payload.byteslice(window_size..-1)
                @@ -163 +163 @@
                -        chunk[:flags] -= [:end_stream] if end_stream
                +        chunk[:flags] ^= END_STREAM if end_stream
        lib/http/2/framer.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/framer.rb	2026-06-17 02:34:12.814525841 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/framer.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -3,0 +4,19 @@
                +  # Frame flags as defined by the spec (max 255 bits)
                +  # DATA:          ( X X COMPRESSED X PADDED X X END_STREAM )
                +  # HEADERS:       ( X X PRIORITY X PADDED END_HEADERS X END_STREAM )
                +  # PRIORITY:      ( X X X X X X X X )
                +  # RST_STREAM:    ( X X X X X X X X )
                +  # SETTINGS:      ( X X X X X X X ACK )
                +  # PUSH_PROMISE:  ( X X X X PADDED END_HEADERS X X )
                +  # PING:          ( X X X X X X X ACK )
                +  # GOAWAY:        ( X X X X X X X X )
                +  # WINDOW_UPDATE: ( X X X X X X X X )
                +  # CONTINUATION:  ( X X X X X END_HEADERS X X )
                +  # ALTSVC:        ( X X X X X X X X )
                +  # ORIGIN:        ( RESERVED4 X X RESERVED3 X RESERVED2 RESERVED X )
                +  END_STREAM = ACK = 0b0001 # 1
                +  RESERVED = 0b0010 # 2
                +  END_HEADERS = 0b0100 # 4
                +  PADDED = 0b1000 # 8
                +  PRIORITY = 0b0010_0000 # 32
                +
                @@ -43,33 +61,0 @@
                -    # Per frame flags as defined by the spec
                -    FRAME_FLAGS = {
                -      data: {
                -        end_stream: 0,
                -        padded: 3,
                -        compressed: 5
                -      },
                -      headers: {
                -        end_stream: 0,
                -        end_headers: 2,
                -        padded: 3,
                -        priority: 5
                -      },
                -      priority: {},
                -      rst_stream: {},
                -      settings: { ack: 0 },
                -      push_promise: {
                -        end_headers: 2,
                -        padded: 3
                -      },
                -      ping: { ack: 0 },
                -      goaway: {},
                -      window_update: {},
                -      continuation: { end_headers: 2 },
                -      altsvc: {},
                -      origin: {
                -        reserved: 1,
                -        reserved2: 2,
                -        reserved3: 4,
                -        reserved4: 8
                -      }
                -    }.each_value(&:freeze).freeze
                -
                @@ -86,17 +72,19 @@
                -    # Default error types as defined by the spec
                -    DEFINED_ERRORS = {
                -      no_error: 0,
                -      protocol_error: 1,
                -      internal_error: 2,
                -      flow_control_error: 3,
                -      settings_timeout: 4,
                -      stream_closed: 5,
                -      frame_size_error: 6,
                -      refused_stream: 7,
                -      cancel: 8,
                -      compression_error: 9,
                -      connect_error: 10,
                -      enhance_your_calm: 11,
                -      inadequate_security: 12,
                -      http_1_1_required: 13
                -    }.freeze
                +    DEFINED_SETTINGS_BY_ID = DEFINED_SETTINGS.invert.freeze
                +
                +    # Default error types as defined by the spec (the code is the array index)
                +    DEFINED_ERRORS = %i[
                +      no_error
                +      protocol_error
                +      internal_error
                +      flow_control_error
                +      settings_timeout
                +      stream_closed
                +      frame_size_error
                +      refused_stream
                +      cancel
                +      compression_error
                +      connect_error
                +      enhance_your_calm
                +      inadequate_security
                +      http_1_1_required
                +    ].freeze
                @@ -110,0 +99,2 @@
                +    PRIORITYPACK = (UINT32 + UINT8).freeze
                +    ALTSVCPACK = (UINT32 + UINT16).freeze
                @@ -114 +104 @@
                -    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :UINT32, :UINT16, :UINT8
                +    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :PRIORITYPACK, :UINT32, :UINT16, :UINT8
                @@ -148,0 +139,4 @@
                +      flags = frame[:flags]
                +
                +      raise CompressionError, "Invalid frame flag (#{flags}) for #{type}" unless flags.between?(0, 255)
                +
                @@ -163,6 +157 @@
                -             frame[:flags].reduce(0) do |acc, f|
                -               position = FRAME_FLAGS[type][f]
                -               raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
                -
                -               acc | (1 << position)
                -             end,
                +             flags,
                @@ -187,3 +176 @@
                -        flags: FRAME_FLAGS[type].filter_map do |name, pos|
                -          name if flags.anybits?(1 << pos)
                -        end,
                +        flags: flags,
                @@ -201 +188 @@
                -      frame[:flags] ||= EMPTY
                +      frame[:flags] ||= 0
                @@ -204,0 +192 @@
                +        # @type var frame: data_frame | continuation_frame
                @@ -216 +204 @@
                -          frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
                +          frame[:flags] |= PRIORITY
                @@ -219 +207 @@
                -        if frame[:flags].include?(:priority)
                +        if frame[:flags].anybits?(PRIORITY)
                @@ -222,2 +210,4 @@
                -          pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -          pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +          pack(
                +            [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +            PRIORITYPACK, buffer: bytes
                +          )
                @@ -237,2 +227,4 @@
                -        pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -        pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +        pack(
                +          [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +          PRIORITYPACK, buffer: bytes
                +        )
                @@ -251 +242,0 @@
                -        bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
                @@ -253,5 +244,6 @@
                -        settings.each do |(k, v)|
                -          if k.is_a? Integer # rubocop:disable Style/GuardClause
                -            DEFINED_SETTINGS.value?(k) || next
                -          else
                -            k = DEFINED_SETTINGS[k]
                +        case settings
                +        when String
                +          length = settings.bytesize
                +          bytes = settings
                +        else
                +          bytes = String.new("", encoding: Encoding::BINARY, capacity: settings.size * 6)
                @@ -259 +251,12 @@
                -            raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +          settings.each do |(k, v)|
                +            if k.is_a? Integer # rubocop:disable Style/GuardClause
                +              DEFINED_SETTINGS.value?(k) || next
                +            else
                +              k = DEFINED_SETTINGS[k]
                +
                +              raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +            end
                +
                +            pack([k], UINT16, buffer: bytes)
                +            pack([v], UINT32, buffer: bytes)
                +            length += 6
                @@ -261,4 +263,0 @@
                -
                -          pack([k], UINT16, buffer: bytes)
                -          pack([v], UINT32, buffer: bytes)
                -          length += 6
                @@ -298 +297 @@
                -        pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
                +        pack([frame[:max_age], frame[:port]], ALTSVCPACK, buffer: bytes)
                @@ -357 +356 @@
                -        frame[:flags] += [:padded]
                +        frame[:flags] |= PADDED
                @@ -378,3 +377,3 @@
                -      type = frame[:type]
                -      length = frame[:length]
                -      flags = frame[:flags]
                +      type = frame[:type] #: Symbol
                +      length = frame[:length] #: Integer
                +      flags = frame[:flags] #: Integer
                @@ -397 +396 @@
                -        padded = flags.include?(:padded)
                +        padded = flags.anybits?(PADDED)
                @@ -400 +398,0 @@
                -          frame[:padding] = padlen + 1
                @@ -402,0 +401,2 @@
                +          frame[:padding] = padlen + 1
                +
                @@ -405 +405 @@
                -          flags.delete(:padded)
                +          frame[:flags] ^= PADDED
                @@ -413 +413 @@
                -        if flags.include?(:priority)
                +        if flags.anybits?(PRIORITY)
                @@ -417 +417 @@
                -          weight = payload.byteslice(0, 1).ord + 1
                +          weight = payload.getbyte(0) + 1
                @@ -428 +428 @@
                -        weight = payload.byteslice(0, 1).ord + 1
                +        weight = payload.getbyte(0) + 1
                @@ -439 +438,0 @@
                -        frame[:payload] = []
                @@ -444 +443 @@
                -        (frame[:length] / 6).times do
                +        frame[:payload] = (frame[:length] / 6).times.filter_map do
                @@ -450,2 +449,3 @@
                -          name, = DEFINED_SETTINGS.find { |_name, v| v == id }
                -          frame[:payload] << [name, val] if name
                +          if (name = DEFINED_SETTINGS_BY_ID[id])
                +            [name, val]
                +          end
                @@ -467 +467 @@
                -        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
                +        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(ALTSVCPACK)
                @@ -469 +469 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -473 +473 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -498 +498 @@
                -        error = DEFINED_ERRORS[error]
                +        error = DEFINED_ERRORS.index(error)
                @@ -507 +507 @@
                -      DEFINED_ERRORS.key(error) || error
                +      DEFINED_ERRORS.fetch(error, error)
        lib/http/2/header/compressor.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/header/compressor.rb	2026-06-17 02:34:12.815525855 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/header/compressor.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -85,0 +86,2 @@
                +            integer(huffman.bytesize, 7, buffer: buffer)
                +            buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
                @@ -87 +89 @@
                -            set_huffman_size(buffer, huffman_offset)
                +            buffer
                @@ -122 +124 @@
                -        fb = buffer[offset].ord | rep[:pattern]
                +        fb = buffer.getbyte(offset) | rep[:pattern]
                @@ -149,0 +152 @@
                +        buffer << "\x00".b
                @@ -151 +154,9 @@
                -        set_huffman_size(buffer, huffman_offset)
                +        size = buffer.bytesize - huffman_offset - 1
                +
                +        if size < 127
                +          buffer.setbyte(huffman_offset, 0x80 | size)
                +        else
                +          buffer.slice!(huffman_offset, 1)
                +          set_huffman_size(buffer, huffman_offset)
                +        end
                +        buffer
                @@ -168 +179 @@
                -        buffer.setbyte(huffman_offset, buffer[huffman_offset].ord | 0x80)
                +        buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
        lib/http/2/header/decompressor.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/header/decompressor.rb	2026-06-17 02:34:12.815525855 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/header/decompressor.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -36 +36,7 @@
                -        i = n.zero? ? 0 : (shift_byte(buf) & limit)
                +        if n.zero?
                +          i = 0
                +          consumed = 0
                +        else
                +          i = buf.getbyte(0) & limit
                +          consumed = 1
                +        end
                @@ -38 +43,0 @@
                -        m = 0
                @@ -40,5 +45,2 @@
                -          offset = 0
                -
                -          buf.each_byte.with_index do |byte, idx|
                -            offset = idx
                -            # while (byte = shift_byte(buf))
                +          m = 0
                +          while (byte = buf.getbyte(consumed))
                @@ -47 +49 @@
                -
                +            consumed += 1
                @@ -50,2 +51,0 @@
                -
                -          read_str(buf, offset + 1)
                @@ -53,0 +54 @@
                +        read_str(buf, consumed)
        lib/http/2/header/encoding_context.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:12.815525855 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -120,0 +121,2 @@
                +        @table_by_field = Hash.new { |hs, k| hs[k] = [] }
                +        @unshifts = 0
                @@ -131,0 +134,2 @@
                +        tbf = @table_by_field.transform_values(&:dup)
                +        unshifts = @unshifts
                @@ -134,0 +139,2 @@
                +          @table_by_field = tbf
                +          @unshifts = unshifts
                @@ -215,0 +222,2 @@
                +            @unshifts += 1
                +            @table_by_field[name].unshift([value, @unshifts])
                @@ -282,2 +290 @@
                -          @table.each_with_index do |(hfield, hvalue), i|
                -            next unless field == hfield
                +          field_entries = @table_by_field[field]
                @@ -284,0 +292,3 @@
                +          field_entries&.each do |hvalue, unshift_id|
                +            abs_index = (@unshifts - unshift_id) + STATIC_TABLE_SIZE
                +            name_only ||= abs_index
                @@ -286 +296 @@
                -              exact = i + STATIC_TABLE_SIZE
                +              exact = abs_index
                @@ -288,2 +297,0 @@
                -            else
                -              name_only ||= i + STATIC_TABLE_SIZE
                @@ -320 +327,0 @@
                -
                @@ -322,0 +330,5 @@
                +
                +          field_arr = @table_by_field[name]
                +          field_arr.pop
                +          @table_by_field.delete(name) if field_arr.empty?
                +
        lib/http/2/header/huffman.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/header/huffman.rb	2026-06-17 02:34:12.815525855 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/header/huffman.rb	2026-06-17 02:34:12.820525927 +0000
                @@ -22,0 +23,2 @@
                +      EOS_PADDING = (0..7).map { |n| ("1" * n).b.freeze }.freeze
                +
                @@ -32 +34 @@
                -        append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
                +        append_str(bitstring, EOS_PADDING[(8 - bitstring.size) % 8])
                @@ -57 +59 @@
                -            append_str(emit, first.chr) if first
                +            emit << first if first
                @@ -63 +65 @@
                -        emit.force_encoding(Encoding::BINARY)
                +        emit
                @@ -328 +330 @@
                -      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1] }.each(&:freeze).freeze
                +      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1].b.freeze }.freeze
        lib/http/2/server.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/server.rb	2026-06-17 02:34:12.817525884 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/server.rb	2026-06-17 02:34:12.821525941 +0000
                @@ -81,12 +81,6 @@
                -      buf = "".b
                -      append_str(buf, Base64.urlsafe_decode64(settings.to_s))
                -      @framer.common_header(
                -        {
                -          length: buf.bytesize,
                -          type: :settings,
                -          stream: 0,
                -          flags: []
                -        },
                -        buffer: buf
                -      )
                -      receive(buf)
                +      receive(@framer.generate(
                +                type: :settings,
                +                stream: 0,
                +                flags: 0,
                +                payload: Base64.urlsafe_decode64(settings.to_s)
                +              ))
                @@ -100 +94 @@
                -        flags: [:end_headers],
                +        flags: END_HEADERS,
                @@ -109 +103 @@
                -        headers_frame[:flags] << [:end_stream]
                +        headers_frame[:flags] |= END_HEADERS
                @@ -113 +107 @@
                -        stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
                +        stream << { type: :data, stream: 1, payload: body, flags: END_STREAM }
                @@ -138 +132 @@
                -      return unless frame[:flags].include?(:ack) && !@origins_sent
                +      return unless frame[:flags].anybits?(ACK) && !@origins_sent
                @@ -151 +145 @@
                -    # @param flags [Array[Symbol]]
                +    # @param flags Integer
                @@ -160 +154 @@
                -        payload: headers.to_a
                +        payload: headers
        lib/http/2/stream.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/stream.rb	2026-06-17 02:34:12.817525884 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/stream.rb	2026-06-17 02:34:12.821525941 +0000
                @@ -117 +117,2 @@
                -      case frame[:type]
                +      frame_type = frame[:type] #: Symbol
                +      case frame_type
                @@ -118,0 +120 @@
                +        # @type var frame: data_frame
                @@ -131,0 +134 @@
                +        # @type var frame: headers_frame
                @@ -153,0 +157 @@
                +        # @type var frame: priority_frame
                @@ -155,0 +160 @@
                +        # @type var frame: window_update_frame
                @@ -157,0 +163 @@
                +        # @type var frame: origin_frame
                @@ -162,3 +168 @@
                -        emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty?
                -      when :blocked
                -        emit(frame[:type], frame)
                +        emit(frame_type, frame) if !frame[:origin] || frame[:origin].empty?
                @@ -201,0 +206 @@
                +        # @type var frame: data_frame
                @@ -204,0 +210 @@
                +        # @type var frame: window_update_frame
                @@ -206,0 +213 @@
                +        # @type var frame: priority_frame
                @@ -222,3 +229,2 @@
                -      flags = []
                -      flags << :end_headers if end_headers
                -      flags << :end_stream  if end_stream || @_method == "HEAD"
                +      flags = end_headers ? END_HEADERS : 0
                +      flags |= END_STREAM  if end_stream || @_method == "HEAD"
                @@ -232 +238 @@
                -      flags = end_headers ? [:end_headers] : []
                +      flags = end_headers ? END_HEADERS : 0
                @@ -257 +263 @@
                -          send(type: :data, flags: [], payload: chunk)
                +          send(type: :data, flags: 0, payload: chunk)
                @@ -261,2 +267,2 @@
                -      flags = []
                -      flags << :end_stream if end_stream
                +      flags = 0
                +      flags |= END_STREAM if end_stream
                @@ -666 +672,2 @@
                -        frame[:flags] && frame[:flags].include?(:end_stream)
                +        # @type var frame: data_frame | headers_frame | continuation_frame
                +        frame[:flags] && frame[:flags].anybits?(END_STREAM)
        lib/http/2/version.rb
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/lib/http/2/version.rb	2026-06-17 02:34:12.817525884 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/lib/http/2/version.rb	2026-06-17 02:34:12.821525941 +0000
                @@ -4 +4 @@
                -  VERSION = "1.1.3"
                +  VERSION = "1.2.0"
        sig/2.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/2.rbs	2026-06-17 02:34:12.817525884 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/2.rbs	2026-06-17 02:34:12.821525941 +0000
                @@ -38,0 +39,8 @@
                +  # Frame flags
                +  END_STREAM: Integer
                +  ACK: Integer
                +  RESERVED: Integer
                +  END_HEADERS: Integer
                +  PADDED: Integer
                +  PRIORITY: Integer
                +
                @@ -42 +50,3 @@
                -  type frame_control_flags = Array[:end_headers | :end_stream]
                +  type frame_control_flags = Integer
                +
                +  type common_frame = { stream: Integer, flags: frame_control_flags, ?length: Integer, ?ignore: bool }
                @@ -44 +54 @@
                -  type common_frame = { stream: Integer }
                +  type connection_frame = settings_frame | ping_frame | goaway_frame | window_update_frame | altsvc_frame | origin_frame
                @@ -47,2 +57,2 @@
                -  type headers_frame = common_frame & {
                -    type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
                +  type headers_frame_props = {
                +    type: :headers, payload: Enumerable[header_pair] | String,
                @@ -50,0 +61,5 @@
                +  type headers_frame = common_frame & headers_frame_props
                +
                +  type continuation_frame_props = headers_frame_props | { type: :continuation }
                +
                +  type continuation_frame = common_frame & continuation_frame_props
                @@ -53 +68,3 @@
                -  type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
                +  type data_frame_props = { type: :data, ?length: Integer, payload: String, ?padding: Integer }
                +
                +  type data_frame = common_frame & data_frame_props
                @@ -56 +73,3 @@
                -  type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
                +  type push_promise_frame_props = { promise_stream: Integer, ?length: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair] | String, ?padding: Integer }
                +
                +  type push_promise_frame = common_frame & push_promise_frame_props
                @@ -59 +78,3 @@
                -  type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
                +  type settings_frame_props = { type: :settings, payload: (Enumerable[[Symbol | Integer, Integer]] | String) }
                +
                +  type settings_frame = common_frame & settings_frame_props
                @@ -62 +83,3 @@
                -  type window_update_frame = { type: :window_update, increment: Integer }
                +  type window_update_frame_props = { type: :window_update, increment: Integer }
                +
                +  type window_update_frame = common_frame & window_update_frame_props
                @@ -65 +88,5 @@
                -  type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
                +  type priority_frame_inner_props = { dependency: Integer, exclusive: bool, weight: Integer }
                +
                +  type priority_frame_props = { type: :priority } & priority_frame_inner_props
                +
                +  type priority_frame = common_frame & priority_frame_props
                @@ -68 +95,3 @@
                -  type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
                +  type altsvc_frame_props = { type: :altsvc, max_age: Integer, port: Integer, proto: String, host: String }
                +
                +  type altsvc_frame = common_frame & altsvc_frame_props
                @@ -71 +100,3 @@
                -  type origin_frame = { type: :origin, origin: Array[String] }
                +  type origin_frame_props = { type: :origin, payload: Array[String] }
                +
                +  type origin_frame = common_frame & origin_frame_props
                @@ -74 +105,3 @@
                -  type ping_frame = { type: :ping, payload: String, length: Integer }
                +  type ping_frame_props = { type: :ping, payload: String }
                +
                +  type ping_frame = common_frame & ping_frame_props
                @@ -77 +110,3 @@
                -  type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
                +  type goaway_frame_props = { type: :goaway, last_stream: Integer, error: (Symbol | Integer)? }
                +
                +  type goaway_frame = common_frame & goaway_frame_props
                @@ -79 +114,6 @@
                -  # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
                +  # # RST_STREAM
                +  type rst_stream_frame_props = { type: :rst_stream, error: (Symbol | Integer)? }
                +
                +  type rst_stream_frame = common_frame & rst_stream_frame_props
                +
                +  # type frame = headers_frame | continuation_frame | push_promise_frame | data_frame |
                @@ -81 +121,8 @@
                -  #              origin_frame | ping_frame | goaway_frame)
                +  #              origin_frame | ping_frame | goaway_frame | rst_stream_frame
                +
                +  # type connection_frame_props = rst_stream_frame_props | ping_frame_props | goaway_frame_props
                +  #                             | window_update_frame_props | settings_frame_props
                +
                +  # type stream_frame_props = headers_frame_props | continuation_frame_props | push_promise_frame_props
                +  #                         | data_frame_props  | rst_stream_frame_props | priority_frame_props
                +  #                         | window_update_frame_props | origin_frame_props | altsvc_frame_props
                @@ -111,0 +159,2 @@
                +  type connection_frame_props = Hash[frame_key, frame_value]
                +  type stream_frame_props = Hash[frame_key, frame_value]
        sig/connection.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/connection.rbs	2026-06-17 02:34:12.817525884 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/connection.rbs	2026-06-17 02:34:12.822525956 +0000
                @@ -35,0 +36 @@
                +    @oldest_stream_recently_closed: Numeric
                @@ -52,0 +54 @@
                +    @continuation_size: Integer
                @@ -71 +73 @@
                -    def receive: (string data) -> void
                +    def receive: (String data) -> void
                @@ -78 +80 @@
                -    def send: (frame frame) -> void
                +    def send: (connection_frame_props | stream_frame_props frame) -> void
                @@ -84 +86 @@
                -    def connection_management: (frame) -> void
                +    def connection_management: (connection_frame frame) -> void
                @@ -90 +92 @@
                -    def connection_settings: (frame) -> void
                +    def connection_settings: (settings_frame) -> void
                @@ -92 +94 @@
                -    def decode_headers: (frame) -> void
                +    def decode_headers: (headers_frame | push_promise_frame) -> void
                @@ -94 +96 @@
                -    def encode_headers: (frame headers_frame) -> void
                +    def encode_headers: (headers_frame | push_promise_frame) -> void
                @@ -100 +102 @@
                -    def verify_pseudo_headers: (frame) -> void
                +    def verify_pseudo_headers: (headers_frame | push_promise_frame) -> void
                @@ -102 +104 @@
                -    def _verify_pseudo_headers: (frame, Array[String]) -> void
                +    def _verify_pseudo_headers: (headers_frame | push_promise_frame, Array[String]) -> void
                @@ -106 +108 @@
                -end
                \ No newline at end of file
                +end
        sig/flow_buffer.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/flow_buffer.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/flow_buffer.rbs	2026-06-17 02:34:12.822525956 +0000
                @@ -17 +17 @@
                -    def send_data: (?data_frame? frame, ?bool encode) -> void
                +    def send_data: (?data_frame_props? frame, ?bool encode) -> void
                @@ -19 +19 @@
                -    def send_frame: (data_frame frame, bool encode) -> void
                +    def send_frame: (data_frame_props frame, bool encode) -> void
        sig/frame_buffer.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/frame_buffer.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/frame_buffer.rbs	2026-06-17 02:34:12.822525956 +0000
                @@ -2,0 +3,2 @@
                +    include BufferUtils
                +
                @@ -9 +11 @@
                -    def <<: (data_frame frame) -> void
                +    def <<: (data_frame_props frame) -> void
                @@ -13 +15 @@
                -    def retrieve: (Integer) -> data_frame?
                +    def retrieve: (Integer) -> data_frame_props?
        sig/framer.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/framer.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/framer.rbs	2026-06-17 02:34:12.822525956 +0000
                @@ -23 +23,3 @@
                -    DEFINED_ERRORS: Hash[Symbol, Integer]
                +    DEFINED_SETTINGS_BY_ID: Hash[Integer, Symbol]
                +
                +    DEFINED_ERRORS: Array[Symbol]
                @@ -31,0 +34,2 @@
                +    PRIORITYPACK: String
                +    ALTSVCPACK: String
                @@ -44 +48 @@
                -    def read_common_header: (String buf) -> frame
                +    def read_common_header: (String buf) -> (common_frame | { length: Integer })
                @@ -50 +54 @@
                -    def parse: (String) -> frame?
                +    def parse: (String) -> (frame | { length: Integer })?
                @@ -56 +60 @@
                -    def pack_error: (Integer | Symbol error, buffer: String) -> String
                +    def pack_error: (Symbol | Integer error, buffer: String) -> String
        sig/header/compressor.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/header/compressor.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/header/compressor.rbs	2026-06-17 02:34:12.822525956 +0000
                @@ -4,0 +5 @@
                +      include BufferUtils
        sig/header/encoding_context.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/header/encoding_context.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/header/encoding_context.rbs	2026-06-17 02:34:12.823525970 +0000
                @@ -24,0 +25,4 @@
                +      @table_by_field: Hash[string, Array[[string, Integer]]]
                +
                +      @unshifts: Integer
                +
        sig/header/huffman.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/header/huffman.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/header/huffman.rbs	2026-06-17 02:34:12.823525970 +0000
                @@ -11,0 +12,2 @@
                +      EOS_PADDING: Array[String]
                +
        sig/server.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/server.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/server.rbs	2026-06-17 02:34:12.823525970 +0000
                @@ -10 +10 @@
                -    def promise: (Stream parent, Enumerable[header_pair] headers, Array[Symbol] flags) { (Stream) -> void } -> void
                +    def promise: (Stream parent, Enumerable[header_pair] headers, frame_control_flags flags) { (Stream) -> void } -> void
        sig/stream.rbs
                --- /tmp/d20260617-525-4i6s98/http-2-1.1.3/sig/stream.rbs	2026-06-17 02:34:12.818525898 +0000
                +++ /tmp/d20260617-525-4i6s98/http-2-1.2.0/sig/stream.rbs	2026-06-17 02:34:12.823525970 +0000
                @@ -40 +40 @@
                -    def send: (frame frame) -> void
                +    def send: (stream_frame_props frame) -> void
                @@ -73 +73 @@
                -    def transition: (frame, bool sending) -> void
                +    def transition: (stream_frame_props frame, bool sending) -> void
                @@ -83 +83 @@
                -    def process_priority: (priority_frame frame) -> void
                +    def process_priority: (priority_frame_inner_props frame) -> void
                @@ -85 +85 @@
                -    def end_stream?: (frame frame) -> boolish
                +    def end_stream?: (stream_frame_props frame) -> boolish
                @@ -87,2 +87 @@
                -    def stream_error: (Symbol error, ?msg: String?) -> void
                -                    | () -> void
                +    def stream_error: (?Symbol error, ?msg: String?) -> void
                @@ -92 +91 @@
                -    def manage_state: (frame) { () -> void } -> void
                +    def manage_state: (stream_frame_props frame) { () -> void } -> void
                @@ -94 +93 @@
                -end
                \ No newline at end of file
                +end

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
        lib/http/2/settings.rb
                --- /tmp/20260617-1119-8c7kcw	2026-06-17 02:34:13.427590897 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/settings.rb	2026-06-17 02:34:13.425590891 +0000
                @@ -0,0 +1,42 @@
                +# frozen_string_literal: true
                +
                +module HTTP2
                +  # Default values for SETTINGS frame, as defined by the spec.
                +  SPEC_DEFAULT_CONNECTION_SETTINGS = {
                +    settings_header_table_size: 4096,
                +    settings_enable_push: 1, # enabled for servers
                +    settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
                +    settings_initial_window_size: 65_535,
                +    settings_max_frame_size: 16_384,
                +    settings_max_header_list_size: (2 << 30) - 1 # unlimited
                +  }.freeze
                +
                +  Settings = Struct.new(
                +    :settings_header_table_size,
                +    :settings_enable_push,
                +    :settings_max_concurrent_streams,
                +    :settings_initial_window_size,
                +    :settings_max_frame_size,
                +    :settings_max_header_list_size,
                +    keyword_init: true
                +  ) do
                +    def initialize(
                +      settings_header_table_size: 4096,
                +      settings_enable_push: 1,
                +      settings_max_concurrent_streams: 100,
                +      settings_initial_window_size: 65_535,
                +      settings_max_frame_size: 16_384,
                +      settings_max_header_list_size: (2 << 30) - 1
                +    )
                +      super
                +    end
                +
                +    def each_setting
                +      each_pair do |k, v|
                +        next if v == SPEC_DEFAULT_CONNECTION_SETTINGS[k]
                +
                +        yield k, v
                +      end
                +    end
                +  end
                +end
      * Changed:
        lib/http/2/client.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/client.rb	2026-06-17 02:34:13.418590872 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/client.rb	2026-06-17 02:34:13.423590886 +0000
                @@ -72 +72 @@
                -      frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
                +      frame = Framer.new.generate(type: :settings, stream: 0, flags: 0, payload: settings)
        lib/http/2/connection.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/connection.rb	2026-06-17 02:34:13.419590875 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/connection.rb	2026-06-17 02:34:13.423590886 +0000
                @@ -44,2 +43,0 @@
                -  HEADERS_FRAME_TYPES = %i[headers push_promise].freeze
                -
                @@ -93,0 +92 @@
                +      @oldest_stream_recently_closed = nil
                @@ -104,0 +104 @@
                +      @continuation_size = 0
                @@ -159 +159 @@
                -      send(type: :goaway, last_stream: @last_stream_id,
                +      send(type: :goaway, stream: 0, last_stream: @last_stream_id,
                @@ -181 +180,0 @@
                -      @pending_settings << payload
                @@ -215,3 +214,2 @@
                -        # @type var stream_id: Integer
                -        stream_id = frame[:stream]
                -        frame_type = frame[:type]
                +        stream_id = frame[:stream] #: Integer
                +        frame_type = frame[:type] #: Symbol?
                @@ -239,0 +238 @@
                +          # @type var frame: continuation_frame
                @@ -243,2 +242,2 @@
                -          unless frame[:flags].include? :end_headers
                -            buffered_payload = @continuation.sum { |f| f[:payload].bytesize }
                +          @continuation_size += frame[:payload].bytesize
                +          unless frame[:flags].anybits?(END_HEADERS)
                @@ -248 +247 @@
                -            unless buffered_payload < @local_settings[:settings_max_frame_size]
                +            unless @continuation_size < @local_settings[:settings_max_frame_size]
                @@ -261,0 +261 @@
                +          @continuation_size = 0
                @@ -265 +265 @@
                -          frame[:flags] << :end_headers
                +          frame[:flags] |= END_HEADERS
                @@ -273,0 +274 @@
                +          # @type var frame: connection_frame
                @@ -278,0 +280 @@
                +            # @type var frame: headers_frame
                @@ -285 +287 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -314,0 +317 @@
                +            # @type var frame: push_promise_frame
                @@ -317 +320 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -437,2 +439,0 @@
                -      frame_type = frame[:type]
                -
                @@ -440,2 +440,0 @@
                -      if frame_type == :data
                -        send_data(frame, true)
                @@ -443,3 +442 @@
                -      elsif frame_type == :rst_stream && frame[:error] == :protocol_error
                -        # An endpoint can end a connection at any time. In particular, an
                -        # endpoint MAY choose to treat a stream error as a connection error.
                +      frame_type = frame[:type] #: Symbol
                @@ -447,2 +444,5 @@
                -        goaway(:protocol_error)
                -      else
                +      case frame_type
                +      when :data
                +        #: @type var frame: data_frame
                +        send_data(frame, true)
                +      when :headers, :push_promise
                @@ -450,0 +451,10 @@
                +        #: @type var frame: headers_frame | push_promise_frame
                +        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                +      else
                +        if frame_type == :rst_stream && frame[:error] == :protocol_error
                +          # An endpoint can end a connection at any time. In particular, an
                +          # endpoint MAY choose to treat a stream error as a connection error.
                +
                +          goaway(:protocol_error)
                +        end
                +        #: @type var frame: connection_frame
                @@ -459,5 +469 @@
                -      if HEADERS_FRAME_TYPES.include?(frame[:type])
                -        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                -      else
                -        emit(:frame, @framer.generate(frame))
                -      end
                +      emit(:frame, @framer.generate(frame))
                @@ -495,0 +502 @@
                +          # @type var frame: settings_frame
                @@ -497,0 +505 @@
                +          # @type var frame: window_update_frame
                @@ -501,0 +510 @@
                +          # @type var frame: goaway_frame
                @@ -508,0 +518 @@
                +          # @type var frame: altsvc_frame
                @@ -515 +525,2 @@
                -          return if @h2c_upgrade || !frame[:flags].empty?
                +          # @type var frame: origin_frame
                +          return if @h2c_upgrade || !frame[:flags].zero?
                @@ -520,2 +530,0 @@
                -        when :blocked
                -          emit(:blocked, frame)
                @@ -541 +550 @@
                -      if frame[:flags].include? :ack
                +      if frame[:flags].anybits?(ACK)
                @@ -544,2 +553 @@
                -        send(type: :ping, stream: 0,
                -             flags: [:ack], payload: frame[:payload])
                +        send(type: :ping, stream: 0, flags: ACK, payload: frame[:payload])
                @@ -608 +616 @@
                -      if frame[:flags].include?(:ack)
                +      if frame[:flags].anybits?(ACK)
                @@ -613 +620,0 @@
                -        validate_settings(@remote_role, frame[:payload])
                @@ -614,0 +622 @@
                +        validate_settings(@remote_role, settings)
                @@ -684 +692 @@
                -          send(type: :settings, stream: 0, payload: [], flags: [:ack])
                +          send(type: :settings, stream: 0, payload: EMPTY, flags: ACK)
                @@ -714 +722 @@
                -      payload = headers_frame[:payload]
                +      headers_payload = headers_frame[:payload]
                @@ -716 +724 @@
                -        payload = headers_frame[:payload] = @compressor.encode(payload) unless payload.is_a?(String)
                +        payload = headers_payload.is_a?(String) ? headers_payload : @compressor.encode(headers_payload)
                @@ -720,0 +729,3 @@
                +      #: @type var payload: String
                +      headers_frame[:payload] = payload
                +
                @@ -725 +736 @@
                -        emit(:frame, @framer.generate(headers_frame))
                +        encode(headers_frame)
                @@ -730 +741,2 @@
                -      headers_frame[:flags].delete(:end_headers)
                +      total = payload.bytesize
                +      headers_frame[:flags] ^= END_HEADERS
                @@ -732 +744,2 @@
                -      payload = payload.byteslice(max_frame_size..-1)
                +      # payload = payload.byteslice(max_frame_size..-1)
                +      offset = max_frame_size
                @@ -735 +748 @@
                -      emit(:frame, @framer.generate(headers_frame))
                +      encode(headers_frame)
                @@ -737,6 +750 @@
                -      loop do
                -        continuation_frame = headers_frame.merge(
                -          type: :continuation,
                -          flags: EMPTY,
                -          payload: payload.byteslice(0, max_frame_size)
                -        )
                +      stream_id = headers_frame[:stream]
                @@ -744 +752,3 @@
                -        payload = payload.byteslice(max_frame_size..-1)
                +      while offset < total
                +        chunk_end = offset + max_frame_size
                +        is_last = chunk_end >= total
                @@ -746,5 +756,6 @@
                -        if payload.nil? || payload.empty?
                -          continuation_frame[:flags] = [:end_headers]
                -          emit(:frame, @framer.generate(continuation_frame))
                -          break
                -        end
                +        continuation_frame = {
                +          type: :continuation,
                +          flags: is_last ? END_HEADERS : 0,
                +          stream: stream_id,
                +          payload: payload.byteslice(offset, max_frame_size)
                +        } #: continuation_frame
                @@ -752 +763,2 @@
                -        emit(:frame, @framer.generate(continuation_frame))
                +        encode(continuation_frame)
                +        offset = chunk_end
                @@ -779,2 +790,0 @@
                -        _, closed_since = @streams_recently_closed.first
                -
                @@ -783 +793,2 @@
                -        if closed_since && (now - closed_since) > 15
                +        if @oldest_stream_recently_closed && (now - @oldest_stream_recently_closed) > 15
                +          new_oldest = nil
                @@ -786,3 +797,9 @@
                -          @streams_recently_closed = @streams_recently_closed.drop_while do |_, since|
                -            (now - since) > 15
                -          end.to_h
                +          @streams_recently_closed.delete_if do |_, since|
                +            unless (now - since) > 15
                +              new_oldest ||= since
                +              break
                +            end
                +
                +            true
                +          end
                +          @oldest_stream_recently_closed = new_oldest
                @@ -791 +808 @@
                -        @streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
                +        @streams_recently_closed[id] = now
        lib/http/2/extensions.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/extensions.rb	2026-06-17 02:34:13.419590875 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/extensions.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -25,2 +25,3 @@
                -    def read_str(str, n)
                -      return "".b if n == 0
                +    if String.method_defined?(:bytesplice)
                +      def read_str(str, n)
                +        return "".b if n == 0
                @@ -28,4 +29,13 @@
                -      chunk = str.byteslice(0..(n - 1))
                -      remaining = str.byteslice(n..-1)
                -      remaining ? str.replace(remaining) : str.clear
                -      chunk
                +        chunk = str.byteslice(0, n)
                +        str.bytesplice(0, chunk.length, "")
                +        chunk
                +      end
                +    else
                +      def read_str(str, n)
                +        return "".b if n == 0
                +
                +        chunk = str.byteslice(0, n)
                +        remaining = str.byteslice(n, str.size - n)
                +        remaining ? str.replace(remaining) : str.clear
                +        chunk
                +      end
                @@ -36,4 +45,0 @@
                -    end
                -
                -    def shift_byte(str)
                -      read_str(str, 1).ord
        lib/http/2/flow_buffer.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/flow_buffer.rb	2026-06-17 02:34:13.419590875 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/flow_buffer.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -73 +73 @@
                -          end_stream = frame[:flags].include?(:end_stream)
                +          end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -117,0 +118,2 @@
                +    include BufferUtils
                +
                @@ -143 +145 @@
                -      end_stream = frame[:flags].include?(:end_stream)
                +      end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -151,2 +153 @@
                -        chunk   = frame.dup
                -        payload = frame[:payload]
                +        chunk = frame.dup
                @@ -157 +158 @@
                -        chunk[:payload] = payload.byteslice(0, window_size)
                +        chunk[:payload] = read_str(frame[:payload], window_size) # mutates frame[:payload]
                @@ -159 +159,0 @@
                -        frame[:payload] = payload.byteslice(window_size..-1)
                @@ -163 +163 @@
                -        chunk[:flags] -= [:end_stream] if end_stream
                +        chunk[:flags] ^= END_STREAM if end_stream
        lib/http/2/framer.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/framer.rb	2026-06-17 02:34:13.419590875 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/framer.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -3,0 +4,19 @@
                +  # Frame flags as defined by the spec (max 255 bits)
                +  # DATA:          ( X X COMPRESSED X PADDED X X END_STREAM )
                +  # HEADERS:       ( X X PRIORITY X PADDED END_HEADERS X END_STREAM )
                +  # PRIORITY:      ( X X X X X X X X )
                +  # RST_STREAM:    ( X X X X X X X X )
                +  # SETTINGS:      ( X X X X X X X ACK )
                +  # PUSH_PROMISE:  ( X X X X PADDED END_HEADERS X X )
                +  # PING:          ( X X X X X X X ACK )
                +  # GOAWAY:        ( X X X X X X X X )
                +  # WINDOW_UPDATE: ( X X X X X X X X )
                +  # CONTINUATION:  ( X X X X X END_HEADERS X X )
                +  # ALTSVC:        ( X X X X X X X X )
                +  # ORIGIN:        ( RESERVED4 X X RESERVED3 X RESERVED2 RESERVED X )
                +  END_STREAM = ACK = 0b0001 # 1
                +  RESERVED = 0b0010 # 2
                +  END_HEADERS = 0b0100 # 4
                +  PADDED = 0b1000 # 8
                +  PRIORITY = 0b0010_0000 # 32
                +
                @@ -43,33 +61,0 @@
                -    # Per frame flags as defined by the spec
                -    FRAME_FLAGS = {
                -      data: {
                -        end_stream: 0,
                -        padded: 3,
                -        compressed: 5
                -      },
                -      headers: {
                -        end_stream: 0,
                -        end_headers: 2,
                -        padded: 3,
                -        priority: 5
                -      },
                -      priority: {},
                -      rst_stream: {},
                -      settings: { ack: 0 },
                -      push_promise: {
                -        end_headers: 2,
                -        padded: 3
                -      },
                -      ping: { ack: 0 },
                -      goaway: {},
                -      window_update: {},
                -      continuation: { end_headers: 2 },
                -      altsvc: {},
                -      origin: {
                -        reserved: 1,
                -        reserved2: 2,
                -        reserved3: 4,
                -        reserved4: 8
                -      }
                -    }.each_value(&:freeze).freeze
                -
                @@ -86,17 +72,19 @@
                -    # Default error types as defined by the spec
                -    DEFINED_ERRORS = {
                -      no_error: 0,
                -      protocol_error: 1,
                -      internal_error: 2,
                -      flow_control_error: 3,
                -      settings_timeout: 4,
                -      stream_closed: 5,
                -      frame_size_error: 6,
                -      refused_stream: 7,
                -      cancel: 8,
                -      compression_error: 9,
                -      connect_error: 10,
                -      enhance_your_calm: 11,
                -      inadequate_security: 12,
                -      http_1_1_required: 13
                -    }.freeze
                +    DEFINED_SETTINGS_BY_ID = DEFINED_SETTINGS.invert.freeze
                +
                +    # Default error types as defined by the spec (the code is the array index)
                +    DEFINED_ERRORS = %i[
                +      no_error
                +      protocol_error
                +      internal_error
                +      flow_control_error
                +      settings_timeout
                +      stream_closed
                +      frame_size_error
                +      refused_stream
                +      cancel
                +      compression_error
                +      connect_error
                +      enhance_your_calm
                +      inadequate_security
                +      http_1_1_required
                +    ].freeze
                @@ -110,0 +99,2 @@
                +    PRIORITYPACK = (UINT32 + UINT8).freeze
                +    ALTSVCPACK = (UINT32 + UINT16).freeze
                @@ -114 +104 @@
                -    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :UINT32, :UINT16, :UINT8
                +    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :PRIORITYPACK, :UINT32, :UINT16, :UINT8
                @@ -148,0 +139,4 @@
                +      flags = frame[:flags]
                +
                +      raise CompressionError, "Invalid frame flag (#{flags}) for #{type}" unless flags.between?(0, 255)
                +
                @@ -163,6 +157 @@
                -             frame[:flags].reduce(0) do |acc, f|
                -               position = FRAME_FLAGS[type][f]
                -               raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
                -
                -               acc | (1 << position)
                -             end,
                +             flags,
                @@ -187,3 +176 @@
                -        flags: FRAME_FLAGS[type].filter_map do |name, pos|
                -          name if flags.anybits?(1 << pos)
                -        end,
                +        flags: flags,
                @@ -201 +188 @@
                -      frame[:flags] ||= EMPTY
                +      frame[:flags] ||= 0
                @@ -204,0 +192 @@
                +        # @type var frame: data_frame | continuation_frame
                @@ -216 +204 @@
                -          frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
                +          frame[:flags] |= PRIORITY
                @@ -219 +207 @@
                -        if frame[:flags].include?(:priority)
                +        if frame[:flags].anybits?(PRIORITY)
                @@ -222,2 +210,4 @@
                -          pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -          pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +          pack(
                +            [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +            PRIORITYPACK, buffer: bytes
                +          )
                @@ -237,2 +227,4 @@
                -        pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -        pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +        pack(
                +          [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +          PRIORITYPACK, buffer: bytes
                +        )
                @@ -251 +242,0 @@
                -        bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
                @@ -253,5 +244,6 @@
                -        settings.each do |(k, v)|
                -          if k.is_a? Integer # rubocop:disable Style/GuardClause
                -            DEFINED_SETTINGS.value?(k) || next
                -          else
                -            k = DEFINED_SETTINGS[k]
                +        case settings
                +        when String
                +          length = settings.bytesize
                +          bytes = settings
                +        else
                +          bytes = String.new("", encoding: Encoding::BINARY, capacity: settings.size * 6)
                @@ -259 +251,12 @@
                -            raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +          settings.each do |(k, v)|
                +            if k.is_a? Integer # rubocop:disable Style/GuardClause
                +              DEFINED_SETTINGS.value?(k) || next
                +            else
                +              k = DEFINED_SETTINGS[k]
                +
                +              raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +            end
                +
                +            pack([k], UINT16, buffer: bytes)
                +            pack([v], UINT32, buffer: bytes)
                +            length += 6
                @@ -261,4 +263,0 @@
                -
                -          pack([k], UINT16, buffer: bytes)
                -          pack([v], UINT32, buffer: bytes)
                -          length += 6
                @@ -298 +297 @@
                -        pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
                +        pack([frame[:max_age], frame[:port]], ALTSVCPACK, buffer: bytes)
                @@ -357 +356 @@
                -        frame[:flags] += [:padded]
                +        frame[:flags] |= PADDED
                @@ -378,3 +377,3 @@
                -      type = frame[:type]
                -      length = frame[:length]
                -      flags = frame[:flags]
                +      type = frame[:type] #: Symbol
                +      length = frame[:length] #: Integer
                +      flags = frame[:flags] #: Integer
                @@ -397 +396 @@
                -        padded = flags.include?(:padded)
                +        padded = flags.anybits?(PADDED)
                @@ -400 +398,0 @@
                -          frame[:padding] = padlen + 1
                @@ -402,0 +401,2 @@
                +          frame[:padding] = padlen + 1
                +
                @@ -405 +405 @@
                -          flags.delete(:padded)
                +          frame[:flags] ^= PADDED
                @@ -413 +413 @@
                -        if flags.include?(:priority)
                +        if flags.anybits?(PRIORITY)
                @@ -417 +417 @@
                -          weight = payload.byteslice(0, 1).ord + 1
                +          weight = payload.getbyte(0) + 1
                @@ -428 +428 @@
                -        weight = payload.byteslice(0, 1).ord + 1
                +        weight = payload.getbyte(0) + 1
                @@ -439 +438,0 @@
                -        frame[:payload] = []
                @@ -444 +443 @@
                -        (frame[:length] / 6).times do
                +        frame[:payload] = (frame[:length] / 6).times.filter_map do
                @@ -450,2 +449,3 @@
                -          name, = DEFINED_SETTINGS.find { |_name, v| v == id }
                -          frame[:payload] << [name, val] if name
                +          if (name = DEFINED_SETTINGS_BY_ID[id])
                +            [name, val]
                +          end
                @@ -467 +467 @@
                -        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
                +        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(ALTSVCPACK)
                @@ -469 +469 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -473 +473 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -498 +498 @@
                -        error = DEFINED_ERRORS[error]
                +        error = DEFINED_ERRORS.index(error)
                @@ -507 +507 @@
                -      DEFINED_ERRORS.key(error) || error
                +      DEFINED_ERRORS.fetch(error, error)
        lib/http/2/header/compressor.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/header/compressor.rb	2026-06-17 02:34:13.419590875 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/header/compressor.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -85,0 +86,2 @@
                +            integer(huffman.bytesize, 7, buffer: buffer)
                +            buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
                @@ -87 +89 @@
                -            set_huffman_size(buffer, huffman_offset)
                +            buffer
                @@ -122 +124 @@
                -        fb = buffer[offset].ord | rep[:pattern]
                +        fb = buffer.getbyte(offset) | rep[:pattern]
                @@ -149,0 +152 @@
                +        buffer << "\x00".b
                @@ -151 +154,9 @@
                -        set_huffman_size(buffer, huffman_offset)
                +        size = buffer.bytesize - huffman_offset - 1
                +
                +        if size < 127
                +          buffer.setbyte(huffman_offset, 0x80 | size)
                +        else
                +          buffer.slice!(huffman_offset, 1)
                +          set_huffman_size(buffer, huffman_offset)
                +        end
                +        buffer
                @@ -168 +179 @@
                -        buffer.setbyte(huffman_offset, buffer[huffman_offset].ord | 0x80)
                +        buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
        lib/http/2/header/decompressor.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/header/decompressor.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/header/decompressor.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -36 +36,7 @@
                -        i = n.zero? ? 0 : (shift_byte(buf) & limit)
                +        if n.zero?
                +          i = 0
                +          consumed = 0
                +        else
                +          i = buf.getbyte(0) & limit
                +          consumed = 1
                +        end
                @@ -38 +43,0 @@
                -        m = 0
                @@ -40,5 +45,2 @@
                -          offset = 0
                -
                -          buf.each_byte.with_index do |byte, idx|
                -            offset = idx
                -            # while (byte = shift_byte(buf))
                +          m = 0
                +          while (byte = buf.getbyte(consumed))
                @@ -47 +49 @@
                -
                +            consumed += 1
                @@ -50,2 +51,0 @@
                -
                -          read_str(buf, offset + 1)
                @@ -53,0 +54 @@
                +        read_str(buf, consumed)
        lib/http/2/header/encoding_context.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:13.424590889 +0000
                @@ -120,0 +121,2 @@
                +        @table_by_field = Hash.new { |hs, k| hs[k] = [] }
                +        @unshifts = 0
                @@ -131,0 +134,2 @@
                +        tbf = @table_by_field.transform_values(&:dup)
                +        unshifts = @unshifts
                @@ -134,0 +139,2 @@
                +          @table_by_field = tbf
                +          @unshifts = unshifts
                @@ -215,0 +222,2 @@
                +            @unshifts += 1
                +            @table_by_field[name].unshift([value, @unshifts])
                @@ -282,2 +290 @@
                -          @table.each_with_index do |(hfield, hvalue), i|
                -            next unless field == hfield
                +          field_entries = @table_by_field[field]
                @@ -284,0 +292,3 @@
                +          field_entries&.each do |hvalue, unshift_id|
                +            abs_index = (@unshifts - unshift_id) + STATIC_TABLE_SIZE
                +            name_only ||= abs_index
                @@ -286 +296 @@
                -              exact = i + STATIC_TABLE_SIZE
                +              exact = abs_index
                @@ -288,2 +297,0 @@
                -            else
                -              name_only ||= i + STATIC_TABLE_SIZE
                @@ -320 +327,0 @@
                -
                @@ -322,0 +330,5 @@
                +
                +          field_arr = @table_by_field[name]
                +          field_arr.pop
                +          @table_by_field.delete(name) if field_arr.empty?
                +
        lib/http/2/header/huffman.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/header/huffman.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/header/huffman.rb	2026-06-17 02:34:13.425590891 +0000
                @@ -22,0 +23,2 @@
                +      EOS_PADDING = (0..7).map { |n| ("1" * n).b.freeze }.freeze
                +
                @@ -32 +34 @@
                -        append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
                +        append_str(bitstring, EOS_PADDING[(8 - bitstring.size) % 8])
                @@ -57 +59 @@
                -            append_str(emit, first.chr) if first
                +            emit << first if first
                @@ -63 +65 @@
                -        emit.force_encoding(Encoding::BINARY)
                +        emit
                @@ -328 +330 @@
                -      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1] }.each(&:freeze).freeze
                +      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1].b.freeze }.freeze
        lib/http/2/server.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/server.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/server.rb	2026-06-17 02:34:13.425590891 +0000
                @@ -81,12 +81,6 @@
                -      buf = "".b
                -      append_str(buf, Base64.urlsafe_decode64(settings.to_s))
                -      @framer.common_header(
                -        {
                -          length: buf.bytesize,
                -          type: :settings,
                -          stream: 0,
                -          flags: []
                -        },
                -        buffer: buf
                -      )
                -      receive(buf)
                +      receive(@framer.generate(
                +                type: :settings,
                +                stream: 0,
                +                flags: 0,
                +                payload: Base64.urlsafe_decode64(settings.to_s)
                +              ))
                @@ -100 +94 @@
                -        flags: [:end_headers],
                +        flags: END_HEADERS,
                @@ -109 +103 @@
                -        headers_frame[:flags] << [:end_stream]
                +        headers_frame[:flags] |= END_HEADERS
                @@ -113 +107 @@
                -        stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
                +        stream << { type: :data, stream: 1, payload: body, flags: END_STREAM }
                @@ -138 +132 @@
                -      return unless frame[:flags].include?(:ack) && !@origins_sent
                +      return unless frame[:flags].anybits?(ACK) && !@origins_sent
                @@ -151 +145 @@
                -    # @param flags [Array[Symbol]]
                +    # @param flags Integer
                @@ -160 +154 @@
                -        payload: headers.to_a
                +        payload: headers
        lib/http/2/stream.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/stream.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/stream.rb	2026-06-17 02:34:13.425590891 +0000
                @@ -117 +117,2 @@
                -      case frame[:type]
                +      frame_type = frame[:type] #: Symbol
                +      case frame_type
                @@ -118,0 +120 @@
                +        # @type var frame: data_frame
                @@ -131,0 +134 @@
                +        # @type var frame: headers_frame
                @@ -153,0 +157 @@
                +        # @type var frame: priority_frame
                @@ -155,0 +160 @@
                +        # @type var frame: window_update_frame
                @@ -157,0 +163 @@
                +        # @type var frame: origin_frame
                @@ -162,3 +168 @@
                -        emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty?
                -      when :blocked
                -        emit(frame[:type], frame)
                +        emit(frame_type, frame) if !frame[:origin] || frame[:origin].empty?
                @@ -201,0 +206 @@
                +        # @type var frame: data_frame
                @@ -204,0 +210 @@
                +        # @type var frame: window_update_frame
                @@ -206,0 +213 @@
                +        # @type var frame: priority_frame
                @@ -222,3 +229,2 @@
                -      flags = []
                -      flags << :end_headers if end_headers
                -      flags << :end_stream  if end_stream || @_method == "HEAD"
                +      flags = end_headers ? END_HEADERS : 0
                +      flags |= END_STREAM  if end_stream || @_method == "HEAD"
                @@ -232 +238 @@
                -      flags = end_headers ? [:end_headers] : []
                +      flags = end_headers ? END_HEADERS : 0
                @@ -257 +263 @@
                -          send(type: :data, flags: [], payload: chunk)
                +          send(type: :data, flags: 0, payload: chunk)
                @@ -261,2 +267,2 @@
                -      flags = []
                -      flags << :end_stream if end_stream
                +      flags = 0
                +      flags |= END_STREAM if end_stream
                @@ -666 +672,2 @@
                -        frame[:flags] && frame[:flags].include?(:end_stream)
                +        # @type var frame: data_frame | headers_frame | continuation_frame
                +        frame[:flags] && frame[:flags].anybits?(END_STREAM)
        lib/http/2/version.rb
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/lib/http/2/version.rb	2026-06-17 02:34:13.420590878 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/lib/http/2/version.rb	2026-06-17 02:34:13.425590891 +0000
                @@ -4 +4 @@
                -  VERSION = "1.1.3"
                +  VERSION = "1.2.0"
        sig/2.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/2.rbs	2026-06-17 02:34:13.421590880 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/2.rbs	2026-06-17 02:34:13.426590894 +0000
                @@ -38,0 +39,8 @@
                +  # Frame flags
                +  END_STREAM: Integer
                +  ACK: Integer
                +  RESERVED: Integer
                +  END_HEADERS: Integer
                +  PADDED: Integer
                +  PRIORITY: Integer
                +
                @@ -42 +50,3 @@
                -  type frame_control_flags = Array[:end_headers | :end_stream]
                +  type frame_control_flags = Integer
                +
                +  type common_frame = { stream: Integer, flags: frame_control_flags, ?length: Integer, ?ignore: bool }
                @@ -44 +54 @@
                -  type common_frame = { stream: Integer }
                +  type connection_frame = settings_frame | ping_frame | goaway_frame | window_update_frame | altsvc_frame | origin_frame
                @@ -47,2 +57,2 @@
                -  type headers_frame = common_frame & {
                -    type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
                +  type headers_frame_props = {
                +    type: :headers, payload: Enumerable[header_pair] | String,
                @@ -50,0 +61,5 @@
                +  type headers_frame = common_frame & headers_frame_props
                +
                +  type continuation_frame_props = headers_frame_props | { type: :continuation }
                +
                +  type continuation_frame = common_frame & continuation_frame_props
                @@ -53 +68,3 @@
                -  type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
                +  type data_frame_props = { type: :data, ?length: Integer, payload: String, ?padding: Integer }
                +
                +  type data_frame = common_frame & data_frame_props
                @@ -56 +73,3 @@
                -  type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
                +  type push_promise_frame_props = { promise_stream: Integer, ?length: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair] | String, ?padding: Integer }
                +
                +  type push_promise_frame = common_frame & push_promise_frame_props
                @@ -59 +78,3 @@
                -  type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
                +  type settings_frame_props = { type: :settings, payload: (Enumerable[[Symbol | Integer, Integer]] | String) }
                +
                +  type settings_frame = common_frame & settings_frame_props
                @@ -62 +83,3 @@
                -  type window_update_frame = { type: :window_update, increment: Integer }
                +  type window_update_frame_props = { type: :window_update, increment: Integer }
                +
                +  type window_update_frame = common_frame & window_update_frame_props
                @@ -65 +88,5 @@
                -  type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
                +  type priority_frame_inner_props = { dependency: Integer, exclusive: bool, weight: Integer }
                +
                +  type priority_frame_props = { type: :priority } & priority_frame_inner_props
                +
                +  type priority_frame = common_frame & priority_frame_props
                @@ -68 +95,3 @@
                -  type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
                +  type altsvc_frame_props = { type: :altsvc, max_age: Integer, port: Integer, proto: String, host: String }
                +
                +  type altsvc_frame = common_frame & altsvc_frame_props
                @@ -71 +100,3 @@
                -  type origin_frame = { type: :origin, origin: Array[String] }
                +  type origin_frame_props = { type: :origin, payload: Array[String] }
                +
                +  type origin_frame = common_frame & origin_frame_props
                @@ -74 +105,3 @@
                -  type ping_frame = { type: :ping, payload: String, length: Integer }
                +  type ping_frame_props = { type: :ping, payload: String }
                +
                +  type ping_frame = common_frame & ping_frame_props
                @@ -77 +110,3 @@
                -  type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
                +  type goaway_frame_props = { type: :goaway, last_stream: Integer, error: (Symbol | Integer)? }
                +
                +  type goaway_frame = common_frame & goaway_frame_props
                @@ -79 +114,6 @@
                -  # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
                +  # # RST_STREAM
                +  type rst_stream_frame_props = { type: :rst_stream, error: (Symbol | Integer)? }
                +
                +  type rst_stream_frame = common_frame & rst_stream_frame_props
                +
                +  # type frame = headers_frame | continuation_frame | push_promise_frame | data_frame |
                @@ -81 +121,8 @@
                -  #              origin_frame | ping_frame | goaway_frame)
                +  #              origin_frame | ping_frame | goaway_frame | rst_stream_frame
                +
                +  # type connection_frame_props = rst_stream_frame_props | ping_frame_props | goaway_frame_props
                +  #                             | window_update_frame_props | settings_frame_props
                +
                +  # type stream_frame_props = headers_frame_props | continuation_frame_props | push_promise_frame_props
                +  #                         | data_frame_props  | rst_stream_frame_props | priority_frame_props
                +  #                         | window_update_frame_props | origin_frame_props | altsvc_frame_props
                @@ -111,0 +159,2 @@
                +  type connection_frame_props = Hash[frame_key, frame_value]
                +  type stream_frame_props = Hash[frame_key, frame_value]
        sig/connection.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/connection.rbs	2026-06-17 02:34:13.421590880 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/connection.rbs	2026-06-17 02:34:13.426590894 +0000
                @@ -35,0 +36 @@
                +    @oldest_stream_recently_closed: Numeric
                @@ -52,0 +54 @@
                +    @continuation_size: Integer
                @@ -71 +73 @@
                -    def receive: (string data) -> void
                +    def receive: (String data) -> void
                @@ -78 +80 @@
                -    def send: (frame frame) -> void
                +    def send: (connection_frame_props | stream_frame_props frame) -> void
                @@ -84 +86 @@
                -    def connection_management: (frame) -> void
                +    def connection_management: (connection_frame frame) -> void
                @@ -90 +92 @@
                -    def connection_settings: (frame) -> void
                +    def connection_settings: (settings_frame) -> void
                @@ -92 +94 @@
                -    def decode_headers: (frame) -> void
                +    def decode_headers: (headers_frame | push_promise_frame) -> void
                @@ -94 +96 @@
                -    def encode_headers: (frame headers_frame) -> void
                +    def encode_headers: (headers_frame | push_promise_frame) -> void
                @@ -100 +102 @@
                -    def verify_pseudo_headers: (frame) -> void
                +    def verify_pseudo_headers: (headers_frame | push_promise_frame) -> void
                @@ -102 +104 @@
                -    def _verify_pseudo_headers: (frame, Array[String]) -> void
                +    def _verify_pseudo_headers: (headers_frame | push_promise_frame, Array[String]) -> void
                @@ -106 +108 @@
                -end
                \ No newline at end of file
                +end
        sig/flow_buffer.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/flow_buffer.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/flow_buffer.rbs	2026-06-17 02:34:13.426590894 +0000
                @@ -17 +17 @@
                -    def send_data: (?data_frame? frame, ?bool encode) -> void
                +    def send_data: (?data_frame_props? frame, ?bool encode) -> void
                @@ -19 +19 @@
                -    def send_frame: (data_frame frame, bool encode) -> void
                +    def send_frame: (data_frame_props frame, bool encode) -> void
        sig/frame_buffer.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/frame_buffer.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/frame_buffer.rbs	2026-06-17 02:34:13.426590894 +0000
                @@ -2,0 +3,2 @@
                +    include BufferUtils
                +
                @@ -9 +11 @@
                -    def <<: (data_frame frame) -> void
                +    def <<: (data_frame_props frame) -> void
                @@ -13 +15 @@
                -    def retrieve: (Integer) -> data_frame?
                +    def retrieve: (Integer) -> data_frame_props?
        sig/framer.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/framer.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/framer.rbs	2026-06-17 02:34:13.426590894 +0000
                @@ -23 +23,3 @@
                -    DEFINED_ERRORS: Hash[Symbol, Integer]
                +    DEFINED_SETTINGS_BY_ID: Hash[Integer, Symbol]
                +
                +    DEFINED_ERRORS: Array[Symbol]
                @@ -31,0 +34,2 @@
                +    PRIORITYPACK: String
                +    ALTSVCPACK: String
                @@ -44 +48 @@
                -    def read_common_header: (String buf) -> frame
                +    def read_common_header: (String buf) -> (common_frame | { length: Integer })
                @@ -50 +54 @@
                -    def parse: (String) -> frame?
                +    def parse: (String) -> (frame | { length: Integer })?
                @@ -56 +60 @@
                -    def pack_error: (Integer | Symbol error, buffer: String) -> String
                +    def pack_error: (Symbol | Integer error, buffer: String) -> String
        sig/header/compressor.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/header/compressor.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/header/compressor.rbs	2026-06-17 02:34:13.427590897 +0000
                @@ -4,0 +5 @@
                +      include BufferUtils
        sig/header/encoding_context.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/header/encoding_context.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/header/encoding_context.rbs	2026-06-17 02:34:13.427590897 +0000
                @@ -24,0 +25,4 @@
                +      @table_by_field: Hash[string, Array[[string, Integer]]]
                +
                +      @unshifts: Integer
                +
        sig/header/huffman.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/header/huffman.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/header/huffman.rbs	2026-06-17 02:34:13.427590897 +0000
                @@ -11,0 +12,2 @@
                +      EOS_PADDING: Array[String]
                +
        sig/server.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/server.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/server.rbs	2026-06-17 02:34:13.427590897 +0000
                @@ -10 +10 @@
                -    def promise: (Stream parent, Enumerable[header_pair] headers, Array[Symbol] flags) { (Stream) -> void } -> void
                +    def promise: (Stream parent, Enumerable[header_pair] headers, frame_control_flags flags) { (Stream) -> void } -> void
        sig/stream.rbs
                --- /tmp/d20260617-1119-naqxpw/http-2-1.1.3/sig/stream.rbs	2026-06-17 02:34:13.422590883 +0000
                +++ /tmp/d20260617-1119-naqxpw/http-2-1.2.0/sig/stream.rbs	2026-06-17 02:34:13.427590897 +0000
                @@ -40 +40 @@
                -    def send: (frame frame) -> void
                +    def send: (stream_frame_props frame) -> void
                @@ -73 +73 @@
                -    def transition: (frame, bool sending) -> void
                +    def transition: (stream_frame_props frame, bool sending) -> void
                @@ -83 +83 @@
                -    def process_priority: (priority_frame frame) -> void
                +    def process_priority: (priority_frame_inner_props frame) -> void
                @@ -85 +85 @@
                -    def end_stream?: (frame frame) -> boolish
                +    def end_stream?: (stream_frame_props frame) -> boolish
                @@ -87,2 +87 @@
                -    def stream_error: (Symbol error, ?msg: String?) -> void
                -                    | () -> void
                +    def stream_error: (?Symbol error, ?msg: String?) -> void
                @@ -92 +91 @@
                -    def manage_state: (frame) { () -> void } -> void
                +    def manage_state: (stream_frame_props frame) { () -> void } -> void
                @@ -94 +93 @@
                -end
                \ No newline at end of file
                +end

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
        lib/http/2/settings.rb
                --- /tmp/20260617-465-cjbxbu	2026-06-17 02:34:13.519772021 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/settings.rb	2026-06-17 02:34:13.518772025 +0000
                @@ -0,0 +1,42 @@
                +# frozen_string_literal: true
                +
                +module HTTP2
                +  # Default values for SETTINGS frame, as defined by the spec.
                +  SPEC_DEFAULT_CONNECTION_SETTINGS = {
                +    settings_header_table_size: 4096,
                +    settings_enable_push: 1, # enabled for servers
                +    settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
                +    settings_initial_window_size: 65_535,
                +    settings_max_frame_size: 16_384,
                +    settings_max_header_list_size: (2 << 30) - 1 # unlimited
                +  }.freeze
                +
                +  Settings = Struct.new(
                +    :settings_header_table_size,
                +    :settings_enable_push,
                +    :settings_max_concurrent_streams,
                +    :settings_initial_window_size,
                +    :settings_max_frame_size,
                +    :settings_max_header_list_size,
                +    keyword_init: true
                +  ) do
                +    def initialize(
                +      settings_header_table_size: 4096,
                +      settings_enable_push: 1,
                +      settings_max_concurrent_streams: 100,
                +      settings_initial_window_size: 65_535,
                +      settings_max_frame_size: 16_384,
                +      settings_max_header_list_size: (2 << 30) - 1
                +    )
                +      super
                +    end
                +
                +    def each_setting
                +      each_pair do |k, v|
                +        next if v == SPEC_DEFAULT_CONNECTION_SETTINGS[k]
                +
                +        yield k, v
                +      end
                +    end
                +  end
                +end
      * Changed:
        lib/http/2/client.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/client.rb	2026-06-17 02:34:13.509772066 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/client.rb	2026-06-17 02:34:13.515772039 +0000
                @@ -72 +72 @@
                -      frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
                +      frame = Framer.new.generate(type: :settings, stream: 0, flags: 0, payload: settings)
        lib/http/2/connection.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/connection.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/connection.rb	2026-06-17 02:34:13.515772039 +0000
                @@ -44,2 +43,0 @@
                -  HEADERS_FRAME_TYPES = %i[headers push_promise].freeze
                -
                @@ -93,0 +92 @@
                +      @oldest_stream_recently_closed = nil
                @@ -104,0 +104 @@
                +      @continuation_size = 0
                @@ -159 +159 @@
                -      send(type: :goaway, last_stream: @last_stream_id,
                +      send(type: :goaway, stream: 0, last_stream: @last_stream_id,
                @@ -181 +180,0 @@
                -      @pending_settings << payload
                @@ -215,3 +214,2 @@
                -        # @type var stream_id: Integer
                -        stream_id = frame[:stream]
                -        frame_type = frame[:type]
                +        stream_id = frame[:stream] #: Integer
                +        frame_type = frame[:type] #: Symbol?
                @@ -239,0 +238 @@
                +          # @type var frame: continuation_frame
                @@ -243,2 +242,2 @@
                -          unless frame[:flags].include? :end_headers
                -            buffered_payload = @continuation.sum { |f| f[:payload].bytesize }
                +          @continuation_size += frame[:payload].bytesize
                +          unless frame[:flags].anybits?(END_HEADERS)
                @@ -248 +247 @@
                -            unless buffered_payload < @local_settings[:settings_max_frame_size]
                +            unless @continuation_size < @local_settings[:settings_max_frame_size]
                @@ -261,0 +261 @@
                +          @continuation_size = 0
                @@ -265 +265 @@
                -          frame[:flags] << :end_headers
                +          frame[:flags] |= END_HEADERS
                @@ -273,0 +274 @@
                +          # @type var frame: connection_frame
                @@ -278,0 +280 @@
                +            # @type var frame: headers_frame
                @@ -285 +287 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -314,0 +317 @@
                +            # @type var frame: push_promise_frame
                @@ -317 +320 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -437,2 +439,0 @@
                -      frame_type = frame[:type]
                -
                @@ -440,2 +440,0 @@
                -      if frame_type == :data
                -        send_data(frame, true)
                @@ -443,3 +442 @@
                -      elsif frame_type == :rst_stream && frame[:error] == :protocol_error
                -        # An endpoint can end a connection at any time. In particular, an
                -        # endpoint MAY choose to treat a stream error as a connection error.
                +      frame_type = frame[:type] #: Symbol
                @@ -447,2 +444,5 @@
                -        goaway(:protocol_error)
                -      else
                +      case frame_type
                +      when :data
                +        #: @type var frame: data_frame
                +        send_data(frame, true)
                +      when :headers, :push_promise
                @@ -450,0 +451,10 @@
                +        #: @type var frame: headers_frame | push_promise_frame
                +        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                +      else
                +        if frame_type == :rst_stream && frame[:error] == :protocol_error
                +          # An endpoint can end a connection at any time. In particular, an
                +          # endpoint MAY choose to treat a stream error as a connection error.
                +
                +          goaway(:protocol_error)
                +        end
                +        #: @type var frame: connection_frame
                @@ -459,5 +469 @@
                -      if HEADERS_FRAME_TYPES.include?(frame[:type])
                -        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                -      else
                -        emit(:frame, @framer.generate(frame))
                -      end
                +      emit(:frame, @framer.generate(frame))
                @@ -495,0 +502 @@
                +          # @type var frame: settings_frame
                @@ -497,0 +505 @@
                +          # @type var frame: window_update_frame
                @@ -501,0 +510 @@
                +          # @type var frame: goaway_frame
                @@ -508,0 +518 @@
                +          # @type var frame: altsvc_frame
                @@ -515 +525,2 @@
                -          return if @h2c_upgrade || !frame[:flags].empty?
                +          # @type var frame: origin_frame
                +          return if @h2c_upgrade || !frame[:flags].zero?
                @@ -520,2 +530,0 @@
                -        when :blocked
                -          emit(:blocked, frame)
                @@ -541 +550 @@
                -      if frame[:flags].include? :ack
                +      if frame[:flags].anybits?(ACK)
                @@ -544,2 +553 @@
                -        send(type: :ping, stream: 0,
                -             flags: [:ack], payload: frame[:payload])
                +        send(type: :ping, stream: 0, flags: ACK, payload: frame[:payload])
                @@ -608 +616 @@
                -      if frame[:flags].include?(:ack)
                +      if frame[:flags].anybits?(ACK)
                @@ -613 +620,0 @@
                -        validate_settings(@remote_role, frame[:payload])
                @@ -614,0 +622 @@
                +        validate_settings(@remote_role, settings)
                @@ -684 +692 @@
                -          send(type: :settings, stream: 0, payload: [], flags: [:ack])
                +          send(type: :settings, stream: 0, payload: EMPTY, flags: ACK)
                @@ -714 +722 @@
                -      payload = headers_frame[:payload]
                +      headers_payload = headers_frame[:payload]
                @@ -716 +724 @@
                -        payload = headers_frame[:payload] = @compressor.encode(payload) unless payload.is_a?(String)
                +        payload = headers_payload.is_a?(String) ? headers_payload : @compressor.encode(headers_payload)
                @@ -720,0 +729,3 @@
                +      #: @type var payload: String
                +      headers_frame[:payload] = payload
                +
                @@ -725 +736 @@
                -        emit(:frame, @framer.generate(headers_frame))
                +        encode(headers_frame)
                @@ -730 +741,2 @@
                -      headers_frame[:flags].delete(:end_headers)
                +      total = payload.bytesize
                +      headers_frame[:flags] ^= END_HEADERS
                @@ -732 +744,2 @@
                -      payload = payload.byteslice(max_frame_size..-1)
                +      # payload = payload.byteslice(max_frame_size..-1)
                +      offset = max_frame_size
                @@ -735 +748 @@
                -      emit(:frame, @framer.generate(headers_frame))
                +      encode(headers_frame)
                @@ -737,6 +750 @@
                -      loop do
                -        continuation_frame = headers_frame.merge(
                -          type: :continuation,
                -          flags: EMPTY,
                -          payload: payload.byteslice(0, max_frame_size)
                -        )
                +      stream_id = headers_frame[:stream]
                @@ -744 +752,3 @@
                -        payload = payload.byteslice(max_frame_size..-1)
                +      while offset < total
                +        chunk_end = offset + max_frame_size
                +        is_last = chunk_end >= total
                @@ -746,5 +756,6 @@
                -        if payload.nil? || payload.empty?
                -          continuation_frame[:flags] = [:end_headers]
                -          emit(:frame, @framer.generate(continuation_frame))
                -          break
                -        end
                +        continuation_frame = {
                +          type: :continuation,
                +          flags: is_last ? END_HEADERS : 0,
                +          stream: stream_id,
                +          payload: payload.byteslice(offset, max_frame_size)
                +        } #: continuation_frame
                @@ -752 +763,2 @@
                -        emit(:frame, @framer.generate(continuation_frame))
                +        encode(continuation_frame)
                +        offset = chunk_end
                @@ -779,2 +790,0 @@
                -        _, closed_since = @streams_recently_closed.first
                -
                @@ -783 +793,2 @@
                -        if closed_since && (now - closed_since) > 15
                +        if @oldest_stream_recently_closed && (now - @oldest_stream_recently_closed) > 15
                +          new_oldest = nil
                @@ -786,3 +797,9 @@
                -          @streams_recently_closed = @streams_recently_closed.drop_while do |_, since|
                -            (now - since) > 15
                -          end.to_h
                +          @streams_recently_closed.delete_if do |_, since|
                +            unless (now - since) > 15
                +              new_oldest ||= since
                +              break
                +            end
                +
                +            true
                +          end
                +          @oldest_stream_recently_closed = new_oldest
                @@ -791 +808 @@
                -        @streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
                +        @streams_recently_closed[id] = now
        lib/http/2/extensions.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/extensions.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/extensions.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -25,2 +25,3 @@
                -    def read_str(str, n)
                -      return "".b if n == 0
                +    if String.method_defined?(:bytesplice)
                +      def read_str(str, n)
                +        return "".b if n == 0
                @@ -28,4 +29,13 @@
                -      chunk = str.byteslice(0..(n - 1))
                -      remaining = str.byteslice(n..-1)
                -      remaining ? str.replace(remaining) : str.clear
                -      chunk
                +        chunk = str.byteslice(0, n)
                +        str.bytesplice(0, chunk.length, "")
                +        chunk
                +      end
                +    else
                +      def read_str(str, n)
                +        return "".b if n == 0
                +
                +        chunk = str.byteslice(0, n)
                +        remaining = str.byteslice(n, str.size - n)
                +        remaining ? str.replace(remaining) : str.clear
                +        chunk
                +      end
                @@ -36,4 +45,0 @@
                -    end
                -
                -    def shift_byte(str)
                -      read_str(str, 1).ord
        lib/http/2/flow_buffer.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/flow_buffer.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/flow_buffer.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -73 +73 @@
                -          end_stream = frame[:flags].include?(:end_stream)
                +          end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -117,0 +118,2 @@
                +    include BufferUtils
                +
                @@ -143 +145 @@
                -      end_stream = frame[:flags].include?(:end_stream)
                +      end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -151,2 +153 @@
                -        chunk   = frame.dup
                -        payload = frame[:payload]
                +        chunk = frame.dup
                @@ -157 +158 @@
                -        chunk[:payload] = payload.byteslice(0, window_size)
                +        chunk[:payload] = read_str(frame[:payload], window_size) # mutates frame[:payload]
                @@ -159 +159,0 @@
                -        frame[:payload] = payload.byteslice(window_size..-1)
                @@ -163 +163 @@
                -        chunk[:flags] -= [:end_stream] if end_stream
                +        chunk[:flags] ^= END_STREAM if end_stream
        lib/http/2/framer.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/framer.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/framer.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -3,0 +4,19 @@
                +  # Frame flags as defined by the spec (max 255 bits)
                +  # DATA:          ( X X COMPRESSED X PADDED X X END_STREAM )
                +  # HEADERS:       ( X X PRIORITY X PADDED END_HEADERS X END_STREAM )
                +  # PRIORITY:      ( X X X X X X X X )
                +  # RST_STREAM:    ( X X X X X X X X )
                +  # SETTINGS:      ( X X X X X X X ACK )
                +  # PUSH_PROMISE:  ( X X X X PADDED END_HEADERS X X )
                +  # PING:          ( X X X X X X X ACK )
                +  # GOAWAY:        ( X X X X X X X X )
                +  # WINDOW_UPDATE: ( X X X X X X X X )
                +  # CONTINUATION:  ( X X X X X END_HEADERS X X )
                +  # ALTSVC:        ( X X X X X X X X )
                +  # ORIGIN:        ( RESERVED4 X X RESERVED3 X RESERVED2 RESERVED X )
                +  END_STREAM = ACK = 0b0001 # 1
                +  RESERVED = 0b0010 # 2
                +  END_HEADERS = 0b0100 # 4
                +  PADDED = 0b1000 # 8
                +  PRIORITY = 0b0010_0000 # 32
                +
                @@ -43,33 +61,0 @@
                -    # Per frame flags as defined by the spec
                -    FRAME_FLAGS = {
                -      data: {
                -        end_stream: 0,
                -        padded: 3,
                -        compressed: 5
                -      },
                -      headers: {
                -        end_stream: 0,
                -        end_headers: 2,
                -        padded: 3,
                -        priority: 5
                -      },
                -      priority: {},
                -      rst_stream: {},
                -      settings: { ack: 0 },
                -      push_promise: {
                -        end_headers: 2,
                -        padded: 3
                -      },
                -      ping: { ack: 0 },
                -      goaway: {},
                -      window_update: {},
                -      continuation: { end_headers: 2 },
                -      altsvc: {},
                -      origin: {
                -        reserved: 1,
                -        reserved2: 2,
                -        reserved3: 4,
                -        reserved4: 8
                -      }
                -    }.each_value(&:freeze).freeze
                -
                @@ -86,17 +72,19 @@
                -    # Default error types as defined by the spec
                -    DEFINED_ERRORS = {
                -      no_error: 0,
                -      protocol_error: 1,
                -      internal_error: 2,
                -      flow_control_error: 3,
                -      settings_timeout: 4,
                -      stream_closed: 5,
                -      frame_size_error: 6,
                -      refused_stream: 7,
                -      cancel: 8,
                -      compression_error: 9,
                -      connect_error: 10,
                -      enhance_your_calm: 11,
                -      inadequate_security: 12,
                -      http_1_1_required: 13
                -    }.freeze
                +    DEFINED_SETTINGS_BY_ID = DEFINED_SETTINGS.invert.freeze
                +
                +    # Default error types as defined by the spec (the code is the array index)
                +    DEFINED_ERRORS = %i[
                +      no_error
                +      protocol_error
                +      internal_error
                +      flow_control_error
                +      settings_timeout
                +      stream_closed
                +      frame_size_error
                +      refused_stream
                +      cancel
                +      compression_error
                +      connect_error
                +      enhance_your_calm
                +      inadequate_security
                +      http_1_1_required
                +    ].freeze
                @@ -110,0 +99,2 @@
                +    PRIORITYPACK = (UINT32 + UINT8).freeze
                +    ALTSVCPACK = (UINT32 + UINT16).freeze
                @@ -114 +104 @@
                -    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :UINT32, :UINT16, :UINT8
                +    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :PRIORITYPACK, :UINT32, :UINT16, :UINT8
                @@ -148,0 +139,4 @@
                +      flags = frame[:flags]
                +
                +      raise CompressionError, "Invalid frame flag (#{flags}) for #{type}" unless flags.between?(0, 255)
                +
                @@ -163,6 +157 @@
                -             frame[:flags].reduce(0) do |acc, f|
                -               position = FRAME_FLAGS[type][f]
                -               raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
                -
                -               acc | (1 << position)
                -             end,
                +             flags,
                @@ -187,3 +176 @@
                -        flags: FRAME_FLAGS[type].filter_map do |name, pos|
                -          name if flags.anybits?(1 << pos)
                -        end,
                +        flags: flags,
                @@ -201 +188 @@
                -      frame[:flags] ||= EMPTY
                +      frame[:flags] ||= 0
                @@ -204,0 +192 @@
                +        # @type var frame: data_frame | continuation_frame
                @@ -216 +204 @@
                -          frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
                +          frame[:flags] |= PRIORITY
                @@ -219 +207 @@
                -        if frame[:flags].include?(:priority)
                +        if frame[:flags].anybits?(PRIORITY)
                @@ -222,2 +210,4 @@
                -          pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -          pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +          pack(
                +            [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +            PRIORITYPACK, buffer: bytes
                +          )
                @@ -237,2 +227,4 @@
                -        pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -        pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +        pack(
                +          [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +          PRIORITYPACK, buffer: bytes
                +        )
                @@ -251 +242,0 @@
                -        bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
                @@ -253,5 +244,6 @@
                -        settings.each do |(k, v)|
                -          if k.is_a? Integer # rubocop:disable Style/GuardClause
                -            DEFINED_SETTINGS.value?(k) || next
                -          else
                -            k = DEFINED_SETTINGS[k]
                +        case settings
                +        when String
                +          length = settings.bytesize
                +          bytes = settings
                +        else
                +          bytes = String.new("", encoding: Encoding::BINARY, capacity: settings.size * 6)
                @@ -259 +251,12 @@
                -            raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +          settings.each do |(k, v)|
                +            if k.is_a? Integer # rubocop:disable Style/GuardClause
                +              DEFINED_SETTINGS.value?(k) || next
                +            else
                +              k = DEFINED_SETTINGS[k]
                +
                +              raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +            end
                +
                +            pack([k], UINT16, buffer: bytes)
                +            pack([v], UINT32, buffer: bytes)
                +            length += 6
                @@ -261,4 +263,0 @@
                -
                -          pack([k], UINT16, buffer: bytes)
                -          pack([v], UINT32, buffer: bytes)
                -          length += 6
                @@ -298 +297 @@
                -        pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
                +        pack([frame[:max_age], frame[:port]], ALTSVCPACK, buffer: bytes)
                @@ -357 +356 @@
                -        frame[:flags] += [:padded]
                +        frame[:flags] |= PADDED
                @@ -378,3 +377,3 @@
                -      type = frame[:type]
                -      length = frame[:length]
                -      flags = frame[:flags]
                +      type = frame[:type] #: Symbol
                +      length = frame[:length] #: Integer
                +      flags = frame[:flags] #: Integer
                @@ -397 +396 @@
                -        padded = flags.include?(:padded)
                +        padded = flags.anybits?(PADDED)
                @@ -400 +398,0 @@
                -          frame[:padding] = padlen + 1
                @@ -402,0 +401,2 @@
                +          frame[:padding] = padlen + 1
                +
                @@ -405 +405 @@
                -          flags.delete(:padded)
                +          frame[:flags] ^= PADDED
                @@ -413 +413 @@
                -        if flags.include?(:priority)
                +        if flags.anybits?(PRIORITY)
                @@ -417 +417 @@
                -          weight = payload.byteslice(0, 1).ord + 1
                +          weight = payload.getbyte(0) + 1
                @@ -428 +428 @@
                -        weight = payload.byteslice(0, 1).ord + 1
                +        weight = payload.getbyte(0) + 1
                @@ -439 +438,0 @@
                -        frame[:payload] = []
                @@ -444 +443 @@
                -        (frame[:length] / 6).times do
                +        frame[:payload] = (frame[:length] / 6).times.filter_map do
                @@ -450,2 +449,3 @@
                -          name, = DEFINED_SETTINGS.find { |_name, v| v == id }
                -          frame[:payload] << [name, val] if name
                +          if (name = DEFINED_SETTINGS_BY_ID[id])
                +            [name, val]
                +          end
                @@ -467 +467 @@
                -        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
                +        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(ALTSVCPACK)
                @@ -469 +469 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -473 +473 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -498 +498 @@
                -        error = DEFINED_ERRORS[error]
                +        error = DEFINED_ERRORS.index(error)
                @@ -507 +507 @@
                -      DEFINED_ERRORS.key(error) || error
                +      DEFINED_ERRORS.fetch(error, error)
        lib/http/2/header/compressor.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/header/compressor.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/header/compressor.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -85,0 +86,2 @@
                +            integer(huffman.bytesize, 7, buffer: buffer)
                +            buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
                @@ -87 +89 @@
                -            set_huffman_size(buffer, huffman_offset)
                +            buffer
                @@ -122 +124 @@
                -        fb = buffer[offset].ord | rep[:pattern]
                +        fb = buffer.getbyte(offset) | rep[:pattern]
                @@ -149,0 +152 @@
                +        buffer << "\x00".b
                @@ -151 +154,9 @@
                -        set_huffman_size(buffer, huffman_offset)
                +        size = buffer.bytesize - huffman_offset - 1
                +
                +        if size < 127
                +          buffer.setbyte(huffman_offset, 0x80 | size)
                +        else
                +          buffer.slice!(huffman_offset, 1)
                +          set_huffman_size(buffer, huffman_offset)
                +        end
                +        buffer
                @@ -168 +179 @@
                -        buffer.setbyte(huffman_offset, buffer[huffman_offset].ord | 0x80)
                +        buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
        lib/http/2/header/decompressor.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/header/decompressor.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/header/decompressor.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -36 +36,7 @@
                -        i = n.zero? ? 0 : (shift_byte(buf) & limit)
                +        if n.zero?
                +          i = 0
                +          consumed = 0
                +        else
                +          i = buf.getbyte(0) & limit
                +          consumed = 1
                +        end
                @@ -38 +43,0 @@
                -        m = 0
                @@ -40,5 +45,2 @@
                -          offset = 0
                -
                -          buf.each_byte.with_index do |byte, idx|
                -            offset = idx
                -            # while (byte = shift_byte(buf))
                +          m = 0
                +          while (byte = buf.getbyte(consumed))
                @@ -47 +49 @@
                -
                +            consumed += 1
                @@ -50,2 +51,0 @@
                -
                -          read_str(buf, offset + 1)
                @@ -53,0 +54 @@
                +        read_str(buf, consumed)
        lib/http/2/header/encoding_context.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -120,0 +121,2 @@
                +        @table_by_field = Hash.new { |hs, k| hs[k] = [] }
                +        @unshifts = 0
                @@ -131,0 +134,2 @@
                +        tbf = @table_by_field.transform_values(&:dup)
                +        unshifts = @unshifts
                @@ -134,0 +139,2 @@
                +          @table_by_field = tbf
                +          @unshifts = unshifts
                @@ -215,0 +222,2 @@
                +            @unshifts += 1
                +            @table_by_field[name].unshift([value, @unshifts])
                @@ -282,2 +290 @@
                -          @table.each_with_index do |(hfield, hvalue), i|
                -            next unless field == hfield
                +          field_entries = @table_by_field[field]
                @@ -284,0 +292,3 @@
                +          field_entries&.each do |hvalue, unshift_id|
                +            abs_index = (@unshifts - unshift_id) + STATIC_TABLE_SIZE
                +            name_only ||= abs_index
                @@ -286 +296 @@
                -              exact = i + STATIC_TABLE_SIZE
                +              exact = abs_index
                @@ -288,2 +297,0 @@
                -            else
                -              name_only ||= i + STATIC_TABLE_SIZE
                @@ -320 +327,0 @@
                -
                @@ -322,0 +330,5 @@
                +
                +          field_arr = @table_by_field[name]
                +          field_arr.pop
                +          @table_by_field.delete(name) if field_arr.empty?
                +
        lib/http/2/header/huffman.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/header/huffman.rb	2026-06-17 02:34:13.510772062 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/header/huffman.rb	2026-06-17 02:34:13.516772035 +0000
                @@ -22,0 +23,2 @@
                +      EOS_PADDING = (0..7).map { |n| ("1" * n).b.freeze }.freeze
                +
                @@ -32 +34 @@
                -        append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
                +        append_str(bitstring, EOS_PADDING[(8 - bitstring.size) % 8])
                @@ -57 +59 @@
                -            append_str(emit, first.chr) if first
                +            emit << first if first
                @@ -63 +65 @@
                -        emit.force_encoding(Encoding::BINARY)
                +        emit
                @@ -328 +330 @@
                -      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1] }.each(&:freeze).freeze
                +      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1].b.freeze }.freeze
        lib/http/2/server.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/server.rb	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/server.rb	2026-06-17 02:34:13.517772030 +0000
                @@ -81,12 +81,6 @@
                -      buf = "".b
                -      append_str(buf, Base64.urlsafe_decode64(settings.to_s))
                -      @framer.common_header(
                -        {
                -          length: buf.bytesize,
                -          type: :settings,
                -          stream: 0,
                -          flags: []
                -        },
                -        buffer: buf
                -      )
                -      receive(buf)
                +      receive(@framer.generate(
                +                type: :settings,
                +                stream: 0,
                +                flags: 0,
                +                payload: Base64.urlsafe_decode64(settings.to_s)
                +              ))
                @@ -100 +94 @@
                -        flags: [:end_headers],
                +        flags: END_HEADERS,
                @@ -109 +103 @@
                -        headers_frame[:flags] << [:end_stream]
                +        headers_frame[:flags] |= END_HEADERS
                @@ -113 +107 @@
                -        stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
                +        stream << { type: :data, stream: 1, payload: body, flags: END_STREAM }
                @@ -138 +132 @@
                -      return unless frame[:flags].include?(:ack) && !@origins_sent
                +      return unless frame[:flags].anybits?(ACK) && !@origins_sent
                @@ -151 +145 @@
                -    # @param flags [Array[Symbol]]
                +    # @param flags Integer
                @@ -160 +154 @@
                -        payload: headers.to_a
                +        payload: headers
        lib/http/2/stream.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/stream.rb	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/stream.rb	2026-06-17 02:34:13.518772025 +0000
                @@ -117 +117,2 @@
                -      case frame[:type]
                +      frame_type = frame[:type] #: Symbol
                +      case frame_type
                @@ -118,0 +120 @@
                +        # @type var frame: data_frame
                @@ -131,0 +134 @@
                +        # @type var frame: headers_frame
                @@ -153,0 +157 @@
                +        # @type var frame: priority_frame
                @@ -155,0 +160 @@
                +        # @type var frame: window_update_frame
                @@ -157,0 +163 @@
                +        # @type var frame: origin_frame
                @@ -162,3 +168 @@
                -        emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty?
                -      when :blocked
                -        emit(frame[:type], frame)
                +        emit(frame_type, frame) if !frame[:origin] || frame[:origin].empty?
                @@ -201,0 +206 @@
                +        # @type var frame: data_frame
                @@ -204,0 +210 @@
                +        # @type var frame: window_update_frame
                @@ -206,0 +213 @@
                +        # @type var frame: priority_frame
                @@ -222,3 +229,2 @@
                -      flags = []
                -      flags << :end_headers if end_headers
                -      flags << :end_stream  if end_stream || @_method == "HEAD"
                +      flags = end_headers ? END_HEADERS : 0
                +      flags |= END_STREAM  if end_stream || @_method == "HEAD"
                @@ -232 +238 @@
                -      flags = end_headers ? [:end_headers] : []
                +      flags = end_headers ? END_HEADERS : 0
                @@ -257 +263 @@
                -          send(type: :data, flags: [], payload: chunk)
                +          send(type: :data, flags: 0, payload: chunk)
                @@ -261,2 +267,2 @@
                -      flags = []
                -      flags << :end_stream if end_stream
                +      flags = 0
                +      flags |= END_STREAM if end_stream
                @@ -666 +672,2 @@
                -        frame[:flags] && frame[:flags].include?(:end_stream)
                +        # @type var frame: data_frame | headers_frame | continuation_frame
                +        frame[:flags] && frame[:flags].anybits?(END_STREAM)
        lib/http/2/version.rb
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/lib/http/2/version.rb	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/lib/http/2/version.rb	2026-06-17 02:34:13.518772025 +0000
                @@ -4 +4 @@
                -  VERSION = "1.1.3"
                +  VERSION = "1.2.0"
        sig/2.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/2.rbs	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/2.rbs	2026-06-17 02:34:13.518772025 +0000
                @@ -38,0 +39,8 @@
                +  # Frame flags
                +  END_STREAM: Integer
                +  ACK: Integer
                +  RESERVED: Integer
                +  END_HEADERS: Integer
                +  PADDED: Integer
                +  PRIORITY: Integer
                +
                @@ -42 +50,3 @@
                -  type frame_control_flags = Array[:end_headers | :end_stream]
                +  type frame_control_flags = Integer
                +
                +  type common_frame = { stream: Integer, flags: frame_control_flags, ?length: Integer, ?ignore: bool }
                @@ -44 +54 @@
                -  type common_frame = { stream: Integer }
                +  type connection_frame = settings_frame | ping_frame | goaway_frame | window_update_frame | altsvc_frame | origin_frame
                @@ -47,2 +57,2 @@
                -  type headers_frame = common_frame & {
                -    type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
                +  type headers_frame_props = {
                +    type: :headers, payload: Enumerable[header_pair] | String,
                @@ -50,0 +61,5 @@
                +  type headers_frame = common_frame & headers_frame_props
                +
                +  type continuation_frame_props = headers_frame_props | { type: :continuation }
                +
                +  type continuation_frame = common_frame & continuation_frame_props
                @@ -53 +68,3 @@
                -  type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
                +  type data_frame_props = { type: :data, ?length: Integer, payload: String, ?padding: Integer }
                +
                +  type data_frame = common_frame & data_frame_props
                @@ -56 +73,3 @@
                -  type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
                +  type push_promise_frame_props = { promise_stream: Integer, ?length: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair] | String, ?padding: Integer }
                +
                +  type push_promise_frame = common_frame & push_promise_frame_props
                @@ -59 +78,3 @@
                -  type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
                +  type settings_frame_props = { type: :settings, payload: (Enumerable[[Symbol | Integer, Integer]] | String) }
                +
                +  type settings_frame = common_frame & settings_frame_props
                @@ -62 +83,3 @@
                -  type window_update_frame = { type: :window_update, increment: Integer }
                +  type window_update_frame_props = { type: :window_update, increment: Integer }
                +
                +  type window_update_frame = common_frame & window_update_frame_props
                @@ -65 +88,5 @@
                -  type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
                +  type priority_frame_inner_props = { dependency: Integer, exclusive: bool, weight: Integer }
                +
                +  type priority_frame_props = { type: :priority } & priority_frame_inner_props
                +
                +  type priority_frame = common_frame & priority_frame_props
                @@ -68 +95,3 @@
                -  type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
                +  type altsvc_frame_props = { type: :altsvc, max_age: Integer, port: Integer, proto: String, host: String }
                +
                +  type altsvc_frame = common_frame & altsvc_frame_props
                @@ -71 +100,3 @@
                -  type origin_frame = { type: :origin, origin: Array[String] }
                +  type origin_frame_props = { type: :origin, payload: Array[String] }
                +
                +  type origin_frame = common_frame & origin_frame_props
                @@ -74 +105,3 @@
                -  type ping_frame = { type: :ping, payload: String, length: Integer }
                +  type ping_frame_props = { type: :ping, payload: String }
                +
                +  type ping_frame = common_frame & ping_frame_props
                @@ -77 +110,3 @@
                -  type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
                +  type goaway_frame_props = { type: :goaway, last_stream: Integer, error: (Symbol | Integer)? }
                +
                +  type goaway_frame = common_frame & goaway_frame_props
                @@ -79 +114,6 @@
                -  # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
                +  # # RST_STREAM
                +  type rst_stream_frame_props = { type: :rst_stream, error: (Symbol | Integer)? }
                +
                +  type rst_stream_frame = common_frame & rst_stream_frame_props
                +
                +  # type frame = headers_frame | continuation_frame | push_promise_frame | data_frame |
                @@ -81 +121,8 @@
                -  #              origin_frame | ping_frame | goaway_frame)
                +  #              origin_frame | ping_frame | goaway_frame | rst_stream_frame
                +
                +  # type connection_frame_props = rst_stream_frame_props | ping_frame_props | goaway_frame_props
                +  #                             | window_update_frame_props | settings_frame_props
                +
                +  # type stream_frame_props = headers_frame_props | continuation_frame_props | push_promise_frame_props
                +  #                         | data_frame_props  | rst_stream_frame_props | priority_frame_props
                +  #                         | window_update_frame_props | origin_frame_props | altsvc_frame_props
                @@ -111,0 +159,2 @@
                +  type connection_frame_props = Hash[frame_key, frame_value]
                +  type stream_frame_props = Hash[frame_key, frame_value]
        sig/connection.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/connection.rbs	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/connection.rbs	2026-06-17 02:34:13.518772025 +0000
                @@ -35,0 +36 @@
                +    @oldest_stream_recently_closed: Numeric
                @@ -52,0 +54 @@
                +    @continuation_size: Integer
                @@ -71 +73 @@
                -    def receive: (string data) -> void
                +    def receive: (String data) -> void
                @@ -78 +80 @@
                -    def send: (frame frame) -> void
                +    def send: (connection_frame_props | stream_frame_props frame) -> void
                @@ -84 +86 @@
                -    def connection_management: (frame) -> void
                +    def connection_management: (connection_frame frame) -> void
                @@ -90 +92 @@
                -    def connection_settings: (frame) -> void
                +    def connection_settings: (settings_frame) -> void
                @@ -92 +94 @@
                -    def decode_headers: (frame) -> void
                +    def decode_headers: (headers_frame | push_promise_frame) -> void
                @@ -94 +96 @@
                -    def encode_headers: (frame headers_frame) -> void
                +    def encode_headers: (headers_frame | push_promise_frame) -> void
                @@ -100 +102 @@
                -    def verify_pseudo_headers: (frame) -> void
                +    def verify_pseudo_headers: (headers_frame | push_promise_frame) -> void
                @@ -102 +104 @@
                -    def _verify_pseudo_headers: (frame, Array[String]) -> void
                +    def _verify_pseudo_headers: (headers_frame | push_promise_frame, Array[String]) -> void
                @@ -106 +108 @@
                -end
                \ No newline at end of file
                +end
        sig/flow_buffer.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/flow_buffer.rbs	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/flow_buffer.rbs	2026-06-17 02:34:13.518772025 +0000
                @@ -17 +17 @@
                -    def send_data: (?data_frame? frame, ?bool encode) -> void
                +    def send_data: (?data_frame_props? frame, ?bool encode) -> void
                @@ -19 +19 @@
                -    def send_frame: (data_frame frame, bool encode) -> void
                +    def send_frame: (data_frame_props frame, bool encode) -> void
        sig/frame_buffer.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/frame_buffer.rbs	2026-06-17 02:34:13.511772057 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/frame_buffer.rbs	2026-06-17 02:34:13.518772025 +0000
                @@ -2,0 +3,2 @@
                +    include BufferUtils
                +
                @@ -9 +11 @@
                -    def <<: (data_frame frame) -> void
                +    def <<: (data_frame_props frame) -> void
                @@ -13 +15 @@
                -    def retrieve: (Integer) -> data_frame?
                +    def retrieve: (Integer) -> data_frame_props?
        sig/framer.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/framer.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/framer.rbs	2026-06-17 02:34:13.518772025 +0000
                @@ -23 +23,3 @@
                -    DEFINED_ERRORS: Hash[Symbol, Integer]
                +    DEFINED_SETTINGS_BY_ID: Hash[Integer, Symbol]
                +
                +    DEFINED_ERRORS: Array[Symbol]
                @@ -31,0 +34,2 @@
                +    PRIORITYPACK: String
                +    ALTSVCPACK: String
                @@ -44 +48 @@
                -    def read_common_header: (String buf) -> frame
                +    def read_common_header: (String buf) -> (common_frame | { length: Integer })
                @@ -50 +54 @@
                -    def parse: (String) -> frame?
                +    def parse: (String) -> (frame | { length: Integer })?
                @@ -56 +60 @@
                -    def pack_error: (Integer | Symbol error, buffer: String) -> String
                +    def pack_error: (Symbol | Integer error, buffer: String) -> String
        sig/header/compressor.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/header/compressor.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/header/compressor.rbs	2026-06-17 02:34:13.519772021 +0000
                @@ -4,0 +5 @@
                +      include BufferUtils
        sig/header/encoding_context.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/header/encoding_context.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/header/encoding_context.rbs	2026-06-17 02:34:13.519772021 +0000
                @@ -24,0 +25,4 @@
                +      @table_by_field: Hash[string, Array[[string, Integer]]]
                +
                +      @unshifts: Integer
                +
        sig/header/huffman.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/header/huffman.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/header/huffman.rbs	2026-06-17 02:34:13.519772021 +0000
                @@ -11,0 +12,2 @@
                +      EOS_PADDING: Array[String]
                +
        sig/server.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/server.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/server.rbs	2026-06-17 02:34:13.519772021 +0000
                @@ -10 +10 @@
                -    def promise: (Stream parent, Enumerable[header_pair] headers, Array[Symbol] flags) { (Stream) -> void } -> void
                +    def promise: (Stream parent, Enumerable[header_pair] headers, frame_control_flags flags) { (Stream) -> void } -> void
        sig/stream.rbs
                --- /tmp/d20260617-465-g5hhde/http-2-1.1.3/sig/stream.rbs	2026-06-17 02:34:13.514772044 +0000
                +++ /tmp/d20260617-465-g5hhde/http-2-1.2.0/sig/stream.rbs	2026-06-17 02:34:13.519772021 +0000
                @@ -40 +40 @@
                -    def send: (frame frame) -> void
                +    def send: (stream_frame_props frame) -> void
                @@ -73 +73 @@
                -    def transition: (frame, bool sending) -> void
                +    def transition: (stream_frame_props frame, bool sending) -> void
                @@ -83 +83 @@
                -    def process_priority: (priority_frame frame) -> void
                +    def process_priority: (priority_frame_inner_props frame) -> void
                @@ -85 +85 @@
                -    def end_stream?: (frame frame) -> boolish
                +    def end_stream?: (stream_frame_props frame) -> boolish
                @@ -87,2 +87 @@
                -    def stream_error: (Symbol error, ?msg: String?) -> void
                -                    | () -> void
                +    def stream_error: (?Symbol error, ?msg: String?) -> void
                @@ -92 +91 @@
                -    def manage_state: (frame) { () -> void } -> void
                +    def manage_state: (stream_frame_props frame) { () -> void } -> void
                @@ -94 +93 @@
                -end
                \ No newline at end of file
                +end

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

gem compare httpx 1.7.8 1.8.0

Compared versions: ["1.7.8", "1.8.0"]
  DIFFERENT version:
    1.7.8: 1.7.8
    1.8.0: 1.8.0
  DIFFERENT files:
    1.7.8->1.8.0:
      * Deleted:
            lib/httpx/plugins/response_cache/file_store.rb
            lib/httpx/plugins/response_cache/store.rb
            sig/plugins/response_cache/file_store.rbs
            sig/plugins/response_cache/store.rbs
      * Added:
            doc/release_notes/1_8_0.md +100/-0
            lib/httpx/plugins/cache.rb +221/-0
            lib/httpx/plugins/cache/file_store.rb +141/-0
            lib/httpx/plugins/cache/store.rb +33/-0
            lib/httpx/plugins/ntlm_v2_auth.rb +92/-0
            lib/httpx/plugins/server_sent_events.rb +158/-0
            lib/httpx/resolver/cache/file.rb +56/-0
            sig/plugins/cache.rbs +69/-0
            sig/plugins/cache/file_store.rbs +21/-0
            sig/plugins/cache/store.rbs +13/-0
            sig/plugins/ntlm_v2_auth.rbs +36/-0
            sig/plugins/server_sent_events.rbs +45/-0
            sig/resolver/cache/file.rbs +13/-0
      * Changed:
            lib/httpx/adapters/datadog.rb +3/-1
            lib/httpx/connection.rb +76/-7
            lib/httpx/connection/http1.rb +10/-1
            lib/httpx/connection/http2.rb +37/-4
            lib/httpx/errors.rb +8/-1
            lib/httpx/io/tcp.rb +11/-1
            lib/httpx/options.rb +16/-4
            lib/httpx/parser/http1.rb +8/-2
            lib/httpx/plugins/auth.rb +52/-4
            lib/httpx/plugins/fiber_concurrency.rb +50/-3
            lib/httpx/plugins/oauth.rb +66/-14
            lib/httpx/plugins/proxy.rb +5/-0
            lib/httpx/plugins/response_cache.rb +26/-105
            lib/httpx/plugins/retries.rb +7/-5
            lib/httpx/plugins/ssrf_filter.rb +16/-1
            lib/httpx/plugins/stream.rb +7/-3
            lib/httpx/plugins/tracing.rb +15/-4
            lib/httpx/request.rb +18/-1
            lib/httpx/resolver/native.rb +14/-3
            lib/httpx/response.rb +9/-1
            lib/httpx/response/body.rb +4/-2
            lib/httpx/selector.rb +7/-1
            lib/httpx/version.rb +1/-1
            sig/chainable.rbs +3/-0
            sig/connection.rbs +11/-8
            sig/connection/http1.rbs +1/-1
            sig/connection/http2.rbs +1/-1
            sig/errors.rbs +9/-3
            sig/httpx.rbs +2/-0
            sig/io/tcp.rbs +2/-0
            sig/loggable.rbs +4/-0
            sig/options.rbs +25/-12
            sig/parser/http1.rbs +3/-1
            sig/plugins/auth/ntlm.rbs +1/-1
            sig/plugins/fiber_concurrency.rbs +4/-0
            sig/plugins/response_cache.rbs +13/-38
            sig/plugins/retries.rbs +5/-5
            sig/plugins/ssrf_filter.rbs +5/-1
            sig/plugins/stream.rbs +1/-1
            sig/plugins/stream_bidi.rbs +0/-2
            sig/plugins/webdav.rbs +1/-1
            sig/pool.rbs +2/-2
            sig/request.rbs +7/-3
            sig/resolver.rbs +3/-0
            sig/resolver/entry.rbs +1/-1
            sig/resolver/https.rbs +3/-3
            sig/resolver/multi.rbs +1/-1
            sig/resolver/native.rbs +5/-5
            sig/resolver/resolver.rbs +1/-3
            sig/resolver/system.rbs +2/-2
            sig/response.rbs +3/-0
            sig/selector.rbs +11/-8
            sig/timers.rbs +5/-5
            sig/transcoder.rbs +2/-0
            sig/transcoder/body.rbs +1/-1
            sig/transcoder/gzip.rbs +3/-2
            sig/transcoder/multipart.rbs +4/-1
            sig/transcoder/utils/deflater.rbs +2/-0
            sig/utils.rbs +1/-1
  DIFFERENT extra_rdoc_files:
    1.7.8->1.8.0:
      * Added:
            doc/release_notes/1_8_0.md +100/-0
  DIFFERENT runtime dependencies:
    1.7.8->1.8.0:
      * Updated:
            http-2 from: [">= 1.1.3"] to: [">= 1.2.0"]

3 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

gem compare httpx 1.7.8 1.8.0

Compared versions: ["1.7.8", "1.8.0"]
  DIFFERENT version:
    1.7.8: 1.7.8
    1.8.0: 1.8.0
  DIFFERENT files:
    1.7.8->1.8.0:
      * Deleted:
            lib/httpx/plugins/response_cache/file_store.rb
            lib/httpx/plugins/response_cache/store.rb
            sig/plugins/response_cache/file_store.rbs
            sig/plugins/response_cache/store.rbs
      * Added:
            doc/release_notes/1_8_0.md +100/-0
            lib/httpx/plugins/cache.rb +221/-0
            lib/httpx/plugins/cache/file_store.rb +141/-0
            lib/httpx/plugins/cache/store.rb +33/-0
            lib/httpx/plugins/ntlm_v2_auth.rb +92/-0
            lib/httpx/plugins/server_sent_events.rb +158/-0
            lib/httpx/resolver/cache/file.rb +56/-0
            sig/plugins/cache.rbs +69/-0
            sig/plugins/cache/file_store.rbs +21/-0
            sig/plugins/cache/store.rbs +13/-0
            sig/plugins/ntlm_v2_auth.rbs +36/-0
            sig/plugins/server_sent_events.rbs +45/-0
            sig/resolver/cache/file.rbs +13/-0
      * Changed:
            lib/httpx/adapters/datadog.rb +3/-1
            lib/httpx/connection.rb +76/-7
            lib/httpx/connection/http1.rb +10/-1
            lib/httpx/connection/http2.rb +37/-4
            lib/httpx/errors.rb +8/-1
            lib/httpx/io/tcp.rb +11/-1
            lib/httpx/options.rb +16/-4
            lib/httpx/parser/http1.rb +8/-2
            lib/httpx/plugins/auth.rb +52/-4
            lib/httpx/plugins/fiber_concurrency.rb +50/-3
            lib/httpx/plugins/oauth.rb +66/-14
            lib/httpx/plugins/proxy.rb +5/-0
            lib/httpx/plugins/response_cache.rb +26/-105
            lib/httpx/plugins/retries.rb +7/-5
            lib/httpx/plugins/ssrf_filter.rb +16/-1
            lib/httpx/plugins/stream.rb +7/-3
            lib/httpx/plugins/tracing.rb +15/-4
            lib/httpx/request.rb +18/-1
            lib/httpx/resolver/native.rb +14/-3
            lib/httpx/response.rb +9/-1
            lib/httpx/response/body.rb +4/-2
            lib/httpx/selector.rb +7/-1
            lib/httpx/version.rb +1/-1
            sig/chainable.rbs +3/-0
            sig/connection.rbs +11/-8
            sig/connection/http1.rbs +1/-1
            sig/connection/http2.rbs +1/-1
            sig/errors.rbs +9/-3
            sig/httpx.rbs +2/-0
            sig/io/tcp.rbs +2/-0
            sig/loggable.rbs +4/-0
            sig/options.rbs +25/-12
            sig/parser/http1.rbs +3/-1
            sig/plugins/auth/ntlm.rbs +1/-1
            sig/plugins/fiber_concurrency.rbs +4/-0
            sig/plugins/response_cache.rbs +13/-38
            sig/plugins/retries.rbs +5/-5
            sig/plugins/ssrf_filter.rbs +5/-1
            sig/plugins/stream.rbs +1/-1
            sig/plugins/stream_bidi.rbs +0/-2
            sig/plugins/webdav.rbs +1/-1
            sig/pool.rbs +2/-2
            sig/request.rbs +7/-3
            sig/resolver.rbs +3/-0
            sig/resolver/entry.rbs +1/-1
            sig/resolver/https.rbs +3/-3
            sig/resolver/multi.rbs +1/-1
            sig/resolver/native.rbs +5/-5
            sig/resolver/resolver.rbs +1/-3
            sig/resolver/system.rbs +2/-2
            sig/response.rbs +3/-0
            sig/selector.rbs +11/-8
            sig/timers.rbs +5/-5
            sig/transcoder.rbs +2/-0
            sig/transcoder/body.rbs +1/-1
            sig/transcoder/gzip.rbs +3/-2
            sig/transcoder/multipart.rbs +4/-1
            sig/transcoder/utils/deflater.rbs +2/-0
            sig/utils.rbs +1/-1
  DIFFERENT extra_rdoc_files:
    1.7.8->1.8.0:
      * Added:
            doc/release_notes/1_8_0.md +100/-0
  DIFFERENT runtime dependencies:
    1.7.8->1.8.0:
      * Updated:
            http-2 from: [">= 1.1.3"] to: [">= 1.2.0"]

@github-actions

Copy link
Copy Markdown
Contributor

gem compare httpx 1.7.8 1.8.0

Compared versions: ["1.7.8", "1.8.0"]
  DIFFERENT version:
    1.7.8: 1.7.8
    1.8.0: 1.8.0
  DIFFERENT files:
    1.7.8->1.8.0:
      * Deleted:
            lib/httpx/plugins/response_cache/file_store.rb
            lib/httpx/plugins/response_cache/store.rb
            sig/plugins/response_cache/file_store.rbs
            sig/plugins/response_cache/store.rbs
      * Added:
            doc/release_notes/1_8_0.md +100/-0
            lib/httpx/plugins/cache.rb +221/-0
            lib/httpx/plugins/cache/file_store.rb +141/-0
            lib/httpx/plugins/cache/store.rb +33/-0
            lib/httpx/plugins/ntlm_v2_auth.rb +92/-0
            lib/httpx/plugins/server_sent_events.rb +158/-0
            lib/httpx/resolver/cache/file.rb +56/-0
            sig/plugins/cache.rbs +69/-0
            sig/plugins/cache/file_store.rbs +21/-0
            sig/plugins/cache/store.rbs +13/-0
            sig/plugins/ntlm_v2_auth.rbs +36/-0
            sig/plugins/server_sent_events.rbs +45/-0
            sig/resolver/cache/file.rbs +13/-0
      * Changed:
            lib/httpx/adapters/datadog.rb +3/-1
            lib/httpx/connection.rb +76/-7
            lib/httpx/connection/http1.rb +10/-1
            lib/httpx/connection/http2.rb +37/-4
            lib/httpx/errors.rb +8/-1
            lib/httpx/io/tcp.rb +11/-1
            lib/httpx/options.rb +16/-4
            lib/httpx/parser/http1.rb +8/-2
            lib/httpx/plugins/auth.rb +52/-4
            lib/httpx/plugins/fiber_concurrency.rb +50/-3
            lib/httpx/plugins/oauth.rb +66/-14
            lib/httpx/plugins/proxy.rb +5/-0
            lib/httpx/plugins/response_cache.rb +26/-105
            lib/httpx/plugins/retries.rb +7/-5
            lib/httpx/plugins/ssrf_filter.rb +16/-1
            lib/httpx/plugins/stream.rb +7/-3
            lib/httpx/plugins/tracing.rb +15/-4
            lib/httpx/request.rb +18/-1
            lib/httpx/resolver/native.rb +14/-3
            lib/httpx/response.rb +9/-1
            lib/httpx/response/body.rb +4/-2
            lib/httpx/selector.rb +7/-1
            lib/httpx/version.rb +1/-1
            sig/chainable.rbs +3/-0
            sig/connection.rbs +11/-8
            sig/connection/http1.rbs +1/-1
            sig/connection/http2.rbs +1/-1
            sig/errors.rbs +9/-3
            sig/httpx.rbs +2/-0
            sig/io/tcp.rbs +2/-0
            sig/loggable.rbs +4/-0
            sig/options.rbs +25/-12
            sig/parser/http1.rbs +3/-1
            sig/plugins/auth/ntlm.rbs +1/-1
            sig/plugins/fiber_concurrency.rbs +4/-0
            sig/plugins/response_cache.rbs +13/-38
            sig/plugins/retries.rbs +5/-5
            sig/plugins/ssrf_filter.rbs +5/-1
            sig/plugins/stream.rbs +1/-1
            sig/plugins/stream_bidi.rbs +0/-2
            sig/plugins/webdav.rbs +1/-1
            sig/pool.rbs +2/-2
            sig/request.rbs +7/-3
            sig/resolver.rbs +3/-0
            sig/resolver/entry.rbs +1/-1
            sig/resolver/https.rbs +3/-3
            sig/resolver/multi.rbs +1/-1
            sig/resolver/native.rbs +5/-5
            sig/resolver/resolver.rbs +1/-3
            sig/resolver/system.rbs +2/-2
            sig/response.rbs +3/-0
            sig/selector.rbs +11/-8
            sig/timers.rbs +5/-5
            sig/transcoder.rbs +2/-0
            sig/transcoder/body.rbs +1/-1
            sig/transcoder/gzip.rbs +3/-2
            sig/transcoder/multipart.rbs +4/-1
            sig/transcoder/utils/deflater.rbs +2/-0
            sig/utils.rbs +1/-1
  DIFFERENT extra_rdoc_files:
    1.7.8->1.8.0:
      * Added:
            doc/release_notes/1_8_0.md +100/-0
  DIFFERENT runtime dependencies:
    1.7.8->1.8.0:
      * Updated:
            http-2 from: [">= 1.1.3"] to: [">= 1.2.0"]

@github-actions

Copy link
Copy Markdown
Contributor

gem compare httpx 1.7.8 1.8.0

Compared versions: ["1.7.8", "1.8.0"]
  DIFFERENT version:
    1.7.8: 1.7.8
    1.8.0: 1.8.0
  DIFFERENT files:
    1.7.8->1.8.0:
      * Deleted:
            lib/httpx/plugins/response_cache/file_store.rb
            lib/httpx/plugins/response_cache/store.rb
            sig/plugins/response_cache/file_store.rbs
            sig/plugins/response_cache/store.rbs
      * Added:
            doc/release_notes/1_8_0.md +100/-0
            lib/httpx/plugins/cache.rb +221/-0
            lib/httpx/plugins/cache/file_store.rb +141/-0
            lib/httpx/plugins/cache/store.rb +33/-0
            lib/httpx/plugins/ntlm_v2_auth.rb +92/-0
            lib/httpx/plugins/server_sent_events.rb +158/-0
            lib/httpx/resolver/cache/file.rb +56/-0
            sig/plugins/cache.rbs +69/-0
            sig/plugins/cache/file_store.rbs +21/-0
            sig/plugins/cache/store.rbs +13/-0
            sig/plugins/ntlm_v2_auth.rbs +36/-0
            sig/plugins/server_sent_events.rbs +45/-0
            sig/resolver/cache/file.rbs +13/-0
      * Changed:
            lib/httpx/adapters/datadog.rb +3/-1
            lib/httpx/connection.rb +76/-7
            lib/httpx/connection/http1.rb +10/-1
            lib/httpx/connection/http2.rb +37/-4
            lib/httpx/errors.rb +8/-1
            lib/httpx/io/tcp.rb +11/-1
            lib/httpx/options.rb +16/-4
            lib/httpx/parser/http1.rb +8/-2
            lib/httpx/plugins/auth.rb +52/-4
            lib/httpx/plugins/fiber_concurrency.rb +50/-3
            lib/httpx/plugins/oauth.rb +66/-14
            lib/httpx/plugins/proxy.rb +5/-0
            lib/httpx/plugins/response_cache.rb +26/-105
            lib/httpx/plugins/retries.rb +7/-5
            lib/httpx/plugins/ssrf_filter.rb +16/-1
            lib/httpx/plugins/stream.rb +7/-3
            lib/httpx/plugins/tracing.rb +15/-4
            lib/httpx/request.rb +18/-1
            lib/httpx/resolver/native.rb +14/-3
            lib/httpx/response.rb +9/-1
            lib/httpx/response/body.rb +4/-2
            lib/httpx/selector.rb +7/-1
            lib/httpx/version.rb +1/-1
            sig/chainable.rbs +3/-0
            sig/connection.rbs +11/-8
            sig/connection/http1.rbs +1/-1
            sig/connection/http2.rbs +1/-1
            sig/errors.rbs +9/-3
            sig/httpx.rbs +2/-0
            sig/io/tcp.rbs +2/-0
            sig/loggable.rbs +4/-0
            sig/options.rbs +25/-12
            sig/parser/http1.rbs +3/-1
            sig/plugins/auth/ntlm.rbs +1/-1
            sig/plugins/fiber_concurrency.rbs +4/-0
            sig/plugins/response_cache.rbs +13/-38
            sig/plugins/retries.rbs +5/-5
            sig/plugins/ssrf_filter.rbs +5/-1
            sig/plugins/stream.rbs +1/-1
            sig/plugins/stream_bidi.rbs +0/-2
            sig/plugins/webdav.rbs +1/-1
            sig/pool.rbs +2/-2
            sig/request.rbs +7/-3
            sig/resolver.rbs +3/-0
            sig/resolver/entry.rbs +1/-1
            sig/resolver/https.rbs +3/-3
            sig/resolver/multi.rbs +1/-1
            sig/resolver/native.rbs +5/-5
            sig/resolver/resolver.rbs +1/-3
            sig/resolver/system.rbs +2/-2
            sig/response.rbs +3/-0
            sig/selector.rbs +11/-8
            sig/timers.rbs +5/-5
            sig/transcoder.rbs +2/-0
            sig/transcoder/body.rbs +1/-1
            sig/transcoder/gzip.rbs +3/-2
            sig/transcoder/multipart.rbs +4/-1
            sig/transcoder/utils/deflater.rbs +2/-0
            sig/utils.rbs +1/-1
  DIFFERENT extra_rdoc_files:
    1.7.8->1.8.0:
      * Added:
            doc/release_notes/1_8_0.md +100/-0
  DIFFERENT runtime dependencies:
    1.7.8->1.8.0:
      * Updated:
            http-2 from: [">= 1.1.3"] to: [">= 1.2.0"]

@github-actions

Copy link
Copy Markdown
Contributor

gem compare http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT version:
    1.1.3: 1.1.3
    1.2.0: 1.2.0
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
            lib/http/2/settings.rb +42/-0
      * Changed:
            lib/http/2/client.rb +1/-1
            lib/http/2/connection.rb +79/-62
            lib/http/2/extensions.rb +16/-10
            lib/http/2/flow_buffer.rb +7/-7
            lib/http/2/framer.rb +98/-98
            lib/http/2/header/compressor.rb +15/-4
            lib/http/2/header/decompressor.rb +11/-10
            lib/http/2/header/encoding_context.rb +18/-6
            lib/http/2/header/huffman.rb +6/-4
            lib/http/2/server.rb +12/-18
            lib/http/2/stream.rb +19/-12
            lib/http/2/version.rb +1/-1
            sig/2.rbs +64/-15
            sig/connection.rbs +11/-9
            sig/flow_buffer.rbs +2/-2
            sig/frame_buffer.rbs +4/-2
            sig/framer.rbs +8/-4
            sig/header/compressor.rbs +1/-0
            sig/header/encoding_context.rbs +4/-0
            sig/header/huffman.rbs +2/-0
            sig/server.rbs +1/-1
            sig/stream.rbs +7/-8

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff httpx 1.7.8 1.8.0

Diff too large (125710 chars)

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff httpx 1.7.8 1.8.0

Diff too large (125709 chars)

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff httpx 1.7.8 1.8.0

Diff too large (125710 chars)

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff httpx 1.7.8 1.8.0

Diff too large (125708 chars)

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff http-2 1.1.3 1.2.0

Compared versions: ["1.1.3", "1.2.0"]
  DIFFERENT files:
    1.1.3->1.2.0:
      * Added:
        lib/http/2/settings.rb
                --- /tmp/20260617-505-rz27kn	2026-06-17 02:34:59.312220208 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/settings.rb	2026-06-17 02:34:59.311220188 +0000
                @@ -0,0 +1,42 @@
                +# frozen_string_literal: true
                +
                +module HTTP2
                +  # Default values for SETTINGS frame, as defined by the spec.
                +  SPEC_DEFAULT_CONNECTION_SETTINGS = {
                +    settings_header_table_size: 4096,
                +    settings_enable_push: 1, # enabled for servers
                +    settings_max_concurrent_streams: Framer::MAX_STREAM_ID, # unlimited
                +    settings_initial_window_size: 65_535,
                +    settings_max_frame_size: 16_384,
                +    settings_max_header_list_size: (2 << 30) - 1 # unlimited
                +  }.freeze
                +
                +  Settings = Struct.new(
                +    :settings_header_table_size,
                +    :settings_enable_push,
                +    :settings_max_concurrent_streams,
                +    :settings_initial_window_size,
                +    :settings_max_frame_size,
                +    :settings_max_header_list_size,
                +    keyword_init: true
                +  ) do
                +    def initialize(
                +      settings_header_table_size: 4096,
                +      settings_enable_push: 1,
                +      settings_max_concurrent_streams: 100,
                +      settings_initial_window_size: 65_535,
                +      settings_max_frame_size: 16_384,
                +      settings_max_header_list_size: (2 << 30) - 1
                +    )
                +      super
                +    end
                +
                +    def each_setting
                +      each_pair do |k, v|
                +        next if v == SPEC_DEFAULT_CONNECTION_SETTINGS[k]
                +
                +        yield k, v
                +      end
                +    end
                +  end
                +end
      * Changed:
        lib/http/2/client.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/client.rb	2026-06-17 02:34:59.305220066 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/client.rb	2026-06-17 02:34:59.309220147 +0000
                @@ -72 +72 @@
                -      frame = Framer.new.generate(type: :settings, stream: 0, payload: settings)
                +      frame = Framer.new.generate(type: :settings, stream: 0, flags: 0, payload: settings)
        lib/http/2/connection.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/connection.rb	2026-06-17 02:34:59.305220066 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/connection.rb	2026-06-17 02:34:59.309220147 +0000
                @@ -44,2 +43,0 @@
                -  HEADERS_FRAME_TYPES = %i[headers push_promise].freeze
                -
                @@ -93,0 +92 @@
                +      @oldest_stream_recently_closed = nil
                @@ -104,0 +104 @@
                +      @continuation_size = 0
                @@ -159 +159 @@
                -      send(type: :goaway, last_stream: @last_stream_id,
                +      send(type: :goaway, stream: 0, last_stream: @last_stream_id,
                @@ -181 +180,0 @@
                -      @pending_settings << payload
                @@ -215,3 +214,2 @@
                -        # @type var stream_id: Integer
                -        stream_id = frame[:stream]
                -        frame_type = frame[:type]
                +        stream_id = frame[:stream] #: Integer
                +        frame_type = frame[:type] #: Symbol?
                @@ -239,0 +238 @@
                +          # @type var frame: continuation_frame
                @@ -243,2 +242,2 @@
                -          unless frame[:flags].include? :end_headers
                -            buffered_payload = @continuation.sum { |f| f[:payload].bytesize }
                +          @continuation_size += frame[:payload].bytesize
                +          unless frame[:flags].anybits?(END_HEADERS)
                @@ -248 +247 @@
                -            unless buffered_payload < @local_settings[:settings_max_frame_size]
                +            unless @continuation_size < @local_settings[:settings_max_frame_size]
                @@ -261,0 +261 @@
                +          @continuation_size = 0
                @@ -265 +265 @@
                -          frame[:flags] << :end_headers
                +          frame[:flags] |= END_HEADERS
                @@ -273,0 +274 @@
                +          # @type var frame: connection_frame
                @@ -278,0 +280 @@
                +            # @type var frame: headers_frame
                @@ -285 +287 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -314,0 +317 @@
                +            # @type var frame: push_promise_frame
                @@ -317 +320 @@
                -            unless frame[:flags].include? :end_headers
                +            unless frame[:flags].anybits?(END_HEADERS)
                @@ -437,2 +439,0 @@
                -      frame_type = frame[:type]
                -
                @@ -440,2 +440,0 @@
                -      if frame_type == :data
                -        send_data(frame, true)
                @@ -443,3 +442 @@
                -      elsif frame_type == :rst_stream && frame[:error] == :protocol_error
                -        # An endpoint can end a connection at any time. In particular, an
                -        # endpoint MAY choose to treat a stream error as a connection error.
                +      frame_type = frame[:type] #: Symbol
                @@ -447,2 +444,5 @@
                -        goaway(:protocol_error)
                -      else
                +      case frame_type
                +      when :data
                +        #: @type var frame: data_frame
                +        send_data(frame, true)
                +      when :headers, :push_promise
                @@ -450,0 +451,10 @@
                +        #: @type var frame: headers_frame | push_promise_frame
                +        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                +      else
                +        if frame_type == :rst_stream && frame[:error] == :protocol_error
                +          # An endpoint can end a connection at any time. In particular, an
                +          # endpoint MAY choose to treat a stream error as a connection error.
                +
                +          goaway(:protocol_error)
                +        end
                +        #: @type var frame: connection_frame
                @@ -459,5 +469 @@
                -      if HEADERS_FRAME_TYPES.include?(frame[:type])
                -        encode_headers(frame) # HEADERS and PUSH_PROMISE may create more than one frame
                -      else
                -        emit(:frame, @framer.generate(frame))
                -      end
                +      emit(:frame, @framer.generate(frame))
                @@ -495,0 +502 @@
                +          # @type var frame: settings_frame
                @@ -497,0 +505 @@
                +          # @type var frame: window_update_frame
                @@ -501,0 +510 @@
                +          # @type var frame: goaway_frame
                @@ -508,0 +518 @@
                +          # @type var frame: altsvc_frame
                @@ -515 +525,2 @@
                -          return if @h2c_upgrade || !frame[:flags].empty?
                +          # @type var frame: origin_frame
                +          return if @h2c_upgrade || !frame[:flags].zero?
                @@ -520,2 +530,0 @@
                -        when :blocked
                -          emit(:blocked, frame)
                @@ -541 +550 @@
                -      if frame[:flags].include? :ack
                +      if frame[:flags].anybits?(ACK)
                @@ -544,2 +553 @@
                -        send(type: :ping, stream: 0,
                -             flags: [:ack], payload: frame[:payload])
                +        send(type: :ping, stream: 0, flags: ACK, payload: frame[:payload])
                @@ -608 +616 @@
                -      if frame[:flags].include?(:ack)
                +      if frame[:flags].anybits?(ACK)
                @@ -613 +620,0 @@
                -        validate_settings(@remote_role, frame[:payload])
                @@ -614,0 +622 @@
                +        validate_settings(@remote_role, settings)
                @@ -684 +692 @@
                -          send(type: :settings, stream: 0, payload: [], flags: [:ack])
                +          send(type: :settings, stream: 0, payload: EMPTY, flags: ACK)
                @@ -714 +722 @@
                -      payload = headers_frame[:payload]
                +      headers_payload = headers_frame[:payload]
                @@ -716 +724 @@
                -        payload = headers_frame[:payload] = @compressor.encode(payload) unless payload.is_a?(String)
                +        payload = headers_payload.is_a?(String) ? headers_payload : @compressor.encode(headers_payload)
                @@ -720,0 +729,3 @@
                +      #: @type var payload: String
                +      headers_frame[:payload] = payload
                +
                @@ -725 +736 @@
                -        emit(:frame, @framer.generate(headers_frame))
                +        encode(headers_frame)
                @@ -730 +741,2 @@
                -      headers_frame[:flags].delete(:end_headers)
                +      total = payload.bytesize
                +      headers_frame[:flags] ^= END_HEADERS
                @@ -732 +744,2 @@
                -      payload = payload.byteslice(max_frame_size..-1)
                +      # payload = payload.byteslice(max_frame_size..-1)
                +      offset = max_frame_size
                @@ -735 +748 @@
                -      emit(:frame, @framer.generate(headers_frame))
                +      encode(headers_frame)
                @@ -737,6 +750 @@
                -      loop do
                -        continuation_frame = headers_frame.merge(
                -          type: :continuation,
                -          flags: EMPTY,
                -          payload: payload.byteslice(0, max_frame_size)
                -        )
                +      stream_id = headers_frame[:stream]
                @@ -744 +752,3 @@
                -        payload = payload.byteslice(max_frame_size..-1)
                +      while offset < total
                +        chunk_end = offset + max_frame_size
                +        is_last = chunk_end >= total
                @@ -746,5 +756,6 @@
                -        if payload.nil? || payload.empty?
                -          continuation_frame[:flags] = [:end_headers]
                -          emit(:frame, @framer.generate(continuation_frame))
                -          break
                -        end
                +        continuation_frame = {
                +          type: :continuation,
                +          flags: is_last ? END_HEADERS : 0,
                +          stream: stream_id,
                +          payload: payload.byteslice(offset, max_frame_size)
                +        } #: continuation_frame
                @@ -752 +763,2 @@
                -        emit(:frame, @framer.generate(continuation_frame))
                +        encode(continuation_frame)
                +        offset = chunk_end
                @@ -779,2 +790,0 @@
                -        _, closed_since = @streams_recently_closed.first
                -
                @@ -783 +793,2 @@
                -        if closed_since && (now - closed_since) > 15
                +        if @oldest_stream_recently_closed && (now - @oldest_stream_recently_closed) > 15
                +          new_oldest = nil
                @@ -786,3 +797,9 @@
                -          @streams_recently_closed = @streams_recently_closed.drop_while do |_, since|
                -            (now - since) > 15
                -          end.to_h
                +          @streams_recently_closed.delete_if do |_, since|
                +            unless (now - since) > 15
                +              new_oldest ||= since
                +              break
                +            end
                +
                +            true
                +          end
                +          @oldest_stream_recently_closed = new_oldest
                @@ -791 +808 @@
                -        @streams_recently_closed[id] = Process.clock_gettime(Process::CLOCK_MONOTONIC)
                +        @streams_recently_closed[id] = now
        lib/http/2/extensions.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/extensions.rb	2026-06-17 02:34:59.305220066 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/extensions.rb	2026-06-17 02:34:59.309220147 +0000
                @@ -25,2 +25,3 @@
                -    def read_str(str, n)
                -      return "".b if n == 0
                +    if String.method_defined?(:bytesplice)
                +      def read_str(str, n)
                +        return "".b if n == 0
                @@ -28,4 +29,13 @@
                -      chunk = str.byteslice(0..(n - 1))
                -      remaining = str.byteslice(n..-1)
                -      remaining ? str.replace(remaining) : str.clear
                -      chunk
                +        chunk = str.byteslice(0, n)
                +        str.bytesplice(0, chunk.length, "")
                +        chunk
                +      end
                +    else
                +      def read_str(str, n)
                +        return "".b if n == 0
                +
                +        chunk = str.byteslice(0, n)
                +        remaining = str.byteslice(n, str.size - n)
                +        remaining ? str.replace(remaining) : str.clear
                +        chunk
                +      end
                @@ -36,4 +45,0 @@
                -    end
                -
                -    def shift_byte(str)
                -      read_str(str, 1).ord
        lib/http/2/flow_buffer.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/flow_buffer.rb	2026-06-17 02:34:59.305220066 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/flow_buffer.rb	2026-06-17 02:34:59.309220147 +0000
                @@ -73 +73 @@
                -          end_stream = frame[:flags].include?(:end_stream)
                +          end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -117,0 +118,2 @@
                +    include BufferUtils
                +
                @@ -143 +145 @@
                -      end_stream = frame[:flags].include?(:end_stream)
                +      end_stream = frame[:flags].anybits?(END_STREAM)
                @@ -151,2 +153 @@
                -        chunk   = frame.dup
                -        payload = frame[:payload]
                +        chunk = frame.dup
                @@ -157 +158 @@
                -        chunk[:payload] = payload.byteslice(0, window_size)
                +        chunk[:payload] = read_str(frame[:payload], window_size) # mutates frame[:payload]
                @@ -159 +159,0 @@
                -        frame[:payload] = payload.byteslice(window_size..-1)
                @@ -163 +163 @@
                -        chunk[:flags] -= [:end_stream] if end_stream
                +        chunk[:flags] ^= END_STREAM if end_stream
        lib/http/2/framer.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/framer.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/framer.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -3,0 +4,19 @@
                +  # Frame flags as defined by the spec (max 255 bits)
                +  # DATA:          ( X X COMPRESSED X PADDED X X END_STREAM )
                +  # HEADERS:       ( X X PRIORITY X PADDED END_HEADERS X END_STREAM )
                +  # PRIORITY:      ( X X X X X X X X )
                +  # RST_STREAM:    ( X X X X X X X X )
                +  # SETTINGS:      ( X X X X X X X ACK )
                +  # PUSH_PROMISE:  ( X X X X PADDED END_HEADERS X X )
                +  # PING:          ( X X X X X X X ACK )
                +  # GOAWAY:        ( X X X X X X X X )
                +  # WINDOW_UPDATE: ( X X X X X X X X )
                +  # CONTINUATION:  ( X X X X X END_HEADERS X X )
                +  # ALTSVC:        ( X X X X X X X X )
                +  # ORIGIN:        ( RESERVED4 X X RESERVED3 X RESERVED2 RESERVED X )
                +  END_STREAM = ACK = 0b0001 # 1
                +  RESERVED = 0b0010 # 2
                +  END_HEADERS = 0b0100 # 4
                +  PADDED = 0b1000 # 8
                +  PRIORITY = 0b0010_0000 # 32
                +
                @@ -43,33 +61,0 @@
                -    # Per frame flags as defined by the spec
                -    FRAME_FLAGS = {
                -      data: {
                -        end_stream: 0,
                -        padded: 3,
                -        compressed: 5
                -      },
                -      headers: {
                -        end_stream: 0,
                -        end_headers: 2,
                -        padded: 3,
                -        priority: 5
                -      },
                -      priority: {},
                -      rst_stream: {},
                -      settings: { ack: 0 },
                -      push_promise: {
                -        end_headers: 2,
                -        padded: 3
                -      },
                -      ping: { ack: 0 },
                -      goaway: {},
                -      window_update: {},
                -      continuation: { end_headers: 2 },
                -      altsvc: {},
                -      origin: {
                -        reserved: 1,
                -        reserved2: 2,
                -        reserved3: 4,
                -        reserved4: 8
                -      }
                -    }.each_value(&:freeze).freeze
                -
                @@ -86,17 +72,19 @@
                -    # Default error types as defined by the spec
                -    DEFINED_ERRORS = {
                -      no_error: 0,
                -      protocol_error: 1,
                -      internal_error: 2,
                -      flow_control_error: 3,
                -      settings_timeout: 4,
                -      stream_closed: 5,
                -      frame_size_error: 6,
                -      refused_stream: 7,
                -      cancel: 8,
                -      compression_error: 9,
                -      connect_error: 10,
                -      enhance_your_calm: 11,
                -      inadequate_security: 12,
                -      http_1_1_required: 13
                -    }.freeze
                +    DEFINED_SETTINGS_BY_ID = DEFINED_SETTINGS.invert.freeze
                +
                +    # Default error types as defined by the spec (the code is the array index)
                +    DEFINED_ERRORS = %i[
                +      no_error
                +      protocol_error
                +      internal_error
                +      flow_control_error
                +      settings_timeout
                +      stream_closed
                +      frame_size_error
                +      refused_stream
                +      cancel
                +      compression_error
                +      connect_error
                +      enhance_your_calm
                +      inadequate_security
                +      http_1_1_required
                +    ].freeze
                @@ -110,0 +99,2 @@
                +    PRIORITYPACK = (UINT32 + UINT8).freeze
                +    ALTSVCPACK = (UINT32 + UINT16).freeze
                @@ -114 +104 @@
                -    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :UINT32, :UINT16, :UINT8
                +    private_constant :RBIT, :RBYTE, :EBIT, :HEADERPACK, :PRIORITYPACK, :UINT32, :UINT16, :UINT8
                @@ -148,0 +139,4 @@
                +      flags = frame[:flags]
                +
                +      raise CompressionError, "Invalid frame flag (#{flags}) for #{type}" unless flags.between?(0, 255)
                +
                @@ -163,6 +157 @@
                -             frame[:flags].reduce(0) do |acc, f|
                -               position = FRAME_FLAGS[type][f]
                -               raise CompressionError, "Invalid frame flag (#{f}) for #{type}" unless position
                -
                -               acc | (1 << position)
                -             end,
                +             flags,
                @@ -187,3 +176 @@
                -        flags: FRAME_FLAGS[type].filter_map do |name, pos|
                -          name if flags.anybits?(1 << pos)
                -        end,
                +        flags: flags,
                @@ -201 +188 @@
                -      frame[:flags] ||= EMPTY
                +      frame[:flags] ||= 0
                @@ -204,0 +192 @@
                +        # @type var frame: data_frame | continuation_frame
                @@ -216 +204 @@
                -          frame[:flags] += [:priority] unless frame[:flags].include?(:priority)
                +          frame[:flags] |= PRIORITY
                @@ -219 +207 @@
                -        if frame[:flags].include?(:priority)
                +        if frame[:flags].anybits?(PRIORITY)
                @@ -222,2 +210,4 @@
                -          pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -          pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +          pack(
                +            [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +            PRIORITYPACK, buffer: bytes
                +          )
                @@ -237,2 +227,4 @@
                -        pack([(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT)], UINT32, buffer: bytes)
                -        pack([frame[:weight] - 1], UINT8, buffer: bytes)
                +        pack(
                +          [(frame[:exclusive] ? EBIT : 0) | (frame[:dependency] & RBIT), frame[:weight] - 1],
                +          PRIORITYPACK, buffer: bytes
                +        )
                @@ -251 +242,0 @@
                -        bytes = String.new("", encoding: Encoding::BINARY, capacity: length)
                @@ -253,5 +244,6 @@
                -        settings.each do |(k, v)|
                -          if k.is_a? Integer # rubocop:disable Style/GuardClause
                -            DEFINED_SETTINGS.value?(k) || next
                -          else
                -            k = DEFINED_SETTINGS[k]
                +        case settings
                +        when String
                +          length = settings.bytesize
                +          bytes = settings
                +        else
                +          bytes = String.new("", encoding: Encoding::BINARY, capacity: settings.size * 6)
                @@ -259 +251,12 @@
                -            raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +          settings.each do |(k, v)|
                +            if k.is_a? Integer # rubocop:disable Style/GuardClause
                +              DEFINED_SETTINGS.value?(k) || next
                +            else
                +              k = DEFINED_SETTINGS[k]
                +
                +              raise CompressionError, "Unknown settings ID for #{k}" if k.nil?
                +            end
                +
                +            pack([k], UINT16, buffer: bytes)
                +            pack([v], UINT32, buffer: bytes)
                +            length += 6
                @@ -261,4 +263,0 @@
                -
                -          pack([k], UINT16, buffer: bytes)
                -          pack([v], UINT32, buffer: bytes)
                -          length += 6
                @@ -298 +297 @@
                -        pack([frame[:max_age], frame[:port]], UINT32 + UINT16, buffer: bytes)
                +        pack([frame[:max_age], frame[:port]], ALTSVCPACK, buffer: bytes)
                @@ -357 +356 @@
                -        frame[:flags] += [:padded]
                +        frame[:flags] |= PADDED
                @@ -378,3 +377,3 @@
                -      type = frame[:type]
                -      length = frame[:length]
                -      flags = frame[:flags]
                +      type = frame[:type] #: Symbol
                +      length = frame[:length] #: Integer
                +      flags = frame[:flags] #: Integer
                @@ -397 +396 @@
                -        padded = flags.include?(:padded)
                +        padded = flags.anybits?(PADDED)
                @@ -400 +398,0 @@
                -          frame[:padding] = padlen + 1
                @@ -402,0 +401,2 @@
                +          frame[:padding] = padlen + 1
                +
                @@ -405 +405 @@
                -          flags.delete(:padded)
                +          frame[:flags] ^= PADDED
                @@ -413 +413 @@
                -        if flags.include?(:priority)
                +        if flags.anybits?(PRIORITY)
                @@ -417 +417 @@
                -          weight = payload.byteslice(0, 1).ord + 1
                +          weight = payload.getbyte(0) + 1
                @@ -428 +428 @@
                -        weight = payload.byteslice(0, 1).ord + 1
                +        weight = payload.getbyte(0) + 1
                @@ -439 +438,0 @@
                -        frame[:payload] = []
                @@ -444 +443 @@
                -        (frame[:length] / 6).times do
                +        frame[:payload] = (frame[:length] / 6).times.filter_map do
                @@ -450,2 +449,3 @@
                -          name, = DEFINED_SETTINGS.find { |_name, v| v == id }
                -          frame[:payload] << [name, val] if name
                +          if (name = DEFINED_SETTINGS_BY_ID[id])
                +            [name, val]
                +          end
                @@ -467 +467 @@
                -        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(UINT32 + UINT16)
                +        frame[:max_age], frame[:port] = read_str(payload, 6).unpack(ALTSVCPACK)
                @@ -469 +469 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -473 +473 @@
                -        len = payload.byteslice(0, 1).ord
                +        len = payload.getbyte(0)
                @@ -498 +498 @@
                -        error = DEFINED_ERRORS[error]
                +        error = DEFINED_ERRORS.index(error)
                @@ -507 +507 @@
                -      DEFINED_ERRORS.key(error) || error
                +      DEFINED_ERRORS.fetch(error, error)
        lib/http/2/header/compressor.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/header/compressor.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/header/compressor.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -85,0 +86,2 @@
                +            integer(huffman.bytesize, 7, buffer: buffer)
                +            buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
                @@ -87 +89 @@
                -            set_huffman_size(buffer, huffman_offset)
                +            buffer
                @@ -122 +124 @@
                -        fb = buffer[offset].ord | rep[:pattern]
                +        fb = buffer.getbyte(offset) | rep[:pattern]
                @@ -149,0 +152 @@
                +        buffer << "\x00".b
                @@ -151 +154,9 @@
                -        set_huffman_size(buffer, huffman_offset)
                +        size = buffer.bytesize - huffman_offset - 1
                +
                +        if size < 127
                +          buffer.setbyte(huffman_offset, 0x80 | size)
                +        else
                +          buffer.slice!(huffman_offset, 1)
                +          set_huffman_size(buffer, huffman_offset)
                +        end
                +        buffer
                @@ -168 +179 @@
                -        buffer.setbyte(huffman_offset, buffer[huffman_offset].ord | 0x80)
                +        buffer.setbyte(huffman_offset, buffer.getbyte(huffman_offset) | 0x80)
        lib/http/2/header/decompressor.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/header/decompressor.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/header/decompressor.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -36 +36,7 @@
                -        i = n.zero? ? 0 : (shift_byte(buf) & limit)
                +        if n.zero?
                +          i = 0
                +          consumed = 0
                +        else
                +          i = buf.getbyte(0) & limit
                +          consumed = 1
                +        end
                @@ -38 +43,0 @@
                -        m = 0
                @@ -40,5 +45,2 @@
                -          offset = 0
                -
                -          buf.each_byte.with_index do |byte, idx|
                -            offset = idx
                -            # while (byte = shift_byte(buf))
                +          m = 0
                +          while (byte = buf.getbyte(consumed))
                @@ -47 +49 @@
                -
                +            consumed += 1
                @@ -50,2 +51,0 @@
                -
                -          read_str(buf, offset + 1)
                @@ -53,0 +54 @@
                +        read_str(buf, consumed)
        lib/http/2/header/encoding_context.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/header/encoding_context.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -120,0 +121,2 @@
                +        @table_by_field = Hash.new { |hs, k| hs[k] = [] }
                +        @unshifts = 0
                @@ -131,0 +134,2 @@
                +        tbf = @table_by_field.transform_values(&:dup)
                +        unshifts = @unshifts
                @@ -134,0 +139,2 @@
                +          @table_by_field = tbf
                +          @unshifts = unshifts
                @@ -215,0 +222,2 @@
                +            @unshifts += 1
                +            @table_by_field[name].unshift([value, @unshifts])
                @@ -282,2 +290 @@
                -          @table.each_with_index do |(hfield, hvalue), i|
                -            next unless field == hfield
                +          field_entries = @table_by_field[field]
                @@ -284,0 +292,3 @@
                +          field_entries&.each do |hvalue, unshift_id|
                +            abs_index = (@unshifts - unshift_id) + STATIC_TABLE_SIZE
                +            name_only ||= abs_index
                @@ -286 +296 @@
                -              exact = i + STATIC_TABLE_SIZE
                +              exact = abs_index
                @@ -288,2 +297,0 @@
                -            else
                -              name_only ||= i + STATIC_TABLE_SIZE
                @@ -320 +327,0 @@
                -
                @@ -322,0 +330,5 @@
                +
                +          field_arr = @table_by_field[name]
                +          field_arr.pop
                +          @table_by_field.delete(name) if field_arr.empty?
                +
        lib/http/2/header/huffman.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/header/huffman.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/header/huffman.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -22,0 +23,2 @@
                +      EOS_PADDING = (0..7).map { |n| ("1" * n).b.freeze }.freeze
                +
                @@ -32 +34 @@
                -        append_str(bitstring, "1" * ((8 - bitstring.size) % 8))
                +        append_str(bitstring, EOS_PADDING[(8 - bitstring.size) % 8])
                @@ -57 +59 @@
                -            append_str(emit, first.chr) if first
                +            emit << first if first
                @@ -63 +65 @@
                -        emit.force_encoding(Encoding::BINARY)
                +        emit
                @@ -328 +330 @@
                -      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1] }.each(&:freeze).freeze
                +      ENCODE_TABLE = CODES.map { |c, l| [c].pack("N").unpack1("B*")[-l..-1].b.freeze }.freeze
        lib/http/2/server.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/server.rb	2026-06-17 02:34:59.306220087 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/server.rb	2026-06-17 02:34:59.310220168 +0000
                @@ -81,12 +81,6 @@
                -      buf = "".b
                -      append_str(buf, Base64.urlsafe_decode64(settings.to_s))
                -      @framer.common_header(
                -        {
                -          length: buf.bytesize,
                -          type: :settings,
                -          stream: 0,
                -          flags: []
                -        },
                -        buffer: buf
                -      )
                -      receive(buf)
                +      receive(@framer.generate(
                +                type: :settings,
                +                stream: 0,
                +                flags: 0,
                +                payload: Base64.urlsafe_decode64(settings.to_s)
                +              ))
                @@ -100 +94 @@
                -        flags: [:end_headers],
                +        flags: END_HEADERS,
                @@ -109 +103 @@
                -        headers_frame[:flags] << [:end_stream]
                +        headers_frame[:flags] |= END_HEADERS
                @@ -113 +107 @@
                -        stream << { type: :data, stream: 1, payload: body, flags: [:end_stream] }
                +        stream << { type: :data, stream: 1, payload: body, flags: END_STREAM }
                @@ -138 +132 @@
                -      return unless frame[:flags].include?(:ack) && !@origins_sent
                +      return unless frame[:flags].anybits?(ACK) && !@origins_sent
                @@ -151 +145 @@
                -    # @param flags [Array[Symbol]]
                +    # @param flags Integer
                @@ -160 +154 @@
                -        payload: headers.to_a
                +        payload: headers
        lib/http/2/stream.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/stream.rb	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/stream.rb	2026-06-17 02:34:59.311220188 +0000
                @@ -117 +117,2 @@
                -      case frame[:type]
                +      frame_type = frame[:type] #: Symbol
                +      case frame_type
                @@ -118,0 +120 @@
                +        # @type var frame: data_frame
                @@ -131,0 +134 @@
                +        # @type var frame: headers_frame
                @@ -153,0 +157 @@
                +        # @type var frame: priority_frame
                @@ -155,0 +160 @@
                +        # @type var frame: window_update_frame
                @@ -157,0 +163 @@
                +        # @type var frame: origin_frame
                @@ -162,3 +168 @@
                -        emit(frame[:type], frame) if !frame[:origin] || frame[:origin].empty?
                -      when :blocked
                -        emit(frame[:type], frame)
                +        emit(frame_type, frame) if !frame[:origin] || frame[:origin].empty?
                @@ -201,0 +206 @@
                +        # @type var frame: data_frame
                @@ -204,0 +210 @@
                +        # @type var frame: window_update_frame
                @@ -206,0 +213 @@
                +        # @type var frame: priority_frame
                @@ -222,3 +229,2 @@
                -      flags = []
                -      flags << :end_headers if end_headers
                -      flags << :end_stream  if end_stream || @_method == "HEAD"
                +      flags = end_headers ? END_HEADERS : 0
                +      flags |= END_STREAM  if end_stream || @_method == "HEAD"
                @@ -232 +238 @@
                -      flags = end_headers ? [:end_headers] : []
                +      flags = end_headers ? END_HEADERS : 0
                @@ -257 +263 @@
                -          send(type: :data, flags: [], payload: chunk)
                +          send(type: :data, flags: 0, payload: chunk)
                @@ -261,2 +267,2 @@
                -      flags = []
                -      flags << :end_stream if end_stream
                +      flags = 0
                +      flags |= END_STREAM if end_stream
                @@ -666 +672,2 @@
                -        frame[:flags] && frame[:flags].include?(:end_stream)
                +        # @type var frame: data_frame | headers_frame | continuation_frame
                +        frame[:flags] && frame[:flags].anybits?(END_STREAM)
        lib/http/2/version.rb
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/lib/http/2/version.rb	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/lib/http/2/version.rb	2026-06-17 02:34:59.311220188 +0000
                @@ -4 +4 @@
                -  VERSION = "1.1.3"
                +  VERSION = "1.2.0"
        sig/2.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/2.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/2.rbs	2026-06-17 02:34:59.311220188 +0000
                @@ -38,0 +39,8 @@
                +  # Frame flags
                +  END_STREAM: Integer
                +  ACK: Integer
                +  RESERVED: Integer
                +  END_HEADERS: Integer
                +  PADDED: Integer
                +  PRIORITY: Integer
                +
                @@ -42 +50,3 @@
                -  type frame_control_flags = Array[:end_headers | :end_stream]
                +  type frame_control_flags = Integer
                +
                +  type common_frame = { stream: Integer, flags: frame_control_flags, ?length: Integer, ?ignore: bool }
                @@ -44 +54 @@
                -  type common_frame = { stream: Integer }
                +  type connection_frame = settings_frame | ping_frame | goaway_frame | window_update_frame | altsvc_frame | origin_frame
                @@ -47,2 +57,2 @@
                -  type headers_frame = common_frame & {
                -    type: :headers, flags: frame_control_flags, payload: Enumerable[header_pair] | String,
                +  type headers_frame_props = {
                +    type: :headers, payload: Enumerable[header_pair] | String,
                @@ -50,0 +61,5 @@
                +  type headers_frame = common_frame & headers_frame_props
                +
                +  type continuation_frame_props = headers_frame_props | { type: :continuation }
                +
                +  type continuation_frame = common_frame & continuation_frame_props
                @@ -53 +68,3 @@
                -  type data_frame = { type: :data, flags: frame_control_flags, ?length: Integer, payload: String, ?padding: Integer }
                +  type data_frame_props = { type: :data, ?length: Integer, payload: String, ?padding: Integer }
                +
                +  type data_frame = common_frame & data_frame_props
                @@ -56 +73,3 @@
                -  type push_promise_frame = { type: :push_promise, promise_stream: Integer, flags: frame_control_flags, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair], ?padding: Integer }
                +  type push_promise_frame_props = { promise_stream: Integer, ?length: Integer, ?method: Symbol, ?trailer: Array[String], ?content_length: Integer, payload: Enumerable[header_pair] | String, ?padding: Integer }
                +
                +  type push_promise_frame = common_frame & push_promise_frame_props
                @@ -59 +78,3 @@
                -  type settings_frame = { type: :settings, payload: Array[[Symbol | Integer, Integer]] }
                +  type settings_frame_props = { type: :settings, payload: (Enumerable[[Symbol | Integer, Integer]] | String) }
                +
                +  type settings_frame = common_frame & settings_frame_props
                @@ -62 +83,3 @@
                -  type window_update_frame = { type: :window_update, increment: Integer }
                +  type window_update_frame_props = { type: :window_update, increment: Integer }
                +
                +  type window_update_frame = common_frame & window_update_frame_props
                @@ -65 +88,5 @@
                -  type priority_frame = { dependency: Integer, exclusive: bool, weight: Integer }
                +  type priority_frame_inner_props = { dependency: Integer, exclusive: bool, weight: Integer }
                +
                +  type priority_frame_props = { type: :priority } & priority_frame_inner_props
                +
                +  type priority_frame = common_frame & priority_frame_props
                @@ -68 +95,3 @@
                -  type altsvc_frame = { type: :altsvc, max_age: Integer, port: Integer, proto: "String", host: String }
                +  type altsvc_frame_props = { type: :altsvc, max_age: Integer, port: Integer, proto: String, host: String }
                +
                +  type altsvc_frame = common_frame & altsvc_frame_props
                @@ -71 +100,3 @@
                -  type origin_frame = { type: :origin, origin: Array[String] }
                +  type origin_frame_props = { type: :origin, payload: Array[String] }
                +
                +  type origin_frame = common_frame & origin_frame_props
                @@ -74 +105,3 @@
                -  type ping_frame = { type: :ping, payload: String, length: Integer }
                +  type ping_frame_props = { type: :ping, payload: String }
                +
                +  type ping_frame = common_frame & ping_frame_props
                @@ -77 +110,3 @@
                -  type goaway_frame = { type: :goaway, last_stream: Integer, error: Symbol? }
                +  type goaway_frame_props = { type: :goaway, last_stream: Integer, error: (Symbol | Integer)? }
                +
                +  type goaway_frame = common_frame & goaway_frame_props
                @@ -79 +114,6 @@
                -  # type frame = common_frame & (headers_frame | data_frame | push_promise_frame |
                +  # # RST_STREAM
                +  type rst_stream_frame_props = { type: :rst_stream, error: (Symbol | Integer)? }
                +
                +  type rst_stream_frame = common_frame & rst_stream_frame_props
                +
                +  # type frame = headers_frame | continuation_frame | push_promise_frame | data_frame |
                @@ -81 +121,8 @@
                -  #              origin_frame | ping_frame | goaway_frame)
                +  #              origin_frame | ping_frame | goaway_frame | rst_stream_frame
                +
                +  # type connection_frame_props = rst_stream_frame_props | ping_frame_props | goaway_frame_props
                +  #                             | window_update_frame_props | settings_frame_props
                +
                +  # type stream_frame_props = headers_frame_props | continuation_frame_props | push_promise_frame_props
                +  #                         | data_frame_props  | rst_stream_frame_props | priority_frame_props
                +  #                         | window_update_frame_props | origin_frame_props | altsvc_frame_props
                @@ -111,0 +159,2 @@
                +  type connection_frame_props = Hash[frame_key, frame_value]
                +  type stream_frame_props = Hash[frame_key, frame_value]
        sig/connection.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/connection.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/connection.rbs	2026-06-17 02:34:59.311220188 +0000
                @@ -35,0 +36 @@
                +    @oldest_stream_recently_closed: Numeric
                @@ -52,0 +54 @@
                +    @continuation_size: Integer
                @@ -71 +73 @@
                -    def receive: (string data) -> void
                +    def receive: (String data) -> void
                @@ -78 +80 @@
                -    def send: (frame frame) -> void
                +    def send: (connection_frame_props | stream_frame_props frame) -> void
                @@ -84 +86 @@
                -    def connection_management: (frame) -> void
                +    def connection_management: (connection_frame frame) -> void
                @@ -90 +92 @@
                -    def connection_settings: (frame) -> void
                +    def connection_settings: (settings_frame) -> void
                @@ -92 +94 @@
                -    def decode_headers: (frame) -> void
                +    def decode_headers: (headers_frame | push_promise_frame) -> void
                @@ -94 +96 @@
                -    def encode_headers: (frame headers_frame) -> void
                +    def encode_headers: (headers_frame | push_promise_frame) -> void
                @@ -100 +102 @@
                -    def verify_pseudo_headers: (frame) -> void
                +    def verify_pseudo_headers: (headers_frame | push_promise_frame) -> void
                @@ -102 +104 @@
                -    def _verify_pseudo_headers: (frame, Array[String]) -> void
                +    def _verify_pseudo_headers: (headers_frame | push_promise_frame, Array[String]) -> void
                @@ -106 +108 @@
                -end
                \ No newline at end of file
                +end
        sig/flow_buffer.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/flow_buffer.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/flow_buffer.rbs	2026-06-17 02:34:59.311220188 +0000
                @@ -17 +17 @@
                -    def send_data: (?data_frame? frame, ?bool encode) -> void
                +    def send_data: (?data_frame_props? frame, ?bool encode) -> void
                @@ -19 +19 @@
                -    def send_frame: (data_frame frame, bool encode) -> void
                +    def send_frame: (data_frame_props frame, bool encode) -> void
        sig/frame_buffer.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/frame_buffer.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/frame_buffer.rbs	2026-06-17 02:34:59.311220188 +0000
                @@ -2,0 +3,2 @@
                +    include BufferUtils
                +
                @@ -9 +11 @@
                -    def <<: (data_frame frame) -> void
                +    def <<: (data_frame_props frame) -> void
                @@ -13 +15 @@
                -    def retrieve: (Integer) -> data_frame?
                +    def retrieve: (Integer) -> data_frame_props?
        sig/framer.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/framer.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/framer.rbs	2026-06-17 02:34:59.311220188 +0000
                @@ -23 +23,3 @@
                -    DEFINED_ERRORS: Hash[Symbol, Integer]
                +    DEFINED_SETTINGS_BY_ID: Hash[Integer, Symbol]
                +
                +    DEFINED_ERRORS: Array[Symbol]
                @@ -31,0 +34,2 @@
                +    PRIORITYPACK: String
                +    ALTSVCPACK: String
                @@ -44 +48 @@
                -    def read_common_header: (String buf) -> frame
                +    def read_common_header: (String buf) -> (common_frame | { length: Integer })
                @@ -50 +54 @@
                -    def parse: (String) -> frame?
                +    def parse: (String) -> (frame | { length: Integer })?
                @@ -56 +60 @@
                -    def pack_error: (Integer | Symbol error, buffer: String) -> String
                +    def pack_error: (Symbol | Integer error, buffer: String) -> String
        sig/header/compressor.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/header/compressor.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/header/compressor.rbs	2026-06-17 02:34:59.312220208 +0000
                @@ -4,0 +5 @@
                +      include BufferUtils
        sig/header/encoding_context.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/header/encoding_context.rbs	2026-06-17 02:34:59.307220107 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/header/encoding_context.rbs	2026-06-17 02:34:59.312220208 +0000
                @@ -24,0 +25,4 @@
                +      @table_by_field: Hash[string, Array[[string, Integer]]]
                +
                +      @unshifts: Integer
                +
        sig/header/huffman.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/header/huffman.rbs	2026-06-17 02:34:59.308220127 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/header/huffman.rbs	2026-06-17 02:34:59.312220208 +0000
                @@ -11,0 +12,2 @@
                +      EOS_PADDING: Array[String]
                +
        sig/server.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/server.rbs	2026-06-17 02:34:59.308220127 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/server.rbs	2026-06-17 02:34:59.312220208 +0000
                @@ -10 +10 @@
                -    def promise: (Stream parent, Enumerable[header_pair] headers, Array[Symbol] flags) { (Stream) -> void } -> void
                +    def promise: (Stream parent, Enumerable[header_pair] headers, frame_control_flags flags) { (Stream) -> void } -> void
        sig/stream.rbs
                --- /tmp/d20260617-505-eixn53/http-2-1.1.3/sig/stream.rbs	2026-06-17 02:34:59.308220127 +0000
                +++ /tmp/d20260617-505-eixn53/http-2-1.2.0/sig/stream.rbs	2026-06-17 02:34:59.312220208 +0000
                @@ -40 +40 @@
                -    def send: (frame frame) -> void
                +    def send: (stream_frame_props frame) -> void
                @@ -73 +73 @@
                -    def transition: (frame, bool sending) -> void
                +    def transition: (stream_frame_props frame, bool sending) -> void
                @@ -83 +83 @@
                -    def process_priority: (priority_frame frame) -> void
                +    def process_priority: (priority_frame_inner_props frame) -> void
                @@ -85 +85 @@
                -    def end_stream?: (frame frame) -> boolish
                +    def end_stream?: (stream_frame_props frame) -> boolish
                @@ -87,2 +87 @@
                -    def stream_error: (Symbol error, ?msg: String?) -> void
                -                    | () -> void
                +    def stream_error: (?Symbol error, ?msg: String?) -> void
                @@ -92 +91 @@
                -    def manage_state: (frame) { () -> void } -> void
                +    def manage_state: (stream_frame_props frame) { () -> void } -> void
                @@ -94 +93 @@
                -end
                \ No newline at end of file
                +end

@github-actions

Copy link
Copy Markdown
Contributor

gem compare httpx 1.7.8 1.8.0

Compared versions: ["1.7.8", "1.8.0"]
  DIFFERENT version:
    1.7.8: 1.7.8
    1.8.0: 1.8.0
  DIFFERENT files:
    1.7.8->1.8.0:
      * Deleted:
            lib/httpx/plugins/response_cache/file_store.rb
            lib/httpx/plugins/response_cache/store.rb
            sig/plugins/response_cache/file_store.rbs
            sig/plugins/response_cache/store.rbs
      * Added:
            doc/release_notes/1_8_0.md +100/-0
            lib/httpx/plugins/cache.rb +221/-0
            lib/httpx/plugins/cache/file_store.rb +141/-0
            lib/httpx/plugins/cache/store.rb +33/-0
            lib/httpx/plugins/ntlm_v2_auth.rb +92/-0
            lib/httpx/plugins/server_sent_events.rb +158/-0
            lib/httpx/resolver/cache/file.rb +56/-0
            sig/plugins/cache.rbs +69/-0
            sig/plugins/cache/file_store.rbs +21/-0
            sig/plugins/cache/store.rbs +13/-0
            sig/plugins/ntlm_v2_auth.rbs +36/-0
            sig/plugins/server_sent_events.rbs +45/-0
            sig/resolver/cache/file.rbs +13/-0
      * Changed:
            lib/httpx/adapters/datadog.rb +3/-1
            lib/httpx/connection.rb +76/-7
            lib/httpx/connection/http1.rb +10/-1
            lib/httpx/connection/http2.rb +37/-4
            lib/httpx/errors.rb +8/-1
            lib/httpx/io/tcp.rb +11/-1
            lib/httpx/options.rb +16/-4
            lib/httpx/parser/http1.rb +8/-2
            lib/httpx/plugins/auth.rb +52/-4
            lib/httpx/plugins/fiber_concurrency.rb +50/-3
            lib/httpx/plugins/oauth.rb +66/-14
            lib/httpx/plugins/proxy.rb +5/-0
            lib/httpx/plugins/response_cache.rb +26/-105
            lib/httpx/plugins/retries.rb +7/-5
            lib/httpx/plugins/ssrf_filter.rb +16/-1
            lib/httpx/plugins/stream.rb +7/-3
            lib/httpx/plugins/tracing.rb +15/-4
            lib/httpx/request.rb +18/-1
            lib/httpx/resolver/native.rb +14/-3
            lib/httpx/response.rb +9/-1
            lib/httpx/response/body.rb +4/-2
            lib/httpx/selector.rb +7/-1
            lib/httpx/version.rb +1/-1
            sig/chainable.rbs +3/-0
            sig/connection.rbs +11/-8
            sig/connection/http1.rbs +1/-1
            sig/connection/http2.rbs +1/-1
            sig/errors.rbs +9/-3
            sig/httpx.rbs +2/-0
            sig/io/tcp.rbs +2/-0
            sig/loggable.rbs +4/-0
            sig/options.rbs +25/-12
            sig/parser/http1.rbs +3/-1
            sig/plugins/auth/ntlm.rbs +1/-1
            sig/plugins/fiber_concurrency.rbs +4/-0
            sig/plugins/response_cache.rbs +13/-38
            sig/plugins/retries.rbs +5/-5
            sig/plugins/ssrf_filter.rbs +5/-1
            sig/plugins/stream.rbs +1/-1
            sig/plugins/stream_bidi.rbs +0/-2
            sig/plugins/webdav.rbs +1/-1
            sig/pool.rbs +2/-2
            sig/request.rbs +7/-3
            sig/resolver.rbs +3/-0
            sig/resolver/entry.rbs +1/-1
            sig/resolver/https.rbs +3/-3
            sig/resolver/multi.rbs +1/-1
            sig/resolver/native.rbs +5/-5
            sig/resolver/resolver.rbs +1/-3
            sig/resolver/system.rbs +2/-2
            sig/response.rbs +3/-0
            sig/selector.rbs +11/-8
            sig/timers.rbs +5/-5
            sig/transcoder.rbs +2/-0
            sig/transcoder/body.rbs +1/-1
            sig/transcoder/gzip.rbs +3/-2
            sig/transcoder/multipart.rbs +4/-1
            sig/transcoder/utils/deflater.rbs +2/-0
            sig/utils.rbs +1/-1
  DIFFERENT extra_rdoc_files:
    1.7.8->1.8.0:
      * Added:
            doc/release_notes/1_8_0.md +100/-0
  DIFFERENT runtime dependencies:
    1.7.8->1.8.0:
      * Updated:
            http-2 from: [">= 1.1.3"] to: [">= 1.2.0"]

@github-actions

Copy link
Copy Markdown
Contributor

gem compare --diff httpx 1.7.8 1.8.0

Diff too large (125710 chars)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies ruby Pull requests that update Ruby code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants