mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-12 21:23:45 +01:00
[CE/SP] Hotfix 6.2.1 (#35140)
GitOrigin-RevId: 015db4b74ac04398e0227775daf8aa8782195489
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
FROM sharelatex/sharelatex:6.2.0
|
||||
|
||||
# [real-time] add strict validation for incoming applyOtUpdate messages
|
||||
COPY pr_35045.patch .
|
||||
RUN patch -p1 < pr_35045.patch && rm pr_35045.patch
|
||||
|
||||
# [real-time] gracefully handle undefined meta.tc
|
||||
COPY pr_35049.patch .
|
||||
RUN patch -p1 < pr_35049.patch && rm pr_35049.patch
|
||||
|
||||
# [web] avoid sending empty sharejs op
|
||||
COPY pr_35066.patch .
|
||||
RUN patch -p1 < pr_35066.patch && rm pr_35066.patch
|
||||
RUN node genScript compile | bash
|
||||
@@ -0,0 +1,49 @@
|
||||
diff --git a/services/real-time/app/js/Router.js b/services/real-time/app/js/Router.js
|
||||
index d25b804a83bc..7bd4864322b5 100644
|
||||
--- a/services/real-time/app/js/Router.js
|
||||
+++ b/services/real-time/app/js/Router.js
|
||||
@@ -26,7 +26,43 @@ const joinDocSchema = z.object({
|
||||
|
||||
const applyOtUpdateSchema = z.object({
|
||||
doc_id: zz.objectId(),
|
||||
- update: z.object(),
|
||||
+ update: z.strictObject({
|
||||
+ doc: zz.objectId().optional(),
|
||||
+ dupIfSource: z.array(z.string()).optional(),
|
||||
+ hash: z.string().optional(),
|
||||
+ lastV: z.number().optional(),
|
||||
+ meta: z
|
||||
+ .strictObject({
|
||||
+ tc: z.string(),
|
||||
+ })
|
||||
+ .optional(),
|
||||
+ op: z
|
||||
+ .array(
|
||||
+ z
|
||||
+ .strictObject({
|
||||
+ i: z.string(),
|
||||
+ p: z.number().int().min(0),
|
||||
+ u: z.boolean().optional(),
|
||||
+ })
|
||||
+ .or(
|
||||
+ z.strictObject({
|
||||
+ d: z.string(),
|
||||
+ p: z.number().int().min(0),
|
||||
+ u: z.boolean().optional(),
|
||||
+ })
|
||||
+ )
|
||||
+ .or(
|
||||
+ z.strictObject({
|
||||
+ c: z.string(),
|
||||
+ p: z.number().int().min(0),
|
||||
+ t: z.string(),
|
||||
+ u: z.boolean().optional(),
|
||||
+ })
|
||||
+ )
|
||||
+ )
|
||||
+ .min(1),
|
||||
+ v: z.number().int().min(0),
|
||||
+ }),
|
||||
})
|
||||
|
||||
let Router
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/services/real-time/app/js/Router.js b/services/real-time/app/js/Router.js
|
||||
index e683c0d261ba..7d68a6911a50 100644
|
||||
--- a/services/real-time/app/js/Router.js
|
||||
+++ b/services/real-time/app/js/Router.js
|
||||
@@ -33,7 +33,7 @@ const applyOtUpdateSchema = z.object({
|
||||
lastV: z.number().optional(),
|
||||
meta: z
|
||||
.strictObject({
|
||||
- tc: z.string(),
|
||||
+ tc: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
op: z
|
||||
@@ -0,0 +1,75 @@
|
||||
diff --git a/services/web/frontend/js/vendor/libs/sharejs.js b/services/web/frontend/js/vendor/libs/sharejs.js
|
||||
index e3bec4804e22..1749e61e6dfa 100644
|
||||
--- a/services/web/frontend/js/vendor/libs/sharejs.js
|
||||
+++ b/services/web/frontend/js/vendor/libs/sharejs.js
|
||||
@@ -1048,6 +1048,24 @@ export const { Doc } = (() => {
|
||||
this.version = msg.v;
|
||||
}
|
||||
|
||||
+ // Overleaf: an inflight op that cancelled out against a remote op is
|
||||
+ // empty; there is nothing to resend. Drop it (resolving its callbacks and
|
||||
+ // clearing the dedup ids) so we do not resend an empty op. If there is no
|
||||
+ // pending op either, the doc is fully in sync, so emit 'saved'; otherwise
|
||||
+ // flush() below sends the pending op normally.
|
||||
+ if (this.inflightOp && this.inflightOp.length === 0) {
|
||||
+ this.inflightOp = null;
|
||||
+ var inflightCallbacks = this.inflightCallbacks;
|
||||
+ this.inflightCallbacks = [];
|
||||
+ this.inflightSubmittedIds.length = 0;
|
||||
+ inflightCallbacks.forEach(function (callback) {
|
||||
+ callback(null);
|
||||
+ });
|
||||
+ if (this.pendingOp === null) {
|
||||
+ this.emit('saved');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// Resend any previously queued operation.
|
||||
if (this.inflightOp) {
|
||||
var response = {
|
||||
@@ -1145,6 +1163,21 @@ export const { Doc } = (() => {
|
||||
|
||||
this.pendingOp = _Array$from8[0];
|
||||
undo = _Array$from8[1];
|
||||
+
|
||||
+ // Overleaf: a pending op fully reverted by the undo is a no-op.
|
||||
+ // Drop it (rather than leaving an empty op list) so it is not
|
||||
+ // flushed and sent as an empty op. Resolve its submit callbacks; the
|
||||
+ // inflight op was already cleared above, so the doc is fully in
|
||||
+ // sync: emit 'saved'.
|
||||
+ if (this.pendingOp.length === 0) {
|
||||
+ this.pendingOp = null;
|
||||
+ var pendingCallbacks = this.pendingCallbacks;
|
||||
+ this.pendingCallbacks = [];
|
||||
+ pendingCallbacks.forEach(function (callback) {
|
||||
+ callback(null);
|
||||
+ });
|
||||
+ this.emit('saved');
|
||||
+ }
|
||||
}
|
||||
|
||||
// ... and apply it locally, reverting the changes.
|
||||
@@ -1261,6 +1294,23 @@ export const { Doc } = (() => {
|
||||
|
||||
this.pendingOp = _Array$from12[0];
|
||||
docOp = _Array$from12[1];
|
||||
+
|
||||
+ // Overleaf: a pending op that fully cancels against the server op is a
|
||||
+ // no-op. Drop it (rather than leaving an empty op list) so it is not
|
||||
+ // flushed and sent to the server as an empty op. Resolve its submit
|
||||
+ // callbacks (it completed as a no-op), and if nothing is inflight either
|
||||
+ // the doc is fully in sync, so emit 'saved'.
|
||||
+ if (this.pendingOp.length === 0) {
|
||||
+ this.pendingOp = null;
|
||||
+ var pendingCallbacks = this.pendingCallbacks;
|
||||
+ this.pendingCallbacks = [];
|
||||
+ pendingCallbacks.forEach(function (callback) {
|
||||
+ callback(null);
|
||||
+ });
|
||||
+ if (this.inflightOp === null) {
|
||||
+ this.emit('saved');
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
this.version++;
|
||||
Reference in New Issue
Block a user