change MAP,LIST,TEXT to be {},[],'' - allow recursion
This commit is contained in:
parent
b96aa168b4
commit
2fc0705907
7 changed files with 159 additions and 96 deletions
automerge-js/src
automerge-wasm
edit-trace
|
@ -4,7 +4,6 @@ const { Int, Uint, Float64 } = require("./numbers");
|
|||
const { Counter, getWriteableCounter } = require("./counter");
|
||||
const { Text } = require("./text");
|
||||
const { STATE, HEADS, FROZEN, OBJECT_ID, READ_ONLY } = require("./constants")
|
||||
const { MAP, LIST, TABLE, TEXT } = require("automerge-wasm")
|
||||
|
||||
function parseListIndex(key) {
|
||||
if (typeof key === 'string' && /^[0-9]+$/.test(key)) key = parseInt(key, 10)
|
||||
|
@ -135,21 +134,21 @@ const MapHandler = {
|
|||
}
|
||||
switch (datatype) {
|
||||
case "list":
|
||||
const list = context.set(objectId, key, LIST)
|
||||
const list = context.set(objectId, key, [])
|
||||
const proxyList = listProxy(context, list, [ ... path, key ], readonly );
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
proxyList[i] = value[i]
|
||||
}
|
||||
break;
|
||||
case "text":
|
||||
const text = context.set(objectId, key, TEXT)
|
||||
const text = context.set(objectId, key, "", "text")
|
||||
const proxyText = textProxy(context, text, [ ... path, key ], readonly );
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
proxyText[i] = value.get(i)
|
||||
}
|
||||
break;
|
||||
case "map":
|
||||
const map = context.set(objectId, key, MAP)
|
||||
const map = context.set(objectId, key, {})
|
||||
const proxyMap = mapProxy(context, map, [ ... path, key ], readonly );
|
||||
for (const key in value) {
|
||||
proxyMap[key] = value[key]
|
||||
|
@ -252,9 +251,9 @@ const ListHandler = {
|
|||
case "list":
|
||||
let list
|
||||
if (index >= context.length(objectId)) {
|
||||
list = context.insert(objectId, index, LIST)
|
||||
list = context.insert(objectId, index, [])
|
||||
} else {
|
||||
list = context.set(objectId, index, LIST)
|
||||
list = context.set(objectId, index, [])
|
||||
}
|
||||
const proxyList = listProxy(context, list, [ ... path, index ], readonly);
|
||||
proxyList.splice(0,0,...value)
|
||||
|
@ -262,9 +261,9 @@ const ListHandler = {
|
|||
case "text":
|
||||
let text
|
||||
if (index >= context.length(objectId)) {
|
||||
text = context.insert(objectId, index, TEXT)
|
||||
text = context.insert(objectId, index, "", "text")
|
||||
} else {
|
||||
text = context.set(objectId, index, TEXT)
|
||||
text = context.set(objectId, index, "", "text")
|
||||
}
|
||||
const proxyText = textProxy(context, text, [ ... path, index ], readonly);
|
||||
proxyText.splice(0,0,...value)
|
||||
|
@ -272,9 +271,9 @@ const ListHandler = {
|
|||
case "map":
|
||||
let map
|
||||
if (index >= context.length(objectId)) {
|
||||
map = context.insert(objectId, index, MAP)
|
||||
map = context.insert(objectId, index, {})
|
||||
} else {
|
||||
map = context.set(objectId, index, MAP)
|
||||
map = context.set(objectId, index, {})
|
||||
}
|
||||
const proxyMap = mapProxy(context, map, [ ... path, index ], readonly);
|
||||
for (const key in value) {
|
||||
|
@ -479,17 +478,17 @@ function listMethods(target) {
|
|||
for (let [value,datatype] of values) {
|
||||
switch (datatype) {
|
||||
case "list":
|
||||
const list = context.insert(objectId, index, LIST)
|
||||
const list = context.insert(objectId, index, [])
|
||||
const proxyList = listProxy(context, list, [ ... path, index ], readonly);
|
||||
proxyList.splice(0,0,...value)
|
||||
break;
|
||||
case "text":
|
||||
const text = context.insert(objectId, index, TEXT)
|
||||
const text = context.insert(objectId, index, "", "text")
|
||||
const proxyText = textProxy(context, text, [ ... path, index ], readonly);
|
||||
proxyText.splice(0,0,...value)
|
||||
break;
|
||||
case "map":
|
||||
const map = context.insert(objectId, index, MAP)
|
||||
const map = context.insert(objectId, index, {})
|
||||
const proxyMap = mapProxy(context, map, [ ... path, index ], readonly);
|
||||
for (const key in value) {
|
||||
proxyMap[key] = value[key]
|
||||
|
|
17
automerge-wasm/index.d.ts
vendored
17
automerge-wasm/index.d.ts
vendored
|
@ -6,8 +6,7 @@ export type SyncMessage = Uint8Array;
|
|||
export type Prop = string | number;
|
||||
export type Hash = string;
|
||||
export type Heads = Hash[];
|
||||
export type ObjectType = string; // opaque ??
|
||||
export type Value = string | number | boolean | null | Date | Uint8Array | ObjectType;
|
||||
export type Value = string | number | boolean | null | Date | Uint8Array | Array | Object;
|
||||
export type FullValue =
|
||||
["str", string] |
|
||||
["int", number] |
|
||||
|
@ -23,11 +22,6 @@ export type FullValue =
|
|||
["text", ObjID] |
|
||||
["table", ObjID]
|
||||
|
||||
export const LIST : ObjectType;
|
||||
export const MAP : ObjectType;
|
||||
export const TABLE : ObjectType;
|
||||
export const TEXT : ObjectType;
|
||||
|
||||
export enum ObjTypeName {
|
||||
list = "list",
|
||||
map = "map",
|
||||
|
@ -44,7 +38,10 @@ export type Datatype =
|
|||
"null" |
|
||||
"timestamp" |
|
||||
"counter" |
|
||||
"bytes";
|
||||
"bytes" |
|
||||
"map" |
|
||||
"text" |
|
||||
"list";
|
||||
|
||||
export type DecodedSyncMessage = {
|
||||
heads: Heads,
|
||||
|
@ -86,10 +83,10 @@ export function decodeSyncState(data: Uint8Array): SyncState;
|
|||
export class Automerge {
|
||||
// change state
|
||||
set(obj: ObjID, prop: Prop, value: Value, datatype?: Datatype): ObjID | undefined;
|
||||
make(obj: ObjID, prop: Prop, value: ObjectType): ObjID;
|
||||
make(obj: ObjID, prop: Prop, value: Value, datatype?: Datatype): ObjID;
|
||||
insert(obj: ObjID, index: number, value: Value, datatype?: Datatype): ObjID | undefined;
|
||||
push(obj: ObjID, value: Value, datatype?: Datatype): ObjID | undefined;
|
||||
splice(obj: ObjID, start: number, delete_count: number, text?: string | Array<Value | FullValue>): ObjID[] | undefined;
|
||||
splice(obj: ObjID, start: number, delete_count: number, text?: string | Array<Value>): ObjID[] | undefined;
|
||||
inc(obj: ObjID, prop: Prop, value: number): void;
|
||||
del(obj: ObjID, prop: Prop): void;
|
||||
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
"main": "./dev/index.js",
|
||||
"scripts": {
|
||||
"build": "rimraf ./dev && wasm-pack build --target nodejs --dev --out-name index -d dev && cp index.d.ts dev",
|
||||
"release": "rimraf ./dev && wasm-pack build --target nodejs --release --out-name index -d dev && yarn opt && cp index.d.ts dev",
|
||||
"release": "rimraf ./dev && wasm-pack build --target nodejs --release --out-name index -d dev && cp index.d.ts dev",
|
||||
"pkg": "rimraf ./pkg && wasm-pack build --target web --release --out-name index -d pkg && cp index.d.ts pkg && cd pkg && yarn pack && mv automerge-wasm*tgz ..",
|
||||
"prof": "rimraf ./dev && wasm-pack build --target nodejs --profiling --out-name index -d dev",
|
||||
"opt": "wasm-opt -Oz dev/index_bg.wasm -o tmp.wasm && mv tmp.wasm dev/index_bg.wasm",
|
||||
"test": "yarn build && ts-mocha -p tsconfig.json --type-check --bail --full-trace test/*.ts"
|
||||
},
|
||||
"dependencies": {},
|
||||
|
|
|
@ -3,6 +3,7 @@ use automerge::{Change, ChangeHash, Prop};
|
|||
use js_sys::{Array, Object, Reflect, Uint8Array};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Display;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
|
@ -257,23 +258,60 @@ pub(crate) fn to_prop(p: JsValue) -> Result<Prop, JsValue> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_objtype(a: &JsValue) -> Option<am::ObjType> {
|
||||
if !a.is_function() {
|
||||
return None;
|
||||
}
|
||||
let f: js_sys::Function = a.clone().try_into().unwrap();
|
||||
let f = f.to_string();
|
||||
if f.starts_with("class MAP", 0) {
|
||||
Some(am::ObjType::Map)
|
||||
} else if f.starts_with("class LIST", 0) {
|
||||
Some(am::ObjType::List)
|
||||
} else if f.starts_with("class TEXT", 0) {
|
||||
Some(am::ObjType::Text)
|
||||
} else if f.starts_with("class TABLE", 0) {
|
||||
Some(am::ObjType::Table)
|
||||
} else {
|
||||
am::log!("to_objtype(function) -> {}", f);
|
||||
None
|
||||
pub(crate) fn to_objtype(
|
||||
value: &JsValue,
|
||||
datatype: &Option<String>,
|
||||
) -> Option<(am::ObjType, Vec<(Prop, JsValue)>)> {
|
||||
match datatype.as_deref() {
|
||||
Some("map") => {
|
||||
let map = value.clone().dyn_into::<js_sys::Object>().ok()?;
|
||||
// FIXME unwrap
|
||||
let map = js_sys::Object::keys(&map)
|
||||
.iter()
|
||||
.zip(js_sys::Object::values(&map).iter())
|
||||
.map(|(key, val)| (key.as_string().unwrap().into(), val))
|
||||
.collect();
|
||||
Some((am::ObjType::Map, map))
|
||||
}
|
||||
Some("list") => {
|
||||
let list = value.clone().dyn_into::<js_sys::Array>().ok()?;
|
||||
let list = list
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, e)| (i.into(), e))
|
||||
.collect();
|
||||
Some((am::ObjType::List, list))
|
||||
}
|
||||
Some("text") => {
|
||||
let text = value.as_string()?;
|
||||
let text = text
|
||||
.graphemes(true)
|
||||
.enumerate()
|
||||
.map(|(i, ch)| (i.into(), ch.into()))
|
||||
.collect();
|
||||
Some((am::ObjType::Text, text))
|
||||
}
|
||||
Some(_) => None,
|
||||
None => {
|
||||
if let Ok(list) = value.clone().dyn_into::<js_sys::Array>() {
|
||||
let list = list
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, e)| (i.into(), e))
|
||||
.collect();
|
||||
Some((am::ObjType::List, list))
|
||||
} else if let Ok(map) = value.clone().dyn_into::<js_sys::Object>() {
|
||||
// FIXME unwrap
|
||||
let map = js_sys::Object::keys(&map)
|
||||
.iter()
|
||||
.zip(js_sys::Object::values(&map).iter())
|
||||
.map(|(key, val)| (key.as_string().unwrap().into(), val))
|
||||
.collect();
|
||||
Some((am::ObjType::Map, map))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -131,15 +131,11 @@ impl Automerge {
|
|||
} else {
|
||||
if let Ok(array) = text.dyn_into::<Array>() {
|
||||
for i in array.iter() {
|
||||
if let Ok(array) = i.clone().dyn_into::<Array>() {
|
||||
let value = array.get(1);
|
||||
let datatype = array.get(2);
|
||||
let value = self.import_value(value, datatype)?;
|
||||
vals.push(value);
|
||||
} else {
|
||||
let value = self.import_value(i, JsValue::null())?;
|
||||
vals.push(value);
|
||||
let (value, subvals) = self.import_value(&i, None)?;
|
||||
if !subvals.is_empty() {
|
||||
return Err(to_js_err("splice must be shallow"));
|
||||
}
|
||||
vals.push(value);
|
||||
}
|
||||
}
|
||||
let result = self.0.splice(&obj, start, delete_count, vals)?;
|
||||
|
@ -162,9 +158,10 @@ impl Automerge {
|
|||
datatype: JsValue,
|
||||
) -> Result<Option<String>, JsValue> {
|
||||
let obj = self.import(obj)?;
|
||||
let value = self.import_value(value, datatype)?;
|
||||
let (value, subvals) = self.import_value(&value, datatype.as_string())?;
|
||||
let index = self.0.length(&obj);
|
||||
let opid = self.0.insert(&obj, index, value)?;
|
||||
self.subset(&opid, subvals)?;
|
||||
Ok(opid.map(|id| id.to_string()))
|
||||
}
|
||||
|
||||
|
@ -177,8 +174,9 @@ impl Automerge {
|
|||
) -> Result<Option<String>, JsValue> {
|
||||
let obj = self.import(obj)?;
|
||||
let index = index as f64;
|
||||
let value = self.import_value(value, datatype)?;
|
||||
let (value, subvals) = self.import_value(&value, datatype.as_string())?;
|
||||
let opid = self.0.insert(&obj, index as usize, value)?;
|
||||
self.subset(&opid, subvals)?;
|
||||
Ok(opid.map(|id| id.to_string()))
|
||||
}
|
||||
|
||||
|
@ -191,17 +189,44 @@ impl Automerge {
|
|||
) -> Result<JsValue, JsValue> {
|
||||
let obj = self.import(obj)?;
|
||||
let prop = self.import_prop(prop)?;
|
||||
let value = self.import_value(value, datatype)?;
|
||||
let (value, subvals) = self.import_value(&value, datatype.as_string())?;
|
||||
let opid = self.0.set(&obj, prop, value)?;
|
||||
self.subset(&opid, subvals)?;
|
||||
Ok(opid.map(|id| id.to_string()).into())
|
||||
}
|
||||
|
||||
pub fn make(&mut self, obj: JsValue, prop: JsValue, value: JsValue) -> Result<String, JsValue> {
|
||||
fn subset(
|
||||
&mut self,
|
||||
obj: &Option<am::ObjId>,
|
||||
vals: Vec<(am::Prop, JsValue)>,
|
||||
) -> Result<(), JsValue> {
|
||||
if let Some(id) = obj {
|
||||
for (p, v) in vals {
|
||||
let (value, subvals) = self.import_value(&v, None)?;
|
||||
//let opid = self.0.set(id, p, value)?;
|
||||
let opid = match p {
|
||||
Prop::Map(s) => self.0.set(id, s, value)?,
|
||||
Prop::Seq(i) => self.0.insert(id, i, value)?,
|
||||
};
|
||||
self.subset(&opid, subvals)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn make(
|
||||
&mut self,
|
||||
obj: JsValue,
|
||||
prop: JsValue,
|
||||
value: JsValue,
|
||||
datatype: JsValue,
|
||||
) -> Result<String, JsValue> {
|
||||
let obj = self.import(obj)?;
|
||||
let prop = self.import_prop(prop)?;
|
||||
let value = self.import_value(value, JsValue::null())?;
|
||||
let (value, subvals) = self.import_value(&value, datatype.as_string())?;
|
||||
if value.is_object() {
|
||||
let opid = self.0.set(&obj, prop, value)?;
|
||||
self.subset(&opid, subvals)?;
|
||||
Ok(opid.unwrap().to_string())
|
||||
} else {
|
||||
Err(to_js_err("invalid object type"))
|
||||
|
@ -480,15 +505,18 @@ impl Automerge {
|
|||
}
|
||||
}
|
||||
|
||||
fn import_value(&mut self, value: JsValue, datatype: JsValue) -> Result<Value, JsValue> {
|
||||
let d = datatype.as_string();
|
||||
match self.import_scalar(&value, &d) {
|
||||
Some(val) => Ok(val.into()),
|
||||
fn import_value(
|
||||
&mut self,
|
||||
value: &JsValue,
|
||||
datatype: Option<String>,
|
||||
) -> Result<(Value, Vec<(Prop, JsValue)>), JsValue> {
|
||||
match self.import_scalar(value, &datatype) {
|
||||
Some(val) => Ok((val.into(), vec![])),
|
||||
None => {
|
||||
if let Some(o) = to_objtype(&value) {
|
||||
Ok(o.into())
|
||||
if let Some((o, subvals)) = to_objtype(value, &datatype) {
|
||||
Ok((o.into(), subvals))
|
||||
} else {
|
||||
web_sys::console::log_3(&"Invalid value".into(), &value, &datatype);
|
||||
web_sys::console::log_2(&"Invalid value".into(), value);
|
||||
Err(to_js_err("invalid value"))
|
||||
}
|
||||
}
|
||||
|
@ -591,15 +619,3 @@ pub fn encode_sync_state(state: SyncState) -> Result<Uint8Array, JsValue> {
|
|||
pub fn decode_sync_state(data: Uint8Array) -> Result<SyncState, JsValue> {
|
||||
SyncState::decode(data)
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = MAP)]
|
||||
pub struct Map {}
|
||||
|
||||
#[wasm_bindgen(js_name = LIST)]
|
||||
pub struct List {}
|
||||
|
||||
#[wasm_bindgen(js_name = TEXT)]
|
||||
pub struct Text {}
|
||||
|
||||
#[wasm_bindgen(js_name = TABLE)]
|
||||
pub struct Table {}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { describe, it } from 'mocha';
|
|||
import assert from 'assert'
|
||||
//@ts-ignore
|
||||
import { BloomFilter } from './helpers/sync'
|
||||
import { create, loadDoc, SyncState, Automerge, MAP, LIST, TEXT, encodeChange, decodeChange, initSyncState, decodeSyncMessage, decodeSyncState, encodeSyncState, encodeSyncMessage } from '../dev/index'
|
||||
import { create, loadDoc, SyncState, Automerge, encodeChange, decodeChange, initSyncState, decodeSyncMessage, decodeSyncState, encodeSyncState, encodeSyncMessage } from '../dev/index'
|
||||
import { DecodedSyncMessage } from '../index';
|
||||
import { Hash } from '../dev/index';
|
||||
|
||||
|
@ -64,7 +64,7 @@ describe('Automerge', () => {
|
|||
doc.set(root, "bool", true)
|
||||
doc.set(root, "time1", 1000, "timestamp")
|
||||
doc.set(root, "time2", new Date(1001))
|
||||
doc.set(root, "list", LIST);
|
||||
doc.set(root, "list", []);
|
||||
doc.set(root, "null", null)
|
||||
|
||||
result = doc.value(root,"hello")
|
||||
|
@ -124,7 +124,7 @@ describe('Automerge', () => {
|
|||
let root = "_root"
|
||||
let result
|
||||
|
||||
let submap = doc.set(root, "submap", MAP)
|
||||
let submap = doc.set(root, "submap", {})
|
||||
if (!submap) throw new Error('should be not null')
|
||||
doc.set(submap, "number", 6, "uint")
|
||||
assert.strictEqual(doc.pendingOps(),2)
|
||||
|
@ -141,7 +141,7 @@ describe('Automerge', () => {
|
|||
let doc = create()
|
||||
let root = "_root"
|
||||
|
||||
let submap = doc.set(root, "numbers", LIST)
|
||||
let submap = doc.set(root, "numbers", [])
|
||||
if (!submap) throw new Error('should be not null')
|
||||
doc.insert(submap, 0, "a");
|
||||
doc.insert(submap, 1, "b");
|
||||
|
@ -165,7 +165,7 @@ describe('Automerge', () => {
|
|||
let doc = create()
|
||||
let root = "_root"
|
||||
|
||||
let submap = doc.set(root, "letters", LIST)
|
||||
let submap = doc.set(root, "letters", [])
|
||||
if (!submap) throw new Error('should be not null')
|
||||
doc.insert(submap, 0, "a");
|
||||
doc.insert(submap, 0, "b");
|
||||
|
@ -230,11 +230,11 @@ describe('Automerge', () => {
|
|||
let doc = create()
|
||||
let root = "_root";
|
||||
|
||||
let text = doc.set(root, "text", TEXT);
|
||||
let text = doc.set(root, "text", "", "text");
|
||||
if (!text) throw new Error('should not be undefined')
|
||||
doc.splice(text, 0, 0, "hello ")
|
||||
doc.splice(text, 6, 0, ["w","o","r","l","d"])
|
||||
doc.splice(text, 11, 0, [["str","!"],["str","?"]])
|
||||
doc.splice(text, 11, 0, ["!","?"])
|
||||
assert.deepEqual(doc.value(text, 0),["str","h"])
|
||||
assert.deepEqual(doc.value(text, 1),["str","e"])
|
||||
assert.deepEqual(doc.value(text, 9),["str","l"])
|
||||
|
@ -282,7 +282,7 @@ describe('Automerge', () => {
|
|||
|
||||
it('should be able to splice text', () => {
|
||||
let doc = create()
|
||||
let text = doc.set("_root", "text", TEXT);
|
||||
let text = doc.set("_root", "text", "", "text");
|
||||
if (!text) throw new Error('should not be undefined')
|
||||
doc.splice(text, 0, 0, "hello world");
|
||||
let heads1 = doc.commit();
|
||||
|
@ -331,7 +331,7 @@ describe('Automerge', () => {
|
|||
|
||||
it('local inc increments all visible counters in a sequence', () => {
|
||||
let doc1 = create("aaaa")
|
||||
let seq = doc1.set("_root", "seq", LIST)
|
||||
let seq = doc1.set("_root", "seq", [])
|
||||
if (!seq) throw new Error('Should not be undefined')
|
||||
doc1.insert(seq, 0, "hello")
|
||||
let doc2 = loadDoc(doc1.save(), "bbbb");
|
||||
|
@ -363,18 +363,32 @@ describe('Automerge', () => {
|
|||
doc4.free()
|
||||
})
|
||||
|
||||
it('recursive sets are possible', () => {
|
||||
let doc = create("aaaa")
|
||||
let l1 = doc.make("_root","list",[{ foo: "bar"}, [1,2,3]])
|
||||
let l2 = doc.insert(l1, 0, { zip: ["a", "b"] })
|
||||
let l3 = doc.set("_root","info1","hello world","text")
|
||||
let l4 = doc.set("_root","info2","hello world")
|
||||
assert.deepEqual(doc.toJS(), {
|
||||
"list": [ { zip: ["a", "b"] }, { foo: "bar"}, [ 1,2,3]],
|
||||
"info1": "hello world".split(""),
|
||||
"info2": "hello world"
|
||||
})
|
||||
doc.free()
|
||||
})
|
||||
|
||||
it('only returns an object id when objects are created', () => {
|
||||
let doc = create("aaaa")
|
||||
let r1 = doc.set("_root","foo","bar")
|
||||
let r2 = doc.set("_root","list",LIST)
|
||||
let r2 = doc.set("_root","list",[])
|
||||
let r3 = doc.set("_root","counter",10, "counter")
|
||||
let r4 = doc.inc("_root","counter",1)
|
||||
let r5 = doc.del("_root","counter")
|
||||
if (!r2) throw new Error('should not be undefined')
|
||||
let r6 = doc.insert(r2,0,10);
|
||||
let r7 = doc.insert(r2,0,MAP);
|
||||
let r7 = doc.insert(r2,0,{});
|
||||
let r8 = doc.splice(r2,1,0,["a","b","c"]);
|
||||
let r9 = doc.splice(r2,1,0,["a",LIST,MAP,"d"]);
|
||||
let r9 = doc.splice(r2,1,0,["a",[],{},"d"]);
|
||||
assert.deepEqual(r1,null);
|
||||
assert.deepEqual(r2,"2@aaaa");
|
||||
assert.deepEqual(r3,null);
|
||||
|
@ -389,11 +403,11 @@ describe('Automerge', () => {
|
|||
|
||||
it('objects without properties are preserved', () => {
|
||||
let doc1 = create("aaaa")
|
||||
let a = doc1.set("_root","a",MAP);
|
||||
let a = doc1.set("_root","a",{});
|
||||
if (!a) throw new Error('should not be undefined')
|
||||
let b = doc1.set("_root","b",MAP);
|
||||
let b = doc1.set("_root","b",{});
|
||||
if (!b) throw new Error('should not be undefined')
|
||||
let c = doc1.set("_root","c",MAP);
|
||||
let c = doc1.set("_root","c",{});
|
||||
if (!c) throw new Error('should not be undefined')
|
||||
let d = doc1.set(c,"d","dd");
|
||||
let saved = doc1.save();
|
||||
|
@ -411,7 +425,7 @@ describe('Automerge', () => {
|
|||
|
||||
it('should handle merging text conflicts then saving & loading', () => {
|
||||
let A = create("aabbcc")
|
||||
let At = A.make('_root', 'text', TEXT)
|
||||
let At = A.make('_root', 'text', "", "text")
|
||||
A.splice(At, 0, 0, 'hello')
|
||||
|
||||
let B = A.fork()
|
||||
|
@ -462,7 +476,7 @@ describe('Automerge', () => {
|
|||
let s1 = initSyncState(), s2 = initSyncState()
|
||||
|
||||
// make two nodes with the same changes
|
||||
let list = n1.set("_root","n", LIST)
|
||||
let list = n1.set("_root","n", [])
|
||||
if (!list) throw new Error('undefined')
|
||||
n1.commit("",0)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
@ -486,7 +500,7 @@ describe('Automerge', () => {
|
|||
let n1 = create(), n2 = create()
|
||||
|
||||
// make changes for n1 that n2 should request
|
||||
let list = n1.set("_root","n",LIST)
|
||||
let list = n1.set("_root","n",[])
|
||||
if (!list) throw new Error('undefined')
|
||||
n1.commit("",0)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
@ -503,7 +517,7 @@ describe('Automerge', () => {
|
|||
let n1 = create(), n2 = create()
|
||||
|
||||
// make changes for n1 that n2 should request
|
||||
let list = n1.set("_root","n",LIST)
|
||||
let list = n1.set("_root","n",[])
|
||||
if (!list) throw new Error('undefined')
|
||||
n1.commit("",0)
|
||||
for (let i = 0; i < 10; i++) {
|
||||
|
@ -660,7 +674,7 @@ describe('Automerge', () => {
|
|||
let n1 = create('01234567'), n2 = create('89abcdef')
|
||||
let s1 = initSyncState(), s2 = initSyncState(), message = null
|
||||
|
||||
let items = n1.set("_root", "items", LIST)
|
||||
let items = n1.set("_root", "items", [])
|
||||
if (!items) throw new Error('undefined')
|
||||
n1.commit("",0)
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ const Automerge = require('../automerge-wasm')
|
|||
|
||||
const start = new Date()
|
||||
|
||||
let doc = Automerge.init();
|
||||
let text = doc.set("_root", "text", Automerge.TEXT)
|
||||
let doc = Automerge.create();
|
||||
let text = doc.set("_root", "text", "", "text")
|
||||
|
||||
for (let i = 0; i < edits.length; i++) {
|
||||
let edit = edits[i]
|
||||
|
|
Loading…
Add table
Reference in a new issue