ProseMirror / prosemirror-tables

Table module for ProseMirror
https://prosemirror-tables.netlify.app/
MIT License
259 stars 155 forks source link

Fixtable randomly causes table adding a huge amount of unexpected columns during collaboration #249

Open qinwenshi opened 1 week ago

qinwenshi commented 1 week ago

Abstract:

We are developing a system based on Tiptap. The underlying framework is ProseMirror + Yjs. The table component is developed based on prosemirror-tables.

We observed that when users intensively perform row and column operations (we will provide a method to reproduce this issue below), in some cases, it triggers infinite table growth. By "infinite growth," we mean that users can visually see the table columns rapidly expanding on the right side. This growth exhibits an uncontrolled trend, causing the document content to increase exponentially in a short period of time. As a result, the document contains too many DOM elements, making the rendering time excessively long and rendering the entire document, the browser crashed in the end.

image

Trigger method:

Suppose there is a 2×2 table in the document, with two users online simultaneously, namely user A and user B.

User A quickly adds columns to the end of the table.

User B quickly adds rows to the end of the table.

Analysis:

User A and User B will, at some point, both be in the following state, causing both to fix a cell in r3c3 simultaneously. The first fix makes the table complete, but the second fix will cause row 3 to have 4 cells. At this point, User A sees the table as complete, while User B sees an extra cell in the third row. This discrepancy causes User B to fix row 1 column 4 (R1C4) and row 2 column 4 (R2C4) again. This fix, when broadcasted to User A, triggers an infinite loop of fixtable.

x x a

x x a

b b X

Fix Discussion:

Could we make the fixtable operation idempotent? For example, when fixing r3c3, add a flag to the cell. The next time we attempt to fix r3c3, check if the flag already exists. If it does, stop the fix.

Log Investigation:

We added logs in fixtable.ts after calculating mustAdd. We observed that "fixTable mustAdd:[0,0,0,1,0,0]" was logged 119 times and "fixTable mustAdd:[1,1,1,0,1,1]" was logged 89 times. In summary, during the period of failure, logs related to fixTable mustAdd were called intensively.

ocavue commented 1 week ago

I would love to accept a PR for this issue.

ramezrafla commented 4 days ago

We have faced a similar issue. I was going to open a new issue, but the symptoms are similar. A very large table is generated ending in a page crash when fixTable is called with the HTML snippet below:

<html>
   <body>
      <table>
         <tbody>
            <tr>
               <td colspan="3"> </td>
               <td></td>
               <td></td>
               <td></td>
               <td></td>
               <td></td>
               <td></td>
               <td></td>
               <td></td>
            </tr>
         </tbody>
      </table>
</html>

If we remove the colpan, it renders perfectly