@oxidezap/whatsapp-rust-bridge 0.11.0 → 0.13.0

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.
@@ -1649,6 +1649,24 @@ export interface WhatsAppEventCallbacks {
1649
1649
  * Protobuf-wire message path. The bridge packs a bounded ordered group of
1650
1650
  * messages — payloads and metadata alike — into one flat buffer. Decode it
1651
1651
  * with `decodeMessageWireBatch`.
1652
+ *
1653
+ * Decode every batch, exactly once, in the order it arrives, before calling
1654
+ * back into the client: addresses and push names repeat, so a batch defines
1655
+ * them once and later batches reference the table the decoder is holding.
1656
+ * A batch skipped or decoded out of order leaves that table describing a
1657
+ * history the records do not have.
1658
+ *
1659
+ * The return type is `void` and TypeScript lets an `async` method satisfy
1660
+ * it, so this is checked rather than trusted: a callback that hands back
1661
+ * anything promise-like has not decoded inside its call, and the bridge
1662
+ * gives up the cross-batch table for the rest of the session — every batch
1663
+ * then carries every value it names, which decodes the same in any order.
1664
+ * Keeping the buffer is fine; decoding it later is what costs the table.
1665
+ *
1666
+ * The check runs after the batch has been handed over, so the batch that
1667
+ * revealed the violation is the one it cannot save: decoded after a later
1668
+ * one, it reads that one's table. Every batch after it is safe whenever it
1669
+ * is decoded.
1652
1670
  */
1653
1671
  onMessageBatch(batch: MessageWireBatch): void;
1654
1672
  /**
@@ -2589,7 +2607,7 @@ export type PresenceStatus = "available" | "unavailable";
2589
2607
  * `From` impls below by walking the source chain. This keeps the JS object
2590
2608
  * shape predictable and the codegen / `Tsify` output simple.
2591
2609
  */
2592
- export type BridgeError = { kind: "server"; serverCode: number; serverText: string } | { kind: "timeout" } | { kind: "not-connected" } | { kind: "disconnected"; reason: string } | { kind: "invalid-argument"; field: string; reason: string } | { kind: "protocol-violation"; reason: string } | { kind: "crypto"; operation: string } | { kind: "storage"; operation: string } | { kind: "internal"; message: string };
2610
+ export type BridgeError = { kind: "server"; serverCode: number; serverText: string } | { kind: "timeout" } | { kind: "not-connected" } | { kind: "disconnected"; reason: string } | { kind: "invalid-argument"; field: string; reason: string } | { kind: "protocol-violation"; reason: string } | { kind: "crypto"; operation: string } | { kind: "storage"; operation: string } | { kind: "no-recipient-device"; attempted: number } | { kind: "internal"; message: string };
2593
2611
 
2594
2612
  /**
2595
2613
  * Public portion of one pre-key in a supplied pairwise session bundle.
@@ -4636,12 +4654,12 @@ export interface InitOutput {
4636
4654
  readonly intounderlyingsink_write: (a: number, b: number) => number;
4637
4655
  readonly intounderlyingsource_cancel: (a: number) => void;
4638
4656
  readonly intounderlyingsource_pull: (a: number, b: number) => number;
4639
- readonly __wasm_bindgen_func_elem_4319: (a: number, b: number, c: number) => void;
4640
- readonly __wasm_bindgen_func_elem_26161: (a: number, b: number, c: number, d: number) => void;
4641
- readonly __wasm_bindgen_func_elem_26163: (a: number, b: number, c: number, d: number) => void;
4642
- readonly __wasm_bindgen_func_elem_9212: (a: number, b: number, c: number) => void;
4643
- readonly __wasm_bindgen_func_elem_4318: (a: number, b: number, c: number) => void;
4644
- readonly __wasm_bindgen_func_elem_4317: (a: number, b: number) => void;
4657
+ readonly __wasm_bindgen_func_elem_4333: (a: number, b: number, c: number) => void;
4658
+ readonly __wasm_bindgen_func_elem_26304: (a: number, b: number, c: number, d: number) => void;
4659
+ readonly __wasm_bindgen_func_elem_26306: (a: number, b: number, c: number, d: number) => void;
4660
+ readonly __wasm_bindgen_func_elem_9238: (a: number, b: number, c: number) => void;
4661
+ readonly __wasm_bindgen_func_elem_4332: (a: number, b: number, c: number) => void;
4662
+ readonly __wasm_bindgen_func_elem_4331: (a: number, b: number) => void;
4645
4663
  readonly __wbindgen_export: (a: number, b: number) => number;
4646
4664
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
4647
4665
  readonly __wbindgen_export3: (a: number) => void;
Binary file
@@ -2,10 +2,19 @@
2
2
  * Packed wire-batch codecs (message metadata, receipts, server acks).
3
3
  *
4
4
  * The bridge crosses hot per-event metadata as fixed-width numeric records
5
- * plus a per-batch deduplicated string table: repeated addresses, push names
6
- * and ack classes pay one decode per batch instead of one FFI object build
7
- * per event. This module is the single host-side owner of every record
8
- * layout; the Rust writers live in `src/wasm_client.rs`.
5
+ * plus a string table that outlives the batch: repeated addresses, push names
6
+ * and ack classes are materialized once per process and referenced by index
7
+ * afterwards, instead of one FFI object build per event. This module is the
8
+ * single host-side owner of every record layout; the Rust writers live in
9
+ * `src/wire_batch.rs`.
10
+ *
11
+ * A table that outlives a batch only works while both sides agree on when it
12
+ * is dropped, so every codec here speaks one invalidation protocol: the writer
13
+ * sets `PACKED_FLAG_RESET_CACHES` in a batch's header and the reader clears
14
+ * before reading it. That makes every decoder here **stateful**. Decode each
15
+ * batch exactly once, in the order the bridge delivered it; a batch decoded
16
+ * twice, out of order, or not at all leaves the table describing a history the
17
+ * records do not have.
9
18
  */
10
19
  /** Serde shape of the core's `Jid` as carried by bridge events. */
11
20
  export interface WireJid {
@@ -54,8 +63,44 @@ export interface MessageWireEntry {
54
63
  info: MessageWireInfo;
55
64
  }
56
65
  /**
57
- * Inverse of `decodeMessageWireBatch`, for hosts that need to fabricate batches
58
- * (tests, replay tooling). Mirrors the Rust writer byte for byte.
66
+ * Build-side mirror of the Rust `MessageWireBatch`, for hosts that need to
67
+ * fabricate batches (tests, replay tooling).
68
+ *
69
+ * One encoder is one writer: it keeps the table across `encode` calls exactly
70
+ * as the bridge's does, so a run of batches decodes the way a run from the
71
+ * bridge decodes — later batches defining nothing and indexing what earlier
72
+ * ones defined. Its first batch always asks the reader to clear, so a run
73
+ * starts from a table it owns rather than one someone else left behind.
74
+ *
75
+ * Deliberately not re-exported from the package root. There is one standing
76
+ * table per realm, so a second live run has nowhere of its own to decode
77
+ * against: its reset batch would take the first run's entries with it. That
78
+ * makes this safe for a test or a replay that owns the process and unsafe as
79
+ * a public API. Hosts get `encodeMessageWireBatch`, whose batches are
80
+ * self-contained.
81
+ */
82
+ export declare class MessageWireBatchEncoder {
83
+ private readonly cache;
84
+ /** Entries the reader holds, and so the index the next definition takes. */
85
+ private held;
86
+ private cacheBytes;
87
+ private flags;
88
+ /**
89
+ * Encode one batch, as `MessageWireBatch::write_flat` writes one.
90
+ *
91
+ * A throw part-way leaves the encoder holding cache entries whose definitions
92
+ * were never written, so it gives the whole table up rather than hand the
93
+ * next batch indices the reader has no entries for — the same thing the Rust
94
+ * writer does with a batch it abandons.
95
+ */
96
+ encode(entries: readonly MessageWireEntry[]): PackedWireBatch;
97
+ private encodeBatch;
98
+ }
99
+ /**
100
+ * Inverse of `decodeMessageWireBatch` for a single standalone batch: it carries
101
+ * its own table definitions and asks the reader to clear, so it decodes the
102
+ * same whatever ran before it. Use `MessageWireBatchEncoder` to fabricate a run
103
+ * of batches that share a table the way the bridge's do.
59
104
  */
60
105
  export declare function encodeMessageWireBatch(entries: readonly MessageWireEntry[]): PackedWireBatch;
61
106
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxidezap/whatsapp-rust-bridge",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "A high-performance utilities for WhatsApp, powered by Rust and WebAssembly.",
5
5
  "author": "João Lucas <jlucaso@hotmail.com>",
6
6
  "license": "MIT",
@@ -31,6 +31,12 @@
31
31
  "bench": "bun run build && bun run benches/binary.ts && bun run benches/signal.ts && bun run benches/curve.ts && bun run benches/crypto.ts",
32
32
  "bench:node": "bun run build && node --expose-gc benches/binary.ts && node --expose-gc benches/signal.ts && node --expose-gc benches/curve.ts && node --expose-gc benches/crypto.ts",
33
33
  "bench:proto": "bun run benches/proto-encode.ts",
34
+ "bench:wire": "bun run benches/wire-batch-decode.ts",
35
+ "bench:wire:message": "bun run benches/message-wire-batch.ts",
36
+ "bench:codec-memory": "bun run benches/codec-memory/codec-count.ts",
37
+ "bench:codec-memory:in-situ": "bun run benches/codec-memory/in-situ.ts",
38
+ "bench:codec-memory:equivalence": "node --stack-size=4000 benches/codec-memory/equivalence.mjs",
39
+ "bench:codec-memory:import-stages": "bun run benches/codec-memory/import-stages.ts",
34
40
  "gen:bridge-types": "cargo fetch && cd codegen && cargo run -q --bin gen-types --target $(rustc -vV | grep host | cut -d' ' -f2) > ../src/generated_types.rs.tmp && mv ../src/generated_types.rs.tmp ../src/generated_types.rs",
35
41
  "gen:proto-codec": "bun run scripts/gen-ts-proto.ts",
36
42
  "gen:proto-types": "bun run scripts/gen-protobufjs-dts.ts",
@@ -47,6 +53,9 @@
47
53
  "example": "NODE_TLS_REJECT_UNAUTHORIZED=0 bun run examples/connect.ts",
48
54
  "test:rust": "wasm-pack test --node",
49
55
  "check:size": "bun run scripts/check-size.ts",
56
+ "check:wasm-shape": "node scripts/check-wasm-shape.mjs",
57
+ "measure:fn-sizes": "node scripts/wasm-fn-sizes.mjs pkg/whatsapp_rust_bridge_bg.wasm",
58
+ "measure:zone-peak": "node scripts/wasm-zone-peak.mjs pkg/whatsapp_rust_bridge_bg.wasm",
50
59
  "prepack": "bun run scripts/check-pack.ts",
51
60
  "prepublishOnly": "bun run build"
52
61
  },