mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Merge pull request #20421 from overleaf/em-history-limit-tracked-deletes
Do not count tracked deletes towards size limit in history GitOrigin-RevId: 0185e6df80d8f3433aa489a1c90f5a6499af5ef4
This commit is contained in:
@@ -3,8 +3,6 @@
|
||||
const assert = require('check-types').assert
|
||||
const OError = require('@overleaf/o-error')
|
||||
|
||||
const TextOperation = require('./operation/text_operation')
|
||||
|
||||
class NotFoundError extends OError {
|
||||
constructor(hash) {
|
||||
super(`blob ${hash} not found`, { hash })
|
||||
@@ -26,17 +24,14 @@ class Blob {
|
||||
* in to determine that; so it is useful to have an upper bound on the byte
|
||||
* length of a file that might be editable.
|
||||
*
|
||||
* The reason for the factor of 3 is as follows. We cannot currently edit files
|
||||
* that contain characters outside of the basic multilingual plane, so we're
|
||||
* limited to characters that can be represented in a single, two-byte UCS-2
|
||||
* code unit. Encoding the largest such value, 0xFFFF (which is not actually
|
||||
* a valid character), takes three bytes in UTF-8: 0xEF 0xBF 0xBF. A file
|
||||
* composed entirely of three-byte UTF-8 codepoints is the worst case; in
|
||||
* practice, this is a very conservative upper bound.
|
||||
*
|
||||
* @type {number}
|
||||
* This used to be 3 times the max editable file length to account for 3-byte
|
||||
* UTF-8 codepoints. However, editable file blobs now include tracked deletes
|
||||
* and the system used to allow unlimited tracked deletes on a single file.
|
||||
* A practical limit is the 16 MB Mongo size limit. It wouldn't have been
|
||||
* possible to store more than 16 MB of tracked deletes. We therefore fall
|
||||
* back to this limit.
|
||||
*/
|
||||
static MAX_EDITABLE_BYTE_LENGTH_BOUND = 3 * TextOperation.MAX_STRING_LENGTH
|
||||
static MAX_EDITABLE_BYTE_LENGTH_BOUND = 16 * 1024 * 1024
|
||||
|
||||
static NotFoundError = NotFoundError
|
||||
|
||||
|
||||
@@ -41,6 +41,17 @@ class TrackedChangeList {
|
||||
return this._trackedChanges.length
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over tracked changes
|
||||
*
|
||||
* @returns {Iterator<TrackedChange>}
|
||||
*/
|
||||
*[Symbol.iterator]() {
|
||||
for (const change of this._trackedChanges) {
|
||||
yield change
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {readonly TrackedChange[]}
|
||||
*/
|
||||
|
||||
@@ -46,9 +46,18 @@ class TextOperation extends EditOperation {
|
||||
/**
|
||||
* Length of the longest file that we'll attempt to edit, in characters.
|
||||
*
|
||||
* @type {number}
|
||||
* This number used to be 2M characters, but it didn't include tracked
|
||||
* deletes. Now that it includes tracked deletes, we raise the limit to the
|
||||
* Mongo document size limit. It would have been impossible to store more
|
||||
* tracked deletes in a single document.
|
||||
*/
|
||||
static MAX_STRING_LENGTH = 2 * Math.pow(1024, 2)
|
||||
static MAX_STRING_LENGTH = 16 * Math.pow(1024, 2)
|
||||
|
||||
/**
|
||||
* Max editable file length, excluding tracked deletes.
|
||||
*/
|
||||
static MAX_STRING_LENGTH_EXCLUDING_TRACKED_DELETES = 2 * Math.pow(1024, 2)
|
||||
|
||||
static UnprocessableError = UnprocessableError
|
||||
static ApplyError = ApplyError
|
||||
static InvalidInsertionError = InvalidInsertionError
|
||||
@@ -325,9 +334,30 @@ class TextOperation extends EditOperation {
|
||||
}
|
||||
|
||||
if (result.length > TextOperation.MAX_STRING_LENGTH) {
|
||||
// We're over the hard limit, with or without tracked deletes
|
||||
throw new TextOperation.TooLongError(operation, result.length)
|
||||
}
|
||||
|
||||
if (
|
||||
result.length > TextOperation.MAX_STRING_LENGTH_EXCLUDING_TRACKED_DELETES
|
||||
) {
|
||||
// We might be over the limit, but we need to check how much of the
|
||||
// length is tracked deletes.
|
||||
let trackedDeletesLength = 0
|
||||
for (const change of file.trackedChanges) {
|
||||
if (change.tracking.type === 'delete') {
|
||||
trackedDeletesLength += change.range.length
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
result.length - trackedDeletesLength >
|
||||
TextOperation.MAX_STRING_LENGTH_EXCLUDING_TRACKED_DELETES
|
||||
) {
|
||||
throw new TextOperation.TooLongError(operation, result.length)
|
||||
}
|
||||
}
|
||||
|
||||
file.content = result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user