Imagining a client connecting to a server and taking aside server push, HTTP/2 specifies that it is possible for the client to theoretically send as many DATA frames as possible until EOS (End Of Stream) and the same is true for the server response. This interaction is semiduplex-like and is illustrated at https://datatracker.ietf.org/doc/html/rfc9113#section-5.1.
AFAICT after the initial handshake specified at RFC8441, WebSocket data is transferred over HTTP/2 DATA frames but the full-duplex nature of WebSocket makes the definition of stream states impracticable.
https://datatracker.ietf.org/doc/html/rfc8441#section-5.1 shows an example but doesn't detail data exchange. Perhaps I am missing something? Do libraries implementing RFC8441 ignore stream states?
It's not clear what you exactly mean by "semiduplex", but HTTP/2 is "full duplex", as in "the communication in both directions is simultaneous".
Given this, WebSocket (also full duplex), maps perfectly over HTTP/2, as HTTP/2 DATA frames wrap WebSocket frames.
The example you report in RFC 8441 (https://datatracker.ietf.org/doc/html/rfc8441#section-5.1) shows the interaction; it has been formatted so that it shows first a DATA frame that goes from client to server, then a DATA frame that goes from server to client, but the two can be simultaneous.
The example also shows only 2 DATA frames sent by the client, but the client (and the server) can send a large amount of DATA frames, all of them without the "end-stream" flag.
Only when the WebSocket communication is closed (by the application or due to errors or timeouts), then a last DATA frame with "end-stream=true" flag will be sent, containing the WebSocket CLOSE frame.
If you have a 2 cores client system, you can have 1 thread on core0 reading DATA frames from the server, and 1 thread on core1 writing DATA frames to the server, happening in parallel (simultaneously).
HTTP/2 stream states are irrelevant, because the WebSocket communication happens when the HTTP/2 stream is in state "open", until it is closed by the WebSocket layer closing the communication.