| 534 | |
| 535 | // Transform server op data by a client op, and vice versa. Ops are edited in place. |
| 536 | function transformX(client, server) { |
| 537 | // Order of statements in this function matters. Be especially careful if |
| 538 | // refactoring this function |
| 539 | |
| 540 | // A client delete op should dominate if both the server and the client |
| 541 | // delete the document. Thus, any ops following the client delete (such as a |
| 542 | // subsequent create) will be maintained, since the server op is transformed |
| 543 | // to a no-op |
| 544 | if (client.del) return setNoOp(server); |
| 545 | |
| 546 | if (server.del) { |
| 547 | return new ShareDBError(ERROR_CODE.ERR_DOC_WAS_DELETED, 'Document was deleted'); |
| 548 | } |
| 549 | if (server.create) { |
| 550 | return new ShareDBError(ERROR_CODE.ERR_DOC_ALREADY_CREATED, 'Document already created'); |
| 551 | } |
| 552 | |
| 553 | // Ignore no-op coming from server |
| 554 | if (!('op' in server)) return; |
| 555 | |
| 556 | // I believe that this should not occur, but check just in case |
| 557 | if (client.create) { |
| 558 | return new ShareDBError(ERROR_CODE.ERR_DOC_ALREADY_CREATED, 'Document already created'); |
| 559 | } |
| 560 | |
| 561 | // They both edited the document. This is the normal case for this function - |
| 562 | // as in, most of the time we'll end up down here. |
| 563 | // |
| 564 | // You should be wondering why I'm using client.type instead of this.type. |
| 565 | // The reason is, if we get ops at an old version of the document, this.type |
| 566 | // might be undefined or a totally different type. By pinning the type to the |
| 567 | // op data, we make sure the right type has its transform function called. |
| 568 | if (client.type.transformX) { |
| 569 | var result = client.type.transformX(client.op, server.op); |
| 570 | client.op = result[0]; |
| 571 | server.op = result[1]; |
| 572 | } else { |
| 573 | var clientOp = client.type.transform(client.op, server.op, 'left'); |
| 574 | var serverOp = client.type.transform(server.op, client.op, 'right'); |
| 575 | client.op = clientOp; |
| 576 | server.op = serverOp; |
| 577 | } |
| 578 | }; |
| 579 | |
| 580 | /** |
| 581 | * Applies the operation to the snapshot |