mirror of
https://github.com/loro-dev/loro.git
synced 2025-01-22 21:07:43 +00:00
fix: wasm interface
This commit is contained in:
parent
71fd00418e
commit
e124bbbec1
13 changed files with 194 additions and 84 deletions
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -788,6 +788,7 @@ dependencies = [
|
|||
"ring",
|
||||
"rle",
|
||||
"serde",
|
||||
"serde-wasm-bindgen",
|
||||
"serde_columnar",
|
||||
"serde_json",
|
||||
"smallvec",
|
||||
|
@ -1483,6 +1484,17 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_columnar"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -26,6 +26,7 @@ tabled = { version = "0.10.0", optional = true }
|
|||
colored = "2.0.0"
|
||||
bit-vec = "0.6.3"
|
||||
wasm-bindgen = { version = "0.2.83", optional = true }
|
||||
serde-wasm-bindgen = { version = "0.4.5", optional = true }
|
||||
js-sys = { version = "0.3.60", optional = true }
|
||||
serde_json = { version = "1.0.87", optional = true }
|
||||
arref = "0.1.0"
|
||||
|
@ -52,7 +53,7 @@ debug-log = "0.1.1"
|
|||
doctest = false
|
||||
|
||||
[features]
|
||||
wasm = ["wasm-bindgen", "js-sys"]
|
||||
wasm = ["wasm-bindgen", "js-sys", "serde-wasm-bindgen"]
|
||||
json = ["serde_json"]
|
||||
# whether to use list slice instead of raw str in text container
|
||||
test_utils = ["crdt-list/fuzzing", "rand", "arbitrary", "tabled", "json"]
|
||||
|
|
|
@ -23,6 +23,7 @@ use crate::{
|
|||
op::{InnerContent, Op, RemoteContent, RichOp},
|
||||
value::LoroValue,
|
||||
version::IdSpanVector,
|
||||
LoroError,
|
||||
};
|
||||
|
||||
use super::list_op::InnerListOp;
|
||||
|
@ -90,6 +91,13 @@ impl ListContainer {
|
|||
Some(id)
|
||||
}
|
||||
|
||||
pub fn get(&self, pos: usize) -> Option<LoroValue> {
|
||||
self.state
|
||||
.get(pos)
|
||||
.map(|range| self.raw_data.slice(&range.as_ref().0))
|
||||
.and_then(|slice| slice.first().cloned())
|
||||
}
|
||||
|
||||
pub fn delete<C: Context>(&mut self, ctx: &C, pos: usize, len: usize) -> Option<ID> {
|
||||
if len == 0 {
|
||||
return None;
|
||||
|
@ -279,7 +287,12 @@ impl List {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn insert_batch<C: Context>(&mut self, ctx: &C, pos: usize, values: Vec<LoroValue>) {
|
||||
pub fn insert_batch<C: Context>(
|
||||
&mut self,
|
||||
ctx: &C,
|
||||
pos: usize,
|
||||
values: Vec<LoroValue>,
|
||||
) -> Result<(), LoroError> {
|
||||
self.with_container_checked(ctx, |x| x.insert_batch(ctx, pos, values))
|
||||
}
|
||||
|
||||
|
@ -288,7 +301,7 @@ impl List {
|
|||
ctx: &C,
|
||||
pos: usize,
|
||||
value: V,
|
||||
) -> Option<ID> {
|
||||
) -> Result<Option<ID>, LoroError> {
|
||||
self.with_container_checked(ctx, |x| x.insert(ctx, pos, value))
|
||||
}
|
||||
|
||||
|
@ -297,12 +310,21 @@ impl List {
|
|||
ctx: &C,
|
||||
pos: usize,
|
||||
obj: ContainerType,
|
||||
) -> ContainerID {
|
||||
) -> Result<ContainerID, LoroError> {
|
||||
self.with_container_checked(ctx, |x| x.insert_obj(ctx, pos, obj))
|
||||
}
|
||||
|
||||
pub fn delete<C: Context>(&mut self, ctx: &C, pos: usize, len: usize) -> Option<ID> {
|
||||
self.with_container_checked(ctx, |text| text.delete(ctx, pos, len))
|
||||
pub fn delete<C: Context>(
|
||||
&mut self,
|
||||
ctx: &C,
|
||||
pos: usize,
|
||||
len: usize,
|
||||
) -> Result<Option<ID>, LoroError> {
|
||||
self.with_container_checked(ctx, |list| list.delete(ctx, pos, len))
|
||||
}
|
||||
|
||||
pub fn get(&self, pos: usize) -> Option<LoroValue> {
|
||||
self.with_container(|list| list.get(pos))
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
|
|
@ -117,6 +117,11 @@ impl MapContainer {
|
|||
pub fn delete<C: Context>(&mut self, ctx: &C, key: InternalString) {
|
||||
self.insert(ctx, key, LoroValue::Null);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(&self, key: &InternalString) -> Option<LoroValue> {
|
||||
self.state.get(key).map(|v| &v.value).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Container for MapContainer {
|
||||
|
@ -230,7 +235,12 @@ impl Map {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn insert<C: Context, V: Into<LoroValue>>(&mut self, ctx: &C, key: &str, value: V) {
|
||||
pub fn insert<C: Context, V: Into<LoroValue>>(
|
||||
&mut self,
|
||||
ctx: &C,
|
||||
key: &str,
|
||||
value: V,
|
||||
) -> Result<(), crate::LoroError> {
|
||||
self.with_container_checked(ctx, |map| {
|
||||
map.insert(ctx, key.into(), value);
|
||||
})
|
||||
|
@ -241,16 +251,20 @@ impl Map {
|
|||
ctx: &C,
|
||||
key: &str,
|
||||
obj: ContainerType,
|
||||
) -> ContainerID {
|
||||
) -> Result<ContainerID, crate::LoroError> {
|
||||
self.with_container_checked(ctx, |map| map.insert_obj(ctx, key.into(), obj))
|
||||
}
|
||||
|
||||
pub fn delete<C: Context>(&mut self, ctx: &C, key: &str) {
|
||||
pub fn delete<C: Context>(&mut self, ctx: &C, key: &str) -> Result<(), crate::LoroError> {
|
||||
self.with_container_checked(ctx, |map| {
|
||||
map.delete(ctx, key.into());
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &str) -> Option<LoroValue> {
|
||||
self.with_container(|map| map.get(&key.into()))
|
||||
}
|
||||
|
||||
pub fn id(&self) -> ContainerID {
|
||||
self.instance.lock().unwrap().as_map().unwrap().id.clone()
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
id::{ClientID, ContainerIdx},
|
||||
op::{RemoteContent, RichOp},
|
||||
version::IdSpanVector,
|
||||
LoroValue, VersionVector,
|
||||
LoroError, LoroValue, VersionVector,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -297,19 +297,18 @@ pub trait ContainerWrapper {
|
|||
where
|
||||
F: FnOnce(&mut Self::Container) -> R;
|
||||
|
||||
fn with_container_checked<C: Context, F, R>(&self, ctx: &C, f: F) -> R
|
||||
fn with_container_checked<C: Context, F, R>(&self, ctx: &C, f: F) -> Result<R, LoroError>
|
||||
where
|
||||
F: FnOnce(&mut Self::Container) -> R,
|
||||
{
|
||||
let store_client_id = ctx.log_store().read().unwrap().this_client_id();
|
||||
if store_client_id != self.client_id() {
|
||||
panic!(
|
||||
"Context's client_id({}) does not match Container's client_id({})",
|
||||
store_client_id,
|
||||
self.client_id()
|
||||
);
|
||||
return Err(LoroError::UnmatchedContext {
|
||||
expected: self.client_id(),
|
||||
found: store_client_id,
|
||||
});
|
||||
}
|
||||
self.with_container(f)
|
||||
Ok(self.with_container(f))
|
||||
}
|
||||
|
||||
fn client_id(&self) -> ClientID;
|
||||
|
|
|
@ -302,11 +302,21 @@ impl Text {
|
|||
self.instance.lock().unwrap().as_text().unwrap().id.clone()
|
||||
}
|
||||
|
||||
pub fn insert<C: Context>(&mut self, ctx: &C, pos: usize, text: &str) -> Option<ID> {
|
||||
pub fn insert<C: Context>(
|
||||
&mut self,
|
||||
ctx: &C,
|
||||
pos: usize,
|
||||
text: &str,
|
||||
) -> Result<Option<ID>, crate::LoroError> {
|
||||
self.with_container_checked(ctx, |x| x.insert(ctx, pos, text))
|
||||
}
|
||||
|
||||
pub fn delete<C: Context>(&mut self, ctx: &C, pos: usize, len: usize) -> Option<ID> {
|
||||
pub fn delete<C: Context>(
|
||||
&mut self,
|
||||
ctx: &C,
|
||||
pos: usize,
|
||||
len: usize,
|
||||
) -> Result<Option<ID>, crate::LoroError> {
|
||||
self.with_container_checked(ctx, |text| text.delete(ctx, pos, len))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use thiserror::Error;
|
||||
|
||||
use crate::id::ClientID;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum LoroError {
|
||||
#[error("Context's client_id({found:?}) does not match Container's client_id({expected:?})")]
|
||||
UnmatchedContext { expected: ClientID, found: ClientID },
|
||||
// #[error("the data for key `{0}` is not available")]
|
||||
// Redaction(String),
|
||||
// #[error("invalid header (expected {expected:?}, found {found:?})")]
|
||||
|
|
|
@ -350,7 +350,9 @@ impl Actionable for Vec<Actor> {
|
|||
container.insert(&actor.loro, &key.to_string(), *i);
|
||||
}
|
||||
FuzzValue::Container(c) => {
|
||||
let new = container.insert_obj(&actor.loro, &key.to_string(), *c);
|
||||
let new = container
|
||||
.insert_obj(&actor.loro, &key.to_string(), *c)
|
||||
.unwrap();
|
||||
actor.add_new_container(new);
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +382,9 @@ impl Actionable for Vec<Actor> {
|
|||
container.insert(&actor.loro, *key as usize, *i);
|
||||
}
|
||||
FuzzValue::Container(c) => {
|
||||
let new = container.insert_obj(&actor.loro, *key as usize, *c);
|
||||
let new = container
|
||||
.insert_obj(&actor.loro, *key as usize, *c)
|
||||
.unwrap();
|
||||
actor.add_new_container(new)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,9 +148,13 @@ impl From<ContainerID> for LoroValue {
|
|||
pub mod wasm {
|
||||
use fxhash::FxHashMap;
|
||||
use js_sys::{Array, Object};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::{JsCast, JsValue, __rt::IntoJsResult};
|
||||
|
||||
use crate::LoroValue;
|
||||
use crate::{container::ContainerID as _ContainerID, LoroValue};
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct ContainerID(_ContainerID);
|
||||
|
||||
pub fn convert(value: LoroValue) -> JsValue {
|
||||
match value {
|
||||
|
@ -176,8 +180,10 @@ pub mod wasm {
|
|||
|
||||
map.into_js_result().unwrap()
|
||||
}
|
||||
LoroValue::Unresolved(_) => {
|
||||
unreachable!()
|
||||
LoroValue::Unresolved(container_id) => {
|
||||
// FIXME:
|
||||
// serde_wasm_bindgen::to_value(&container_id).unwrap()
|
||||
ContainerID(*container_id).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ fn example() {
|
|||
|
||||
let mut doc = LoroCore::default();
|
||||
let mut list = doc.get_list("list");
|
||||
list.insert(&doc, 0, 123);
|
||||
let map_id = list.insert_obj(&doc, 1, ContainerType::Map);
|
||||
list.insert(&doc, 0, 123).unwrap();
|
||||
let map_id = list.insert_obj(&doc, 1, ContainerType::Map).unwrap();
|
||||
let mut map = doc.get_map(map_id);
|
||||
let text = map.insert_obj(&doc, "map_b", ContainerType::Text);
|
||||
let text = map.insert_obj(&doc, "map_b", ContainerType::Text).unwrap();
|
||||
let mut text = doc.get_text(text);
|
||||
text.insert(&doc, 0, "world!");
|
||||
text.insert(&doc, 0, "hello ");
|
||||
text.insert(&doc, 0, "world!").unwrap();
|
||||
text.insert(&doc, 0, "hello ").unwrap();
|
||||
assert_eq!(
|
||||
r#"[123,{"map_b":"hello world!"}]"#,
|
||||
list.get_value_deep(&doc).to_json()
|
||||
|
@ -30,11 +30,17 @@ fn list() {
|
|||
let mut loro_b = LoroCore::default();
|
||||
let mut list_a = loro_a.get_list("list");
|
||||
let mut list_b = loro_b.get_list("list");
|
||||
list_a.insert_batch(&loro_a, 0, vec![12.into(), "haha".into()]);
|
||||
list_b.insert_batch(&loro_b, 0, vec![123.into(), "kk".into()]);
|
||||
let map_id = list_b.insert_obj(&loro_b, 1, loro_core::ContainerType::Map);
|
||||
list_a
|
||||
.insert_batch(&loro_a, 0, vec![12.into(), "haha".into()])
|
||||
.unwrap();
|
||||
list_b
|
||||
.insert_batch(&loro_b, 0, vec![123.into(), "kk".into()])
|
||||
.unwrap();
|
||||
let map_id = list_b
|
||||
.insert_obj(&loro_b, 1, loro_core::ContainerType::Map)
|
||||
.unwrap();
|
||||
let mut map = loro_b.get_map(map_id);
|
||||
map.insert(&loro_b, "map_b", 123);
|
||||
map.insert(&loro_b, "map_b", 123).unwrap();
|
||||
println!("{}", list_a.get_value().to_json());
|
||||
println!("{}", list_b.get_value().to_json());
|
||||
loro_b.import(loro_a.export(loro_b.vv()));
|
||||
|
@ -49,7 +55,7 @@ fn list() {
|
|||
fn map() {
|
||||
let mut loro = LoroCore::new(Default::default(), Some(10));
|
||||
let mut root = loro.get_map("root");
|
||||
root.insert(&loro, "haha", 1.2);
|
||||
root.insert(&loro, "haha", 1.2).unwrap();
|
||||
let value = root.get_value();
|
||||
assert_eq!(value.as_map().unwrap().len(), 1);
|
||||
assert_eq!(
|
||||
|
@ -62,7 +68,9 @@ fn map() {
|
|||
.unwrap(),
|
||||
1.2
|
||||
);
|
||||
let map_id = root.insert_obj(&loro, "map", loro_core::ContainerType::Map);
|
||||
let map_id = root
|
||||
.insert_obj(&loro, "map", loro_core::ContainerType::Map)
|
||||
.unwrap();
|
||||
drop(root);
|
||||
let mut sub_map = loro.get_map(&map_id);
|
||||
sub_map.insert(&loro, "sub", false);
|
||||
|
@ -93,9 +101,9 @@ fn map() {
|
|||
fn two_client_text_sync() {
|
||||
let mut store = LoroCore::new(Default::default(), Some(10));
|
||||
let mut text_container = store.get_text("haha");
|
||||
text_container.insert(&store, 0, "012");
|
||||
text_container.insert(&store, 1, "34");
|
||||
text_container.insert(&store, 1, "56");
|
||||
text_container.insert(&store, 0, "012").unwrap();
|
||||
text_container.insert(&store, 1, "34").unwrap();
|
||||
text_container.insert(&store, 1, "56").unwrap();
|
||||
let value = text_container.get_value();
|
||||
let value = value.as_string().unwrap();
|
||||
assert_eq!(&**value, "0563412");
|
||||
|
@ -110,8 +118,8 @@ fn two_client_text_sync() {
|
|||
let value = value.as_string().unwrap();
|
||||
assert_eq!(&**value, "0563412");
|
||||
|
||||
text_container.delete(&store_b, 0, 2);
|
||||
text_container.insert(&store_b, 4, "789");
|
||||
text_container.delete(&store_b, 0, 2).unwrap();
|
||||
text_container.insert(&store_b, 4, "789").unwrap();
|
||||
let value = text_container.get_value();
|
||||
let value = value.as_string().unwrap();
|
||||
assert_eq!(&**value, "63417892");
|
||||
|
@ -122,8 +130,8 @@ fn two_client_text_sync() {
|
|||
let value = text_container.get_value();
|
||||
let value = value.as_string().unwrap();
|
||||
assert_eq!(&**value, "63417892");
|
||||
text_container.delete(&store, 0, 8);
|
||||
text_container.insert(&store, 0, "abc");
|
||||
text_container.delete(&store, 0, 8).unwrap();
|
||||
text_container.insert(&store, 0, "abc").unwrap();
|
||||
let value = text_container.get_value();
|
||||
let value = value.as_string().unwrap();
|
||||
assert_eq!(&**value, "abc");
|
||||
|
@ -143,8 +151,8 @@ fn test_recursive_should_panic() {
|
|||
let mut store_b = LoroCore::new(Default::default(), Some(2));
|
||||
let mut text_a = store_a.get_text("text_a");
|
||||
let mut text_b = store_b.get_text("text_b");
|
||||
text_a.insert(&store_a, 0, "012");
|
||||
text_b.insert(&store_a, 1, "34");
|
||||
text_a.insert(&store_a, 0, "012").unwrap();
|
||||
text_b.insert(&store_a, 1, "34").unwrap();
|
||||
}
|
||||
|
||||
#[ctor]
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
"https://deno.land/std@0.105.0/path/posix.ts": "b81974c768d298f8dcd2c720229639b3803ca4a241fa9a355c762fa2bc5ef0c1",
|
||||
"https://deno.land/std@0.105.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c",
|
||||
"https://deno.land/std@0.105.0/path/win32.ts": "f4a3d4a3f2c9fe894da046d5eac48b5e789a0ebec5152b2c0985efe96a9f7ae1",
|
||||
"https://deno.land/std@0.165.0/fmt/colors.ts": "9e36a716611dcd2e4865adea9c4bec916b5c60caad4cdcdc630d4974e6bb8bd4",
|
||||
"https://deno.land/std@0.165.0/testing/_diff.ts": "a23e7fc2b4d8daa3e158fa06856bedf5334ce2a2831e8bf9e509717f455adb2c",
|
||||
"https://deno.land/std@0.165.0/testing/_format.ts": "cd11136e1797791045e639e9f0f4640d5b4166148796cad37e6ef75f7d7f3832",
|
||||
"https://deno.land/std@0.165.0/testing/asserts.ts": "1e340c589853e82e0807629ba31a43c84ebdcdeca910c4a9705715dfdb0f5ce8",
|
||||
"https://deno.land/x/dirname@1.1.2/mod.ts": "4029ca6b49da58d262d65f826ba9b3a89cc0b92a94c7220d5feb7bd34e498a54",
|
||||
"https://deno.land/x/dirname@1.1.2/types.ts": "c1ed1667545bc4b1d69bdb2fc26a5fa8edae3a56e3081209c16a408a322a2319",
|
||||
"https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149",
|
||||
|
|
|
@ -23,7 +23,9 @@ Deno.test({
|
|||
b.set(loro, "ab", 123);
|
||||
console.log(b.value);
|
||||
console.log(a.value);
|
||||
|
||||
const bText = b.getText(loro, "hh");
|
||||
|
||||
await t.step("getValueDeep", () => {
|
||||
bText.insert(loro, 0, "hello world Text");
|
||||
assertEquals(b.getValueDeep(loro), { ab: 123, hh: "hello world Text" });
|
||||
|
@ -37,8 +39,12 @@ Deno.test({
|
|||
});
|
||||
|
||||
await t.step("get value error", () => {
|
||||
assertThrows(()=>{
|
||||
const _ = bText.value;
|
||||
});
|
||||
// assertThrows(()=>{
|
||||
const map = loro.getMap("map");
|
||||
const list = map.getList(loro, "list");
|
||||
list.insert(loro, 0, 123);
|
||||
console.log(map.value);
|
||||
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,6 +18,8 @@ pub fn set_panic_hook() {
|
|||
console_error_panic_hook::set_once();
|
||||
}
|
||||
|
||||
type JsResult<T> = Result<T, JsError>;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub struct Loro(LoroCore);
|
||||
|
||||
|
@ -43,13 +45,13 @@ impl Loro {
|
|||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getText")]
|
||||
pub fn get_text(&mut self, name: &str) -> Result<LoroText, JsValue> {
|
||||
pub fn get_text(&mut self, name: &str) -> JsResult<LoroText> {
|
||||
let text = self.0.get_text(name);
|
||||
Ok(LoroText(text))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getMap")]
|
||||
pub fn get_map(&mut self, name: &str) -> Result<LoroMap, JsValue> {
|
||||
pub fn get_map(&mut self, name: &str) -> JsResult<LoroMap> {
|
||||
let map = self.0.get_map(name);
|
||||
Ok(LoroMap(map))
|
||||
}
|
||||
|
@ -60,16 +62,18 @@ pub struct LoroText(Text);
|
|||
|
||||
#[wasm_bindgen]
|
||||
impl LoroText {
|
||||
pub fn insert(&mut self, ctx: &Loro, index: usize, content: &str) {
|
||||
self.0.insert(ctx.deref(), index, content);
|
||||
pub fn insert(&mut self, ctx: &Loro, index: usize, content: &str) -> JsResult<()> {
|
||||
self.0.insert(ctx.deref(), index, content)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(&mut self, ctx: &Loro, index: usize, len: usize) {
|
||||
self.0.delete(ctx.deref(), index, len);
|
||||
pub fn delete(&mut self, ctx: &Loro, index: usize, len: usize) -> JsResult<()> {
|
||||
self.0.delete(ctx.deref(), index, len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "value", method, getter)]
|
||||
pub fn get_value(&mut self) -> String {
|
||||
pub fn get_value(&self) -> String {
|
||||
self.0.get_value().as_string().unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
@ -80,43 +84,54 @@ pub struct LoroMap(Map);
|
|||
#[wasm_bindgen]
|
||||
impl LoroMap {
|
||||
#[wasm_bindgen(js_name = "set")]
|
||||
pub fn insert(&mut self, ctx: &Loro, key: &str, value: JsValue) {
|
||||
self.0.insert(ctx.deref(), key, value);
|
||||
pub fn insert(&mut self, ctx: &Loro, key: &str, value: JsValue) -> JsResult<()> {
|
||||
self.0.insert(ctx.deref(), key, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(&mut self, ctx: &Loro, key: &str) {
|
||||
self.0.delete(ctx.deref(), key);
|
||||
pub fn delete(&mut self, ctx: &Loro, key: &str) -> JsResult<()> {
|
||||
self.0.delete(ctx.deref(), key)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &str) -> JsValue {
|
||||
self.0.get(key).into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "value", method, getter)]
|
||||
pub fn get_value(&mut self) -> JsValue {
|
||||
pub fn get_value(&self) -> JsValue {
|
||||
// TODO: if unresolved, return a container ID
|
||||
self.0.get_value().into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getValueDeep")]
|
||||
pub fn get_value_deep(&mut self, ctx: &Loro) -> JsValue {
|
||||
pub fn get_value_deep(&self, ctx: &Loro) -> JsValue {
|
||||
self.0.get_value_deep(ctx.deref()).into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getText")]
|
||||
pub fn get_text(&mut self, ctx: &mut Loro, key: &str) -> LoroText {
|
||||
let id = self.0.insert_obj(&ctx.0, key, ContainerType::Text);
|
||||
pub fn get_text(&mut self, ctx: &mut Loro, key: &str) -> JsResult<LoroText> {
|
||||
let id = self.0.insert_obj(&ctx.0, key, ContainerType::Text)?;
|
||||
let text = ctx.deref().get_container(&id).unwrap();
|
||||
LoroText(Text::from_instance(text, ctx.deref().client_id()))
|
||||
Ok(LoroText(Text::from_instance(text, ctx.deref().client_id())))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getMap")]
|
||||
pub fn get_map(&mut self, ctx: &mut Loro, key: &str) -> LoroMap {
|
||||
let id = self.0.insert_obj(ctx.deref_mut(), key, ContainerType::Map);
|
||||
pub fn get_map(&mut self, ctx: &mut Loro, key: &str) -> JsResult<LoroMap> {
|
||||
let id = self
|
||||
.0
|
||||
.insert_obj(ctx.deref_mut(), key, ContainerType::Map)?;
|
||||
let map = ctx.deref().get_container(&id).unwrap();
|
||||
LoroMap(Map::from_instance(map, ctx.deref().client_id()))
|
||||
Ok(LoroMap(Map::from_instance(map, ctx.deref().client_id())))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getList")]
|
||||
pub fn get_list(&mut self, ctx: &mut Loro, key: &str) -> LoroList {
|
||||
let id = self.0.insert_obj(ctx.deref_mut(), key, ContainerType::List);
|
||||
pub fn get_list(&mut self, ctx: &mut Loro, key: &str) -> JsResult<LoroList> {
|
||||
let id = self
|
||||
.0
|
||||
.insert_obj(ctx.deref_mut(), key, ContainerType::List)?;
|
||||
let list = ctx.deref().get_container(&id).unwrap();
|
||||
LoroList(List::from_instance(list, ctx.deref().client_id()))
|
||||
Ok(LoroList(List::from_instance(list, ctx.deref().client_id())))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,13 +140,18 @@ pub struct LoroList(List);
|
|||
|
||||
#[wasm_bindgen]
|
||||
impl LoroList {
|
||||
#[wasm_bindgen(js_name = "set")]
|
||||
pub fn insert(&mut self, ctx: &Loro, index: usize, value: JsValue) {
|
||||
self.0.insert(ctx.deref(), index, value);
|
||||
pub fn insert(&mut self, ctx: &Loro, index: usize, value: JsValue) -> JsResult<()> {
|
||||
self.0.insert(ctx.deref(), index, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete(&mut self, ctx: &Loro, index: usize, len: usize) {
|
||||
self.0.delete(ctx.deref(), index, len);
|
||||
pub fn delete(&mut self, ctx: &Loro, index: usize, len: usize) -> JsResult<()> {
|
||||
self.0.delete(ctx.deref(), index, len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> JsValue {
|
||||
self.0.get(index).into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "value", method, getter)]
|
||||
|
@ -140,35 +160,35 @@ impl LoroList {
|
|||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getValueDeep")]
|
||||
pub fn get_value_deep(&mut self, ctx: &Loro) -> JsValue {
|
||||
pub fn get_value_deep(&self, ctx: &Loro) -> JsValue {
|
||||
self.0.get_value_deep(ctx.deref()).into()
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getText")]
|
||||
pub fn get_text(&mut self, ctx: &mut Loro, index: usize) -> LoroText {
|
||||
pub fn get_text(&mut self, ctx: &mut Loro, index: usize) -> JsResult<LoroText> {
|
||||
let id = self
|
||||
.0
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::Text);
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::Text)?;
|
||||
let text = ctx.deref().get_container(&id).unwrap();
|
||||
LoroText(Text::from_instance(text, ctx.deref().client_id()))
|
||||
Ok(LoroText(Text::from_instance(text, ctx.deref().client_id())))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getMap")]
|
||||
pub fn get_map(&mut self, ctx: &mut Loro, index: usize) -> LoroMap {
|
||||
pub fn get_map(&mut self, ctx: &mut Loro, index: usize) -> JsResult<LoroMap> {
|
||||
let id = self
|
||||
.0
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::Map);
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::Map)?;
|
||||
let map = ctx.deref().get_container(&id).unwrap();
|
||||
LoroMap(Map::from_instance(map, ctx.deref().client_id()))
|
||||
Ok(LoroMap(Map::from_instance(map, ctx.deref().client_id())))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "getList")]
|
||||
pub fn get_list(&mut self, ctx: &mut Loro, index: usize) -> LoroList {
|
||||
pub fn get_list(&mut self, ctx: &mut Loro, index: usize) -> JsResult<LoroList> {
|
||||
let id = self
|
||||
.0
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::List);
|
||||
.insert_obj(ctx.deref_mut(), index, ContainerType::List)?;
|
||||
let list = ctx.deref().get_container(&id).unwrap();
|
||||
LoroList(List::from_instance(list, ctx.deref().client_id()))
|
||||
Ok(LoroList(List::from_instance(list, ctx.deref().client_id())))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue