@automerge/automerge-repo-react-hooks 2.5.2 → 2.6.0-subduction.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +84 -988
- package/dist/index.js.map +1 -1
- package/dist/usePresence.d.ts +0 -24
- package/dist/usePresence.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/usePresence.ts +0 -44
package/dist/index.js
CHANGED
|
@@ -2146,969 +2146,103 @@ const useLocalAwareness = ({
|
|
|
2146
2146
|
return [localState, setState];
|
|
2147
2147
|
};
|
|
2148
2148
|
|
|
2149
|
-
//
|
|
2150
|
-
const STATE = Symbol.for("_am_meta"); // symbol used to hide application metadata on automerge objects
|
|
2151
|
-
const TRACE = Symbol.for("_am_trace"); // used for debugging
|
|
2152
|
-
const OBJECT_ID = Symbol.for("_am_objectId"); // symbol used to hide the object id on automerge objects
|
|
2153
|
-
const IS_PROXY = Symbol.for("_am_isProxy"); // symbol used to test if the document is a proxy object
|
|
2154
|
-
const CLEAR_CACHE = Symbol.for("_am_clearCache"); // symbol used to tell a proxy object to clear its cache
|
|
2155
|
-
const UINT = Symbol.for("_am_uint");
|
|
2156
|
-
const INT = Symbol.for("_am_int");
|
|
2157
|
-
const F64 = Symbol.for("_am_f64");
|
|
2158
|
-
const COUNTER = Symbol.for("_am_counter");
|
|
2159
|
-
const IMMUTABLE_STRING = Symbol.for("_am_immutableString");
|
|
2149
|
+
BigInt("9223372036854775807"); // 2n ** 63n - 1n;
|
|
2160
2150
|
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2151
|
+
let wasm;
|
|
2152
|
+
|
|
2153
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
2154
|
+
|
|
2155
|
+
cachedTextDecoder.decode();
|
|
2156
|
+
|
|
2157
|
+
const cachedTextEncoder = new TextEncoder();
|
|
2158
|
+
|
|
2159
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
2160
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
2161
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
2162
|
+
view.set(buf);
|
|
2163
|
+
return {
|
|
2164
|
+
read: arg.length,
|
|
2165
|
+
written: buf.length
|
|
2166
|
+
};
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
function takeFromExternrefTable0(idx) {
|
|
2171
|
+
const value = wasm.__wbindgen_export_4.get(idx);
|
|
2172
|
+
wasm.__externref_table_dealloc(idx);
|
|
2173
|
+
return value;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
(typeof FinalizationRegistry === 'undefined')
|
|
2177
|
+
? { }
|
|
2178
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_automerge_free(ptr >>> 0, 1));
|
|
2179
|
+
|
|
2180
|
+
const SyncStateFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
2181
|
+
? { register: () => {}, unregister: () => {} }
|
|
2182
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_syncstate_free(ptr >>> 0, 1));
|
|
2183
|
+
|
|
2184
|
+
class SyncState {
|
|
2185
|
+
|
|
2186
|
+
static __wrap(ptr) {
|
|
2187
|
+
ptr = ptr >>> 0;
|
|
2188
|
+
const obj = Object.create(SyncState.prototype);
|
|
2189
|
+
obj.__wbg_ptr = ptr;
|
|
2190
|
+
SyncStateFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
2191
|
+
return obj;
|
|
2181
2192
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
return this.valueOf().toString();
|
|
2193
|
+
|
|
2194
|
+
__destroy_into_raw() {
|
|
2195
|
+
const ptr = this.__wbg_ptr;
|
|
2196
|
+
this.__wbg_ptr = 0;
|
|
2197
|
+
SyncStateFinalization.unregister(this);
|
|
2198
|
+
return ptr;
|
|
2189
2199
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
toJSON() {
|
|
2195
|
-
return this.value;
|
|
2200
|
+
|
|
2201
|
+
free() {
|
|
2202
|
+
const ptr = this.__destroy_into_raw();
|
|
2203
|
+
wasm.__wbg_syncstate_free(ptr, 0);
|
|
2196
2204
|
}
|
|
2197
2205
|
/**
|
|
2198
|
-
*
|
|
2199
|
-
* increases the value of the counter by 1.
|
|
2200
|
-
*
|
|
2201
|
-
* Will throw an error if used outside of a change callback.
|
|
2206
|
+
* @returns {Heads}
|
|
2202
2207
|
*/
|
|
2203
|
-
|
|
2204
|
-
|
|
2208
|
+
get sharedHeads() {
|
|
2209
|
+
const ret = wasm.syncstate_sharedHeads(this.__wbg_ptr);
|
|
2210
|
+
return ret;
|
|
2205
2211
|
}
|
|
2206
2212
|
/**
|
|
2207
|
-
*
|
|
2208
|
-
* decreases the value of the counter by 1.
|
|
2209
|
-
*
|
|
2210
|
-
* Will throw an error if used outside of a change callback.
|
|
2213
|
+
* @returns {Heads}
|
|
2211
2214
|
*/
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
}
|
|
2216
|
-
/**
|
|
2217
|
-
* An instance of this class is used when a counter is accessed within a change
|
|
2218
|
-
* callback.
|
|
2219
|
-
*/
|
|
2220
|
-
class WriteableCounter extends Counter {
|
|
2221
|
-
constructor(value, context, path, objectId, key) {
|
|
2222
|
-
super(value);
|
|
2223
|
-
this.context = context;
|
|
2224
|
-
this.path = path;
|
|
2225
|
-
this.objectId = objectId;
|
|
2226
|
-
this.key = key;
|
|
2215
|
+
get lastSentHeads() {
|
|
2216
|
+
const ret = wasm.syncstate_lastSentHeads(this.__wbg_ptr);
|
|
2217
|
+
return ret;
|
|
2227
2218
|
}
|
|
2228
2219
|
/**
|
|
2229
|
-
*
|
|
2230
|
-
* increases the value of the counter by 1.
|
|
2220
|
+
* @param {Heads} heads
|
|
2231
2221
|
*/
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2222
|
+
set lastSentHeads(heads) {
|
|
2223
|
+
const ret = wasm.syncstate_set_lastSentHeads(this.__wbg_ptr, heads);
|
|
2224
|
+
if (ret[1]) {
|
|
2225
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
2226
|
+
}
|
|
2237
2227
|
}
|
|
2238
2228
|
/**
|
|
2239
|
-
*
|
|
2240
|
-
* decreases the value of the counter by 1.
|
|
2229
|
+
* @param {Heads} hashes
|
|
2241
2230
|
*/
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
* Returns an instance of `WriteableCounter` for use in a change callback.
|
|
2248
|
-
* `context` is the proxy context that keeps track of the mutations.
|
|
2249
|
-
* `objectId` is the ID of the object containing the counter, and `key` is
|
|
2250
|
-
* the property name (key in map, or index in list) where the counter is
|
|
2251
|
-
* located.
|
|
2252
|
-
*/
|
|
2253
|
-
function getWriteableCounter(value, context, path, objectId, key) {
|
|
2254
|
-
return new WriteableCounter(value, context, path, objectId, key);
|
|
2255
|
-
}
|
|
2256
|
-
//module.exports = { Counter, getWriteableCounter }
|
|
2257
|
-
|
|
2258
|
-
var _a;
|
|
2259
|
-
class ImmutableString {
|
|
2260
|
-
constructor(val) {
|
|
2261
|
-
// Used to detect whether a value is a ImmutableString object rather than using an instanceof check
|
|
2262
|
-
this[_a] = true;
|
|
2263
|
-
this.val = val;
|
|
2231
|
+
set sentHashes(hashes) {
|
|
2232
|
+
const ret = wasm.syncstate_set_sentHashes(this.__wbg_ptr, hashes);
|
|
2233
|
+
if (ret[1]) {
|
|
2234
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
2235
|
+
}
|
|
2264
2236
|
}
|
|
2265
2237
|
/**
|
|
2266
|
-
*
|
|
2238
|
+
* @returns {SyncState}
|
|
2267
2239
|
*/
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
toJSON() {
|
|
2272
|
-
return this.val;
|
|
2240
|
+
clone() {
|
|
2241
|
+
const ret = wasm.syncstate_clone(this.__wbg_ptr);
|
|
2242
|
+
return SyncState.__wrap(ret);
|
|
2273
2243
|
}
|
|
2274
2244
|
}
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
function parseListIndex(key) {
|
|
2278
|
-
if (typeof key === "string" && /^[0-9]+$/.test(key))
|
|
2279
|
-
key = parseInt(key, 10);
|
|
2280
|
-
if (typeof key !== "number") {
|
|
2281
|
-
return key;
|
|
2282
|
-
}
|
|
2283
|
-
if (key < 0 || isNaN(key) || key === Infinity || key === -Infinity) {
|
|
2284
|
-
throw new RangeError("A list index must be positive, but you passed " + key);
|
|
2285
|
-
}
|
|
2286
|
-
return key;
|
|
2287
|
-
}
|
|
2288
|
-
function valueAt(target, prop) {
|
|
2289
|
-
const { context, objectId, path } = target;
|
|
2290
|
-
const value = context.getWithType(objectId, prop);
|
|
2291
|
-
if (value === null) {
|
|
2292
|
-
return;
|
|
2293
|
-
}
|
|
2294
|
-
const datatype = value[0];
|
|
2295
|
-
const val = value[1];
|
|
2296
|
-
switch (datatype) {
|
|
2297
|
-
case undefined:
|
|
2298
|
-
return;
|
|
2299
|
-
case "map":
|
|
2300
|
-
return mapProxy(context, val, [...path, prop]);
|
|
2301
|
-
case "list":
|
|
2302
|
-
return listProxy(context, val, [...path, prop]);
|
|
2303
|
-
case "text":
|
|
2304
|
-
return context.text(val);
|
|
2305
|
-
case "str":
|
|
2306
|
-
return new ImmutableString(val);
|
|
2307
|
-
case "uint":
|
|
2308
|
-
return val;
|
|
2309
|
-
case "int":
|
|
2310
|
-
return val;
|
|
2311
|
-
case "f64":
|
|
2312
|
-
return val;
|
|
2313
|
-
case "boolean":
|
|
2314
|
-
return val;
|
|
2315
|
-
case "null":
|
|
2316
|
-
return null;
|
|
2317
|
-
case "bytes":
|
|
2318
|
-
return val;
|
|
2319
|
-
case "timestamp":
|
|
2320
|
-
return val;
|
|
2321
|
-
case "counter": {
|
|
2322
|
-
const counter = getWriteableCounter(val, context, path, objectId, prop);
|
|
2323
|
-
return counter;
|
|
2324
|
-
}
|
|
2325
|
-
default:
|
|
2326
|
-
throw RangeError(`datatype ${datatype} unimplemented`);
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
function import_value(value, path, context) {
|
|
2330
|
-
const type = typeof value;
|
|
2331
|
-
switch (type) {
|
|
2332
|
-
case "object":
|
|
2333
|
-
if (value == null) {
|
|
2334
|
-
return [null, "null"];
|
|
2335
|
-
}
|
|
2336
|
-
else if (value[UINT]) {
|
|
2337
|
-
return [value.value, "uint"];
|
|
2338
|
-
}
|
|
2339
|
-
else if (value[INT]) {
|
|
2340
|
-
return [value.value, "int"];
|
|
2341
|
-
}
|
|
2342
|
-
else if (value[F64]) {
|
|
2343
|
-
return [value.value, "f64"];
|
|
2344
|
-
}
|
|
2345
|
-
else if (value[COUNTER]) {
|
|
2346
|
-
return [value.value, "counter"];
|
|
2347
|
-
}
|
|
2348
|
-
else if (value instanceof Date) {
|
|
2349
|
-
return [value.getTime(), "timestamp"];
|
|
2350
|
-
}
|
|
2351
|
-
else if (isImmutableString(value)) {
|
|
2352
|
-
return [value.toString(), "str"];
|
|
2353
|
-
}
|
|
2354
|
-
else if (value instanceof Uint8Array) {
|
|
2355
|
-
return [value, "bytes"];
|
|
2356
|
-
}
|
|
2357
|
-
else if (value instanceof Array) {
|
|
2358
|
-
return [value, "list"];
|
|
2359
|
-
}
|
|
2360
|
-
else if (Object.prototype.toString.call(value) === "[object Object]") {
|
|
2361
|
-
return [value, "map"];
|
|
2362
|
-
}
|
|
2363
|
-
else if (isSameDocument(value, context)) {
|
|
2364
|
-
throw new RangeError("Cannot create a reference to an existing document object");
|
|
2365
|
-
}
|
|
2366
|
-
else {
|
|
2367
|
-
throw new RangeError(`Cannot assign unknown object: ${value}`);
|
|
2368
|
-
}
|
|
2369
|
-
case "boolean":
|
|
2370
|
-
return [value, "boolean"];
|
|
2371
|
-
case "number":
|
|
2372
|
-
if (Number.isInteger(value)) {
|
|
2373
|
-
return [value, "int"];
|
|
2374
|
-
}
|
|
2375
|
-
else {
|
|
2376
|
-
return [value, "f64"];
|
|
2377
|
-
}
|
|
2378
|
-
case "string":
|
|
2379
|
-
return [value, "text"];
|
|
2380
|
-
case "undefined":
|
|
2381
|
-
throw new RangeError([
|
|
2382
|
-
`Cannot assign undefined value at ${printPath(path)}, `,
|
|
2383
|
-
"because `undefined` is not a valid JSON data type. ",
|
|
2384
|
-
"You might consider setting the property's value to `null`, ",
|
|
2385
|
-
"or using `delete` to remove it altogether.",
|
|
2386
|
-
].join(""));
|
|
2387
|
-
default:
|
|
2388
|
-
throw new RangeError([
|
|
2389
|
-
`Cannot assign ${type} value at ${printPath(path)}. `,
|
|
2390
|
-
`All JSON primitive datatypes (object, array, string, number, boolean, null) `,
|
|
2391
|
-
`are supported in an Automerge document; ${type} values are not. `,
|
|
2392
|
-
].join(""));
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2395
|
-
// When we assign a value to a property in a proxy we recursively walk through
|
|
2396
|
-
// the value we are assigning and copy it into the document. This is generally
|
|
2397
|
-
// desirable behaviour. However, a very common bug is to accidentally assign a
|
|
2398
|
-
// value which is already in the document to another key within the same
|
|
2399
|
-
// document, this often leads to surprising behaviour where users expected to
|
|
2400
|
-
// _move_ the object, but it is instead copied. To avoid this we check if the
|
|
2401
|
-
// value is from the same document and if it is we throw an error, this means
|
|
2402
|
-
// we require an explicit Object.assign call to copy the object, thus avoiding
|
|
2403
|
-
// the footgun
|
|
2404
|
-
function isSameDocument(val, context) {
|
|
2405
|
-
var _b, _c;
|
|
2406
|
-
// Date is technically an object, but immutable, so allowing people to assign
|
|
2407
|
-
// a date from one place in the document to another place in the document is
|
|
2408
|
-
// not likely to be a bug
|
|
2409
|
-
if (val instanceof Date) {
|
|
2410
|
-
return false;
|
|
2411
|
-
}
|
|
2412
|
-
// this depends on __wbg_ptr being the wasm pointer
|
|
2413
|
-
// a new version of wasm-bindgen will break this
|
|
2414
|
-
// but the tests should expose the break
|
|
2415
|
-
if (val && ((_c = (_b = val[STATE]) === null || _b === void 0 ? void 0 : _b.handle) === null || _c === void 0 ? void 0 : _c.__wbg_ptr) === context.__wbg_ptr) {
|
|
2416
|
-
return true;
|
|
2417
|
-
}
|
|
2418
|
-
return false;
|
|
2419
|
-
}
|
|
2420
|
-
const MapHandler = {
|
|
2421
|
-
get(target, key) {
|
|
2422
|
-
const { context, objectId, cache } = target;
|
|
2423
|
-
if (key === Symbol.toStringTag) {
|
|
2424
|
-
return target[Symbol.toStringTag];
|
|
2425
|
-
}
|
|
2426
|
-
if (key === OBJECT_ID)
|
|
2427
|
-
return objectId;
|
|
2428
|
-
if (key === IS_PROXY)
|
|
2429
|
-
return true;
|
|
2430
|
-
if (key === TRACE)
|
|
2431
|
-
return target.trace;
|
|
2432
|
-
if (key === STATE)
|
|
2433
|
-
return { handle: context };
|
|
2434
|
-
if (!cache[key]) {
|
|
2435
|
-
cache[key] = valueAt(target, key);
|
|
2436
|
-
}
|
|
2437
|
-
return cache[key];
|
|
2438
|
-
},
|
|
2439
|
-
set(target, key, val) {
|
|
2440
|
-
const { context, objectId, path } = target;
|
|
2441
|
-
target.cache = {}; // reset cache on set
|
|
2442
|
-
if (isSameDocument(val, context)) {
|
|
2443
|
-
throw new RangeError("Cannot create a reference to an existing document object");
|
|
2444
|
-
}
|
|
2445
|
-
if (key === TRACE) {
|
|
2446
|
-
target.trace = val;
|
|
2447
|
-
return true;
|
|
2448
|
-
}
|
|
2449
|
-
if (key === CLEAR_CACHE) {
|
|
2450
|
-
return true;
|
|
2451
|
-
}
|
|
2452
|
-
const [value, datatype] = import_value(val, [...path, key], context);
|
|
2453
|
-
switch (datatype) {
|
|
2454
|
-
case "list": {
|
|
2455
|
-
const list = context.putObject(objectId, key, []);
|
|
2456
|
-
const proxyList = listProxy(context, list, [...path, key]);
|
|
2457
|
-
for (let i = 0; i < value.length; i++) {
|
|
2458
|
-
proxyList[i] = value[i];
|
|
2459
|
-
}
|
|
2460
|
-
break;
|
|
2461
|
-
}
|
|
2462
|
-
case "text": {
|
|
2463
|
-
context.putObject(objectId, key, value);
|
|
2464
|
-
break;
|
|
2465
|
-
}
|
|
2466
|
-
case "map": {
|
|
2467
|
-
const map = context.putObject(objectId, key, {});
|
|
2468
|
-
const proxyMap = mapProxy(context, map, [...path, key]);
|
|
2469
|
-
for (const key in value) {
|
|
2470
|
-
proxyMap[key] = value[key];
|
|
2471
|
-
}
|
|
2472
|
-
break;
|
|
2473
|
-
}
|
|
2474
|
-
default:
|
|
2475
|
-
context.put(objectId, key, value, datatype);
|
|
2476
|
-
}
|
|
2477
|
-
return true;
|
|
2478
|
-
},
|
|
2479
|
-
deleteProperty(target, key) {
|
|
2480
|
-
const { context, objectId } = target;
|
|
2481
|
-
target.cache = {}; // reset cache on delete
|
|
2482
|
-
context.delete(objectId, key);
|
|
2483
|
-
return true;
|
|
2484
|
-
},
|
|
2485
|
-
has(target, key) {
|
|
2486
|
-
const value = this.get(target, key);
|
|
2487
|
-
return value !== undefined;
|
|
2488
|
-
},
|
|
2489
|
-
getOwnPropertyDescriptor(target, key) {
|
|
2490
|
-
// const { context, objectId } = target
|
|
2491
|
-
const value = this.get(target, key);
|
|
2492
|
-
if (typeof value !== "undefined") {
|
|
2493
|
-
return {
|
|
2494
|
-
configurable: true,
|
|
2495
|
-
enumerable: true,
|
|
2496
|
-
value,
|
|
2497
|
-
};
|
|
2498
|
-
}
|
|
2499
|
-
},
|
|
2500
|
-
ownKeys(target) {
|
|
2501
|
-
const { context, objectId } = target;
|
|
2502
|
-
// FIXME - this is a tmp workaround until fix the dupe key bug in keys()
|
|
2503
|
-
const keys = context.keys(objectId);
|
|
2504
|
-
return [...new Set(keys)];
|
|
2505
|
-
},
|
|
2506
|
-
};
|
|
2507
|
-
const ListHandler = {
|
|
2508
|
-
get(target, index) {
|
|
2509
|
-
const { context, objectId } = target;
|
|
2510
|
-
index = parseListIndex(index);
|
|
2511
|
-
if (index === Symbol.hasInstance) {
|
|
2512
|
-
return (instance) => {
|
|
2513
|
-
return Array.isArray(instance);
|
|
2514
|
-
};
|
|
2515
|
-
}
|
|
2516
|
-
if (index === Symbol.toStringTag) {
|
|
2517
|
-
return target[Symbol.toStringTag];
|
|
2518
|
-
}
|
|
2519
|
-
if (index === OBJECT_ID)
|
|
2520
|
-
return objectId;
|
|
2521
|
-
if (index === IS_PROXY)
|
|
2522
|
-
return true;
|
|
2523
|
-
if (index === TRACE)
|
|
2524
|
-
return target.trace;
|
|
2525
|
-
if (index === STATE)
|
|
2526
|
-
return { handle: context };
|
|
2527
|
-
if (index === "length")
|
|
2528
|
-
return context.length(objectId);
|
|
2529
|
-
if (typeof index === "number") {
|
|
2530
|
-
return valueAt(target, index);
|
|
2531
|
-
}
|
|
2532
|
-
else {
|
|
2533
|
-
return listMethods(target)[index];
|
|
2534
|
-
}
|
|
2535
|
-
},
|
|
2536
|
-
set(target, index, val) {
|
|
2537
|
-
const { context, objectId, path } = target;
|
|
2538
|
-
index = parseListIndex(index);
|
|
2539
|
-
if (isSameDocument(val, context)) {
|
|
2540
|
-
throw new RangeError("Cannot create a reference to an existing document object");
|
|
2541
|
-
}
|
|
2542
|
-
if (index === CLEAR_CACHE) {
|
|
2543
|
-
return true;
|
|
2544
|
-
}
|
|
2545
|
-
if (index === TRACE) {
|
|
2546
|
-
target.trace = val;
|
|
2547
|
-
return true;
|
|
2548
|
-
}
|
|
2549
|
-
if (typeof index == "string") {
|
|
2550
|
-
throw new RangeError("list index must be a number");
|
|
2551
|
-
}
|
|
2552
|
-
const [value, datatype] = import_value(val, [...path, index], context);
|
|
2553
|
-
switch (datatype) {
|
|
2554
|
-
case "list": {
|
|
2555
|
-
let list;
|
|
2556
|
-
if (index >= context.length(objectId)) {
|
|
2557
|
-
list = context.insertObject(objectId, index, []);
|
|
2558
|
-
}
|
|
2559
|
-
else {
|
|
2560
|
-
list = context.putObject(objectId, index, []);
|
|
2561
|
-
}
|
|
2562
|
-
const proxyList = listProxy(context, list, [...path, index]);
|
|
2563
|
-
proxyList.splice(0, 0, ...value);
|
|
2564
|
-
break;
|
|
2565
|
-
}
|
|
2566
|
-
case "text": {
|
|
2567
|
-
if (index >= context.length(objectId)) {
|
|
2568
|
-
context.insertObject(objectId, index, value);
|
|
2569
|
-
}
|
|
2570
|
-
else {
|
|
2571
|
-
context.putObject(objectId, index, value);
|
|
2572
|
-
}
|
|
2573
|
-
break;
|
|
2574
|
-
}
|
|
2575
|
-
case "map": {
|
|
2576
|
-
let map;
|
|
2577
|
-
if (index >= context.length(objectId)) {
|
|
2578
|
-
map = context.insertObject(objectId, index, {});
|
|
2579
|
-
}
|
|
2580
|
-
else {
|
|
2581
|
-
map = context.putObject(objectId, index, {});
|
|
2582
|
-
}
|
|
2583
|
-
const proxyMap = mapProxy(context, map, [...path, index]);
|
|
2584
|
-
for (const key in value) {
|
|
2585
|
-
proxyMap[key] = value[key];
|
|
2586
|
-
}
|
|
2587
|
-
break;
|
|
2588
|
-
}
|
|
2589
|
-
default:
|
|
2590
|
-
if (index >= context.length(objectId)) {
|
|
2591
|
-
context.insert(objectId, index, value, datatype);
|
|
2592
|
-
}
|
|
2593
|
-
else {
|
|
2594
|
-
context.put(objectId, index, value, datatype);
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2597
|
-
return true;
|
|
2598
|
-
},
|
|
2599
|
-
deleteProperty(target, index) {
|
|
2600
|
-
const { context, objectId } = target;
|
|
2601
|
-
index = parseListIndex(index);
|
|
2602
|
-
const elem = context.get(objectId, index);
|
|
2603
|
-
if (elem != null && elem[0] == "counter") {
|
|
2604
|
-
throw new TypeError("Unsupported operation: deleting a counter from a list");
|
|
2605
|
-
}
|
|
2606
|
-
context.delete(objectId, index);
|
|
2607
|
-
return true;
|
|
2608
|
-
},
|
|
2609
|
-
has(target, index) {
|
|
2610
|
-
const { context, objectId } = target;
|
|
2611
|
-
index = parseListIndex(index);
|
|
2612
|
-
if (typeof index === "number") {
|
|
2613
|
-
return index < context.length(objectId);
|
|
2614
|
-
}
|
|
2615
|
-
return index === "length";
|
|
2616
|
-
},
|
|
2617
|
-
getOwnPropertyDescriptor(target, index) {
|
|
2618
|
-
const { context, objectId } = target;
|
|
2619
|
-
if (index === "length")
|
|
2620
|
-
return { writable: true, value: context.length(objectId) };
|
|
2621
|
-
if (index === OBJECT_ID)
|
|
2622
|
-
return { configurable: false, enumerable: false, value: objectId };
|
|
2623
|
-
index = parseListIndex(index);
|
|
2624
|
-
const value = valueAt(target, index);
|
|
2625
|
-
return { configurable: true, enumerable: true, value };
|
|
2626
|
-
},
|
|
2627
|
-
getPrototypeOf(target) {
|
|
2628
|
-
return Object.getPrototypeOf(target);
|
|
2629
|
-
},
|
|
2630
|
-
ownKeys( /*target*/) {
|
|
2631
|
-
const keys = [];
|
|
2632
|
-
// uncommenting this causes assert.deepEqual() to fail when comparing to a pojo array
|
|
2633
|
-
// but not uncommenting it causes for (i in list) {} to not enumerate values properly
|
|
2634
|
-
//const {context, objectId } = target
|
|
2635
|
-
//for (let i = 0; i < target.context.length(objectId); i++) { keys.push(i.toString()) }
|
|
2636
|
-
keys.push("length");
|
|
2637
|
-
return keys;
|
|
2638
|
-
},
|
|
2639
|
-
};
|
|
2640
|
-
Object.assign({}, ListHandler, {
|
|
2641
|
-
get(target, index) {
|
|
2642
|
-
const { context, objectId } = target;
|
|
2643
|
-
index = parseListIndex(index);
|
|
2644
|
-
if (index === Symbol.hasInstance) {
|
|
2645
|
-
return (instance) => {
|
|
2646
|
-
return Array.isArray(instance);
|
|
2647
|
-
};
|
|
2648
|
-
}
|
|
2649
|
-
if (index === Symbol.toStringTag) {
|
|
2650
|
-
return target[Symbol.toStringTag];
|
|
2651
|
-
}
|
|
2652
|
-
if (index === OBJECT_ID)
|
|
2653
|
-
return objectId;
|
|
2654
|
-
if (index === IS_PROXY)
|
|
2655
|
-
return true;
|
|
2656
|
-
if (index === TRACE)
|
|
2657
|
-
return target.trace;
|
|
2658
|
-
if (index === STATE)
|
|
2659
|
-
return { handle: context };
|
|
2660
|
-
if (index === "length")
|
|
2661
|
-
return context.length(objectId);
|
|
2662
|
-
if (typeof index === "number") {
|
|
2663
|
-
return valueAt(target, index);
|
|
2664
|
-
}
|
|
2665
|
-
else {
|
|
2666
|
-
return textMethods(target)[index] || listMethods(target)[index];
|
|
2667
|
-
}
|
|
2668
|
-
},
|
|
2669
|
-
getPrototypeOf( /*target*/) {
|
|
2670
|
-
return Object.getPrototypeOf(new Text());
|
|
2671
|
-
},
|
|
2672
|
-
});
|
|
2673
|
-
function mapProxy(context, objectId, path) {
|
|
2674
|
-
const target = {
|
|
2675
|
-
context,
|
|
2676
|
-
objectId,
|
|
2677
|
-
path: path || [],
|
|
2678
|
-
cache: {},
|
|
2679
|
-
};
|
|
2680
|
-
const proxied = {};
|
|
2681
|
-
Object.assign(proxied, target);
|
|
2682
|
-
const result = new Proxy(proxied, MapHandler);
|
|
2683
|
-
// conversion through unknown is necessary because the types are so different
|
|
2684
|
-
return result;
|
|
2685
|
-
}
|
|
2686
|
-
function listProxy(context, objectId, path) {
|
|
2687
|
-
const target = {
|
|
2688
|
-
context,
|
|
2689
|
-
objectId,
|
|
2690
|
-
path: path || [],
|
|
2691
|
-
cache: {},
|
|
2692
|
-
};
|
|
2693
|
-
const proxied = [];
|
|
2694
|
-
Object.assign(proxied, target);
|
|
2695
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2696
|
-
// @ts-ignore
|
|
2697
|
-
return new Proxy(proxied, ListHandler);
|
|
2698
|
-
}
|
|
2699
|
-
function listMethods(target) {
|
|
2700
|
-
const { context, objectId, path } = target;
|
|
2701
|
-
const methods = {
|
|
2702
|
-
at(index) {
|
|
2703
|
-
return valueAt(target, index);
|
|
2704
|
-
},
|
|
2705
|
-
deleteAt(index, numDelete) {
|
|
2706
|
-
if (typeof numDelete === "number") {
|
|
2707
|
-
context.splice(objectId, index, numDelete);
|
|
2708
|
-
}
|
|
2709
|
-
else {
|
|
2710
|
-
context.delete(objectId, index);
|
|
2711
|
-
}
|
|
2712
|
-
return this;
|
|
2713
|
-
},
|
|
2714
|
-
fill(val, start, end) {
|
|
2715
|
-
const [value, datatype] = import_value(val, [...path, start], context);
|
|
2716
|
-
const length = context.length(objectId);
|
|
2717
|
-
start = parseListIndex(start || 0);
|
|
2718
|
-
end = parseListIndex(end || length);
|
|
2719
|
-
for (let i = start; i < Math.min(end, length); i++) {
|
|
2720
|
-
if (datatype === "list" || datatype === "map") {
|
|
2721
|
-
context.putObject(objectId, i, value);
|
|
2722
|
-
}
|
|
2723
|
-
else if (datatype === "text") {
|
|
2724
|
-
context.putObject(objectId, i, value);
|
|
2725
|
-
}
|
|
2726
|
-
else {
|
|
2727
|
-
context.put(objectId, i, value, datatype);
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
return this;
|
|
2731
|
-
},
|
|
2732
|
-
indexOf(searchElement, start = 0) {
|
|
2733
|
-
const length = context.length(objectId);
|
|
2734
|
-
for (let i = start; i < length; i++) {
|
|
2735
|
-
const valueWithType = context.getWithType(objectId, i);
|
|
2736
|
-
if (!valueWithType) {
|
|
2737
|
-
continue;
|
|
2738
|
-
}
|
|
2739
|
-
const [valType, value] = valueWithType;
|
|
2740
|
-
// Either the target element is an object, and we return if we have found
|
|
2741
|
-
// the same object or it is a primitive value and we return if it matches
|
|
2742
|
-
// the current value
|
|
2743
|
-
const isObject = ["map", "list", "text"].includes(valType);
|
|
2744
|
-
if (!isObject) {
|
|
2745
|
-
// If the element is not an object, then check if the value is equal to the target
|
|
2746
|
-
if (value === searchElement) {
|
|
2747
|
-
return i;
|
|
2748
|
-
}
|
|
2749
|
-
else {
|
|
2750
|
-
continue;
|
|
2751
|
-
}
|
|
2752
|
-
}
|
|
2753
|
-
// if it's an object, but the type of the search element is a string, then we
|
|
2754
|
-
// need to check if the object is a text object with the same value as the search element
|
|
2755
|
-
if (valType === "text" && typeof searchElement === "string") {
|
|
2756
|
-
if (searchElement === valueAt(target, i)) {
|
|
2757
|
-
return i;
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
// The only possible match now is if the searchElement is an object already in the
|
|
2761
|
-
// automerge document with the same object ID as the value
|
|
2762
|
-
if (searchElement[OBJECT_ID] === value) {
|
|
2763
|
-
return i;
|
|
2764
|
-
}
|
|
2765
|
-
}
|
|
2766
|
-
return -1;
|
|
2767
|
-
},
|
|
2768
|
-
insertAt(index, ...values) {
|
|
2769
|
-
this.splice(index, 0, ...values);
|
|
2770
|
-
return this;
|
|
2771
|
-
},
|
|
2772
|
-
pop() {
|
|
2773
|
-
const length = context.length(objectId);
|
|
2774
|
-
if (length == 0) {
|
|
2775
|
-
return undefined;
|
|
2776
|
-
}
|
|
2777
|
-
const last = valueAt(target, length - 1);
|
|
2778
|
-
context.delete(objectId, length - 1);
|
|
2779
|
-
return last;
|
|
2780
|
-
},
|
|
2781
|
-
push(...values) {
|
|
2782
|
-
const len = context.length(objectId);
|
|
2783
|
-
this.splice(len, 0, ...values);
|
|
2784
|
-
return context.length(objectId);
|
|
2785
|
-
},
|
|
2786
|
-
shift() {
|
|
2787
|
-
if (context.length(objectId) == 0)
|
|
2788
|
-
return;
|
|
2789
|
-
const first = valueAt(target, 0);
|
|
2790
|
-
context.delete(objectId, 0);
|
|
2791
|
-
return first;
|
|
2792
|
-
},
|
|
2793
|
-
splice(index, del, ...vals) {
|
|
2794
|
-
index = parseListIndex(index);
|
|
2795
|
-
// if del is undefined, delete until the end of the list
|
|
2796
|
-
if (typeof del !== "number") {
|
|
2797
|
-
del = context.length(objectId) - index;
|
|
2798
|
-
}
|
|
2799
|
-
del = parseListIndex(del);
|
|
2800
|
-
for (const val of vals) {
|
|
2801
|
-
if (isSameDocument(val, context)) {
|
|
2802
|
-
throw new RangeError("Cannot create a reference to an existing document object");
|
|
2803
|
-
}
|
|
2804
|
-
}
|
|
2805
|
-
const result = [];
|
|
2806
|
-
for (let i = 0; i < del; i++) {
|
|
2807
|
-
const value = valueAt(target, index);
|
|
2808
|
-
if (value !== undefined) {
|
|
2809
|
-
result.push(value);
|
|
2810
|
-
}
|
|
2811
|
-
context.delete(objectId, index);
|
|
2812
|
-
}
|
|
2813
|
-
const values = vals.map((val, index) => {
|
|
2814
|
-
try {
|
|
2815
|
-
return import_value(val, [...path], context);
|
|
2816
|
-
}
|
|
2817
|
-
catch (e) {
|
|
2818
|
-
if (e instanceof RangeError) {
|
|
2819
|
-
throw new RangeError(`${e.message} (at index ${index} in the input)`);
|
|
2820
|
-
}
|
|
2821
|
-
else {
|
|
2822
|
-
throw e;
|
|
2823
|
-
}
|
|
2824
|
-
}
|
|
2825
|
-
});
|
|
2826
|
-
for (const [value, datatype] of values) {
|
|
2827
|
-
switch (datatype) {
|
|
2828
|
-
case "list": {
|
|
2829
|
-
const list = context.insertObject(objectId, index, []);
|
|
2830
|
-
const proxyList = listProxy(context, list, [...path, index]);
|
|
2831
|
-
proxyList.splice(0, 0, ...value);
|
|
2832
|
-
break;
|
|
2833
|
-
}
|
|
2834
|
-
case "text": {
|
|
2835
|
-
context.insertObject(objectId, index, value);
|
|
2836
|
-
break;
|
|
2837
|
-
}
|
|
2838
|
-
case "map": {
|
|
2839
|
-
const map = context.insertObject(objectId, index, {});
|
|
2840
|
-
const proxyMap = mapProxy(context, map, [...path, index]);
|
|
2841
|
-
for (const key in value) {
|
|
2842
|
-
proxyMap[key] = value[key];
|
|
2843
|
-
}
|
|
2844
|
-
break;
|
|
2845
|
-
}
|
|
2846
|
-
default:
|
|
2847
|
-
context.insert(objectId, index, value, datatype);
|
|
2848
|
-
}
|
|
2849
|
-
index += 1;
|
|
2850
|
-
}
|
|
2851
|
-
return result;
|
|
2852
|
-
},
|
|
2853
|
-
unshift(...values) {
|
|
2854
|
-
this.splice(0, 0, ...values);
|
|
2855
|
-
return context.length(objectId);
|
|
2856
|
-
},
|
|
2857
|
-
entries() {
|
|
2858
|
-
let i = 0;
|
|
2859
|
-
const iterator = {
|
|
2860
|
-
next: () => {
|
|
2861
|
-
const value = valueAt(target, i);
|
|
2862
|
-
if (value === undefined) {
|
|
2863
|
-
return { value: undefined, done: true };
|
|
2864
|
-
}
|
|
2865
|
-
else {
|
|
2866
|
-
return { value: [i++, value], done: false };
|
|
2867
|
-
}
|
|
2868
|
-
},
|
|
2869
|
-
[Symbol.iterator]() {
|
|
2870
|
-
return this;
|
|
2871
|
-
},
|
|
2872
|
-
};
|
|
2873
|
-
return iterator;
|
|
2874
|
-
},
|
|
2875
|
-
keys() {
|
|
2876
|
-
let i = 0;
|
|
2877
|
-
const len = context.length(objectId);
|
|
2878
|
-
const iterator = {
|
|
2879
|
-
next: () => {
|
|
2880
|
-
if (i < len) {
|
|
2881
|
-
return { value: i++, done: false };
|
|
2882
|
-
}
|
|
2883
|
-
return { value: undefined, done: true };
|
|
2884
|
-
},
|
|
2885
|
-
[Symbol.iterator]() {
|
|
2886
|
-
return this;
|
|
2887
|
-
},
|
|
2888
|
-
};
|
|
2889
|
-
return iterator;
|
|
2890
|
-
},
|
|
2891
|
-
values() {
|
|
2892
|
-
let i = 0;
|
|
2893
|
-
const iterator = {
|
|
2894
|
-
next: () => {
|
|
2895
|
-
const value = valueAt(target, i++);
|
|
2896
|
-
if (value === undefined) {
|
|
2897
|
-
return { value: undefined, done: true };
|
|
2898
|
-
}
|
|
2899
|
-
else {
|
|
2900
|
-
return { value, done: false };
|
|
2901
|
-
}
|
|
2902
|
-
},
|
|
2903
|
-
[Symbol.iterator]() {
|
|
2904
|
-
return this;
|
|
2905
|
-
},
|
|
2906
|
-
};
|
|
2907
|
-
return iterator;
|
|
2908
|
-
},
|
|
2909
|
-
toArray() {
|
|
2910
|
-
const list = [];
|
|
2911
|
-
let value;
|
|
2912
|
-
do {
|
|
2913
|
-
value = valueAt(target, list.length);
|
|
2914
|
-
if (value !== undefined) {
|
|
2915
|
-
list.push(value);
|
|
2916
|
-
}
|
|
2917
|
-
} while (value !== undefined);
|
|
2918
|
-
return list;
|
|
2919
|
-
},
|
|
2920
|
-
map(f) {
|
|
2921
|
-
return this.toArray().map(f);
|
|
2922
|
-
},
|
|
2923
|
-
toString() {
|
|
2924
|
-
return this.toArray().toString();
|
|
2925
|
-
},
|
|
2926
|
-
toLocaleString() {
|
|
2927
|
-
return this.toArray().toLocaleString();
|
|
2928
|
-
},
|
|
2929
|
-
forEach(f) {
|
|
2930
|
-
return this.toArray().forEach(f);
|
|
2931
|
-
},
|
|
2932
|
-
// todo: real concat function is different
|
|
2933
|
-
concat(other) {
|
|
2934
|
-
return this.toArray().concat(other);
|
|
2935
|
-
},
|
|
2936
|
-
every(f) {
|
|
2937
|
-
return this.toArray().every(f);
|
|
2938
|
-
},
|
|
2939
|
-
filter(f) {
|
|
2940
|
-
return this.toArray().filter(f);
|
|
2941
|
-
},
|
|
2942
|
-
find(f) {
|
|
2943
|
-
let index = 0;
|
|
2944
|
-
for (const v of this) {
|
|
2945
|
-
if (f(v, index)) {
|
|
2946
|
-
return v;
|
|
2947
|
-
}
|
|
2948
|
-
index += 1;
|
|
2949
|
-
}
|
|
2950
|
-
},
|
|
2951
|
-
findIndex(f) {
|
|
2952
|
-
let index = 0;
|
|
2953
|
-
for (const v of this) {
|
|
2954
|
-
if (f(v, index)) {
|
|
2955
|
-
return index;
|
|
2956
|
-
}
|
|
2957
|
-
index += 1;
|
|
2958
|
-
}
|
|
2959
|
-
return -1;
|
|
2960
|
-
},
|
|
2961
|
-
includes(elem) {
|
|
2962
|
-
return this.find(e => e === elem) !== undefined;
|
|
2963
|
-
},
|
|
2964
|
-
join(sep) {
|
|
2965
|
-
return this.toArray().join(sep);
|
|
2966
|
-
},
|
|
2967
|
-
reduce(f, initialValue) {
|
|
2968
|
-
return this.toArray().reduce(f, initialValue);
|
|
2969
|
-
},
|
|
2970
|
-
reduceRight(f, initialValue) {
|
|
2971
|
-
return this.toArray().reduceRight(f, initialValue);
|
|
2972
|
-
},
|
|
2973
|
-
lastIndexOf(search, fromIndex = +Infinity) {
|
|
2974
|
-
// this can be faster
|
|
2975
|
-
return this.toArray().lastIndexOf(search, fromIndex);
|
|
2976
|
-
},
|
|
2977
|
-
slice(index, num) {
|
|
2978
|
-
return this.toArray().slice(index, num);
|
|
2979
|
-
},
|
|
2980
|
-
some(f) {
|
|
2981
|
-
let index = 0;
|
|
2982
|
-
for (const v of this) {
|
|
2983
|
-
if (f(v, index)) {
|
|
2984
|
-
return true;
|
|
2985
|
-
}
|
|
2986
|
-
index += 1;
|
|
2987
|
-
}
|
|
2988
|
-
return false;
|
|
2989
|
-
},
|
|
2990
|
-
[Symbol.iterator]: function* () {
|
|
2991
|
-
let i = 0;
|
|
2992
|
-
let value = valueAt(target, i);
|
|
2993
|
-
while (value !== undefined) {
|
|
2994
|
-
yield value;
|
|
2995
|
-
i += 1;
|
|
2996
|
-
value = valueAt(target, i);
|
|
2997
|
-
}
|
|
2998
|
-
},
|
|
2999
|
-
};
|
|
3000
|
-
return methods;
|
|
3001
|
-
}
|
|
3002
|
-
function textMethods(target) {
|
|
3003
|
-
const { context, objectId } = target;
|
|
3004
|
-
const methods = {
|
|
3005
|
-
set(index, value) {
|
|
3006
|
-
return (this[index] = value);
|
|
3007
|
-
},
|
|
3008
|
-
get(index) {
|
|
3009
|
-
return this[index];
|
|
3010
|
-
},
|
|
3011
|
-
toString() {
|
|
3012
|
-
return context.text(objectId).replace(//g, "");
|
|
3013
|
-
},
|
|
3014
|
-
toSpans() {
|
|
3015
|
-
const spans = [];
|
|
3016
|
-
let chars = "";
|
|
3017
|
-
const length = context.length(objectId);
|
|
3018
|
-
for (let i = 0; i < length; i++) {
|
|
3019
|
-
const value = this[i];
|
|
3020
|
-
if (typeof value === "string") {
|
|
3021
|
-
chars += value;
|
|
3022
|
-
}
|
|
3023
|
-
else {
|
|
3024
|
-
if (chars.length > 0) {
|
|
3025
|
-
spans.push(chars);
|
|
3026
|
-
chars = "";
|
|
3027
|
-
}
|
|
3028
|
-
spans.push(value);
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
if (chars.length > 0) {
|
|
3032
|
-
spans.push(chars);
|
|
3033
|
-
}
|
|
3034
|
-
return spans;
|
|
3035
|
-
},
|
|
3036
|
-
toJSON() {
|
|
3037
|
-
return this.toString();
|
|
3038
|
-
},
|
|
3039
|
-
indexOf(o, start = 0) {
|
|
3040
|
-
const text = context.text(objectId);
|
|
3041
|
-
return text.indexOf(o, start);
|
|
3042
|
-
},
|
|
3043
|
-
insertAt(index, ...values) {
|
|
3044
|
-
if (values.every(v => typeof v === "string")) {
|
|
3045
|
-
context.splice(objectId, index, 0, values.join(""));
|
|
3046
|
-
}
|
|
3047
|
-
else {
|
|
3048
|
-
listMethods(target).insertAt(index, ...values);
|
|
3049
|
-
}
|
|
3050
|
-
},
|
|
3051
|
-
};
|
|
3052
|
-
return methods;
|
|
3053
|
-
}
|
|
3054
|
-
function printPath(path) {
|
|
3055
|
-
// print the path as a json pointer
|
|
3056
|
-
const jsonPointerComponents = path.map(component => {
|
|
3057
|
-
// if its a number just turn it into a string
|
|
3058
|
-
if (typeof component === "number") {
|
|
3059
|
-
return component.toString();
|
|
3060
|
-
}
|
|
3061
|
-
else if (typeof component === "string") {
|
|
3062
|
-
// otherwise we have to escape `/` and `~` characters
|
|
3063
|
-
return component.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
3064
|
-
}
|
|
3065
|
-
});
|
|
3066
|
-
if (path.length === 0) {
|
|
3067
|
-
return "";
|
|
3068
|
-
}
|
|
3069
|
-
else {
|
|
3070
|
-
return "/" + jsonPointerComponents.join("/");
|
|
3071
|
-
}
|
|
3072
|
-
}
|
|
3073
|
-
/*
|
|
3074
|
-
* Check if an object is a {@link ImmutableString}
|
|
3075
|
-
*/
|
|
3076
|
-
function isImmutableString(obj) {
|
|
3077
|
-
// We used to determine whether something was a ImmutableString by doing an instanceof check, but
|
|
3078
|
-
// this doesn't work if the automerge module is loaded twice somehow. Instead, use the presence
|
|
3079
|
-
// of a symbol to determine if something is a ImmutableString
|
|
3080
|
-
return (typeof obj === "object" &&
|
|
3081
|
-
obj !== null &&
|
|
3082
|
-
Object.prototype.hasOwnProperty.call(obj, IMMUTABLE_STRING));
|
|
3083
|
-
}
|
|
3084
|
-
|
|
3085
|
-
let wasm;
|
|
3086
|
-
|
|
3087
|
-
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
|
3088
|
-
|
|
3089
|
-
(typeof cachedTextEncoder.encodeInto === 'function'
|
|
3090
|
-
? function (arg, view) {
|
|
3091
|
-
return cachedTextEncoder.encodeInto(arg, view);
|
|
3092
|
-
}
|
|
3093
|
-
: function (arg, view) {
|
|
3094
|
-
const buf = cachedTextEncoder.encode(arg);
|
|
3095
|
-
view.set(buf);
|
|
3096
|
-
return {
|
|
3097
|
-
read: arg.length,
|
|
3098
|
-
written: buf.length
|
|
3099
|
-
};
|
|
3100
|
-
});
|
|
3101
|
-
|
|
3102
|
-
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
|
3103
|
-
|
|
3104
|
-
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }
|
|
3105
|
-
(typeof FinalizationRegistry === 'undefined')
|
|
3106
|
-
? { }
|
|
3107
|
-
: new FinalizationRegistry(ptr => wasm.__wbg_automerge_free(ptr >>> 0, 1));
|
|
3108
|
-
|
|
3109
|
-
(typeof FinalizationRegistry === 'undefined')
|
|
3110
|
-
? { }
|
|
3111
|
-
: new FinalizationRegistry(ptr => wasm.__wbg_syncstate_free(ptr >>> 0, 1));
|
|
2245
|
+
if (Symbol.dispose) SyncState.prototype[Symbol.dispose] = SyncState.prototype.free;
|
|
3112
2246
|
|
|
3113
2247
|
(undefined && undefined.__rest) || function (s, e) {
|
|
3114
2248
|
var t = {};
|
|
@@ -6241,13 +5375,6 @@ const REUSE_BUFFER_MODE = 512;
|
|
|
6241
5375
|
const RESET_BUFFER_MODE = 1024;
|
|
6242
5376
|
const THROW_ON_ITERABLE = 2048;
|
|
6243
5377
|
|
|
6244
|
-
/**
|
|
6245
|
-
* FinalizationRegistry for automatic cleanup of Ref instances.
|
|
6246
|
-
* This ensures subscriptions are cleaned up when Refs are garbage collected,
|
|
6247
|
-
* even if dispose() is never called.
|
|
6248
|
-
*/
|
|
6249
|
-
new FinalizationRegistry(cleanup => cleanup());
|
|
6250
|
-
|
|
6251
5378
|
var sha256$1 = {exports: {}};
|
|
6252
5379
|
|
|
6253
5380
|
var sha256 = sha256$1.exports;
|
|
@@ -6758,7 +5885,7 @@ class PeerStateView {
|
|
|
6758
5885
|
getLastSeenPeer(peers) {
|
|
6759
5886
|
let freshestLastSeenAt;
|
|
6760
5887
|
return peers.reduce((freshest, curr) => {
|
|
6761
|
-
const lastSeenAt = this.value[curr]?.
|
|
5888
|
+
const lastSeenAt = this.value[curr]?.lastActiveAt;
|
|
6762
5889
|
if (!lastSeenAt) {
|
|
6763
5890
|
return freshest;
|
|
6764
5891
|
}
|
|
@@ -6848,15 +5975,11 @@ class PeerPresenceInfo {
|
|
|
6848
5975
|
* @param peerId
|
|
6849
5976
|
*/
|
|
6850
5977
|
markSeen(peerId) {
|
|
6851
|
-
if (!(peerId in this.#peerStates.value)) {
|
|
6852
|
-
// Ignore heartbeats from peers we have not seen before: they will send a snapshot
|
|
6853
|
-
return;
|
|
6854
|
-
}
|
|
6855
5978
|
this.#peerStates = new PeerStateView({
|
|
6856
5979
|
...this.#peerStates.value,
|
|
6857
5980
|
[peerId]: {
|
|
6858
5981
|
...this.#peerStates.value[peerId],
|
|
6859
|
-
|
|
5982
|
+
lastSeen: Date.now(),
|
|
6860
5983
|
},
|
|
6861
5984
|
});
|
|
6862
5985
|
}
|
|
@@ -6878,7 +6001,7 @@ class PeerPresenceInfo {
|
|
|
6878
6001
|
deviceId,
|
|
6879
6002
|
userId,
|
|
6880
6003
|
lastActiveAt: now,
|
|
6881
|
-
|
|
6004
|
+
lastUpdateAt: now,
|
|
6882
6005
|
value: {
|
|
6883
6006
|
...existingState,
|
|
6884
6007
|
...value,
|
|
@@ -6902,15 +6025,9 @@ class PeerPresenceInfo {
|
|
|
6902
6025
|
*/
|
|
6903
6026
|
prune() {
|
|
6904
6027
|
const threshold = Date.now() - this.ttl;
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
const keep = state.lastSeenAt >= threshold;
|
|
6908
|
-
if (!keep) {
|
|
6909
|
-
pruned.push(id);
|
|
6910
|
-
}
|
|
6911
|
-
return keep;
|
|
6028
|
+
this.#peerStates = new PeerStateView(Object.fromEntries(Object.entries(this.#peerStates).filter(([, state]) => {
|
|
6029
|
+
return state.lastActiveAt >= threshold;
|
|
6912
6030
|
})));
|
|
6913
|
-
return pruned;
|
|
6914
6031
|
}
|
|
6915
6032
|
/**
|
|
6916
6033
|
* Get a snapshot of the current peer states
|
|
@@ -7151,10 +6268,7 @@ class Presence extends EventEmitter {
|
|
|
7151
6268
|
// to minimize variance between peer expiration, since the heartbeat frequency
|
|
7152
6269
|
// is expected to be several times higher.
|
|
7153
6270
|
this.#pruningInterval = setInterval(() => {
|
|
7154
|
-
|
|
7155
|
-
if (pruned.length > 0) {
|
|
7156
|
-
this.emit("pruning", { pruned });
|
|
7157
|
-
}
|
|
6271
|
+
this.#peers.prune();
|
|
7158
6272
|
}, this.#heartbeatMs);
|
|
7159
6273
|
}
|
|
7160
6274
|
stopPruningPeers() {
|
|
@@ -7193,26 +6307,10 @@ function usePresence({
|
|
|
7193
6307
|
presence.on("snapshot", () => setPeerStates(presence.getPeerStates()));
|
|
7194
6308
|
presence.on("update", () => setPeerStates(presence.getPeerStates()));
|
|
7195
6309
|
presence.on("goodbye", () => setPeerStates(presence.getPeerStates()));
|
|
7196
|
-
presence.on("pruning", () => setPeerStates(presence.getPeerStates()));
|
|
7197
6310
|
return () => {
|
|
7198
6311
|
presence.stop();
|
|
7199
6312
|
};
|
|
7200
6313
|
}, [presence, userId, deviceId, firstInitialState, firstOpts]);
|
|
7201
|
-
const start = useCallback(
|
|
7202
|
-
(config) => {
|
|
7203
|
-
const initialState2 = config?.initialState ?? presence.getLocalState();
|
|
7204
|
-
const opts = {
|
|
7205
|
-
...firstOpts.current,
|
|
7206
|
-
...config,
|
|
7207
|
-
initialState: initialState2
|
|
7208
|
-
};
|
|
7209
|
-
presence.start(opts);
|
|
7210
|
-
},
|
|
7211
|
-
[presence, firstOpts]
|
|
7212
|
-
);
|
|
7213
|
-
const stop = useCallback(() => {
|
|
7214
|
-
presence.stop();
|
|
7215
|
-
}, [presence]);
|
|
7216
6314
|
const update = useCallback(
|
|
7217
6315
|
(channel, msg) => {
|
|
7218
6316
|
presence.broadcast(channel, msg);
|
|
@@ -7224,9 +6322,7 @@ function usePresence({
|
|
|
7224
6322
|
return {
|
|
7225
6323
|
peerStates,
|
|
7226
6324
|
localState,
|
|
7227
|
-
update
|
|
7228
|
-
start,
|
|
7229
|
-
stop
|
|
6325
|
+
update
|
|
7230
6326
|
};
|
|
7231
6327
|
}
|
|
7232
6328
|
|