test: add compatibility tests (#503)

This commit is contained in:
Zixuan Chen 2024-10-09 17:42:05 +08:00 committed by GitHub
parent 9bfe97bce4
commit 66b8a76fdf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 558 additions and 16 deletions

131
Cargo.lock generated
View file

@ -700,6 +700,7 @@ dependencies = [
"fxhash",
"itertools 0.12.1",
"loro 0.16.12",
"loro 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro 0.16.2 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@0.16.7)",
"loro 0.16.2 (git+https://github.com/loro-dev/loro.git?rev=90470658435ec4c62b5af59ebb82fe9e1f5aa761)",
"num_cpus",
@ -1058,13 +1059,27 @@ dependencies = [
"loro-common 0.16.12",
"loro-delta 0.16.12",
"loro-internal 0.16.12",
"loro-kv-store",
"loro-kv-store 0.16.2",
"pretty_assertions",
"rand",
"serde_json",
"tracing",
]
[[package]]
name = "loro"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"enum-as-inner 0.6.0",
"generic-btree",
"loro-common 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-delta 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-internal 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-kv-store 0.16.2 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"tracing",
]
[[package]]
name = "loro-common"
version = "0.16.2"
@ -1116,6 +1131,24 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "loro-common"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"arbitrary",
"enum-as-inner 0.6.0",
"fxhash",
"leb128",
"loro-rle 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"nonmax",
"serde",
"serde_columnar",
"serde_json",
"string_cache",
"thiserror",
]
[[package]]
name = "loro-delta"
version = "0.16.2"
@ -1156,6 +1189,18 @@ dependencies = [
"tracing-subscriber",
]
[[package]]
name = "loro-delta"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"arrayvec",
"enum-as-inner 0.5.1",
"generic-btree",
"heapless 0.8.0",
"tracing",
]
[[package]]
name = "loro-ffi"
version = "0.16.2"
@ -1262,7 +1307,7 @@ dependencies = [
"leb128",
"loro-common 0.16.12",
"loro-delta 0.16.12",
"loro-kv-store",
"loro-kv-store 0.16.2",
"loro-rle 0.16.12",
"loro_fractional_index 0.16.12",
"md5",
@ -1291,6 +1336,47 @@ dependencies = [
"zstd",
]
[[package]]
name = "loro-internal"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"append-only-bytes",
"arref",
"bytes",
"either",
"ensure-cov",
"enum-as-inner 0.6.0",
"enum_dispatch",
"fxhash",
"generic-btree",
"getrandom",
"im",
"itertools 0.12.1",
"leb128",
"loro-common 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-delta 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-kv-store 0.16.2 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro-rle 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"loro_fractional_index 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"md5",
"nonmax",
"num",
"num-derive",
"num-traits",
"once_cell",
"postcard",
"pretty_assertions",
"rand",
"serde",
"serde_columnar",
"serde_json",
"smallvec",
"thiserror",
"tracing",
"xxhash-rust",
]
[[package]]
name = "loro-kv-store"
version = "0.16.2"
@ -1309,6 +1395,22 @@ dependencies = [
"xxhash-rust",
]
[[package]]
name = "loro-kv-store"
version = "0.16.2"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"bytes",
"ensure-cov",
"fxhash",
"loro-common 0.16.12 (git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4)",
"lz4_flex",
"once_cell",
"quick_cache",
"tracing",
"xxhash-rust",
]
[[package]]
name = "loro-rle"
version = "0.16.2"
@ -1352,6 +1454,19 @@ dependencies = [
"static_assertions",
]
[[package]]
name = "loro-rle"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"append-only-bytes",
"arref",
"enum-as-inner 0.6.0",
"fxhash",
"num",
"smallvec",
]
[[package]]
name = "loro-thunderdome"
version = "0.6.2"
@ -1411,6 +1526,18 @@ dependencies = [
"smallvec",
]
[[package]]
name = "loro_fractional_index"
version = "0.16.12"
source = "git+https://github.com/loro-dev/loro.git?tag=loro-crdt@1.0.0-alpha.4#9bfe97bce4912c6dc8439817497d18423a0e8cb7"
dependencies = [
"imbl",
"once_cell",
"rand",
"serde",
"smallvec",
]
[[package]]
name = "lz4_flex"
version = "0.11.3"

View file

@ -24,6 +24,7 @@ rayon = "1.10.0"
bytes = "1"
ensure-cov = { workspace = true }
pretty_assertions = "1.4.0"
loro-alpha-4 = { git = "https://github.com/loro-dev/loro.git", tag = "loro-crdt@1.0.0-alpha.4", package = "loro" }
[dev-dependencies]
ctor = "0.2"

View file

@ -149,3 +149,286 @@ fn snapshot_from_016_can_be_imported_in_cur_version() {
doc_current.get_deep_value().to_json()
);
}
/// Macro to generate random operations on a LoroDoc.
///
/// This macro creates a series of random operations on various container types
/// within a LoroDoc. It's useful for testing and fuzzing purposes.
///
/// # Parameters
///
/// * `$doc` - A reference to a `loro::LoroDoc` instance.
/// * `$seed` - A `u64` value used to seed the random number generator.
/// * `$len` - A `usize` value specifying the number of random operations to perform.
///
/// # Example
///
/// ```
/// let doc = loro::LoroDoc::new();
/// gen_random_ops!(doc, 12345, 100);
/// ```
#[macro_export]
macro_rules! gen_random_ops {
($doc:expr, $seed:expr, $len:expr) => {{
use rand::rngs::StdRng;
use rand::seq::SliceRandom;
use rand::{Rng, SeedableRng};
let mut rng = StdRng::seed_from_u64($seed);
let containers = ["text", "map", "list", "tree", "movable_list"];
for _ in 0..$len {
let container = containers.choose(&mut rng).unwrap();
match *container {
"text" => {
let text = $doc.get_text("text");
let pos = rng.gen_range(0..=text.len_unicode());
let content = (0..5).map(|_| rng.gen::<char>()).collect::<String>();
if rng.gen_bool(0.7) {
text.insert(pos, &content).unwrap_or_default();
} else {
let del_len = rng.gen_range(0..=text.len_unicode().saturating_sub(pos));
text.delete(pos, del_len).unwrap_or_default();
}
}
"map" => {
let map = $doc.get_map("map");
let key = format!("key_{}", rng.gen::<u32>());
if rng.gen_bool(0.7) {
let value = format!("value_{}", rng.gen::<u32>());
map.insert(&key, value).unwrap();
} else if !map.is_empty() {
let v = map.get_value();
let existing_key = v
.as_map()
.unwrap()
.keys()
.nth(rng.gen_range(0..map.len()))
.unwrap();
map.delete(&existing_key).unwrap();
}
}
"list" => {
let list = $doc.get_list("list");
let pos = rng.gen_range(0..=list.len());
if rng.gen_bool(0.7) {
let value = rng.gen::<i32>();
list.insert(pos, value).unwrap();
} else if !list.is_empty() {
list.delete(pos, 1).unwrap_or_default();
}
}
"tree" => {
let tree = $doc.get_tree("tree");
tree.enable_fractional_index(0);
let nodes: Vec<_> = tree.nodes();
if nodes.is_empty() {
tree.create(None).unwrap();
} else {
let node = nodes.choose(&mut rng).unwrap();
match rng.gen_range(0..3) {
0 => {
tree.create(Some(*node)).unwrap();
}
1 if !tree.is_node_deleted(node).unwrap() => {
tree.delete(*node).unwrap_or_default();
}
_ => {
if let Some(sibling) = nodes.choose(&mut rng) {
if sibling != node
&& !tree.is_node_deleted(sibling).unwrap()
&& !tree.is_node_deleted(node).unwrap()
{
tree.mov_before(*node, *sibling).unwrap_or_default();
}
}
}
}
}
}
"movable_list" => {
let movable_list = $doc.get_movable_list("movable_list");
let pos = rng.gen_range(0..=movable_list.len());
match rng.gen_range(0..3) {
0 => {
let value = rng.gen::<i32>();
movable_list.insert(pos, value).unwrap();
}
1 => {
if !movable_list.is_empty() {
movable_list.delete(pos, 1).unwrap_or_default();
}
}
2 => {
if !movable_list.is_empty() {
let from = rng.gen_range(0..movable_list.len());
let to = rng.gen_range(0..=movable_list.len());
movable_list.mov(from, to).unwrap_or_default();
}
}
_ => unreachable!("unreachable movable list op"),
}
}
_ => unreachable!("unreachable container type"),
}
}
$doc.commit();
}};
}
#[ctor::ctor]
fn init() {
dev_utils::setup_test_log();
}
mod compatibility_with_10_alpha_4 {
use super::*;
use loro_alpha_4::{self, ToJson};
#[test]
fn test_shallow_snapshot() {
let doc1 = loro::LoroDoc::new();
doc1.set_peer_id(1).unwrap();
gen_random_ops!(doc1, 12345, 100);
let snapshot = doc1
.export(loro::ExportMode::shallow_snapshot_since(ID::new(1, 50)))
.unwrap();
let doc2 = loro_alpha_4::LoroDoc::new();
doc2.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
assert_eq!(
doc2.shallow_since_frontiers().encode(),
loro::Frontiers::from_id(ID::new(1, 50)).encode()
);
gen_random_ops!(doc2, 12345, 100);
let snapshot = doc2
.export(loro_alpha_4::ExportMode::all_updates())
.unwrap();
doc1.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
}
#[test]
fn test_shallow_snapshot_mirrored() {
let doc1 = loro_alpha_4::LoroDoc::new();
doc1.set_peer_id(1).unwrap();
gen_random_ops!(doc1, 1234, 100);
let snapshot = doc1
.export(loro_alpha_4::ExportMode::shallow_snapshot_since(
loro_alpha_4::ID::new(1, 50),
))
.unwrap();
let doc2 = loro::LoroDoc::new();
doc2.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
assert_eq!(
doc2.shallow_since_frontiers().encode(),
loro_alpha_4::Frontiers::from_id(loro_alpha_4::ID::new(1, 50)).encode()
);
gen_random_ops!(doc2, 1234, 100);
let snapshot = doc2.export(loro::ExportMode::all_updates()).unwrap();
doc1.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
}
#[test]
fn test_snapshot() {
let doc1 = loro_alpha_4::LoroDoc::new();
doc1.set_peer_id(1).unwrap();
gen_random_ops!(doc1, 1234, 100);
let snapshot = doc1.export(loro_alpha_4::ExportMode::Snapshot).unwrap();
let doc2 = loro::LoroDoc::new();
doc2.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
gen_random_ops!(doc2, 5678, 100);
let snapshot = doc2.export(loro::ExportMode::Snapshot).unwrap();
doc1.import(&snapshot).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
let updates =
serde_json::to_value(doc1.export_json_updates(&Default::default(), &doc1.oplog_vv()))
.unwrap();
let updates_b =
serde_json::to_value(doc2.export_json_updates(&Default::default(), &doc2.oplog_vv()))
.unwrap();
assert_eq!(updates, updates_b);
}
#[test]
fn test_updates() {
let doc1 = loro_alpha_4::LoroDoc::new();
let doc2 = Arc::new(loro::LoroDoc::new());
let doc2_clone = doc2.clone();
doc1.set_peer_id(1).unwrap();
doc1.subscribe_local_update(Box::new(move |updates| {
doc2_clone.import(updates).unwrap();
true
}))
.detach();
for i in 0..5 {
gen_random_ops!(doc1, i, 10);
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
}
}
#[test]
fn test_update_in_range() {
let doc1 = loro_alpha_4::LoroDoc::new();
let doc2 = loro::LoroDoc::new();
// Generate some initial content
gen_random_ops!(doc1, 1234, 50);
let version = doc1.oplog_vv();
let doc1_value = doc1.get_deep_value().to_json_value();
gen_random_ops!(doc1, 1234, 50);
let updates = doc1
.export(loro_alpha_4::ExportMode::updates_till(&version))
.unwrap();
doc2.import(&updates).unwrap();
assert_eq!(doc1_value, doc2.get_deep_value().to_json_value());
}
#[test]
fn test_json_updates() {
let doc1 = loro_alpha_4::LoroDoc::new();
let doc2 = loro::LoroDoc::new();
gen_random_ops!(doc1, 0, 1000);
let updates =
serde_json::to_string(&doc1.export_json_updates(&Default::default(), &doc1.oplog_vv()))
.unwrap();
doc2.import_json_updates(updates).unwrap();
assert_eq!(
doc1.get_deep_value().to_json_value(),
doc2.get_deep_value().to_json_value()
);
}
}

View file

@ -505,7 +505,7 @@ impl TreeCacheForDiff {
self.is_ancestor_of(maybe_ancestor, parent)
}
TreeParentId::Deleted | TreeParentId::Root => false,
TreeParentId::Unexist => unreachable!(),
TreeParentId::Unexist => false,
}
}

View file

@ -3702,6 +3702,51 @@ impl MapHandler {
Ok(())
}
pub fn keys(&self) -> impl Iterator<Item = InternalString> + '_ {
let mut keys: Vec<InternalString> = Vec::with_capacity(self.len());
match &self.inner {
MaybeDetached::Detached(m) => {
let m = m.try_lock().unwrap();
keys = m.value.keys().map(|x| x.as_str().into()).collect();
}
MaybeDetached::Attached(a) => {
a.with_state(|state| {
for (k, _) in state.as_map_state().unwrap().iter() {
keys.push(k.clone());
}
});
}
}
keys.into_iter()
}
pub fn values(&self) -> impl Iterator<Item = ValueOrHandler> + '_ {
let mut values: Vec<ValueOrHandler> = Vec::with_capacity(self.len());
match &self.inner {
MaybeDetached::Detached(m) => {
let m = m.try_lock().unwrap();
values = m.value.values().cloned().collect();
}
MaybeDetached::Attached(a) => {
a.with_state(|state| {
for (_, v) in state.as_map_state().unwrap().iter() {
let value = match &v.value {
Some(LoroValue::Container(container_id)) => {
ValueOrHandler::Handler(create_handler(a, container_id.clone()))
}
Some(value) => ValueOrHandler::Value(value.clone()),
None => continue,
};
values.push(value);
}
});
}
}
values.into_iter()
}
}
#[inline(always)]

View file

@ -288,6 +288,12 @@ impl TreeHandler {
pub(crate) fn delete_with_txn(&self, txn: &mut Transaction, target: TreeID) -> LoroResult<()> {
let inner = self.inner.try_attached_state()?;
let index = match self.get_index_by_tree_id(&target) {
Some(i) => i,
None => {
return Err(LoroTreeError::TreeNodeDeletedOrNotExist(target).into());
}
};
txn.apply_local_op(
inner.container_idx,
crate::op::RawOpContent::Tree(Arc::new(TreeOp::Delete { target })),
@ -295,7 +301,7 @@ impl TreeHandler {
target,
action: TreeExternalDiff::Delete {
old_parent: self.get_node_parent(&target).unwrap(),
old_index: self.get_index_by_tree_id(&target).unwrap(),
old_index: index
},
}]),
&inner.state,
@ -993,4 +999,17 @@ impl TreeHandler {
MaybeDetached::Attached(a) => a.is_deleted(),
}
}
pub fn is_empty(&self) -> bool {
match &self.inner {
MaybeDetached::Detached(t) => {
let t = t.try_lock().unwrap();
t.value.map.is_empty()
}
MaybeDetached::Attached(a) => a.with_state(|state| {
let a = state.as_tree_state().unwrap();
a.is_empty()
}),
}
}
}

View file

@ -1013,6 +1013,13 @@ impl TreeState {
}
}
}
pub fn is_empty(&self) -> bool {
match self.children.get(&TreeParentId::Root) {
Some(c) => c.len() == 0,
None => true,
}
}
}
pub(crate) enum FractionalIndexGenResult {

View file

@ -2,6 +2,7 @@
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
use event::{DiffEvent, Subscriber};
use loro_common::InternalString;
pub use loro_internal::cursor::CannotFindRelativePosition;
use loro_internal::cursor::Cursor;
use loro_internal::cursor::PosQueryResult;
@ -1281,6 +1282,19 @@ impl LoroMap {
pub fn clear(&self) -> LoroResult<()> {
self.handler.clear()
}
/// Get the keys of the map.
pub fn keys(&self) -> impl Iterator<Item = InternalString> + '_ {
self.handler.keys()
}
/// Get the values of the map.
pub fn values(&self) -> impl Iterator<Item = ValueOrContainer> + '_ {
self.handler.values().map(|v| match v {
ValueOrHandler::Value(v) => ValueOrContainer::Value(v),
ValueOrHandler::Handler(c) => ValueOrContainer::Container(Container::from_handler(c)),
})
}
}
impl Default for LoroMap {
@ -1920,6 +1934,13 @@ impl LoroTree {
pub fn disable_fractional_index(&self) {
self.handler.disable_fractional_index();
}
/// Whether the tree is empty.
///
#[inline]
pub fn is_empty(&self) -> bool {
self.handler.is_empty()
}
}
impl Default for LoroTree {

View file

@ -36,6 +36,7 @@
"esbuild": "^0.18.20",
"eslint": "^8.46.0",
"loro-crdt-old": "npm:loro-crdt@=0.16.0",
"loro-crdt-alpha-4": "npm:loro-crdt@=1.0.0-alpha.4",
"prettier": "^3.0.0",
"rollup": "^3.20.1",
"rollup-plugin-dts": "^5.3.0",

View file

@ -19,10 +19,10 @@ importers:
devDependencies:
vite-plugin-top-level-await:
specifier: ^1.2.2
version: 1.4.1(vite@4.5.3)
version: 1.4.1(rollup@4.17.2)(vite@5.2.11)
vite-plugin-wasm:
specifier: ^3.1.0
version: 3.3.0(vite@4.5.3)
version: 3.3.0(vite@5.2.11)
examples/loro-quill:
dependencies:
@ -44,7 +44,7 @@ importers:
version: 1.3.10
'@vitejs/plugin-vue':
specifier: ^4.1.0
version: 4.6.2(vite@4.5.3)(vue@3.4.27)
version: 4.6.2(vite@4.5.3)(vue@3.4.27(typescript@5.4.5))
typescript:
specifier: ^5.2.0
version: 5.4.5
@ -53,7 +53,7 @@ importers:
version: 4.5.3
vite-plugin-top-level-await:
specifier: ^1.3.0
version: 1.4.1(vite@4.5.3)
version: 1.4.1(rollup@4.17.2)(vite@4.5.3)
vite-plugin-wasm:
specifier: ^3.2.2
version: 3.3.0(vite@4.5.3)
@ -82,6 +82,9 @@ importers:
eslint:
specifier: ^8.46.0
version: 8.57.0
loro-crdt-alpha-4:
specifier: npm:loro-crdt@=1.0.0-alpha.4
version: loro-crdt@1.0.0-alpha.4
loro-crdt-old:
specifier: npm:loro-crdt@=0.16.0
version: loro-crdt@0.16.0
@ -1669,9 +1672,15 @@ packages:
loro-crdt@0.16.0:
resolution: {integrity: sha512-U/fwXPfe3GjE96tP97qzIjGoDOz5K/zSNPs1QZ7ZO4pqOAkjkLhBifSYZWW2v1t7ufFgUa4XqXpS1pn7Hyze2A==}
loro-crdt@1.0.0-alpha.4:
resolution: {integrity: sha512-WFVf/goGbiC9wmA7GNf9Fmdwry5hJq/CcQkXjoEp4QC9OYMUGm6QqKsrI7M4q05e2l7JeTc0RU858C7FRtg7qw==}
loro-wasm@0.16.0:
resolution: {integrity: sha512-2puF09ppACoUwMf9+6BkuYlogY+qZqqStq6RbYYXMhL8Uxrf8DXJdmLA+XGgI4suxXh39jvt6XfwdafqcUuu4A==}
loro-wasm@1.0.0-alpha.4:
resolution: {integrity: sha512-M1Bwh1PQQUFwdAldpSGZD3wl5D/6gQkbTC6aRoC8SjIxv0mgVzibp9sw9DXnolwoJ/Abd4hWeCz2sOvYOzw+Hg==}
loupe@2.3.7:
resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==}
@ -2896,15 +2905,19 @@ snapshots:
is-builtin-module: 3.2.1
is-module: 1.0.0
resolve: 1.22.8
optionalDependencies:
rollup: 3.29.4
'@rollup/plugin-virtual@3.0.2': {}
'@rollup/plugin-virtual@3.0.2(rollup@4.17.2)':
optionalDependencies:
rollup: 4.17.2
'@rollup/pluginutils@5.1.0(rollup@3.29.4)':
dependencies:
'@types/estree': 1.0.5
estree-walker: 2.0.2
picomatch: 2.3.1
optionalDependencies:
rollup: 3.29.4
'@rollup/rollup-android-arm-eabi@4.17.2':
@ -3033,6 +3046,7 @@ snapshots:
'@typescript-eslint/visitor-keys': 6.21.0
debug: 4.3.4
eslint: 8.57.0
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@ -3054,6 +3068,7 @@ snapshots:
minimatch: 9.0.3
semver: 7.6.2
ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
- supports-color
@ -3065,7 +3080,7 @@ snapshots:
'@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-vue@4.6.2(vite@4.5.3)(vue@3.4.27)':
'@vitejs/plugin-vue@4.6.2(vite@4.5.3)(vue@3.4.27(typescript@5.4.5))':
dependencies:
vite: 4.5.3
vue: 3.4.27(typescript@5.4.5)
@ -3163,8 +3178,9 @@ snapshots:
minimatch: 9.0.4
muggle-string: 0.3.1
path-browserify: 1.0.1
typescript: 5.4.5
vue-template-compiler: 2.7.16
optionalDependencies:
typescript: 5.4.5
'@vue/reactivity@3.4.27':
dependencies:
@ -3181,7 +3197,7 @@ snapshots:
'@vue/shared': 3.4.27
csstype: 3.1.3
'@vue/server-renderer@3.4.27(vue@3.4.27)':
'@vue/server-renderer@3.4.27(vue@3.4.27(typescript@5.4.5))':
dependencies:
'@vue/compiler-ssr': 3.4.27
'@vue/shared': 3.4.27
@ -4159,8 +4175,14 @@ snapshots:
dependencies:
loro-wasm: 0.16.0
loro-crdt@1.0.0-alpha.4:
dependencies:
loro-wasm: 1.0.0-alpha.4
loro-wasm@0.16.0: {}
loro-wasm@1.0.0-alpha.4: {}
loupe@2.3.7:
dependencies:
get-func-name: 2.0.2
@ -4836,9 +4858,9 @@ snapshots:
- supports-color
- terser
vite-plugin-top-level-await@1.4.1(vite@4.5.3):
vite-plugin-top-level-await@1.4.1(rollup@4.17.2)(vite@4.5.3):
dependencies:
'@rollup/plugin-virtual': 3.0.2
'@rollup/plugin-virtual': 3.0.2(rollup@4.17.2)
'@swc/core': 1.5.5
uuid: 9.0.1
vite: 4.5.3
@ -4846,10 +4868,24 @@ snapshots:
- '@swc/helpers'
- rollup
vite-plugin-top-level-await@1.4.1(rollup@4.17.2)(vite@5.2.11):
dependencies:
'@rollup/plugin-virtual': 3.0.2(rollup@4.17.2)
'@swc/core': 1.5.5
uuid: 9.0.1
vite: 5.2.11
transitivePeerDependencies:
- '@swc/helpers'
- rollup
vite-plugin-wasm@3.3.0(vite@4.5.3):
dependencies:
vite: 4.5.3
vite-plugin-wasm@3.3.0(vite@5.2.11):
dependencies:
vite: 5.2.11
vite@4.5.3:
dependencies:
esbuild: 0.18.20
@ -4872,7 +4908,6 @@ snapshots:
'@vitest/runner': 1.6.0
'@vitest/snapshot': 1.6.0
'@vitest/spy': 1.6.0
'@vitest/ui': 1.6.0(vitest@1.6.0)
'@vitest/utils': 1.6.0
acorn-walk: 8.3.2
chai: 4.4.1
@ -4889,6 +4924,8 @@ snapshots:
vite: 5.2.11
vite-node: 1.6.0
why-is-node-running: 2.2.2
optionalDependencies:
'@vitest/ui': 1.6.0(vitest@1.6.0)
transitivePeerDependencies:
- less
- lightningcss
@ -4915,8 +4952,9 @@ snapshots:
'@vue/compiler-dom': 3.4.27
'@vue/compiler-sfc': 3.4.27
'@vue/runtime-dom': 3.4.27
'@vue/server-renderer': 3.4.27(vue@3.4.27)
'@vue/server-renderer': 3.4.27(vue@3.4.27(typescript@5.4.5))
'@vue/shared': 3.4.27
optionalDependencies:
typescript: 5.4.5
wcwidth@1.0.1: