-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Object extensible error #480
Comments
Have you got a minimally working example? |
Hello there, anything new on this? It actually happens in all 3 list operations: li, ld, lm. It fails the first time and after that works. If there is not anything new and the issue is still pending I can create a repo with a small example. Cheers! |
@gsavvidis96 repro case would definitely be good, please |
It seems I found the issue after a long day so I leave here what I found out in case it is of help. I am using react with zustand for state management. After subscribing to the document I was saving the
So instead, I saved the Here is a simple component of my use-case.
|
In general, ShareDB's The gotcha here is that libraries — especially data stores (Redux, Vuex, etc.) — can attempt to mutate When using ShareDB in conjunction with a frontend data store, I would recommend storing a deep clone of In addition, if you want/need reactivity, you'll also need to write adapters to apply your ops to your data store representation (so that you can incrementally change the object, rather than clobber reactivity by overwriting the whole thing). For example, here's a function we're using to update a Vuex object according to an op: export default function applyOp(json0: any, op: Op): void {
op = clone(op);
const path = op.p as string[];
const key = path.pop();
const parent = dig(json0, path);
const parentKey = path.pop();
const grandparent = dig(json0, path);
if (parent === undefined) return;
if ('oi' in op) {
return Vue.set(parent, key, op.oi);
}
if ('li' in op) {
// Don't need to use Vue.set, because it will already be watching
// the array: https://vuejs.org/v2/guide/list.html#Mutation-Methods
(parent as any[]).splice(parseInt(key), 0, op.li);
return;
}
if ('od' in op) {
return Vue.delete(parent, key);
}
if ('ld' in op) {
(parent as any[]).splice(parseInt(key), 1);
return;
}
if ('lm' in op) {
(parent as any[]).splice(parseInt(op.lm), 0, (parent as any[]).splice(parseInt(key), 1)[0]);
return;
}
if ('si' in op) {
const updatedString = parent.substring(0, key) + op.si + parent.substring(key);
return Vue.set(grandparent, parentKey, updatedString);
}
if ('sd' in op) {
const updatedString = parent.substring(0, key) + parent.substring(key + op.sd.length);
return Vue.set(grandparent, parentKey, updatedString);
}
throw new Error('Unrecognised op type');
} |
FWIW Here's a solution that makes import ShareDB, { Connection } from 'sharedb/lib/client';
import { type as json0 } from 'ot-json0';
import produce from 'immer';
const originalApply = json0.apply;
json0.apply = (snapshot, op) =>
produce(snapshot, (draftSnapshot) => {
originalApply(draftSnapshot, op);
}); This is used in the VizHub codebase as it makes it a lot easier to work with the state as it changes (e.g. triggering Not sure if this is related to the issue at hand, but might be! |
I honestly have no clue why this is happening. Here is how my stack works:
TypeError: Cannot add property 0, object is not extensible
at Array.splice in json0This doesnt seem to happen when I create a doc on the client side and apply the same op to it. Is there anything special I need to do when creating the doc on the server side?
I have no clue where even to begin with this. Where in the ShareDB stack is
Object.preventExtensions()
being called? Does this have something to do with the websocket configuration?The text was updated successfully, but these errors were encountered: