@remix-run/router 0.0.0-experimental-d90c8fb3 → 0.0.0-experimental-e7ce8959

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remix-run/router",
3
- "version": "0.0.0-experimental-d90c8fb3",
3
+ "version": "0.0.0-experimental-e7ce8959",
4
4
  "description": "Nested/Data-driven/Framework-agnostic Routing",
5
5
  "keywords": [
6
6
  "remix",
package/router.ts CHANGED
@@ -2834,6 +2834,7 @@ export const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
2834
2834
  */
2835
2835
  export interface StaticHandlerFutureConfig {
2836
2836
  v7_relativeSplatPath: boolean;
2837
+ v7_throwAbortReason: boolean;
2837
2838
  }
2838
2839
 
2839
2840
  export interface CreateStaticHandlerOptions {
@@ -2872,6 +2873,7 @@ export function createStaticHandler(
2872
2873
  // Config driven behavior flags
2873
2874
  let future: StaticHandlerFutureConfig = {
2874
2875
  v7_relativeSplatPath: false,
2876
+ v7_throwAbortReason: false,
2875
2877
  ...(opts ? opts.future : null),
2876
2878
  };
2877
2879
 
@@ -3141,10 +3143,7 @@ export function createStaticHandler(
3141
3143
  );
3142
3144
 
3143
3145
  if (request.signal.aborted) {
3144
- let method = isRouteRequest ? "queryRoute" : "query";
3145
- throw new Error(
3146
- `${method}() call aborted: ${request.method} ${request.url}`
3147
- );
3146
+ throwStaticHandlerAbortedError(request, isRouteRequest, future);
3148
3147
  }
3149
3148
  }
3150
3149
 
@@ -3312,10 +3311,7 @@ export function createStaticHandler(
3312
3311
  ]);
3313
3312
 
3314
3313
  if (request.signal.aborted) {
3315
- let method = isRouteRequest ? "queryRoute" : "query";
3316
- throw new Error(
3317
- `${method}() call aborted: ${request.method} ${request.url}`
3318
- );
3314
+ throwStaticHandlerAbortedError(request, isRouteRequest, future);
3319
3315
  }
3320
3316
 
3321
3317
  // Process and commit output from loaders
@@ -3380,6 +3376,19 @@ export function getStaticContextFromError(
3380
3376
  return newContext;
3381
3377
  }
3382
3378
 
3379
+ function throwStaticHandlerAbortedError(
3380
+ request: Request,
3381
+ isRouteRequest: boolean,
3382
+ future: StaticHandlerFutureConfig
3383
+ ) {
3384
+ if (future.v7_throwAbortReason && request.signal.reason !== undefined) {
3385
+ throw request.signal.reason;
3386
+ }
3387
+
3388
+ let method = isRouteRequest ? "queryRoute" : "query";
3389
+ throw new Error(`${method}() call aborted: ${request.method} ${request.url}`);
3390
+ }
3391
+
3383
3392
  function isSubmissionNavigation(
3384
3393
  opts: BaseNavigateOrFetchOptions
3385
3394
  ): opts is SubmissionNavigateOptions {
package/utils.ts CHANGED
@@ -485,14 +485,16 @@ export function matchRoutes<
485
485
 
486
486
  let matches = null;
487
487
  for (let i = 0; matches == null && i < branches.length; ++i) {
488
- // Incoming pathnames are generally encoded from either window.location
489
- // or from router.navigate, but we want to match against the unencoded
490
- // paths in the route definitions. Memory router locations won't be
491
- // encoded here but there also shouldn't be anything to decode so this
492
- // should be a safe operation. This avoids needing matchRoutes to be
493
- // history-aware.
494
- let decoded = decodePath(pathname);
495
- matches = matchRouteBranch<string, RouteObjectType>(branches[i], decoded);
488
+ matches = matchRouteBranch<string, RouteObjectType>(
489
+ branches[i],
490
+ // Incoming pathnames are generally encoded from either window.location
491
+ // or from router.navigate, but we want to match against the unencoded
492
+ // paths in the route definitions. Memory router locations won't be
493
+ // encoded here but there also shouldn't be anything to decode so this
494
+ // should be a safe operation. This avoids needing matchRoutes to be
495
+ // history-aware.
496
+ safelyDecodeURI(pathname)
497
+ );
496
498
  }
497
499
 
498
500
  return matches;
@@ -928,7 +930,7 @@ export function matchPath<
928
930
  if (isOptional && !value) {
929
931
  memo[paramName] = undefined;
930
932
  } else {
931
- memo[paramName] = (value || "").replace(/%2F/g, "/");
933
+ memo[paramName] = safelyDecodeURIComponent(value || "", paramName);
932
934
  }
933
935
  return memo;
934
936
  },
@@ -1000,12 +1002,9 @@ function compilePath(
1000
1002
  return [matcher, params];
1001
1003
  }
1002
1004
 
1003
- function decodePath(value: string) {
1005
+ function safelyDecodeURI(value: string) {
1004
1006
  try {
1005
- return value
1006
- .split("/")
1007
- .map((v) => decodeURIComponent(v).replace(/\//g, "%2F"))
1008
- .join("/");
1007
+ return decodeURI(value);
1009
1008
  } catch (error) {
1010
1009
  warning(
1011
1010
  false,
@@ -1018,6 +1017,21 @@ function decodePath(value: string) {
1018
1017
  }
1019
1018
  }
1020
1019
 
1020
+ function safelyDecodeURIComponent(value: string, paramName: string) {
1021
+ try {
1022
+ return decodeURIComponent(value);
1023
+ } catch (error) {
1024
+ warning(
1025
+ false,
1026
+ `The value for the URL param "${paramName}" will not be decoded because` +
1027
+ ` the string "${value}" is a malformed URL segment. This is probably` +
1028
+ ` due to a bad percent encoding (${error}).`
1029
+ );
1030
+
1031
+ return value;
1032
+ }
1033
+ }
1034
+
1021
1035
  /**
1022
1036
  * @private
1023
1037
  */