@remix-run/router
Advanced tools
Comparing version 0.2.0-pre.8 to 0.2.0-pre.9
# @remix-run/router | ||
## 0.2.0-pre.9 | ||
### Patch Changes | ||
- fix: rename resetScroll -> preventScrollReset (#9199) | ||
- fix: Await should fallback on route params navigations (#9181) | ||
- fix: proxy defer resolve/reject values through tracked promises (#9200) | ||
## 0.2.0-pre.8 | ||
@@ -4,0 +12,0 @@ |
@@ -5,3 +5,3 @@ import type { BrowserHistoryOptions, HashHistoryOptions, MemoryHistoryOptions } from "./history"; | ||
export type { ActionFunction, ActionFunctionArgs, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticRouteMatch, AgnosticRouteObject, TrackedPromise, FormEncType, FormMethod, JsonFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, PathMatch, PathPattern, RedirectFunction, ShouldRevalidateFunction, Submission, } from "./utils"; | ||
export { ErrorResponse, defer, generatePath, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, warning, } from "./utils"; | ||
export { AbortedDeferredError, ErrorResponse, defer, generatePath, getToPathname, invariant, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, resolvePath, resolveTo, stripBasename, warning, } from "./utils"; | ||
export type { BrowserHistory, HashHistory, History, InitialEntry, Location, MemoryHistory, Path, To, } from "./history"; | ||
@@ -8,0 +8,0 @@ export { Action, createBrowserHistory, createPath, createHashHistory, createMemoryHistory, parsePath, } from "./history"; |
@@ -121,6 +121,6 @@ import { History, Location, To } from "./history"; | ||
/** | ||
* Indicate whether this navigation should reset the scroll position if we | ||
* are unable to restore the scroll position | ||
* Indicate whether this navigation should skip resetting the scroll position | ||
* if we are unable to restore the scroll position | ||
*/ | ||
resetScrollPosition: boolean; | ||
preventScrollReset: boolean; | ||
/** | ||
@@ -218,3 +218,3 @@ * Tracks the state of the current navigation | ||
state?: any; | ||
resetScroll?: boolean; | ||
preventScrollReset?: boolean; | ||
}; | ||
@@ -221,0 +221,0 @@ /** |
@@ -298,5 +298,9 @@ import type { Location, Path, To } from "./history"; | ||
} | ||
export declare class AbortedDeferredError extends Error { | ||
} | ||
export declare class DeferredData { | ||
private pendingKeys; | ||
private cancelled; | ||
private controller; | ||
private abortPromise; | ||
private unlistenAbortSignal; | ||
private subscriber?; | ||
@@ -303,0 +307,0 @@ data: Record<string, unknown>; |
@@ -38,2 +38,3 @@ import type { | ||
export { | ||
AbortedDeferredError, | ||
ErrorResponse, | ||
@@ -40,0 +41,0 @@ defer, |
{ | ||
"name": "@remix-run/router", | ||
"version": "0.2.0-pre.8", | ||
"version": "0.2.0-pre.9", | ||
"description": "Nested/Data-driven/Framework-agnostic Routing", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -48,4 +48,4 @@ # Router | ||
restoreScrollPosition: number | false | null; | ||
// Proxied `resetScroll` value passed to router.navigate() (default true) | ||
resetScrollPosition: boolean; | ||
// Proxied `preventScrollReset` value passed to router.navigate() (default false) | ||
preventScrollReset: boolean; | ||
// Data from the loaders for the current matches | ||
@@ -52,0 +52,0 @@ loaderData: RouteData; |
51
utils.ts
@@ -234,3 +234,3 @@ import type { Location, Path, To } from "./history"; | ||
// Walk the route tree generating unique IDs where necessary so we are working | ||
// solely with DataRouteObject's within the Router | ||
// solely with AgnosticDataRouteObject's within the Router | ||
export function convertRoutesToDataRoutes( | ||
@@ -899,5 +899,9 @@ routes: AgnosticRouteObject[], | ||
export class AbortedDeferredError extends Error {} | ||
export class DeferredData { | ||
private pendingKeys: Set<string | number> = new Set<string | number>(); | ||
private cancelled: boolean = false; | ||
private controller: AbortController; | ||
private abortPromise: Promise<void>; | ||
private unlistenAbortSignal: () => void; | ||
private subscriber?: (aborted: boolean) => void = undefined; | ||
@@ -911,2 +915,14 @@ data: Record<string, unknown>; | ||
); | ||
// Set up an AbortController + Promise we can race against to exit early | ||
// cancellation | ||
let reject: (e: AbortedDeferredError) => void; | ||
this.abortPromise = new Promise((_, r) => (reject = r)); | ||
this.controller = new AbortController(); | ||
let onAbort = () => | ||
reject(new AbortedDeferredError("Deferred data aborted")); | ||
this.unlistenAbortSignal = () => | ||
this.controller.signal.removeEventListener("abort", onAbort); | ||
this.controller.signal.addEventListener("abort", onAbort); | ||
this.data = Object.entries(data).reduce( | ||
@@ -933,6 +949,11 @@ (acc, [key, value]) => | ||
// _data/_error props upon resolve/reject | ||
let promise: TrackedPromise = value.then( | ||
let promise: TrackedPromise = Promise.race([value, this.abortPromise]).then( | ||
(data) => this.onSettle(promise, key, null, data as unknown), | ||
(error) => this.onSettle(promise, key, error as unknown) | ||
); | ||
// Register rejection listeners to avoid uncaught promise rejections on | ||
// errors or aborted deferred values | ||
promise.catch(() => {}); | ||
Object.defineProperty(promise, "_tracked", { get: () => true }); | ||
@@ -947,15 +968,27 @@ return promise; | ||
data?: unknown | ||
): void { | ||
if (this.cancelled) { | ||
return; | ||
): unknown { | ||
if ( | ||
this.controller.signal.aborted && | ||
error instanceof AbortedDeferredError | ||
) { | ||
this.unlistenAbortSignal(); | ||
return Promise.reject(error); | ||
} | ||
this.pendingKeys.delete(key); | ||
if (this.done) { | ||
// Nothing left to abort! | ||
this.unlistenAbortSignal(); | ||
} | ||
if (error) { | ||
Object.defineProperty(promise, "_error", { get: () => error }); | ||
} else { | ||
Object.defineProperty(promise, "_data", { get: () => data }); | ||
this.subscriber?.(false); | ||
return Promise.reject(error); | ||
} | ||
Object.defineProperty(promise, "_data", { get: () => data }); | ||
this.subscriber?.(false); | ||
return data; | ||
} | ||
@@ -968,3 +1001,3 @@ | ||
cancel() { | ||
this.cancelled = true; | ||
this.controller.abort(); | ||
this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k)); | ||
@@ -971,0 +1004,0 @@ this.subscriber?.(true); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
859030
10313