saghul / txiki.js

A tiny JavaScript runtime
MIT License
2.37k stars 157 forks source link

Error: invalid argument at Connection #523

Open guest271314 opened 2 weeks ago

guest271314 commented 2 weeks ago

I'm writing a JavaScript runtime agnostic HTTP and WebSocket server.

txiki.js Connection throws

Error: invalid argument
    at pull (:0:0)
    at apply (native)
    at call (native)
    at x (:0:0)
    at C (:0:0)
    at <anonymous> (:0:0)
    at <anonymous> (:0:0)
    at Ht (:0:0)
    at [[[PullSteps]]] (:0:0)
    at Rr (:0:0)

Trace: 
    at <anonymous> (txikijs-ws-server.js:86:3)

when sending WebSocket close frame to the client.

I don't know where or why the error is thrown.

Essentially the same code does not throw when Direct Sockets TCPServerSocker is used as a WebSocket server in an Isolated Web App in Chromium and Chrome browsers.

Steps to reproduce:

Download attached files to the same directory, run the following

 tjs run txikijs-ws-server.js

For client run

deno run -A --unstable websocketstream.js

or run the same code in Chromium or Chrome browser which supports WebSocketStream.

Relevant code in txikijs-ws-server.js L36-52

if (!/(GET|POST|HEAD|OPTIONS|QUERY)/i.test(request)) {
  // console.log({ data });
  const response = parseWebSocketFrame(data);
  console.log({
    response
  });
  if (response === null) {
    // https://stackoverflow.com/a/17177146
    const closeFrame = new Uint8Array([0x88, 0x00]); // 136, 0
    console.log(closeFrame);
    await writer.ready;
    await writer.write(closeFrame);
    await writer.close();
    await writer.closed.then(() => console.log("writer closed"));
    return;
    // return abortable.abort("WebSocket closed by client, aborted in server");
  } else {
    await writer.write(new Uint8Array(response));
  }

and the end of writable side of Connecion piped to a WritableStream() where the error is read L73-88.

        close() {
          console.log("Stream closed");
        },
        abort(reason) {
          console.log(reason);
        },
      })
    , {highWaterMark: Infinity})
    .then(() => console.log("Stream aborted")).catch((e) => {
      throw e;
    });
} catch (e) {
  //console.log(e.stack);
  console.trace();
  listener.close();
}

Tested with deno version 1.43.3 (release, x86_64-unknown-linux-gnu) and Chromium Version 126.0.6477.0 (Developer Build) (64-bit).

txiki.js version: v23.12.0.

Potentially related: https://github.com/saghul/txiki.js/issues/450.

guest271314 commented 2 weeks ago

tjs-ws-streams-throw.zip

saghul commented 1 week ago

Can you try making a debug from latest master? The backtrace will be more meaningfull. You can do that with make debug

guest271314 commented 1 week ago

I don't see much difference in the output in terminal with a debug build

tjs run txikijs-ws-server.js
Listening on family: 2, ip: 0.0.0.0, port: 8080
{ family: 2, ip: '127.0.0.1', port: 8080 } { family: 2, ip: '127.0.0.1', port: 59444 }
{ response: {} }
[connection close frame]

Close frame null
{ response: null }
{ '0': 136, '1': 0 }
writer closed
Error: invalid argument
    at pull (�W$:0:0)
    at apply (native)
    at call (native)
    at x (�W$:0:0)
    at C (�W$:0:0)
    at <anonymous> (�W$:0:0)
    at <anonymous> (�W$:0:0)
    at Ht (�W$:0:0)
    at [[[PullSteps]]] (�W$:0:0)
    at Rr (�W$:0:0)

Trace: 
    at <anonymous> (txikijs-ws-server.js:86:3)