@markless/router 0.8.0 → 0.10.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.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { d as REPLACE_ATTRIBUTE, f as SCROLL_ATTRIBUTE, i as HTML_ATTRIBUTES_SLOT, l as LINK_ATTRIBUTE, s as routeMountTarget, t as rememberRequestLocals, u as PREFETCH_ATTRIBUTE } from "./request-locals-BDAhNpEa.js";
1
+ import { f as LINK_ATTRIBUTE, h as SCROLL_ATTRIBUTE, m as REPLACE_ATTRIBUTE, o as HTML_ATTRIBUTES_SLOT, p as PREFETCH_ATTRIBUTE, r as rememberRequestLocals, t as MARKLESS_NAV_PENDING_MIN_MS, u as routeMountTarget } from "./navigation-timing-CzH6VaBR.js";
2
2
  import { a as normalizeRequestPathname, c as parseRequestFile, i as matchRouteManifest, l as transformRequestFileSource, n as buildRouteManifestFromFileIds, o as normalizeRouteFileId, s as normalizeRequestFileId } from "./route-manifest-DmoxXanW.js";
3
3
  import { createExternalDelegateStructureTokens, createExternalDelegateView } from "@markless/web/fns/external-delegate";
4
4
  import { render } from "@markless/web/render";
5
- import { MARKLESS_PENDING_MIN_VISIBLE_MS as MARKLESS_NAV_PENDING_MIN_MS, settleOrPendingDeadline } from "@markless/web/fns/pending-timing";
5
+ import { settleOrPendingDeadline } from "@markless/web/fns/pending-timing";
6
6
  //#region src/route-state.ts
7
7
  const MARKLESS_ROUTER_ROUTE_EVENT = "marklessrouternavigate";
8
8
  const MARKLESS_ROUTER_RENDERED_EVENT = "marklessrouterrendered";
@@ -1,4 +1,5 @@
1
1
  import { CONTAINER_ATTRIBUTE, PROTOCOL_CONTAINER_END_COMMENT, PROTOCOL_CONTAINER_START_COMMENT, PROTOCOL_LOCATOR_PATHS_ATTRIBUTE } from "@markless/web/fns/container-region";
2
+ import { MARKLESS_PENDING_MIN_VISIBLE_MS as MARKLESS_NAV_PENDING_MIN_MS, MARKLESS_PENDING_SETTLE_DEADLINE_MS as MARKLESS_NAV_SETTLE_DEADLINE_MS } from "@markless/web/fns/pending-timing";
2
3
  //#region src/link-attributes.ts
3
4
  const LINK_ATTRIBUTE = "data-markless-router-link";
4
5
  const REPLACE_ATTRIBUTE = "data-markless-router-replace";
@@ -9,8 +10,9 @@ const PREFETCH_ATTRIBUTE = "data-markless-router-prefetch";
9
10
  const ROUTE_SCRIPT_TYPE = "@markless/core/route";
10
11
  const HTML_ATTRIBUTES_SLOT = "__marklessRouterHtmlAttributes";
11
12
  const SERVED_HTML_ATTRIBUTES_PROPERTY = "__marklessServedHtmlAttributes";
13
+ const SERVED_BODY_ATTRIBUTES_PROPERTY = "__marklessServedBodyAttributes";
12
14
  function servedHtmlAttributesScript() {
13
- return `<script>document.documentElement.${SERVED_HTML_ATTRIBUTES_PROPERTY}=document.documentElement.getAttributeNames()<\/script>`;
15
+ return `<script>(()=>{const r=document.documentElement,p=(e)=>Array.from(e.attributes,(a)=>[a.name,a.value]),b=()=>!!document.body&&!!(r.${SERVED_BODY_ATTRIBUTES_PROPERTY}=p(document.body));r.${SERVED_HTML_ATTRIBUTES_PROPERTY}=p(r);b()||new MutationObserver((_,o)=>{b()&&o.disconnect()}).observe(r,{childList:true})})()<\/script>`;
14
16
  }
15
17
  function routeMountTarget(document, currentRoot) {
16
18
  const root = currentRoot ?? document.querySelector(`script[type="@markless/core/route"]`)?.parentElement;
@@ -91,4 +93,4 @@ function takeMiddlewareHeaders(request) {
91
93
  return record.taken;
92
94
  }
93
95
  //#endregion
94
- export { ROUTE_SCRIPT_TYPE as a, servedHtmlAttributesScript as c, REPLACE_ATTRIBUTE as d, SCROLL_ATTRIBUTE as f, HTML_ATTRIBUTES_SLOT as i, LINK_ATTRIBUTE as l, requestLocals as n, SERVED_HTML_ATTRIBUTES_PROPERTY as o, takeMiddlewareHeaders as r, routeMountTarget as s, rememberRequestLocals as t, PREFETCH_ATTRIBUTE as u };
96
+ export { takeMiddlewareHeaders as a, SERVED_BODY_ATTRIBUTES_PROPERTY as c, servedHtmlAttributesScript as d, LINK_ATTRIBUTE as f, SCROLL_ATTRIBUTE as h, requestLocals as i, SERVED_HTML_ATTRIBUTES_PROPERTY as l, REPLACE_ATTRIBUTE as m, MARKLESS_NAV_SETTLE_DEADLINE_MS as n, HTML_ATTRIBUTES_SLOT as o, PREFETCH_ATTRIBUTE as p, rememberRequestLocals as r, ROUTE_SCRIPT_TYPE as s, MARKLESS_NAV_PENDING_MIN_MS as t, routeMountTarget as u };
@@ -10,6 +10,7 @@ export interface ServerEntryOptions {
10
10
  readonly prerenderWakeEntryPath?: string;
11
11
  readonly routeModulePreloads?: Record<string, readonly ModulePreloadInput[]>;
12
12
  readonly routeSsrModulePreloads?: Record<string, readonly ModulePreloadInput[]>;
13
+ readonly routeResumeModules?: Readonly<Record<string, readonly string[]>>;
13
14
  readonly routeStylesheets?: Record<string, readonly string[]>;
14
15
  readonly documentStylesheets?: readonly string[];
15
16
  readonly importMap?: string;
@@ -1 +1 @@
1
- export { t as createServerEntry, n as routerLinkBridgeModules } from "../../create-server-entry-BsYTWdxi.js";
1
+ export { t as createServerEntry, n as routerLinkBridgeModules } from "../../create-server-entry-BnaEfDHl.js";
@@ -5,6 +5,80 @@ declare const ASYNC_BOUNDARY_ARM: {
5
5
  readonly catch: 2;
6
6
  };
7
7
  //#endregion
8
+ //#region ../serializer/src/value.d.ts
9
+ type SerializedPrimitive = null | string | number | boolean | {
10
+ readonly $type: 'undefined';
11
+ } | {
12
+ readonly $type: 'bigint';
13
+ readonly value: string;
14
+ } | {
15
+ readonly $type: 'number';
16
+ readonly value: NonFiniteNumberName;
17
+ };
18
+ /** JSON has no form for these, so a bare number slot would print as `null`. */
19
+ type NonFiniteNumberName = 'Infinity' | '-Infinity' | 'NaN';
20
+ type SerializedSlot = SerializedPrimitive | {
21
+ readonly $ref: number;
22
+ } | {
23
+ readonly $type: 'date';
24
+ readonly value: string;
25
+ } | {
26
+ readonly $type: 'regexp';
27
+ readonly source: string;
28
+ readonly flags: string;
29
+ } | {
30
+ readonly $type: 'url';
31
+ readonly value: string;
32
+ };
33
+ type SerializedRecord = {
34
+ readonly id: number;
35
+ readonly type: 'object';
36
+ readonly fields: ReadonlyArray<readonly [string, SerializedSlot]>;
37
+ } | {
38
+ readonly id: number;
39
+ readonly type: 'array';
40
+ readonly items: ReadonlyArray<SerializedSlot>;
41
+ } | {
42
+ readonly id: number;
43
+ readonly type: 'map';
44
+ readonly entries: ReadonlyArray<readonly [SerializedSlot, SerializedSlot]>;
45
+ } | {
46
+ readonly id: number;
47
+ readonly type: 'set';
48
+ readonly values: ReadonlyArray<SerializedSlot>;
49
+ } | {
50
+ readonly id: number;
51
+ readonly type: 'date';
52
+ readonly value: string;
53
+ } | {
54
+ readonly id: number;
55
+ readonly type: 'regexp';
56
+ readonly source: string;
57
+ readonly flags: string;
58
+ } | {
59
+ readonly id: number;
60
+ readonly type: 'url';
61
+ readonly value: string;
62
+ } | {
63
+ readonly id: number;
64
+ readonly type: 'array-buffer';
65
+ readonly bytes: ReadonlyArray<number>;
66
+ } | {
67
+ readonly id: number;
68
+ readonly type: 'typed-array';
69
+ readonly arrayType: TypedArrayName;
70
+ readonly buffer: SerializedSlot;
71
+ readonly byteOffset: number;
72
+ readonly length: number;
73
+ } | {
74
+ readonly id: number;
75
+ readonly type: 'data-view';
76
+ readonly buffer: SerializedSlot;
77
+ readonly byteOffset: number;
78
+ readonly byteLength: number;
79
+ };
80
+ type TypedArrayName = 'Int8Array' | 'Uint8Array' | 'Uint8ClampedArray' | 'Int16Array' | 'Uint16Array' | 'Int32Array' | 'Uint32Array' | 'Float32Array' | 'Float64Array' | 'BigInt64Array' | 'BigUint64Array';
81
+ //#endregion
8
82
  //#region ../serializer/src/protocol-constants.d.ts
9
83
  declare const ASYNC_PROTOCOL_VERSION = 1;
10
84
  declare const STORAGE_PROTOCOL_VERSION = 2;
@@ -15,6 +89,15 @@ declare const PROTOCOL_EVENT_ACTION_KIND: {
15
89
  //#endregion
16
90
  //#region ../serializer/src/protocol.d.ts
17
91
  type ProtocolAsyncBoundaryArm = (typeof ASYNC_BOUNDARY_ARM)[keyof typeof ASYNC_BOUNDARY_ARM];
92
+ /**
93
+ * Where an element sits below the node an address starts from, one step per
94
+ * level. A step counts the parent's element children, and each @if, @switch or
95
+ * @try block as one (its start comment, content and end comment together). Text
96
+ * never counts, since adjacent text merges and an empty value renders no node,
97
+ * so the server's HTML and a client-built tree read the same. A negative step
98
+ * counts back from the end: -1 is the last.
99
+ */
100
+ type ProtocolElementAddress = ReadonlyArray<number>;
18
101
  type ProtocolSyncPolicyCondition = {
19
102
  readonly type: 'and';
20
103
  readonly conditions: ReadonlyArray<ProtocolSyncPolicyCondition>;
@@ -28,6 +111,8 @@ type ProtocolSyncPolicyCondition = {
28
111
  readonly type: 'graph-truthy';
29
112
  readonly graphNodeId: string;
30
113
  readonly path?: ReadonlyArray<string>;
114
+ /** When present, the read must equal this value rather than be truthy. */
115
+ readonly equals?: string | number | boolean | null;
31
116
  } | {
32
117
  readonly type: 'constant-truthy';
33
118
  readonly value: unknown;
@@ -93,6 +178,7 @@ type ProtocolStatePayload = {
93
178
  readonly key: unknown;
94
179
  readonly error: unknown;
95
180
  };
181
+ readonly hostScope?: string;
96
182
  }>;
97
183
  readonly sharedSeeds?: ReadonlyArray<{
98
184
  readonly graphNodeId: string;
@@ -132,6 +218,7 @@ type ProtocolStatePayload = {
132
218
  readonly graphNodeId: string;
133
219
  readonly key: string;
134
220
  }>;
221
+ readonly sharedRecords?: ReadonlyArray<SerializedRecord>;
135
222
  };
136
223
  type ProtocolBranchContentRead = {
137
224
  readonly graphNodeId: string;
@@ -197,6 +284,8 @@ type ProtocolArmRecordSet = {
197
284
  readonly elementHandles: ProtocolViewPayload['elementHandles'];
198
285
  readonly keyedRepeats?: ProtocolViewPayload['keyedRepeats'];
199
286
  readonly branches?: ReadonlyArray<ProtocolArmBranchRecord>;
287
+ /** Served beside `events` sent as templates: the names the stream boot listens for. */
288
+ readonly eventNames?: ReadonlyArray<string>;
200
289
  };
201
290
  /**
202
291
  * Where one row-template slot's value comes from: the repeated item, a graph
@@ -224,6 +313,23 @@ type ProtocolRowTemplateSlotValue = {
224
313
  readonly path: ReadonlyArray<string>;
225
314
  }>;
226
315
  };
316
+ /** One arm of a row's branch: its markup and slots, FRAGMENT-relative to the arm's first node. */
317
+ type ProtocolRowTemplateArm = {
318
+ readonly html: string;
319
+ readonly textSlots?: ReadonlyArray<{
320
+ readonly path: ReadonlyArray<number>;
321
+ } & ProtocolRowTemplateSlotValue>;
322
+ readonly attributeSlots?: ReadonlyArray<{
323
+ readonly path: ReadonlyArray<number>;
324
+ readonly name: string;
325
+ } & ProtocolRowTemplateSlotValue>;
326
+ };
327
+ type ProtocolRowTemplateBranchSlot = {
328
+ readonly path: ReadonlyArray<number>;
329
+ readonly branchId: string;
330
+ readonly armTests?: ReadonlyArray<unknown>;
331
+ readonly arms: ReadonlyArray<ProtocolRowTemplateArm>;
332
+ } & ProtocolRowTemplateSlotValue;
227
333
  type ProtocolViewPayload = {
228
334
  readonly version: typeof ASYNC_PROTOCOL_VERSION;
229
335
  readonly asyncRunners?: Readonly<Record<string, string>>;
@@ -340,7 +446,7 @@ type ProtocolViewPayload = {
340
446
  */
341
447
  readonly enclosingRow?: {
342
448
  readonly repeatId: string;
343
- readonly parentHostPath: ReadonlyArray<number>;
449
+ readonly parentHostPath: ProtocolElementAddress;
344
450
  readonly itemPath?: ReadonlyArray<string>;
345
451
  };
346
452
  readonly collectionGraphNodeId?: string;
@@ -363,6 +469,11 @@ type ProtocolViewPayload = {
363
469
  readonly arm: number;
364
470
  };
365
471
  readonly itemName: string;
472
+ /**
473
+ * The `index` name of the `@for`, which a row handler reading it is handed
474
+ * beside the item. Pay-per-use: present only when a row handler reads it.
475
+ */
476
+ readonly indexName?: string;
366
477
  readonly rowElementCount: number;
367
478
  /**
368
479
  * Element children of the parent that stand before the rows. Rows occupy
@@ -441,6 +552,18 @@ type ProtocolViewPayload = {
441
552
  readonly path: ReadonlyArray<number>;
442
553
  readonly name: string;
443
554
  } & ProtocolRowTemplateSlotValue>;
555
+ /**
556
+ * An `@if`/`@switch` written in the row, flipped per row. The slot value is
557
+ * the test (the discriminant for a `@switch`, matched against `armTests`),
558
+ * and `path` names the marker in `html` the shown arm's anchors and nodes
559
+ * replace. A branch that IS the row (`@for { @if { <tr> } }`) has the marker
560
+ * as the whole html: its arm is the row root, so a flip rebuilds the row.
561
+ * `branchId` is the branch site as the anchor comments spell it, before
562
+ * composition's prefix, like `branchArm.branchId`.
563
+ *
564
+ * Pay-per-use: a row with no such branch omits the field.
565
+ */
566
+ readonly branchSlots?: ReadonlyArray<ProtocolRowTemplateBranchSlot>;
444
567
  };
445
568
  /**
446
569
  * The parent graph node each prop a `rowTemplate` source slot reads follows,
@@ -493,16 +616,25 @@ type ProtocolViewPayload = {
493
616
  readonly rowChunkId?: string;
494
617
  };
495
618
  readonly rowElementHandles?: ReadonlyArray<{
496
- readonly hostPath: ReadonlyArray<number>;
619
+ readonly hostPath: ProtocolElementAddress;
497
620
  readonly handleId: string;
498
621
  readonly name: string;
499
622
  readonly plural?: boolean;
500
623
  }>;
501
624
  readonly rowEvents: ReadonlyArray<{
502
- readonly hostPath: ReadonlyArray<number>;
625
+ readonly hostPath: ProtocolElementAddress;
503
626
  readonly eventName: string;
504
627
  readonly symbolIds: ReadonlyArray<string>;
505
628
  readonly syncPolicy?: ProtocolSyncPolicy;
629
+ /**
630
+ * The event's host sits in arm `arm` of `rowTemplate.branchSlots[slot]`, so it
631
+ * exists only while that arm shows, and `hostPath` is ARM-relative: element
632
+ * index among the arm's nodes, then child-node indexes from there.
633
+ */
634
+ readonly arm?: {
635
+ readonly slot: number;
636
+ readonly arm: number;
637
+ };
506
638
  }>;
507
639
  }>;
508
640
  readonly branches?: ReadonlyArray<{
@@ -519,7 +651,7 @@ type ProtocolViewPayload = {
519
651
  readonly armTests?: ReadonlyArray<unknown>;
520
652
  readonly armRecords?: ReadonlyArray<{
521
653
  readonly events: ReadonlyArray<{
522
- readonly hostPath: ReadonlyArray<number>;
654
+ readonly hostPath: ProtocolElementAddress;
523
655
  readonly eventName: string;
524
656
  readonly symbolIds: ReadonlyArray<string>;
525
657
  readonly syncPolicy?: ProtocolSyncPolicy;
@@ -602,6 +734,9 @@ type ProtocolViewPayload = {
602
734
  readonly path: ReadonlyArray<string>;
603
735
  readonly runnerSymbolId?: string;
604
736
  }>;
737
+ /** As on a branch: the part instance that authored this boundary and where its live props now live, for the arm its own module re-renders on settle. */
738
+ readonly composedInstancePath?: string;
739
+ readonly composedGraphProps?: ReadonlyArray<ProtocolComposedGraphProp>;
605
740
  }>;
606
741
  };
607
742
  //#endregion
@@ -688,7 +823,27 @@ type RuntimeDemandMapClosurePlan = {
688
823
  }>;
689
824
  };
690
825
  //#endregion
826
+ //#region ../runtime/src/graph-reconcile.d.ts
827
+ /**
828
+ * One array inside a derived value that reconciles by key instead of by
829
+ * element identity. `path` names the array (`[]` is the derived value itself)
830
+ * and `keyPath` is read on each element to get its identity.
831
+ */
832
+ type RuntimeGraphReconcileKey = {
833
+ readonly path: ReadonlyArray<string>;
834
+ readonly keyPath: ReadonlyArray<string>;
835
+ };
836
+ /** Reconcile options carried by a computed or async computed graph node. */
837
+ type RuntimeGraphReconcileOptions = {
838
+ readonly keyed?: ReadonlyArray<RuntimeGraphReconcileKey>;
839
+ };
840
+ //#endregion
691
841
  //#region ../runtime/src/graph.d.ts
842
+ type RuntimeGraphRead = (graphNodeId: string, path?: ReadonlyArray<string>) => unknown;
843
+ type RuntimeGraphComputedDependency = {
844
+ readonly graphNodeId: string;
845
+ readonly path?: ReadonlyArray<string>;
846
+ };
692
847
  type RuntimeGraphAsyncSnapshot = {
693
848
  readonly status: 'idle';
694
849
  readonly version: 0;
@@ -708,6 +863,19 @@ type RuntimeGraphAsyncSnapshot = {
708
863
  readonly key: unknown;
709
864
  readonly error: unknown;
710
865
  };
866
+ type RuntimeGraphAsyncComputed = {
867
+ readonly graphNodeId: string;
868
+ readonly dependencies: ReadonlyArray<RuntimeGraphComputedDependency>;
869
+ readonly initialSnapshot?: RuntimeGraphAsyncSnapshot;
870
+ readonly key: (read: RuntimeGraphRead) => unknown;
871
+ /** How a fulfilled value reconciles against the previously published one. */
872
+ readonly reconcile?: RuntimeGraphReconcileOptions;
873
+ readonly run: (input: {
874
+ readonly key: unknown;
875
+ readonly signal: AbortSignal;
876
+ readonly read: RuntimeGraphRead;
877
+ }) => unknown | Promise<unknown>;
878
+ };
711
879
  type DomJournalEntry = {
712
880
  readonly type: 'setText';
713
881
  readonly locator: string;
@@ -777,6 +945,8 @@ type RuntimeGraphSubscription = {
777
945
  readonly graphNodeId: string;
778
946
  readonly path?: ReadonlyArray<string>;
779
947
  readonly run: (value: unknown) => DomJournalResult | RuntimeGraphCommit | void | Promise<DomJournalResult | RuntimeGraphCommit | void>;
948
+ /** False while `run` still has code to load; a write observer then leaves its DOM to the pass, so the task's writes land together. */
949
+ readonly ready?: () => boolean;
780
950
  };
781
951
  /**
782
952
  * Told about a write the moment it lands, before the flush that write schedules.
@@ -819,11 +989,14 @@ type RuntimeGraph = {
819
989
  readonly listSharedDefinitions: () => NonNullable<ProtocolStatePayload['sharedDefinitions']>;
820
990
  readonly takeSharedPatches: () => RuntimeGraphSharedPatch[];
821
991
  readonly applySharedPatch: (patch: RuntimeGraphSharedPatch) => boolean;
822
- readonly write: (write: RuntimeGraphWrite) => void;
992
+ /** Answers the value written, as the assignment it lowers from does. */
993
+ readonly write: (write: RuntimeGraphWrite) => unknown;
823
994
  readonly update: (update: RuntimeGraphUpdate) => unknown;
824
995
  readonly call: (call: RuntimeGraphCall) => unknown;
825
996
  readonly delete: (deletion: RuntimeGraphDelete) => boolean;
826
997
  readonly subscribe: (subscription: RuntimeGraphSubscription) => () => void;
998
+ /** Adds an async computed a component rendered after the graph was built; false when the node already exists. */
999
+ readonly defineAsyncComputed?: (asyncComputed: RuntimeGraphAsyncComputed) => boolean;
827
1000
  /**
828
1001
  * Optional so a facade over a subset of this contract stays a `RuntimeGraph`;
829
1002
  * a caller without it gets the flush-time answer it always had.
@@ -866,7 +1039,7 @@ type ResumeDomElement = ResumeDomNode & {
866
1039
  readonly dispatchEvent?: (event: ResumeSharedPatchEvent) => boolean;
867
1040
  readonly setAttribute?: (name: string, value: string) => void;
868
1041
  readonly removeAttribute?: (name: string) => void;
869
- __marklessDelegatedDispatch?: boolean;
1042
+ __marklessDelegatedDispatch?: boolean | string;
870
1043
  __marklessListen?: (eventType: string) => void;
871
1044
  __marklessDispatch?: (input: {
872
1045
  readonly root: ResumeDomElement;
@@ -878,6 +1051,7 @@ type ResumeDomElement = ResumeDomNode & {
878
1051
  __marklessReleaseDispatch?: () => void;
879
1052
  __marklessEventOnlyGraph?: Map<string, unknown>;
880
1053
  __marklessCensus?: ResumeDomElement[];
1054
+ __marklessComments?: ResumeDomComment[];
881
1055
  __marklessBranchArms?: Map<string, ResumeBranchArmEntry>;
882
1056
  readonly ownerDocument?: ResumeDomOwnerDocument;
883
1057
  };
@@ -916,7 +1090,7 @@ type ResumeDomEvent = {
916
1090
  readonly preventDefault?: () => void;
917
1091
  readonly stopPropagation?: () => void;
918
1092
  readonly composedPath?: () => ReadonlyArray<ResumeDomElement>;
919
- __marklessPressHost?: ResumeDomElement;
1093
+ __marklessPressPath?: ReadonlyArray<ResumeDomElement>;
920
1094
  };
921
1095
  type ResumeSharedPatchEvent = {
922
1096
  readonly type: 'async:shared-patch';
@@ -936,6 +1110,8 @@ type ResumeAsyncBoundaryRecord = {
936
1110
  readonly endAnchor: ResumeDomComment;
937
1111
  readonly asyncReads: ProtocolViewPayload['asyncBoundaries'][number]['asyncReads'];
938
1112
  readonly armRecords?: ResumeArmRecordSet | ReadonlyArray<unknown>;
1113
+ readonly composedInstancePath?: string;
1114
+ readonly composedGraphProps?: ProtocolViewPayload['asyncBoundaries'][number]['composedGraphProps'];
939
1115
  };
940
1116
  type ResumeBranchArmRecordSet = NonNullable<NonNullable<ProtocolViewPayload['branches']>[number]['armRecords']>[number];
941
1117
  type ResumeBranchRecord = {
@@ -1006,6 +1182,13 @@ type ResumeArmRecordSet = {
1006
1182
  readonly elementHandles: ProtocolViewPayload['elementHandles'];
1007
1183
  readonly keyedRepeats?: NonNullable<ProtocolViewPayload['keyedRepeats']>;
1008
1184
  readonly branches?: ReadonlyArray<ResumeArmBranchRecord>;
1185
+ /** @try blocks the arm renders inside itself, anchor indexes counted from the arm start. */
1186
+ readonly asyncBoundaries?: ReadonlyArray<Omit<ResumeAsyncBoundaryPayload, 'armRecords'> & {
1187
+ readonly armRecords?: ResumeArmRecordSet;
1188
+ }>;
1189
+ };
1190
+ type ResumeAsyncBoundaryPayload = ProtocolViewPayload['asyncBoundaries'][number] & {
1191
+ readonly armRecords?: ResumeArmRecordSet | ReadonlyArray<unknown>;
1009
1192
  };
1010
1193
  type ResumeSymbolContext = {
1011
1194
  readonly graph?: RuntimeGraph;
@@ -4,7 +4,7 @@ import { i as protocolStateVersion, n as protocolInstanceQualifies, t as protoco
4
4
  /** The field names each templated record list may spell, in the order its templates index them. */
5
5
  const PROTOCOL_RECORD_KEYS = {
6
6
  "markless/state": {
7
- computed: "graphNodeId name async deriveSymbolId value version root $type $ref source flags records id type fields items entries values bytes arrayType buffer byteOffset length byteLength directValue dependencies path snapshot status key error",
7
+ computed: "graphNodeId name async deriveSymbolId value version root $type $ref source flags records id type fields items entries values bytes arrayType buffer byteOffset length byteLength directValue dependencies path snapshot status key error hostScope",
8
8
  sharedSeeds: "graphNodeId deriveSymbolId dependencies path reads",
9
9
  sharedDefinitions: "id name exportedName scope version graphNodeIds projectionIds dependencies definitionId definitionName returnProperties kind graphNodeId path"
10
10
  },
@@ -17,34 +17,114 @@ const PROTOCOL_RECORD_KEYS = {
17
17
  //#endregion
18
18
  //#region ../serializer/src/protocol-templated-lists.ts
19
19
  /**
20
- * The record lists a payload script may serve as record templates instead of a plain array. The
21
- * inline resumer reads the others at page load, before any decoder has loaded, so they stay plain.
20
+ * The record lists a payload script may serve as record templates instead of a plain array. A
21
+ * reader that parses a payload script without decoding it may read only the other lists.
22
22
  */
23
23
  const PROTOCOL_TEMPLATED_LISTS = {
24
24
  "markless/state": [
25
+ "cells",
25
26
  "computed",
26
27
  "sharedSeeds",
27
- "sharedDefinitions"
28
+ "sharedDefinitions",
29
+ "sharedRecords"
28
30
  ],
29
31
  "markless/view": [
32
+ "locators",
33
+ "events",
30
34
  "domUpdates",
31
35
  "behaviors",
32
- "elementHandles"
36
+ "elementHandles",
37
+ "keyedRepeats"
33
38
  ]
34
39
  };
35
40
  //#endregion
41
+ //#region ../serializer/src/protocol-shared-records-decode.ts
42
+ const ref = (slot, copy) => typeof slot === "object" && slot !== null && "$ref" in slot ? { $ref: copy(slot.$ref) } : slot;
43
+ function renamed(record, copy) {
44
+ const map = (slot) => ref(slot, copy);
45
+ if (record.type === "object") return {
46
+ ...record,
47
+ fields: record.fields.map(([key, slot]) => [key, map(slot)])
48
+ };
49
+ if (record.type === "array") return {
50
+ ...record,
51
+ items: record.items.map(map)
52
+ };
53
+ if (record.type === "map") return {
54
+ ...record,
55
+ entries: record.entries.map(([key, value]) => [map(key), map(value)])
56
+ };
57
+ if (record.type === "set") return {
58
+ ...record,
59
+ values: record.values.map(map)
60
+ };
61
+ if (record.type === "typed-array" || record.type === "data-view") return {
62
+ ...record,
63
+ buffer: map(record.buffer)
64
+ };
65
+ return record;
66
+ }
67
+ /**
68
+ * Gives every envelope of a freshly parsed state payload, in place, a copy of each shared subtree
69
+ * it references, under ids of its own: two references to one shared record are two objects.
70
+ */
71
+ function expandSharedRecords(state) {
72
+ const payload = state;
73
+ const shared = payload?.sharedRecords;
74
+ if (!shared) return state;
75
+ const byId = new Map(shared.map((record) => [record.id, record]));
76
+ const expand = (envelope) => {
77
+ const records = envelope?.records;
78
+ if (!Array.isArray(records)) return;
79
+ let next = 0;
80
+ for (const record of records) next = Math.max(next, record.id + 1);
81
+ const copies = [];
82
+ const copy = (id) => {
83
+ const record = byId.get(id);
84
+ if (!record) return id;
85
+ const at = next++;
86
+ const slot = copies.push(record) - 1;
87
+ copies[slot] = {
88
+ ...renamed(record, copy),
89
+ id: at
90
+ };
91
+ return at;
92
+ };
93
+ const own = records.map((record) => renamed(record, copy));
94
+ if (copies.length) envelope.records = [...own, ...copies];
95
+ };
96
+ for (const cell of payload.cells ?? []) expand(cell?.value);
97
+ for (const computed of payload.computed ?? []) {
98
+ expand(computed?.value);
99
+ const snapshot = computed?.snapshot;
100
+ expand(snapshot?.key);
101
+ expand(snapshot?.value);
102
+ expand(snapshot?.error);
103
+ }
104
+ delete payload.sharedRecords;
105
+ return state;
106
+ }
107
+ //#endregion
36
108
  //#region ../serializer/src/protocol-record-templates.ts
37
- function expandRecordTemplates(list, keys = "") {
109
+ function expandRecordTemplates(list, keys = "", instancePaths = []) {
38
110
  if (Array.isArray(list)) return list;
39
111
  const { t, r } = list;
40
112
  const names = keys.split(" ");
41
- const parts = t.map((text) => text.replace(/~(\d+):/g, (_, at) => `"${names[+at]}":`).split(/\^(\d+)/));
113
+ const paths = [];
114
+ const path = (at) => {
115
+ const entry = instancePaths[at];
116
+ return paths[at] ??= typeof entry === "string" ? entry : path(entry[0]) + entry[1];
117
+ };
118
+ const parts = t.map((text) => text.replace(/~(\d+):/g, (_, at) => `"${names[+at]}":`).split(/([\^`])(\d+)/));
42
119
  return r.map((ref) => {
43
120
  if (typeof ref === "number") return JSON.parse(parts[ref][0]);
44
121
  if (!Array.isArray(ref)) return ref;
45
122
  const part = parts[ref[0]];
46
123
  let text = part[0];
47
- for (let at = 1; at < part.length; at += 2) text += ref[+part[at] + 1] + part[at + 1];
124
+ for (let at = 1; at < part.length; at += 3) {
125
+ const value = ref[+part[at + 1] + 1];
126
+ text += (part[at] === "`" ? path(value) : value) + part[at + 2];
127
+ }
48
128
  return JSON.parse(text);
49
129
  });
50
130
  }
@@ -52,11 +132,20 @@ function expandRecordTemplates(list, keys = "") {
52
132
  function decodeProtocolPayloadLists(type, payload) {
53
133
  const record = payload;
54
134
  const keys = PROTOCOL_RECORD_KEYS[type];
55
- if (record) for (const key of PROTOCOL_TEMPLATED_LISTS[type]) {
56
- const list = record[key];
57
- if (list && !Array.isArray(list)) record[key] = expandRecordTemplates(list, keys[key]);
135
+ if (record) {
136
+ const paths = record.instancePaths;
137
+ const inRows = record.inRows;
138
+ for (const key of PROTOCOL_TEMPLATED_LISTS[type]) {
139
+ const list = record[key];
140
+ if (list && !Array.isArray(list)) record[key] = expandRecordTemplates(list, keys[key], paths);
141
+ const rows = inRows?.[key] && expandRecordTemplates(inRows[key], keys[key], paths);
142
+ let at = 0;
143
+ if (rows) record[key] = list.map((item) => item ?? rows[at++]);
144
+ }
145
+ delete record.instancePaths;
146
+ delete record.inRows;
58
147
  }
59
- return payload;
148
+ return expandSharedRecords(payload);
60
149
  }
61
150
  //#endregion
62
151
  //#region ../serializer/src/storage-cookie.ts
@@ -742,7 +831,7 @@ async function runScalar(root, event, prepared, symbol) {
742
831
  },
743
832
  write(write) {
744
833
  check(write.graphNodeId, write.path);
745
- value = write.value;
834
+ return value = write.value;
746
835
  },
747
836
  update(update) {
748
837
  check(update.graphNodeId, update.path);
@@ -1330,6 +1419,9 @@ function islandScopedFamilyRecord(record, context) {
1330
1419
  index: context.commentOffset + Number(anchor.index)
1331
1420
  };
1332
1421
  }
1422
+ if (isFamilyRecord(record.rowTemplate)) mapped.rowTemplate = islandScopedRowTemplate(record.rowTemplate, island);
1423
+ if ((record.rowTemplate || record.rowComponent) && record.instancePath === void 0 && island.segment) mapped.instancePath = island.segment;
1424
+ if (Array.isArray(record.propRoutes)) mapped.propRoutes = record.propRoutes.map((route) => isFamilyRecord(route) ? islandScopedGraphRecord(route, island) : route);
1333
1425
  for (const key of MDX_NESTED_RECORD_KEYS) {
1334
1426
  const nested = record[key];
1335
1427
  if (Array.isArray(nested)) mapped[key] = nested.map((entry) => isFamilyRecord(entry) ? islandScopedFamilyRecord(entry, context) : entry);
@@ -1337,6 +1429,26 @@ function islandScopedFamilyRecord(record, context) {
1337
1429
  }
1338
1430
  return mapped;
1339
1431
  }
1432
+ function islandScopedRowTemplate(template, island) {
1433
+ const slot = (value) => {
1434
+ if (!isFamilyRecord(value)) return value;
1435
+ const scoped = { ...islandScopedGraphRecord(value, island) };
1436
+ if (Array.isArray(value.reads)) scoped.reads = value.reads.map((read) => isFamilyRecord(read) ? islandScopedGraphRecord(read, island) : read);
1437
+ if (Array.isArray(value.arms)) scoped.arms = value.arms.map(slots);
1438
+ return scoped;
1439
+ };
1440
+ const slots = (owner) => {
1441
+ if (!isFamilyRecord(owner)) return owner;
1442
+ const scoped = { ...owner };
1443
+ for (const key of [
1444
+ "textSlots",
1445
+ "attributeSlots",
1446
+ "branchSlots"
1447
+ ]) if (Array.isArray(owner[key])) scoped[key] = owner[key].map(slot);
1448
+ return scoped;
1449
+ };
1450
+ return slots(template);
1451
+ }
1340
1452
  function isFamilyRecord(value) {
1341
1453
  return typeof value === "object" && value !== null && !Array.isArray(value);
1342
1454
  }