Skip to content

Commit 8e49634

Browse files
shumkovclaude
andcommitted
refactor(wasm-dpp2,wasm-sdk): reorder operations to eliminate options.clone()
Reorder constructor operations to extract complex types first (borrowing &options), then call serde_wasm_bindgen::from_value(options.into()) last (consuming options). This eliminates unnecessary .clone() calls on options objects since try_from_options borrows while serde consumes. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 231cdbf commit 8e49634

30 files changed

+480
-787
lines changed

packages/wasm-dpp2/src/asset_lock_proof/proof.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use crate::identifier::IdentifierWasm;
77
use crate::impl_try_from_js_value;
88
use crate::impl_try_from_options;
99
use crate::impl_wasm_type_info;
10-
use crate::utils::{IntoWasm, get_class_type, try_from_options, try_to_object};
10+
use crate::utils::{IntoWasm, get_class_type, try_from_options};
1111
use dpp::prelude::AssetLockProof;
12-
use js_sys::{Object, Reflect};
12+
use js_sys::Reflect;
1313
use wasm_bindgen::prelude::*;
1414

1515
#[wasm_bindgen(typescript_custom_section)]
@@ -184,26 +184,24 @@ impl AssetLockProofWasm {
184184
};
185185

186186
// Add type field: 0 = Instant, 1 = Chain
187-
let object = Object::from(inner_object);
188187
let proof_type: u8 = match &self.0 {
189188
AssetLockProof::Instant(_) => 0,
190189
AssetLockProof::Chain(_) => 1,
191190
};
192191
Reflect::set(
193-
&object,
192+
&inner_object,
194193
&JsValue::from_str("type"),
195194
&JsValue::from(proof_type),
196195
)
197196
.map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?;
198197

199-
Ok(JsValue::from(object).into())
198+
Ok(inner_object.into())
200199
}
201200

202201
#[wasm_bindgen(js_name = "fromObject")]
203202
pub fn from_object(object: AssetLockProofObjectJs) -> WasmDppResult<AssetLockProofWasm> {
204203
let js_value: JsValue = object.into();
205-
let object = try_to_object(js_value.clone(), "object")?;
206-
let proof_type: AssetLockProofTypeWasm = try_from_options(&object, "type")?;
204+
let proof_type: AssetLockProofTypeWasm = try_from_options(&js_value, "type")?;
207205

208206
match proof_type {
209207
AssetLockProofTypeWasm::Instant => {
@@ -228,26 +226,24 @@ impl AssetLockProofWasm {
228226
};
229227

230228
// Add type field: 0 = Instant, 1 = Chain
231-
let object = Object::from(inner_json);
232229
let proof_type: u8 = match &self.0 {
233230
AssetLockProof::Instant(_) => 0,
234231
AssetLockProof::Chain(_) => 1,
235232
};
236233
Reflect::set(
237-
&object,
234+
&inner_json,
238235
&JsValue::from_str("type"),
239236
&JsValue::from(proof_type),
240237
)
241238
.map_err(|e| WasmDppError::serialization(format!("{:?}", e)))?;
242239

243-
Ok(JsValue::from(object).into())
240+
Ok(inner_json.into())
244241
}
245242

246243
#[wasm_bindgen(js_name = "fromJSON")]
247244
pub fn from_json(object: AssetLockProofJSONJs) -> WasmDppResult<AssetLockProofWasm> {
248245
let js_value: JsValue = object.into();
249-
let object = try_to_object(js_value.clone(), "json")?;
250-
let proof_type: AssetLockProofTypeWasm = try_from_options(&object, "type")?;
246+
let proof_type: AssetLockProofTypeWasm = try_from_options(&js_value, "type")?;
251247

252248
match proof_type {
253249
AssetLockProofTypeWasm::Instant => {

packages/wasm-dpp2/src/data_contract/document/model.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::impl_wasm_type_info;
77
use crate::serialization;
88
use crate::utils::{
99
ToSerdeJSONExt, try_from_options_optional_with, try_from_options_with, try_to_fixed_bytes,
10-
try_to_object, try_to_string,
10+
try_to_string,
1111
};
1212
use crate::version::{PlatformVersionLikeJs, PlatformVersionWasm};
1313
use dpp::document::serialization_traits::{
@@ -190,31 +190,28 @@ struct DocumentOptionsInput {
190190
impl DocumentWasm {
191191
#[wasm_bindgen(constructor)]
192192
pub fn constructor(options: DocumentOptionsJs) -> WasmDppResult<DocumentWasm> {
193-
let options_value: JsValue = options.into();
194-
let options_obj = try_to_object(options_value.clone(), "options")?;
195-
196-
// Deserialize fields via serde (includes IdentifierWasm)
197-
let input: DocumentOptionsInput = serde_wasm_bindgen::from_value(options_value)
198-
.map_err(|e| WasmDppError::invalid_argument(e.to_string()))?;
199-
200-
let data_contract_id: Identifier = input.data_contract_id.into();
201-
let owner_id: Identifier = input.owner_id.into();
202-
let revision = input.revision.unwrap_or(1);
203-
204-
// Extract complex types that don't have Deserialize
205-
let document_type_name = try_from_options_with(&options_obj, "documentTypeName", |v| {
193+
// Extract complex types first (borrows &options)
194+
let document_type_name = try_from_options_with(&options, "documentTypeName", |v| {
206195
try_to_string(v, "documentTypeName")
207196
})?;
208197

209-
let properties = try_from_options_with(&options_obj, "properties", |v| {
198+
let properties = try_from_options_with(&options, "properties", |v| {
210199
v.with_serde_to_platform_value_map()
211200
})?;
212201

213202
let entropy: Option<[u8; 32]> =
214-
try_from_options_optional_with(&options_obj, "entropy", |v| {
203+
try_from_options_optional_with(&options, "entropy", |v| {
215204
try_to_fixed_bytes::<32>(v.clone(), "entropy")
216205
})?;
217206

207+
// Deserialize simple fields via serde last (consumes options)
208+
let input: DocumentOptionsInput = serde_wasm_bindgen::from_value(options.into())
209+
.map_err(|e| WasmDppError::invalid_argument(e.to_string()))?;
210+
211+
let data_contract_id: Identifier = input.data_contract_id.into();
212+
let owner_id: Identifier = input.owner_id.into();
213+
let revision = input.revision.unwrap_or(1);
214+
218215
let entropy: [u8; 32] = entropy.map_or_else(
219216
|| {
220217
entropy_generator::DefaultEntropyGenerator

packages/wasm-dpp2/src/data_contract/model.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,39 +170,36 @@ pub fn tokens_configuration_from_js_value(
170170
impl DataContractWasm {
171171
#[wasm_bindgen(constructor)]
172172
pub fn constructor(options: DataContractOptionsJs) -> WasmDppResult<DataContractWasm> {
173-
let options: JsValue = options.into();
174-
let object = try_to_object(options.clone(), "options")?;
175-
176173
// Extract ownerId (required)
177-
let owner_id: IdentifierWasm = try_from_options(&object, "ownerId")?;
174+
let owner_id: IdentifierWasm = try_from_options(&options, "ownerId")?;
178175

179176
// Extract schemas (required)
180-
let schema: Value = try_from_options_with(&object, "schemas", |v| {
177+
let schema: Value = try_from_options_with(&options, "schemas", |v| {
181178
serialization::platform_value_from_object(v)
182179
})?;
183180

184181
// Extract definitions (optional)
185182
let definitions: Option<Value> = try_from_options_optional_with(
186-
&object,
183+
&options,
187184
"definitions",
188185
serialization::platform_value_from_object,
189186
)?;
190187

191188
// Extract tokens (optional)
192189
let tokens: BTreeMap<TokenContractPosition, TokenConfiguration> =
193-
try_from_options_optional_with(&object, "tokens", |v| {
190+
try_from_options_optional_with(&options, "tokens", |v| {
194191
tokens_configuration_from_js_value(v)
195192
})?
196193
.unwrap_or_default();
197194

198195
// Extract platformVersion (optional)
199196
let platform_version: PlatformVersion =
200-
try_from_options_optional::<PlatformVersionWasm>(&object, "platformVersion")?
197+
try_from_options_optional::<PlatformVersionWasm>(&options, "platformVersion")?
201198
.map(Into::into)
202199
.unwrap_or_else(|| PlatformVersionWasm::default().into());
203200

204201
// Extract simple fields via serde
205-
let opts: DataContractOptions = serde_wasm_bindgen::from_value(options)
202+
let opts: DataContractOptions = serde_wasm_bindgen::from_value(options.into())
206203
.map_err(|e| WasmDppError::invalid_argument(e.to_string()))?;
207204

208205
let data_contract_structure_version_value = Value::from(

packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ use crate::error::{WasmDppError, WasmDppResult};
22
use crate::identifier::IdentifierWasm;
33
use crate::impl_from_for_extern_type;
44
use crate::impl_wasm_type_info;
5-
use crate::utils::{
6-
JsMapExt, try_from_options_with, try_to_map, try_to_object, try_to_u32, try_to_u64,
7-
};
5+
use crate::utils::{JsMapExt, try_from_options_with, try_to_map, try_to_u32, try_to_u64};
86
use dpp::block::finalized_epoch_info::FinalizedEpochInfo;
97
use dpp::block::finalized_epoch_info::v0::FinalizedEpochInfoV0;
108
use dpp::block::finalized_epoch_info::v0::getters::FinalizedEpochInfoGettersV0;
@@ -161,51 +159,49 @@ impl FinalizedEpochInfoWasm {
161159
pub fn constructor(
162160
options: FinalizedEpochInfoOptionsJs,
163161
) -> WasmDppResult<FinalizedEpochInfoWasm> {
164-
let options_obj = try_to_object(options.into(), "options")?;
165-
166-
let first_block_time = try_from_options_with(&options_obj, "firstBlockTime", |v| {
162+
let first_block_time = try_from_options_with(&options, "firstBlockTime", |v| {
167163
try_to_u64(v, "firstBlockTime")
168164
})?;
169165

170-
let first_block_height = try_from_options_with(&options_obj, "firstBlockHeight", |v| {
166+
let first_block_height = try_from_options_with(&options, "firstBlockHeight", |v| {
171167
try_to_u64(v, "firstBlockHeight")
172168
})?;
173169

174170
let total_blocks_in_epoch =
175-
try_from_options_with(&options_obj, "totalBlocksInEpoch", |v| {
171+
try_from_options_with(&options, "totalBlocksInEpoch", |v| {
176172
try_to_u64(v, "totalBlocksInEpoch")
177173
})?;
178174

179175
let first_core_block_height =
180-
try_from_options_with(&options_obj, "firstCoreBlockHeight", |v| {
176+
try_from_options_with(&options, "firstCoreBlockHeight", |v| {
181177
try_to_u32(v, "firstCoreBlockHeight")
182178
})?;
183179

184180
let next_epoch_start_core_block_height =
185-
try_from_options_with(&options_obj, "nextEpochStartCoreBlockHeight", |v| {
181+
try_from_options_with(&options, "nextEpochStartCoreBlockHeight", |v| {
186182
try_to_u32(v, "nextEpochStartCoreBlockHeight")
187183
})?;
188184

189185
let total_processing_fees =
190-
try_from_options_with(&options_obj, "totalProcessingFees", |v| {
186+
try_from_options_with(&options, "totalProcessingFees", |v| {
191187
try_to_u64(v, "totalProcessingFees")
192188
})?;
193189

194190
let total_distributed_storage_fees =
195-
try_from_options_with(&options_obj, "totalDistributedStorageFees", |v| {
191+
try_from_options_with(&options, "totalDistributedStorageFees", |v| {
196192
try_to_u64(v, "totalDistributedStorageFees")
197193
})?;
198194

199195
let total_created_storage_fees =
200-
try_from_options_with(&options_obj, "totalCreatedStorageFees", |v| {
196+
try_from_options_with(&options, "totalCreatedStorageFees", |v| {
201197
try_to_u64(v, "totalCreatedStorageFees")
202198
})?;
203199

204-
let core_block_rewards = try_from_options_with(&options_obj, "coreBlockRewards", |v| {
200+
let core_block_rewards = try_from_options_with(&options, "coreBlockRewards", |v| {
205201
try_to_u64(v, "coreBlockRewards")
206202
})?;
207203

208-
let block_proposers = try_from_options_with(&options_obj, "blockProposers", |v| {
204+
let block_proposers = try_from_options_with(&options, "blockProposers", |v| {
209205
if !v.is_instance_of::<Map>() {
210206
return Err(WasmDppError::invalid_argument(
211207
"'blockProposers' must be a Map",
@@ -215,11 +211,11 @@ impl FinalizedEpochInfoWasm {
215211
})?;
216212

217213
let fee_multiplier_permille =
218-
try_from_options_with(&options_obj, "feeMultiplierPermille", |v| {
214+
try_from_options_with(&options, "feeMultiplierPermille", |v| {
219215
try_to_u64(v, "feeMultiplierPermille")
220216
})?;
221217

222-
let protocol_version = try_from_options_with(&options_obj, "protocolVersion", |v| {
218+
let protocol_version = try_from_options_with(&options, "protocolVersion", |v| {
223219
try_to_u32(v, "protocolVersion")
224220
})?;
225221

@@ -386,7 +382,7 @@ impl FinalizedEpochInfoWasm {
386382
#[wasm_bindgen(js_name = "blockProposers")] block_proposers: BlockProposersMapJs,
387383
) -> WasmDppResult<()> {
388384
let block_proposers_map =
389-
block_proposers_from_map(&try_to_map(block_proposers.into(), "blockProposers")?)?;
385+
block_proposers_from_map(&try_to_map(block_proposers, "blockProposers")?)?;
390386
self.v0_mut().block_proposers = block_proposers_map;
391387
Ok(())
392388
}

packages/wasm-dpp2/src/identity/partial_identity.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,24 +76,22 @@ impl From<PartialIdentity> for PartialIdentityWasm {
7676
impl PartialIdentityWasm {
7777
#[wasm_bindgen(constructor)]
7878
pub fn constructor(options: PartialIdentityOptionsJs) -> WasmDppResult<Self> {
79-
let options_obj = try_to_object(options.into(), "options")?;
79+
let id: IdentifierWasm = try_from_options(&options, "id")?;
8080

81-
let id: IdentifierWasm = try_from_options(&options_obj, "id")?;
82-
83-
let loaded_public_keys = try_from_options_with(&options_obj, "loadedPublicKeys", |v| {
81+
let loaded_public_keys = try_from_options_with(&options, "loadedPublicKeys", |v| {
8482
value_to_loaded_public_keys(v)
8583
})?;
8684

8785
let balance: Option<Credits> =
88-
try_from_options_optional_with(&options_obj, "balance", |v| try_to_u64(v, "balance"))?;
86+
try_from_options_optional_with(&options, "balance", |v| try_to_u64(v, "balance"))?;
8987

9088
let revision: Option<Revision> =
91-
try_from_options_optional_with(&options_obj, "revision", |v| {
89+
try_from_options_optional_with(&options, "revision", |v| {
9290
try_to_u64(v, "revision")
9391
})?;
9492

9593
let not_found_public_keys: Option<Array> =
96-
try_from_options_optional_with(&options_obj, "notFoundPublicKeys", |v| {
94+
try_from_options_optional_with(&options, "notFoundPublicKeys", |v| {
9795
try_to_array(v, "notFoundPublicKeys")
9896
})?;
9997
let not_found_keys: BTreeSet<KeyID> = option_array_to_not_found(not_found_public_keys)?;
@@ -211,29 +209,29 @@ impl PartialIdentityWasm {
211209

212210
#[wasm_bindgen(js_name = "fromObject")]
213211
pub fn from_object(obj: PartialIdentityObjectJs) -> WasmDppResult<PartialIdentityWasm> {
214-
let options_obj = try_to_object(obj, "obj")?;
212+
let obj: JsValue = obj.into();
215213

216214
// id - can be Uint8Array or Identifier
217-
let id: IdentifierWasm = try_from_options(&options_obj, "id")?;
215+
let id: IdentifierWasm = try_from_options(&obj, "id")?;
218216

219217
// loadedPublicKeys - values are plain objects
220-
let loaded_public_keys = try_from_options_with(&options_obj, "loadedPublicKeys", |v| {
218+
let loaded_public_keys = try_from_options_with(&obj, "loadedPublicKeys", |v| {
221219
value_to_loaded_public_keys_from_object(v)
222220
})?;
223221

224222
// balance - can be BigInt, number, or undefined
225223
let balance: Option<Credits> =
226-
try_from_options_optional_with(&options_obj, "balance", |v| try_to_u64(v, "balance"))?;
224+
try_from_options_optional_with(&obj, "balance", |v| try_to_u64(v, "balance"))?;
227225

228226
// revision - can be BigInt, number, or undefined
229227
let revision: Option<Revision> =
230-
try_from_options_optional_with(&options_obj, "revision", |v| {
228+
try_from_options_optional_with(&obj, "revision", |v| {
231229
try_to_u64(v, "revision")
232230
})?;
233231

234232
// notFoundPublicKeys
235233
let not_found_public_keys: Option<Array> =
236-
try_from_options_optional_with(&options_obj, "notFoundPublicKeys", |v| {
234+
try_from_options_optional_with(&obj, "notFoundPublicKeys", |v| {
237235
try_to_array(v, "notFoundPublicKeys")
238236
})?;
239237
let not_found_keys: BTreeSet<KeyID> = option_array_to_not_found(not_found_public_keys)?;
@@ -249,29 +247,29 @@ impl PartialIdentityWasm {
249247

250248
#[wasm_bindgen(js_name = "fromJSON")]
251249
pub fn from_json(json: PartialIdentityJSONJs) -> WasmDppResult<PartialIdentityWasm> {
252-
let options_obj = try_to_object(json, "json")?;
250+
let json: JsValue = json.into();
253251

254252
// id - base58 string
255-
let id: IdentifierWasm = try_from_options(&options_obj, "id")?;
253+
let id: IdentifierWasm = try_from_options(&json, "id")?;
256254

257255
// loadedPublicKeys - values are JSON objects
258-
let loaded_public_keys = try_from_options_with(&options_obj, "loadedPublicKeys", |v| {
256+
let loaded_public_keys = try_from_options_with(&json, "loadedPublicKeys", |v| {
259257
value_to_loaded_public_keys_from_json(v)
260258
})?;
261259

262260
// balance - can be BigInt, number, or string (JSON doesn't support BigInt natively)
263261
let balance: Option<Credits> =
264-
try_from_options_optional_with(&options_obj, "balance", |v| try_to_u64(v, "balance"))?;
262+
try_from_options_optional_with(&json, "balance", |v| try_to_u64(v, "balance"))?;
265263

266264
// revision - can be BigInt, number, or string (JSON doesn't support BigInt natively)
267265
let revision: Option<Revision> =
268-
try_from_options_optional_with(&options_obj, "revision", |v| {
266+
try_from_options_optional_with(&json, "revision", |v| {
269267
try_to_u64(v, "revision")
270268
})?;
271269

272270
// notFoundPublicKeys
273271
let not_found_public_keys: Option<Array> =
274-
try_from_options_optional_with(&options_obj, "notFoundPublicKeys", |v| {
272+
try_from_options_optional_with(&json, "notFoundPublicKeys", |v| {
275273
try_to_array(v, "notFoundPublicKeys")
276274
})?;
277275
let not_found_keys: BTreeSet<KeyID> = option_array_to_not_found(not_found_public_keys)?;

packages/wasm-dpp2/src/identity/public_key.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,6 @@ impl From<IdentityPublicKeyWasm> for IdentityPublicKey {
156156
impl IdentityPublicKeyWasm {
157157
#[wasm_bindgen(constructor)]
158158
pub fn constructor(options: IdentityPublicKeyOptionsJs) -> WasmDppResult<Self> {
159-
let options: JsValue = options.into();
160-
161159
// Extract purpose (required, complex type)
162160
let purpose: PurposeWasm = try_from_options(&options, "purpose")?;
163161

@@ -173,7 +171,7 @@ impl IdentityPublicKeyWasm {
173171
.map(Into::into);
174172

175173
// Extract simple fields via serde
176-
let opts: IdentityPublicKeyOptions = serde_wasm_bindgen::from_value(options)
174+
let opts: IdentityPublicKeyOptions = serde_wasm_bindgen::from_value(options.into())
177175
.map_err(|e| WasmDppError::invalid_argument(e.to_string()))?;
178176

179177
Ok(IdentityPublicKeyWasm(IdentityPublicKey::from(

0 commit comments

Comments
 (0)