vinext 1.3.1 → 1.4.1
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/README.md +25 -22
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +4 -3
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +4 -7
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay-store.d.ts +1 -0
- package/dist/client/dev-error-overlay.d.ts +2 -0
- package/dist/client/dev-error-overlay.js +20 -4
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +2 -0
- package/dist/config/destination-params.d.ts +2 -1
- package/dist/config/destination-params.js +52 -2
- package/dist/config/next-config.d.ts +25 -0
- package/dist/config/next-config.js +82 -4
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -49
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +36 -9
- package/dist/index.js +112 -90
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/strip-server-exports.js +2 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +21 -5
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +86 -66
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +7 -7
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +5 -4
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +4 -14
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +43 -4
- package/dist/server/app-page-boundary-render.js +10 -14
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -11
- package/dist/server/app-page-dispatch.js +84 -155
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +13 -12
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +102 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -13
- package/dist/server/app-page-render.js +103 -234
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +86 -63
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +12 -8
- package/dist/server/app-page-stream.js +4 -3
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +11 -5
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.d.ts +1 -1
- package/dist/server/app-route-handler-runtime.js +28 -11
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +12 -12
- package/dist/server/app-rsc-cache-busting.js +31 -72
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +10 -2
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +11 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +80 -83
- package/dist/server/app-rsc-request-normalization.d.ts +10 -16
- package/dist/server/app-rsc-request-normalization.js +12 -18
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +9 -15
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +15 -8
- package/dist/server/app-ssr-entry.d.ts +8 -0
- package/dist/server/app-ssr-entry.js +22 -16
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +37 -6
- package/dist/server/app-worker-stages.js +81 -9
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/bfcache-identity.d.ts +7 -0
- package/dist/server/bfcache-identity.js +10 -1
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-manifest.js +1 -2
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-origin-check.d.ts +2 -1
- package/dist/server/dev-origin-check.js +2 -1
- package/dist/server/dev-server.js +6 -4
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/image-optimization.d.ts +5 -0
- package/dist/server/image-optimization.js +6 -1
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +30 -2
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/middleware-matcher.js +19 -6
- package/dist/server/middleware-runtime.js +6 -2
- package/dist/server/multi-stage.d.ts +57 -12
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.d.ts +1 -1
- package/dist/server/pages-node-compat.js +54 -27
- package/dist/server/pages-page-data.js +2 -1
- package/dist/server/pages-page-handler.js +28 -26
- package/dist/server/pages-page-response.d.ts +9 -0
- package/dist/server/pages-page-response.js +18 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +36 -14
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/pages-router-entry.js +3 -2
- package/dist/server/prod-server.d.ts +2 -2
- package/dist/server/prod-server.js +47 -9
- package/dist/server/request-error-log.d.ts +9 -0
- package/dist/server/request-error-log.js +13 -0
- package/dist/server/request-pipeline.d.ts +15 -4
- package/dist/server/request-pipeline.js +43 -15
- package/dist/server/rsc-completion-metadata.js +3 -0
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/static-file-cache.d.ts +9 -0
- package/dist/server/static-file-cache.js +13 -2
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +23 -26
- package/dist/shims/cache-request-state.js +22 -57
- package/dist/shims/cache-runtime.d.ts +3 -1
- package/dist/shims/cache-runtime.js +94 -48
- package/dist/shims/cache.d.ts +16 -10
- package/dist/shims/cache.js +47 -36
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-hook-error.d.ts +2 -0
- package/dist/shims/client-hook-error.js +16 -1
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +39 -25
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +10 -24
- package/dist/shims/headers.js +22 -70
- package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +8 -11
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +184 -31
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +3 -2
- package/dist/shims/slot.d.ts +16 -0
- package/dist/shims/slot.js +44 -9
- package/dist/shims/unified-request-context.d.ts +7 -1
- package/dist/shims/unified-request-context.js +3 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/cache-life-profiles.d.ts +33 -0
- package/dist/utils/cache-life-profiles.js +111 -0
- package/dist/utils/middleware-request-headers.d.ts +14 -3
- package/dist/utils/middleware-request-headers.js +54 -7
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -31,6 +31,7 @@ var AppBrowserHistoryController = class {
|
|
|
31
31
|
#treeSnapshots = /* @__PURE__ */ new Map();
|
|
32
32
|
#treeSnapshotClaimCounts = /* @__PURE__ */ new Map();
|
|
33
33
|
#treeSnapshotClaimByHistoryIndex = /* @__PURE__ */ new Map();
|
|
34
|
+
#treeSnapshotIdPrefix = createDocumentTreeSnapshotIdPrefix();
|
|
34
35
|
#readHistoryState;
|
|
35
36
|
#readCurrentHref;
|
|
36
37
|
#pushHistoryState;
|
|
@@ -41,6 +42,9 @@ var AppBrowserHistoryController = class {
|
|
|
41
42
|
#currentTreeSnapshotId = null;
|
|
42
43
|
#nextTreeSnapshotId = 0;
|
|
43
44
|
#treeSnapshotIdPendingFreshState = null;
|
|
45
|
+
#historyIndicesAwaitingTreeSnapshot = /* @__PURE__ */ new Set();
|
|
46
|
+
#treeSnapshotPending = true;
|
|
47
|
+
#historyIndexAwaitingTreeClaim = null;
|
|
44
48
|
constructor(deps) {
|
|
45
49
|
this.#readHistoryState = deps.readHistoryState;
|
|
46
50
|
this.#readCurrentHref = deps.readCurrentHref;
|
|
@@ -99,18 +103,29 @@ var AppBrowserHistoryController = class {
|
|
|
99
103
|
const previousState = this.readCurrentTreeSnapshot();
|
|
100
104
|
const previousOperation = previousState?.activeOperation;
|
|
101
105
|
if (previousState && previousOperation?.navigationCommitKind === "detached" && state.activeOperation?.navigationCommitKind === "authoritative" && state.activeOperation.navigationId === previousOperation.navigationId) this.#restorableClientState.replaceHistoryStateSnapshots(previousState, state);
|
|
106
|
+
for (const historyIndex of this.#historyIndicesAwaitingTreeSnapshot) this.#restorableClientState.rememberHistoryStateSnapshot({
|
|
107
|
+
historyIndex,
|
|
108
|
+
state
|
|
109
|
+
});
|
|
110
|
+
this.#historyIndicesAwaitingTreeSnapshot.clear();
|
|
102
111
|
this.#restorableClientState.rememberHistoryStateSnapshot({
|
|
103
112
|
historyIndex: this.#currentHistoryTraversalIndex,
|
|
104
113
|
state
|
|
105
114
|
});
|
|
115
|
+
this.#treeSnapshotPending = false;
|
|
106
116
|
const historyTreeSnapshotId = readHistoryStateTreeSnapshotId(this.#readHistoryState());
|
|
107
|
-
const treeSnapshotId = historyTreeSnapshotId !== null && this.#treeSnapshots.has(historyTreeSnapshotId) && (historyTreeSnapshotId === this.#treeSnapshotIdPendingFreshState || this.#treeSnapshotClaimCounts.has(historyTreeSnapshotId)) ? historyTreeSnapshotId : this.#nextTreeSnapshotId
|
|
117
|
+
const treeSnapshotId = historyTreeSnapshotId !== null && this.#treeSnapshots.has(historyTreeSnapshotId) && (historyTreeSnapshotId === this.#treeSnapshotIdPendingFreshState || this.#treeSnapshotClaimCounts.has(historyTreeSnapshotId)) ? historyTreeSnapshotId : `${this.#treeSnapshotIdPrefix}:${this.#nextTreeSnapshotId++}`;
|
|
108
118
|
this.#treeSnapshotIdPendingFreshState = null;
|
|
109
119
|
const previousTreeSnapshotId = this.#currentTreeSnapshotId;
|
|
110
120
|
this.#currentTreeSnapshotId = treeSnapshotId;
|
|
111
121
|
this.#treeSnapshots.set(treeSnapshotId, state);
|
|
122
|
+
const claimingHistoryIndex = this.#historyIndexAwaitingTreeClaim;
|
|
123
|
+
this.#historyIndexAwaitingTreeClaim = null;
|
|
124
|
+
const claimsTree = claimingHistoryIndex !== null && claimingHistoryIndex === this.#currentHistoryTraversalIndex && claimingHistoryIndex === readHistoryStateTraversalIndex(this.#readHistoryState());
|
|
125
|
+
if (claimsTree) this.#claimTreeSnapshotAtHistoryIndex(claimingHistoryIndex, treeSnapshotId);
|
|
112
126
|
if (previousTreeSnapshotId !== null && previousTreeSnapshotId !== treeSnapshotId && !this.#treeSnapshotClaimCounts.has(previousTreeSnapshotId)) this.#treeSnapshots.delete(previousTreeSnapshotId);
|
|
113
|
-
if (
|
|
127
|
+
if (claimsTree) this.#replaceHistoryState(createHistoryStateWithTreeSnapshotClaim(createHistoryStateWithTreeSnapshotId(this.#readHistoryState(), treeSnapshotId), true));
|
|
128
|
+
else if (historyTreeSnapshotId !== treeSnapshotId) this.#replaceHistoryState(createHistoryStateWithTreeSnapshotId(this.#readHistoryState(), treeSnapshotId));
|
|
114
129
|
}
|
|
115
130
|
/** The router state of the most recently committed render, if any. */
|
|
116
131
|
readCurrentTreeSnapshot() {
|
|
@@ -125,7 +140,21 @@ var AppBrowserHistoryController = class {
|
|
|
125
140
|
claimCurrentHistoryTreeSnapshot(historyUpdateMode, previousHistoryState) {
|
|
126
141
|
let historyState = this.#readHistoryState();
|
|
127
142
|
const treeSnapshotId = readHistoryStateTreeSnapshotId(historyState);
|
|
128
|
-
if (treeSnapshotId === null || !this.#treeSnapshots.has(treeSnapshotId))
|
|
143
|
+
if (treeSnapshotId === null || !this.#treeSnapshots.has(treeSnapshotId)) {
|
|
144
|
+
if (historyUpdateMode === "push") {
|
|
145
|
+
const previousHistoryIndex = readHistoryStateTraversalIndex(previousHistoryState);
|
|
146
|
+
if (previousHistoryIndex !== null && this.#treeSnapshotPending) this.#historyIndicesAwaitingTreeSnapshot.add(previousHistoryIndex);
|
|
147
|
+
this.#releaseForwardTreeSnapshotClaims();
|
|
148
|
+
const historyIndex = this.#nextHistoryTraversalIndex + 1;
|
|
149
|
+
this.#replaceHistoryState(createHistoryStateWithNavigationMetadata(historyState, {
|
|
150
|
+
previousNextUrl: readHistoryStatePreviousNextUrl(historyState),
|
|
151
|
+
traversalIndex: historyIndex
|
|
152
|
+
}));
|
|
153
|
+
this.commitHistoryTraversalIndex(historyIndex);
|
|
154
|
+
this.#historyIndexAwaitingTreeClaim = this.#treeSnapshotPending ? historyIndex : null;
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
129
158
|
let historyIndex;
|
|
130
159
|
if (historyUpdateMode === "push") {
|
|
131
160
|
this.#releaseForwardTreeSnapshotClaims();
|
|
@@ -185,7 +214,6 @@ var AppBrowserHistoryController = class {
|
|
|
185
214
|
if (treeSnapshotId !== this.#currentTreeSnapshotId) this.#treeSnapshots.delete(treeSnapshotId);
|
|
186
215
|
}
|
|
187
216
|
commitHashOnlyNavigation(href, historyUpdateMode, scroll) {
|
|
188
|
-
if (historyUpdateMode === "push") this.#releaseForwardTreeSnapshotClaims();
|
|
189
217
|
const navigationHistoryIndex = this.allocateNavigationHistoryTraversalIndex(historyUpdateMode);
|
|
190
218
|
const historyState = this.#readHistoryState();
|
|
191
219
|
const visible = this.#readVisibleNavigationMetadata();
|
|
@@ -199,11 +227,59 @@ var AppBrowserHistoryController = class {
|
|
|
199
227
|
previousNextUrl,
|
|
200
228
|
traversalIndex: navigationHistoryIndex
|
|
201
229
|
}), true);
|
|
202
|
-
|
|
203
|
-
else this.#pushHistoryState(nextHistoryState, href);
|
|
230
|
+
const historyIndex = this.#writeNavigationHistoryState(historyUpdateMode, nextHistoryState, href, navigationHistoryIndex, false);
|
|
204
231
|
const treeSnapshotId = readHistoryStateTreeSnapshotId(nextHistoryState);
|
|
205
|
-
if (
|
|
206
|
-
|
|
232
|
+
if (historyIndex !== null && treeSnapshotId !== null) this.#claimTreeSnapshotAtHistoryIndex(historyIndex, treeSnapshotId);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Writes an app-owned push or replace entry and returns the traversal index
|
|
236
|
+
* it landed at. A history wrapper installed after boot can make its own
|
|
237
|
+
* writes before forwarding this one. When those moved the indices, the index
|
|
238
|
+
* is assigned as the write lands: a push goes after them, and a replace takes
|
|
239
|
+
* the index of the entry it actually overwrites. The index is committed as
|
|
240
|
+
* soon as the write succeeds, so a push the wrapper makes after forwarding
|
|
241
|
+
* goes after it.
|
|
242
|
+
*/
|
|
243
|
+
#writeNavigationHistoryState(historyUpdateMode, state, href, allocatedIndex, rendersTree) {
|
|
244
|
+
const allocatedCurrentIndex = this.#currentHistoryTraversalIndex;
|
|
245
|
+
const allocatedNextIndex = this.#nextHistoryTraversalIndex;
|
|
246
|
+
const releaseClaims = (overwrittenHistoryState) => {
|
|
247
|
+
if (historyUpdateMode === "push") {
|
|
248
|
+
this.#releaseForwardTreeSnapshotClaims();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (!rendersTree) return;
|
|
252
|
+
const overwrittenIndex = readHistoryStateTraversalIndex(overwrittenHistoryState) ?? this.#currentHistoryTraversalIndex;
|
|
253
|
+
if (overwrittenIndex !== null) this.#releaseTreeSnapshotClaimAtHistoryIndex(overwrittenIndex);
|
|
254
|
+
};
|
|
255
|
+
let landedIndex;
|
|
256
|
+
let landingStarted = false;
|
|
257
|
+
const land = (data) => {
|
|
258
|
+
landingStarted = true;
|
|
259
|
+
const index = this.#currentHistoryTraversalIndex !== allocatedCurrentIndex || this.#nextHistoryTraversalIndex !== allocatedNextIndex ? this.allocateNavigationHistoryTraversalIndex(historyUpdateMode) : allocatedIndex;
|
|
260
|
+
const overwrittenHistoryState = this.#readHistoryState();
|
|
261
|
+
return {
|
|
262
|
+
data: index === allocatedIndex ? data : createHistoryStateWithNavigationMetadata(data, {
|
|
263
|
+
previousNextUrl: readHistoryStatePreviousNextUrl(data),
|
|
264
|
+
traversalIndex: index
|
|
265
|
+
}),
|
|
266
|
+
commit: () => {
|
|
267
|
+
releaseClaims(overwrittenHistoryState);
|
|
268
|
+
if (rendersTree) this.#treeSnapshotPending = true;
|
|
269
|
+
landedIndex = index;
|
|
270
|
+
this.commitHistoryTraversalIndex(index);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
const historyStateBeforeWrite = this.#readHistoryState();
|
|
275
|
+
if (historyUpdateMode === "push") this.#pushHistoryState(state, href, land);
|
|
276
|
+
else this.#replaceHistoryState(state, href, land);
|
|
277
|
+
if (landedIndex !== void 0) return landedIndex;
|
|
278
|
+
if (landingStarted) return null;
|
|
279
|
+
releaseClaims(historyStateBeforeWrite);
|
|
280
|
+
if (rendersTree) this.#treeSnapshotPending = true;
|
|
281
|
+
this.commitHistoryTraversalIndex(allocatedIndex);
|
|
282
|
+
return allocatedIndex;
|
|
207
283
|
}
|
|
208
284
|
#createHashOnlyNavigationBaseHistoryState(historyUpdateMode, scroll) {
|
|
209
285
|
const historyState = this.#readHistoryState();
|
|
@@ -238,19 +314,15 @@ var AppBrowserHistoryController = class {
|
|
|
238
314
|
let wroteHistoryState = false;
|
|
239
315
|
if (options.historyUpdateMode === "replace" && (currentHref !== targetHref || replacesClaimedOrExternalTree)) {
|
|
240
316
|
options.stageClientParams();
|
|
241
|
-
|
|
242
|
-
if (currentHistoryIndex !== null) this.#releaseTreeSnapshotClaimAtHistoryIndex(currentHistoryIndex);
|
|
243
|
-
this.#replaceHistoryState(historyState, options.href);
|
|
317
|
+
this.#writeNavigationHistoryState("replace", historyState, options.href, navigationHistoryIndex, true);
|
|
244
318
|
wroteHistoryState = true;
|
|
245
|
-
this.commitHistoryTraversalIndex(navigationHistoryIndex);
|
|
246
319
|
} else if (options.historyUpdateMode === "push" && currentHref !== targetHref) {
|
|
247
320
|
options.stageClientParams();
|
|
248
|
-
this.#
|
|
249
|
-
this.#pushHistoryState(historyState, options.href);
|
|
321
|
+
this.#writeNavigationHistoryState("push", historyState, options.href, navigationHistoryIndex, true);
|
|
250
322
|
wroteHistoryState = true;
|
|
251
|
-
this.commitHistoryTraversalIndex(navigationHistoryIndex);
|
|
252
323
|
}
|
|
253
324
|
if (!wroteHistoryState) {
|
|
325
|
+
this.#treeSnapshotPending = true;
|
|
254
326
|
this.syncCurrentHistoryStatePreviousNextUrl(options.previousNextUrl, options.bfcacheIds, options.activeRoutePaths);
|
|
255
327
|
options.stageClientParams();
|
|
256
328
|
if (options.targetHistoryIndex !== void 0) this.commitHistoryTraversalIndex(options.targetHistoryIndex);
|
|
@@ -306,6 +378,7 @@ var AppBrowserHistoryController = class {
|
|
|
306
378
|
state,
|
|
307
379
|
beforeCommit: () => {
|
|
308
380
|
this.commitTraversalIndexFromHistoryState(options.historyState);
|
|
381
|
+
this.#treeSnapshotPending = true;
|
|
309
382
|
options.stageClientParams(state.navigationSnapshot.params);
|
|
310
383
|
}
|
|
311
384
|
});
|
|
@@ -317,11 +390,16 @@ var AppBrowserHistoryController = class {
|
|
|
317
390
|
state: decision.state,
|
|
318
391
|
beforeCommit: () => {
|
|
319
392
|
this.commitHistoryTraversalIndex(decision.targetHistoryIndex);
|
|
393
|
+
this.#treeSnapshotPending = true;
|
|
320
394
|
options.stageClientParams(decision.state.navigationSnapshot.params);
|
|
321
395
|
}
|
|
322
396
|
});
|
|
323
397
|
}
|
|
324
398
|
};
|
|
399
|
+
function createDocumentTreeSnapshotIdPrefix() {
|
|
400
|
+
const bytes = crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(8));
|
|
401
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
402
|
+
}
|
|
325
403
|
function areStringArraysEqual(a, b) {
|
|
326
404
|
if (a === b) return true;
|
|
327
405
|
if (a === null || b === null || a.length !== b.length) return false;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { AppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
3
|
-
import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
|
|
4
3
|
import { AppElements } from "./app-elements-wire.js";
|
|
5
4
|
import "./app-elements.js";
|
|
5
|
+
import { ClientNavigationRenderSnapshot, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
6
|
+
import { NavigationRuntimeVisibleCommitMode } from "../client/navigation-runtime.js";
|
|
6
7
|
import { OperationLane } from "./operation-token.js";
|
|
7
8
|
import { ServerActionRevalidationKind } from "./app-browser-action-result.js";
|
|
8
|
-
import { ClientNavigationRenderSnapshot, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
9
9
|
import { AppNavigationPayloadOrigin, AppRouterState } from "./app-browser-state.js";
|
|
10
10
|
import { Dispatch, ReactNode } from "react";
|
|
11
11
|
//#region src/server/app-browser-navigation-controller.d.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { withBasePath } from "../shims/url-utils.js";
|
|
3
3
|
import { clearAppNavigationFailureTarget, getAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
|
|
4
|
-
import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
5
4
|
import { resolveServerActionOperationLane, shouldScheduleRefreshForDiscardedServerAction } from "./app-browser-action-result.js";
|
|
6
5
|
import { resolveActiveRoutePaths } from "./app-history-state.js";
|
|
6
|
+
import { claimAppRouterScrollIntentForCommit, clearAppRouterScrollIntent, consumeAppRouterScrollIntent } from "../shims/app-router-scroll-state.js";
|
|
7
7
|
import { activateNavigationSnapshot, clearPendingPathname, commitClientNavigationState, createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
8
8
|
import { FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN, createPendingNavigationCommit, createPendingNavigationCommitFromElements } from "./app-browser-state.js";
|
|
9
9
|
import { applyApprovedVisibleCommit, approveHmrVisibleCommit, approvePendingNavigationCommit, resolveAndClassifyNavigationCommit } from "./app-browser-visible-commit.js";
|
|
@@ -408,7 +408,6 @@ function createAppBrowserNavigationController(deps = {}) {
|
|
|
408
408
|
elements: options.restoredState.elements,
|
|
409
409
|
interception: options.restoredState.interception,
|
|
410
410
|
interceptionContext: options.restoredState.interceptionContext,
|
|
411
|
-
layoutFlags: options.restoredState.layoutFlags,
|
|
412
411
|
layoutIds: options.restoredState.layoutIds,
|
|
413
412
|
navigationSnapshot: options.restoredState.navigationSnapshot,
|
|
414
413
|
operation,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isDangerousScheme, reportBlockedDangerousNavigation } from "../shims/url-safety.js";
|
|
2
|
-
import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam,
|
|
2
|
+
import { resolveHardNavigationTargetFromRscResponse, stripRscCacheBustingSearchParam, toPathAbsolutePathname } from "./app-rsc-cache-busting.js";
|
|
3
3
|
//#region src/server/app-browser-rsc-redirect.ts
|
|
4
4
|
const MAX_RSC_REDIRECT_DEPTH = 10;
|
|
5
5
|
function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
|
|
@@ -11,11 +11,10 @@ function blockDangerousStreamedRscRedirect(response, streamedRedirectTarget) {
|
|
|
11
11
|
function toVisibleAppHref(href, origin) {
|
|
12
12
|
const url = new URL(href, origin);
|
|
13
13
|
stripRscCacheBustingSearchParam(url);
|
|
14
|
-
return `${
|
|
14
|
+
return `${toPathAbsolutePathname(url.pathname)}${url.search}${url.hash}`;
|
|
15
15
|
}
|
|
16
|
-
function toStreamedRedirectVisibleAppHref(
|
|
17
|
-
|
|
18
|
-
return `${url.pathname}${url.search}${url.hash}`;
|
|
16
|
+
function toStreamedRedirectVisibleAppHref(url) {
|
|
17
|
+
return `${toPathAbsolutePathname(url.pathname)}${url.search}${url.hash}`;
|
|
19
18
|
}
|
|
20
19
|
function resolveRedirectLifecycleHopFromTarget(options) {
|
|
21
20
|
if (options.targetUrl.origin !== options.origin) return {
|
|
@@ -53,10 +52,11 @@ function resolveRscRedirectLifecycleHop(options) {
|
|
|
53
52
|
});
|
|
54
53
|
}
|
|
55
54
|
function resolveStreamedRscRedirectLifecycleHop(options) {
|
|
56
|
-
const
|
|
55
|
+
const requestedUrl = new URL(options.currentHref, options.origin);
|
|
56
|
+
const streamedRedirectUrl = new URL(options.streamedRedirectTarget, requestedUrl);
|
|
57
57
|
return resolveRedirectLifecycleHopFromTarget({
|
|
58
58
|
...options,
|
|
59
|
-
redirectedHref: toStreamedRedirectVisibleAppHref(
|
|
59
|
+
redirectedHref: toStreamedRedirectVisibleAppHref(streamedRedirectUrl),
|
|
60
60
|
targetUrl: streamedRedirectUrl
|
|
61
61
|
});
|
|
62
62
|
}
|
|
@@ -21,6 +21,8 @@ type ActionRedirectTarget = {
|
|
|
21
21
|
export type ClientServerActionDeps = {
|
|
22
22
|
basePath: string;
|
|
23
23
|
clearClientNavigationCaches(): void;
|
|
24
|
+
/** Evict only the cached navigation data that may be dynamic. */
|
|
25
|
+
clearDynamicClientNavigationCaches(): void;
|
|
24
26
|
clientRscCompatibilityId: string | null;
|
|
25
27
|
commitSameUrlNavigatePayload(elements: Promise<AppElements>, actionInitiation: ClientServerActionInitiation, returnValue: ServerActionResult["returnValue"] | undefined, revalidation: ServerActionRevalidationKind, renderedPathAndSearch: string | null): Promise<unknown>;
|
|
26
28
|
navigationPlanner: typeof navigationPlanner;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { hasBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
|
|
3
3
|
import { DANGEROUS_URL_BLOCK_MESSAGE, isDangerousScheme } from "../shims/url-safety.js";
|
|
4
|
+
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl, toPathAbsolutePathname } from "./app-rsc-cache-busting.js";
|
|
5
|
+
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
4
6
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
5
7
|
import "./app-elements.js";
|
|
6
|
-
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createServerActionRequestUrl } from "./app-rsc-cache-busting.js";
|
|
7
|
-
import { throwOnServerActionNotFound } from "./server-action-not-found.js";
|
|
8
8
|
import { createServerActionResultFacts, isServerActionResult, normalizeServerActionThrownValue, parseServerActionRevalidationHeader, readInvalidServerActionResponseError, shouldClearClientNavigationCachesForServerActionResult, shouldSyncServerActionHttpFallbackHead } from "./app-browser-action-result.js";
|
|
9
9
|
import { parseRenderedPathAndSearchHeader } from "../shims/navigation.js";
|
|
10
10
|
import { resolveServerActionRequestState } from "./app-browser-state.js";
|
|
@@ -49,7 +49,7 @@ var ServerActionRedirectError = class extends Error {
|
|
|
49
49
|
constructor(target) {
|
|
50
50
|
super("NEXT_REDIRECT");
|
|
51
51
|
const redirectUrl = new URL(target.href, window.location.href);
|
|
52
|
-
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
52
|
+
const redirectHref = toPathAbsolutePathname(redirectUrl.pathname) + redirectUrl.search + redirectUrl.hash;
|
|
53
53
|
const redirectType = target.type === "push" ? "push" : "replace";
|
|
54
54
|
this.digest = `NEXT_REDIRECT;${redirectType};${redirectHref};${target.status};`;
|
|
55
55
|
}
|
|
@@ -89,7 +89,8 @@ async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
|
89
89
|
const actionResultDecision = deps.navigationPlanner.classifyServerActionResult(actionResultFacts);
|
|
90
90
|
if (applyServerActionResultDecision(actionResultDecision, () => deps.clearClientNavigationCaches(), (url, historyMode) => deps.performHardNavigation(url, historyMode))) return;
|
|
91
91
|
const revalidation = parseServerActionRevalidationHeader(fetchResponse.headers);
|
|
92
|
-
if (revalidation
|
|
92
|
+
if (revalidation === "staticAndDynamic") deps.clearClientNavigationCaches();
|
|
93
|
+
else if (revalidation === "dynamicOnly") deps.clearDynamicClientNavigationCaches();
|
|
93
94
|
const invalidResponseError = await readInvalidServerActionResponseError(fetchResponse.clone(), actionRedirectTarget !== null);
|
|
94
95
|
if (invalidResponseError) throw invalidResponseError;
|
|
95
96
|
if (actionRedirectTarget && !fetchResponseIsRsc) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { CacheEntryReuseProof } from "./cache-proof.js";
|
|
3
|
-
import { AppElements, AppElementsInterception, AppElementsSlotBinding
|
|
3
|
+
import { AppElements, AppElementsInterception, AppElementsSlotBinding } from "./app-elements-wire.js";
|
|
4
4
|
import "./app-elements.js";
|
|
5
|
+
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
5
6
|
import { NavigationTrace } from "./navigation-trace.js";
|
|
6
7
|
import { OperationLane } from "./operation-token.js";
|
|
7
8
|
import "./navigation-planner.js";
|
|
8
9
|
import { BfcacheIdMap, HistoryTraversalIntent, createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
9
10
|
import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
10
|
-
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
11
11
|
//#region src/server/app-browser-state.d.ts
|
|
12
12
|
type OperationRecordBase = {
|
|
13
13
|
id: number;
|
|
@@ -30,7 +30,6 @@ export type AppRouterState = {
|
|
|
30
30
|
elements: AppElements;
|
|
31
31
|
interception: AppElementsInterception | null;
|
|
32
32
|
interceptionContext: string | null;
|
|
33
|
-
layoutFlags: LayoutFlags;
|
|
34
33
|
layoutIds: readonly string[];
|
|
35
34
|
previousNextUrl: string | null;
|
|
36
35
|
renderId: number;
|
|
@@ -46,7 +45,6 @@ export type AppRouterAction = {
|
|
|
46
45
|
elements: AppElements;
|
|
47
46
|
interception: AppElementsInterception | null;
|
|
48
47
|
interceptionContext: string | null;
|
|
49
|
-
layoutFlags: LayoutFlags;
|
|
50
48
|
layoutIds: readonly string[];
|
|
51
49
|
navigationSnapshot: ClientNavigationRenderSnapshot;
|
|
52
50
|
operation: PendingOperationRecord;
|
|
@@ -3,17 +3,18 @@ import { VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } from
|
|
|
3
3
|
import { NEXT_ACTION_HEADER, RSC_ACTION_HEADER } from "./headers.js";
|
|
4
4
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
5
5
|
import { normalizePath } from "./normalize-path.js";
|
|
6
|
+
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
6
7
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
7
8
|
import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
|
|
8
|
-
import { bindAppElementsRenderedSearch } from "../shims/slot.js";
|
|
9
|
-
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
10
9
|
import { createBfcacheSegmentIdentityMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
11
|
-
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
12
10
|
import { createAppOwnedHistoryState, createExternalHistoryStatePreservingMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, createHistoryStateWithTreeSnapshotId, isExternalHistoryState, isHistoryStateBfcacheVersionCurrent, readHistoryStateActiveRoutePaths, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveActiveRoutePaths, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
13
11
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
14
12
|
import { verifyOperationTokenForCommit } from "./operation-token.js";
|
|
15
13
|
import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
|
|
16
14
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
15
|
+
import { holdsSkippedLayouts } from "./app-mounted-layouts.js";
|
|
16
|
+
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
17
|
+
import { bindAppElementsRenderedSearch } from "../shims/slot.js";
|
|
17
18
|
//#region src/server/app-browser-state.ts
|
|
18
19
|
const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
|
|
19
20
|
const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
|
|
@@ -239,6 +240,11 @@ function mapNavigationDecisionToPendingDisposition(decision) {
|
|
|
239
240
|
function mergeSkippedLayoutPreservation(options) {
|
|
240
241
|
if (options.decision.disposition !== "dispatch") return options.decision;
|
|
241
242
|
if (options.pending.skippedLayoutIds.length === 0) return options.decision;
|
|
243
|
+
if (!holdsSkippedLayouts(options.currentState, options.pending.action.elements)) return {
|
|
244
|
+
disposition: "hard-navigate",
|
|
245
|
+
preserveElementIds: [],
|
|
246
|
+
trace: options.decision.trace
|
|
247
|
+
};
|
|
242
248
|
const currentLayoutIds = new Set(options.currentState.layoutIds);
|
|
243
249
|
const targetLayoutIds = new Set(options.pending.action.layoutIds);
|
|
244
250
|
const preserveElementIds = [...options.decision.preserveElementIds];
|
|
@@ -303,7 +309,6 @@ function createPendingNavigationCommitFromElements(options) {
|
|
|
303
309
|
interception: metadata.interception,
|
|
304
310
|
interceptionContext: metadata.interceptionContext,
|
|
305
311
|
layoutIds: metadata.layoutIds,
|
|
306
|
-
layoutFlags: metadata.layoutFlags,
|
|
307
312
|
slotBindings: metadata.slotBindings,
|
|
308
313
|
navigationSnapshot: options.navigationSnapshot,
|
|
309
314
|
operation: createOperationRecord({
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { addBasePathToPathname, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
3
3
|
import { normalizePath } from "./normalize-path.js";
|
|
4
|
-
import { APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
4
|
+
import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
5
5
|
import "./app-elements.js";
|
|
6
|
+
import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
|
|
6
7
|
//#region src/server/app-browser-supplemental-refresh.ts
|
|
7
8
|
const SUPPLEMENTAL_REFRESH_TIMEOUT_MS = 1e4;
|
|
8
9
|
var SupplementalRefreshError = class extends Error {
|
|
@@ -67,6 +68,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
67
68
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: refreshedMetadata.layoutIds })
|
|
68
69
|
};
|
|
69
70
|
for (const binding of retainedBindings) merged[binding.slotId] = currentElements[binding.slotId];
|
|
71
|
+
copySlotIdentities(merged, refreshedElements, currentElements, retainedBindings.map((binding) => binding.slotId));
|
|
70
72
|
if (promotedBindings.length === 1) merged[promotedBindings[0].slotId] = refreshedElements[refreshedChildrenBindings[0].slotId];
|
|
71
73
|
copyRefreshedBranchElements(merged, currentElements, { overwrite: false });
|
|
72
74
|
return merged;
|
|
@@ -79,6 +81,7 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
79
81
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
|
|
80
82
|
};
|
|
81
83
|
for (const binding of refreshedBindings) merged[binding.slotId] = refreshedElements[binding.slotId];
|
|
84
|
+
copySlotIdentities(merged, currentElements, refreshedElements, refreshedBindings.map((binding) => binding.slotId));
|
|
82
85
|
copyRefreshedBranchElements(merged, refreshedElements);
|
|
83
86
|
return merged;
|
|
84
87
|
}
|
|
@@ -93,9 +96,21 @@ function mergeRefreshedParallelSlot(currentElements, refreshedElements) {
|
|
|
93
96
|
[interception.slotId]: refreshedSlot,
|
|
94
97
|
[APP_SLOT_BINDINGS_KEY]: normalizeAppElementsSlotBindings(slotBindings, { layoutIds: currentMetadata.layoutIds })
|
|
95
98
|
};
|
|
99
|
+
copySlotIdentities(merged, currentElements, refreshedElements, [interception.slotId]);
|
|
96
100
|
copyRefreshedBranchElements(merged, refreshedElements);
|
|
97
101
|
return merged;
|
|
98
102
|
}
|
|
103
|
+
function copySlotIdentities(target, baseElements, slotElements, slotIds) {
|
|
104
|
+
const isSlotSegment = (id) => slotIds.some((slotId) => id === slotId || isNestedBfcacheSlotSegmentIdFor(id, slotId));
|
|
105
|
+
const isNestedSegment = (id) => !slotIds.includes(id) && isSlotSegment(id);
|
|
106
|
+
for (const id of Object.keys(baseElements)) if (isNestedSegment(id)) delete target[id];
|
|
107
|
+
for (const [id, element] of Object.entries(slotElements)) if (isNestedSegment(id)) target[id] = element;
|
|
108
|
+
const identities = {};
|
|
109
|
+
for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(baseElements).bfcacheSegmentIdentities)) if (!isSlotSegment(id)) identities[id] = identity;
|
|
110
|
+
for (const [id, identity] of Object.entries(AppElementsWire.readMetadata(slotElements).bfcacheSegmentIdentities)) if (isSlotSegment(id)) identities[id] = identity;
|
|
111
|
+
if (Object.keys(identities).length > 0) target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY] = identities;
|
|
112
|
+
else delete target[APP_BFCACHE_SEGMENT_IDENTITIES_KEY];
|
|
113
|
+
}
|
|
99
114
|
function copyRefreshedBranchElements(target, refreshedElements, options = {}) {
|
|
100
115
|
for (const [elementId, element] of Object.entries(refreshedElements)) {
|
|
101
116
|
const parsed = AppElementsWire.parseElementKey(elementId);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { BrowserRouteManifest } from "../routing/browser-route-manifest.js";
|
|
2
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
3
3
|
import "./app-elements.js";
|
|
4
|
+
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
4
5
|
import { NavigationTrace } from "./navigation-trace.js";
|
|
5
6
|
import { OperationLane } from "./operation-token.js";
|
|
6
|
-
import { ClientNavigationRenderSnapshot } from "../shims/navigation.js";
|
|
7
7
|
import { AppNavigationPayloadOrigin, AppRouterAction, AppRouterState, PendingNavigationCommit } from "./app-browser-state.js";
|
|
8
8
|
//#region src/server/app-browser-visible-commit.d.ts
|
|
9
9
|
type VisibleCommitDecision = {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
|
-
import { mergeElements } from "../shims/slot.js";
|
|
4
|
-
import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
|
|
5
3
|
import { createBfcacheSegmentIdentityMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
6
4
|
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
5
|
+
import { mergeElements } from "../shims/slot.js";
|
|
7
6
|
import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
|
|
7
|
+
import { resolveAppPageRouteStateKey } from "./app-page-segment-state.js";
|
|
8
8
|
//#region src/server/app-browser-visible-commit.ts
|
|
9
9
|
const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
|
|
10
10
|
function hasSameServerTemplateSeedIdentity(id, currentSnapshot, nextSnapshot) {
|
|
@@ -87,11 +87,11 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
87
87
|
const hmrUniquePreserveElementIds = hmrPreserveElementIds.length > 1 ? [...new Set(hmrPreserveElementIds)] : hmrPreserveElementIds;
|
|
88
88
|
const preserveElementIds = action.operation.lane === "hmr" ? hmrUniquePreserveElementIds : bfcacheCompatiblePreserveElementIds;
|
|
89
89
|
const preserveTemplateIds = action.reuseCurrentBfcacheIds && (action.operation.lane === "navigation" || action.operation.lane === "traverse" || action.operation.lane === "server-action") ? Object.keys(state.elements).filter((id) => Object.hasOwn(action.elements, id) && hasSameServerTemplateSeedIdentity(id, state.navigationSnapshot, action.navigationSnapshot)) : [];
|
|
90
|
-
const mergedPreserveElementIds = preserveTemplateIds.length === 0 ? preserveElementIds : [.../* @__PURE__ */ new Set([...preserveElementIds, ...preserveTemplateIds])];
|
|
91
90
|
const mergedElements = mergeElements(state.elements, action.elements, {
|
|
92
91
|
clearAbsentSlots: action.type === "traverse" || !action.reuseCurrentBfcacheIds,
|
|
93
92
|
preserveAbsentSlots: action.reuseCurrentBfcacheIds && commit.decision.preserveAbsentSlots,
|
|
94
|
-
preserveElementIds
|
|
93
|
+
preserveElementIds,
|
|
94
|
+
preserveElementSeedIds: preserveTemplateIds,
|
|
95
95
|
preservePreviousSlotIds: effectivePreservePreviousSlotIds
|
|
96
96
|
});
|
|
97
97
|
return commitVisibleRouterState(state, {
|
|
@@ -105,7 +105,6 @@ function reduceApprovedVisibleCommitState(state, commit) {
|
|
|
105
105
|
elements: mergedElements,
|
|
106
106
|
interception: action.interception,
|
|
107
107
|
interceptionContext: action.interceptionContext,
|
|
108
|
-
layoutFlags: mergeLayoutFlags(state.layoutFlags, action.layoutFlags, preserveElementIds),
|
|
109
108
|
layoutIds: action.layoutIds,
|
|
110
109
|
navigationSnapshot: action.navigationSnapshot,
|
|
111
110
|
previousNextUrl: action.previousNextUrl,
|
|
@@ -145,15 +144,6 @@ function createVisibleCommitDecision(trace = createNavigationTrace(NavigationTra
|
|
|
145
144
|
trace
|
|
146
145
|
};
|
|
147
146
|
}
|
|
148
|
-
function mergeLayoutFlags(previousFlags, nextFlags, preserveElementIds) {
|
|
149
|
-
const merged = { ...nextFlags };
|
|
150
|
-
for (const id of preserveElementIds) {
|
|
151
|
-
if (Object.hasOwn(merged, id)) continue;
|
|
152
|
-
const value = previousFlags[id];
|
|
153
|
-
if (value) merged[id] = value;
|
|
154
|
-
}
|
|
155
|
-
return merged;
|
|
156
|
-
}
|
|
157
147
|
function createApprovedVisibleCommit(options) {
|
|
158
148
|
return {
|
|
159
149
|
[approvedVisibleCommitBrand]: true,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
2
2
|
import { CacheEntryReuseProof } from "./cache-proof.js";
|
|
3
|
-
import { ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
|
|
4
3
|
import { BfcacheSegmentIdentity } from "./bfcache-identity.js";
|
|
5
4
|
import { compareStrings } from "../utils/compare.js";
|
|
6
5
|
import { AppElementsWireElementKey } from "./app-elements-wire-key.js";
|
|
@@ -12,7 +11,6 @@ export declare const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
|
12
11
|
export declare const APP_INTERCEPTION_KEY = "__interception";
|
|
13
12
|
export declare const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
14
13
|
export declare const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
15
|
-
export declare const APP_LAYOUT_FLAGS_KEY = "__layoutFlags";
|
|
16
14
|
export declare const APP_ROUTE_KEY = "__route";
|
|
17
15
|
export declare const APP_ROOT_LAYOUT_KEY = "__rootLayout";
|
|
18
16
|
export declare const APP_SKIPPED_LAYOUT_IDS_KEY = "__skippedLayoutIds";
|
|
@@ -51,28 +49,10 @@ export declare const compareAppElementsSlotIds: typeof compareStrings;
|
|
|
51
49
|
export declare function normalizeAppElementsSlotBindings(slotBindings: readonly AppElementsSlotBinding[], options?: {
|
|
52
50
|
layoutIds?: readonly string[];
|
|
53
51
|
}): readonly AppElementsSlotBinding[];
|
|
54
|
-
export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null |
|
|
55
|
-
type AppWireElementValue = ReactNode | string | null |
|
|
52
|
+
export type AppElementValue = ReactNode | typeof UNMATCHED_SLOT | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
|
|
53
|
+
type AppWireElementValue = ReactNode | string | null | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | readonly string[] | readonly AppElementsSlotBinding[];
|
|
56
54
|
export type AppElements = Readonly<Record<string, AppElementValue>>;
|
|
57
55
|
export type AppWireElements = Readonly<Record<string, AppWireElementValue>>;
|
|
58
|
-
/**
|
|
59
|
-
* Per-layout static/dynamic flags. `"s"` = static (skippable on next nav);
|
|
60
|
-
* `"d"` = dynamic (must always render).
|
|
61
|
-
*
|
|
62
|
-
* Lifecycle (partial — later PRs extend this):
|
|
63
|
-
*
|
|
64
|
-
* 1. PROBE — probeAppPageLayouts (server/app-page-execution.ts) returns
|
|
65
|
-
* LayoutFlags for every layout in the route at render time.
|
|
66
|
-
*
|
|
67
|
-
* 2. ATTACH — AppElementsWire.encodeOutgoingPayload writes `__layoutFlags`
|
|
68
|
-
* into the outgoing App Router payload record.
|
|
69
|
-
*
|
|
70
|
-
* 3. WIRE — renderToReadableStream serializes the record as RSC row 0.
|
|
71
|
-
*
|
|
72
|
-
* 4. PARSE — AppElementsWire.readMetadata extracts layoutFlags from the
|
|
73
|
-
* wire payload on the client side.
|
|
74
|
-
*/
|
|
75
|
-
export type LayoutFlags = Readonly<Record<string, "s" | "d">>;
|
|
76
56
|
export type AppElementsBfcacheSegmentIdentities = Readonly<Record<string, BfcacheSegmentIdentity>>;
|
|
77
57
|
type AppElementsMetadata = {
|
|
78
58
|
artifactCompatibility: ArtifactCompatibilityEnvelope;
|
|
@@ -81,7 +61,6 @@ type AppElementsMetadata = {
|
|
|
81
61
|
interception: AppElementsInterception | null;
|
|
82
62
|
interceptionContext: string | null;
|
|
83
63
|
layoutIds: readonly string[];
|
|
84
|
-
layoutFlags: LayoutFlags;
|
|
85
64
|
routeId: string;
|
|
86
65
|
rootLayoutTreePath: string | null;
|
|
87
66
|
bfcacheSegmentIdentities: AppElementsBfcacheSegmentIdentities;
|
|
@@ -113,11 +92,11 @@ type AppElementsWireMetadataEntries = Readonly<{
|
|
|
113
92
|
}>;
|
|
114
93
|
/**
|
|
115
94
|
* The outgoing wire payload shape. Includes ReactNode values for the
|
|
116
|
-
* rendered tree plus metadata values
|
|
117
|
-
*
|
|
95
|
+
* rendered tree plus metadata values attached under known keys (e.g.
|
|
96
|
+
* __artifactCompatibility). Distinct from AppElements / AppWireElements
|
|
118
97
|
* which only carry render-time values.
|
|
119
98
|
*/
|
|
120
|
-
export type AppOutgoingElements = Readonly<Record<string, ReactNode |
|
|
99
|
+
export type AppOutgoingElements = Readonly<Record<string, ReactNode | AppElementsBfcacheSegmentIdentities | ArtifactCompatibilityEnvelope | CacheEntryReuseProof | AppElementsInterception | number | readonly string[] | readonly AppElementsSlotBinding[]>>;
|
|
121
100
|
type AppElementsWireKeys = {
|
|
122
101
|
readonly artifactCompatibility: typeof APP_ARTIFACT_COMPATIBILITY_KEY;
|
|
123
102
|
readonly cacheEntryReuseProof: typeof APP_CACHE_ENTRY_REUSE_PROOF_KEY;
|
|
@@ -125,7 +104,6 @@ type AppElementsWireKeys = {
|
|
|
125
104
|
readonly interception: typeof APP_INTERCEPTION_KEY;
|
|
126
105
|
readonly interceptionContext: typeof APP_INTERCEPTION_CONTEXT_KEY;
|
|
127
106
|
readonly layoutIds: typeof APP_LAYOUT_IDS_KEY;
|
|
128
|
-
readonly layoutFlags: typeof APP_LAYOUT_FLAGS_KEY;
|
|
129
107
|
readonly rootLayout: typeof APP_ROOT_LAYOUT_KEY;
|
|
130
108
|
readonly route: typeof APP_ROUTE_KEY;
|
|
131
109
|
readonly bfcacheSegmentIdentities: typeof APP_BFCACHE_SEGMENT_IDENTITIES_KEY;
|
|
@@ -145,8 +123,6 @@ type AppElementsWireCodec = {
|
|
|
145
123
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
146
124
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
147
125
|
dynamicStaleTimeSeconds?: number;
|
|
148
|
-
layoutFlags: LayoutFlags;
|
|
149
|
-
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
150
126
|
}): ReactNode | AppOutgoingElements;
|
|
151
127
|
encodePageId(routePath: string, interceptionContext: string | null): string;
|
|
152
128
|
encodeRouteId(routePath: string, interceptionContext: string | null): string;
|
|
@@ -155,9 +131,6 @@ type AppElementsWireCodec = {
|
|
|
155
131
|
isSlotId(key: string): boolean;
|
|
156
132
|
parseElementKey(key: string): AppElementsWireElementKey | null;
|
|
157
133
|
readMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
158
|
-
withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
|
|
159
|
-
[APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
|
|
160
|
-
};
|
|
161
134
|
};
|
|
162
135
|
export declare function normalizeAppElements(elements: AppWireElements): AppElements;
|
|
163
136
|
/**
|
|
@@ -165,21 +138,16 @@ export declare function normalizeAppElements(elements: AppWireElements): AppElem
|
|
|
165
138
|
* Used to distinguish the App Router payload object from bare React elements at
|
|
166
139
|
* the render boundary. Narrows to `Readonly<Record<string, unknown>>` because
|
|
167
140
|
* the outgoing payload carries heterogeneous values (ReactNodes for the rendered
|
|
168
|
-
* tree, plus metadata like `
|
|
141
|
+
* tree, plus metadata like `__artifactCompatibility`, a plain object). Delegates
|
|
169
142
|
* to React's canonical `isValidElement` so we don't depend on React's internal
|
|
170
143
|
* `$$typeof` marker scheme.
|
|
171
144
|
*/
|
|
172
145
|
export declare function isAppElementsRecord(value: unknown): value is Readonly<Record<string, unknown>>;
|
|
173
|
-
export declare function withLayoutFlags<T extends Record<string, unknown>>(elements: T, layoutFlags: LayoutFlags): T & {
|
|
174
|
-
[APP_LAYOUT_FLAGS_KEY]: LayoutFlags;
|
|
175
|
-
};
|
|
176
146
|
export declare function buildOutgoingAppPayload(input: {
|
|
177
147
|
element: ReactNode | AppElements;
|
|
178
148
|
artifactCompatibility?: ArtifactCompatibilityEnvelope;
|
|
179
149
|
cacheEntryReuseProof?: CacheEntryReuseProof;
|
|
180
150
|
dynamicStaleTimeSeconds?: number;
|
|
181
|
-
layoutFlags: LayoutFlags;
|
|
182
|
-
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
183
151
|
}): ReactNode | AppOutgoingElements;
|
|
184
152
|
export declare function readAppElementsMetadata(elements: Readonly<Record<string, unknown>>): AppElementsMetadata;
|
|
185
153
|
export declare const AppElementsWire: AppElementsWireCodec;
|