@peerbit/native-backbone 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,7 @@ use crate::documents::{
17
17
  document_index_plain_put_payload_append_commit, DocumentIndexAppendCommit,
18
18
  DocumentIndexValuePrefix,
19
19
  };
20
+ use crate::error::BackboneError;
20
21
  use crate::js_interop::{
21
22
  ensure_same_len, has_duplicate_strings, optional_usize_from_js, required_bytes_from_array,
22
23
  strings_from_array, strings_to_array,
@@ -24,6 +25,19 @@ use crate::js_interop::{
24
25
  use crate::shared_log_plan::leader_samples_to_optional_rows;
25
26
  use crate::NativePeerbitBackbone;
26
27
 
28
+ /// Forward a JsValue error from an untyped documents-layer helper without
29
+ /// altering its message. The document-commit builders and the
30
+ /// required-previous-signer validator construct every error via
31
+ /// `JsValue::from_str`, so `as_string()` recovers the exact string they would
32
+ /// have thrown; the fallback only guards the theoretically-non-string case.
33
+ fn js_wrapper_error(error: JsValue) -> BackboneError {
34
+ BackboneError::Message(
35
+ error
36
+ .as_string()
37
+ .unwrap_or_else(|| "Invalid document index append input".to_string()),
38
+ )
39
+ }
40
+
27
41
  #[wasm_bindgen]
28
42
  impl NativePeerbitBackbone {
29
43
  #[allow(clippy::too_many_arguments)]
@@ -43,7 +57,7 @@ impl NativePeerbitBackbone {
43
57
  self_replicating: bool,
44
58
  resolve_trimmed_entries: bool,
45
59
  ) -> Result<Array, JsValue> {
46
- self.prepare_plain_storage_append_transaction_inner(
60
+ Ok(self.prepare_plain_storage_append_transaction_inner(
47
61
  wall_time,
48
62
  logical,
49
63
  gid,
@@ -60,7 +74,7 @@ impl NativePeerbitBackbone {
60
74
  None,
61
75
  true,
62
76
  None,
63
- )
77
+ )?)
64
78
  }
65
79
 
66
80
  #[allow(clippy::too_many_arguments)]
@@ -128,7 +142,7 @@ impl NativePeerbitBackbone {
128
142
  document_projection_encoded_document: JsValue,
129
143
  document_projection_signer: JsValue,
130
144
  ) -> Result<Array, JsValue> {
131
- self.prepare_plain_storage_append_transaction_inner(
145
+ Ok(self.prepare_plain_storage_append_transaction_inner(
132
146
  wall_time,
133
147
  logical,
134
148
  gid,
@@ -154,7 +168,7 @@ impl NativePeerbitBackbone {
154
168
  document_projection_encoded_document,
155
169
  document_projection_signer,
156
170
  )?),
157
- )
171
+ )?)
158
172
  }
159
173
 
160
174
  #[allow(clippy::too_many_arguments)]
@@ -191,21 +205,23 @@ impl NativePeerbitBackbone {
191
205
  document_projection_encoded_document,
192
206
  document_projection_signer,
193
207
  )?;
194
- self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
195
- wall_time,
196
- logical,
197
- fallback_gid,
198
- entry_type,
199
- meta_data,
200
- payload_data,
201
- replicas,
202
- role_age_ms,
203
- now,
204
- self_hash,
205
- self_replicating,
206
- resolve_trimmed_entries,
207
- trim_length_to,
208
- document_index_commit,
208
+ Ok(
209
+ self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
210
+ wall_time,
211
+ logical,
212
+ fallback_gid,
213
+ entry_type,
214
+ meta_data,
215
+ payload_data,
216
+ replicas,
217
+ role_age_ms,
218
+ now,
219
+ self_hash,
220
+ self_replicating,
221
+ resolve_trimmed_entries,
222
+ trim_length_to,
223
+ document_index_commit,
224
+ )?,
209
225
  )
210
226
  }
211
227
 
@@ -246,21 +262,23 @@ impl NativePeerbitBackbone {
246
262
  )?;
247
263
  document_index_commit.required_previous_signer_public_key =
248
264
  Some(required_previous_signer_public_key.to_vec());
249
- self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
250
- wall_time,
251
- logical,
252
- fallback_gid,
253
- entry_type,
254
- meta_data,
255
- payload_data,
256
- replicas,
257
- role_age_ms,
258
- now,
259
- self_hash,
260
- self_replicating,
261
- resolve_trimmed_entries,
262
- trim_length_to,
263
- document_index_commit,
265
+ Ok(
266
+ self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
267
+ wall_time,
268
+ logical,
269
+ fallback_gid,
270
+ entry_type,
271
+ meta_data,
272
+ payload_data,
273
+ replicas,
274
+ role_age_ms,
275
+ now,
276
+ self_hash,
277
+ self_replicating,
278
+ resolve_trimmed_entries,
279
+ trim_length_to,
280
+ document_index_commit,
281
+ )?,
264
282
  )
265
283
  }
266
284
 
@@ -296,21 +314,23 @@ impl NativePeerbitBackbone {
296
314
  document_projection_encoded_document,
297
315
  document_projection_signer,
298
316
  )?;
299
- self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
300
- wall_time,
301
- logical,
302
- fallback_gid,
303
- entry_type,
304
- meta_data,
305
- payload_data,
306
- replicas,
307
- role_age_ms,
308
- now,
309
- self_hash,
310
- self_replicating,
311
- resolve_trimmed_entries,
312
- trim_length_to,
313
- document_index_commit,
317
+ Ok(
318
+ self.prepare_plain_committed_storage_append_document_index_latest_transaction_inner(
319
+ wall_time,
320
+ logical,
321
+ fallback_gid,
322
+ entry_type,
323
+ meta_data,
324
+ payload_data,
325
+ replicas,
326
+ role_age_ms,
327
+ now,
328
+ self_hash,
329
+ self_replicating,
330
+ resolve_trimmed_entries,
331
+ trim_length_to,
332
+ document_index_commit,
333
+ )?,
314
334
  )
315
335
  }
316
336
 
@@ -348,21 +368,22 @@ impl NativePeerbitBackbone {
348
368
  document_projection_encoded_document,
349
369
  document_projection_signer,
350
370
  )?;
351
- self.prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
352
- wall_time,
353
- logical,
354
- fallback_gid,
355
- entry_type,
356
- meta_data,
357
- payload_data,
358
- replicas,
359
- role_age_ms,
360
- now,
361
- self_hash,
362
- self_replicating,
363
- trim_length_to,
364
- document_index_commit,
365
- )
371
+ Ok(self
372
+ .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
373
+ wall_time,
374
+ logical,
375
+ fallback_gid,
376
+ entry_type,
377
+ meta_data,
378
+ payload_data,
379
+ replicas,
380
+ role_age_ms,
381
+ now,
382
+ self_hash,
383
+ self_replicating,
384
+ trim_length_to,
385
+ document_index_commit,
386
+ )?)
366
387
  }
367
388
 
368
389
  #[allow(clippy::too_many_arguments)]
@@ -391,21 +412,22 @@ impl NativePeerbitBackbone {
391
412
  document_byte_element_index_limit,
392
413
  document_delete_trimmed_heads,
393
414
  )?;
394
- self.prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
395
- wall_time,
396
- logical,
397
- fallback_gid,
398
- entry_type,
399
- meta_data,
400
- payload_data,
401
- replicas,
402
- role_age_ms,
403
- now,
404
- self_hash,
405
- self_replicating,
406
- trim_length_to,
407
- document_index_commit,
408
- )
415
+ Ok(self
416
+ .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
417
+ wall_time,
418
+ logical,
419
+ fallback_gid,
420
+ entry_type,
421
+ meta_data,
422
+ payload_data,
423
+ replicas,
424
+ role_age_ms,
425
+ now,
426
+ self_hash,
427
+ self_replicating,
428
+ trim_length_to,
429
+ document_index_commit,
430
+ )?)
409
431
  }
410
432
 
411
433
  #[allow(clippy::too_many_arguments)]
@@ -445,21 +467,22 @@ impl NativePeerbitBackbone {
445
467
  )?;
446
468
  document_index_commit.required_previous_signer_public_key =
447
469
  Some(required_previous_signer_public_key.to_vec());
448
- self.prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
449
- wall_time,
450
- logical,
451
- fallback_gid,
452
- entry_type,
453
- meta_data,
454
- payload_data,
455
- replicas,
456
- role_age_ms,
457
- now,
458
- self_hash,
459
- self_replicating,
460
- trim_length_to,
461
- document_index_commit,
462
- )
470
+ Ok(self
471
+ .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
472
+ wall_time,
473
+ logical,
474
+ fallback_gid,
475
+ entry_type,
476
+ meta_data,
477
+ payload_data,
478
+ replicas,
479
+ role_age_ms,
480
+ now,
481
+ self_hash,
482
+ self_replicating,
483
+ trim_length_to,
484
+ document_index_commit,
485
+ )?)
463
486
  }
464
487
 
465
488
  #[allow(clippy::too_many_arguments)]
@@ -494,21 +517,22 @@ impl NativePeerbitBackbone {
494
517
  document_projection_encoded_document,
495
518
  document_projection_signer,
496
519
  )?;
497
- self.prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
498
- wall_time,
499
- logical,
500
- fallback_gid,
501
- entry_type,
502
- meta_data,
503
- payload_data,
504
- replicas,
505
- role_age_ms,
506
- now,
507
- self_hash,
508
- self_replicating,
509
- trim_length_to,
510
- document_index_commit,
511
- )
520
+ Ok(self
521
+ .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
522
+ wall_time,
523
+ logical,
524
+ fallback_gid,
525
+ entry_type,
526
+ meta_data,
527
+ payload_data,
528
+ replicas,
529
+ role_age_ms,
530
+ now,
531
+ self_hash,
532
+ self_replicating,
533
+ trim_length_to,
534
+ document_index_commit,
535
+ )?)
512
536
  }
513
537
 
514
538
  #[allow(clippy::too_many_arguments)]
@@ -542,21 +566,22 @@ impl NativePeerbitBackbone {
542
566
  document_projection_plan_id,
543
567
  document_projection_signer,
544
568
  )?;
545
- self.prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
546
- wall_time,
547
- logical,
548
- fallback_gid,
549
- entry_type,
550
- meta_data,
551
- payload_data,
552
- replicas,
553
- role_age_ms,
554
- now,
555
- self_hash,
556
- self_replicating,
557
- trim_length_to,
558
- document_index_commit,
559
- )
569
+ Ok(self
570
+ .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
571
+ wall_time,
572
+ logical,
573
+ fallback_gid,
574
+ entry_type,
575
+ meta_data,
576
+ payload_data,
577
+ replicas,
578
+ role_age_ms,
579
+ now,
580
+ self_hash,
581
+ self_replicating,
582
+ trim_length_to,
583
+ document_index_commit,
584
+ )?)
560
585
  }
561
586
 
562
587
  #[allow(clippy::too_many_arguments)]
@@ -596,38 +621,39 @@ impl NativePeerbitBackbone {
596
621
  "batch document value prefixes",
597
622
  )?;
598
623
  let document_keys = strings_from_array(document_keys)?;
599
- self.prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
600
- wall_times,
601
- logicals,
602
- fallback_gids,
603
- entry_type,
604
- meta_datas,
605
- payload_datas,
606
- replicas,
607
- role_age_ms,
608
- now,
609
- self_hash,
610
- self_replicating,
611
- resolve_trimmed_entries,
612
- trim_length_to,
613
- &mut |index| {
614
- document_index_append_commit(
615
- document_keys[index as usize].clone(),
616
- required_bytes_from_array(
617
- &document_value_prefix_bytes,
618
- index,
619
- "document value prefix",
620
- )?
621
- .to_vec(),
622
- String::new(),
623
- document_byte_element_index_limit,
624
- document_delete_trimmed_heads,
625
- JsValue::UNDEFINED,
626
- JsValue::UNDEFINED,
627
- JsValue::UNDEFINED,
628
- )
629
- },
630
- )
624
+ Ok(self
625
+ .prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
626
+ wall_times,
627
+ logicals,
628
+ fallback_gids,
629
+ entry_type,
630
+ meta_datas,
631
+ payload_datas,
632
+ replicas,
633
+ role_age_ms,
634
+ now,
635
+ self_hash,
636
+ self_replicating,
637
+ resolve_trimmed_entries,
638
+ trim_length_to,
639
+ &mut |index| {
640
+ document_index_append_commit(
641
+ document_keys[index as usize].clone(),
642
+ required_bytes_from_array(
643
+ &document_value_prefix_bytes,
644
+ index,
645
+ "document value prefix",
646
+ )?
647
+ .to_vec(),
648
+ String::new(),
649
+ document_byte_element_index_limit,
650
+ document_delete_trimmed_heads,
651
+ JsValue::UNDEFINED,
652
+ JsValue::UNDEFINED,
653
+ JsValue::UNDEFINED,
654
+ )
655
+ },
656
+ )?)
631
657
  }
632
658
 
633
659
  #[allow(clippy::too_many_arguments)]
@@ -669,41 +695,42 @@ impl NativePeerbitBackbone {
669
695
  )?;
670
696
  let required_previous_signer_public_key = required_previous_signer_public_key.to_vec();
671
697
  let document_keys = strings_from_array(document_keys)?;
672
- self.prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
673
- wall_times,
674
- logicals,
675
- fallback_gids,
676
- entry_type,
677
- meta_datas,
678
- payload_datas,
679
- replicas,
680
- role_age_ms,
681
- now,
682
- self_hash,
683
- self_replicating,
684
- resolve_trimmed_entries,
685
- trim_length_to,
686
- &mut |index| {
687
- let mut document_index_commit = document_index_append_commit(
688
- document_keys[index as usize].clone(),
689
- required_bytes_from_array(
690
- &document_value_prefix_bytes,
691
- index,
692
- "document value prefix",
693
- )?
694
- .to_vec(),
695
- String::new(),
696
- document_byte_element_index_limit,
697
- document_delete_trimmed_heads,
698
- JsValue::UNDEFINED,
699
- JsValue::UNDEFINED,
700
- JsValue::UNDEFINED,
701
- )?;
702
- document_index_commit.required_previous_signer_public_key =
703
- Some(required_previous_signer_public_key.clone());
704
- Ok(document_index_commit)
705
- },
706
- )
698
+ Ok(self
699
+ .prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
700
+ wall_times,
701
+ logicals,
702
+ fallback_gids,
703
+ entry_type,
704
+ meta_datas,
705
+ payload_datas,
706
+ replicas,
707
+ role_age_ms,
708
+ now,
709
+ self_hash,
710
+ self_replicating,
711
+ resolve_trimmed_entries,
712
+ trim_length_to,
713
+ &mut |index| {
714
+ let mut document_index_commit = document_index_append_commit(
715
+ document_keys[index as usize].clone(),
716
+ required_bytes_from_array(
717
+ &document_value_prefix_bytes,
718
+ index,
719
+ "document value prefix",
720
+ )?
721
+ .to_vec(),
722
+ String::new(),
723
+ document_byte_element_index_limit,
724
+ document_delete_trimmed_heads,
725
+ JsValue::UNDEFINED,
726
+ JsValue::UNDEFINED,
727
+ JsValue::UNDEFINED,
728
+ )?;
729
+ document_index_commit.required_previous_signer_public_key =
730
+ Some(required_previous_signer_public_key.clone());
731
+ Ok(document_index_commit)
732
+ },
733
+ )?)
707
734
  }
708
735
 
709
736
  #[allow(clippy::too_many_arguments)]
@@ -762,7 +789,7 @@ impl NativePeerbitBackbone {
762
789
  JsValue::UNDEFINED,
763
790
  )?);
764
791
  }
765
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
792
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
766
793
  wall_times,
767
794
  logicals,
768
795
  fallback_gids,
@@ -777,7 +804,7 @@ impl NativePeerbitBackbone {
777
804
  trim_length_to,
778
805
  &document_keys,
779
806
  document_index_commits,
780
- )
807
+ )?)
781
808
  }
782
809
 
783
810
  #[allow(clippy::too_many_arguments)]
@@ -820,7 +847,7 @@ impl NativePeerbitBackbone {
820
847
  document_delete_trimmed_heads,
821
848
  )?);
822
849
  }
823
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
850
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
824
851
  wall_times,
825
852
  logicals,
826
853
  fallback_gids,
@@ -835,7 +862,7 @@ impl NativePeerbitBackbone {
835
862
  trim_length_to,
836
863
  &document_keys,
837
864
  document_index_commits,
838
- )
865
+ )?)
839
866
  }
840
867
 
841
868
  #[allow(clippy::too_many_arguments)]
@@ -899,7 +926,7 @@ impl NativePeerbitBackbone {
899
926
  Some(required_previous_signer_public_key.clone());
900
927
  document_index_commits.push(document_index_commit);
901
928
  }
902
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
929
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
903
930
  wall_times,
904
931
  logicals,
905
932
  fallback_gids,
@@ -914,7 +941,7 @@ impl NativePeerbitBackbone {
914
941
  trim_length_to,
915
942
  &document_keys,
916
943
  document_index_commits,
917
- )
944
+ )?)
918
945
  }
919
946
 
920
947
  #[allow(clippy::too_many_arguments)]
@@ -957,36 +984,37 @@ impl NativePeerbitBackbone {
957
984
  &document_projection_signers,
958
985
  )?;
959
986
  let document_keys = strings_from_array(document_keys)?;
960
- self.prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
961
- wall_times,
962
- logicals,
963
- fallback_gids,
964
- entry_type,
965
- meta_datas,
966
- payload_datas,
967
- replicas,
968
- role_age_ms,
969
- now,
970
- self_hash,
971
- self_replicating,
972
- resolve_trimmed_entries,
973
- trim_length_to,
974
- &mut |index| {
975
- let encoded_document = required_projection_encoded_document(
976
- &document_projection_encoded_documents,
977
- index,
978
- )?;
979
- document_index_cached_projection_append_commit(
980
- document_keys[index as usize].clone(),
981
- String::new(),
982
- document_byte_element_index_limit,
983
- document_delete_trimmed_heads,
984
- document_projection_plan_ids.get_index(index),
985
- encoded_document,
986
- document_projection_signers.get(index),
987
- )
988
- },
989
- )
987
+ Ok(self
988
+ .prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
989
+ wall_times,
990
+ logicals,
991
+ fallback_gids,
992
+ entry_type,
993
+ meta_datas,
994
+ payload_datas,
995
+ replicas,
996
+ role_age_ms,
997
+ now,
998
+ self_hash,
999
+ self_replicating,
1000
+ resolve_trimmed_entries,
1001
+ trim_length_to,
1002
+ &mut |index| {
1003
+ let encoded_document = required_projection_encoded_document(
1004
+ &document_projection_encoded_documents,
1005
+ index,
1006
+ )?;
1007
+ document_index_cached_projection_append_commit(
1008
+ document_keys[index as usize].clone(),
1009
+ String::new(),
1010
+ document_byte_element_index_limit,
1011
+ document_delete_trimmed_heads,
1012
+ document_projection_plan_ids.get_index(index),
1013
+ encoded_document,
1014
+ document_projection_signers.get(index),
1015
+ )
1016
+ },
1017
+ )?)
990
1018
  }
991
1019
 
992
1020
  #[allow(clippy::too_many_arguments)]
@@ -1031,39 +1059,40 @@ impl NativePeerbitBackbone {
1031
1059
  )?;
1032
1060
  let required_previous_signer_public_key = required_previous_signer_public_key.to_vec();
1033
1061
  let document_keys = strings_from_array(document_keys)?;
1034
- self.prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
1035
- wall_times,
1036
- logicals,
1037
- fallback_gids,
1038
- entry_type,
1039
- meta_datas,
1040
- payload_datas,
1041
- replicas,
1042
- role_age_ms,
1043
- now,
1044
- self_hash,
1045
- self_replicating,
1046
- resolve_trimmed_entries,
1047
- trim_length_to,
1048
- &mut |index| {
1049
- let encoded_document = required_projection_encoded_document(
1050
- &document_projection_encoded_documents,
1051
- index,
1052
- )?;
1053
- let mut document_index_commit = document_index_cached_projection_append_commit(
1054
- document_keys[index as usize].clone(),
1055
- String::new(),
1056
- document_byte_element_index_limit,
1057
- document_delete_trimmed_heads,
1058
- document_projection_plan_ids.get_index(index),
1059
- encoded_document,
1060
- document_projection_signers.get(index),
1061
- )?;
1062
- document_index_commit.required_previous_signer_public_key =
1063
- Some(required_previous_signer_public_key.clone());
1064
- Ok(document_index_commit)
1065
- },
1066
- )
1062
+ Ok(self
1063
+ .prepare_plain_committed_storage_append_document_index_latest_batch_transaction_inner(
1064
+ wall_times,
1065
+ logicals,
1066
+ fallback_gids,
1067
+ entry_type,
1068
+ meta_datas,
1069
+ payload_datas,
1070
+ replicas,
1071
+ role_age_ms,
1072
+ now,
1073
+ self_hash,
1074
+ self_replicating,
1075
+ resolve_trimmed_entries,
1076
+ trim_length_to,
1077
+ &mut |index| {
1078
+ let encoded_document = required_projection_encoded_document(
1079
+ &document_projection_encoded_documents,
1080
+ index,
1081
+ )?;
1082
+ let mut document_index_commit = document_index_cached_projection_append_commit(
1083
+ document_keys[index as usize].clone(),
1084
+ String::new(),
1085
+ document_byte_element_index_limit,
1086
+ document_delete_trimmed_heads,
1087
+ document_projection_plan_ids.get_index(index),
1088
+ encoded_document,
1089
+ document_projection_signers.get(index),
1090
+ )?;
1091
+ document_index_commit.required_previous_signer_public_key =
1092
+ Some(required_previous_signer_public_key.clone());
1093
+ Ok(document_index_commit)
1094
+ },
1095
+ )?)
1067
1096
  }
1068
1097
 
1069
1098
  #[allow(clippy::too_many_arguments)]
@@ -1123,7 +1152,7 @@ impl NativePeerbitBackbone {
1123
1152
  document_projection_signers.get(index_u32),
1124
1153
  )?);
1125
1154
  }
1126
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1155
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1127
1156
  wall_times,
1128
1157
  logicals,
1129
1158
  fallback_gids,
@@ -1138,7 +1167,7 @@ impl NativePeerbitBackbone {
1138
1167
  trim_length_to,
1139
1168
  &document_keys,
1140
1169
  document_index_commits,
1141
- )
1170
+ )?)
1142
1171
  }
1143
1172
 
1144
1173
  #[allow(clippy::too_many_arguments)]
@@ -1203,7 +1232,7 @@ impl NativePeerbitBackbone {
1203
1232
  Some(required_previous_signer_public_key.clone());
1204
1233
  document_index_commits.push(document_index_commit);
1205
1234
  }
1206
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1235
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1207
1236
  wall_times,
1208
1237
  logicals,
1209
1238
  fallback_gids,
@@ -1218,7 +1247,7 @@ impl NativePeerbitBackbone {
1218
1247
  trim_length_to,
1219
1248
  &document_keys,
1220
1249
  document_index_commits,
1221
- )
1250
+ )?)
1222
1251
  }
1223
1252
 
1224
1253
  #[allow(clippy::too_many_arguments)]
@@ -1274,7 +1303,7 @@ impl NativePeerbitBackbone {
1274
1303
  )?,
1275
1304
  );
1276
1305
  }
1277
- self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1306
+ Ok(self.prepare_plain_committed_storage_append_document_index_latest_compact_batch_transaction_dispatch(
1278
1307
  wall_times,
1279
1308
  logicals,
1280
1309
  fallback_gids,
@@ -1289,7 +1318,7 @@ impl NativePeerbitBackbone {
1289
1318
  trim_length_to,
1290
1319
  &document_keys,
1291
1320
  document_index_commits,
1292
- )
1321
+ )?)
1293
1322
  }
1294
1323
 
1295
1324
  #[allow(clippy::too_many_arguments)]
@@ -1310,7 +1339,7 @@ impl NativePeerbitBackbone {
1310
1339
  resolve_trimmed_entries: bool,
1311
1340
  trim_length_to: usize,
1312
1341
  ) -> Result<Array, JsValue> {
1313
- self.prepare_plain_storage_append_transaction_inner(
1342
+ Ok(self.prepare_plain_storage_append_transaction_inner(
1314
1343
  wall_time,
1315
1344
  logical,
1316
1345
  gid,
@@ -1327,7 +1356,7 @@ impl NativePeerbitBackbone {
1327
1356
  Some(trim_length_to),
1328
1357
  true,
1329
1358
  None,
1330
- )
1359
+ )?)
1331
1360
  }
1332
1361
 
1333
1362
  #[allow(clippy::too_many_arguments)]
@@ -1397,7 +1426,7 @@ impl NativePeerbitBackbone {
1397
1426
  document_projection_signer: JsValue,
1398
1427
  trim_length_to: usize,
1399
1428
  ) -> Result<Array, JsValue> {
1400
- self.prepare_plain_storage_append_transaction_inner(
1429
+ Ok(self.prepare_plain_storage_append_transaction_inner(
1401
1430
  wall_time,
1402
1431
  logical,
1403
1432
  gid,
@@ -1423,7 +1452,7 @@ impl NativePeerbitBackbone {
1423
1452
  document_projection_encoded_document,
1424
1453
  document_projection_signer,
1425
1454
  )?),
1426
- )
1455
+ )?)
1427
1456
  }
1428
1457
  }
1429
1458
 
@@ -1445,7 +1474,7 @@ impl NativePeerbitBackbone {
1445
1474
  trim_length_to: Option<usize>,
1446
1475
  document_keys: &[String],
1447
1476
  document_index_commits: Vec<DocumentIndexAppendCommit>,
1448
- ) -> Result<Array, JsValue> {
1477
+ ) -> Result<Array, BackboneError> {
1449
1478
  if has_duplicate_strings(document_keys) {
1450
1479
  let out = Array::new();
1451
1480
  for (index, document_index_commit) in document_index_commits.into_iter().enumerate() {
@@ -1453,7 +1482,7 @@ impl NativePeerbitBackbone {
1453
1482
  let fallback_gid = fallback_gids
1454
1483
  .get(index_u32)
1455
1484
  .as_string()
1456
- .ok_or_else(|| JsValue::from_str("Expected batch fallback gid string"))?;
1485
+ .ok_or(BackboneError::ExpectedString("batch fallback gid"))?;
1457
1486
  let row = self
1458
1487
  .prepare_plain_committed_storage_append_document_index_latest_compact_transaction_inner(
1459
1488
  wall_times.get_index(index_u32),
@@ -1508,11 +1537,12 @@ impl NativePeerbitBackbone {
1508
1537
  resolve_trimmed_entries: bool,
1509
1538
  trim_length_to: JsValue,
1510
1539
  mut document_index_commit: DocumentIndexAppendCommit,
1511
- ) -> Result<Array, JsValue> {
1540
+ ) -> Result<Array, BackboneError> {
1512
1541
  let trim_length_to = optional_usize_from_js(trim_length_to, "trimLengthTo")?;
1513
1542
  let (_, gid, next_hashes) =
1514
1543
  self.resolve_latest_document_append_context(&mut document_index_commit, fallback_gid)?;
1515
- self.validate_document_index_required_previous_signer(&document_index_commit)?;
1544
+ self.validate_document_index_required_previous_signer(&document_index_commit)
1545
+ .map_err(js_wrapper_error)?;
1516
1546
  self.prepare_plain_storage_append_transaction_inner(
1517
1547
  wall_time,
1518
1548
  logical,
@@ -1553,13 +1583,13 @@ impl NativePeerbitBackbone {
1553
1583
  u32,
1554
1584
  )
1555
1585
  -> Result<DocumentIndexAppendCommit, JsValue>,
1556
- ) -> Result<Array, JsValue> {
1586
+ ) -> Result<Array, BackboneError> {
1557
1587
  let batch_len = payload_datas.length() as usize;
1558
1588
  if batch_len == 0 {
1559
1589
  return Ok(Array::new());
1560
1590
  }
1561
1591
  let profile_enabled = self.append_profile_enabled;
1562
- let storage_append_started = profile_enabled.then(js_sys::Date::now);
1592
+ let storage_append_started = profile_enabled.then(crate::time::now_ms);
1563
1593
  self.reserve_document_batch(batch_len);
1564
1594
  let mut pending_appends = Vec::with_capacity(batch_len);
1565
1595
  let mut coordinate_inputs = Vec::with_capacity(batch_len);
@@ -1612,7 +1642,7 @@ impl NativePeerbitBackbone {
1612
1642
 
1613
1643
  let out = Array::new();
1614
1644
  for (pending, coordinate_facts) in pending_appends.into_iter().zip(coordinate_facts) {
1615
- let coordinate_core_started = profile_enabled.then(js_sys::Date::now);
1645
+ let coordinate_core_started = profile_enabled.then(crate::time::now_ms);
1616
1646
  self.commit_coordinate_core_from_compact_facts(
1617
1647
  &coordinate_facts,
1618
1648
  &pending.next_hashes,
@@ -1621,19 +1651,28 @@ impl NativePeerbitBackbone {
1621
1651
  pending.meta_bytes,
1622
1652
  );
1623
1653
  if let Some(started) = coordinate_core_started {
1624
- self.append_profile.coordinate_core_ms += js_sys::Date::now() - started;
1654
+ self.append_profile.coordinate_core_ms += crate::time::now_ms() - started;
1625
1655
  }
1626
1656
 
1627
- let result_row_started = profile_enabled.then(js_sys::Date::now);
1657
+ // Rebuild the frozen JS entry/trim rows from the owned pending state
1658
+ // at the emit boundary, timed against the same entry_row/trim_rows
1659
+ // profile counters the pre-lift inline build used.
1660
+ let entry_row = self.committed_entry_facts_to_row_profiled(&pending.entry_facts);
1661
+ let trim_rows = self.native_backbone_trim_entries_to_rows_profiled(
1662
+ pending.trimmed_entries,
1663
+ pending.resolve_trimmed_entries,
1664
+ );
1665
+
1666
+ let result_row_started = profile_enabled.then(crate::time::now_ms);
1628
1667
  let row = Array::new();
1629
- row.push(&pending.entry_row);
1668
+ row.push(&entry_row);
1630
1669
  row.push(&leader_samples_to_optional_rows(&coordinate_facts.leaders));
1631
1670
  row.push(&JsValue::from_bool(coordinate_facts.is_leader));
1632
1671
  row.push(&JsValue::from_bool(
1633
1672
  coordinate_facts.assigned_to_range_boundary,
1634
1673
  ));
1635
1674
  row.push(&coordinate_plan_to_row(&self.resolution, &coordinate_facts));
1636
- row.push(&pending.trim_rows);
1675
+ row.push(&trim_rows);
1637
1676
  row.push(&strings_to_array(pending.trim_hashes));
1638
1677
  row.push(&JsValue::from_bool(
1639
1678
  pending.document_trimmed_heads_processed,
@@ -1647,12 +1686,12 @@ impl NativePeerbitBackbone {
1647
1686
  );
1648
1687
  out.push(&row);
1649
1688
  if let Some(started) = result_row_started {
1650
- self.append_profile.result_row_ms += js_sys::Date::now() - started;
1689
+ self.append_profile.result_row_ms += crate::time::now_ms() - started;
1651
1690
  }
1652
1691
  }
1653
1692
 
1654
1693
  if let Some(started) = storage_append_started {
1655
- self.append_profile.storage_append_inner_ms += js_sys::Date::now() - started;
1694
+ self.append_profile.storage_append_inner_ms += crate::time::now_ms() - started;
1656
1695
  }
1657
1696
  Ok(out)
1658
1697
  }
@@ -1680,27 +1719,29 @@ impl NativePeerbitBackbone {
1680
1719
  -> Result<DocumentIndexAppendCommit, JsValue>,
1681
1720
  pending_appends: &mut Vec<LatestBatchPendingAppend>,
1682
1721
  coordinate_inputs: &mut Vec<NativeLocalAppendCompactInput>,
1683
- ) -> Result<(), JsValue> {
1722
+ ) -> Result<(), BackboneError> {
1684
1723
  let profile_enabled = self.append_profile_enabled;
1685
1724
  let fallback_gid = fallback_gids
1686
1725
  .get(index)
1687
1726
  .as_string()
1688
- .ok_or_else(|| JsValue::from_str("Expected batch fallback gid string"))?;
1689
- let mut document_index_commit = make_document_index_commit(index)?;
1727
+ .ok_or(BackboneError::ExpectedString("batch fallback gid"))?;
1728
+ let mut document_index_commit =
1729
+ make_document_index_commit(index).map_err(js_wrapper_error)?;
1690
1730
  let payload_data = required_bytes_from_array(payload_datas, index, "payload")?;
1691
1731
  let trim_length_to = optional_usize_from_js(trim_length_to.clone(), "trimLengthTo")?;
1692
1732
  let payload_size = payload_data.length();
1693
1733
  let delete_trimmed_document_heads = document_index_commit.delete_trimmed_heads;
1694
1734
  let (previous_document_context, gid, next_hashes) =
1695
1735
  self.resolve_latest_document_append_context(&mut document_index_commit, fallback_gid)?;
1696
- self.validate_document_index_required_previous_signer(&document_index_commit)?;
1736
+ self.validate_document_index_required_previous_signer(&document_index_commit)
1737
+ .map_err(js_wrapper_error)?;
1697
1738
 
1698
1739
  let (meta_data, payload_data) =
1699
- self.copy_append_inputs_profiled(meta_datas.get(index), &payload_data);
1740
+ self.copy_append_inputs_profiled(meta_datas.get(index), &payload_data)?;
1700
1741
 
1701
1742
  let wall_time = wall_times.get_index(index);
1702
- let (entry_facts, trim_hashes, entry_row, trim_rows) = self
1703
- .prepare_committed_log_append_rows_profiled(
1743
+ let (entry_facts, trimmed_entries, trim_hashes) = self
1744
+ .prepare_committed_log_append_owned_profiled(
1704
1745
  wall_time,
1705
1746
  logicals.get_index(index),
1706
1747
  gid.clone(),
@@ -1737,22 +1778,27 @@ impl NativePeerbitBackbone {
1737
1778
  next_hashes: next_hashes.clone(),
1738
1779
  delete_hashes: trim_hashes.clone(),
1739
1780
  });
1781
+ // Keep the entry hash for the document-index put; `entry_facts` itself
1782
+ // moves into the pending state so the JS entry row is rebuilt only when
1783
+ // the batch is emitted.
1784
+ let entry_hash = entry_facts.hash.clone();
1740
1785
  let mut pending_append = LatestBatchPendingAppend {
1741
1786
  wall_time,
1742
1787
  next_hashes,
1743
1788
  meta_bytes: entry_facts.meta_bytes.clone(),
1744
1789
  trim_hashes,
1745
- entry_row,
1746
- trim_rows,
1790
+ entry_facts,
1791
+ trimmed_entries,
1792
+ resolve_trimmed_entries,
1747
1793
  document_trimmed_heads_processed: false,
1748
1794
  previous_document_context,
1749
1795
  };
1750
1796
 
1751
- let document_index_started = profile_enabled.then(js_sys::Date::now);
1797
+ let document_index_started = profile_enabled.then(crate::time::now_ms);
1752
1798
  let prepared_document_put = match self.prepare_document_index_append_put(
1753
1799
  document_index_commit,
1754
1800
  wall_time,
1755
- &entry_facts.hash,
1801
+ &entry_hash,
1756
1802
  &gid,
1757
1803
  payload_size,
1758
1804
  None,
@@ -1770,7 +1816,7 @@ impl NativePeerbitBackbone {
1770
1816
  && self.delete_documents_by_context_heads_profiled(&pending_append.trim_hashes);
1771
1817
  pending_append.document_trimmed_heads_processed = document_trimmed_heads_processed;
1772
1818
  if let Some(started) = document_index_started {
1773
- self.append_profile.document_index_commit_ms += js_sys::Date::now() - started;
1819
+ self.append_profile.document_index_commit_ms += crate::time::now_ms() - started;
1774
1820
  }
1775
1821
  pending_appends.push(pending_append);
1776
1822
  Ok(())
@@ -1786,7 +1832,7 @@ impl NativePeerbitBackbone {
1786
1832
  now: &str,
1787
1833
  self_hash: &str,
1788
1834
  self_replicating: bool,
1789
- ) -> Result<(), JsValue> {
1835
+ ) -> Result<(), BackboneError> {
1790
1836
  if coordinate_inputs.is_empty() {
1791
1837
  return Ok(());
1792
1838
  }
@@ -1829,9 +1875,9 @@ impl NativePeerbitBackbone {
1829
1875
  self_replicating: bool,
1830
1876
  trim_length_to: Option<usize>,
1831
1877
  document_index_commits: Vec<DocumentIndexAppendCommit>,
1832
- ) -> Result<Array, JsValue> {
1878
+ ) -> Result<Array, BackboneError> {
1833
1879
  let profile_enabled = self.append_profile_enabled;
1834
- let storage_append_started = profile_enabled.then(js_sys::Date::now);
1880
+ let storage_append_started = profile_enabled.then(crate::time::now_ms);
1835
1881
  let batch_len = document_index_commits.len();
1836
1882
  self.reserve_document_batch(batch_len);
1837
1883
  let mut pending_appends = Vec::with_capacity(batch_len);
@@ -1842,16 +1888,17 @@ impl NativePeerbitBackbone {
1842
1888
  let fallback_gid = fallback_gids
1843
1889
  .get(index_u32)
1844
1890
  .as_string()
1845
- .ok_or_else(|| JsValue::from_str("Expected batch fallback gid string"))?;
1891
+ .ok_or(BackboneError::ExpectedString("batch fallback gid"))?;
1846
1892
  let payload_bytes = required_bytes_from_array(&payload_datas, index_u32, "payload")?;
1847
1893
  let payload_size = payload_bytes.length();
1848
1894
  let delete_trimmed_document_heads = document_index_commit.delete_trimmed_heads;
1849
1895
  let (previous_document_context, gid, next_hashes) = self
1850
1896
  .resolve_latest_document_append_context(&mut document_index_commit, fallback_gid)?;
1851
- self.validate_document_index_required_previous_signer(&document_index_commit)?;
1897
+ self.validate_document_index_required_previous_signer(&document_index_commit)
1898
+ .map_err(js_wrapper_error)?;
1852
1899
 
1853
1900
  let (meta_data, payload_data) =
1854
- self.copy_append_inputs_profiled(meta_datas.get(index_u32), &payload_bytes);
1901
+ self.copy_append_inputs_profiled(meta_datas.get(index_u32), &payload_bytes)?;
1855
1902
 
1856
1903
  let (entry_facts, trim_hashes) = self.prepare_latest_log_append_profiled(
1857
1904
  wall_times.get_index(index_u32),
@@ -1910,7 +1957,7 @@ impl NativePeerbitBackbone {
1910
1957
 
1911
1958
  let out = Array::new();
1912
1959
  for (pending, coordinate_facts) in pending_appends.into_iter().zip(coordinate_facts) {
1913
- let coordinate_core_started = profile_enabled.then(js_sys::Date::now);
1960
+ let coordinate_core_started = profile_enabled.then(crate::time::now_ms);
1914
1961
  self.commit_coordinate_core_from_compact_facts(
1915
1962
  &coordinate_facts,
1916
1963
  &pending.entry_facts.next,
@@ -1919,7 +1966,7 @@ impl NativePeerbitBackbone {
1919
1966
  pending.entry_facts.meta_bytes.clone(),
1920
1967
  );
1921
1968
  if let Some(started) = coordinate_core_started {
1922
- self.append_profile.coordinate_core_ms += js_sys::Date::now() - started;
1969
+ self.append_profile.coordinate_core_ms += crate::time::now_ms() - started;
1923
1970
  }
1924
1971
 
1925
1972
  let document_trimmed_heads_processed = self.commit_append_document_index_profiled(
@@ -1933,7 +1980,7 @@ impl NativePeerbitBackbone {
1933
1980
  &pending.trim_hashes,
1934
1981
  )?;
1935
1982
 
1936
- let result_row_started = profile_enabled.then(js_sys::Date::now);
1983
+ let result_row_started = profile_enabled.then(crate::time::now_ms);
1937
1984
  let row = latest_compact_entry_row(
1938
1985
  &self.resolution,
1939
1986
  pending.entry_facts,
@@ -1950,12 +1997,12 @@ impl NativePeerbitBackbone {
1950
1997
  );
1951
1998
  out.push(&row);
1952
1999
  if let Some(started) = result_row_started {
1953
- self.append_profile.result_row_ms += js_sys::Date::now() - started;
2000
+ self.append_profile.result_row_ms += crate::time::now_ms() - started;
1954
2001
  }
1955
2002
  }
1956
2003
 
1957
2004
  if let Some(started) = storage_append_started {
1958
- self.append_profile.storage_append_inner_ms += js_sys::Date::now() - started;
2005
+ self.append_profile.storage_append_inner_ms += crate::time::now_ms() - started;
1959
2006
  }
1960
2007
  Ok(out)
1961
2008
  }
@@ -1976,16 +2023,18 @@ impl NativePeerbitBackbone {
1976
2023
  self_replicating: bool,
1977
2024
  trim_length_to: Option<usize>,
1978
2025
  mut document_index_commit: DocumentIndexAppendCommit,
1979
- ) -> Result<Array, JsValue> {
2026
+ ) -> Result<Array, BackboneError> {
1980
2027
  let profile_enabled = self.append_profile_enabled;
1981
- let storage_append_started = profile_enabled.then(js_sys::Date::now);
2028
+ let storage_append_started = profile_enabled.then(crate::time::now_ms);
1982
2029
  let payload_size = payload_data.length();
1983
2030
  let delete_trimmed_document_heads = document_index_commit.delete_trimmed_heads;
1984
2031
  let (previous_document_context, gid, next_hashes) =
1985
2032
  self.resolve_latest_document_append_context(&mut document_index_commit, fallback_gid)?;
1986
- self.validate_document_index_required_previous_signer(&document_index_commit)?;
2033
+ self.validate_document_index_required_previous_signer(&document_index_commit)
2034
+ .map_err(js_wrapper_error)?;
1987
2035
 
1988
- let (meta_data, payload_data) = self.copy_append_inputs_profiled(meta_data, &payload_data);
2036
+ let (meta_data, payload_data) =
2037
+ self.copy_append_inputs_profiled(meta_data, &payload_data)?;
1989
2038
 
1990
2039
  let (entry_facts, trim_hashes) = self.prepare_latest_log_append_profiled(
1991
2040
  wall_time,
@@ -2000,7 +2049,7 @@ impl NativePeerbitBackbone {
2000
2049
 
2001
2050
  let hash_number = self.hash_number_profiled(&entry_facts.hash_digest_bytes)?;
2002
2051
 
2003
- let coordinate_plan_started = profile_enabled.then(js_sys::Date::now);
2052
+ let coordinate_plan_started = profile_enabled.then(crate::time::now_ms);
2004
2053
  let coordinate_facts = commit_local_append_for_gid_compact_core(
2005
2054
  &mut self.shared_log,
2006
2055
  entry_facts.hash.clone(),
@@ -2017,10 +2066,10 @@ impl NativePeerbitBackbone {
2017
2066
  true,
2018
2067
  )?;
2019
2068
  if let Some(started) = coordinate_plan_started {
2020
- self.append_profile.coordinate_plan_ms += js_sys::Date::now() - started;
2069
+ self.append_profile.coordinate_plan_ms += crate::time::now_ms() - started;
2021
2070
  }
2022
2071
 
2023
- let coordinate_core_started = profile_enabled.then(js_sys::Date::now);
2072
+ let coordinate_core_started = profile_enabled.then(crate::time::now_ms);
2024
2073
  self.commit_coordinate_core_from_compact_facts(
2025
2074
  &coordinate_facts,
2026
2075
  &entry_facts.next,
@@ -2029,7 +2078,7 @@ impl NativePeerbitBackbone {
2029
2078
  entry_facts.meta_bytes.clone(),
2030
2079
  );
2031
2080
  if let Some(started) = coordinate_core_started {
2032
- self.append_profile.coordinate_core_ms += js_sys::Date::now() - started;
2081
+ self.append_profile.coordinate_core_ms += crate::time::now_ms() - started;
2033
2082
  }
2034
2083
 
2035
2084
  let document_trimmed_heads_processed = self.commit_append_document_index_profiled(
@@ -2043,7 +2092,7 @@ impl NativePeerbitBackbone {
2043
2092
  &trim_hashes,
2044
2093
  )?;
2045
2094
 
2046
- let result_row_started = profile_enabled.then(js_sys::Date::now);
2095
+ let result_row_started = profile_enabled.then(crate::time::now_ms);
2047
2096
  let out = latest_compact_entry_row(
2048
2097
  &self.resolution,
2049
2098
  entry_facts,
@@ -2053,11 +2102,35 @@ impl NativePeerbitBackbone {
2053
2102
  previous_document_context.as_ref(),
2054
2103
  );
2055
2104
  if let Some(started) = result_row_started {
2056
- self.append_profile.result_row_ms += js_sys::Date::now() - started;
2105
+ self.append_profile.result_row_ms += crate::time::now_ms() - started;
2057
2106
  }
2058
2107
  if let Some(started) = storage_append_started {
2059
- self.append_profile.storage_append_inner_ms += js_sys::Date::now() - started;
2108
+ self.append_profile.storage_append_inner_ms += crate::time::now_ms() - started;
2060
2109
  }
2061
2110
  Ok(out)
2062
2111
  }
2063
2112
  }
2113
+
2114
+ #[cfg(test)]
2115
+ mod tests {
2116
+ use crate::error::BackboneError;
2117
+
2118
+ // `js_wrapper_error` forwards the untyped documents-layer JsValue messages
2119
+ // verbatim through `BackboneError::Message`. These are the exact strings
2120
+ // the required-previous-signer validator throws; pin their Display so the
2121
+ // forwarded messages stay byte-for-byte with master. (The `JsValue` recovery
2122
+ // itself is exercised on wasm by the TS suite; host `cargo test` cannot
2123
+ // construct a round-tripping `JsValue`, so it pins the Message rendering.)
2124
+ #[test]
2125
+ fn forwarded_document_signer_messages_render_verbatim() {
2126
+ for message in [
2127
+ "Previous document signer public key unavailable",
2128
+ "Previous document signer public key did not match native policy",
2129
+ ] {
2130
+ assert_eq!(
2131
+ BackboneError::Message(message.to_string()).to_string(),
2132
+ message
2133
+ );
2134
+ }
2135
+ }
2136
+ }