diff --git a/Cargo.lock b/Cargo.lock index e3298b27..7a6c0616 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -564,6 +564,16 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "364ff57c5031fee39b026dcdfdc9c7dc1d1d79451bfdacba90f040524b766254" +[[package]] +name = "debug-log" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d13e7dd03f70e6b332a2b42a9cdfa5b04f1015098c9656e77995c09772c947" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "derive_arbitrary" version = "1.3.1" @@ -721,13 +731,15 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -999,13 +1011,14 @@ dependencies = [ "crdt-list", "criterion 0.4.0", "ctor", - "debug-log", + "debug-log 0.1.4", "dhat", "enum-as-inner 0.5.1", "enum_dispatch", "flate2", "fxhash", "generic-btree", + "getrandom", "im", "itertools", "js-sys", @@ -1019,7 +1032,6 @@ dependencies = [ "proptest", "proptest-derive", "rand", - "ring", "rle", "serde", "serde-wasm-bindgen", @@ -1060,6 +1072,8 @@ name = "loro-wasm" version = "0.1.0" dependencies = [ "console_error_panic_hook", + "debug-log 0.2.1", + "getrandom", "js-sys", "loro-internal", "serde-wasm-bindgen", @@ -1725,7 +1739,7 @@ dependencies = [ "color-backtrace", "crdt-list", "ctor", - "debug-log", + "debug-log 0.1.4", "enum-as-inner 0.5.1", "fxhash", "heapless", diff --git a/crates/loro-internal/Cargo.toml b/crates/loro-internal/Cargo.toml index 7652232a..5de8d7af 100644 --- a/crates/loro-internal/Cargo.toml +++ b/crates/loro-internal/Cargo.toml @@ -13,7 +13,6 @@ loro-common = { path = "../loro-common" } smallvec = { version = "1.8.0", features = ["serde"] } smartstring = { version = "1.0.1" } fxhash = "0.2.1" -ring = "0.16.20" serde = { version = "1.0.140", features = ["derive"] } thiserror = "1.0.31" enum-as-inner = "0.5.1" @@ -40,6 +39,7 @@ generic-btree = "0.4.0" compact-bytes = { path = "../compact-bytes" } lz4_flex = "0.11.1" miniz_oxide = "0.7.1" +getrandom = "0.2.10" [dev-dependencies] serde_json = "1.0.87" diff --git a/crates/loro-internal/benches/text.rs b/crates/loro-internal/benches/text.rs index b0427b1c..6c17ca4b 100644 --- a/crates/loro-internal/benches/text.rs +++ b/crates/loro-internal/benches/text.rs @@ -61,8 +61,8 @@ mod run { let text = txn.get_text("text"); for TextAction { pos, ins, del } in actions.iter() { - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } txn.commit().unwrap(); diff --git a/crates/loro-internal/benches/text_r.rs b/crates/loro-internal/benches/text_r.rs index eb2c6b7b..1b7eadc7 100644 --- a/crates/loro-internal/benches/text_r.rs +++ b/crates/loro-internal/benches/text_r.rs @@ -20,8 +20,8 @@ mod run { let mut txn = loro.txn().unwrap(); for TextAction { pos, ins, del } in actions.iter() { - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } }) }); @@ -35,8 +35,8 @@ mod run { })); let mut txn = loro.txn().unwrap(); for TextAction { pos, ins, del } in actions.iter() { - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } }) }); @@ -54,8 +54,8 @@ mod run { txn = loro.txn().unwrap(); } n += 1; - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } txn.commit().unwrap(); @@ -77,8 +77,8 @@ mod run { txn = loro.txn().unwrap(); } n += 1; - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } txn.commit().unwrap(); @@ -99,8 +99,8 @@ mod run { txn = loro.txn().unwrap(); } n += 1; - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } txn.commit().unwrap(); @@ -124,8 +124,8 @@ mod run { txn = loro.txn().unwrap(); } n += 1; - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } txn.commit().unwrap(); @@ -143,8 +143,8 @@ mod run { let mut txn = loro.txn().unwrap(); for TextAction { pos, ins, del } in actions.iter() { - text.delete_utf16(&mut txn, *pos, *del); - text.insert_utf16(&mut txn, *pos, ins); + text.delete_utf16(&mut txn, *pos, *del).unwrap(); + text.insert_utf16(&mut txn, *pos, ins).unwrap(); } }) }); @@ -162,8 +162,8 @@ mod run { txn = loro.txn().unwrap(); } n += 1; - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } }) }); @@ -175,8 +175,8 @@ mod run { { for TextAction { pos, ins, del } in actions.iter() { let mut txn = loro.txn().unwrap(); - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); txn.commit().unwrap(); } } @@ -193,8 +193,8 @@ mod run { { for TextAction { pos, ins, del } in actions.iter() { let mut txn = loro.txn().unwrap(); - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); txn.commit().unwrap(); } } @@ -209,8 +209,8 @@ mod run { for TextAction { pos, ins, del } in actions.iter() { { let mut txn = loro.txn().unwrap(); - text.delete(&mut txn, *pos, *del); - text.insert(&mut txn, *pos, ins); + text.delete(&mut txn, *pos, *del).unwrap(); + text.insert(&mut txn, *pos, ins).unwrap(); } loro_b @@ -239,14 +239,14 @@ mod run { { let mut txn = loro.txn().unwrap(); - text.delete(&mut txn, pos, del); - text.insert(&mut txn, pos, ins); + text.delete(&mut txn, pos, del).unwrap(); + text.insert(&mut txn, pos, ins).unwrap(); } { let mut txn = loro_b.txn().unwrap(); - text2.delete(&mut txn, pos, del); - text2.insert(&mut txn, pos, ins); + text2.delete(&mut txn, pos, del).unwrap(); + text2.insert(&mut txn, pos, ins).unwrap(); } loro_b .import(&loro.export_from(&loro_b.vv_cloned())) diff --git a/crates/loro-internal/src/configure.rs b/crates/loro-internal/src/configure.rs index ec11ef70..11f2c5b1 100644 --- a/crates/loro-internal/src/configure.rs +++ b/crates/loro-internal/src/configure.rs @@ -1,7 +1,6 @@ use std::{fmt::Debug, sync::Arc}; use crate::{log_store::GcConfig, Timestamp}; -use ring::rand::{SecureRandom, SystemRandom}; #[derive(Clone)] pub struct Configure { @@ -19,6 +18,14 @@ impl Debug for Configure { } } +pub struct DefaultRandom; + +impl SecureRandomGenerator for DefaultRandom { + fn fill_byte(&self, dest: &mut [u8]) { + getrandom::getrandom(dest).unwrap(); + } +} + pub trait SecureRandomGenerator: Send + Sync { fn fill_byte(&self, dest: &mut [u8]); fn next_u64(&self) -> u64 { @@ -46,18 +53,12 @@ pub trait SecureRandomGenerator: Send + Sync { } } -impl SecureRandomGenerator for SystemRandom { - fn fill_byte(&self, dest: &mut [u8]) { - self.fill(dest).unwrap(); - } -} - impl Default for Configure { fn default() -> Self { Self { gc: GcConfig::default(), get_time: || 0, - rand: Arc::new(SystemRandom::new()), + rand: Arc::new(DefaultRandom), } } } diff --git a/crates/loro-internal/src/container.rs b/crates/loro-internal/src/container.rs index c9589ce4..8a6dc697 100644 --- a/crates/loro-internal/src/container.rs +++ b/crates/loro-internal/src/container.rs @@ -5,6 +5,7 @@ //! Every [Container] can take a [Snapshot], which contains [crate::LoroValue] that describes the state. //! use crate::{ + arena::SharedArena, event::{Observer, ObserverHandler, SubscriptionID}, hierarchy::Hierarchy, log_store::ImportContext, @@ -121,6 +122,41 @@ pub enum ContainerIdRaw { Normal { id: ID }, } +pub trait IntoContainerId { + fn into_container_id(self, arena: &SharedArena, kind: ContainerType) -> ContainerID; +} + +impl IntoContainerId for String { + fn into_container_id(self, _arena: &SharedArena, kind: ContainerType) -> ContainerID { + ContainerID::Root { + name: InternalString::from(self.as_str()), + container_type: kind, + } + } +} + +impl<'a> IntoContainerId for &'a str { + fn into_container_id(self, _arena: &SharedArena, kind: ContainerType) -> ContainerID { + ContainerID::Root { + name: InternalString::from(self), + container_type: kind, + } + } +} + +impl IntoContainerId for ContainerID { + fn into_container_id(self, _arena: &SharedArena, _kind: ContainerType) -> ContainerID { + self + } +} + +impl IntoContainerId for ContainerIdx { + fn into_container_id(self, arena: &SharedArena, kind: ContainerType) -> ContainerID { + assert_eq!(self.get_type(), kind); + arena.get_container_id(self).unwrap() + } +} + impl From for ContainerIdRaw { fn from(value: String) -> Self { ContainerIdRaw::Root { name: value.into() } diff --git a/crates/loro-internal/src/container/list/list_container.rs b/crates/loro-internal/src/container/list/list_container.rs index 528365a7..838516db 100644 --- a/crates/loro-internal/src/container/list/list_container.rs +++ b/crates/loro-internal/src/container/list/list_container.rs @@ -582,7 +582,6 @@ impl List { self.container_idx } - /// Inserts an element at position index within the List pub fn insert( &mut self, txn: &T, diff --git a/crates/loro-internal/src/fuzz.rs b/crates/loro-internal/src/fuzz.rs index b1892b36..6fb68fdf 100644 --- a/crates/loro-internal/src/fuzz.rs +++ b/crates/loro-internal/src/fuzz.rs @@ -213,13 +213,13 @@ impl Actionable for Vec { let site = &mut self[*site as usize]; let mut txn = site.txn().unwrap(); let text = txn.get_text("text"); - text.insert(&mut txn, *pos, &content.to_string()); + text.insert(&mut txn, *pos, &content.to_string()).unwrap(); } Action::Del { pos, len, site } => { let site = &mut self[*site as usize]; let mut txn = site.txn().unwrap(); let text = txn.get_text("text"); - text.delete(&mut txn, *pos, *len); + text.delete(&mut txn, *pos, *len).unwrap(); } Action::Sync { from, to } => { if from != to { diff --git a/crates/loro-internal/src/fuzz/recursive_refactored.rs b/crates/loro-internal/src/fuzz/recursive_refactored.rs index 9f76571c..50cfb280 100644 --- a/crates/loro-internal/src/fuzz/recursive_refactored.rs +++ b/crates/loro-internal/src/fuzz/recursive_refactored.rs @@ -504,13 +504,17 @@ impl Actionable for Vec { let mut txn = actor.loro.txn().unwrap(); match value { FuzzValue::Null => { - container.delete(&mut txn, &key.to_string()); + container.delete(&mut txn, &key.to_string()).unwrap(); } FuzzValue::I32(i) => { - container.insert(&mut txn, &key.to_string(), LoroValue::from(*i)); + container + .insert(&mut txn, &key.to_string(), LoroValue::from(*i)) + .unwrap(); } FuzzValue::Container(c) => { - let idx = container.insert_container(&mut txn, &key.to_string(), *c); + let idx = container + .insert_container(&mut txn, &key.to_string(), *c) + .unwrap(); actor.add_new_container(idx, *c); } }; @@ -534,13 +538,17 @@ impl Actionable for Vec { let mut txn = actor.loro.txn().unwrap(); match value { FuzzValue::Null => { - container.delete(&mut txn, *key as usize, 1); + container.delete(&mut txn, *key as usize, 1).unwrap(); } FuzzValue::I32(i) => { - container.insert(&mut txn, *key as usize, LoroValue::from(*i)); + container + .insert(&mut txn, *key as usize, LoroValue::from(*i)) + .unwrap(); } FuzzValue::Container(c) => { - let idx = container.insert_container(&mut txn, *key as usize, *c); + let idx = container + .insert_container(&mut txn, *key as usize, *c) + .unwrap(); actor.add_new_container(idx, *c); } }; @@ -563,9 +571,13 @@ impl Actionable for Vec { }; let mut txn = actor.loro.txn().unwrap(); if *is_del { - container.delete(&mut txn, *pos as usize, *value as usize); + container + .delete(&mut txn, *pos as usize, *value as usize) + .unwrap(); } else { - container.insert(&mut txn, *pos as usize, &(format!("[{}]", value))); + container + .insert(&mut txn, *pos as usize, &(format!("[{}]", value))) + .unwrap(); } drop(txn); } diff --git a/crates/loro-internal/src/lib.rs b/crates/loro-internal/src/lib.rs index 3663fa3c..c8c59ae6 100644 --- a/crates/loro-internal/src/lib.rs +++ b/crates/loro-internal/src/lib.rs @@ -16,6 +16,7 @@ pub mod log_store; pub mod op; pub mod refactor; pub mod version; +pub use refactor::*; mod error; #[cfg(feature = "test_utils")] diff --git a/crates/loro-internal/src/refactor/event.rs b/crates/loro-internal/src/refactor/event.rs index fba36cc8..218b985d 100644 --- a/crates/loro-internal/src/refactor/event.rs +++ b/crates/loro-internal/src/refactor/event.rs @@ -17,7 +17,7 @@ pub struct ContainerDiff { pub diff: Diff, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct DiffEvent<'a> { /// whether the event comes from the children of the container. pub from_children: bool, @@ -73,3 +73,30 @@ impl<'a> InternalDocDiff<'a> { self.origin == other.origin && self.local == other.local } } + +#[cfg(test)] +mod test { + use std::sync::Arc; + + use crate::LoroDoc; + + #[test] + fn test_text_event() { + let loro = LoroDoc::new(); + loro.subscribe_deep(Arc::new(|event| { + assert_eq!( + &event.container.diff.as_text().unwrap().vec[0] + .as_insert() + .unwrap() + .0, + &"h223ello" + ); + dbg!(event); + })); + let mut txn = loro.txn().unwrap(); + let text = loro.get_text("id"); + text.insert(&mut txn, 0, "hello").unwrap(); + text.insert(&mut txn, 1, "223").unwrap(); + txn.commit().unwrap(); + } +} diff --git a/crates/loro-internal/src/refactor/handler.rs b/crates/loro-internal/src/refactor/handler.rs index 66b0f713..9064f532 100644 --- a/crates/loro-internal/src/refactor/handler.rs +++ b/crates/loro-internal/src/refactor/handler.rs @@ -1,10 +1,13 @@ use super::{state::DocState, txn::Transaction}; -use crate::container::{ - list::list_op::{DeleteSpan, ListOp}, - registry::ContainerIdx, - text::text_content::ListSlice, +use crate::{ + container::{ + list::list_op::{DeleteSpan, ListOp}, + registry::ContainerIdx, + text::text_content::ListSlice, + }, + txn::EventHint, }; -use loro_common::{ContainerID, ContainerType, LoroValue}; +use loro_common::{ContainerID, ContainerType, LoroResult, LoroValue}; use std::{ borrow::Cow, sync::{Mutex, Weak}, @@ -81,15 +84,15 @@ impl TextHandler { } } -#[cfg(not(features = "wasm"))] +#[cfg(not(feature = "wasm"))] impl TextHandler { #[inline(always)] - pub fn insert(&self, txn: &mut Transaction, pos: usize, s: &str) { + pub fn insert(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> { self.insert_utf8(txn, pos, s) } #[inline(always)] - pub fn delete(&self, txn: &mut Transaction, pos: usize, len: usize) { + pub fn delete(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> { self.delete_utf8(txn, pos, len) } @@ -98,9 +101,9 @@ impl TextHandler { self.len_utf8() } - pub fn insert_utf8(&self, txn: &mut Transaction, pos: usize, s: &str) { + pub fn insert_utf8(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> { if s.is_empty() { - return; + return Ok(()); } txn.apply_local_op( @@ -110,12 +113,12 @@ impl TextHandler { pos, }), None, - ); + ) } - pub fn delete_utf8(&self, txn: &mut Transaction, pos: usize, len: usize) { + pub fn delete_utf8(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> { if len == 0 { - return; + return Ok(()); } txn.apply_local_op( @@ -125,12 +128,12 @@ impl TextHandler { len: len as isize, })), None, - ); + ) } - pub fn insert_utf16(&self, txn: &mut Transaction, pos: usize, s: &str) { + pub fn insert_utf16(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> { if s.is_empty() { - return; + return Ok(()); } let start = @@ -152,12 +155,14 @@ impl TextHandler { pos: start, }), None, - ); + )?; + + Ok(()) } - pub fn delete_utf16(&self, txn: &mut Transaction, pos: usize, del: usize) { + pub fn delete_utf16(&self, txn: &mut Transaction, pos: usize, del: usize) -> LoroResult<()> { if del == 0 { - return; + return Ok(()); } let (start, end) = @@ -178,11 +183,11 @@ impl TextHandler { len: (end - start) as isize, })), None, - ); + ) } } -#[cfg(features = "wasm")] +#[cfg(feature = "wasm")] impl TextHandler { #[inline(always)] pub fn len(&self) -> usize { @@ -190,29 +195,18 @@ impl TextHandler { } #[inline(always)] - pub fn delete(&self, txn: &mut Transaction, pos: usize, del: usize) { + pub fn delete(&self, txn: &mut Transaction, pos: usize, del: usize) -> LoroResult<()> { self.delete_utf16(txn, pos, del) } #[inline(always)] - pub fn insert(&self, txn: &mut Transaction, pos: usize, s: &str) { + pub fn insert(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> { self.insert_utf16(txn, pos, s) } - pub fn len_utf16(&self) -> usize { - self.state - .upgrade() - .unwrap() - .lock() - .unwrap() - .with_state(self.container_idx, |state| { - state.as_text_state().as_ref().unwrap().len_wchars() - }) - } - - pub fn insert_utf16(&self, txn: &mut Transaction, pos: usize, s: &str) { + pub fn insert_utf16(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> { if s.is_empty() { - return; + return Ok(()); } let start = @@ -234,12 +228,12 @@ impl TextHandler { pos: start, }), Some(EventHint::Utf16 { pos, len: 0 }), - ); + ) } - pub fn delete_utf16(&self, txn: &mut Transaction, pos: usize, del: usize) { + pub fn delete_utf16(&self, txn: &mut Transaction, pos: usize, del: usize) -> LoroResult<()> { if del == 0 { - return; + return Ok(()); } let (start, end) = @@ -260,7 +254,7 @@ impl TextHandler { len: (end - start) as isize, })), Some(EventHint::Utf16 { pos, len: del }), - ); + ) } } @@ -273,10 +267,10 @@ impl ListHandler { } } - pub fn insert(&self, txn: &mut Transaction, pos: usize, v: LoroValue) { + pub fn insert(&self, txn: &mut Transaction, pos: usize, v: LoroValue) -> LoroResult<()> { if let Some(container) = v.as_container() { - self.insert_container(txn, pos, container.container_type()); - return; + self.insert_container(txn, pos, container.container_type())?; + return Ok(()); } txn.apply_local_op( @@ -286,7 +280,7 @@ impl ListHandler { pos, }), None, - ); + ) } pub fn insert_container( @@ -294,7 +288,7 @@ impl ListHandler { txn: &mut Transaction, pos: usize, c_type: ContainerType, - ) -> ContainerIdx { + ) -> LoroResult { let id = txn.next_id(); let container_id = ContainerID::new_normal(id, c_type); let child_idx = txn.arena.register_container(&container_id); @@ -307,13 +301,13 @@ impl ListHandler { pos, }), None, - ); - child_idx + )?; + Ok(child_idx) } - pub fn delete(&self, txn: &mut Transaction, pos: usize, len: usize) { + pub fn delete(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> { if len == 0 { - return; + return Ok(()); } txn.apply_local_op( @@ -323,10 +317,10 @@ impl ListHandler { len: len as isize, })), None, - ); + ) } - pub(crate) fn len(&self) -> usize { + pub fn len(&self) -> usize { self.state .upgrade() .unwrap() @@ -337,7 +331,7 @@ impl ListHandler { }) } - pub(crate) fn is_empty(&self) -> bool { + pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -360,6 +354,18 @@ impl ListHandler { .idx_to_id(self.container_idx) .unwrap() } + + pub fn get(&self, index: usize) -> Option { + self.state + .upgrade() + .unwrap() + .lock() + .unwrap() + .with_state(self.container_idx, |state| { + let a = state.as_list_state().unwrap(); + a.get(index).cloned() + }) + } } impl MapHandler { @@ -371,10 +377,10 @@ impl MapHandler { } } - pub fn insert(&self, txn: &mut Transaction, key: &str, value: LoroValue) { + pub fn insert(&self, txn: &mut Transaction, key: &str, value: LoroValue) -> LoroResult<()> { if let Some(value) = value.as_container() { - self.insert_container(txn, key, value.container_type()); - return; + self.insert_container(txn, key, value.container_type())?; + return Ok(()); } txn.apply_local_op( @@ -384,7 +390,7 @@ impl MapHandler { value, }), None, - ); + ) } pub fn insert_container( @@ -392,7 +398,7 @@ impl MapHandler { txn: &mut Transaction, key: &str, c_type: ContainerType, - ) -> ContainerIdx { + ) -> LoroResult { let id = txn.next_id(); let container_id = ContainerID::new_normal(id, c_type); let child_idx = txn.arena.register_container(&container_id); @@ -404,11 +410,11 @@ impl MapHandler { value: LoroValue::Container(container_id), }), None, - ); - child_idx + )?; + Ok(child_idx) } - pub fn delete(&self, txn: &mut Transaction, key: &str) { + pub fn delete(&self, txn: &mut Transaction, key: &str) -> LoroResult<()> { txn.apply_local_op( self.container_idx, crate::op::RawOpContent::Map(crate::container::map::MapSet { @@ -417,7 +423,7 @@ impl MapHandler { value: LoroValue::Null, }), None, - ); + ) } pub fn get_value(&self) -> LoroValue { @@ -429,6 +435,18 @@ impl MapHandler { .get_value_by_idx(self.container_idx) } + pub fn get(&self, key: &str) -> Option { + self.state + .upgrade() + .unwrap() + .lock() + .unwrap() + .with_state(self.container_idx, |state| { + let a = state.as_map_state().unwrap(); + a.get(key).cloned() + }) + } + pub fn id(&self) -> ContainerID { self.state .upgrade() @@ -439,6 +457,21 @@ impl MapHandler { .idx_to_id(self.container_idx) .unwrap() } + + pub fn len(&self) -> usize { + self.state + .upgrade() + .unwrap() + .lock() + .unwrap() + .with_state(self.container_idx, |state| { + state.as_map_state().as_ref().unwrap().len() + }) + } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } #[cfg(test)] @@ -451,14 +484,14 @@ mod test { let loro = LoroDoc::new(); let mut txn = loro.txn().unwrap(); let text = txn.get_text("hello"); - text.insert(&mut txn, 0, "hello"); + text.insert(&mut txn, 0, "hello").unwrap(); assert_eq!(&**text.get_value().as_string().unwrap(), "hello"); - text.insert(&mut txn, 2, " kk "); + text.insert(&mut txn, 2, " kk ").unwrap(); assert_eq!(&**text.get_value().as_string().unwrap(), "he kk llo"); txn.abort(); let mut txn = loro.txn().unwrap(); assert_eq!(&**text.get_value().as_string().unwrap(), ""); - text.insert(&mut txn, 0, "hi"); + text.insert(&mut txn, 0, "hi").unwrap(); txn.commit().unwrap(); assert_eq!(&**text.get_value().as_string().unwrap(), "hi"); } @@ -472,14 +505,14 @@ mod test { let mut txn = loro.txn().unwrap(); let text = txn.get_text("hello"); - text.insert(&mut txn, 0, "hello"); + text.insert(&mut txn, 0, "hello").unwrap(); txn.commit().unwrap(); let exported = loro.export_from(&Default::default()); loro2.import(&exported).unwrap(); let mut txn = loro2.txn().unwrap(); let text = txn.get_text("hello"); assert_eq!(&**text.get_value().as_string().unwrap(), "hello"); - text.insert(&mut txn, 5, " world"); + text.insert(&mut txn, 5, " world").unwrap(); assert_eq!(&**text.get_value().as_string().unwrap(), "hello world"); txn.commit().unwrap(); loro.import(&loro2.export_from(&Default::default())) diff --git a/crates/loro-internal/src/refactor/loro.rs b/crates/loro-internal/src/refactor/loro.rs index 4dba892b..39c72598 100644 --- a/crates/loro-internal/src/refactor/loro.rs +++ b/crates/loro-internal/src/refactor/loro.rs @@ -1,15 +1,18 @@ use std::{ borrow::Cow, + cmp::Ordering, sync::{Arc, Mutex}, }; use debug_log::debug_dbg; -use loro_common::{ContainerID, ContainerType, LoroValue}; +use loro_common::{ContainerID, ContainerType, LoroResult, LoroValue}; use crate::{ - container::{registry::ContainerIdx, ContainerIdRaw}, + arena::SharedArena, + container::{registry::ContainerIdx, IntoContainerId}, id::PeerID, log_store::encoding::{ConcreteEncodeMode, ENCODE_SCHEMA_VERSION, MAGIC_BYTES}, + version::Frontiers, EncodeMode, InternalString, LoroError, VersionVector, }; @@ -44,6 +47,7 @@ use super::{ pub struct LoroDoc { oplog: Arc>, state: Arc>, + arena: SharedArena, observer: Arc, detached: bool, } @@ -58,7 +62,8 @@ impl LoroDoc { oplog: Arc::new(Mutex::new(oplog)), state, detached: false, - observer: Arc::new(Observer::new(arena)), + observer: Arc::new(Observer::new(arena.clone())), + arena, } } @@ -69,6 +74,7 @@ impl LoroDoc { pub(super) fn from_existing(oplog: OpLog, state: DocState) -> Self { let obs = Observer::new(oplog.arena.clone()); Self { + arena: oplog.arena.clone(), observer: Arc::new(obs), oplog: Arc::new(Mutex::new(oplog)), state: Arc::new(Mutex::new(state)), @@ -76,6 +82,10 @@ impl LoroDoc { } } + pub fn peer_id(&self) -> PeerID { + self.state.lock().unwrap().peer + } + pub fn set_peer_id(&self, peer: PeerID) { self.state.lock().unwrap().peer = peer; } @@ -105,18 +115,23 @@ impl LoroDoc { }); } + #[inline(always)] pub fn txn(&self) -> Result { - if self.state.lock().unwrap().is_in_txn() { - return Err(LoroError::DuplicatedTransactionError); + self.txn_with_origin("") + } + + pub fn txn_with_origin(&self, origin: &str) -> Result { + let mut txn = + Transaction::new_with_origin(self.state.clone(), self.oplog.clone(), origin.into()); + if self.state.lock().unwrap().is_recording() { + let obs = self.observer.clone(); + txn.set_on_commit(Box::new(move |state| { + let events = state.lock().unwrap().take_events(); + for event in events { + obs.emit(event); + } + })); } - let mut txn = Transaction::new(self.state.clone(), self.oplog.clone()); - let obs = self.observer.clone(); - txn.set_on_commit(Box::new(move |state| { - let events = state.lock().unwrap().take_events(); - for event in events { - obs.emit(event); - } - })); Ok(txn) } @@ -228,21 +243,21 @@ impl LoroDoc { /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_text>(&self, id: I) -> TextHandler { + pub fn get_text(&self, id: I) -> TextHandler { let idx = self.get_container_idx(id, ContainerType::Text); TextHandler::new(idx, Arc::downgrade(&self.state)) } /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_list>(&self, id: I) -> ListHandler { + pub fn get_list(&self, id: I) -> ListHandler { let idx = self.get_container_idx(id, ContainerType::List); ListHandler::new(idx, Arc::downgrade(&self.state)) } /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_map>(&self, id: I) -> MapHandler { + pub fn get_map(&self, id: I) -> MapHandler { let idx = self.get_container_idx(id, ContainerType::Map); MapHandler::new(idx, Arc::downgrade(&self.state)) } @@ -251,26 +266,20 @@ impl LoroDoc { self.oplog().lock().unwrap().diagnose_size(); } - fn get_container_idx>( - &self, - id: I, - c_type: ContainerType, - ) -> ContainerIdx { - let id: ContainerIdRaw = id.into(); - match id { - ContainerIdRaw::Root { name } => self.oplog().lock().unwrap().arena.register_container( - &crate::container::ContainerID::Root { - name, - container_type: c_type, - }, - ), - ContainerIdRaw::Normal { id: _ } => self - .oplog() - .lock() - .unwrap() - .arena - .register_container(&id.with_type(c_type)), - } + fn get_container_idx(&self, id: I, c_type: ContainerType) -> ContainerIdx { + let id = id.into_container_id(&self.arena, c_type); + self.arena.register_container(&id) + } + + pub fn frontiers(&self) -> Frontiers { + self.oplog().lock().unwrap().frontiers().clone() + } + + /// - Ordering::Less means self is less than target or parallel + /// - Ordering::Equal means versions equal + /// - Ordering::Greater means self's version is greater than target + pub fn cmp_frontiers(&self, other: &Frontiers) -> Ordering { + self.oplog().lock().unwrap().cmp_frontiers(other) } pub fn subscribe_deep(&self, callback: Subscriber) -> SubID { @@ -294,6 +303,19 @@ impl LoroDoc { pub fn unsubscribe(&self, id: SubID) { self.observer.unsubscribe(id); } + + // PERF: opt + pub fn import_batch(&self, bytes: &[Vec]) -> LoroResult<()> { + for data in bytes.iter() { + self.import(data)?; + } + + Ok(()) + } + + pub fn to_json(&self) -> LoroValue { + self.state.lock().unwrap().get_deep_value() + } } impl Default for LoroDoc { diff --git a/crates/loro-internal/src/refactor/mod.rs b/crates/loro-internal/src/refactor/mod.rs index dbd2c31a..efd1269e 100644 --- a/crates/loro-internal/src/refactor/mod.rs +++ b/crates/loro-internal/src/refactor/mod.rs @@ -4,7 +4,11 @@ pub(super) mod arena; mod container; pub(super) mod diff_calc; pub mod handler; +pub use event::{ContainerDiff, DiffEvent, DocDiff}; pub use handler::{ListHandler, MapHandler, TextHandler}; +pub use loro::LoroDoc; +pub use oplog::OpLog; +pub use state::DocState; pub mod event; pub mod loro; pub mod obs; diff --git a/crates/loro-internal/src/refactor/obs.rs b/crates/loro-internal/src/refactor/obs.rs index 96486b68..3aa255da 100644 --- a/crates/loro-internal/src/refactor/obs.rs +++ b/crates/loro-internal/src/refactor/obs.rs @@ -1,5 +1,5 @@ use std::sync::{ - atomic::{AtomicUsize, Ordering}, + atomic::{AtomicU32, AtomicUsize, Ordering}, Arc, Mutex, }; @@ -25,12 +25,22 @@ struct ObserverInner { } #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct SubID(usize); +pub struct SubID(u32); + +impl SubID { + pub fn into_u32(self) -> u32 { + self.0 + } + + pub fn from_u32(id: u32) -> Self { + Self(id) + } +} pub struct Observer { inner: Mutex, arena: SharedArena, - next_sub_id: AtomicUsize, + next_sub_id: AtomicU32, taken_times: AtomicUsize, } @@ -38,7 +48,7 @@ impl Observer { pub fn new(arena: SharedArena) -> Self { Self { arena, - next_sub_id: AtomicUsize::new(0), + next_sub_id: AtomicU32::new(0), taken_times: AtomicUsize::new(0), inner: Mutex::new(ObserverInner { subscribers: Default::default(), @@ -223,14 +233,14 @@ mod test { if text.get_value().as_string().unwrap().len() > 10 { return; } - text.insert(&mut txn, 0, "123"); + text.insert(&mut txn, 0, "123").unwrap(); txn.commit().unwrap(); })); let loro = loro_cp; let mut txn = loro.txn().unwrap(); let text = loro.get_text("id"); - text.insert(&mut txn, 0, "123"); + text.insert(&mut txn, 0, "123").unwrap(); txn.commit().unwrap(); let count = count.load(Ordering::SeqCst); assert!(count > 2, "{}", count); @@ -250,20 +260,20 @@ mod test { assert_eq!(count.load(Ordering::SeqCst), 0); { let mut txn = loro.txn().unwrap(); - text.insert(&mut txn, 0, "123"); + text.insert(&mut txn, 0, "123").unwrap(); txn.commit().unwrap(); } assert_eq!(count.load(Ordering::SeqCst), 1); { let mut txn = loro.txn().unwrap(); - text.insert(&mut txn, 0, "123"); + text.insert(&mut txn, 0, "123").unwrap(); txn.commit().unwrap(); } assert_eq!(count.load(Ordering::SeqCst), 2); loro.unsubscribe(sub); { let mut txn = loro.txn().unwrap(); - text.insert(&mut txn, 0, "123"); + text.insert(&mut txn, 0, "123").unwrap(); txn.commit().unwrap(); } assert_eq!(count.load(Ordering::SeqCst), 2); diff --git a/crates/loro-internal/src/refactor/oplog.rs b/crates/loro-internal/src/refactor/oplog.rs index d5d807de..0c2147c7 100644 --- a/crates/loro-internal/src/refactor/oplog.rs +++ b/crates/loro-internal/src/refactor/oplog.rs @@ -2,6 +2,7 @@ pub(crate) mod dag; use std::borrow::Cow; use std::cell::RefCell; +use std::cmp::Ordering; use std::rc::Rc; use fxhash::FxHashMap; @@ -234,6 +235,13 @@ impl OpLog { &self.dag.frontiers } + /// - Ordering::Less means self is less than target or parallel + /// - Ordering::Equal means versions equal + /// - Ordering::Greater means self's version is greater than target + pub fn cmp_frontiers(&self, other: &Frontiers) -> Ordering { + self.dag.cmp_frontiers(other) + } + pub(crate) fn export_changes_from(&self, from: &VersionVector) -> RemoteClientChanges { let mut changes = RemoteClientChanges::default(); for (&peer, &cnt) in self.vv().iter() { diff --git a/crates/loro-internal/src/refactor/oplog/dag.rs b/crates/loro-internal/src/refactor/oplog/dag.rs index 20048092..a6ba7393 100644 --- a/crates/loro-internal/src/refactor/oplog/dag.rs +++ b/crates/loro-internal/src/refactor/oplog/dag.rs @@ -200,4 +200,17 @@ impl AppDag { pub fn get_frontiers(&self) -> &Frontiers { &self.frontiers } + + /// - Ordering::Less means self is less than target or parallel + /// - Ordering::Equal means versions equal + /// - Ordering::Greater means self's version is greater than target + pub fn cmp_frontiers(&self, other: &Frontiers) -> Ordering { + if &self.frontiers == other { + Ordering::Equal + } else if other.iter().all(|id| self.vv.includes_id(*id)) { + Ordering::Greater + } else { + Ordering::Less + } + } } diff --git a/crates/loro-internal/src/refactor/snapshot_encode.rs b/crates/loro-internal/src/refactor/snapshot_encode.rs index cbca791f..cc8384fe 100644 --- a/crates/loro-internal/src/refactor/snapshot_encode.rs +++ b/crates/loro-internal/src/refactor/snapshot_encode.rs @@ -800,7 +800,7 @@ mod test { let app = LoroDoc::new(); let mut txn = app.txn().unwrap(); let text = txn.get_text("id"); - text.insert(&mut txn, 0, "hello"); + text.insert(&mut txn, 0, "hello").unwrap(); txn.commit().unwrap(); let snapshot = app.export_snapshot(); let app2 = LoroDoc::new(); @@ -818,7 +818,7 @@ mod test { // test import snapshot to a LoroApp that is already changed let mut txn = app2.txn().unwrap(); let text = txn.get_text("id"); - text.insert(&mut txn, 2, " "); + text.insert(&mut txn, 2, " ").unwrap(); txn.commit().unwrap(); debug_log::group!("app2 export"); let snapshot = app2.export_snapshot(); diff --git a/crates/loro-internal/src/refactor/state.rs b/crates/loro-internal/src/refactor/state.rs index a774454f..2ed6707d 100644 --- a/crates/loro-internal/src/refactor/state.rs +++ b/crates/loro-internal/src/refactor/state.rs @@ -4,11 +4,10 @@ use debug_log::debug_dbg; use enum_as_inner::EnumAsInner; use enum_dispatch::enum_dispatch; use fxhash::{FxHashMap, FxHashSet}; -use loro_common::ContainerID; -use ring::rand::SystemRandom; +use loro_common::{ContainerID, LoroResult}; use crate::{ - configure::SecureRandomGenerator, + configure::{DefaultRandom, SecureRandomGenerator}, container::{registry::ContainerIdx, ContainerIdRaw}, delta::{Delta, DeltaItem}, event::{Diff, Index, Utf16Meta}, @@ -105,7 +104,7 @@ impl State { impl DocState { #[inline] pub fn new(arena: SharedArena) -> Self { - let peer = SystemRandom::new().next_u64(); + let peer = DefaultRandom.next_u64(); // TODO: maybe we should switch to certain version in oplog? Self { peer, @@ -242,7 +241,7 @@ impl DocState { debug_dbg!(self.get_deep_value()); } - pub fn apply_local_op(&mut self, op: RawOp) { + pub fn apply_local_op(&mut self, op: RawOp) -> LoroResult<()> { let state = self .states .entry(op.container) @@ -253,7 +252,9 @@ impl DocState { self.changed_idx_in_txn.insert(op.container); } + // TODO: make apply_op return a result state.apply_op(op, &self.arena); + Ok(()) } pub(crate) fn start_txn(&mut self, origin: InternalString, local: bool) { @@ -539,7 +540,6 @@ impl DocState { match idx.get_type() { ContainerType::Text => { - let state = self.states.get(&idx).unwrap().as_text_state().unwrap(); let mut ans: Delta = Delta::new(); let mut index = 0; for span in seq.iter() { @@ -554,10 +554,12 @@ impl DocState { crate::delta::DeltaItem::Insert { value, .. } => { let len = value.0.iter().fold(0, |acc, cur| acc + cur.0.len()); let mut s = String::with_capacity(len); - for sub in state.slice(index..index + len) { - s.push_str(sub); + for slice in value.0.iter() { + let bytes = self + .arena + .slice_bytes(slice.0.start as usize..slice.0.end as usize); + s.push_str(std::str::from_utf8(&bytes).unwrap()); } - ans.push(DeltaItem::Insert { value: s, meta: Utf16Meta { utf16_len: None }, diff --git a/crates/loro-internal/src/refactor/state/list_state.rs b/crates/loro-internal/src/refactor/state/list_state.rs index 43714318..e5c5ca03 100644 --- a/crates/loro-internal/src/refactor/state/list_state.rs +++ b/crates/loro-internal/src/refactor/state/list_state.rs @@ -247,6 +247,15 @@ impl ListState { } ans } + + pub fn get(&self, index: usize) -> Option<&LoroValue> { + let result = self.list.query::(&index); + if result.found { + Some(result.elem(&self.list).unwrap()) + } else { + None + } + } } impl ContainerState for ListState { diff --git a/crates/loro-internal/src/refactor/state/map_state.rs b/crates/loro-internal/src/refactor/state/map_state.rs index aa4dcd1d..b2362654 100644 --- a/crates/loro-internal/src/refactor/state/map_state.rs +++ b/crates/loro-internal/src/refactor/state/map_state.rs @@ -142,7 +142,7 @@ impl MapState { self.map.iter() } - fn len(&self) -> usize { + pub fn len(&self) -> usize { self.map.len() } @@ -160,4 +160,14 @@ impl MapState { } ans } + + pub fn get(&self, k: &str) -> Option<&LoroValue> { + match self.map.get(&k.into()) { + Some(value) => match &value.value { + Some(v) => Some(v), + None => None, + }, + None => None, + } + } } diff --git a/crates/loro-internal/src/refactor/state/text_state.rs b/crates/loro-internal/src/refactor/state/text_state.rs index cae32f09..7dcfe385 100644 --- a/crates/loro-internal/src/refactor/state/text_state.rs +++ b/crates/loro-internal/src/refactor/state/text_state.rs @@ -233,7 +233,7 @@ impl TextState { self.rope.slice_substrings(range) } - #[cfg(not(features = "wasm"))] + #[cfg(not(feature = "wasm"))] fn apply_seq_raw( &mut self, delta: &mut Delta, @@ -261,7 +261,7 @@ impl TextState { None } - #[cfg(features = "wasm")] + #[cfg(feature = "wasm")] fn apply_seq_raw( &mut self, delta: &mut Delta, @@ -283,14 +283,14 @@ impl TextState { let start_utf16_len = self.len_wchars(); for value in value.0.iter() { let s = arena.slice_bytes(value.0.start as usize..value.0.end as usize); - self.insert(index, std::str::from_utf8(&s).unwrap()); + self.insert_utf8(index, std::str::from_utf8(&s).unwrap()); index += s.len(); } utf16_index += self.len_wchars() - start_utf16_len; } DeltaItem::Delete { len, .. } => { let start_utf16_len = self.len_wchars(); - self.delete(index..index + len); + self.delete_utf8(index..index + len); new_delta = new_delta.delete(start_utf16_len - self.len_wchars()); } } diff --git a/crates/loro-internal/src/refactor/txn.rs b/crates/loro-internal/src/refactor/txn.rs index f5341969..22998045 100644 --- a/crates/loro-internal/src/refactor/txn.rs +++ b/crates/loro-internal/src/refactor/txn.rs @@ -4,9 +4,10 @@ use std::{ sync::{Arc, Mutex}, }; +use debug_log::debug_dbg; use enum_as_inner::EnumAsInner; use fxhash::FxHashMap; -use loro_common::ContainerType; +use loro_common::{ContainerType, LoroResult}; use rle::{HasLength, RleVec}; use smallvec::smallvec; @@ -14,7 +15,7 @@ use crate::{ change::{Change, Lamport}, container::{ list::list_op::InnerListOp, registry::ContainerIdx, text::text_content::SliceRanges, - ContainerIdRaw, + IntoContainerId, }, delta::{Delta, MapValue}, event::Diff, @@ -68,6 +69,10 @@ impl Transaction { origin: InternalString, ) -> Self { let mut state_lock = state.lock().unwrap(); + if state_lock.is_in_txn() { + panic!("Cannot start a transaction while another one is in progress"); + } + let oplog_lock = oplog.lock().unwrap(); state_lock.start_txn(origin, true); let arena = state_lock.arena.clone(); @@ -186,7 +191,7 @@ impl Transaction { content: RawOpContent, // we need extra hint to reduce calculation for utf16 text op hint: Option, - ) { + ) -> LoroResult<()> { let len = content.content_len(); let op = RawOp { id: ID { @@ -198,14 +203,16 @@ impl Transaction { content, }; + let mut state = self.state.lock().unwrap(); + state.apply_local_op(op.clone())?; + drop(state); if let Some(hint) = hint { self.event_hints.insert(op.id.counter, hint); } self.push_local_op_to_log(&op); - let mut state = self.state.lock().unwrap(); - state.apply_local_op(op); self.next_counter += len as Counter; self.next_lamport += len as Lamport; + Ok(()) } fn push_local_op_to_log(&mut self, op: &RawOp) { @@ -215,43 +222,28 @@ impl Transaction { /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_text>(&self, id: I) -> TextHandler { + pub fn get_text(&self, id: I) -> TextHandler { let idx = self.get_container_idx(id, ContainerType::Text); TextHandler::new(idx, Arc::downgrade(&self.state)) } /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_list>(&self, id: I) -> ListHandler { + pub fn get_list(&self, id: I) -> ListHandler { let idx = self.get_container_idx(id, ContainerType::List); ListHandler::new(idx, Arc::downgrade(&self.state)) } /// id can be a str, ContainerID, or ContainerIdRaw. /// if it's str it will use Root container, which will not be None - pub fn get_map>(&self, id: I) -> MapHandler { + pub fn get_map(&self, id: I) -> MapHandler { let idx = self.get_container_idx(id, ContainerType::Map); MapHandler::new(idx, Arc::downgrade(&self.state)) } - fn get_container_idx>( - &self, - id: I, - c_type: ContainerType, - ) -> ContainerIdx { - let id: ContainerIdRaw = id.into(); - match id { - ContainerIdRaw::Root { name } => { - self.arena - .register_container(&crate::container::ContainerID::Root { - name, - container_type: c_type, - }) - } - ContainerIdRaw::Normal { id: _ } => { - self.arena.register_container(&id.with_type(c_type)) - } - } + fn get_container_idx(&self, id: I, c_type: ContainerType) -> ContainerIdx { + let id = id.into_container_id(&self.arena, c_type); + self.arena.register_container(&id) } pub fn get_value_by_idx(&self, idx: ContainerIdx) -> LoroValue { @@ -351,5 +343,7 @@ fn change_to_diff( lamport += op.content_len() as Lamport; diff.push(diff_op); } + + debug_dbg!(&diff); diff } diff --git a/crates/loro-internal/src/value.rs b/crates/loro-internal/src/value.rs index 9c401480..ab53128a 100644 --- a/crates/loro-internal/src/value.rs +++ b/crates/loro-internal/src/value.rs @@ -288,7 +288,7 @@ pub mod wasm { use wasm_bindgen::{JsValue, __rt::IntoJsResult}; use crate::{ - delta::{Delta, DeltaItem, MapDiff}, + delta::{Delta, DeltaItem, MapDelta, MapDiff}, event::{Diff, Index, Utf16Meta}, LoroValue, }; @@ -385,12 +385,7 @@ pub mod wasm { ) .unwrap(); - js_sys::Reflect::set( - &obj, - &JsValue::from_str("diff"), - &serde_wasm_bindgen::to_value(&map).unwrap(), - ) - .unwrap(); + js_sys::Reflect::set(&obj, &JsValue::from_str("updated"), &map.into()).unwrap(); } Diff::SeqRaw(text) => { // set type as "text" @@ -431,6 +426,22 @@ pub mod wasm { } } + impl From for JsValue { + fn from(value: MapDelta) -> Self { + let obj = Object::new(); + for (key, value) in value.updated.iter() { + js_sys::Reflect::set( + &obj, + &JsValue::from_str(key), + &JsValue::from(value.value.clone()), + ) + .unwrap(); + } + + obj.into_js_result().unwrap() + } + } + impl From> for JsValue { fn from(value: MapDiff) -> Self { let obj = Object::new(); @@ -508,7 +519,7 @@ pub mod wasm { fn from(value: DeltaItem) -> Self { let obj = Object::new(); match value { - DeltaItem::Retain { len: _len, meta } => { + DeltaItem::Retain { len, meta: _ } => { js_sys::Reflect::set( &obj, &JsValue::from_str("type"), @@ -518,7 +529,7 @@ pub mod wasm { js_sys::Reflect::set( &obj, &JsValue::from_str("len"), - &JsValue::from_f64(meta.utf16_len.unwrap() as f64), + &JsValue::from_f64(len as f64), ) .unwrap(); } @@ -537,7 +548,7 @@ pub mod wasm { ) .unwrap(); } - DeltaItem::Delete { len: _len, meta } => { + DeltaItem::Delete { len, meta: _ } => { js_sys::Reflect::set( &obj, &JsValue::from_str("type"), @@ -547,7 +558,7 @@ pub mod wasm { js_sys::Reflect::set( &obj, &JsValue::from_str("len"), - &JsValue::from_f64(meta.utf16_len.unwrap() as f64), + &JsValue::from_f64(len as f64), ) .unwrap(); } diff --git a/crates/loro-wasm/Cargo.toml b/crates/loro-wasm/Cargo.toml index 7eee71eb..a37e2ced 100644 --- a/crates/loro-wasm/Cargo.toml +++ b/crates/loro-wasm/Cargo.toml @@ -12,6 +12,8 @@ loro-internal = { path = "../loro-internal", features = ["wasm"] } wasm-bindgen = "0.2.83" serde-wasm-bindgen = { version = "0.5.0" } console_error_panic_hook = { version = "0.1.6", optional = true } +getrandom = { version = "0.2.10", features = ["js"] } +debug-log = { version = "0.2.1", features = ["wasm"] } [features] default = ["console_error_panic_hook"] diff --git a/crates/loro-wasm/scripts/build.ts b/crates/loro-wasm/scripts/build.ts index 632c7582..d8b8938e 100644 --- a/crates/loro-wasm/scripts/build.ts +++ b/crates/loro-wasm/scripts/build.ts @@ -19,12 +19,13 @@ const LoroWasmDir = resolve(__dirname, ".."); console.log(LoroWasmDir); async function build() { await cargoBuild(); - if (Deno.args[1] != null) { - if (!TARGETS.includes(Deno.args[1])) { - throw new Error(`Invalid target ${Deno.args[1]}`); + const target = Deno.args[1]; + if (target != null) { + if (!TARGETS.includes(target)) { + throw new Error(`Invalid target ${target}`); } - buildTarget(Deno.args[1]); + buildTarget(target); return; } @@ -74,13 +75,29 @@ async function buildTarget(target: string) { try { await Deno.remove(targetDirPath, { recursive: true }); console.log("Clear directory " + targetDirPath); - } catch (e) {} + } catch (_e) { + // + } const cmd = `wasm-bindgen --weak-refs --target ${target} --out-dir ${target} ../../target/wasm32-unknown-unknown/${profileDir}/loro_wasm.wasm`; console.log(">", cmd); await Deno.run({ cmd: cmd.split(" "), cwd: LoroWasmDir }).status(); console.log(); + + if (target === "nodejs") { + console.log("🔨 Patching nodejs target"); + const patch = await Deno.readTextFile( + resolve(__dirname, "./nodejs_patch.js"), + ); + const wasm = await Deno.readTextFile( + resolve(targetDirPath, "loro_wasm.js"), + ); + await Deno.writeTextFile( + resolve(targetDirPath, "loro_wasm.js"), + wasm + "\n" + patch, + ); + } } build(); diff --git a/crates/loro-wasm/scripts/nodejs_patch.js b/crates/loro-wasm/scripts/nodejs_patch.js new file mode 100644 index 00000000..1a7371d7 --- /dev/null +++ b/crates/loro-wasm/scripts/nodejs_patch.js @@ -0,0 +1,2 @@ +const { webcrypto } = require("crypto"); +globalThis.crypto = webcrypto; diff --git a/crates/loro-wasm/src/lib.rs b/crates/loro-wasm/src/lib.rs index 38d96f2c..8f2e899a 100644 --- a/crates/loro-wasm/src/lib.rs +++ b/crates/loro-wasm/src/lib.rs @@ -1,23 +1,20 @@ -use js_sys::{Array, Object, Promise, Reflect, Uint8Array}; +use js_sys::{Array, Promise, Uint8Array}; use loro_internal::{ - configure::{Configure, SecureRandomGenerator}, - container::{registry::ContainerWrapper, ContainerID}, - context::Context, + configure::SecureRandomGenerator, + container::ContainerID, event::{Diff, Path}, - log_store::GcConfig, + obs::SubID, + refactor::handler::{ListHandler, MapHandler, TextHandler}, + refactor::txn::Transaction as Txn, version::Frontiers, - ContainerType, List, LoroCore, Map, Origin, Text, Transact, TransactionWrap, VersionVector, + ContainerType, DiffEvent, LoroDoc, VersionVector, }; use std::{cell::RefCell, cmp::Ordering, ops::Deref, rc::Rc, sync::Arc}; -use wasm_bindgen::{ - __rt::{IntoJsResult, RefMut}, - prelude::*, -}; +use wasm_bindgen::{__rt::IntoJsResult, prelude::*}; mod log; mod prelim; pub use prelim::{PrelimList, PrelimMap, PrelimText}; -use crate::convert::js_try_to_prelim; mod convert; #[wasm_bindgen(js_name = setPanicHook)] @@ -32,13 +29,18 @@ pub fn set_panic_hook() { console_error_panic_hook::set_once(); } +#[wasm_bindgen(js_name = setDebug)] +pub fn set_debug(filter: &str) { + debug_log::set_debug(filter) +} + type JsResult = Result; #[wasm_bindgen] -pub struct Loro(RefCell); +pub struct Loro(RefCell); impl Deref for Loro { - type Target = RefCell; + type Target = RefCell; fn deref(&self) -> &Self::Target { &self.0 @@ -79,6 +81,8 @@ mod observer { use wasm_bindgen::JsValue; + use crate::JsResult; + /// We need to wrap the observer function in a struct so that we can implement Send for it. /// But it's not Send essentially, so we need to check it manually in runtime. #[derive(Clone)] @@ -95,9 +99,9 @@ mod observer { } } - pub fn call1(&self, arg: &JsValue) { + pub fn call1(&self, arg: &JsValue) -> JsResult { if std::thread::current().id() == self.thread { - self.f.call1(&JsValue::NULL, arg).unwrap(); + self.f.call1(&JsValue::NULL, arg) } else { panic!("Observer called from different thread") } @@ -111,17 +115,20 @@ mod observer { impl Loro { #[wasm_bindgen(constructor)] pub fn new() -> Self { - let cfg: Configure = Configure { - gc: GcConfig::default().with_gc(false), - get_time: || js_sys::Date::now() as i64, - rand: Arc::new(MathRandom), - }; - Self(RefCell::new(LoroCore::new(cfg, None))) + Self(RefCell::new(LoroDoc::new())) + } + + pub fn txn(&self) -> Transaction { + Transaction(self.0.borrow().txn().unwrap()) + } + + pub fn txn_with_origin(&self, origin: &str) -> Transaction { + Transaction(self.0.borrow().txn_with_origin(origin).unwrap()) } #[wasm_bindgen(js_name = "clientId", method, getter)] pub fn client_id(&self) -> u64 { - self.0.borrow().client_id() + self.0.borrow().peer_id() } #[wasm_bindgen(js_name = "getText")] @@ -146,26 +153,20 @@ impl Loro { pub fn get_container_by_id(&self, container_id: JsContainerID) -> JsResult { let container_id: ContainerID = container_id.to_owned().try_into()?; let ty = container_id.container_type(); - let container = self.0.borrow_mut().get_container(&container_id); - if let Some(container) = container { - let client_id = self.0.borrow().client_id(); - Ok(match ty { - ContainerType::Text => { - let text: Text = Text::from_instance(container, client_id); - LoroText(text).into() - } - ContainerType::Map => { - let map: Map = Map::from_instance(container, client_id); - LoroMap(map).into() - } - ContainerType::List => { - let list: List = List::from_instance(container, client_id); - LoroList(list).into() - } - }) - } else { - Err(JsValue::from_str("Container not found")) - } + Ok(match ty { + ContainerType::Text => { + let text = self.0.borrow().get_text(container_id); + LoroText(text).into() + } + ContainerType::Map => { + let map = self.0.borrow().get_map(container_id); + LoroMap(map).into() + } + ContainerType::List => { + let list = self.0.borrow().get_list(container_id); + LoroList(list).into() + } + }) } #[inline(always)] @@ -194,7 +195,7 @@ impl Loro { #[wasm_bindgen(js_name = "exportSnapshot")] pub fn export_snapshot(&self) -> JsResult> { - Ok(self.0.borrow().encode_all()) + Ok(self.0.borrow().export_snapshot()) } #[wasm_bindgen(skip_typescript, js_name = "exportFrom")] @@ -211,11 +212,11 @@ impl Loro { None => Default::default(), }; - Ok(self.0.borrow().encode_from(vv)) + Ok(self.0.borrow().export_from(&vv)) } pub fn import(&self, update_or_snapshot: &[u8]) -> JsResult<()> { - self.0.borrow_mut().decode(update_or_snapshot)?; + self.0.borrow_mut().import(update_or_snapshot)?; Ok(()) } @@ -231,7 +232,7 @@ impl Loro { if data.is_empty() { return Ok(()); } - Ok(self.0.borrow_mut().decode_batch(&data)?) + Ok(self.0.borrow_mut().import_batch(&data)?) } #[wasm_bindgen(js_name = "toJson")] @@ -243,45 +244,55 @@ impl Loro { // TODO: convert event and event sub config pub fn subscribe(&self, f: js_sys::Function) -> u32 { let observer = observer::Observer::new(f); - self.0.borrow_mut().subscribe_deep(Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - })) + self.0 + .borrow_mut() + .subscribe_deep(Arc::new(move |e| { + call_after_micro_task(observer.clone(), e); + })) + .into_u32() } pub fn unsubscribe(&self, subscription: u32) { - self.0.borrow_mut().unsubscribe_deep(subscription) + self.0 + .borrow_mut() + .unsubscribe(SubID::from_u32(subscription)) } /// It's the caller's responsibility to commit and free the transaction #[wasm_bindgen(js_name = "__raw__transactionWithOrigin")] - pub fn transaction_with_origin(&self, origin: &JsOrigin, f: js_sys::Function) -> JsResult<()> { - let origin = origin.as_string().map(Origin::from); - let txn = self.0.borrow().transact_with(origin); + pub fn transaction_with_origin( + &self, + origin: &JsOrigin, + f: js_sys::Function, + ) -> JsResult { + let origin = origin.as_string().unwrap(); + debug_log::group!("transaction with origin: {}", origin); + let txn = self.0.borrow().txn_with_origin(&origin)?; let js_txn = JsValue::from(Transaction(txn)); - f.call1(&JsValue::NULL, &js_txn)?; - Ok(()) + let ans = f.call1(&JsValue::NULL, &js_txn); + debug_log::group_end!(); + ans } } -fn call_after_micro_task(ob: observer::Observer, e: &loro_internal::event::Event) { - let e = e.clone(); +fn call_after_micro_task(ob: observer::Observer, e: DiffEvent) { let promise = Promise::resolve(&JsValue::NULL); type C = Closure; let drop_handler: Rc>> = Rc::new(RefCell::new(None)); let copy = drop_handler.clone(); + let event = Event { + local: e.doc.local, + origin: e.doc.origin.to_string(), + target: e.container.id.clone(), + diff: Either::A(e.container.diff.to_owned()), + path: Either::A(e.container.path.iter().map(|x| x.1.clone()).collect()), + }; let closure = Closure::once(move |_: JsValue| { - ob.call1( - &Event { - local: e.local, - origin: e.origin.clone(), - target: e.target.clone(), - diff: Either::A(e.diff), - path: Either::A(e.absolute_path.clone()), - } - .into(), - ); - + let ans = ob.call1(&event.into()); drop(copy); + if let Err(e) = ans { + console_log!("Error when calling observer: {:#?}", e); + } }); let _ = promise.then(&closure); drop_handler.borrow_mut().replace(closure); @@ -301,7 +312,7 @@ enum Either { #[wasm_bindgen] pub struct Event { pub local: bool, - origin: Option, + origin: String, target: ContainerID, diff: Either, path: Either, @@ -310,10 +321,8 @@ pub struct Event { #[wasm_bindgen] impl Event { #[wasm_bindgen(js_name = "origin", method, getter)] - pub fn origin(&self) -> Option { - self.origin - .as_ref() - .map(|o| JsValue::from_str(o.as_str()).into()) + pub fn origin(&self) -> String { + self.origin.clone() } #[wasm_bindgen(getter)] @@ -351,62 +360,38 @@ impl Event { } #[wasm_bindgen] -pub struct Transaction(TransactionWrap); +pub struct Transaction(Txn); #[wasm_bindgen] impl Transaction { - pub fn commit(&self) -> JsResult<()> { + pub fn commit(self) -> JsResult<()> { self.0.commit()?; Ok(()) } } -fn get_transaction_mut(txn: &JsTransaction) -> TransactionWrap { - use wasm_bindgen::convert::RefMutFromWasmAbi; - let js: &JsValue = txn.as_ref(); - if js.is_undefined() || js.is_null() { - panic!("you should input Transaction"); - } else { - let ctor_name = Object::get_prototype_of(js).constructor().name(); - if ctor_name == "Transaction" { - let ptr = Reflect::get(js, &JsValue::from_str("ptr")).unwrap(); - let ptr = ptr.as_f64().ok_or(JsValue::NULL).unwrap() as u32; - let txn: RefMut = unsafe { Transaction::ref_mut_from_abi(ptr) }; - txn.0.transact() - } else if ctor_name == "Loro" { - let ptr = Reflect::get(js, &JsValue::from_str("ptr")).unwrap(); - let ptr = ptr.as_f64().ok_or(JsValue::NULL).unwrap() as u32; - let loro: RefMut = unsafe { Loro::ref_mut_from_abi(ptr) }; - let loro = loro.0.borrow(); - loro.transact() - } else { - panic!("you should input Transaction"); - } - } -} - #[wasm_bindgen] -pub struct LoroText(Text); +pub struct LoroText(TextHandler); #[wasm_bindgen] impl LoroText { - pub fn __loro_insert(&mut self, txn: &Loro, index: usize, content: &str) -> JsResult<()> { - self.0.insert_utf16(&*txn.0.borrow(), index, content)?; + pub fn __txn_insert( + &mut self, + txn: &mut Transaction, + index: usize, + content: &str, + ) -> JsResult<()> { + self.0.insert_utf16(&mut txn.0, index, content)?; Ok(()) } - pub fn __loro_delete(&mut self, txn: &Loro, index: usize, len: usize) -> JsResult<()> { - self.0.delete_utf16(&*txn.0.borrow(), index, len)?; - Ok(()) - } - - pub fn __txn_insert(&mut self, txn: &Transaction, index: usize, content: &str) -> JsResult<()> { - self.0.insert_utf16(&txn.0, index, content)?; - Ok(()) - } - - pub fn __txn_delete(&mut self, txn: &Transaction, index: usize, len: usize) -> JsResult<()> { - self.0.delete_utf16(&txn.0, index, len)?; + pub fn __txn_delete( + &mut self, + txn: &mut Transaction, + index: usize, + len: usize, + ) -> JsResult<()> { + self.0.delete_utf16(&mut txn.0, index, len)?; Ok(()) } @@ -427,69 +412,44 @@ impl LoroText { self.0.len() } - pub fn subscribe(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { + pub fn subscribe(&self, loro: &Loro, f: js_sys::Function) -> JsResult { let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe( - &txn, - Box::new(move |e| { + let ans = loro.0.borrow_mut().subscribe( + &self.0.id(), + Arc::new(move |e| { call_after_micro_task(observer.clone(), e); }), - )?; - Ok(ans) + ); + + Ok(ans.into_u32()) } - #[wasm_bindgen(js_name = "subscribeOnce")] - pub fn subscribe_once(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { - let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe_once( - &txn, - Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - }), - )?; - Ok(ans) - } - - pub fn unsubscribe(&self, txn: &JsTransaction, subscription: u32) -> JsResult<()> { - let txn = get_transaction_mut(txn); - self.0.unsubscribe(&txn, subscription)?; + pub fn unsubscribe(&self, loro: &Loro, subscription: u32) -> JsResult<()> { + loro.0 + .borrow_mut() + .unsubscribe(SubID::from_u32(subscription)); Ok(()) } } #[wasm_bindgen] -pub struct LoroMap(Map); +pub struct LoroMap(MapHandler); const CONTAINER_TYPE_ERR: &str = "Invalid container type, only supports Text, Map, List"; #[wasm_bindgen] impl LoroMap { - pub fn __loro_insert(&mut self, txn: &Loro, key: &str, value: JsValue) -> JsResult<()> { - if let Some(v) = js_try_to_prelim(&value) { - self.0.insert(&*txn.0.borrow(), key, v)?; - } else { - self.0.insert(&*txn.0.borrow(), key, value)?; - }; + pub fn __txn_insert( + &mut self, + txn: &mut Transaction, + key: &str, + value: JsValue, + ) -> JsResult<()> { + self.0.insert(&mut txn.0, key, value.into())?; Ok(()) } - pub fn __txn_insert(&mut self, txn: &Transaction, key: &str, value: JsValue) -> JsResult<()> { - if let Some(v) = js_try_to_prelim(&value) { - self.0.insert(&txn.0, key, v)?; - } else { - self.0.insert(&txn.0, key, value)?; - }; - Ok(()) - } - - pub fn __loro_delete(&mut self, txn: &Loro, key: &str) -> JsResult<()> { - self.0.delete(&*txn.0.borrow(), key)?; - Ok(()) - } - - pub fn __txn_delete(&mut self, txn: &Transaction, key: &str) -> JsResult<()> { - self.0.delete(&txn.0, key)?; + pub fn __txn_delete(&mut self, txn: &mut Transaction, key: &str) -> JsResult<()> { + self.0.delete(&mut txn.0, key)?; Ok(()) } @@ -510,85 +470,44 @@ impl LoroMap { } #[wasm_bindgen(js_name = "getValueDeep")] - pub fn get_value_deep(&self, ctx: &Loro) -> JsValue { - self.0.get_value_deep(ctx.deref()).into() + pub fn get_value_deep(&self) -> JsValue { + todo!() + // self.0.get_value_deep(ctx.deref()).into() } #[wasm_bindgen(js_name = "insertContainer")] pub fn insert_container( &mut self, - txn: &JsTransaction, + txn: &mut Transaction, key: &str, container_type: &str, ) -> JsResult { - let txn = get_transaction_mut(txn); let type_ = match container_type { "text" | "Text" => ContainerType::Text, "map" | "Map" => ContainerType::Map, "list" | "List" => ContainerType::List, _ => return Err(JsValue::from_str(CONTAINER_TYPE_ERR)), }; - let idx = self.0.insert(&txn, key, type_)?.unwrap(); + let idx = self.0.insert_container(&mut txn.0, key, type_)?; let container = match type_ { - ContainerType::Text => { - let x = txn.get_text_by_idx(idx).unwrap(); - LoroText(x).into() - } - ContainerType::Map => { - let x = txn.get_map_by_idx(idx).unwrap(); - LoroMap(x).into() - } - ContainerType::List => { - let x = txn.get_list_by_idx(idx).unwrap(); - LoroList(x).into() - } + ContainerType::Text => LoroText(txn.0.get_text(idx)).into(), + ContainerType::Map => LoroMap(txn.0.get_map(idx)).into(), + ContainerType::List => LoroList(txn.0.get_list(idx)).into(), }; Ok(container) } - pub fn subscribe(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { + pub fn subscribe(&self, loro: &Loro, f: js_sys::Function) -> JsResult { let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe( - &txn, - Box::new(move |e| { + let id = loro.0.borrow_mut().subscribe( + &self.0.id(), + Arc::new(move |e| { call_after_micro_task(observer.clone(), e); }), - )?; - Ok(ans) - } + ); - #[wasm_bindgen(js_name = "subscribeOnce")] - pub fn subscribe_once(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { - let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe_once( - &txn, - Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - }), - )?; - Ok(ans) - } - - #[wasm_bindgen(js_name = "subscribeDeep")] - pub fn subscribe_deep(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { - let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe_deep( - &txn, - Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - }), - )?; - Ok(ans) - } - - pub fn unsubscribe(&self, txn: &JsTransaction, subscription: u32) -> JsResult<()> { - let txn = get_transaction_mut(txn); - self.0.unsubscribe(&txn, subscription)?; - Ok(()) + Ok(id.into_u32()) } #[wasm_bindgen(js_name = "size", method, getter)] @@ -598,40 +517,27 @@ impl LoroMap { } #[wasm_bindgen] -pub struct LoroList(List); +pub struct LoroList(ListHandler); #[wasm_bindgen] impl LoroList { - pub fn __loro_insert(&mut self, loro: &Loro, index: usize, value: JsValue) -> JsResult<()> { - if let Some(v) = js_try_to_prelim(&value) { - self.0.insert(&*loro.0.borrow(), index, v)?; - } else { - self.0.insert(&*loro.0.borrow(), index, value)?; - }; - Ok(()) - } - pub fn __txn_insert( &mut self, - txn: &Transaction, + txn: &mut Transaction, index: usize, value: JsValue, ) -> JsResult<()> { - if let Some(v) = js_try_to_prelim(&value) { - self.0.insert(&txn.0, index, v)?; - } else { - self.0.insert(&txn.0, index, value)?; - }; + self.0.insert(&mut txn.0, index, value.into())?; Ok(()) } - pub fn __loro_delete(&mut self, loro: &Loro, index: usize, len: usize) -> JsResult<()> { - self.0.delete(&*loro.0.borrow(), index, len)?; - Ok(()) - } - - pub fn __txn_delete(&mut self, loro: &Transaction, index: usize, len: usize) -> JsResult<()> { - self.0.delete(&loro.0, index, len)?; + pub fn __txn_delete( + &mut self, + txn: &mut Transaction, + index: usize, + len: usize, + ) -> JsResult<()> { + self.0.delete(&mut txn.0, index, len)?; Ok(()) } @@ -651,85 +557,43 @@ impl LoroList { } #[wasm_bindgen(js_name = "getValueDeep")] - pub fn get_value_deep(&self, ctx: &Loro) -> JsValue { - let value = self.0.get_value_deep(ctx.deref()); - value.into() + pub fn get_value_deep(&self) -> JsValue { + todo!() + // let value = self.0.get_value_deep(ctx.deref()); + // value.into() } #[wasm_bindgen(js_name = "insertContainer")] pub fn insert_container( &mut self, - txn: &JsTransaction, + txn: &mut Transaction, pos: usize, container: &str, ) -> JsResult { - let txn = get_transaction_mut(txn); let _type = match container { "text" | "Text" => ContainerType::Text, "map" | "Map" => ContainerType::Map, "list" | "List" => ContainerType::List, _ => return Err(JsValue::from_str(CONTAINER_TYPE_ERR)), }; - let idx = self.0.insert(&txn, pos, _type)?.unwrap(); + let idx = self.0.insert_container(&mut txn.0, pos, _type)?; let container = match _type { - ContainerType::Text => { - let x = txn.get_text_by_idx(idx).unwrap(); - LoroText(x).into() - } - ContainerType::Map => { - let x = txn.get_map_by_idx(idx).unwrap(); - LoroMap(x).into() - } - ContainerType::List => { - let x = txn.get_list_by_idx(idx).unwrap(); - LoroList(x).into() - } + ContainerType::Text => LoroText(txn.0.get_text(idx)).into(), + ContainerType::Map => LoroMap(txn.0.get_map(idx)).into(), + ContainerType::List => LoroList(txn.0.get_list(idx)).into(), }; Ok(container) } - pub fn subscribe(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { + pub fn subscribe(&self, loro: &Loro, f: js_sys::Function) -> JsResult { let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe( - &txn, - Box::new(move |e| { + let ans = loro.0.borrow_mut().subscribe( + &self.0.id(), + Arc::new(move |e| { call_after_micro_task(observer.clone(), e); }), - )?; - Ok(ans) - } - - #[wasm_bindgen(js_name = "subscribeOnce")] - pub fn subscribe_once(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { - let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe_once( - &txn, - Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - }), - )?; - Ok(ans) - } - - #[wasm_bindgen(js_name = "subscribeDeep")] - pub fn subscribe_deep(&self, txn: &JsTransaction, f: js_sys::Function) -> JsResult { - let observer = observer::Observer::new(f); - let txn = get_transaction_mut(txn); - let ans = self.0.subscribe_deep( - &txn, - Box::new(move |e| { - call_after_micro_task(observer.clone(), e); - }), - )?; - Ok(ans) - } - - pub fn unsubscribe(&self, txn: &JsTransaction, subscription: u32) -> JsResult<()> { - let txn = get_transaction_mut(txn); - self.0.unsubscribe(&txn, subscription)?; - Ok(()) + ); + Ok(ans.into_u32()) } #[wasm_bindgen(js_name = "length", method, getter)] diff --git a/loro-js/.vscode/settings.json b/loro-js/.vscode/settings.json index 974a2b4b..b8f98cc8 100644 --- a/loro-js/.vscode/settings.json +++ b/loro-js/.vscode/settings.json @@ -1,3 +1,8 @@ { - "deno.enable": false + "deno.enable": false, + "editor.defaultFormatter": "vscode.typescript-language-features", + "editor.formatOnSave": true, + "[typescript]": { + "editor.defaultFormatter": "vscode.typescript-language-features" + } } diff --git a/loro-js/package.json b/loro-js/package.json index 54d50021..d5677fbd 100644 --- a/loro-js/package.json +++ b/loro-js/package.json @@ -18,7 +18,10 @@ }, "devDependencies": { "@rollup/plugin-node-resolve": "^15.0.1", + "@typescript-eslint/parser": "^6.2.0", "esbuild": "^0.17.12", + "eslint": "^8.46.0", + "prettier": "^3.0.0", "rollup": "^3.20.1", "rollup-plugin-dts": "^5.3.0", "rollup-plugin-esbuild": "^5.0.0", diff --git a/loro-js/src/index.ts b/loro-js/src/index.ts index 09cc6434..c2ddae51 100644 --- a/loro-js/src/index.ts +++ b/loro-js/src/index.ts @@ -23,11 +23,10 @@ import { export type { ContainerID, ContainerType } from "loro-wasm"; Loro.prototype.transact = function (cb, origin) { - this.__raw__transactionWithOrigin(origin, (txn: Transaction) => { + return this.__raw__transactionWithOrigin(origin || "", (txn: Transaction) => { try { - cb(txn); + return cb(txn); } finally { - txn.commit(); txn.free(); } }); @@ -55,51 +54,27 @@ LoroMap.prototype.getTyped = function (loro, key) { LoroMap.prototype.setTyped = LoroMap.prototype.set; LoroText.prototype.insert = function (txn, pos, text) { - if (txn instanceof Loro) { - this.__loro_insert(txn, pos, text); - } else { - this.__txn_insert(txn, pos, text); - } + this.__txn_insert(txn, pos, text); }; LoroText.prototype.delete = function (txn, pos, len) { - if (txn instanceof Loro) { - this.__loro_delete(txn, pos, len); - } else { - this.__txn_delete(txn, pos, len); - } + this.__txn_delete(txn, pos, len); }; LoroList.prototype.insert = function (txn, pos, len) { - if (txn instanceof Loro) { - this.__loro_insert(txn, pos, len); - } else { - this.__txn_insert(txn, pos, len); - } + this.__txn_insert(txn, pos, len); }; LoroList.prototype.delete = function (txn, pos, len) { - if (txn instanceof Loro) { - this.__loro_delete(txn, pos, len); - } else { - this.__txn_delete(txn, pos, len); - } + this.__txn_delete(txn, pos, len); }; LoroMap.prototype.set = function (txn, key, value) { - if (txn instanceof Loro) { - this.__loro_insert(txn, key, value); - } else { - this.__txn_insert(txn, key, value); - } + this.__txn_insert(txn, key, value); }; LoroMap.prototype.delete = function (txn, key) { - if (txn instanceof Loro) { - this.__loro_delete(txn, key); - } else { - this.__txn_delete(txn, key); - } + this.__txn_delete(txn, key); }; export type Value = @@ -136,14 +111,7 @@ export type TextDiff = { export type MapDiff = { type: "map"; - diff: { - added: Record; - deleted: Record; - updated: Record; - }; + updated: Record; }; export type Diff = ListDiff | TextDiff | MapDiff; @@ -191,7 +159,7 @@ export { Loro }; declare module "loro-wasm" { interface Loro { subscribe(listener: Listener): number; - transact(f: (tx: Transaction) => void, origin?: string): void; + transact(f: (tx: Transaction) => T, origin?: string): T; } interface Loro = Record> { @@ -205,22 +173,22 @@ declare module "loro-wasm" { interface LoroList { insertContainer( - txn: Transaction | Loro, + txn: Transaction, pos: number, container: "Map", ): LoroMap; insertContainer( - txn: Transaction | Loro, + txn: Transaction, pos: number, container: "List", ): LoroList; insertContainer( - txn: Transaction | Loro, + txn: Transaction, pos: number, container: "Text", ): LoroText; insertContainer( - txn: Transaction | Loro, + txn: Transaction, pos: number, container: string, ): never; @@ -228,35 +196,33 @@ declare module "loro-wasm" { get(index: number): Value; getTyped(loro: Loro, index: Key): T[Key]; insertTyped( - txn: Transaction | Loro, + txn: Transaction, pos: Key, value: T[Key], ): void; - insert(txn: Transaction | Loro, pos: number, value: Value | Prelim): void; - delete(txn: Transaction | Loro, pos: number, len: number): void; - subscribe(txn: Transaction | Loro, listener: Listener): number; - subscribeDeep(txn: Transaction | Loro, listener: Listener): number; - subscribeOnce(txn: Transaction | Loro, listener: Listener): number; + insert(txn: Transaction, pos: number, value: Value | Prelim): void; + delete(txn: Transaction, pos: number, len: number): void; + subscribe(txn: Loro, listener: Listener): number; } interface LoroMap = Record> { insertContainer( - txn: Transaction | Loro, + txn: Transaction, key: string, container_type: "Map", ): LoroMap; insertContainer( - txn: Transaction | Loro, + txn: Transaction, key: string, container_type: "List", ): LoroList; insertContainer( - txn: Transaction | Loro, + txn: Transaction, key: string, container_type: "Text", ): LoroText; insertContainer( - txn: Transaction | Loro, + txn: Transaction, key: string, container_type: string, ): never; @@ -266,23 +232,19 @@ declare module "loro-wasm" { txn: Loro, key: Key, ): T[Key]; - set(txn: Transaction | Loro, key: string, value: Value | Prelim): void; + set(txn: Transaction, key: string, value: Value | Prelim): void; setTyped( - txn: Transaction | Loro, + txn: Transaction, key: Key, value: T[Key], ): void; - delete(txn: Transaction | Loro, key: string): void; - subscribe(txn: Transaction | Loro, listener: Listener): number; - subscribeDeep(txn: Transaction | Loro, listener: Listener): number; - subscribeOnce(txn: Transaction | Loro, listener: Listener): number; + delete(txn: Transaction, key: string): void; + subscribe(txn: Loro, listener: Listener): number; } interface LoroText { - insert(txn: Transaction | Loro, pos: number, text: string): void; - delete(txn: Transaction | Loro, pos: number, len: number): void; - subscribe(txn: Transaction | Loro, listener: Listener): number; - subscribeDeep(txn: Transaction | Loro, listener: Listener): number; - subscribeOnce(txn: Transaction | Loro, listener: Listener): number; + insert(txn: Transaction, pos: number, text: string): void; + delete(txn: Transaction, pos: number, len: number): void; + subscribe(txn: Loro, listener: Listener): number; } } diff --git a/loro-js/tests/event.test.ts b/loro-js/tests/event.test.ts index 0bfa0113..effd91c4 100644 --- a/loro-js/tests/event.test.ts +++ b/loro-js/tests/event.test.ts @@ -6,8 +6,10 @@ import { LoroEvent, MapDiff as MapDiff, TextDiff, + setPanicHook } from "../src"; +setPanicHook(); describe("event", () => { it("target", async () => { const loro = new Loro(); @@ -17,7 +19,9 @@ describe("event", () => { }); const text = loro.getText("text"); const id = text.id; - text.insert(loro, 0, "123"); + loro.transact((tx) => { + text.insert(tx, 0, "123"); + }); await zeroMs(); expect(lastEvent?.target).toEqual(id); }); @@ -29,15 +33,24 @@ describe("event", () => { lastEvent = event; }); const map = loro.getMap("map"); - const subMap = map.insertContainer(loro, "sub", "Map"); - subMap.set(loro, "0", "1"); + const subMap = loro.transact((tx) => { + const subMap = map.insertContainer(tx, "sub", "Map"); + subMap.set(tx, "0", "1"); + return subMap; + }); + await zeroMs(); expect(lastEvent?.path).toStrictEqual(["map", "sub"]); - const list = subMap.insertContainer(loro, "list", "List"); - list.insert(loro, 0, "2"); - const text = list.insertContainer(loro, 1, "Text"); + const text = loro.transact((tx) => { + const list = subMap.insertContainer(tx, "list", "List"); + list.insert(tx, 0, "2"); + const text = list.insertContainer(tx, 1, "Text"); + return text; + }); await zeroMs(); - text.insert(loro, 0, "3"); + loro.transact((tx) => { + text.insert(tx, 0, "3"); + }); await zeroMs(); expect(lastEvent?.path).toStrictEqual(["map", "sub", "list", 1]); }); @@ -49,12 +62,16 @@ describe("event", () => { lastEvent = event; }); const text = loro.getText("t"); - text.insert(loro, 0, "3"); + loro.transact(tx => { + text.insert(tx, 0, "3"); + }) await zeroMs(); expect(lastEvent?.diff).toStrictEqual( { type: "text", diff: [{ type: "insert", value: "3" }] } as TextDiff, ); - text.insert(loro, 1, "12"); + loro.transact(tx => { + text.insert(tx, 1, "12"); + }) await zeroMs(); expect(lastEvent?.diff).toStrictEqual( { @@ -71,12 +88,16 @@ describe("event", () => { lastEvent = event; }); const text = loro.getList("l"); - text.insert(loro, 0, "3"); + loro.transact(tx => { + text.insert(tx, 0, "3"); + }) await zeroMs(); expect(lastEvent?.diff).toStrictEqual( { type: "list", diff: [{ type: "insert", value: ["3"] }] } as ListDiff, ); - text.insert(loro, 1, "12"); + loro.transact(tx => { + text.insert(tx, 1, "12"); + }) await zeroMs(); expect(lastEvent?.diff).toStrictEqual( { @@ -101,14 +122,10 @@ describe("event", () => { expect(lastEvent?.diff).toStrictEqual( { type: "map", - diff: { - added: { - "0": "3", - "1": "2", - }, - deleted: {}, - updated: {}, - }, + updated: { + "0": "3", + "1": "2", + } } as MapDiff, ); loro.transact((tx) => { @@ -119,13 +136,9 @@ describe("event", () => { expect(lastEvent?.diff).toStrictEqual( { type: "map", - diff: { - added: {}, - updated: { - "0": { old: "3", new: "0" }, - "1": { old: "2", new: "1" }, - }, - deleted: {}, + updated: { + "0": "0", + "1": "1" }, } as MapDiff, ); @@ -136,10 +149,6 @@ describe("event", () => { const loro = new Loro(); const text = loro.getText("text"); let ran = 0; - let oneTimeRan = 0; - text.subscribeOnce(loro, (_) => { - oneTimeRan += 1; - }); const sub = text.subscribe(loro, (event) => { if (!ran) { expect(event.diff.diff).toStrictEqual( @@ -149,18 +158,24 @@ describe("event", () => { ran += 1; expect(event.target).toBe(text.id); }); - text.insert(loro, 0, "123"); - text.insert(loro, 1, "456"); + + loro.transact(tx => { + text.insert(tx, 0, "123"); + }); + loro.transact(tx => { + text.insert(tx, 1, "456"); + }); await zeroMs(); expect(ran).toBeTruthy(); // subscribeOnce test - expect(oneTimeRan).toBe(1); expect(text.toString()).toEqual("145623"); // unsubscribe const oldRan = ran; text.unsubscribe(loro, sub); - text.insert(loro, 0, "789"); + loro.transact(tx => { + text.insert(tx, 0, "789"); + }) expect(ran).toBe(oldRan); }); @@ -168,23 +183,27 @@ describe("event", () => { const loro = new Loro(); const map = loro.getMap("map"); let times = 0; - const sub = map.subscribeDeep(loro, (event) => { + const sub = map.subscribe(loro, (event) => { times += 1; }); - const subMap = map.insertContainer(loro, "sub", "Map"); + + const subMap = + loro.transact(tx => + map.insertContainer(tx, "sub", "Map") + ); await zeroMs(); expect(times).toBe(1); - const text = subMap.insertContainer(loro, "k", "Text"); + const text = loro.transact(tx => subMap.insertContainer(tx, "k", "Text")); await zeroMs(); expect(times).toBe(2); - text.insert(loro, 0, "123"); + loro.transact(tx => text.insert(tx, 0, "123")); await zeroMs(); expect(times).toBe(3); // unsubscribe - map.unsubscribe(loro, sub); - text.insert(loro, 0, "123"); + loro.unsubscribe(sub); + loro.transact(tx => text.insert(tx, 0, "123")); await zeroMs(); expect(times).toBe(3); }); @@ -193,20 +212,20 @@ describe("event", () => { const loro = new Loro(); const list = loro.getList("list"); let times = 0; - const sub = list.subscribeDeep(loro, (_) => { + const sub = list.subscribe(loro, (_) => { times += 1; }); - const text = list.insertContainer(loro, 0, "Text"); + const text = loro.transact(tx => list.insertContainer(tx, 0, "Text")); await zeroMs(); expect(times).toBe(1); - text.insert(loro, 0, "123"); + loro.transact(tx => text.insert(tx, 0, "123")); await zeroMs(); expect(times).toBe(2); // unsubscribe - list.unsubscribe(loro, sub); - text.insert(loro, 0, "123"); + loro.unsubscribe(sub); + loro.transact(tx => text.insert(tx, 0, "123")); await zeroMs(); expect(times).toBe(2); }); @@ -237,19 +256,19 @@ describe("event", () => { string = newString + string.slice(pos); } }); - text.insert(loro, 0, "你好"); + loro.transact(tx => text.insert(tx, 0, "你好")); await zeroMs(); expect(text.toString()).toBe(string); - text.insert(loro, 1, "世界"); + loro.transact(tx => text.insert(tx, 1, "世界")); await zeroMs(); expect(text.toString()).toBe(string); - text.insert(loro, 2, "👍"); + loro.transact(tx => text.insert(tx, 2, "👍")); await zeroMs(); expect(text.toString()).toBe(string); - text.insert(loro, 4, "♪(^∇^*)"); + loro.transact(tx => text.insert(tx, 2, "♪(^∇^*)")); await zeroMs(); expect(text.toString()).toBe(string); }); diff --git a/loro-js/tests/frontiers.test.ts b/loro-js/tests/frontiers.test.ts index f04998b3..479f3df0 100644 --- a/loro-js/tests/frontiers.test.ts +++ b/loro-js/tests/frontiers.test.ts @@ -5,22 +5,31 @@ import { Loro, LoroEvent, MapDiff as MapDiff, + setPanicHook, TextDiff, } from "../src"; +setPanicHook(); describe("Frontiers", () => { it("two clients", () => { const doc = new Loro(); const text = doc.getText("text"); - text.insert(doc, 0, "0"); + const txn = doc.txn(); + text.insert(txn, 0, "0"); + txn.commit(); + const v0 = doc.frontiers(); const docB = new Loro(); docB.import(doc.exportFrom()); expect(docB.cmpFrontiers(v0)).toBe(0); - text.insert(doc, 1, "0"); + doc.transact((t) => { + text.insert(t, 1, "0"); + }); expect(docB.cmpFrontiers(doc.frontiers())).toBe(-1); const textB = docB.getText("text"); - textB.insert(docB, 0, "0"); + docB.transact((t) => { + textB.insert(t, 0, "0"); + }); expect(docB.cmpFrontiers(doc.frontiers())).toBe(-1); docB.import(doc.exportFrom()); expect(docB.cmpFrontiers(doc.frontiers())).toBe(1); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44cd9818..cd320923 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false importers: @@ -22,9 +26,18 @@ importers: '@rollup/plugin-node-resolve': specifier: ^15.0.1 version: 15.0.1(rollup@3.20.2) + '@typescript-eslint/parser': + specifier: ^6.2.0 + version: registry.npmmirror.com/@typescript-eslint/parser@6.2.0(eslint@8.46.0)(typescript@5.0.3) esbuild: specifier: ^0.17.12 version: 0.17.15 + eslint: + specifier: ^8.46.0 + version: registry.npmmirror.com/eslint@8.46.0 + prettier: + specifier: ^3.0.0 + version: registry.npmmirror.com/prettier@3.0.0 rollup: specifier: ^3.20.1 version: 3.20.2 @@ -702,7 +715,7 @@ packages: peerDependencies: vite: ^2 || ^3 || ^4 dependencies: - vite: registry.npmmirror.com/vite@4.2.1 + vite: 4.2.1(@types/node@18.15.11) dev: true /vite@4.2.1(@types/node@18.15.11): @@ -817,6 +830,29 @@ packages: engines: {node: '>=12.20'} dev: true + registry.nlark.com/@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha1-dhnC6yGyVIP20WdUi0z9WnSIw9U=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/@nodelib/fs.scandir/download/@nodelib/fs.scandir-2.1.5.tgz} + name: '@nodelib/fs.scandir' + version: 2.1.5 + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': registry.npmmirror.com/@nodelib/fs.stat@2.0.5 + run-parallel: registry.npmmirror.com/run-parallel@1.2.0 + dev: true + + registry.nlark.com/concat-map@0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=, registry: http://registry.npm.taobao.org/, tarball: https://registry.nlark.com/concat-map/download/concat-map-0.0.1.tgz} + name: concat-map + version: 0.0.1 + dev: true + + registry.npmmirror.com/@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz} + name: '@aashutoshrathi/word-wrap' + version: 1.2.6 + engines: {node: '>=0.10.0'} + dev: true + registry.npmmirror.com/@babel/code-frame@7.21.4: resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.21.4.tgz} name: '@babel/code-frame' @@ -1070,6 +1106,95 @@ packages: dev: true optional: true + registry.npmmirror.com/@eslint-community/eslint-utils@4.4.0(eslint@8.46.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz} + id: registry.npmmirror.com/@eslint-community/eslint-utils/4.4.0 + name: '@eslint-community/eslint-utils' + version: 4.4.0 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: registry.npmmirror.com/eslint@8.46.0 + eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys@3.4.2 + dev: true + + registry.npmmirror.com/@eslint-community/regexpp@4.6.2: + resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.6.2.tgz} + name: '@eslint-community/regexpp' + version: 4.6.2 + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + registry.npmmirror.com/@eslint/eslintrc@2.1.1: + resolution: {integrity: sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.1.1.tgz} + name: '@eslint/eslintrc' + version: 2.1.1 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: registry.npmmirror.com/ajv@6.12.6 + debug: registry.npmmirror.com/debug@4.3.4 + espree: registry.npmmirror.com/espree@9.6.1 + globals: registry.npmmirror.com/globals@13.20.0 + ignore: registry.npmmirror.com/ignore@5.2.4 + import-fresh: registry.npmmirror.com/import-fresh@3.3.0 + js-yaml: registry.npmmirror.com/js-yaml@4.1.0 + minimatch: registry.npmmirror.com/minimatch@3.1.2 + strip-json-comments: registry.npmmirror.com/strip-json-comments@3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@eslint/js@8.46.0: + resolution: {integrity: sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@eslint/js/-/js-8.46.0.tgz} + name: '@eslint/js' + version: 8.46.0 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + registry.npmmirror.com/@humanwhocodes/config-array@0.11.10: + resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz} + name: '@humanwhocodes/config-array' + version: 0.11.10 + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': registry.npmmirror.com/@humanwhocodes/object-schema@1.2.1 + debug: registry.npmmirror.com/debug@4.3.4 + minimatch: registry.npmmirror.com/minimatch@3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz} + name: '@humanwhocodes/module-importer' + version: 1.0.1 + engines: {node: '>=12.22'} + dev: true + + registry.npmmirror.com/@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz} + name: '@humanwhocodes/object-schema' + version: 1.2.1 + dev: true + + registry.npmmirror.com/@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz} + name: '@nodelib/fs.stat' + version: 2.0.5 + engines: {node: '>= 8'} + dev: true + + registry.npmmirror.com/@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz} + name: '@nodelib/fs.walk' + version: 1.2.8 + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': registry.nlark.com/@nodelib/fs.scandir@2.1.5 + fastq: registry.npmmirror.com/fastq@1.15.0 + dev: true + registry.npmmirror.com/@swc/core-darwin-arm64@1.3.44: resolution: {integrity: sha512-Y+oVsCjXUPvr3D9YLuB1gjP84TseM/CRkbPNrf+3JXQhsPEkgxdIdFP1cl/obeqMQrRgPpvSfK+TOvGuOuV22g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.44.tgz} name: '@swc/core-darwin-arm64' @@ -1184,6 +1309,245 @@ packages: dev: true optional: true + registry.npmmirror.com/@typescript-eslint/parser@6.2.0(eslint@8.46.0)(typescript@5.0.3): + resolution: {integrity: sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-6.2.0.tgz} + id: registry.npmmirror.com/@typescript-eslint/parser/6.2.0 + name: '@typescript-eslint/parser' + version: 6.2.0 + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': registry.npmmirror.com/@typescript-eslint/scope-manager@6.2.0 + '@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@6.2.0 + '@typescript-eslint/typescript-estree': registry.npmmirror.com/@typescript-eslint/typescript-estree@6.2.0(typescript@5.0.3) + '@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys@6.2.0 + debug: registry.npmmirror.com/debug@4.3.4 + eslint: registry.npmmirror.com/eslint@8.46.0 + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@typescript-eslint/scope-manager@6.2.0: + resolution: {integrity: sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-6.2.0.tgz} + name: '@typescript-eslint/scope-manager' + version: 6.2.0 + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@6.2.0 + '@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys@6.2.0 + dev: true + + registry.npmmirror.com/@typescript-eslint/types@6.2.0: + resolution: {integrity: sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/types/-/types-6.2.0.tgz} + name: '@typescript-eslint/types' + version: 6.2.0 + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + registry.npmmirror.com/@typescript-eslint/typescript-estree@6.2.0(typescript@5.0.3): + resolution: {integrity: sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.0.tgz} + id: registry.npmmirror.com/@typescript-eslint/typescript-estree/6.2.0 + name: '@typescript-eslint/typescript-estree' + version: 6.2.0 + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@6.2.0 + '@typescript-eslint/visitor-keys': registry.npmmirror.com/@typescript-eslint/visitor-keys@6.2.0 + debug: registry.npmmirror.com/debug@4.3.4 + globby: registry.npmmirror.com/globby@11.1.0 + is-glob: registry.npmmirror.com/is-glob@4.0.3 + semver: registry.npmmirror.com/semver@7.5.4 + ts-api-utils: registry.npmmirror.com/ts-api-utils@1.0.1(typescript@5.0.3) + typescript: 5.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/@typescript-eslint/visitor-keys@6.2.0: + resolution: {integrity: sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.0.tgz} + name: '@typescript-eslint/visitor-keys' + version: 6.2.0 + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': registry.npmmirror.com/@typescript-eslint/types@6.2.0 + eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys@3.4.2 + dev: true + + registry.npmmirror.com/acorn-jsx@5.3.2(acorn@8.10.0): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz} + id: registry.npmmirror.com/acorn-jsx/5.3.2 + name: acorn-jsx + version: 5.3.2 + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: registry.npmmirror.com/acorn@8.10.0 + dev: true + + registry.npmmirror.com/acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/acorn/-/acorn-8.10.0.tgz} + name: acorn + version: 8.10.0 + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + registry.npmmirror.com/ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz} + name: ajv + version: 6.12.6 + dependencies: + fast-deep-equal: registry.npmmirror.com/fast-deep-equal@3.1.3 + fast-json-stable-stringify: registry.npmmirror.com/fast-json-stable-stringify@2.1.0 + json-schema-traverse: registry.npmmirror.com/json-schema-traverse@0.4.1 + uri-js: registry.npmmirror.com/uri-js@4.4.1 + dev: true + + registry.npmmirror.com/ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz} + name: ansi-regex + version: 5.0.1 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz} + name: ansi-styles + version: 4.3.0 + engines: {node: '>=8'} + dependencies: + color-convert: registry.npmmirror.com/color-convert@2.0.1 + dev: true + + registry.npmmirror.com/argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz} + name: argparse + version: 2.0.1 + dev: true + + registry.npmmirror.com/array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz} + name: array-union + version: 2.1.0 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz} + name: balanced-match + version: 1.0.2 + dev: true + + registry.npmmirror.com/brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz} + name: brace-expansion + version: 1.1.11 + dependencies: + balanced-match: registry.npmmirror.com/balanced-match@1.0.2 + concat-map: registry.nlark.com/concat-map@0.0.1 + dev: true + + registry.npmmirror.com/braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz} + name: braces + version: 3.0.2 + engines: {node: '>=8'} + dependencies: + fill-range: registry.npmmirror.com/fill-range@7.0.1 + dev: true + + registry.npmmirror.com/callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz} + name: callsites + version: 3.1.0 + engines: {node: '>=6'} + dev: true + + registry.npmmirror.com/chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz} + name: chalk + version: 4.1.2 + engines: {node: '>=10'} + dependencies: + ansi-styles: registry.npmmirror.com/ansi-styles@4.3.0 + supports-color: registry.npmmirror.com/supports-color@7.2.0 + dev: true + + registry.npmmirror.com/color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz} + name: color-convert + version: 2.0.1 + engines: {node: '>=7.0.0'} + dependencies: + color-name: registry.npmmirror.com/color-name@1.1.4 + dev: true + + registry.npmmirror.com/color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz} + name: color-name + version: 1.1.4 + dev: true + + registry.npmmirror.com/cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz} + name: cross-spawn + version: 7.0.3 + engines: {node: '>= 8'} + dependencies: + path-key: registry.npmmirror.com/path-key@3.1.1 + shebang-command: registry.npmmirror.com/shebang-command@2.0.0 + which: registry.npmmirror.com/which@2.0.2 + dev: true + + registry.npmmirror.com/debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz} + name: debug + version: 4.3.4 + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: registry.npmmirror.com/ms@2.1.2 + dev: true + + registry.npmmirror.com/deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz} + name: deep-is + version: 0.1.4 + dev: true + + registry.npmmirror.com/dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz} + name: dir-glob + version: 3.0.1 + engines: {node: '>=8'} + dependencies: + path-type: registry.npmmirror.com/path-type@4.0.0 + dev: true + + registry.npmmirror.com/doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz} + name: doctrine + version: 3.0.0 + engines: {node: '>=6.0.0'} + dependencies: + esutils: registry.npmmirror.com/esutils@2.0.3 + dev: true + registry.npmmirror.com/esbuild@0.17.15: resolution: {integrity: sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esbuild/-/esbuild-0.17.15.tgz} name: esbuild @@ -1216,6 +1580,210 @@ packages: '@esbuild/win32-x64': registry.npmmirror.com/@esbuild/win32-x64@0.17.15 dev: true + registry.npmmirror.com/escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz} + name: escape-string-regexp + version: 4.0.0 + engines: {node: '>=10'} + dev: true + + registry.npmmirror.com/eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.2.tgz} + name: eslint-scope + version: 7.2.2 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: registry.npmmirror.com/esrecurse@4.3.0 + estraverse: registry.npmmirror.com/estraverse@5.3.0 + dev: true + + registry.npmmirror.com/eslint-visitor-keys@3.4.2: + resolution: {integrity: sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz} + name: eslint-visitor-keys + version: 3.4.2 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + registry.npmmirror.com/eslint@8.46.0: + resolution: {integrity: sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/eslint/-/eslint-8.46.0.tgz} + name: eslint + version: 8.46.0 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': registry.npmmirror.com/@eslint-community/eslint-utils@4.4.0(eslint@8.46.0) + '@eslint-community/regexpp': registry.npmmirror.com/@eslint-community/regexpp@4.6.2 + '@eslint/eslintrc': registry.npmmirror.com/@eslint/eslintrc@2.1.1 + '@eslint/js': registry.npmmirror.com/@eslint/js@8.46.0 + '@humanwhocodes/config-array': registry.npmmirror.com/@humanwhocodes/config-array@0.11.10 + '@humanwhocodes/module-importer': registry.npmmirror.com/@humanwhocodes/module-importer@1.0.1 + '@nodelib/fs.walk': registry.npmmirror.com/@nodelib/fs.walk@1.2.8 + ajv: registry.npmmirror.com/ajv@6.12.6 + chalk: registry.npmmirror.com/chalk@4.1.2 + cross-spawn: registry.npmmirror.com/cross-spawn@7.0.3 + debug: registry.npmmirror.com/debug@4.3.4 + doctrine: registry.npmmirror.com/doctrine@3.0.0 + escape-string-regexp: registry.npmmirror.com/escape-string-regexp@4.0.0 + eslint-scope: registry.npmmirror.com/eslint-scope@7.2.2 + eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys@3.4.2 + espree: registry.npmmirror.com/espree@9.6.1 + esquery: registry.npmmirror.com/esquery@1.5.0 + esutils: registry.npmmirror.com/esutils@2.0.3 + fast-deep-equal: registry.npmmirror.com/fast-deep-equal@3.1.3 + file-entry-cache: registry.npmmirror.com/file-entry-cache@6.0.1 + find-up: registry.npmmirror.com/find-up@5.0.0 + glob-parent: registry.npmmirror.com/glob-parent@6.0.2 + globals: registry.npmmirror.com/globals@13.20.0 + graphemer: registry.npmmirror.com/graphemer@1.4.0 + ignore: registry.npmmirror.com/ignore@5.2.4 + imurmurhash: registry.npmmirror.com/imurmurhash@0.1.4 + is-glob: registry.npmmirror.com/is-glob@4.0.3 + is-path-inside: registry.npmmirror.com/is-path-inside@3.0.3 + js-yaml: registry.npmmirror.com/js-yaml@4.1.0 + json-stable-stringify-without-jsonify: registry.npmmirror.com/json-stable-stringify-without-jsonify@1.0.1 + levn: registry.npmmirror.com/levn@0.4.1 + lodash.merge: registry.npmmirror.com/lodash.merge@4.6.2 + minimatch: registry.npmmirror.com/minimatch@3.1.2 + natural-compare: registry.npmmirror.com/natural-compare@1.4.0 + optionator: registry.npmmirror.com/optionator@0.9.3 + strip-ansi: registry.npmmirror.com/strip-ansi@6.0.1 + text-table: registry.npmmirror.com/text-table@0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + registry.npmmirror.com/espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/espree/-/espree-9.6.1.tgz} + name: espree + version: 9.6.1 + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: registry.npmmirror.com/acorn@8.10.0 + acorn-jsx: registry.npmmirror.com/acorn-jsx@5.3.2(acorn@8.10.0) + eslint-visitor-keys: registry.npmmirror.com/eslint-visitor-keys@3.4.2 + dev: true + + registry.npmmirror.com/esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz} + name: esquery + version: 1.5.0 + engines: {node: '>=0.10'} + dependencies: + estraverse: registry.npmmirror.com/estraverse@5.3.0 + dev: true + + registry.npmmirror.com/esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz} + name: esrecurse + version: 4.3.0 + engines: {node: '>=4.0'} + dependencies: + estraverse: registry.npmmirror.com/estraverse@5.3.0 + dev: true + + registry.npmmirror.com/estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz} + name: estraverse + version: 5.3.0 + engines: {node: '>=4.0'} + dev: true + + registry.npmmirror.com/esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz} + name: esutils + version: 2.0.3 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz} + name: fast-deep-equal + version: 3.1.3 + dev: true + + registry.npmmirror.com/fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.1.tgz} + name: fast-glob + version: 3.3.1 + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': registry.npmmirror.com/@nodelib/fs.stat@2.0.5 + '@nodelib/fs.walk': registry.npmmirror.com/@nodelib/fs.walk@1.2.8 + glob-parent: registry.npmmirror.com/glob-parent@5.1.2 + merge2: registry.npmmirror.com/merge2@1.4.1 + micromatch: registry.npmmirror.com/micromatch@4.0.5 + dev: true + + registry.npmmirror.com/fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz} + name: fast-json-stable-stringify + version: 2.1.0 + dev: true + + registry.npmmirror.com/fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz} + name: fast-levenshtein + version: 2.0.6 + dev: true + + registry.npmmirror.com/fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz} + name: fastq + version: 1.15.0 + dependencies: + reusify: registry.npmmirror.com/reusify@1.0.4 + dev: true + + registry.npmmirror.com/file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz} + name: file-entry-cache + version: 6.0.1 + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: registry.npmmirror.com/flat-cache@3.0.4 + dev: true + + registry.npmmirror.com/fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz} + name: fill-range + version: 7.0.1 + engines: {node: '>=8'} + dependencies: + to-regex-range: registry.npmmirror.com/to-regex-range@5.0.1 + dev: true + + registry.npmmirror.com/find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz} + name: find-up + version: 5.0.0 + engines: {node: '>=10'} + dependencies: + locate-path: registry.npmmirror.com/locate-path@6.0.0 + path-exists: registry.npmmirror.com/path-exists@4.0.0 + dev: true + + registry.npmmirror.com/flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz} + name: flat-cache + version: 3.0.4 + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: registry.npmmirror.com/flatted@3.2.7 + rimraf: registry.npmmirror.com/rimraf@3.0.2 + dev: true + + registry.npmmirror.com/flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz} + name: flatted + version: 3.2.7 + dev: true + + registry.npmmirror.com/fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz} + name: fs.realpath + version: 1.0.0 + dev: true + registry.npmmirror.com/fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz} name: fsevents @@ -1232,6 +1800,73 @@ packages: version: 1.1.1 dev: true + registry.npmmirror.com/glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz} + name: glob-parent + version: 5.1.2 + engines: {node: '>= 6'} + dependencies: + is-glob: registry.npmmirror.com/is-glob@4.0.3 + dev: true + + registry.npmmirror.com/glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz} + name: glob-parent + version: 6.0.2 + engines: {node: '>=10.13.0'} + dependencies: + is-glob: registry.npmmirror.com/is-glob@4.0.3 + dev: true + + registry.npmmirror.com/glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz} + name: glob + version: 7.2.3 + dependencies: + fs.realpath: registry.npmmirror.com/fs.realpath@1.0.0 + inflight: registry.npmmirror.com/inflight@1.0.6 + inherits: registry.npmmirror.com/inherits@2.0.4 + minimatch: registry.npmmirror.com/minimatch@3.1.2 + once: registry.npmmirror.com/once@1.4.0 + path-is-absolute: registry.npmmirror.com/path-is-absolute@1.0.1 + dev: true + + registry.npmmirror.com/globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/globals/-/globals-13.20.0.tgz} + name: globals + version: 13.20.0 + engines: {node: '>=8'} + dependencies: + type-fest: registry.npmmirror.com/type-fest@0.20.2 + dev: true + + registry.npmmirror.com/globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz} + name: globby + version: 11.1.0 + engines: {node: '>=10'} + dependencies: + array-union: registry.npmmirror.com/array-union@2.1.0 + dir-glob: registry.npmmirror.com/dir-glob@3.0.1 + fast-glob: registry.npmmirror.com/fast-glob@3.3.1 + ignore: registry.npmmirror.com/ignore@5.2.4 + merge2: registry.npmmirror.com/merge2@1.4.1 + slash: registry.npmmirror.com/slash@3.0.0 + dev: true + + registry.npmmirror.com/graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz} + name: graphemer + version: 1.4.0 + dev: true + + registry.npmmirror.com/has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz} + name: has-flag + version: 4.0.0 + engines: {node: '>=8'} + dev: true + registry.npmmirror.com/has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/has/-/has-1.0.3.tgz} name: has @@ -1241,6 +1876,45 @@ packages: function-bind: registry.npmmirror.com/function-bind@1.1.1 dev: true + registry.npmmirror.com/ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz} + name: ignore + version: 5.2.4 + engines: {node: '>= 4'} + dev: true + + registry.npmmirror.com/import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz} + name: import-fresh + version: 3.3.0 + engines: {node: '>=6'} + dependencies: + parent-module: registry.npmmirror.com/parent-module@1.0.1 + resolve-from: registry.npmmirror.com/resolve-from@4.0.0 + dev: true + + registry.npmmirror.com/imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz} + name: imurmurhash + version: 0.1.4 + engines: {node: '>=0.8.19'} + dev: true + + registry.npmmirror.com/inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz} + name: inflight + version: 1.0.6 + dependencies: + once: registry.npmmirror.com/once@1.4.0 + wrappy: registry.npmmirror.com/wrappy@1.0.2 + dev: true + + registry.npmmirror.com/inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz} + name: inherits + version: 2.0.4 + dev: true + registry.npmmirror.com/is-core-module@2.11.0: resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-core-module/-/is-core-module-2.11.0.tgz} name: is-core-module @@ -1249,6 +1923,128 @@ packages: has: registry.npmmirror.com/has@1.0.3 dev: true + registry.npmmirror.com/is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz} + name: is-extglob + version: 2.1.1 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz} + name: is-glob + version: 4.0.3 + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: registry.npmmirror.com/is-extglob@2.1.1 + dev: true + + registry.npmmirror.com/is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz} + name: is-number + version: 7.0.0 + engines: {node: '>=0.12.0'} + dev: true + + registry.npmmirror.com/is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz} + name: is-path-inside + version: 3.0.3 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz} + name: isexe + version: 2.0.0 + dev: true + + registry.npmmirror.com/js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz} + name: js-yaml + version: 4.1.0 + hasBin: true + dependencies: + argparse: registry.npmmirror.com/argparse@2.0.1 + dev: true + + registry.npmmirror.com/json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz} + name: json-schema-traverse + version: 0.4.1 + dev: true + + registry.npmmirror.com/json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz} + name: json-stable-stringify-without-jsonify + version: 1.0.1 + dev: true + + registry.npmmirror.com/levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz} + name: levn + version: 0.4.1 + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: registry.npmmirror.com/prelude-ls@1.2.1 + type-check: registry.npmmirror.com/type-check@0.4.0 + dev: true + + registry.npmmirror.com/locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz} + name: locate-path + version: 6.0.0 + engines: {node: '>=10'} + dependencies: + p-locate: registry.npmmirror.com/p-locate@5.0.0 + dev: true + + registry.npmmirror.com/lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz} + name: lodash.merge + version: 4.6.2 + dev: true + + registry.npmmirror.com/lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz} + name: lru-cache + version: 6.0.0 + engines: {node: '>=10'} + dependencies: + yallist: registry.npmmirror.com/yallist@4.0.0 + dev: true + + registry.npmmirror.com/merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz} + name: merge2 + version: 1.4.1 + engines: {node: '>= 8'} + dev: true + + registry.npmmirror.com/micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz} + name: micromatch + version: 4.0.5 + engines: {node: '>=8.6'} + dependencies: + braces: registry.npmmirror.com/braces@3.0.2 + picomatch: registry.npmmirror.com/picomatch@2.3.1 + dev: true + + registry.npmmirror.com/minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz} + name: minimatch + version: 3.1.2 + dependencies: + brace-expansion: registry.npmmirror.com/brace-expansion@1.1.11 + dev: true + + registry.npmmirror.com/ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz} + name: ms + version: 2.1.2 + dev: true + registry.npmmirror.com/nanoid@3.3.6: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz} name: nanoid @@ -1257,18 +2053,108 @@ packages: hasBin: true dev: true + registry.npmmirror.com/natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz} + name: natural-compare + version: 1.4.0 + dev: true + + registry.npmmirror.com/once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/once/-/once-1.4.0.tgz} + name: once + version: 1.4.0 + dependencies: + wrappy: registry.npmmirror.com/wrappy@1.0.2 + dev: true + + registry.npmmirror.com/optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/optionator/-/optionator-0.9.3.tgz} + name: optionator + version: 0.9.3 + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': registry.npmmirror.com/@aashutoshrathi/word-wrap@1.2.6 + deep-is: registry.npmmirror.com/deep-is@0.1.4 + fast-levenshtein: registry.npmmirror.com/fast-levenshtein@2.0.6 + levn: registry.npmmirror.com/levn@0.4.1 + prelude-ls: registry.npmmirror.com/prelude-ls@1.2.1 + type-check: registry.npmmirror.com/type-check@0.4.0 + dev: true + + registry.npmmirror.com/p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz} + name: p-limit + version: 3.1.0 + engines: {node: '>=10'} + dependencies: + yocto-queue: registry.npmmirror.com/yocto-queue@0.1.0 + dev: true + + registry.npmmirror.com/p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz} + name: p-locate + version: 5.0.0 + engines: {node: '>=10'} + dependencies: + p-limit: registry.npmmirror.com/p-limit@3.1.0 + dev: true + + registry.npmmirror.com/parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz} + name: parent-module + version: 1.0.1 + engines: {node: '>=6'} + dependencies: + callsites: registry.npmmirror.com/callsites@3.1.0 + dev: true + + registry.npmmirror.com/path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz} + name: path-exists + version: 4.0.0 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz} + name: path-is-absolute + version: 1.0.1 + engines: {node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz} + name: path-key + version: 3.1.1 + engines: {node: '>=8'} + dev: true + registry.npmmirror.com/path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz} name: path-parse version: 1.0.7 dev: true + registry.npmmirror.com/path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz} + name: path-type + version: 4.0.0 + engines: {node: '>=8'} + dev: true + registry.npmmirror.com/picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz} name: picocolors version: 1.0.0 dev: true + registry.npmmirror.com/picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz} + name: picomatch + version: 2.3.1 + engines: {node: '>=8.6'} + dev: true + registry.npmmirror.com/postcss@8.4.21: resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/postcss/-/postcss-8.4.21.tgz} name: postcss @@ -1280,6 +2166,41 @@ packages: source-map-js: registry.npmmirror.com/source-map-js@1.0.2 dev: true + registry.npmmirror.com/prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz} + name: prelude-ls + version: 1.2.1 + engines: {node: '>= 0.8.0'} + dev: true + + registry.npmmirror.com/prettier@3.0.0: + resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prettier/-/prettier-3.0.0.tgz} + name: prettier + version: 3.0.0 + engines: {node: '>=14'} + hasBin: true + dev: true + + registry.npmmirror.com/punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz} + name: punycode + version: 2.3.0 + engines: {node: '>=6'} + dev: true + + registry.npmmirror.com/queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz} + name: queue-microtask + version: 1.2.3 + dev: true + + registry.npmmirror.com/resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz} + name: resolve-from + version: 4.0.0 + engines: {node: '>=4'} + dev: true + registry.npmmirror.com/resolve@1.22.1: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/resolve/-/resolve-1.22.1.tgz} name: resolve @@ -1291,6 +2212,22 @@ packages: supports-preserve-symlinks-flag: registry.npmmirror.com/supports-preserve-symlinks-flag@1.0.0 dev: true + registry.npmmirror.com/reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz} + name: reusify + version: 1.0.4 + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + registry.npmmirror.com/rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz} + name: rimraf + version: 3.0.2 + hasBin: true + dependencies: + glob: registry.npmmirror.com/glob@7.2.3 + dev: true + registry.npmmirror.com/rollup@3.20.2: resolution: {integrity: sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/rollup/-/rollup-3.20.2.tgz} name: rollup @@ -1301,6 +2238,47 @@ packages: fsevents: registry.npmmirror.com/fsevents@2.3.2 dev: true + registry.npmmirror.com/run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz} + name: run-parallel + version: 1.2.0 + dependencies: + queue-microtask: registry.npmmirror.com/queue-microtask@1.2.3 + dev: true + + registry.npmmirror.com/semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz} + name: semver + version: 7.5.4 + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: registry.npmmirror.com/lru-cache@6.0.0 + dev: true + + registry.npmmirror.com/shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz} + name: shebang-command + version: 2.0.0 + engines: {node: '>=8'} + dependencies: + shebang-regex: registry.npmmirror.com/shebang-regex@3.0.0 + dev: true + + registry.npmmirror.com/shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz} + name: shebang-regex + version: 3.0.0 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz} + name: slash + version: 3.0.0 + engines: {node: '>=8'} + dev: true + registry.npmmirror.com/source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz} name: source-map-js @@ -1308,6 +2286,31 @@ packages: engines: {node: '>=0.10.0'} dev: true + registry.npmmirror.com/strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz} + name: strip-ansi + version: 6.0.1 + engines: {node: '>=8'} + dependencies: + ansi-regex: registry.npmmirror.com/ansi-regex@5.0.1 + dev: true + + registry.npmmirror.com/strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz} + name: strip-json-comments + version: 3.1.1 + engines: {node: '>=8'} + dev: true + + registry.npmmirror.com/supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz} + name: supports-color + version: 7.2.0 + engines: {node: '>=8'} + dependencies: + has-flag: registry.npmmirror.com/has-flag@4.0.0 + dev: true + registry.npmmirror.com/supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz} name: supports-preserve-symlinks-flag @@ -1315,6 +2318,57 @@ packages: engines: {node: '>= 0.4'} dev: true + registry.npmmirror.com/text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz} + name: text-table + version: 0.2.0 + dev: true + + registry.npmmirror.com/to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz} + name: to-regex-range + version: 5.0.1 + engines: {node: '>=8.0'} + dependencies: + is-number: registry.npmmirror.com/is-number@7.0.0 + dev: true + + registry.npmmirror.com/ts-api-utils@1.0.1(typescript@5.0.3): + resolution: {integrity: sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.0.1.tgz} + id: registry.npmmirror.com/ts-api-utils/1.0.1 + name: ts-api-utils + version: 1.0.1 + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.0.3 + dev: true + + registry.npmmirror.com/type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz} + name: type-check + version: 0.4.0 + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: registry.npmmirror.com/prelude-ls@1.2.1 + dev: true + + registry.npmmirror.com/type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz} + name: type-fest + version: 0.20.2 + engines: {node: '>=10'} + dev: true + + registry.npmmirror.com/uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz} + name: uri-js + version: 4.4.1 + dependencies: + punycode: registry.npmmirror.com/punycode@2.3.0 + dev: true + registry.npmmirror.com/vite@4.2.1: resolution: {integrity: sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/vite/-/vite-4.2.1.tgz} name: vite @@ -1349,3 +2403,32 @@ packages: optionalDependencies: fsevents: registry.npmmirror.com/fsevents@2.3.2 dev: true + + registry.npmmirror.com/which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/which/-/which-2.0.2.tgz} + name: which + version: 2.0.2 + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: registry.npmmirror.com/isexe@2.0.0 + dev: true + + registry.npmmirror.com/wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz} + name: wrappy + version: 1.0.2 + dev: true + + registry.npmmirror.com/yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz} + name: yallist + version: 4.0.0 + dev: true + + registry.npmmirror.com/yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, registry: http://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz} + name: yocto-queue + version: 0.1.0 + engines: {node: '>=10'} + dev: true