(wasm) Improved memory management, track by struct so drop works, use --weak-ref for wasm-bindgen
This commit is contained in:
		| @@ -3,7 +3,7 @@ use super::*; | ||||
|  | ||||
| #[wasm_bindgen()] | ||||
| pub struct VeilidRoutingContext { | ||||
|     id: u32, | ||||
|     inner_routing_context: Option<RoutingContext>, | ||||
| } | ||||
|  | ||||
| #[wasm_bindgen()] | ||||
| @@ -12,8 +12,10 @@ impl VeilidRoutingContext { | ||||
|     /// Use one of the `VeilidRoutingContext.create___()` factory methods instead. | ||||
|     /// @deprecated | ||||
|     #[wasm_bindgen(constructor)] | ||||
|     pub fn new(id: u32) -> Self { | ||||
|         Self { id } | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             inner_routing_context: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // -------------------------------- | ||||
| @@ -24,8 +26,9 @@ impl VeilidRoutingContext { | ||||
|     pub fn createWithoutPrivacy() -> APIResult<VeilidRoutingContext> { | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let routing_context = veilid_api.routing_context(); | ||||
|         let id = add_routing_context(routing_context); | ||||
|         Ok(VeilidRoutingContext { id }) | ||||
|         Ok(VeilidRoutingContext { | ||||
|             inner_routing_context: Some(routing_context), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Turn on sender privacy, enabling the use of safety routes. | ||||
| @@ -39,8 +42,9 @@ impl VeilidRoutingContext { | ||||
|     pub fn createWithPrivacy() -> APIResult<VeilidRoutingContext> { | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let routing_context = veilid_api.routing_context().with_privacy()?; | ||||
|         let id = add_routing_context(routing_context); | ||||
|         Ok(VeilidRoutingContext { id }) | ||||
|         Ok(VeilidRoutingContext { | ||||
|             inner_routing_context: Some(routing_context), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Turn on privacy using a custom `SafetySelection` | ||||
| @@ -51,16 +55,18 @@ impl VeilidRoutingContext { | ||||
|         let routing_context = veilid_api | ||||
|             .routing_context() | ||||
|             .with_custom_privacy(safety_selection)?; | ||||
|         let id = add_routing_context(routing_context); | ||||
|         Ok(VeilidRoutingContext { id }) | ||||
|         Ok(VeilidRoutingContext { | ||||
|             inner_routing_context: Some(routing_context), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     /// Use a specified `Sequencing` preference, with or without privacy. | ||||
|     pub fn createWithSequencing(sequencing: Sequencing) -> APIResult<VeilidRoutingContext> { | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let routing_context = veilid_api.routing_context().with_sequencing(sequencing); | ||||
|         let id = add_routing_context(routing_context); | ||||
|         Ok(VeilidRoutingContext { id }) | ||||
|         Ok(VeilidRoutingContext { | ||||
|             inner_routing_context: Some(routing_context), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     // -------------------------------- | ||||
| @@ -115,6 +121,7 @@ impl VeilidRoutingContext { | ||||
|     /// * `call_id` - specifies which call to reply to, and it comes from a VeilidUpdate::AppCall, specifically the VeilidAppCall::id() value. | ||||
|     /// * `message` - is an answer blob to be returned by the remote node's RoutingContext::app_call() function, and may be up to 32768 bytes | ||||
|     pub async fn appCallReply(call_id: String, message: String) -> APIResult<()> { | ||||
|         let message = unmarshall(message); | ||||
|         let call_id = match call_id.parse() { | ||||
|             Ok(v) => v, | ||||
|             Err(e) => { | ||||
| @@ -124,9 +131,7 @@ impl VeilidRoutingContext { | ||||
|             } | ||||
|         }; | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         veilid_api | ||||
|             .app_call_reply(call_id, message.into_bytes()) | ||||
|             .await?; | ||||
|         veilid_api.app_call_reply(call_id, message).await?; | ||||
|         APIRESULT_UNDEFINED | ||||
|     } | ||||
|  | ||||
| @@ -134,9 +139,8 @@ impl VeilidRoutingContext { | ||||
|     // Instance methods | ||||
|     // -------------------------------- | ||||
|     fn getRoutingContext(&self) -> APIResult<RoutingContext> { | ||||
|         let rc = (*ROUTING_CONTEXTS).borrow(); | ||||
|         let Some(routing_context) = rc.get(&self.id) else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("getRoutingContext", "id", self.id)); | ||||
|         let Some(routing_context) = &self.inner_routing_context else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getRoutingContext instance. inner_routing_context is None.")); | ||||
|         }; | ||||
|         APIResult::Ok(routing_context.clone()) | ||||
|     } | ||||
| @@ -150,12 +154,11 @@ impl VeilidRoutingContext { | ||||
|     #[wasm_bindgen(skip_jsdoc)] | ||||
|     pub async fn appMessage(&self, target_string: String, message: String) -> APIResult<()> { | ||||
|         let routing_context = self.getRoutingContext()?; | ||||
|         let message = unmarshall(message); | ||||
|  | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let target = veilid_api.parse_as_target(target_string).await?; | ||||
|         routing_context | ||||
|             .app_message(target, message.into_bytes()) | ||||
|             .await?; | ||||
|         routing_context.app_message(target, message).await?; | ||||
|         APIRESULT_UNDEFINED | ||||
|     } | ||||
|  | ||||
| @@ -168,15 +171,13 @@ impl VeilidRoutingContext { | ||||
|     /// @returns an answer blob of up to `32768` bytes, base64Url encoded. | ||||
|     #[wasm_bindgen(skip_jsdoc)] | ||||
|     pub async fn appCall(&self, target_string: String, request: String) -> APIResult<String> { | ||||
|         let request: Vec<u8> = data_encoding::BASE64URL_NOPAD | ||||
|             .decode(&request.as_bytes()) | ||||
|             .unwrap(); | ||||
|         let request: Vec<u8> = unmarshall(request); | ||||
|         let routing_context = self.getRoutingContext()?; | ||||
|  | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let target = veilid_api.parse_as_target(target_string).await?; | ||||
|         let answer = routing_context.app_call(target, request).await?; | ||||
|         let answer = data_encoding::BASE64URL_NOPAD.encode(&answer); | ||||
|         let answer = marshall(&answer); | ||||
|         APIResult::Ok(answer) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,7 @@ use super::*; | ||||
|  | ||||
| #[wasm_bindgen()] | ||||
| pub struct VeilidTableDB { | ||||
|     id: u32, | ||||
|     inner_table_db: Option<TableDB>, | ||||
|     tableName: String, | ||||
|     columnCount: u32, | ||||
| } | ||||
| @@ -15,48 +15,35 @@ impl VeilidTableDB { | ||||
|     #[wasm_bindgen(constructor)] | ||||
|     pub fn new(tableName: String, columnCount: u32) -> Self { | ||||
|         Self { | ||||
|             id: 0, | ||||
|             inner_table_db: None, | ||||
|             tableName, | ||||
|             columnCount, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn getTableDB(&self) -> APIResult<TableDB> { | ||||
|         let table_dbs = (*TABLE_DBS).borrow(); | ||||
|         let Some(table_db) = table_dbs.get(&self.id) else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("getTableDB", "id", self.id)); | ||||
|         let Some(table_db) = &self.inner_table_db else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getTableDB instance. Ensure you've called openTable().")); | ||||
|         }; | ||||
|         APIResult::Ok(table_db.clone()) | ||||
|     } | ||||
|  | ||||
|     /// Get or create the TableDB database table. | ||||
|     /// This is called automatically when performing actions on the TableDB. | ||||
|     pub async fn openTable(&mut self) -> APIResult<u32> { | ||||
|     pub async fn openTable(&mut self) -> APIResult<()> { | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let tstore = veilid_api.table_store()?; | ||||
|         let table_db = tstore | ||||
|             .open(&self.tableName, self.columnCount) | ||||
|             .await | ||||
|             .map_err(veilid_core::VeilidAPIError::generic)?; | ||||
|         let new_id = add_table_db(table_db); | ||||
|         self.id = new_id; | ||||
|         APIResult::Ok(new_id) | ||||
|     } | ||||
|  | ||||
|     /// Release the TableDB instance from memory. | ||||
|     pub fn releaseTable(&mut self) -> bool { | ||||
|         let mut tdbs = (*TABLE_DBS).borrow_mut(); | ||||
|         let status = tdbs.remove(&self.id); | ||||
|         self.id = 0; | ||||
|         if status.is_none() { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|         self.inner_table_db = Some(table_db); | ||||
|         APIRESULT_UNDEFINED | ||||
|     } | ||||
|  | ||||
|     /// Delete this TableDB. | ||||
|     pub async fn deleteTable(&mut self) -> APIResult<bool> { | ||||
|         self.releaseTable(); | ||||
|         self.inner_table_db = None; | ||||
|  | ||||
|         let veilid_api = get_veilid_api()?; | ||||
|         let tstore = veilid_api.table_store()?; | ||||
| @@ -68,7 +55,7 @@ impl VeilidTableDB { | ||||
|     } | ||||
|  | ||||
|     async fn ensureOpen(&mut self) { | ||||
|         if self.id == 0 { | ||||
|         if self.inner_table_db.is_none() { | ||||
|             let _ = self.openTable().await; | ||||
|         } | ||||
|     } | ||||
| @@ -128,14 +115,15 @@ impl VeilidTableDB { | ||||
|         let table_db = self.getTableDB()?; | ||||
|  | ||||
|         let transaction = table_db.transact(); | ||||
|         let transaction_id = add_table_db_transaction(transaction); | ||||
|         APIResult::Ok(VeilidTableDBTransaction { id: transaction_id }) | ||||
|         APIResult::Ok(VeilidTableDBTransaction { | ||||
|             inner_transaction: Some(transaction), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[wasm_bindgen] | ||||
| pub struct VeilidTableDBTransaction { | ||||
|     id: u32, | ||||
|     inner_transaction: Option<TableDBTransaction>, | ||||
| } | ||||
|  | ||||
| #[wasm_bindgen] | ||||
| @@ -144,28 +132,19 @@ impl VeilidTableDBTransaction { | ||||
|     /// Use `.createTransaction()` on an instance of `VeilidTableDB` instead. | ||||
|     /// @deprecated | ||||
|     #[wasm_bindgen(constructor)] | ||||
|     pub fn new(id: u32) -> Self { | ||||
|         Self { id } | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             inner_transaction: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn getTransaction(&self) -> APIResult<TableDBTransaction> { | ||||
|         let transactions = (*TABLE_DB_TRANSACTIONS).borrow(); | ||||
|         let Some(transaction) = transactions.get(&self.id) else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::invalid_argument("getTransaction", "id", &self.id)); | ||||
|         let Some(transaction) = &self.inner_transaction else { | ||||
|             return APIResult::Err(veilid_core::VeilidAPIError::generic("Unable to getTransaction instance. inner_transaction is None.")); | ||||
|         }; | ||||
|         APIResult::Ok(transaction.clone()) | ||||
|     } | ||||
|  | ||||
|     /// Releases the transaction from memory. | ||||
|     pub fn releaseTransaction(&mut self) -> bool { | ||||
|         let mut transactions = (*TABLE_DB_TRANSACTIONS).borrow_mut(); | ||||
|         self.id = 0; | ||||
|         if transactions.remove(&self.id).is_none() { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /// Commit the transaction. Performs all actions atomically. | ||||
|     pub async fn commit(&self) -> APIResult<()> { | ||||
|         let transaction = self.getTransaction()?; | ||||
|   | ||||
| @@ -37,7 +37,7 @@ if [[ "$1" == "release" ]]; then | ||||
|  | ||||
|     cargo build --target wasm32-unknown-unknown --release | ||||
|     mkdir -p $OUTPUTDIR | ||||
|     wasm-bindgen --out-dir $OUTPUTDIR --target web $INPUTDIR/veilid_wasm.wasm | ||||
|     wasm-bindgen --out-dir $OUTPUTDIR --target web --weak-refs $INPUTDIR/veilid_wasm.wasm | ||||
|     wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm | ||||
| else | ||||
|     OUTPUTDIR=../target/wasm32-unknown-unknown/debug/pkg | ||||
| @@ -45,7 +45,7 @@ else | ||||
|  | ||||
|     RUSTFLAGS="-O -g $RUSTFLAGS" cargo build --target wasm32-unknown-unknown | ||||
|     mkdir -p $OUTPUTDIR | ||||
|     wasm-bindgen --out-dir $OUTPUTDIR --target web --keep-debug --debug $INPUTDIR/veilid_wasm.wasm | ||||
|     wasm-bindgen --out-dir $OUTPUTDIR --target web --weak-refs --keep-debug --debug $INPUTDIR/veilid_wasm.wasm | ||||
|     ./wasm-sourcemap.py $OUTPUTDIR/veilid_wasm_bg.wasm -o $OUTPUTDIR/veilid_wasm_bg.wasm.map --dwarfdump $DWARFDUMP | ||||
|     # wasm-strip $OUTPUTDIR/veilid_wasm_bg.wasm | ||||
| fi | ||||
|   | ||||
		Reference in New Issue
	
	Block a user