@net-mesh/browser 0.42.0 → 0.44.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.
Files changed (45) hide show
  1. package/CHANGELOG.md +200 -0
  2. package/README.md +12 -0
  3. package/dist/index.bundle.js +2 -2
  4. package/dist/leader/session.d.ts +4 -2
  5. package/dist/leader/session.js +30 -6
  6. package/dist/lobby.d.ts +29 -2
  7. package/dist/lobby.js +80 -10
  8. package/dist/net_leaf.d.ts +19 -21
  9. package/dist/net_leaf.js +42 -44
  10. package/dist/net_leaf_bg.wasm +0 -0
  11. package/dist/net_leaf_bg.wasm.d.ts +10 -10
  12. package/dist/netcode/assignment.d.ts +169 -0
  13. package/dist/netcode/assignment.js +321 -0
  14. package/dist/netcode/client.d.ts +125 -3
  15. package/dist/netcode/client.js +291 -27
  16. package/dist/netcode/codec.d.ts +180 -0
  17. package/dist/netcode/codec.js +547 -0
  18. package/dist/netcode/host.d.ts +58 -1
  19. package/dist/netcode/host.js +254 -9
  20. package/dist/netcode/index.d.ts +14 -4
  21. package/dist/netcode/index.js +8 -3
  22. package/dist/netcode/interpolate.d.ts +24 -1
  23. package/dist/netcode/interpolate.js +52 -1
  24. package/dist/netcode/paths.d.ts +115 -0
  25. package/dist/netcode/paths.js +261 -0
  26. package/dist/netcode/shards.d.ts +138 -0
  27. package/dist/netcode/shards.js +270 -0
  28. package/dist/netcode/wire.d.ts +37 -3
  29. package/dist/netcode/wire.js +28 -1
  30. package/dist/node.d.ts +20 -0
  31. package/dist/node.js +76 -1
  32. package/dist/store/host.js +10 -4
  33. package/dist/store/join.js +38 -2
  34. package/dist/store/owner.d.ts +11 -0
  35. package/dist/store/owner.js +27 -7
  36. package/dist/store/types.d.ts +6 -0
  37. package/dist/stream.d.ts +29 -1
  38. package/dist/stream.js +66 -4
  39. package/dist/udp-probe.d.ts +21 -3
  40. package/dist/udp-probe.js +78 -7
  41. package/dist/world/link.d.ts +9 -0
  42. package/dist/world/link.js +4 -3
  43. package/dist/world/regions.d.ts +9 -2
  44. package/dist/world/regions.js +34 -4
  45. package/package.json +3 -2
@@ -57,7 +57,10 @@ export interface SessionOptions extends ConnectOptions {
57
57
  dbName?: string;
58
58
  /**
59
59
  * Override the Web Lock and `BroadcastChannel` name. Defaults to
60
- * `net-mesh/<origin>/<identity-fingerprint>`.
60
+ * `net-mesh/<origin>/<identity-fingerprint>`, or — with a custodial
61
+ * `entitySecretHex` — to the identity lock `connect()` takes for that
62
+ * secret, so a `connect()` tab and an `openSession()` tab cannot both run
63
+ * the identity. Setting it opts out of that contention.
61
64
  *
62
65
  * For tests that need two independent elections inside one origin.
63
66
  * A page should not set it: two scopes on one identity is two nodes
@@ -65,7 +68,6 @@ export interface SessionOptions extends ConnectOptions {
65
68
  */
66
69
  lockScope?: string;
67
70
  }
68
- /** The origin's Net node, as this tab sees it. */
69
71
  export declare class MeshSession {
70
72
  private readonly inner;
71
73
  /**
@@ -28,7 +28,7 @@
28
28
  */
29
29
  import { fromWasmError, OrgCancelledError, OrgLeaderLostError, } from '../errors.js';
30
30
  import { clientStreamOrgTrampoline, duplexOrgTrampoline, OrgDuplex, OrgHandleRegistry, OrgServe, OrgStream, OrgUpload, streamingOrgTrampoline, toWasmOrgCallOptions, toWasmOrgServeOptions, unaryOrgTrampoline, } from '../org.js';
31
- import { buildConnectRequest, parseAttemptStatus, parseCounters, parseDescriptors, } from '../node.js';
31
+ import { buildConnectRequest, identityLockName, parseAttemptStatus, parseCounters, parseDescriptors, } from '../node.js';
32
32
  import { acceptPeer as driveAccept, answerWaitingOffer, connectPeer as driveConnect, noteOffer, PeerAttempts, } from '../peer-driver.js';
33
33
  import { LeafStream } from '../stream.js';
34
34
  import { idArg, loadLeafWasm } from '../wasm.js';
@@ -36,6 +36,13 @@ import { isLifecycleEvent, parseSessionEvent, } from './events.js';
36
36
  import { asSessionModule } from './wasm.js';
37
37
  import { EventHub } from '../events.js';
38
38
  /** The origin's Net node, as this tab sees it. */
39
+ /**
40
+ * What a send on a stream ended by a leader change fails with. Worded
41
+ * the way the leaf words a stale handle, because `isStaleStream` (the
42
+ * store's reopen test) matches exactly that: a store over a session
43
+ * reopens on the new leader rather than counting `send-failed` forever.
44
+ */
45
+ const STALE_AFTER_HANDOFF = 'stale stream handle: the leader changed; reopen the stream';
39
46
  export class MeshSession {
40
47
  inner;
41
48
  /**
@@ -100,7 +107,7 @@ export class MeshSession {
100
107
  // The generation that owned the calls is the one they were
101
108
  // issued under — typed `LeaderLost`, never resumed.
102
109
  this.orgHandles.retireAll(new OrgLeaderLostError(this.streamGeneration));
103
- this.endStreams();
110
+ this.endStreams(STALE_AFTER_HANDOFF);
104
111
  return;
105
112
  }
106
113
  // And the abrupt case: a generation that moved under us. Read
@@ -114,7 +121,7 @@ export class MeshSession {
114
121
  const previous = this.streamGeneration;
115
122
  this.streamGeneration = current;
116
123
  this.orgHandles.retireAll(new OrgLeaderLostError(previous));
117
- this.endStreams();
124
+ this.endStreams(STALE_AFTER_HANDOFF);
118
125
  });
119
126
  }
120
127
  /** `'leader'` if this tab runs the node, `'follower'` if another does. */
@@ -725,11 +732,17 @@ export class MeshSession {
725
732
  * on close; idempotent, because a page may have closed a stream
726
733
  * itself.
727
734
  */
728
- endStreams() {
735
+ endStreams(staleReason) {
729
736
  const open = [...this.streams];
730
737
  this.streams.clear();
731
- for (const stream of open)
732
- stream.close();
738
+ for (const stream of open) {
739
+ // A leader change retires with the reopenable wording; closing the
740
+ // session is permanent.
741
+ if (staleReason === undefined)
742
+ stream.close();
743
+ else
744
+ stream.retire(staleReason);
745
+ }
733
746
  }
734
747
  /**
735
748
  * Re-type whatever the boundary threw.
@@ -777,6 +790,17 @@ export async function openSession(options) {
777
790
  ...(options.dbName === undefined ? {} : { dbName: options.dbName }),
778
791
  ...(options.lockScope === undefined ? {} : { lockScope: options.lockScope }),
779
792
  };
793
+ // A custodial identity elects under the same lock name `connect()` takes
794
+ // for it, so mixed connect()/openSession() tabs with one secret cannot
795
+ // both run a node (cubic review of PR #1228). The scope also names the
796
+ // `BroadcastChannel`, and every session tab with that secret derives the
797
+ // same name, so the leader and its followers still meet.
798
+ // `lockIdentity: false` keeps the leaf's own default scope.
799
+ if (request.lockScope === undefined && request.entitySecretHex !== undefined && options.lockIdentity !== false) {
800
+ const shared = await identityLockName(request.entitySecretHex);
801
+ if (shared !== null)
802
+ request.lockScope = shared;
803
+ }
780
804
  try {
781
805
  return new MeshSession(await module.MeshSession.open(request));
782
806
  }
package/dist/lobby.d.ts CHANGED
@@ -89,8 +89,33 @@ export declare const MAX_LOBBY_CAPACITY = 256;
89
89
  /** Characters a code is made of: no 0/O, 1/I/L, so a code survives being read aloud. */
90
90
  export declare const LOBBY_CODE_ALPHABET = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
91
91
  export declare const LOBBY_CODE_LENGTH = 6;
92
- /** How often a lobby re-announces itself. */
93
- export declare const LOBBY_ANNOUNCE_MS = 2000;
92
+ /**
93
+ * How often a lobby (and a joiner's seek tag) refreshes its announcement.
94
+ * A change of players is announced at once; this is only the lease
95
+ * refresh, well inside the leaf's 300 s announcement TTL.
96
+ *
97
+ * It was 2 s. Every node's re-announcement is flooded through the anchor
98
+ * to every peer, each of which answers every packet with a credit grant,
99
+ * so the load grows with the square of the players: at 64 players on one
100
+ * anchor (sharded-match plan, S0b) a 2 s refresh pinned the host's anchor
101
+ * link at its SCTP advisory (84,667 refused sends), starving every
102
+ * relayed pair and timing out handshakes. At 30 s the same run joined all
103
+ * 64, every pair direct, with no refusals.
104
+ *
105
+ * A node that connects later does not wait for this refresh: the anchor
106
+ * replays the announcements it holds to each session that enrolls, within
107
+ * its game, so an existing lobby is listed at once.
108
+ *
109
+ * A FAILED announcement is not left to this cadence: it is retried after
110
+ * {@link ANNOUNCE_RETRY_MS}, doubling up to {@link ANNOUNCE_RETRY_MAX_MS},
111
+ * until one succeeds. A joiner gives up after 20 s, and a lobby whose
112
+ * first announcement failed must not stay unfindable for 30.
113
+ */
114
+ export declare const LOBBY_ANNOUNCE_MS = 30000;
115
+ /** The first retry after a failed announcement, ms (lobbies, seek tags, region hosts). */
116
+ export declare const ANNOUNCE_RETRY_MS = 1000;
117
+ /** The longest wait between retries of a failing announcement, ms. */
118
+ export declare const ANNOUNCE_RETRY_MAX_MS = 8000;
94
119
  /** A code as typed: case, spaces and dashes forgiven. */
95
120
  export declare function normalizeLobbyCode(code: string): string;
96
121
  /** What `createLobby` takes: a store's host options, minus the transport, plus the lobby. */
@@ -173,6 +198,8 @@ export interface JoinLobbyOptions<S extends object, A extends ActionSpec, I exte
173
198
  * announces goes here. The same option as `createLobby`'s.
174
199
  */
175
200
  readonly tags?: readonly string[];
201
+ /** How often the seek tag is refreshed while joined. Default {@link LOBBY_ANNOUNCE_MS}. */
202
+ readonly announceEveryMs?: number;
176
203
  }
177
204
  /**
178
205
  * Join a lobby by code or by listing. Resolves once the host is found
package/dist/lobby.js CHANGED
@@ -46,7 +46,7 @@
46
46
  * tags the node should keep announcing as `tags`.
47
47
  */
48
48
  import { StoreError } from './store/errors.js';
49
- import { hostInternals, hostStore, } from './store/host.js';
49
+ import { hostInternals, hostStore, nodeHexOf, } from './store/host.js';
50
50
  import { joinStore } from './store/join.js';
51
51
  import { hostPlayer } from './store/player.js';
52
52
  export class LobbyError extends Error {
@@ -65,8 +65,33 @@ export const MAX_LOBBY_CAPACITY = 256;
65
65
  /** Characters a code is made of: no 0/O, 1/I/L, so a code survives being read aloud. */
66
66
  export const LOBBY_CODE_ALPHABET = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789';
67
67
  export const LOBBY_CODE_LENGTH = 6;
68
- /** How often a lobby re-announces itself. */
69
- export const LOBBY_ANNOUNCE_MS = 2_000;
68
+ /**
69
+ * How often a lobby (and a joiner's seek tag) refreshes its announcement.
70
+ * A change of players is announced at once; this is only the lease
71
+ * refresh, well inside the leaf's 300 s announcement TTL.
72
+ *
73
+ * It was 2 s. Every node's re-announcement is flooded through the anchor
74
+ * to every peer, each of which answers every packet with a credit grant,
75
+ * so the load grows with the square of the players: at 64 players on one
76
+ * anchor (sharded-match plan, S0b) a 2 s refresh pinned the host's anchor
77
+ * link at its SCTP advisory (84,667 refused sends), starving every
78
+ * relayed pair and timing out handshakes. At 30 s the same run joined all
79
+ * 64, every pair direct, with no refusals.
80
+ *
81
+ * A node that connects later does not wait for this refresh: the anchor
82
+ * replays the announcements it holds to each session that enrolls, within
83
+ * its game, so an existing lobby is listed at once.
84
+ *
85
+ * A FAILED announcement is not left to this cadence: it is retried after
86
+ * {@link ANNOUNCE_RETRY_MS}, doubling up to {@link ANNOUNCE_RETRY_MAX_MS},
87
+ * until one succeeds. A joiner gives up after 20 s, and a lobby whose
88
+ * first announcement failed must not stay unfindable for 30.
89
+ */
90
+ export const LOBBY_ANNOUNCE_MS = 30_000;
91
+ /** The first retry after a failed announcement, ms (lobbies, seek tags, region hosts). */
92
+ export const ANNOUNCE_RETRY_MS = 1_000;
93
+ /** The longest wait between retries of a failing announcement, ms. */
94
+ export const ANNOUNCE_RETRY_MAX_MS = 8_000;
70
95
  /** The frame bound the package's own tests and demo use. */
71
96
  const DEFAULT_MAX_EVENT_BYTES = 8104;
72
97
  const GAME = /^[a-z0-9][a-z0-9._-]{0,63}$/;
@@ -215,10 +240,14 @@ function decodeRecord(game, tag) {
215
240
  return null;
216
241
  }
217
242
  }
243
+ // Read the id the way every other caller-held id is read (`nodeHexOf`):
244
+ // sixteen hex digits are hex, and anything shorter may be the exact-decimal
245
+ // `peerNode` an event handed the page. Reading every digit run as hex kicked
246
+ // a DIFFERENT id and removed nobody (SDK audit 2026-10-11).
218
247
  function hexPeer(peer) {
219
- const raw = peer.startsWith('0x') ? peer.slice(2) : peer;
220
- if (/^[0-9a-fA-F]{1,16}$/.test(raw))
221
- return raw.toLowerCase().padStart(16, '0');
248
+ const hex = nodeHexOf(peer);
249
+ if (hex !== null)
250
+ return hex;
222
251
  throw new LobbyError('invalid', `not a peer id: ${JSON.stringify(peer)}`);
223
252
  }
224
253
  /**
@@ -279,6 +308,10 @@ export async function createLobby(options) {
279
308
  let closed = false;
280
309
  let announcing = null;
281
310
  let again = false;
311
+ // A failed announcement is retried on its own short backoff, not at the
312
+ // next lease refresh.
313
+ let retry = null;
314
+ let retryMs = ANNOUNCE_RETRY_MS;
282
315
  function currentTags() {
283
316
  const list = [...(tags ?? []), lookup];
284
317
  if (visibility === 'public') {
@@ -294,11 +327,25 @@ export async function createLobby(options) {
294
327
  again = true;
295
328
  return;
296
329
  }
330
+ if (retry !== null) {
331
+ clearTimeout(retry);
332
+ retry = null;
333
+ }
297
334
  announcing = node
298
335
  .announce(currentTags())
336
+ .then(() => {
337
+ retryMs = ANNOUNCE_RETRY_MS;
338
+ })
299
339
  .catch(() => {
300
- // The next tick tries again; a lobby that cannot announce is
301
- // simply not found, which the joiner reports as `not-found`.
340
+ // Retried shortly; until one lands the lobby is simply not found,
341
+ // which a joiner reports as `not-found`.
342
+ if (closed || retry !== null)
343
+ return;
344
+ retry = setTimeout(() => {
345
+ retry = null;
346
+ announce();
347
+ }, retryMs);
348
+ retryMs = Math.min(retryMs * 2, ANNOUNCE_RETRY_MAX_MS);
302
349
  })
303
350
  .finally(() => {
304
351
  announcing = null;
@@ -362,6 +409,8 @@ export async function createLobby(options) {
362
409
  return;
363
410
  closed = true;
364
411
  clearInterval(timer);
412
+ if (retry !== null)
413
+ clearTimeout(retry);
365
414
  stopMembership();
366
415
  listeners.clear();
367
416
  await me.close();
@@ -440,15 +489,34 @@ export async function joinLobby(options) {
440
489
  // them, or one landing after it would put the seek tag back — over a
441
490
  // lobby this node created meanwhile.
442
491
  const seekingInFlight = new Set();
492
+ // A failed seek announcement is retried on a short backoff: the host
493
+ // cannot let this player in until it holds one, and the reach below
494
+ // gives up at `timeoutMs` — long before the next lease refresh.
495
+ let retry = null;
496
+ let retryMs = ANNOUNCE_RETRY_MS;
443
497
  const announce = () => {
444
498
  if (stopped !== null)
445
499
  return;
446
- const sent = node.announce(seeking).catch(() => { });
500
+ if (retry !== null) {
501
+ clearTimeout(retry);
502
+ retry = null;
503
+ }
504
+ const sent = node.announce(seeking).then(() => {
505
+ retryMs = ANNOUNCE_RETRY_MS;
506
+ }, () => {
507
+ if (stopped !== null || retry !== null)
508
+ return;
509
+ retry = setTimeout(() => {
510
+ retry = null;
511
+ announce();
512
+ }, retryMs);
513
+ retryMs = Math.min(retryMs * 2, ANNOUNCE_RETRY_MAX_MS);
514
+ });
447
515
  seekingInFlight.add(sent);
448
516
  void sent.finally(() => seekingInFlight.delete(sent));
449
517
  };
450
518
  announce();
451
- const timer = setInterval(announce, LOBBY_ANNOUNCE_MS);
519
+ const timer = setInterval(announce, options.announceEveryMs ?? LOBBY_ANNOUNCE_MS);
452
520
  // Withdraws the seek tag, after any seeking announcement still in
453
521
  // flight. Settles once the withdrawal has been attempted (a failure is
454
522
  // swallowed, as every announcement here is), so a `close()` that awaits
@@ -459,6 +527,8 @@ export async function joinLobby(options) {
459
527
  if (stopped !== null)
460
528
  return stopped;
461
529
  clearInterval(timer);
530
+ if (retry !== null)
531
+ clearTimeout(retry);
462
532
  stopped = Promise.all(seekingInFlight).then(() => node.announce(keep)).catch(() => { });
463
533
  return stopped;
464
534
  };
@@ -487,7 +487,7 @@ export class LeafNode {
487
487
  * The re-attempt owner's ledger, as JSON.
488
488
  *
489
489
  * `{"armed":<bool>,"online":"<n>","iceFailed":"<n>",
490
- * "triggers":"<n>","started":"<n>","coalesced":"<n>",
490
+ * "channelClosed":"<n>","triggers":"<n>","started":"<n>","coalesced":"<n>",
491
491
  * "notEligible":"<n>","openEpisodes":<n>,"owned":<n>,
492
492
  * "last":"<disposition>"|null}`.
493
493
  *
@@ -623,11 +623,10 @@ export class LeafStream {
623
623
  * **Every registration this stream took is given back**, so
624
624
  * repeated open/close leaves [`LeafNode::listener_count`] flat.
625
625
  * A callback registered through [`Self::on_message`] lives on
626
- * the node, not on this object, and it captures the consumer's
627
- * own callback — so a close that removed only the node's stream
628
- * state left the closure attached, still invoked for every
629
- * event the node produced and still holding its consumer
630
- * alive, for as long as the node lived.
626
+ * the node, not on this object — so a close that removed only
627
+ * the node's stream state left it attached, still invoked and
628
+ * still holding its consumer alive, for as long as the node
629
+ * lived.
631
630
  *
632
631
  * A refusal here is reported rather than returned: the handle is
633
632
  * being discarded either way, and `close` is the one operation
@@ -675,7 +674,7 @@ export class LeafStream {
675
674
  * comes from a label or from a publish contract and neither
676
675
  * involves the peer, so one label opened to two peers is one id
677
676
  * on two sessions — a supported composition. Filtering the
678
- * node-wide event stream by the id alone made both wrappers
677
+ * node's events by the id alone made both wrappers
679
678
  * accept whichever peer's payload arrived, delivering one
680
679
  * peer's bytes into the other peer's inbox; a page that echoes
681
680
  * then amplifies it. The incarnation rides the event as
@@ -689,10 +688,9 @@ export class LeafStream {
689
688
  * self` — so the advertised echo trapped instead of sending.
690
689
  *
691
690
  * **Returns the token that cancels the registration**, decimal.
692
- * The closure is registered on the node and captures the
693
- * consumer's callback, so a registration nothing names is
694
- * retained for the node's whole life and keeps being invoked
695
- * for every event it produces — which is what repeated
691
+ * The callback is registered on the node, so a registration
692
+ * nothing names is retained for the node's whole life and keeps
693
+ * being invoked for its stream's data — which is what repeated
696
694
  * open/close accumulated before the token existed.
697
695
  * [`Self::close`] gives back every token this stream took, so
698
696
  * an ordinary consumer never has to; [`Self::remove_listener`]
@@ -1453,16 +1451,16 @@ export interface InitOutput {
1453
1451
  readonly proxystream_send: (a: number, b: number) => number;
1454
1452
  readonly proxystream_stream_id_hex: (a: number, b: number) => void;
1455
1453
  readonly start: () => void;
1456
- readonly __wasm_bindgen_func_elem_6504: (a: number, b: number, c: number, d: number) => void;
1457
- readonly __wasm_bindgen_func_elem_6506: (a: number, b: number, c: number, d: number) => void;
1458
- readonly __wasm_bindgen_func_elem_2365: (a: number, b: number, c: number) => number;
1459
- readonly __wasm_bindgen_func_elem_2366: (a: number, b: number, c: number) => void;
1460
- readonly __wasm_bindgen_func_elem_2366_112: (a: number, b: number, c: number) => void;
1461
- readonly __wasm_bindgen_func_elem_2366_113: (a: number, b: number, c: number) => void;
1462
- readonly __wasm_bindgen_func_elem_2366_114: (a: number, b: number, c: number) => void;
1463
- readonly __wasm_bindgen_func_elem_2366_115: (a: number, b: number, c: number) => void;
1464
- readonly __wasm_bindgen_func_elem_2366_116: (a: number, b: number, c: number) => void;
1465
- readonly __wasm_bindgen_func_elem_2366_117: (a: number, b: number, c: number) => void;
1454
+ readonly __wasm_bindgen_func_elem_6529: (a: number, b: number, c: number, d: number) => void;
1455
+ readonly __wasm_bindgen_func_elem_6531: (a: number, b: number, c: number, d: number) => void;
1456
+ readonly __wasm_bindgen_func_elem_2373: (a: number, b: number, c: number) => number;
1457
+ readonly __wasm_bindgen_func_elem_2374: (a: number, b: number, c: number) => void;
1458
+ readonly __wasm_bindgen_func_elem_2374_112: (a: number, b: number, c: number) => void;
1459
+ readonly __wasm_bindgen_func_elem_2374_113: (a: number, b: number, c: number) => void;
1460
+ readonly __wasm_bindgen_func_elem_2374_114: (a: number, b: number, c: number) => void;
1461
+ readonly __wasm_bindgen_func_elem_2374_115: (a: number, b: number, c: number) => void;
1462
+ readonly __wasm_bindgen_func_elem_2374_116: (a: number, b: number, c: number) => void;
1463
+ readonly __wasm_bindgen_func_elem_2374_117: (a: number, b: number, c: number) => void;
1466
1464
  readonly __wbindgen_export: (a: number, b: number) => number;
1467
1465
  readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
1468
1466
  readonly __wbindgen_export3: (a: number) => void;
package/dist/net_leaf.js CHANGED
@@ -848,7 +848,7 @@ export class LeafNode {
848
848
  * The re-attempt owner's ledger, as JSON.
849
849
  *
850
850
  * `{"armed":<bool>,"online":"<n>","iceFailed":"<n>",
851
- * "triggers":"<n>","started":"<n>","coalesced":"<n>",
851
+ * "channelClosed":"<n>","triggers":"<n>","started":"<n>","coalesced":"<n>",
852
852
  * "notEligible":"<n>","openEpisodes":<n>,"owned":<n>,
853
853
  * "last":"<disposition>"|null}`.
854
854
  *
@@ -1150,11 +1150,10 @@ export class LeafStream {
1150
1150
  * **Every registration this stream took is given back**, so
1151
1151
  * repeated open/close leaves [`LeafNode::listener_count`] flat.
1152
1152
  * A callback registered through [`Self::on_message`] lives on
1153
- * the node, not on this object, and it captures the consumer's
1154
- * own callback — so a close that removed only the node's stream
1155
- * state left the closure attached, still invoked for every
1156
- * event the node produced and still holding its consumer
1157
- * alive, for as long as the node lived.
1153
+ * the node, not on this object — so a close that removed only
1154
+ * the node's stream state left it attached, still invoked and
1155
+ * still holding its consumer alive, for as long as the node
1156
+ * lived.
1158
1157
  *
1159
1158
  * A refusal here is reported rather than returned: the handle is
1160
1159
  * being discarded either way, and `close` is the one operation
@@ -1224,7 +1223,7 @@ export class LeafStream {
1224
1223
  * comes from a label or from a publish contract and neither
1225
1224
  * involves the peer, so one label opened to two peers is one id
1226
1225
  * on two sessions — a supported composition. Filtering the
1227
- * node-wide event stream by the id alone made both wrappers
1226
+ * node's events by the id alone made both wrappers
1228
1227
  * accept whichever peer's payload arrived, delivering one
1229
1228
  * peer's bytes into the other peer's inbox; a page that echoes
1230
1229
  * then amplifies it. The incarnation rides the event as
@@ -1238,10 +1237,9 @@ export class LeafStream {
1238
1237
  * self` — so the advertised echo trapped instead of sending.
1239
1238
  *
1240
1239
  * **Returns the token that cancels the registration**, decimal.
1241
- * The closure is registered on the node and captures the
1242
- * consumer's callback, so a registration nothing names is
1243
- * retained for the node's whole life and keeps being invoked
1244
- * for every event it produces — which is what repeated
1240
+ * The callback is registered on the node, so a registration
1241
+ * nothing names is retained for the node's whole life and keeps
1242
+ * being invoked for its stream's data — which is what repeated
1245
1243
  * open/close accumulated before the token existed.
1246
1244
  * [`Self::close`] gives back every token this stream took, so
1247
1245
  * an ordinary consumer never has to; [`Self::remove_listener`]
@@ -2722,7 +2720,7 @@ function __wbg_get_imports() {
2722
2720
  const ret = getObject(arg0).error;
2723
2721
  return isLikeNone(ret) ? 0 : addHeapObject(ret);
2724
2722
  }, arguments); },
2725
- __wbg_error_917fe43c4c53b37c: function(arg0, arg1) {
2723
+ __wbg_error_def25afd803510fb: function(arg0, arg1) {
2726
2724
  console.error(getStringFromWasm0(arg0, arg1));
2727
2725
  },
2728
2726
  __wbg_fetch_4178962c570137ca: function(arg0, arg1, arg2) {
@@ -2914,7 +2912,7 @@ function __wbg_get_imports() {
2914
2912
  const a = state0.a;
2915
2913
  state0.a = 0;
2916
2914
  try {
2917
- return __wasm_bindgen_func_elem_6506(a, state0.b, arg0, arg1);
2915
+ return __wasm_bindgen_func_elem_6531(a, state0.b, arg0, arg1);
2918
2916
  } finally {
2919
2917
  state0.a = a;
2920
2918
  }
@@ -2956,7 +2954,7 @@ function __wbg_get_imports() {
2956
2954
  const a = state0.a;
2957
2955
  state0.a = 0;
2958
2956
  try {
2959
- return __wasm_bindgen_func_elem_6506(a, state0.b, arg0, arg1);
2957
+ return __wasm_bindgen_func_elem_6531(a, state0.b, arg0, arg1);
2960
2958
  } finally {
2961
2959
  state0.a = a;
2962
2960
  }
@@ -3266,47 +3264,47 @@ function __wbg_get_imports() {
3266
3264
  },
3267
3265
  __wbindgen_generic_0000000000000001: function(arg0, arg1) {
3268
3266
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 34, ret: Externref, inner_ret: Some(Externref) }, mutable: true }) -> Externref`.
3269
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2365);
3267
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2373);
3270
3268
  return addHeapObject(ret);
3271
3269
  },
3272
3270
  __wbindgen_generic_0000000000000002: function(arg0, arg1) {
3273
3271
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3274
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366);
3272
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374);
3275
3273
  return addHeapObject(ret);
3276
3274
  },
3277
3275
  __wbindgen_generic_0000000000000003: function(arg0, arg1) {
3278
- // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 868, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
3279
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6504);
3276
+ // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 866, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
3277
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_6529);
3280
3278
  return addHeapObject(ret);
3281
3279
  },
3282
3280
  __wbindgen_generic_0000000000000004: function(arg0, arg1) {
3283
3281
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("CloseEvent")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3284
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_112);
3282
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_112);
3285
3283
  return addHeapObject(ret);
3286
3284
  },
3287
3285
  __wbindgen_generic_0000000000000005: function(arg0, arg1) {
3288
3286
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("Event")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3289
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_113);
3287
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_113);
3290
3288
  return addHeapObject(ret);
3291
3289
  },
3292
3290
  __wbindgen_generic_0000000000000006: function(arg0, arg1) {
3293
3291
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("MessageEvent")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3294
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_114);
3292
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_114);
3295
3293
  return addHeapObject(ret);
3296
3294
  },
3297
3295
  __wbindgen_generic_0000000000000007: function(arg0, arg1) {
3298
3296
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("RTCDataChannelEvent")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3299
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_115);
3297
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_115);
3300
3298
  return addHeapObject(ret);
3301
3299
  },
3302
3300
  __wbindgen_generic_0000000000000008: function(arg0, arg1) {
3303
3301
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("RTCPeerConnectionIceErrorEvent")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3304
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_116);
3302
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_116);
3305
3303
  return addHeapObject(ret);
3306
3304
  },
3307
3305
  __wbindgen_generic_0000000000000009: function(arg0, arg1) {
3308
3306
  // Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [NamedExternref("RTCPeerConnectionIceEvent")], shim_idx: 35, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
3309
- const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2366_117);
3307
+ const ret = makeMutClosure(arg0, arg1, __wasm_bindgen_func_elem_2374_117);
3310
3308
  return addHeapObject(ret);
3311
3309
  },
3312
3310
  __wbindgen_generic_000000000000000a: function(arg0) {
@@ -3333,47 +3331,47 @@ function __wbg_get_imports() {
3333
3331
  };
3334
3332
  }
3335
3333
 
3336
- function __wasm_bindgen_func_elem_2366(arg0, arg1, arg2) {
3337
- wasm.__wasm_bindgen_func_elem_2366(arg0, arg1, addHeapObject(arg2));
3334
+ function __wasm_bindgen_func_elem_2374(arg0, arg1, arg2) {
3335
+ wasm.__wasm_bindgen_func_elem_2374(arg0, arg1, addHeapObject(arg2));
3338
3336
  }
3339
3337
 
3340
- function __wasm_bindgen_func_elem_2366_112(arg0, arg1, arg2) {
3341
- wasm.__wasm_bindgen_func_elem_2366_112(arg0, arg1, addHeapObject(arg2));
3338
+ function __wasm_bindgen_func_elem_2374_112(arg0, arg1, arg2) {
3339
+ wasm.__wasm_bindgen_func_elem_2374_112(arg0, arg1, addHeapObject(arg2));
3342
3340
  }
3343
3341
 
3344
- function __wasm_bindgen_func_elem_2366_113(arg0, arg1, arg2) {
3345
- wasm.__wasm_bindgen_func_elem_2366_113(arg0, arg1, addHeapObject(arg2));
3342
+ function __wasm_bindgen_func_elem_2374_113(arg0, arg1, arg2) {
3343
+ wasm.__wasm_bindgen_func_elem_2374_113(arg0, arg1, addHeapObject(arg2));
3346
3344
  }
3347
3345
 
3348
- function __wasm_bindgen_func_elem_2366_114(arg0, arg1, arg2) {
3349
- wasm.__wasm_bindgen_func_elem_2366_114(arg0, arg1, addHeapObject(arg2));
3346
+ function __wasm_bindgen_func_elem_2374_114(arg0, arg1, arg2) {
3347
+ wasm.__wasm_bindgen_func_elem_2374_114(arg0, arg1, addHeapObject(arg2));
3350
3348
  }
3351
3349
 
3352
- function __wasm_bindgen_func_elem_2366_115(arg0, arg1, arg2) {
3353
- wasm.__wasm_bindgen_func_elem_2366_115(arg0, arg1, addHeapObject(arg2));
3350
+ function __wasm_bindgen_func_elem_2374_115(arg0, arg1, arg2) {
3351
+ wasm.__wasm_bindgen_func_elem_2374_115(arg0, arg1, addHeapObject(arg2));
3354
3352
  }
3355
3353
 
3356
- function __wasm_bindgen_func_elem_2366_116(arg0, arg1, arg2) {
3357
- wasm.__wasm_bindgen_func_elem_2366_116(arg0, arg1, addHeapObject(arg2));
3354
+ function __wasm_bindgen_func_elem_2374_116(arg0, arg1, arg2) {
3355
+ wasm.__wasm_bindgen_func_elem_2374_116(arg0, arg1, addHeapObject(arg2));
3358
3356
  }
3359
3357
 
3360
- function __wasm_bindgen_func_elem_2366_117(arg0, arg1, arg2) {
3361
- wasm.__wasm_bindgen_func_elem_2366_117(arg0, arg1, addHeapObject(arg2));
3358
+ function __wasm_bindgen_func_elem_2374_117(arg0, arg1, arg2) {
3359
+ wasm.__wasm_bindgen_func_elem_2374_117(arg0, arg1, addHeapObject(arg2));
3362
3360
  }
3363
3361
 
3364
- function __wasm_bindgen_func_elem_2365(arg0, arg1, arg2) {
3365
- const ret = wasm.__wasm_bindgen_func_elem_2365(arg0, arg1, addHeapObject(arg2));
3362
+ function __wasm_bindgen_func_elem_2373(arg0, arg1, arg2) {
3363
+ const ret = wasm.__wasm_bindgen_func_elem_2373(arg0, arg1, addHeapObject(arg2));
3366
3364
  return takeObject(ret);
3367
3365
  }
3368
3366
 
3369
- function __wasm_bindgen_func_elem_6506(arg0, arg1, arg2, arg3) {
3370
- wasm.__wasm_bindgen_func_elem_6506(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
3367
+ function __wasm_bindgen_func_elem_6531(arg0, arg1, arg2, arg3) {
3368
+ wasm.__wasm_bindgen_func_elem_6531(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
3371
3369
  }
3372
3370
 
3373
- function __wasm_bindgen_func_elem_6504(arg0, arg1, arg2) {
3371
+ function __wasm_bindgen_func_elem_6529(arg0, arg1, arg2) {
3374
3372
  try {
3375
3373
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
3376
- wasm.__wasm_bindgen_func_elem_6504(retptr, arg0, arg1, addHeapObject(arg2));
3374
+ wasm.__wasm_bindgen_func_elem_6529(retptr, arg0, arg1, addHeapObject(arg2));
3377
3375
  var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
3378
3376
  var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
3379
3377
  if (r1) {
Binary file
@@ -119,16 +119,16 @@ export const proxystream_peer_node_hex: (a: number, b: number) => void;
119
119
  export const proxystream_send: (a: number, b: number) => number;
120
120
  export const proxystream_stream_id_hex: (a: number, b: number) => void;
121
121
  export const start: () => void;
122
- export const __wasm_bindgen_func_elem_6504: (a: number, b: number, c: number, d: number) => void;
123
- export const __wasm_bindgen_func_elem_6506: (a: number, b: number, c: number, d: number) => void;
124
- export const __wasm_bindgen_func_elem_2365: (a: number, b: number, c: number) => number;
125
- export const __wasm_bindgen_func_elem_2366: (a: number, b: number, c: number) => void;
126
- export const __wasm_bindgen_func_elem_2366_112: (a: number, b: number, c: number) => void;
127
- export const __wasm_bindgen_func_elem_2366_113: (a: number, b: number, c: number) => void;
128
- export const __wasm_bindgen_func_elem_2366_114: (a: number, b: number, c: number) => void;
129
- export const __wasm_bindgen_func_elem_2366_115: (a: number, b: number, c: number) => void;
130
- export const __wasm_bindgen_func_elem_2366_116: (a: number, b: number, c: number) => void;
131
- export const __wasm_bindgen_func_elem_2366_117: (a: number, b: number, c: number) => void;
122
+ export const __wasm_bindgen_func_elem_6529: (a: number, b: number, c: number, d: number) => void;
123
+ export const __wasm_bindgen_func_elem_6531: (a: number, b: number, c: number, d: number) => void;
124
+ export const __wasm_bindgen_func_elem_2373: (a: number, b: number, c: number) => number;
125
+ export const __wasm_bindgen_func_elem_2374: (a: number, b: number, c: number) => void;
126
+ export const __wasm_bindgen_func_elem_2374_112: (a: number, b: number, c: number) => void;
127
+ export const __wasm_bindgen_func_elem_2374_113: (a: number, b: number, c: number) => void;
128
+ export const __wasm_bindgen_func_elem_2374_114: (a: number, b: number, c: number) => void;
129
+ export const __wasm_bindgen_func_elem_2374_115: (a: number, b: number, c: number) => void;
130
+ export const __wasm_bindgen_func_elem_2374_116: (a: number, b: number, c: number) => void;
131
+ export const __wasm_bindgen_func_elem_2374_117: (a: number, b: number, c: number) => void;
132
132
  export const __wbindgen_export: (a: number, b: number) => number;
133
133
  export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
134
134
  export const __wbindgen_export3: (a: number) => void;