diff --git a/services/document-updater/app/js/UpdateManager.js b/services/document-updater/app/js/UpdateManager.js index dd4d2db728..26d1396429 100644 --- a/services/document-updater/app/js/UpdateManager.js +++ b/services/document-updater/app/js/UpdateManager.js @@ -320,7 +320,10 @@ const UpdateManager = { historyRangesSupport ) { let docLength = _.reduce(lines, (chars, line) => chars + line.length, 0) - docLength += lines.length - 1 // count newline characters + // Add newline characters. Lines are joined by newlines, but the last line + // doesn't include a newline. We must make a special case for an empty list + // so that it doesn't report a doc length of -1. + docLength += Math.max(lines.length - 1, 0) let historyDocLength = docLength for (const change of ranges.changes ?? []) { if ('d' in change.op) { diff --git a/services/document-updater/test/unit/js/UpdateManager/UpdateManagerTests.js b/services/document-updater/test/unit/js/UpdateManager/UpdateManagerTests.js index bd5a46a81b..3f90d101c9 100644 --- a/services/document-updater/test/unit/js/UpdateManager/UpdateManagerTests.js +++ b/services/document-updater/test/unit/js/UpdateManager/UpdateManagerTests.js @@ -678,6 +678,29 @@ describe('UpdateManager', function () { }, ]) }) + + it('should calculate the right doc length for an empty document', function () { + this.historyUpdates = [{ v: 42, op: [{ i: 'foobar', p: 0 }] }] + this.UpdateManager._adjustHistoryUpdatesMetadata( + this.historyUpdates, + this.pathname, + this.projectHistoryId, + [], + {}, + false + ) + this.historyUpdates.should.deep.equal([ + { + projectHistoryId: this.projectHistoryId, + v: 42, + op: [{ i: 'foobar', p: 0 }], + meta: { + pathname: this.pathname, + doc_length: 0, + }, + }, + ]) + }) }) describe('lockUpdatesAndDo', function () {