Bug: Firefox duplicating large websocket messages when server takes time to receive the messages
Status: RESOLVED
Priority: --
Resolution: DUPLICATE
Created: 2020-10-26 20:25:16+00:00
Resolved: 2020-10-27 15:18:26+00:00

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0

Steps to reproduce:

What I'm trying to do:

- I have a JavaScript client (in browser) that sends 10 1mb arrays of data (this would normally be binary data from files but I tried to simplify as much as possible) to a websocket server

- The client sends all of the data as fast as it can in a normal `for` loop

- The server reads from the websocket connection, reading the data into memory and then does some processing on that data before moving on (in the go example, `time.Sleep` is used to represent "processing data", the Python version is already quite slow so I didn't add a sleep)

To reproduce this you can use the code in this gist:
https://gist.github.com/psidex/cef1bf2290096816e0642d0e9da95a2f

That includes a server written in golang as well as python, they do the same thing; receive from the websocket and print the first 10 items in the received array

Just run one of the servers and then run the JavaScript in Firefox's console (depending on what site you are on when using the console, some pages don't allow the websocket connection, I found Google does though)


Actual results:

What actually happens:

Some of the data is read by the server, and then the server reads the same data again from the websocket, instead of new data.

In the below server log, you can see that it works fine until the data array containing "5"s gets received 4 times in a row, and then jumps to receiving the "8"'s:

```
Serving at http://127.0.0.1:8080
[0 0 0 0 0 0 0 0 0 0]
[1 1 1 1 1 1 1 1 1 1]
[2 2 2 2 2 2 2 2 2 2]
[3 3 3 3 3 3 3 3 3 3]
[4 4 4 4 4 4 4 4 4 4]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[5 5 5 5 5 5 5 5 5 5]
[8 8 8 8 8 8 8 8 8 8]
```

This only happens if the JavaScript is run in Firefox (tested on v82.0 64-bit), **the code works as intended if I run it in Chrome**.

I have also tested in Firefox Developer edition (83.0b4) and the same bug happens.

If I inspect the traffic using Firefox's debugging tools, it says that it is sending out the correct data (see attached image (I changed the numbers for that screenshot to `65 + i` so that its more readable in the debugging tools)), but the servers are not receiving what firefox says it's sending.


Expected results:

What should happen:

All of the data from the javascript client should end up on the server, with the
server printing out a received array for each number, here's an example server log which shows the first 10 bytes of each message received:

```
[0 0 0 0 0 0 0 0 0 0]
[1 1 1 1 1 1 1 1 1 1]
[2 2 2 2 2 2 2 2 2 2]
[3 3 3 3 3 3 3 3 3 3]
[4 4 4 4 4 4 4 4 4 4]
[5 5 5 5 5 5 5 5 5 5]
[6 6 6 6 6 6 6 6 6 6]
[7 7 7 7 7 7 7 7 7 7]
[8 8 8 8 8 8 8 8 8 8]
[9 9 9 9 9 9 9 9 9 9]
```

This is exactly what I want, each different array was received only once.

There are a few weird things I have found that stop the duplication from happening:

If the `time.Sleep` call is commented out in the go server code, the duplication does not happen.

The python version is inherently slow to process the requests without sleeping (hence no call to sleep to represent processing data), so there is no way to test on the Python server if receiving the websocket messages faster stops the duplication.

This leads me to believe that the issue may be timing related?

The duplication also does not happen if, in the JavaScript, the 2 `1024 * 1024`
statements are replaced with a variable that is pre-calculated, for example

```javascript
const ws = // websocket
const dataSize = 1024 * 1024;

// rest of code up to:

        const data = new Uint8Array(dataSize);
        for (let j = 0; j < dataSize; j++) {
```

I'm pretty confident that this is a bug within Firefox since the issue is reproducible with 2 different servers written in completely different languages, as well as the face that everything works as normal if I use Chrome instead of Firefox.