@remix-run/router 1.6.2 → 1.6.3

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/router.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.6.2
2
+ * @remix-run/router v1.6.3
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -12,14 +12,12 @@ function _extends() {
12
12
  _extends = Object.assign ? Object.assign.bind() : function (target) {
13
13
  for (var i = 1; i < arguments.length; i++) {
14
14
  var source = arguments[i];
15
-
16
15
  for (var key in source) {
17
16
  if (Object.prototype.hasOwnProperty.call(source, key)) {
18
17
  target[key] = source[key];
19
18
  }
20
19
  }
21
20
  }
22
-
23
21
  return target;
24
22
  };
25
23
  return _extends.apply(this, arguments);
@@ -28,12 +26,10 @@ function _extends() {
28
26
  ////////////////////////////////////////////////////////////////////////////////
29
27
  //#region Types and Constants
30
28
  ////////////////////////////////////////////////////////////////////////////////
31
-
32
29
  /**
33
30
  * Actions represent the type of change to a location value.
34
31
  */
35
32
  var Action;
36
-
37
33
  (function (Action) {
38
34
  /**
39
35
  * A POP indicates a change to an arbitrary index in the history stack, such
@@ -48,80 +44,63 @@ var Action;
48
44
  * a link is clicked and a new page loads. When this happens, all subsequent
49
45
  * entries in the stack are lost.
50
46
  */
51
-
52
47
  Action["Push"] = "PUSH";
53
48
  /**
54
49
  * A REPLACE indicates the entry at the current index in the history stack
55
50
  * being replaced by a new one.
56
51
  */
57
-
58
52
  Action["Replace"] = "REPLACE";
59
53
  })(Action || (Action = {}));
60
-
61
54
  const PopStateEventType = "popstate";
62
55
  /**
63
56
  * Memory history stores the current location in memory. It is designed for use
64
57
  * in stateful non-browser environments like tests and React Native.
65
58
  */
66
-
67
59
  function createMemoryHistory(options) {
68
60
  if (options === void 0) {
69
61
  options = {};
70
62
  }
71
-
72
63
  let {
73
64
  initialEntries = ["/"],
74
65
  initialIndex,
75
66
  v5Compat = false
76
67
  } = options;
77
68
  let entries; // Declare so we can access from createMemoryLocation
78
-
79
69
  entries = initialEntries.map((entry, index) => createMemoryLocation(entry, typeof entry === "string" ? null : entry.state, index === 0 ? "default" : undefined));
80
70
  let index = clampIndex(initialIndex == null ? entries.length - 1 : initialIndex);
81
71
  let action = Action.Pop;
82
72
  let listener = null;
83
-
84
73
  function clampIndex(n) {
85
74
  return Math.min(Math.max(n, 0), entries.length - 1);
86
75
  }
87
-
88
76
  function getCurrentLocation() {
89
77
  return entries[index];
90
78
  }
91
-
92
79
  function createMemoryLocation(to, state, key) {
93
80
  if (state === void 0) {
94
81
  state = null;
95
82
  }
96
-
97
83
  let location = createLocation(entries ? getCurrentLocation().pathname : "/", to, state, key);
98
84
  warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in memory history: " + JSON.stringify(to));
99
85
  return location;
100
86
  }
101
-
102
87
  function createHref(to) {
103
88
  return typeof to === "string" ? to : createPath(to);
104
89
  }
105
-
106
90
  let history = {
107
91
  get index() {
108
92
  return index;
109
93
  },
110
-
111
94
  get action() {
112
95
  return action;
113
96
  },
114
-
115
97
  get location() {
116
98
  return getCurrentLocation();
117
99
  },
118
-
119
100
  createHref,
120
-
121
101
  createURL(to) {
122
102
  return new URL(createHref(to), "http://localhost");
123
103
  },
124
-
125
104
  encodeLocation(to) {
126
105
  let path = typeof to === "string" ? parsePath(to) : to;
127
106
  return {
@@ -130,13 +109,11 @@ function createMemoryHistory(options) {
130
109
  hash: path.hash || ""
131
110
  };
132
111
  },
133
-
134
112
  push(to, state) {
135
113
  action = Action.Push;
136
114
  let nextLocation = createMemoryLocation(to, state);
137
115
  index += 1;
138
116
  entries.splice(index, entries.length, nextLocation);
139
-
140
117
  if (v5Compat && listener) {
141
118
  listener({
142
119
  action,
@@ -145,12 +122,10 @@ function createMemoryHistory(options) {
145
122
  });
146
123
  }
147
124
  },
148
-
149
125
  replace(to, state) {
150
126
  action = Action.Replace;
151
127
  let nextLocation = createMemoryLocation(to, state);
152
128
  entries[index] = nextLocation;
153
-
154
129
  if (v5Compat && listener) {
155
130
  listener({
156
131
  action,
@@ -159,13 +134,11 @@ function createMemoryHistory(options) {
159
134
  });
160
135
  }
161
136
  },
162
-
163
137
  go(delta) {
164
138
  action = Action.Pop;
165
139
  let nextIndex = clampIndex(index + delta);
166
140
  let nextLocation = entries[nextIndex];
167
141
  index = nextIndex;
168
-
169
142
  if (listener) {
170
143
  listener({
171
144
  action,
@@ -174,14 +147,12 @@ function createMemoryHistory(options) {
174
147
  });
175
148
  }
176
149
  },
177
-
178
150
  listen(fn) {
179
151
  listener = fn;
180
152
  return () => {
181
153
  listener = null;
182
154
  };
183
155
  }
184
-
185
156
  };
186
157
  return history;
187
158
  }
@@ -192,12 +163,10 @@ function createMemoryHistory(options) {
192
163
  *
193
164
  * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createbrowserhistory
194
165
  */
195
-
196
166
  function createBrowserHistory(options) {
197
167
  if (options === void 0) {
198
168
  options = {};
199
169
  }
200
-
201
170
  function createBrowserLocation(window, globalHistory) {
202
171
  let {
203
172
  pathname,
@@ -208,14 +177,13 @@ function createBrowserHistory(options) {
208
177
  pathname,
209
178
  search,
210
179
  hash
211
- }, // state defaults to `null` because `window.history.state` does
180
+ },
181
+ // state defaults to `null` because `window.history.state` does
212
182
  globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
213
183
  }
214
-
215
184
  function createBrowserHref(window, to) {
216
185
  return typeof to === "string" ? to : createPath(to);
217
186
  }
218
-
219
187
  return getUrlBasedHistory(createBrowserLocation, createBrowserHref, null, options);
220
188
  }
221
189
  /**
@@ -226,12 +194,10 @@ function createBrowserHistory(options) {
226
194
  *
227
195
  * @see https://github.com/remix-run/history/tree/main/docs/api-reference.md#createhashhistory
228
196
  */
229
-
230
197
  function createHashHistory(options) {
231
198
  if (options === void 0) {
232
199
  options = {};
233
200
  }
234
-
235
201
  function createHashLocation(window, globalHistory) {
236
202
  let {
237
203
  pathname = "/",
@@ -242,27 +208,23 @@ function createHashHistory(options) {
242
208
  pathname,
243
209
  search,
244
210
  hash
245
- }, // state defaults to `null` because `window.history.state` does
211
+ },
212
+ // state defaults to `null` because `window.history.state` does
246
213
  globalHistory.state && globalHistory.state.usr || null, globalHistory.state && globalHistory.state.key || "default");
247
214
  }
248
-
249
215
  function createHashHref(window, to) {
250
216
  let base = window.document.querySelector("base");
251
217
  let href = "";
252
-
253
218
  if (base && base.getAttribute("href")) {
254
219
  let url = window.location.href;
255
220
  let hashIndex = url.indexOf("#");
256
221
  href = hashIndex === -1 ? url : url.slice(0, hashIndex);
257
222
  }
258
-
259
223
  return href + "#" + (typeof to === "string" ? to : createPath(to));
260
224
  }
261
-
262
225
  function validateHashLocation(location, to) {
263
226
  warning(location.pathname.charAt(0) === "/", "relative pathnames are not supported in hash history.push(" + JSON.stringify(to) + ")");
264
227
  }
265
-
266
228
  return getUrlBasedHistory(createHashLocation, createHashHref, validateHashLocation, options);
267
229
  }
268
230
  function invariant(value, message) {
@@ -274,26 +236,23 @@ function warning(cond, message) {
274
236
  if (!cond) {
275
237
  // eslint-disable-next-line no-console
276
238
  if (typeof console !== "undefined") console.warn(message);
277
-
278
239
  try {
279
240
  // Welcome to debugging history!
280
241
  //
281
242
  // This error is thrown as a convenience so you can more easily
282
243
  // find the source for a warning that appears in the console by
283
244
  // enabling "pause on exceptions" in your JavaScript debugger.
284
- throw new Error(message); // eslint-disable-next-line no-empty
245
+ throw new Error(message);
246
+ // eslint-disable-next-line no-empty
285
247
  } catch (e) {}
286
248
  }
287
249
  }
288
-
289
250
  function createKey() {
290
251
  return Math.random().toString(36).substr(2, 8);
291
252
  }
292
253
  /**
293
254
  * For browser-based histories, we combine the state and key into an object
294
255
  */
295
-
296
-
297
256
  function getHistoryState(location, index) {
298
257
  return {
299
258
  usr: location.state,
@@ -304,13 +263,10 @@ function getHistoryState(location, index) {
304
263
  /**
305
264
  * Creates a Location object with a unique key from the given Path
306
265
  */
307
-
308
-
309
266
  function createLocation(current, to, state, key) {
310
267
  if (state === void 0) {
311
268
  state = null;
312
269
  }
313
-
314
270
  let location = _extends({
315
271
  pathname: typeof current === "string" ? current : current.pathname,
316
272
  search: "",
@@ -323,13 +279,11 @@ function createLocation(current, to, state, key) {
323
279
  // keep as is for the time being and just let any incoming keys take precedence
324
280
  key: to && to.key || key || createKey()
325
281
  });
326
-
327
282
  return location;
328
283
  }
329
284
  /**
330
285
  * Creates a string URL path from the given pathname, search, and hash components.
331
286
  */
332
-
333
287
  function createPath(_ref) {
334
288
  let {
335
289
  pathname = "/",
@@ -343,38 +297,29 @@ function createPath(_ref) {
343
297
  /**
344
298
  * Parses a string URL path into its separate pathname, search, and hash components.
345
299
  */
346
-
347
300
  function parsePath(path) {
348
301
  let parsedPath = {};
349
-
350
302
  if (path) {
351
303
  let hashIndex = path.indexOf("#");
352
-
353
304
  if (hashIndex >= 0) {
354
305
  parsedPath.hash = path.substr(hashIndex);
355
306
  path = path.substr(0, hashIndex);
356
307
  }
357
-
358
308
  let searchIndex = path.indexOf("?");
359
-
360
309
  if (searchIndex >= 0) {
361
310
  parsedPath.search = path.substr(searchIndex);
362
311
  path = path.substr(0, searchIndex);
363
312
  }
364
-
365
313
  if (path) {
366
314
  parsedPath.pathname = path;
367
315
  }
368
316
  }
369
-
370
317
  return parsedPath;
371
318
  }
372
-
373
319
  function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
374
320
  if (options === void 0) {
375
321
  options = {};
376
322
  }
377
-
378
323
  let {
379
324
  window = document.defaultView,
380
325
  v5Compat = false
@@ -382,30 +327,27 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
382
327
  let globalHistory = window.history;
383
328
  let action = Action.Pop;
384
329
  let listener = null;
385
- let index = getIndex(); // Index should only be null when we initialize. If not, it's because the
330
+ let index = getIndex();
331
+ // Index should only be null when we initialize. If not, it's because the
386
332
  // user called history.pushState or history.replaceState directly, in which
387
333
  // case we should log a warning as it will result in bugs.
388
-
389
334
  if (index == null) {
390
335
  index = 0;
391
336
  globalHistory.replaceState(_extends({}, globalHistory.state, {
392
337
  idx: index
393
338
  }), "");
394
339
  }
395
-
396
340
  function getIndex() {
397
341
  let state = globalHistory.state || {
398
342
  idx: null
399
343
  };
400
344
  return state.idx;
401
345
  }
402
-
403
346
  function handlePop() {
404
347
  action = Action.Pop;
405
348
  let nextIndex = getIndex();
406
349
  let delta = nextIndex == null ? null : nextIndex - index;
407
350
  index = nextIndex;
408
-
409
351
  if (listener) {
410
352
  listener({
411
353
  action,
@@ -414,23 +356,28 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
414
356
  });
415
357
  }
416
358
  }
417
-
418
359
  function push(to, state) {
419
360
  action = Action.Push;
420
361
  let location = createLocation(history.location, to, state);
421
362
  if (validateLocation) validateLocation(location, to);
422
363
  index = getIndex() + 1;
423
364
  let historyState = getHistoryState(location, index);
424
- let url = history.createHref(location); // try...catch because iOS limits us to 100 pushState calls :/
425
-
365
+ let url = history.createHref(location);
366
+ // try...catch because iOS limits us to 100 pushState calls :/
426
367
  try {
427
368
  globalHistory.pushState(historyState, "", url);
428
369
  } catch (error) {
370
+ // If the exception is because `state` can't be serialized, let that throw
371
+ // outwards just like a replace call would so the dev knows the cause
372
+ // https://html.spec.whatwg.org/multipage/nav-history-apis.html#shared-history-push/replace-state-steps
373
+ // https://html.spec.whatwg.org/multipage/structured-data.html#structuredserializeinternal
374
+ if (error instanceof DOMException && error.name === "DataCloneError") {
375
+ throw error;
376
+ }
429
377
  // They are going to lose state here, but there is no real
430
378
  // way to warn them about it since the page will refresh...
431
379
  window.location.assign(url);
432
380
  }
433
-
434
381
  if (v5Compat && listener) {
435
382
  listener({
436
383
  action,
@@ -439,7 +386,6 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
439
386
  });
440
387
  }
441
388
  }
442
-
443
389
  function replace(to, state) {
444
390
  action = Action.Replace;
445
391
  let location = createLocation(history.location, to, state);
@@ -448,7 +394,6 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
448
394
  let historyState = getHistoryState(location, index);
449
395
  let url = history.createHref(location);
450
396
  globalHistory.replaceState(historyState, "", url);
451
-
452
397
  if (v5Compat && listener) {
453
398
  listener({
454
399
  action,
@@ -457,7 +402,6 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
457
402
  });
458
403
  }
459
404
  }
460
-
461
405
  function createURL(to) {
462
406
  // window.location.origin is "null" (the literal string value) in Firefox
463
407
  // under certain conditions, notably when serving from a local HTML file
@@ -467,21 +411,17 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
467
411
  invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
468
412
  return new URL(href, base);
469
413
  }
470
-
471
414
  let history = {
472
415
  get action() {
473
416
  return action;
474
417
  },
475
-
476
418
  get location() {
477
419
  return getLocation(window, globalHistory);
478
420
  },
479
-
480
421
  listen(fn) {
481
422
  if (listener) {
482
423
  throw new Error("A history only accepts one active listener");
483
424
  }
484
-
485
425
  window.addEventListener(PopStateEventType, handlePop);
486
426
  listener = fn;
487
427
  return () => {
@@ -489,13 +429,10 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
489
429
  listener = null;
490
430
  };
491
431
  },
492
-
493
432
  createHref(to) {
494
433
  return createHref(window, to);
495
434
  },
496
-
497
435
  createURL,
498
-
499
436
  encodeLocation(to) {
500
437
  // Encode a Location the same way window.location would
501
438
  let url = createURL(to);
@@ -505,55 +442,45 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
505
442
  hash: url.hash
506
443
  };
507
444
  },
508
-
509
445
  push,
510
446
  replace,
511
-
512
447
  go(n) {
513
448
  return globalHistory.go(n);
514
449
  }
515
-
516
450
  };
517
451
  return history;
518
- } //#endregion
452
+ }
453
+ //#endregion
519
454
 
520
455
  var ResultType;
521
-
522
456
  (function (ResultType) {
523
457
  ResultType["data"] = "data";
524
458
  ResultType["deferred"] = "deferred";
525
459
  ResultType["redirect"] = "redirect";
526
460
  ResultType["error"] = "error";
527
461
  })(ResultType || (ResultType = {}));
528
-
529
462
  const immutableRouteKeys = new Set(["lazy", "caseSensitive", "path", "id", "index", "children"]);
530
-
531
463
  function isIndexRoute(route) {
532
464
  return route.index === true;
533
- } // Walk the route tree generating unique IDs where necessary so we are working
465
+ }
466
+ // Walk the route tree generating unique IDs where necessary so we are working
534
467
  // solely with AgnosticDataRouteObject's within the Router
535
-
536
-
537
468
  function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manifest) {
538
469
  if (parentPath === void 0) {
539
470
  parentPath = [];
540
471
  }
541
-
542
472
  if (manifest === void 0) {
543
473
  manifest = {};
544
474
  }
545
-
546
475
  return routes.map((route, index) => {
547
476
  let treePath = [...parentPath, index];
548
477
  let id = typeof route.id === "string" ? route.id : treePath.join("-");
549
478
  invariant(route.index !== true || !route.children, "Cannot specify children on an index route");
550
479
  invariant(!manifest[id], "Found a route id collision on id \"" + id + "\". Route " + "id's must be globally unique within Data Router usages");
551
-
552
480
  if (isIndexRoute(route)) {
553
481
  let indexRoute = _extends({}, route, mapRouteProperties(route), {
554
482
  id
555
483
  });
556
-
557
484
  manifest[id] = indexRoute;
558
485
  return indexRoute;
559
486
  } else {
@@ -561,13 +488,10 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manif
561
488
  id,
562
489
  children: undefined
563
490
  });
564
-
565
491
  manifest[id] = pathOrLayoutRoute;
566
-
567
492
  if (route.children) {
568
493
  pathOrLayoutRoute.children = convertRoutesToDataRoutes(route.children, mapRouteProperties, treePath, manifest);
569
494
  }
570
-
571
495
  return pathOrLayoutRoute;
572
496
  }
573
497
  });
@@ -577,25 +501,21 @@ function convertRoutesToDataRoutes(routes, mapRouteProperties, parentPath, manif
577
501
  *
578
502
  * @see https://reactrouter.com/utils/match-routes
579
503
  */
580
-
581
504
  function matchRoutes(routes, locationArg, basename) {
582
505
  if (basename === void 0) {
583
506
  basename = "/";
584
507
  }
585
-
586
508
  let location = typeof locationArg === "string" ? parsePath(locationArg) : locationArg;
587
509
  let pathname = stripBasename(location.pathname || "/", basename);
588
-
589
510
  if (pathname == null) {
590
511
  return null;
591
512
  }
592
-
593
513
  let branches = flattenRoutes(routes);
594
514
  rankRouteBranches(branches);
595
515
  let matches = null;
596
-
597
516
  for (let i = 0; matches == null && i < branches.length; ++i) {
598
- matches = matchRouteBranch(branches[i], // Incoming pathnames are generally encoded from either window.location
517
+ matches = matchRouteBranch(branches[i],
518
+ // Incoming pathnames are generally encoded from either window.location
599
519
  // or from router.navigate, but we want to match against the unencoded
600
520
  // paths in the route definitions. Memory router locations won't be
601
521
  // encoded here but there also shouldn't be anything to decode so this
@@ -603,23 +523,18 @@ function matchRoutes(routes, locationArg, basename) {
603
523
  // history-aware.
604
524
  safelyDecodeURI(pathname));
605
525
  }
606
-
607
526
  return matches;
608
527
  }
609
-
610
528
  function flattenRoutes(routes, branches, parentsMeta, parentPath) {
611
529
  if (branches === void 0) {
612
530
  branches = [];
613
531
  }
614
-
615
532
  if (parentsMeta === void 0) {
616
533
  parentsMeta = [];
617
534
  }
618
-
619
535
  if (parentPath === void 0) {
620
536
  parentPath = "";
621
537
  }
622
-
623
538
  let flattenRoute = (route, index, relativePath) => {
624
539
  let meta = {
625
540
  relativePath: relativePath === undefined ? route.path || "" : relativePath,
@@ -627,40 +542,35 @@ function flattenRoutes(routes, branches, parentsMeta, parentPath) {
627
542
  childrenIndex: index,
628
543
  route
629
544
  };
630
-
631
545
  if (meta.relativePath.startsWith("/")) {
632
546
  invariant(meta.relativePath.startsWith(parentPath), "Absolute route path \"" + meta.relativePath + "\" nested under path " + ("\"" + parentPath + "\" is not valid. An absolute child route path ") + "must start with the combined path of all its parent routes.");
633
547
  meta.relativePath = meta.relativePath.slice(parentPath.length);
634
548
  }
635
-
636
549
  let path = joinPaths([parentPath, meta.relativePath]);
637
- let routesMeta = parentsMeta.concat(meta); // Add the children before adding this route to the array so we traverse the
550
+ let routesMeta = parentsMeta.concat(meta);
551
+ // Add the children before adding this route to the array so we traverse the
638
552
  // route tree depth-first and child routes appear before their parents in
639
553
  // the "flattened" version.
640
-
641
554
  if (route.children && route.children.length > 0) {
642
- invariant( // Our types know better, but runtime JS may not!
555
+ invariant(
556
+ // Our types know better, but runtime JS may not!
643
557
  // @ts-expect-error
644
558
  route.index !== true, "Index routes must not have child routes. Please remove " + ("all child routes from route path \"" + path + "\"."));
645
559
  flattenRoutes(route.children, branches, routesMeta, path);
646
- } // Routes without a path shouldn't ever match by themselves unless they are
560
+ }
561
+ // Routes without a path shouldn't ever match by themselves unless they are
647
562
  // index routes, so don't add them to the list of possible branches.
648
-
649
-
650
563
  if (route.path == null && !route.index) {
651
564
  return;
652
565
  }
653
-
654
566
  branches.push({
655
567
  path,
656
568
  score: computeScore(path, route.index),
657
569
  routesMeta
658
570
  });
659
571
  };
660
-
661
572
  routes.forEach((route, index) => {
662
573
  var _route$path;
663
-
664
574
  // coarse-grain check for optional params
665
575
  if (route.path === "" || !((_route$path = route.path) != null && _route$path.includes("?"))) {
666
576
  flattenRoute(route, index);
@@ -686,82 +596,70 @@ function flattenRoutes(routes, branches, parentsMeta, parentPath) {
686
596
  * - `/one/three/:four/:five`
687
597
  * - `/one/:two/three/:four/:five`
688
598
  */
689
-
690
-
691
599
  function explodeOptionalSegments(path) {
692
600
  let segments = path.split("/");
693
601
  if (segments.length === 0) return [];
694
- let [first, ...rest] = segments; // Optional path segments are denoted by a trailing `?`
695
-
696
- let isOptional = first.endsWith("?"); // Compute the corresponding required segment: `foo?` -> `foo`
697
-
602
+ let [first, ...rest] = segments;
603
+ // Optional path segments are denoted by a trailing `?`
604
+ let isOptional = first.endsWith("?");
605
+ // Compute the corresponding required segment: `foo?` -> `foo`
698
606
  let required = first.replace(/\?$/, "");
699
-
700
607
  if (rest.length === 0) {
701
608
  // Intepret empty string as omitting an optional segment
702
609
  // `["one", "", "three"]` corresponds to omitting `:two` from `/one/:two?/three` -> `/one/three`
703
610
  return isOptional ? [required, ""] : [required];
704
611
  }
705
-
706
612
  let restExploded = explodeOptionalSegments(rest.join("/"));
707
- let result = []; // All child paths with the prefix. Do this for all children before the
613
+ let result = [];
614
+ // All child paths with the prefix. Do this for all children before the
708
615
  // optional version for all children so we get consistent ordering where the
709
616
  // parent optional aspect is preferred as required. Otherwise, we can get
710
617
  // child sections interspersed where deeper optional segments are higher than
711
618
  // parent optional segments, where for example, /:two would explodes _earlier_
712
619
  // then /:one. By always including the parent as required _for all children_
713
620
  // first, we avoid this issue
714
-
715
- result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/"))); // Then if this is an optional value, add all child versions without
716
-
621
+ result.push(...restExploded.map(subpath => subpath === "" ? required : [required, subpath].join("/")));
622
+ // Then if this is an optional value, add all child versions without
717
623
  if (isOptional) {
718
624
  result.push(...restExploded);
719
- } // for absolute paths, ensure `/` instead of empty segment
720
-
721
-
625
+ }
626
+ // for absolute paths, ensure `/` instead of empty segment
722
627
  return result.map(exploded => path.startsWith("/") && exploded === "" ? "/" : exploded);
723
628
  }
724
-
725
629
  function rankRouteBranches(branches) {
726
630
  branches.sort((a, b) => a.score !== b.score ? b.score - a.score // Higher score first
727
631
  : compareIndexes(a.routesMeta.map(meta => meta.childrenIndex), b.routesMeta.map(meta => meta.childrenIndex)));
728
632
  }
729
-
730
633
  const paramRe = /^:\w+$/;
731
634
  const dynamicSegmentValue = 3;
732
635
  const indexRouteValue = 2;
733
636
  const emptySegmentValue = 1;
734
637
  const staticSegmentValue = 10;
735
638
  const splatPenalty = -2;
736
-
737
639
  const isSplat = s => s === "*";
738
-
739
640
  function computeScore(path, index) {
740
641
  let segments = path.split("/");
741
642
  let initialScore = segments.length;
742
-
743
643
  if (segments.some(isSplat)) {
744
644
  initialScore += splatPenalty;
745
645
  }
746
-
747
646
  if (index) {
748
647
  initialScore += indexRouteValue;
749
648
  }
750
-
751
649
  return segments.filter(s => !isSplat(s)).reduce((score, segment) => score + (paramRe.test(segment) ? dynamicSegmentValue : segment === "" ? emptySegmentValue : staticSegmentValue), initialScore);
752
650
  }
753
-
754
651
  function compareIndexes(a, b) {
755
652
  let siblings = a.length === b.length && a.slice(0, -1).every((n, i) => n === b[i]);
756
- return siblings ? // If two routes are siblings, we should try to match the earlier sibling
653
+ return siblings ?
654
+ // If two routes are siblings, we should try to match the earlier sibling
757
655
  // first. This allows people to have fine-grained control over the matching
758
656
  // behavior by simply putting routes with identical paths in the order they
759
657
  // want them tried.
760
- a[a.length - 1] - b[b.length - 1] : // Otherwise, it doesn't really make sense to rank non-siblings by index,
658
+ a[a.length - 1] - b[b.length - 1] :
659
+ // Otherwise, it doesn't really make sense to rank non-siblings by index,
761
660
  // so they sort equally.
762
661
  0;
763
662
  }
764
-
765
663
  function matchRouteBranch(branch, pathname) {
766
664
  let {
767
665
  routesMeta
@@ -769,7 +667,6 @@ function matchRouteBranch(branch, pathname) {
769
667
  let matchedParams = {};
770
668
  let matchedPathname = "/";
771
669
  let matches = [];
772
-
773
670
  for (let i = 0; i < routesMeta.length; ++i) {
774
671
  let meta = routesMeta[i];
775
672
  let end = i === routesMeta.length - 1;
@@ -789,12 +686,10 @@ function matchRouteBranch(branch, pathname) {
789
686
  pathnameBase: normalizePathname(joinPaths([matchedPathname, match.pathnameBase])),
790
687
  route
791
688
  });
792
-
793
689
  if (match.pathnameBase !== "/") {
794
690
  matchedPathname = joinPaths([matchedPathname, match.pathnameBase]);
795
691
  }
796
692
  }
797
-
798
693
  return matches;
799
694
  }
800
695
  /**
@@ -802,52 +697,42 @@ function matchRouteBranch(branch, pathname) {
802
697
  *
803
698
  * @see https://reactrouter.com/utils/generate-path
804
699
  */
805
-
806
-
807
700
  function generatePath(originalPath, params) {
808
701
  if (params === void 0) {
809
702
  params = {};
810
703
  }
811
-
812
704
  let path = originalPath;
813
-
814
705
  if (path.endsWith("*") && path !== "*" && !path.endsWith("/*")) {
815
706
  warning(false, "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
816
707
  path = path.replace(/\*$/, "/*");
817
- } // ensure `/` is added at the beginning if the path is absolute
818
-
819
-
708
+ }
709
+ // ensure `/` is added at the beginning if the path is absolute
820
710
  const prefix = path.startsWith("/") ? "/" : "";
821
711
  const segments = path.split(/\/+/).map((segment, index, array) => {
822
- const isLastSegment = index === array.length - 1; // only apply the splat if it's the last segment
823
-
712
+ const isLastSegment = index === array.length - 1;
713
+ // only apply the splat if it's the last segment
824
714
  if (isLastSegment && segment === "*") {
825
715
  const star = "*";
826
- const starParam = params[star]; // Apply the splat
827
-
716
+ const starParam = params[star];
717
+ // Apply the splat
828
718
  return starParam;
829
719
  }
830
-
831
720
  const keyMatch = segment.match(/^:(\w+)(\??)$/);
832
-
833
721
  if (keyMatch) {
834
722
  const [, key, optional] = keyMatch;
835
723
  let param = params[key];
836
-
837
724
  if (optional === "?") {
838
725
  return param == null ? "" : param;
839
726
  }
840
-
841
727
  if (param == null) {
842
728
  invariant(false, "Missing \":" + key + "\" param");
843
729
  }
844
-
845
730
  return param;
846
- } // Remove any optional markers from optional static segments
847
-
848
-
731
+ }
732
+ // Remove any optional markers from optional static segments
849
733
  return segment.replace(/\?$/g, "");
850
- }) // Remove empty segments
734
+ })
735
+ // Remove empty segments
851
736
  .filter(segment => !!segment);
852
737
  return prefix + segments.join("/");
853
738
  }
@@ -857,7 +742,6 @@ function generatePath(originalPath, params) {
857
742
  *
858
743
  * @see https://reactrouter.com/utils/match-path
859
744
  */
860
-
861
745
  function matchPath(pattern, pathname) {
862
746
  if (typeof pattern === "string") {
863
747
  pattern = {
@@ -866,7 +750,6 @@ function matchPath(pattern, pathname) {
866
750
  end: true
867
751
  };
868
752
  }
869
-
870
753
  let [matcher, paramNames] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
871
754
  let match = pathname.match(matcher);
872
755
  if (!match) return null;
@@ -880,7 +763,6 @@ function matchPath(pattern, pathname) {
880
763
  let splatValue = captureGroups[index] || "";
881
764
  pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
882
765
  }
883
-
884
766
  memo[paramName] = safelyDecodeURIComponent(captureGroups[index] || "", paramName);
885
767
  return memo;
886
768
  }, {});
@@ -891,16 +773,13 @@ function matchPath(pattern, pathname) {
891
773
  pattern
892
774
  };
893
775
  }
894
-
895
776
  function compilePath(path, caseSensitive, end) {
896
777
  if (caseSensitive === void 0) {
897
778
  caseSensitive = false;
898
779
  }
899
-
900
780
  if (end === void 0) {
901
781
  end = true;
902
782
  }
903
-
904
783
  warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), "Route path \"" + path + "\" will be treated as if it were " + ("\"" + path.replace(/\*$/, "/*") + "\" because the `*` character must ") + "always follow a `/` in the pattern. To get rid of this warning, " + ("please change the route path to \"" + path.replace(/\*$/, "/*") + "\"."));
905
784
  let paramNames = [];
906
785
  let regexpSource = "^" + path.replace(/\/*\*?$/, "") // Ignore trailing / and /*, we'll handle it below
@@ -910,7 +789,6 @@ function compilePath(path, caseSensitive, end) {
910
789
  paramNames.push(paramName);
911
790
  return "/([^\\/]+)";
912
791
  });
913
-
914
792
  if (path.endsWith("*")) {
915
793
  paramNames.push("*");
916
794
  regexpSource += path === "*" || path === "/*" ? "(.*)$" // Already matched the initial /, just match the rest
@@ -928,11 +806,9 @@ function compilePath(path, caseSensitive, end) {
928
806
  // /user-preferences since `-` counts as a word boundary.
929
807
  regexpSource += "(?:(?=\\/|$))";
930
808
  } else ;
931
-
932
809
  let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
933
810
  return [matcher, paramNames];
934
811
  }
935
-
936
812
  function safelyDecodeURI(value) {
937
813
  try {
938
814
  return decodeURI(value);
@@ -941,7 +817,6 @@ function safelyDecodeURI(value) {
941
817
  return value;
942
818
  }
943
819
  }
944
-
945
820
  function safelyDecodeURIComponent(value, paramName) {
946
821
  try {
947
822
  return decodeURIComponent(value);
@@ -953,25 +828,19 @@ function safelyDecodeURIComponent(value, paramName) {
953
828
  /**
954
829
  * @private
955
830
  */
956
-
957
-
958
831
  function stripBasename(pathname, basename) {
959
832
  if (basename === "/") return pathname;
960
-
961
833
  if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
962
834
  return null;
963
- } // We want to leave trailing slash behavior in the user's control, so if they
835
+ }
836
+ // We want to leave trailing slash behavior in the user's control, so if they
964
837
  // specify a basename with a trailing slash, we should support it
965
-
966
-
967
838
  let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
968
839
  let nextChar = pathname.charAt(startIndex);
969
-
970
840
  if (nextChar && nextChar !== "/") {
971
841
  // pathname does not start with basename/
972
842
  return null;
973
843
  }
974
-
975
844
  return pathname.slice(startIndex) || "/";
976
845
  }
977
846
  /**
@@ -979,12 +848,10 @@ function stripBasename(pathname, basename) {
979
848
  *
980
849
  * @see https://reactrouter.com/utils/resolve-path
981
850
  */
982
-
983
851
  function resolvePath(to, fromPathname) {
984
852
  if (fromPathname === void 0) {
985
853
  fromPathname = "/";
986
854
  }
987
-
988
855
  let {
989
856
  pathname: toPathname,
990
857
  search = "",
@@ -997,7 +864,6 @@ function resolvePath(to, fromPathname) {
997
864
  hash: normalizeHash(hash)
998
865
  };
999
866
  }
1000
-
1001
867
  function resolvePathname(relativePath, fromPathname) {
1002
868
  let segments = fromPathname.replace(/\/+$/, "").split("/");
1003
869
  let relativeSegments = relativePath.split("/");
@@ -1011,7 +877,6 @@ function resolvePathname(relativePath, fromPathname) {
1011
877
  });
1012
878
  return segments.length > 1 ? segments.join("/") : "/";
1013
879
  }
1014
-
1015
880
  function getInvalidPathError(char, field, dest, path) {
1016
881
  return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + "a string in <Link to=\"...\"> and the router will parse it for you.";
1017
882
  }
@@ -1038,22 +903,17 @@ function getInvalidPathError(char, field, dest, path) {
1038
903
  * </Route>
1039
904
  * </Route>
1040
905
  */
1041
-
1042
-
1043
906
  function getPathContributingMatches(matches) {
1044
907
  return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
1045
908
  }
1046
909
  /**
1047
910
  * @private
1048
911
  */
1049
-
1050
912
  function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
1051
913
  if (isPathRelative === void 0) {
1052
914
  isPathRelative = false;
1053
915
  }
1054
-
1055
916
  let to;
1056
-
1057
917
  if (typeof toArg === "string") {
1058
918
  to = parsePath(toArg);
1059
919
  } else {
@@ -1062,10 +922,10 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
1062
922
  invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
1063
923
  invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
1064
924
  }
1065
-
1066
925
  let isEmptyPath = toArg === "" || to.pathname === "";
1067
926
  let toPathname = isEmptyPath ? "/" : to.pathname;
1068
- let from; // Routing is relative to the current pathname if explicitly requested.
927
+ let from;
928
+ // Routing is relative to the current pathname if explicitly requested.
1069
929
  //
1070
930
  // If a pathname is explicitly provided in `to`, it should be relative to the
1071
931
  // route context. This is explained in `Note on `<Link to>` values` in our
@@ -1074,46 +934,38 @@ function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
1074
934
  // `to` values that do not provide a pathname. `to` can simply be a search or
1075
935
  // hash string, in which case we should assume that the navigation is relative
1076
936
  // to the current location's pathname and *not* the route pathname.
1077
-
1078
937
  if (isPathRelative || toPathname == null) {
1079
938
  from = locationPathname;
1080
939
  } else {
1081
940
  let routePathnameIndex = routePathnames.length - 1;
1082
-
1083
941
  if (toPathname.startsWith("..")) {
1084
- let toSegments = toPathname.split("/"); // Each leading .. segment means "go up one route" instead of "go up one
942
+ let toSegments = toPathname.split("/");
943
+ // Each leading .. segment means "go up one route" instead of "go up one
1085
944
  // URL segment". This is a key difference from how <a href> works and a
1086
945
  // major reason we call this a "to" value instead of a "href".
1087
-
1088
946
  while (toSegments[0] === "..") {
1089
947
  toSegments.shift();
1090
948
  routePathnameIndex -= 1;
1091
949
  }
1092
-
1093
950
  to.pathname = toSegments.join("/");
1094
- } // If there are more ".." segments than parent routes, resolve relative to
951
+ }
952
+ // If there are more ".." segments than parent routes, resolve relative to
1095
953
  // the root / URL.
1096
-
1097
-
1098
954
  from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
1099
955
  }
1100
-
1101
- let path = resolvePath(to, from); // Ensure the pathname has a trailing slash if the original "to" had one
1102
-
1103
- let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/"); // Or if this was a link to the current path which has a trailing slash
1104
-
956
+ let path = resolvePath(to, from);
957
+ // Ensure the pathname has a trailing slash if the original "to" had one
958
+ let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
959
+ // Or if this was a link to the current path which has a trailing slash
1105
960
  let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
1106
-
1107
961
  if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
1108
962
  path.pathname += "/";
1109
963
  }
1110
-
1111
964
  return path;
1112
965
  }
1113
966
  /**
1114
967
  * @private
1115
968
  */
1116
-
1117
969
  function getToPathname(to) {
1118
970
  // Empty strings should be treated the same as / paths
1119
971
  return to === "" || to.pathname === "" ? "/" : typeof to === "string" ? parsePath(to).pathname : to.pathname;
@@ -1121,42 +973,34 @@ function getToPathname(to) {
1121
973
  /**
1122
974
  * @private
1123
975
  */
1124
-
1125
976
  const joinPaths = paths => paths.join("/").replace(/\/\/+/g, "/");
1126
977
  /**
1127
978
  * @private
1128
979
  */
1129
-
1130
980
  const normalizePathname = pathname => pathname.replace(/\/+$/, "").replace(/^\/*/, "/");
1131
981
  /**
1132
982
  * @private
1133
983
  */
1134
-
1135
984
  const normalizeSearch = search => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
1136
985
  /**
1137
986
  * @private
1138
987
  */
1139
-
1140
988
  const normalizeHash = hash => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
1141
989
  /**
1142
990
  * This is a shortcut for creating `application/json` responses. Converts `data`
1143
991
  * to JSON and sets the `Content-Type` header.
1144
992
  */
1145
-
1146
993
  const json = function json(data, init) {
1147
994
  if (init === void 0) {
1148
995
  init = {};
1149
996
  }
1150
-
1151
997
  let responseInit = typeof init === "number" ? {
1152
998
  status: init
1153
999
  } : init;
1154
1000
  let headers = new Headers(responseInit.headers);
1155
-
1156
1001
  if (!headers.has("Content-Type")) {
1157
1002
  headers.set("Content-Type", "application/json; charset=utf-8");
1158
1003
  }
1159
-
1160
1004
  return new Response(JSON.stringify(data), _extends({}, responseInit, {
1161
1005
  headers
1162
1006
  }));
@@ -1167,17 +1011,14 @@ class DeferredData {
1167
1011
  this.pendingKeysSet = new Set();
1168
1012
  this.subscribers = new Set();
1169
1013
  this.deferredKeys = [];
1170
- invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects"); // Set up an AbortController + Promise we can race against to exit early
1014
+ invariant(data && typeof data === "object" && !Array.isArray(data), "defer() only accepts plain objects");
1015
+ // Set up an AbortController + Promise we can race against to exit early
1171
1016
  // cancellation
1172
-
1173
1017
  let reject;
1174
1018
  this.abortPromise = new Promise((_, r) => reject = r);
1175
1019
  this.controller = new AbortController();
1176
-
1177
1020
  let onAbort = () => reject(new AbortedDeferredError("Deferred data aborted"));
1178
-
1179
1021
  this.unlistenAbortSignal = () => this.controller.signal.removeEventListener("abort", onAbort);
1180
-
1181
1022
  this.controller.signal.addEventListener("abort", onAbort);
1182
1023
  this.data = Object.entries(data).reduce((acc, _ref) => {
1183
1024
  let [key, value] = _ref;
@@ -1185,34 +1026,29 @@ class DeferredData {
1185
1026
  [key]: this.trackPromise(key, value)
1186
1027
  });
1187
1028
  }, {});
1188
-
1189
1029
  if (this.done) {
1190
1030
  // All incoming values were resolved
1191
1031
  this.unlistenAbortSignal();
1192
1032
  }
1193
-
1194
1033
  this.init = responseInit;
1195
1034
  }
1196
-
1197
1035
  trackPromise(key, value) {
1198
1036
  if (!(value instanceof Promise)) {
1199
1037
  return value;
1200
1038
  }
1201
-
1202
1039
  this.deferredKeys.push(key);
1203
- this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with
1040
+ this.pendingKeysSet.add(key);
1041
+ // We store a little wrapper promise that will be extended with
1204
1042
  // _data/_error props upon resolve/reject
1205
-
1206
- let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error)); // Register rejection listeners to avoid uncaught promise rejections on
1043
+ let promise = Promise.race([value, this.abortPromise]).then(data => this.onSettle(promise, key, null, data), error => this.onSettle(promise, key, error));
1044
+ // Register rejection listeners to avoid uncaught promise rejections on
1207
1045
  // errors or aborted deferred values
1208
-
1209
1046
  promise.catch(() => {});
1210
1047
  Object.defineProperty(promise, "_tracked", {
1211
1048
  get: () => true
1212
1049
  });
1213
1050
  return promise;
1214
1051
  }
1215
-
1216
1052
  onSettle(promise, key, error, data) {
1217
1053
  if (this.controller.signal.aborted && error instanceof AbortedDeferredError) {
1218
1054
  this.unlistenAbortSignal();
@@ -1221,14 +1057,11 @@ class DeferredData {
1221
1057
  });
1222
1058
  return Promise.reject(error);
1223
1059
  }
1224
-
1225
1060
  this.pendingKeysSet.delete(key);
1226
-
1227
1061
  if (this.done) {
1228
1062
  // Nothing left to abort!
1229
1063
  this.unlistenAbortSignal();
1230
1064
  }
1231
-
1232
1065
  if (error) {
1233
1066
  Object.defineProperty(promise, "_error", {
1234
1067
  get: () => error
@@ -1236,54 +1069,43 @@ class DeferredData {
1236
1069
  this.emit(false, key);
1237
1070
  return Promise.reject(error);
1238
1071
  }
1239
-
1240
1072
  Object.defineProperty(promise, "_data", {
1241
1073
  get: () => data
1242
1074
  });
1243
1075
  this.emit(false, key);
1244
1076
  return data;
1245
1077
  }
1246
-
1247
1078
  emit(aborted, settledKey) {
1248
1079
  this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));
1249
1080
  }
1250
-
1251
1081
  subscribe(fn) {
1252
1082
  this.subscribers.add(fn);
1253
1083
  return () => this.subscribers.delete(fn);
1254
1084
  }
1255
-
1256
1085
  cancel() {
1257
1086
  this.controller.abort();
1258
1087
  this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));
1259
1088
  this.emit(true);
1260
1089
  }
1261
-
1262
1090
  async resolveData(signal) {
1263
1091
  let aborted = false;
1264
-
1265
1092
  if (!this.done) {
1266
1093
  let onAbort = () => this.cancel();
1267
-
1268
1094
  signal.addEventListener("abort", onAbort);
1269
1095
  aborted = await new Promise(resolve => {
1270
1096
  this.subscribe(aborted => {
1271
1097
  signal.removeEventListener("abort", onAbort);
1272
-
1273
1098
  if (aborted || this.done) {
1274
1099
  resolve(aborted);
1275
1100
  }
1276
1101
  });
1277
1102
  });
1278
1103
  }
1279
-
1280
1104
  return aborted;
1281
1105
  }
1282
-
1283
1106
  get done() {
1284
1107
  return this.pendingKeysSet.size === 0;
1285
1108
  }
1286
-
1287
1109
  get unwrappedData() {
1288
1110
  invariant(this.data !== null && this.done, "Can only unwrap data on initialized and settled deferreds");
1289
1111
  return Object.entries(this.data).reduce((acc, _ref2) => {
@@ -1293,34 +1115,26 @@ class DeferredData {
1293
1115
  });
1294
1116
  }, {});
1295
1117
  }
1296
-
1297
1118
  get pendingKeys() {
1298
1119
  return Array.from(this.pendingKeysSet);
1299
1120
  }
1300
-
1301
1121
  }
1302
-
1303
1122
  function isTrackedPromise(value) {
1304
1123
  return value instanceof Promise && value._tracked === true;
1305
1124
  }
1306
-
1307
1125
  function unwrapTrackedPromise(value) {
1308
1126
  if (!isTrackedPromise(value)) {
1309
1127
  return value;
1310
1128
  }
1311
-
1312
1129
  if (value._error) {
1313
1130
  throw value._error;
1314
1131
  }
1315
-
1316
1132
  return value._data;
1317
1133
  }
1318
-
1319
1134
  const defer = function defer(data, init) {
1320
1135
  if (init === void 0) {
1321
1136
  init = {};
1322
1137
  }
1323
-
1324
1138
  let responseInit = typeof init === "number" ? {
1325
1139
  status: init
1326
1140
  } : init;
@@ -1330,14 +1144,11 @@ const defer = function defer(data, init) {
1330
1144
  * A redirect response. Sets the status code and the `Location` header.
1331
1145
  * Defaults to "302 Found".
1332
1146
  */
1333
-
1334
1147
  const redirect = function redirect(url, init) {
1335
1148
  if (init === void 0) {
1336
1149
  init = 302;
1337
1150
  }
1338
-
1339
1151
  let responseInit = init;
1340
-
1341
1152
  if (typeof responseInit === "number") {
1342
1153
  responseInit = {
1343
1154
  status: responseInit
@@ -1345,7 +1156,6 @@ const redirect = function redirect(url, init) {
1345
1156
  } else if (typeof responseInit.status === "undefined") {
1346
1157
  responseInit.status = 302;
1347
1158
  }
1348
-
1349
1159
  let headers = new Headers(responseInit.headers);
1350
1160
  headers.set("Location", url);
1351
1161
  return new Response(null, _extends({}, responseInit, {
@@ -1356,17 +1166,14 @@ const redirect = function redirect(url, init) {
1356
1166
  * @private
1357
1167
  * Utility class we use to hold auto-unwrapped 4xx/5xx Response bodies
1358
1168
  */
1359
-
1360
1169
  class ErrorResponse {
1361
1170
  constructor(status, statusText, data, internal) {
1362
1171
  if (internal === void 0) {
1363
1172
  internal = false;
1364
1173
  }
1365
-
1366
1174
  this.status = status;
1367
1175
  this.statusText = statusText || "";
1368
1176
  this.internal = internal;
1369
-
1370
1177
  if (data instanceof Error) {
1371
1178
  this.data = data.toString();
1372
1179
  this.error = data;
@@ -1374,13 +1181,11 @@ class ErrorResponse {
1374
1181
  this.data = data;
1375
1182
  }
1376
1183
  }
1377
-
1378
1184
  }
1379
1185
  /**
1380
1186
  * Check if the given error is an ErrorResponse generated from a 4xx/5xx
1381
1187
  * Response thrown from an action/loader
1382
1188
  */
1383
-
1384
1189
  function isRouteErrorResponse(error) {
1385
1190
  return error != null && typeof error.status === "number" && typeof error.statusText === "string" && typeof error.internal === "boolean" && "data" in error;
1386
1191
  }
@@ -1414,70 +1219,63 @@ const IDLE_BLOCKER = {
1414
1219
  location: undefined
1415
1220
  };
1416
1221
  const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
1417
- const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
1418
- const isServer = !isBrowser;
1419
-
1420
1222
  const defaultMapRouteProperties = route => ({
1421
1223
  hasErrorBoundary: Boolean(route.hasErrorBoundary)
1422
- }); //#endregion
1224
+ });
1225
+ //#endregion
1423
1226
  ////////////////////////////////////////////////////////////////////////////////
1424
1227
  //#region createRouter
1425
1228
  ////////////////////////////////////////////////////////////////////////////////
1426
-
1427
1229
  /**
1428
1230
  * Create a router and listen to history POP navigations
1429
1231
  */
1430
-
1431
-
1432
1232
  function createRouter(init) {
1233
+ const routerWindow = init.window ? init.window : typeof window !== "undefined" ? window : undefined;
1234
+ const isBrowser = typeof routerWindow !== "undefined" && typeof routerWindow.document !== "undefined" && typeof routerWindow.document.createElement !== "undefined";
1235
+ const isServer = !isBrowser;
1433
1236
  invariant(init.routes.length > 0, "You must provide a non-empty routes array to createRouter");
1434
1237
  let mapRouteProperties;
1435
-
1436
1238
  if (init.mapRouteProperties) {
1437
1239
  mapRouteProperties = init.mapRouteProperties;
1438
1240
  } else if (init.detectErrorBoundary) {
1439
1241
  // If they are still using the deprecated version, wrap it with the new API
1440
1242
  let detectErrorBoundary = init.detectErrorBoundary;
1441
-
1442
1243
  mapRouteProperties = route => ({
1443
1244
  hasErrorBoundary: detectErrorBoundary(route)
1444
1245
  });
1445
1246
  } else {
1446
1247
  mapRouteProperties = defaultMapRouteProperties;
1447
- } // Routes keyed by ID
1448
-
1449
-
1450
- let manifest = {}; // Routes in tree format for matching
1451
-
1248
+ }
1249
+ // Routes keyed by ID
1250
+ let manifest = {};
1251
+ // Routes in tree format for matching
1452
1252
  let dataRoutes = convertRoutesToDataRoutes(init.routes, mapRouteProperties, undefined, manifest);
1453
1253
  let inFlightDataRoutes;
1454
- let basename = init.basename || "/"; // Config driven behavior flags
1455
-
1254
+ let basename = init.basename || "/";
1255
+ // Config driven behavior flags
1456
1256
  let future = _extends({
1457
1257
  v7_normalizeFormMethod: false,
1458
1258
  v7_prependBasename: false
1459
- }, init.future); // Cleanup function for history
1460
-
1461
-
1462
- let unlistenHistory = null; // Externally-provided functions to call on all state changes
1463
-
1464
- let subscribers = new Set(); // Externally-provided object to hold scroll restoration locations during routing
1465
-
1466
- let savedScrollPositions = null; // Externally-provided function to get scroll restoration keys
1467
-
1468
- let getScrollRestorationKey = null; // Externally-provided function to get current scroll position
1469
-
1470
- let getScrollPosition = null; // One-time flag to control the initial hydration scroll restoration. Because
1259
+ }, init.future);
1260
+ // Cleanup function for history
1261
+ let unlistenHistory = null;
1262
+ // Externally-provided functions to call on all state changes
1263
+ let subscribers = new Set();
1264
+ // Externally-provided object to hold scroll restoration locations during routing
1265
+ let savedScrollPositions = null;
1266
+ // Externally-provided function to get scroll restoration keys
1267
+ let getScrollRestorationKey = null;
1268
+ // Externally-provided function to get current scroll position
1269
+ let getScrollPosition = null;
1270
+ // One-time flag to control the initial hydration scroll restoration. Because
1471
1271
  // we don't get the saved positions from <ScrollRestoration /> until _after_
1472
1272
  // the initial render, we need to manually trigger a separate updateState to
1473
1273
  // send along the restoreScrollPosition
1474
1274
  // Set to true if we have `hydrationData` since we assume we were SSR'd and that
1475
1275
  // SSR did the initial scroll restoration.
1476
-
1477
1276
  let initialScrollRestored = init.hydrationData != null;
1478
1277
  let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
1479
1278
  let initialErrors = null;
1480
-
1481
1279
  if (initialMatches == null) {
1482
1280
  // If we do not match a user-provided-route, fall back to the root
1483
1281
  // to allow the error boundary to take over
@@ -1493,10 +1291,11 @@ function createRouter(init) {
1493
1291
  [route.id]: error
1494
1292
  };
1495
1293
  }
1496
-
1497
- let initialized = // All initialMatches need to be loaded before we're ready. If we have lazy
1294
+ let initialized =
1295
+ // All initialMatches need to be loaded before we're ready. If we have lazy
1498
1296
  // functions around still then we'll need to run them in initialize()
1499
- !initialMatches.some(m => m.route.lazy) && ( // And we have to either have no loaders or have been provided hydrationData
1297
+ !initialMatches.some(m => m.route.lazy) && (
1298
+ // And we have to either have no loaders or have been provided hydrationData
1500
1299
  !initialMatches.some(m => m.route.loader) || init.hydrationData != null);
1501
1300
  let router;
1502
1301
  let state = {
@@ -1514,57 +1313,57 @@ function createRouter(init) {
1514
1313
  errors: init.hydrationData && init.hydrationData.errors || initialErrors,
1515
1314
  fetchers: new Map(),
1516
1315
  blockers: new Map()
1517
- }; // -- Stateful internal variables to manage navigations --
1316
+ };
1317
+ // -- Stateful internal variables to manage navigations --
1518
1318
  // Current navigation in progress (to be committed in completeNavigation)
1519
-
1520
- let pendingAction = Action.Pop; // Should the current navigation prevent the scroll reset if scroll cannot
1319
+ let pendingAction = Action.Pop;
1320
+ // Should the current navigation prevent the scroll reset if scroll cannot
1521
1321
  // be restored?
1522
-
1523
- let pendingPreventScrollReset = false; // AbortController for the active navigation
1524
-
1525
- let pendingNavigationController; // We use this to avoid touching history in completeNavigation if a
1322
+ let pendingPreventScrollReset = false;
1323
+ // AbortController for the active navigation
1324
+ let pendingNavigationController;
1325
+ // We use this to avoid touching history in completeNavigation if a
1526
1326
  // revalidation is entirely uninterrupted
1527
-
1528
- let isUninterruptedRevalidation = false; // Use this internal flag to force revalidation of all loaders:
1327
+ let isUninterruptedRevalidation = false;
1328
+ // Use this internal flag to force revalidation of all loaders:
1529
1329
  // - submissions (completed or interrupted)
1530
1330
  // - useRevalidator()
1531
1331
  // - X-Remix-Revalidate (from redirect)
1532
-
1533
- let isRevalidationRequired = false; // Use this internal array to capture routes that require revalidation due
1332
+ let isRevalidationRequired = false;
1333
+ // Use this internal array to capture routes that require revalidation due
1534
1334
  // to a cancelled deferred on action submission
1535
-
1536
- let cancelledDeferredRoutes = []; // Use this internal array to capture fetcher loads that were cancelled by an
1335
+ let cancelledDeferredRoutes = [];
1336
+ // Use this internal array to capture fetcher loads that were cancelled by an
1537
1337
  // action navigation and require revalidation
1538
-
1539
- let cancelledFetcherLoads = []; // AbortControllers for any in-flight fetchers
1540
-
1541
- let fetchControllers = new Map(); // Track loads based on the order in which they started
1542
-
1543
- let incrementingLoadId = 0; // Track the outstanding pending navigation data load to be compared against
1338
+ let cancelledFetcherLoads = [];
1339
+ // AbortControllers for any in-flight fetchers
1340
+ let fetchControllers = new Map();
1341
+ // Track loads based on the order in which they started
1342
+ let incrementingLoadId = 0;
1343
+ // Track the outstanding pending navigation data load to be compared against
1544
1344
  // the globally incrementing load when a fetcher load lands after a completed
1545
1345
  // navigation
1546
-
1547
- let pendingNavigationLoadId = -1; // Fetchers that triggered data reloads as a result of their actions
1548
-
1549
- let fetchReloadIds = new Map(); // Fetchers that triggered redirect navigations
1550
-
1551
- let fetchRedirectIds = new Set(); // Most recent href/match for fetcher.load calls for fetchers
1552
-
1553
- let fetchLoadMatches = new Map(); // Store DeferredData instances for active route matches. When a
1346
+ let pendingNavigationLoadId = -1;
1347
+ // Fetchers that triggered data reloads as a result of their actions
1348
+ let fetchReloadIds = new Map();
1349
+ // Fetchers that triggered redirect navigations
1350
+ let fetchRedirectIds = new Set();
1351
+ // Most recent href/match for fetcher.load calls for fetchers
1352
+ let fetchLoadMatches = new Map();
1353
+ // Store DeferredData instances for active route matches. When a
1554
1354
  // route loader returns defer() we stick one in here. Then, when a nested
1555
1355
  // promise resolves we update loaderData. If a new navigation starts we
1556
1356
  // cancel active deferreds for eliminated routes.
1557
-
1558
- let activeDeferreds = new Map(); // Store blocker functions in a separate Map outside of router state since
1357
+ let activeDeferreds = new Map();
1358
+ // Store blocker functions in a separate Map outside of router state since
1559
1359
  // we don't need to update UI state if they change
1560
-
1561
- let blockerFunctions = new Map(); // Flag to ignore the next history update, so we can revert the URL change on
1360
+ let blockerFunctions = new Map();
1361
+ // Flag to ignore the next history update, so we can revert the URL change on
1562
1362
  // a POP navigation that was blocked by the user without touching router state
1563
-
1564
- let ignoreNextHistoryUpdate = false; // Initialize the router, all side effects should be kicked off from here.
1363
+ let ignoreNextHistoryUpdate = false;
1364
+ // Initialize the router, all side effects should be kicked off from here.
1565
1365
  // Implemented as a Fluent API for ease of:
1566
1366
  // let router = createRouter(init).initialize();
1567
-
1568
1367
  function initialize() {
1569
1368
  // If history informs us of a POP navigation, start the navigation but do not update
1570
1369
  // state. We'll update our own state once the navigation completes
@@ -1574,98 +1373,84 @@ function createRouter(init) {
1574
1373
  location,
1575
1374
  delta
1576
1375
  } = _ref;
1577
-
1578
1376
  // Ignore this event if it was just us resetting the URL from a
1579
1377
  // blocked POP navigation
1580
1378
  if (ignoreNextHistoryUpdate) {
1581
1379
  ignoreNextHistoryUpdate = false;
1582
1380
  return;
1583
1381
  }
1584
-
1585
1382
  warning(blockerFunctions.size === 0 || delta != null, "You are trying to use a blocker on a POP navigation to a location " + "that was not created by @remix-run/router. This will fail silently in " + "production. This can happen if you are navigating outside the router " + "via `window.history.pushState`/`window.location.hash` instead of using " + "router navigation APIs. This can also happen if you are using " + "createHashRouter and the user manually changes the URL.");
1586
1383
  let blockerKey = shouldBlockNavigation({
1587
1384
  currentLocation: state.location,
1588
1385
  nextLocation: location,
1589
1386
  historyAction
1590
1387
  });
1591
-
1592
1388
  if (blockerKey && delta != null) {
1593
1389
  // Restore the URL to match the current UI, but don't update router state
1594
1390
  ignoreNextHistoryUpdate = true;
1595
- init.history.go(delta * -1); // Put the blocker into a blocked state
1596
-
1391
+ init.history.go(delta * -1);
1392
+ // Put the blocker into a blocked state
1597
1393
  updateBlocker(blockerKey, {
1598
1394
  state: "blocked",
1599
1395
  location,
1600
-
1601
1396
  proceed() {
1602
1397
  updateBlocker(blockerKey, {
1603
1398
  state: "proceeding",
1604
1399
  proceed: undefined,
1605
1400
  reset: undefined,
1606
1401
  location
1607
- }); // Re-do the same POP navigation we just blocked
1608
-
1402
+ });
1403
+ // Re-do the same POP navigation we just blocked
1609
1404
  init.history.go(delta);
1610
1405
  },
1611
-
1612
1406
  reset() {
1613
1407
  deleteBlocker(blockerKey);
1614
1408
  updateState({
1615
1409
  blockers: new Map(router.state.blockers)
1616
1410
  });
1617
1411
  }
1618
-
1619
1412
  });
1620
1413
  return;
1621
1414
  }
1622
-
1623
1415
  return startNavigation(historyAction, location);
1624
- }); // Kick off initial data load if needed. Use Pop to avoid modifying history
1416
+ });
1417
+ // Kick off initial data load if needed. Use Pop to avoid modifying history
1625
1418
  // Note we don't do any handling of lazy here. For SPA's it'll get handled
1626
1419
  // in the normal navigation flow. For SSR it's expected that lazy modules are
1627
1420
  // resolved prior to router creation since we can't go into a fallbackElement
1628
1421
  // UI for SSR'd apps
1629
-
1630
1422
  if (!state.initialized) {
1631
1423
  startNavigation(Action.Pop, state.location);
1632
1424
  }
1633
-
1634
1425
  return router;
1635
- } // Clean up a router and it's side effects
1636
-
1637
-
1426
+ }
1427
+ // Clean up a router and it's side effects
1638
1428
  function dispose() {
1639
1429
  if (unlistenHistory) {
1640
1430
  unlistenHistory();
1641
1431
  }
1642
-
1643
1432
  subscribers.clear();
1644
1433
  pendingNavigationController && pendingNavigationController.abort();
1645
1434
  state.fetchers.forEach((_, key) => deleteFetcher(key));
1646
1435
  state.blockers.forEach((_, key) => deleteBlocker(key));
1647
- } // Subscribe to state updates for the router
1648
-
1649
-
1436
+ }
1437
+ // Subscribe to state updates for the router
1650
1438
  function subscribe(fn) {
1651
1439
  subscribers.add(fn);
1652
1440
  return () => subscribers.delete(fn);
1653
- } // Update our state and notify the calling context of the change
1654
-
1655
-
1441
+ }
1442
+ // Update our state and notify the calling context of the change
1656
1443
  function updateState(newState) {
1657
1444
  state = _extends({}, state, newState);
1658
1445
  subscribers.forEach(subscriber => subscriber(state));
1659
- } // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
1446
+ }
1447
+ // Complete a navigation returning the state.navigation back to the IDLE_NAVIGATION
1660
1448
  // and setting state.[historyAction/location/matches] to the new route.
1661
1449
  // - Location is a required param
1662
1450
  // - Navigation will always be set to IDLE_NAVIGATION
1663
1451
  // - Can pass any other state in newState
1664
-
1665
-
1666
1452
  function completeNavigation(location, newState) {
1667
1453
  var _location$state, _location$state2;
1668
-
1669
1454
  // Deduce if we're in a loading/actionReload state:
1670
1455
  // - We have committed actionData in the store
1671
1456
  // - The current navigation was a mutation submission
@@ -1673,7 +1458,6 @@ function createRouter(init) {
1673
1458
  // - The location being loaded is not the result of a redirect
1674
1459
  let isActionReload = state.actionData != null && state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && state.navigation.state === "loading" && ((_location$state = location.state) == null ? void 0 : _location$state._isRedirect) !== true;
1675
1460
  let actionData;
1676
-
1677
1461
  if (newState.actionData) {
1678
1462
  if (Object.keys(newState.actionData).length > 0) {
1679
1463
  actionData = newState.actionData;
@@ -1687,25 +1471,21 @@ function createRouter(init) {
1687
1471
  } else {
1688
1472
  // Clear actionData on any other completed navigations
1689
1473
  actionData = null;
1690
- } // Always preserve any existing loaderData from re-used routes
1691
-
1692
-
1693
- let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData; // On a successful navigation we can assume we got through all blockers
1474
+ }
1475
+ // Always preserve any existing loaderData from re-used routes
1476
+ let loaderData = newState.loaderData ? mergeLoaderData(state.loaderData, newState.loaderData, newState.matches || [], newState.errors) : state.loaderData;
1477
+ // On a successful navigation we can assume we got through all blockers
1694
1478
  // so we can start fresh
1695
-
1696
1479
  for (let [key] of blockerFunctions) {
1697
1480
  deleteBlocker(key);
1698
- } // Always respect the user flag. Otherwise don't reset on mutation
1481
+ }
1482
+ // Always respect the user flag. Otherwise don't reset on mutation
1699
1483
  // submission navigations unless they redirect
1700
-
1701
-
1702
1484
  let preventScrollReset = pendingPreventScrollReset === true || state.navigation.formMethod != null && isMutationMethod(state.navigation.formMethod) && ((_location$state2 = location.state) == null ? void 0 : _location$state2._isRedirect) !== true;
1703
-
1704
1485
  if (inFlightDataRoutes) {
1705
1486
  dataRoutes = inFlightDataRoutes;
1706
1487
  inFlightDataRoutes = undefined;
1707
1488
  }
1708
-
1709
1489
  updateState(_extends({}, newState, {
1710
1490
  actionData,
1711
1491
  loaderData,
@@ -1718,30 +1498,26 @@ function createRouter(init) {
1718
1498
  preventScrollReset,
1719
1499
  blockers: new Map(state.blockers)
1720
1500
  }));
1721
-
1722
1501
  if (isUninterruptedRevalidation) ; else if (pendingAction === Action.Pop) ; else if (pendingAction === Action.Push) {
1723
1502
  init.history.push(location, location.state);
1724
1503
  } else if (pendingAction === Action.Replace) {
1725
1504
  init.history.replace(location, location.state);
1726
- } // Reset stateful navigation vars
1727
-
1728
-
1505
+ }
1506
+ // Reset stateful navigation vars
1729
1507
  pendingAction = Action.Pop;
1730
1508
  pendingPreventScrollReset = false;
1731
1509
  isUninterruptedRevalidation = false;
1732
1510
  isRevalidationRequired = false;
1733
1511
  cancelledDeferredRoutes = [];
1734
1512
  cancelledFetcherLoads = [];
1735
- } // Trigger a navigation event, which can either be a numerical POP or a PUSH
1513
+ }
1514
+ // Trigger a navigation event, which can either be a numerical POP or a PUSH
1736
1515
  // replace with an optional submission
1737
-
1738
-
1739
1516
  async function navigate(to, opts) {
1740
1517
  if (typeof to === "number") {
1741
1518
  init.history.go(to);
1742
1519
  return;
1743
1520
  }
1744
-
1745
1521
  let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, to, opts == null ? void 0 : opts.fromRouteId, opts == null ? void 0 : opts.relative);
1746
1522
  let {
1747
1523
  path,
@@ -1749,16 +1525,15 @@ function createRouter(init) {
1749
1525
  error
1750
1526
  } = normalizeNavigateOptions(future.v7_normalizeFormMethod, false, normalizedPath, opts);
1751
1527
  let currentLocation = state.location;
1752
- let nextLocation = createLocation(state.location, path, opts && opts.state); // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
1528
+ let nextLocation = createLocation(state.location, path, opts && opts.state);
1529
+ // When using navigate as a PUSH/REPLACE we aren't reading an already-encoded
1753
1530
  // URL from window.location, so we need to encode it here so the behavior
1754
1531
  // remains the same as POP and non-data-router usages. new URL() does all
1755
1532
  // the same encoding we'd get from a history.pushState/window.location read
1756
1533
  // without having to touch history
1757
-
1758
1534
  nextLocation = _extends({}, nextLocation, init.history.encodeLocation(nextLocation));
1759
1535
  let userReplace = opts && opts.replace != null ? opts.replace : undefined;
1760
1536
  let historyAction = Action.Push;
1761
-
1762
1537
  if (userReplace === true) {
1763
1538
  historyAction = Action.Replace;
1764
1539
  } else if (userReplace === false) ; else if (submission != null && isMutationMethod(submission.formMethod) && submission.formAction === state.location.pathname + state.location.search) {
@@ -1768,42 +1543,36 @@ function createRouter(init) {
1768
1543
  // action/loader this will be ignored and the redirect will be a PUSH
1769
1544
  historyAction = Action.Replace;
1770
1545
  }
1771
-
1772
1546
  let preventScrollReset = opts && "preventScrollReset" in opts ? opts.preventScrollReset === true : undefined;
1773
1547
  let blockerKey = shouldBlockNavigation({
1774
1548
  currentLocation,
1775
1549
  nextLocation,
1776
1550
  historyAction
1777
1551
  });
1778
-
1779
1552
  if (blockerKey) {
1780
1553
  // Put the blocker into a blocked state
1781
1554
  updateBlocker(blockerKey, {
1782
1555
  state: "blocked",
1783
1556
  location: nextLocation,
1784
-
1785
1557
  proceed() {
1786
1558
  updateBlocker(blockerKey, {
1787
1559
  state: "proceeding",
1788
1560
  proceed: undefined,
1789
1561
  reset: undefined,
1790
1562
  location: nextLocation
1791
- }); // Send the same navigation through
1792
-
1563
+ });
1564
+ // Send the same navigation through
1793
1565
  navigate(to, opts);
1794
1566
  },
1795
-
1796
1567
  reset() {
1797
1568
  deleteBlocker(blockerKey);
1798
1569
  updateState({
1799
1570
  blockers: new Map(state.blockers)
1800
1571
  });
1801
1572
  }
1802
-
1803
1573
  });
1804
1574
  return;
1805
1575
  }
1806
-
1807
1576
  return await startNavigation(historyAction, nextLocation, {
1808
1577
  submission,
1809
1578
  // Send through the formData serialization error if we have one so we can
@@ -1812,43 +1581,39 @@ function createRouter(init) {
1812
1581
  preventScrollReset,
1813
1582
  replace: opts && opts.replace
1814
1583
  });
1815
- } // Revalidate all current loaders. If a navigation is in progress or if this
1584
+ }
1585
+ // Revalidate all current loaders. If a navigation is in progress or if this
1816
1586
  // is interrupted by a navigation, allow this to "succeed" by calling all
1817
1587
  // loaders during the next loader round
1818
-
1819
-
1820
1588
  function revalidate() {
1821
1589
  interruptActiveLoads();
1822
1590
  updateState({
1823
1591
  revalidation: "loading"
1824
- }); // If we're currently submitting an action, we don't need to start a new
1592
+ });
1593
+ // If we're currently submitting an action, we don't need to start a new
1825
1594
  // navigation, we'll just let the follow up loader execution call all loaders
1826
-
1827
1595
  if (state.navigation.state === "submitting") {
1828
1596
  return;
1829
- } // If we're currently in an idle state, start a new navigation for the current
1597
+ }
1598
+ // If we're currently in an idle state, start a new navigation for the current
1830
1599
  // action/location and mark it as uninterrupted, which will skip the history
1831
1600
  // update in completeNavigation
1832
-
1833
-
1834
1601
  if (state.navigation.state === "idle") {
1835
1602
  startNavigation(state.historyAction, state.location, {
1836
1603
  startUninterruptedRevalidation: true
1837
1604
  });
1838
1605
  return;
1839
- } // Otherwise, if we're currently in a loading state, just start a new
1606
+ }
1607
+ // Otherwise, if we're currently in a loading state, just start a new
1840
1608
  // navigation to the navigation.location but do not trigger an uninterrupted
1841
1609
  // revalidation so that history correctly updates once the navigation completes
1842
-
1843
-
1844
1610
  startNavigation(pendingAction || state.historyAction, state.navigation.location, {
1845
1611
  overrideNavigation: state.navigation
1846
1612
  });
1847
- } // Start a navigation to the given action/location. Can optionally provide a
1613
+ }
1614
+ // Start a navigation to the given action/location. Can optionally provide a
1848
1615
  // overrideNavigation which will override the normalLoad in the case of a redirect
1849
1616
  // navigation
1850
-
1851
-
1852
1617
  async function startNavigation(historyAction, location, opts) {
1853
1618
  // Abort any in-progress navigations and start a new one. Unset any ongoing
1854
1619
  // uninterrupted revalidations unless told otherwise, since we want this
@@ -1856,15 +1621,15 @@ function createRouter(init) {
1856
1621
  pendingNavigationController && pendingNavigationController.abort();
1857
1622
  pendingNavigationController = null;
1858
1623
  pendingAction = historyAction;
1859
- isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true; // Save the current scroll position every time we start a new navigation,
1624
+ isUninterruptedRevalidation = (opts && opts.startUninterruptedRevalidation) === true;
1625
+ // Save the current scroll position every time we start a new navigation,
1860
1626
  // and track whether we should reset scroll on completion
1861
-
1862
1627
  saveScrollPosition(state.location, state.matches);
1863
1628
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
1864
1629
  let routesToUse = inFlightDataRoutes || dataRoutes;
1865
1630
  let loadingNavigation = opts && opts.overrideNavigation;
1866
- let matches = matchRoutes(routesToUse, location, basename); // Short circuit with a 404 on the root error boundary if we match nothing
1867
-
1631
+ let matches = matchRoutes(routesToUse, location, basename);
1632
+ // Short circuit with a 404 on the root error boundary if we match nothing
1868
1633
  if (!matches) {
1869
1634
  let error = getInternalRouterError(404, {
1870
1635
  pathname: location.pathname
@@ -1872,8 +1637,8 @@ function createRouter(init) {
1872
1637
  let {
1873
1638
  matches: notFoundMatches,
1874
1639
  route
1875
- } = getShortCircuitMatches(routesToUse); // Cancel all pending deferred on 404s since we don't keep any routes
1876
-
1640
+ } = getShortCircuitMatches(routesToUse);
1641
+ // Cancel all pending deferred on 404s since we don't keep any routes
1877
1642
  cancelActiveDeferreds();
1878
1643
  completeNavigation(location, {
1879
1644
  matches: notFoundMatches,
@@ -1883,26 +1648,24 @@ function createRouter(init) {
1883
1648
  }
1884
1649
  });
1885
1650
  return;
1886
- } // Short circuit if it's only a hash change and not a mutation submission.
1651
+ }
1652
+ // Short circuit if it's only a hash change and not a revalidation or
1653
+ // mutation submission.
1654
+ //
1887
1655
  // Ignore on initial page loads because since the initial load will always
1888
- // be "same hash".
1889
- // For example, on /page#hash and submit a <Form method="post"> which will
1890
- // default to a navigation to /page
1891
-
1892
-
1893
- if (state.initialized && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
1656
+ // be "same hash". For example, on /page#hash and submit a <Form method="post">
1657
+ // which will default to a navigation to /page
1658
+ if (state.initialized && !isRevalidationRequired && isHashChangeOnly(state.location, location) && !(opts && opts.submission && isMutationMethod(opts.submission.formMethod))) {
1894
1659
  completeNavigation(location, {
1895
1660
  matches
1896
1661
  });
1897
1662
  return;
1898
- } // Create a controller/Request for this navigation
1899
-
1900
-
1663
+ }
1664
+ // Create a controller/Request for this navigation
1901
1665
  pendingNavigationController = new AbortController();
1902
1666
  let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);
1903
1667
  let pendingActionData;
1904
1668
  let pendingError;
1905
-
1906
1669
  if (opts && opts.pendingError) {
1907
1670
  // If we have a pendingError, it means the user attempted a GET submission
1908
1671
  // with binary FormData so assign here and skip to handleLoaders. That
@@ -1916,40 +1679,33 @@ function createRouter(init) {
1916
1679
  let actionOutput = await handleAction(request, location, opts.submission, matches, {
1917
1680
  replace: opts.replace
1918
1681
  });
1919
-
1920
1682
  if (actionOutput.shortCircuited) {
1921
1683
  return;
1922
1684
  }
1923
-
1924
1685
  pendingActionData = actionOutput.pendingActionData;
1925
1686
  pendingError = actionOutput.pendingActionError;
1926
-
1927
1687
  let navigation = _extends({
1928
1688
  state: "loading",
1929
1689
  location
1930
1690
  }, opts.submission);
1931
-
1932
- loadingNavigation = navigation; // Create a GET request for the loaders
1933
-
1691
+ loadingNavigation = navigation;
1692
+ // Create a GET request for the loaders
1934
1693
  request = new Request(request.url, {
1935
1694
  signal: request.signal
1936
1695
  });
1937
- } // Call loaders
1938
-
1939
-
1696
+ }
1697
+ // Call loaders
1940
1698
  let {
1941
1699
  shortCircuited,
1942
1700
  loaderData,
1943
1701
  errors
1944
1702
  } = await handleLoaders(request, location, matches, loadingNavigation, opts && opts.submission, opts && opts.fetcherSubmission, opts && opts.replace, pendingActionData, pendingError);
1945
-
1946
1703
  if (shortCircuited) {
1947
1704
  return;
1948
- } // Clean up now that the action/loaders have completed. Don't clean up if
1705
+ }
1706
+ // Clean up now that the action/loaders have completed. Don't clean up if
1949
1707
  // we short circuited because pendingNavigationController will have already
1950
1708
  // been assigned to a new controller for the next navigation
1951
-
1952
-
1953
1709
  pendingNavigationController = null;
1954
1710
  completeNavigation(location, _extends({
1955
1711
  matches
@@ -1959,25 +1715,22 @@ function createRouter(init) {
1959
1715
  loaderData,
1960
1716
  errors
1961
1717
  }));
1962
- } // Call the action matched by the leaf route for this navigation and handle
1718
+ }
1719
+ // Call the action matched by the leaf route for this navigation and handle
1963
1720
  // redirects/errors
1964
-
1965
-
1966
1721
  async function handleAction(request, location, submission, matches, opts) {
1967
- interruptActiveLoads(); // Put us in a submitting state
1968
-
1722
+ interruptActiveLoads();
1723
+ // Put us in a submitting state
1969
1724
  let navigation = _extends({
1970
1725
  state: "submitting",
1971
1726
  location
1972
1727
  }, submission);
1973
-
1974
1728
  updateState({
1975
1729
  navigation
1976
- }); // Call our action and get the result
1977
-
1730
+ });
1731
+ // Call our action and get the result
1978
1732
  let result;
1979
1733
  let actionMatch = getTargetMatch(matches, location);
1980
-
1981
1734
  if (!actionMatch.route.action && !actionMatch.route.lazy) {
1982
1735
  result = {
1983
1736
  type: ResultType.error,
@@ -1989,17 +1742,14 @@ function createRouter(init) {
1989
1742
  };
1990
1743
  } else {
1991
1744
  result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename);
1992
-
1993
1745
  if (request.signal.aborted) {
1994
1746
  return {
1995
1747
  shortCircuited: true
1996
1748
  };
1997
1749
  }
1998
1750
  }
1999
-
2000
1751
  if (isRedirectResult(result)) {
2001
1752
  let replace;
2002
-
2003
1753
  if (opts && opts.replace != null) {
2004
1754
  replace = opts.replace;
2005
1755
  } else {
@@ -2008,7 +1758,6 @@ function createRouter(init) {
2008
1758
  // double back-buttons
2009
1759
  replace = result.location === state.location.pathname + state.location.search;
2010
1760
  }
2011
-
2012
1761
  await startRedirectNavigation(state, result, {
2013
1762
  submission,
2014
1763
  replace
@@ -2017,19 +1766,17 @@ function createRouter(init) {
2017
1766
  shortCircuited: true
2018
1767
  };
2019
1768
  }
2020
-
2021
1769
  if (isErrorResult(result)) {
2022
1770
  // Store off the pending error - we use it to determine which loaders
2023
1771
  // to call and will commit it when we complete the navigation
2024
- let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id); // By default, all submissions are REPLACE navigations, but if the
1772
+ let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
1773
+ // By default, all submissions are REPLACE navigations, but if the
2025
1774
  // action threw an error that'll be rendered in an errorElement, we fall
2026
1775
  // back to PUSH so that the user can use the back button to get back to
2027
1776
  // the pre-submission form location to try again
2028
-
2029
1777
  if ((opts && opts.replace) !== true) {
2030
1778
  pendingAction = Action.Push;
2031
1779
  }
2032
-
2033
1780
  return {
2034
1781
  // Send back an empty object we can use to clear out any prior actionData
2035
1782
  pendingActionData: {},
@@ -2038,26 +1785,22 @@ function createRouter(init) {
2038
1785
  }
2039
1786
  };
2040
1787
  }
2041
-
2042
1788
  if (isDeferredResult(result)) {
2043
1789
  throw getInternalRouterError(400, {
2044
1790
  type: "defer-action"
2045
1791
  });
2046
1792
  }
2047
-
2048
1793
  return {
2049
1794
  pendingActionData: {
2050
1795
  [actionMatch.route.id]: result.data
2051
1796
  }
2052
1797
  };
2053
- } // Call all applicable loaders for the given matches, handling redirects,
1798
+ }
1799
+ // Call all applicable loaders for the given matches, handling redirects,
2054
1800
  // errors, etc.
2055
-
2056
-
2057
1801
  async function handleLoaders(request, location, matches, overrideNavigation, submission, fetcherSubmission, replace, pendingActionData, pendingError) {
2058
1802
  // Figure out the right navigation we want to use for data loading
2059
1803
  let loadingNavigation = overrideNavigation;
2060
-
2061
1804
  if (!loadingNavigation) {
2062
1805
  let navigation = _extends({
2063
1806
  state: "loading",
@@ -2067,12 +1810,10 @@ function createRouter(init) {
2067
1810
  formEncType: undefined,
2068
1811
  formData: undefined
2069
1812
  }, submission);
2070
-
2071
1813
  loadingNavigation = navigation;
2072
- } // If this was a redirect from an action we don't have a "submission" but
1814
+ }
1815
+ // If this was a redirect from an action we don't have a "submission" but
2073
1816
  // we have it on the loading navigation so use that if available
2074
-
2075
-
2076
1817
  let activeSubmission = submission || fetcherSubmission ? submission || fetcherSubmission : loadingNavigation.formMethod && loadingNavigation.formAction && loadingNavigation.formData && loadingNavigation.formEncType ? {
2077
1818
  formMethod: loadingNavigation.formMethod,
2078
1819
  formAction: loadingNavigation.formAction,
@@ -2080,12 +1821,12 @@ function createRouter(init) {
2080
1821
  formEncType: loadingNavigation.formEncType
2081
1822
  } : undefined;
2082
1823
  let routesToUse = inFlightDataRoutes || dataRoutes;
2083
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError); // Cancel pending deferreds for no-longer-matched routes or routes we're
1824
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError);
1825
+ // Cancel pending deferreds for no-longer-matched routes or routes we're
2084
1826
  // about to reload. Note that if this is an action reload we would have
2085
1827
  // already cancelled all pending deferreds so this would be a no-op
2086
-
2087
- cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId)); // Short circuit if we have no loaders to run
2088
-
1828
+ cancelActiveDeferreds(routeId => !(matches && matches.some(m => m.route.id === routeId)) || matchesToLoad && matchesToLoad.some(m => m.route.id === routeId));
1829
+ // Short circuit if we have no loaders to run
2089
1830
  if (matchesToLoad.length === 0 && revalidatingFetchers.length === 0) {
2090
1831
  let updatedFetchers = markFetchRedirectsDone();
2091
1832
  completeNavigation(location, _extends({
@@ -2101,12 +1842,11 @@ function createRouter(init) {
2101
1842
  return {
2102
1843
  shortCircuited: true
2103
1844
  };
2104
- } // If this is an uninterrupted revalidation, we remain in our current idle
1845
+ }
1846
+ // If this is an uninterrupted revalidation, we remain in our current idle
2105
1847
  // state. If not, we need to switch to our loading state and load data,
2106
1848
  // preserving any new action data or existing action data (in the case of
2107
1849
  // a revalidation interrupting an actionReload)
2108
-
2109
-
2110
1850
  if (!isUninterruptedRevalidation) {
2111
1851
  revalidatingFetchers.forEach(rf => {
2112
1852
  let fetcher = state.fetchers.get(rf.key);
@@ -2132,7 +1872,6 @@ function createRouter(init) {
2132
1872
  fetchers: new Map(state.fetchers)
2133
1873
  } : {}));
2134
1874
  }
2135
-
2136
1875
  pendingNavigationLoadId = ++incrementingLoadId;
2137
1876
  revalidatingFetchers.forEach(rf => {
2138
1877
  if (rf.controller) {
@@ -2141,37 +1880,31 @@ function createRouter(init) {
2141
1880
  // triggered the revalidation
2142
1881
  fetchControllers.set(rf.key, rf.controller);
2143
1882
  }
2144
- }); // Proxy navigation abort through to revalidation fetchers
2145
-
1883
+ });
1884
+ // Proxy navigation abort through to revalidation fetchers
2146
1885
  let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(f => abortFetcher(f.key));
2147
-
2148
1886
  if (pendingNavigationController) {
2149
1887
  pendingNavigationController.signal.addEventListener("abort", abortPendingFetchRevalidations);
2150
1888
  }
2151
-
2152
1889
  let {
2153
1890
  results,
2154
1891
  loaderResults,
2155
1892
  fetcherResults
2156
1893
  } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, request);
2157
-
2158
1894
  if (request.signal.aborted) {
2159
1895
  return {
2160
1896
  shortCircuited: true
2161
1897
  };
2162
- } // Clean up _after_ loaders have completed. Don't clean up if we short
1898
+ }
1899
+ // Clean up _after_ loaders have completed. Don't clean up if we short
2163
1900
  // circuited because fetchControllers would have been aborted and
2164
1901
  // reassigned to new controllers for the next navigation
2165
-
2166
-
2167
1902
  if (pendingNavigationController) {
2168
1903
  pendingNavigationController.signal.removeEventListener("abort", abortPendingFetchRevalidations);
2169
1904
  }
2170
-
2171
- revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key)); // If any loaders returned a redirect Response, start a new REPLACE navigation
2172
-
1905
+ revalidatingFetchers.forEach(rf => fetchControllers.delete(rf.key));
1906
+ // If any loaders returned a redirect Response, start a new REPLACE navigation
2173
1907
  let redirect = findRedirect(results);
2174
-
2175
1908
  if (redirect) {
2176
1909
  await startRedirectNavigation(state, redirect, {
2177
1910
  replace
@@ -2179,14 +1912,13 @@ function createRouter(init) {
2179
1912
  return {
2180
1913
  shortCircuited: true
2181
1914
  };
2182
- } // Process and commit output from loaders
2183
-
2184
-
1915
+ }
1916
+ // Process and commit output from loaders
2185
1917
  let {
2186
1918
  loaderData,
2187
1919
  errors
2188
- } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds); // Wire up subscribers to update loaderData as promises settle
2189
-
1920
+ } = processLoaderData(state, matches, matchesToLoad, loaderResults, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds);
1921
+ // Wire up subscribers to update loaderData as promises settle
2190
1922
  activeDeferreds.forEach((deferredData, routeId) => {
2191
1923
  deferredData.subscribe(aborted => {
2192
1924
  // Note: No need to updateState here since the TrackedPromise on
@@ -2207,56 +1939,47 @@ function createRouter(init) {
2207
1939
  fetchers: new Map(state.fetchers)
2208
1940
  } : {});
2209
1941
  }
2210
-
2211
1942
  function getFetcher(key) {
2212
1943
  return state.fetchers.get(key) || IDLE_FETCHER;
2213
- } // Trigger a fetcher load/submit for the given fetcher key
2214
-
2215
-
1944
+ }
1945
+ // Trigger a fetcher load/submit for the given fetcher key
2216
1946
  function fetch(key, routeId, href, opts) {
2217
1947
  if (isServer) {
2218
1948
  throw new Error("router.fetch() was called during the server render, but it shouldn't be. " + "You are likely calling a useFetcher() method in the body of your component. " + "Try moving it to a useEffect or a callback.");
2219
1949
  }
2220
-
2221
1950
  if (fetchControllers.has(key)) abortFetcher(key);
2222
1951
  let routesToUse = inFlightDataRoutes || dataRoutes;
2223
1952
  let normalizedPath = normalizeTo(state.location, state.matches, basename, future.v7_prependBasename, href, routeId, opts == null ? void 0 : opts.relative);
2224
1953
  let matches = matchRoutes(routesToUse, normalizedPath, basename);
2225
-
2226
1954
  if (!matches) {
2227
1955
  setFetcherError(key, routeId, getInternalRouterError(404, {
2228
1956
  pathname: normalizedPath
2229
1957
  }));
2230
1958
  return;
2231
1959
  }
2232
-
2233
1960
  let {
2234
1961
  path,
2235
1962
  submission
2236
1963
  } = normalizeNavigateOptions(future.v7_normalizeFormMethod, true, normalizedPath, opts);
2237
1964
  let match = getTargetMatch(matches, path);
2238
1965
  pendingPreventScrollReset = (opts && opts.preventScrollReset) === true;
2239
-
2240
1966
  if (submission && isMutationMethod(submission.formMethod)) {
2241
1967
  handleFetcherAction(key, routeId, path, match, matches, submission);
2242
1968
  return;
2243
- } // Store off the match so we can call it's shouldRevalidate on subsequent
1969
+ }
1970
+ // Store off the match so we can call it's shouldRevalidate on subsequent
2244
1971
  // revalidations
2245
-
2246
-
2247
1972
  fetchLoadMatches.set(key, {
2248
1973
  routeId,
2249
1974
  path
2250
1975
  });
2251
1976
  handleFetcherLoader(key, routeId, path, match, matches, submission);
2252
- } // Call the action for the matched fetcher.submit(), and then handle redirects,
1977
+ }
1978
+ // Call the action for the matched fetcher.submit(), and then handle redirects,
2253
1979
  // errors, and revalidation
2254
-
2255
-
2256
1980
  async function handleFetcherAction(key, routeId, path, match, requestMatches, submission) {
2257
1981
  interruptActiveLoads();
2258
1982
  fetchLoadMatches.delete(key);
2259
-
2260
1983
  if (!match.route.action && !match.route.lazy) {
2261
1984
  let error = getInternalRouterError(405, {
2262
1985
  method: submission.formMethod,
@@ -2265,49 +1988,41 @@ function createRouter(init) {
2265
1988
  });
2266
1989
  setFetcherError(key, routeId, error);
2267
1990
  return;
2268
- } // Put this fetcher into it's submitting state
2269
-
2270
-
1991
+ }
1992
+ // Put this fetcher into it's submitting state
2271
1993
  let existingFetcher = state.fetchers.get(key);
2272
-
2273
1994
  let fetcher = _extends({
2274
1995
  state: "submitting"
2275
1996
  }, submission, {
2276
1997
  data: existingFetcher && existingFetcher.data,
2277
1998
  " _hasFetcherDoneAnything ": true
2278
1999
  });
2279
-
2280
2000
  state.fetchers.set(key, fetcher);
2281
2001
  updateState({
2282
2002
  fetchers: new Map(state.fetchers)
2283
- }); // Call the action for the fetcher
2284
-
2003
+ });
2004
+ // Call the action for the fetcher
2285
2005
  let abortController = new AbortController();
2286
2006
  let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
2287
2007
  fetchControllers.set(key, abortController);
2288
2008
  let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, manifest, mapRouteProperties, basename);
2289
-
2290
2009
  if (fetchRequest.signal.aborted) {
2291
2010
  // We can delete this so long as we weren't aborted by ou our own fetcher
2292
2011
  // re-submit which would have put _new_ controller is in fetchControllers
2293
2012
  if (fetchControllers.get(key) === abortController) {
2294
2013
  fetchControllers.delete(key);
2295
2014
  }
2296
-
2297
2015
  return;
2298
2016
  }
2299
-
2300
2017
  if (isRedirectResult(actionResult)) {
2301
2018
  fetchControllers.delete(key);
2302
2019
  fetchRedirectIds.add(key);
2303
-
2304
2020
  let loadingFetcher = _extends({
2305
2021
  state: "loading"
2306
2022
  }, submission, {
2307
2023
  data: undefined,
2308
2024
  " _hasFetcherDoneAnything ": true
2309
2025
  });
2310
-
2311
2026
  state.fetchers.set(key, loadingFetcher);
2312
2027
  updateState({
2313
2028
  fetchers: new Map(state.fetchers)
@@ -2316,22 +2031,19 @@ function createRouter(init) {
2316
2031
  submission,
2317
2032
  isFetchActionRedirect: true
2318
2033
  });
2319
- } // Process any non-redirect errors thrown
2320
-
2321
-
2034
+ }
2035
+ // Process any non-redirect errors thrown
2322
2036
  if (isErrorResult(actionResult)) {
2323
2037
  setFetcherError(key, routeId, actionResult.error);
2324
2038
  return;
2325
2039
  }
2326
-
2327
2040
  if (isDeferredResult(actionResult)) {
2328
2041
  throw getInternalRouterError(400, {
2329
2042
  type: "defer-action"
2330
2043
  });
2331
- } // Start the data load for current matches, or the next location if we're
2044
+ }
2045
+ // Start the data load for current matches, or the next location if we're
2332
2046
  // in the middle of a navigation
2333
-
2334
-
2335
2047
  let nextLocation = state.navigation.location || state.location;
2336
2048
  let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
2337
2049
  let routesToUse = inFlightDataRoutes || dataRoutes;
@@ -2339,22 +2051,20 @@ function createRouter(init) {
2339
2051
  invariant(matches, "Didn't find any matches after fetcher action");
2340
2052
  let loadId = ++incrementingLoadId;
2341
2053
  fetchReloadIds.set(key, loadId);
2342
-
2343
2054
  let loadFetcher = _extends({
2344
2055
  state: "loading",
2345
2056
  data: actionResult.data
2346
2057
  }, submission, {
2347
2058
  " _hasFetcherDoneAnything ": true
2348
2059
  });
2349
-
2350
2060
  state.fetchers.set(key, loadFetcher);
2351
2061
  let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, {
2352
2062
  [match.route.id]: actionResult.data
2353
2063
  }, undefined // No need to send through errors since we short circuit above
2354
- ); // Put all revalidating fetchers into the loading state, except for the
2064
+ );
2065
+ // Put all revalidating fetchers into the loading state, except for the
2355
2066
  // current fetcher which we want to keep in it's current loading state which
2356
2067
  // contains it's action submission info + action data
2357
-
2358
2068
  revalidatingFetchers.filter(rf => rf.key !== key).forEach(rf => {
2359
2069
  let staleKey = rf.key;
2360
2070
  let existingFetcher = state.fetchers.get(staleKey);
@@ -2368,7 +2078,6 @@ function createRouter(init) {
2368
2078
  " _hasFetcherDoneAnything ": true
2369
2079
  };
2370
2080
  state.fetchers.set(staleKey, revalidatingFetcher);
2371
-
2372
2081
  if (rf.controller) {
2373
2082
  fetchControllers.set(staleKey, rf.controller);
2374
2083
  }
@@ -2376,49 +2085,47 @@ function createRouter(init) {
2376
2085
  updateState({
2377
2086
  fetchers: new Map(state.fetchers)
2378
2087
  });
2379
-
2380
2088
  let abortPendingFetchRevalidations = () => revalidatingFetchers.forEach(rf => abortFetcher(rf.key));
2381
-
2382
2089
  abortController.signal.addEventListener("abort", abortPendingFetchRevalidations);
2383
2090
  let {
2384
2091
  results,
2385
2092
  loaderResults,
2386
2093
  fetcherResults
2387
2094
  } = await callLoadersAndMaybeResolveData(state.matches, matches, matchesToLoad, revalidatingFetchers, revalidationRequest);
2388
-
2389
2095
  if (abortController.signal.aborted) {
2390
2096
  return;
2391
2097
  }
2392
-
2393
2098
  abortController.signal.removeEventListener("abort", abortPendingFetchRevalidations);
2394
2099
  fetchReloadIds.delete(key);
2395
2100
  fetchControllers.delete(key);
2396
2101
  revalidatingFetchers.forEach(r => fetchControllers.delete(r.key));
2397
2102
  let redirect = findRedirect(results);
2398
-
2399
2103
  if (redirect) {
2400
2104
  return startRedirectNavigation(state, redirect);
2401
- } // Process and commit output from loaders
2402
-
2403
-
2105
+ }
2106
+ // Process and commit output from loaders
2404
2107
  let {
2405
2108
  loaderData,
2406
2109
  errors
2407
2110
  } = processLoaderData(state, state.matches, matchesToLoad, loaderResults, undefined, revalidatingFetchers, fetcherResults, activeDeferreds);
2408
- let doneFetcher = {
2409
- state: "idle",
2410
- data: actionResult.data,
2411
- formMethod: undefined,
2412
- formAction: undefined,
2413
- formEncType: undefined,
2414
- formData: undefined,
2415
- " _hasFetcherDoneAnything ": true
2416
- };
2417
- state.fetchers.set(key, doneFetcher);
2418
- let didAbortFetchLoads = abortStaleFetchLoads(loadId); // If we are currently in a navigation loading state and this fetcher is
2111
+ // Since we let revalidations complete even if the submitting fetcher was
2112
+ // deleted, only put it back to idle if it hasn't been deleted
2113
+ if (state.fetchers.has(key)) {
2114
+ let doneFetcher = {
2115
+ state: "idle",
2116
+ data: actionResult.data,
2117
+ formMethod: undefined,
2118
+ formAction: undefined,
2119
+ formEncType: undefined,
2120
+ formData: undefined,
2121
+ " _hasFetcherDoneAnything ": true
2122
+ };
2123
+ state.fetchers.set(key, doneFetcher);
2124
+ }
2125
+ let didAbortFetchLoads = abortStaleFetchLoads(loadId);
2126
+ // If we are currently in a navigation loading state and this fetcher is
2419
2127
  // more recent than the navigation, we want the newer data so abort the
2420
2128
  // navigation and complete it with the fetcher data
2421
-
2422
2129
  if (state.navigation.state === "loading" && loadId > pendingNavigationLoadId) {
2423
2130
  invariant(pendingAction, "Expected pending action");
2424
2131
  pendingNavigationController && pendingNavigationController.abort();
@@ -2435,17 +2142,16 @@ function createRouter(init) {
2435
2142
  updateState(_extends({
2436
2143
  errors,
2437
2144
  loaderData: mergeLoaderData(state.loaderData, loaderData, matches, errors)
2438
- }, didAbortFetchLoads ? {
2145
+ }, didAbortFetchLoads || revalidatingFetchers.length > 0 ? {
2439
2146
  fetchers: new Map(state.fetchers)
2440
2147
  } : {}));
2441
2148
  isRevalidationRequired = false;
2442
2149
  }
2443
- } // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
2444
-
2445
-
2150
+ }
2151
+ // Call the matched loader for fetcher.load(), handling redirects, errors, etc.
2446
2152
  async function handleFetcherLoader(key, routeId, path, match, matches, submission) {
2447
- let existingFetcher = state.fetchers.get(key); // Put this fetcher into it's loading state
2448
-
2153
+ let existingFetcher = state.fetchers.get(key);
2154
+ // Put this fetcher into it's loading state
2449
2155
  let loadingFetcher = _extends({
2450
2156
  state: "loading",
2451
2157
  formMethod: undefined,
@@ -2456,48 +2162,43 @@ function createRouter(init) {
2456
2162
  data: existingFetcher && existingFetcher.data,
2457
2163
  " _hasFetcherDoneAnything ": true
2458
2164
  });
2459
-
2460
2165
  state.fetchers.set(key, loadingFetcher);
2461
2166
  updateState({
2462
2167
  fetchers: new Map(state.fetchers)
2463
- }); // Call the loader for this fetcher route match
2464
-
2168
+ });
2169
+ // Call the loader for this fetcher route match
2465
2170
  let abortController = new AbortController();
2466
2171
  let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
2467
2172
  fetchControllers.set(key, abortController);
2468
- let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename); // Deferred isn't supported for fetcher loads, await everything and treat it
2173
+ let result = await callLoaderOrAction("loader", fetchRequest, match, matches, manifest, mapRouteProperties, basename);
2174
+ // Deferred isn't supported for fetcher loads, await everything and treat it
2469
2175
  // as a normal load. resolveDeferredData will return undefined if this
2470
2176
  // fetcher gets aborted, so we just leave result untouched and short circuit
2471
2177
  // below if that happens
2472
-
2473
2178
  if (isDeferredResult(result)) {
2474
2179
  result = (await resolveDeferredData(result, fetchRequest.signal, true)) || result;
2475
- } // We can delete this so long as we weren't aborted by our our own fetcher
2180
+ }
2181
+ // We can delete this so long as we weren't aborted by our our own fetcher
2476
2182
  // re-load which would have put _new_ controller is in fetchControllers
2477
-
2478
-
2479
2183
  if (fetchControllers.get(key) === abortController) {
2480
2184
  fetchControllers.delete(key);
2481
2185
  }
2482
-
2483
2186
  if (fetchRequest.signal.aborted) {
2484
2187
  return;
2485
- } // If the loader threw a redirect Response, start a new REPLACE navigation
2486
-
2487
-
2188
+ }
2189
+ // If the loader threw a redirect Response, start a new REPLACE navigation
2488
2190
  if (isRedirectResult(result)) {
2489
2191
  fetchRedirectIds.add(key);
2490
2192
  await startRedirectNavigation(state, result);
2491
2193
  return;
2492
- } // Process any non-redirect errors thrown
2493
-
2494
-
2194
+ }
2195
+ // Process any non-redirect errors thrown
2495
2196
  if (isErrorResult(result)) {
2496
2197
  let boundaryMatch = findNearestBoundary(state.matches, routeId);
2497
- state.fetchers.delete(key); // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
2198
+ state.fetchers.delete(key);
2199
+ // TODO: In remix, this would reset to IDLE_NAVIGATION if it was a catch -
2498
2200
  // do we need to behave any differently with our non-redirect errors?
2499
2201
  // What if it was a non-redirect Response?
2500
-
2501
2202
  updateState({
2502
2203
  fetchers: new Map(state.fetchers),
2503
2204
  errors: {
@@ -2506,9 +2207,8 @@ function createRouter(init) {
2506
2207
  });
2507
2208
  return;
2508
2209
  }
2509
-
2510
- invariant(!isDeferredResult(result), "Unhandled fetcher deferred data"); // Put the fetcher back into an idle state
2511
-
2210
+ invariant(!isDeferredResult(result), "Unhandled fetcher deferred data");
2211
+ // Put the fetcher back into an idle state
2512
2212
  let doneFetcher = {
2513
2213
  state: "idle",
2514
2214
  data: result.data,
@@ -2542,57 +2242,47 @@ function createRouter(init) {
2542
2242
  * actually touch history until we've processed redirects, so we just use
2543
2243
  * the history action from the original navigation (PUSH or REPLACE).
2544
2244
  */
2545
-
2546
-
2547
2245
  async function startRedirectNavigation(state, redirect, _temp) {
2548
- var _window;
2549
-
2550
2246
  let {
2551
2247
  submission,
2552
2248
  replace,
2553
2249
  isFetchActionRedirect
2554
2250
  } = _temp === void 0 ? {} : _temp;
2555
-
2556
2251
  if (redirect.revalidate) {
2557
2252
  isRevalidationRequired = true;
2558
2253
  }
2559
-
2560
2254
  let redirectLocation = createLocation(state.location, redirect.location, // TODO: This can be removed once we get rid of useTransition in Remix v2
2561
2255
  _extends({
2562
2256
  _isRedirect: true
2563
2257
  }, isFetchActionRedirect ? {
2564
2258
  _isFetchActionRedirect: true
2565
2259
  } : {}));
2566
- invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an absolute external redirect that goes to a new origin
2567
-
2568
- if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser && typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
2260
+ invariant(redirectLocation, "Expected a location on the redirect navigation");
2261
+ // Check if this an absolute external redirect that goes to a new origin
2262
+ if (ABSOLUTE_URL_REGEX.test(redirect.location) && isBrowser) {
2569
2263
  let url = init.history.createURL(redirect.location);
2570
2264
  let isDifferentBasename = stripBasename(url.pathname, basename) == null;
2571
-
2572
- if (window.location.origin !== url.origin || isDifferentBasename) {
2265
+ if (routerWindow.location.origin !== url.origin || isDifferentBasename) {
2573
2266
  if (replace) {
2574
- window.location.replace(redirect.location);
2267
+ routerWindow.location.replace(redirect.location);
2575
2268
  } else {
2576
- window.location.assign(redirect.location);
2269
+ routerWindow.location.assign(redirect.location);
2577
2270
  }
2578
-
2579
2271
  return;
2580
2272
  }
2581
- } // There's no need to abort on redirects, since we don't detect the
2273
+ }
2274
+ // There's no need to abort on redirects, since we don't detect the
2582
2275
  // redirect until the action/loaders have settled
2583
-
2584
-
2585
2276
  pendingNavigationController = null;
2586
- let redirectHistoryAction = replace === true ? Action.Replace : Action.Push; // Use the incoming submission if provided, fallback on the active one in
2277
+ let redirectHistoryAction = replace === true ? Action.Replace : Action.Push;
2278
+ // Use the incoming submission if provided, fallback on the active one in
2587
2279
  // state.navigation
2588
-
2589
2280
  let {
2590
2281
  formMethod,
2591
2282
  formAction,
2592
2283
  formEncType,
2593
2284
  formData
2594
2285
  } = state.navigation;
2595
-
2596
2286
  if (!submission && formMethod && formAction && formData && formEncType) {
2597
2287
  submission = {
2598
2288
  formMethod,
@@ -2600,11 +2290,10 @@ function createRouter(init) {
2600
2290
  formEncType,
2601
2291
  formData
2602
2292
  };
2603
- } // If this was a 307/308 submission we want to preserve the HTTP method and
2293
+ }
2294
+ // If this was a 307/308 submission we want to preserve the HTTP method and
2604
2295
  // re-submit the GET/POST/PUT/PATCH/DELETE as a submission navigation to the
2605
2296
  // redirected location
2606
-
2607
-
2608
2297
  if (redirectPreserveMethodStatusCodes.has(redirect.status) && submission && isMutationMethod(submission.formMethod)) {
2609
2298
  await startNavigation(redirectHistoryAction, redirectLocation, {
2610
2299
  submission: _extends({}, submission, {
@@ -2646,7 +2335,6 @@ function createRouter(init) {
2646
2335
  });
2647
2336
  }
2648
2337
  }
2649
-
2650
2338
  async function callLoadersAndMaybeResolveData(currentMatches, matches, matchesToLoad, fetchersToLoad, request) {
2651
2339
  // Call all navigation loaders and revalidating fetcher loaders in parallel,
2652
2340
  // then slice off the results into separate arrays so we can handle them
@@ -2673,14 +2361,13 @@ function createRouter(init) {
2673
2361
  fetcherResults
2674
2362
  };
2675
2363
  }
2676
-
2677
2364
  function interruptActiveLoads() {
2678
2365
  // Every interruption triggers a revalidation
2679
- isRevalidationRequired = true; // Cancel pending route-level deferreds and mark cancelled routes for
2366
+ isRevalidationRequired = true;
2367
+ // Cancel pending route-level deferreds and mark cancelled routes for
2680
2368
  // revalidation
2681
-
2682
- cancelledDeferredRoutes.push(...cancelActiveDeferreds()); // Abort in-flight fetcher loads
2683
-
2369
+ cancelledDeferredRoutes.push(...cancelActiveDeferreds());
2370
+ // Abort in-flight fetcher loads
2684
2371
  fetchLoadMatches.forEach((_, key) => {
2685
2372
  if (fetchControllers.has(key)) {
2686
2373
  cancelledFetcherLoads.push(key);
@@ -2688,7 +2375,6 @@ function createRouter(init) {
2688
2375
  }
2689
2376
  });
2690
2377
  }
2691
-
2692
2378
  function setFetcherError(key, routeId, error) {
2693
2379
  let boundaryMatch = findNearestBoundary(state.matches, routeId);
2694
2380
  deleteFetcher(key);
@@ -2699,22 +2385,25 @@ function createRouter(init) {
2699
2385
  fetchers: new Map(state.fetchers)
2700
2386
  });
2701
2387
  }
2702
-
2703
2388
  function deleteFetcher(key) {
2704
- if (fetchControllers.has(key)) abortFetcher(key);
2389
+ let fetcher = state.fetchers.get(key);
2390
+ // Don't abort the controller if this is a deletion of a fetcher.submit()
2391
+ // in it's loading phase since - we don't want to abort the corresponding
2392
+ // revalidation and want them to complete and land
2393
+ if (fetchControllers.has(key) && !(fetcher && fetcher.state === "loading" && fetchReloadIds.has(key))) {
2394
+ abortFetcher(key);
2395
+ }
2705
2396
  fetchLoadMatches.delete(key);
2706
2397
  fetchReloadIds.delete(key);
2707
2398
  fetchRedirectIds.delete(key);
2708
2399
  state.fetchers.delete(key);
2709
2400
  }
2710
-
2711
2401
  function abortFetcher(key) {
2712
2402
  let controller = fetchControllers.get(key);
2713
2403
  invariant(controller, "Expected fetch controller: " + key);
2714
2404
  controller.abort();
2715
2405
  fetchControllers.delete(key);
2716
2406
  }
2717
-
2718
2407
  function markFetchersDone(keys) {
2719
2408
  for (let key of keys) {
2720
2409
  let fetcher = getFetcher(key);
@@ -2730,34 +2419,27 @@ function createRouter(init) {
2730
2419
  state.fetchers.set(key, doneFetcher);
2731
2420
  }
2732
2421
  }
2733
-
2734
2422
  function markFetchRedirectsDone() {
2735
2423
  let doneKeys = [];
2736
2424
  let updatedFetchers = false;
2737
-
2738
2425
  for (let key of fetchRedirectIds) {
2739
2426
  let fetcher = state.fetchers.get(key);
2740
2427
  invariant(fetcher, "Expected fetcher: " + key);
2741
-
2742
2428
  if (fetcher.state === "loading") {
2743
2429
  fetchRedirectIds.delete(key);
2744
2430
  doneKeys.push(key);
2745
2431
  updatedFetchers = true;
2746
2432
  }
2747
2433
  }
2748
-
2749
2434
  markFetchersDone(doneKeys);
2750
2435
  return updatedFetchers;
2751
2436
  }
2752
-
2753
2437
  function abortStaleFetchLoads(landedId) {
2754
2438
  let yeetedKeys = [];
2755
-
2756
2439
  for (let [key, id] of fetchReloadIds) {
2757
2440
  if (id < landedId) {
2758
2441
  let fetcher = state.fetchers.get(key);
2759
2442
  invariant(fetcher, "Expected fetcher: " + key);
2760
-
2761
2443
  if (fetcher.state === "loading") {
2762
2444
  abortFetcher(key);
2763
2445
  fetchReloadIds.delete(key);
@@ -2765,67 +2447,55 @@ function createRouter(init) {
2765
2447
  }
2766
2448
  }
2767
2449
  }
2768
-
2769
2450
  markFetchersDone(yeetedKeys);
2770
2451
  return yeetedKeys.length > 0;
2771
2452
  }
2772
-
2773
2453
  function getBlocker(key, fn) {
2774
2454
  let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2775
-
2776
2455
  if (blockerFunctions.get(key) !== fn) {
2777
2456
  blockerFunctions.set(key, fn);
2778
2457
  }
2779
-
2780
2458
  return blocker;
2781
2459
  }
2782
-
2783
2460
  function deleteBlocker(key) {
2784
2461
  state.blockers.delete(key);
2785
2462
  blockerFunctions.delete(key);
2786
- } // Utility function to update blockers, ensuring valid state transitions
2787
-
2788
-
2463
+ }
2464
+ // Utility function to update blockers, ensuring valid state transitions
2789
2465
  function updateBlocker(key, newBlocker) {
2790
- let blocker = state.blockers.get(key) || IDLE_BLOCKER; // Poor mans state machine :)
2466
+ let blocker = state.blockers.get(key) || IDLE_BLOCKER;
2467
+ // Poor mans state machine :)
2791
2468
  // https://mermaid.live/edit#pako:eNqVkc9OwzAMxl8l8nnjAYrEtDIOHEBIgwvKJTReGy3_lDpIqO27k6awMG0XcrLlnz87nwdonESogKXXBuE79rq75XZO3-yHds0RJVuv70YrPlUrCEe2HfrORS3rubqZfuhtpg5C9wk5tZ4VKcRUq88q9Z8RS0-48cE1iHJkL0ugbHuFLus9L6spZy8nX9MP2CNdomVaposqu3fGayT8T8-jJQwhepo_UtpgBQaDEUom04dZhAN1aJBDlUKJBxE1ceB2Smj0Mln-IBW5AFU2dwUiktt_2Qaq2dBfaKdEup85UV7Yd-dKjlnkabl2Pvr0DTkTreM
2792
-
2793
2469
  invariant(blocker.state === "unblocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "blocked" || blocker.state === "blocked" && newBlocker.state === "proceeding" || blocker.state === "blocked" && newBlocker.state === "unblocked" || blocker.state === "proceeding" && newBlocker.state === "unblocked", "Invalid blocker state transition: " + blocker.state + " -> " + newBlocker.state);
2794
2470
  state.blockers.set(key, newBlocker);
2795
2471
  updateState({
2796
2472
  blockers: new Map(state.blockers)
2797
2473
  });
2798
2474
  }
2799
-
2800
2475
  function shouldBlockNavigation(_ref2) {
2801
2476
  let {
2802
2477
  currentLocation,
2803
2478
  nextLocation,
2804
2479
  historyAction
2805
2480
  } = _ref2;
2806
-
2807
2481
  if (blockerFunctions.size === 0) {
2808
2482
  return;
2809
- } // We ony support a single active blocker at the moment since we don't have
2483
+ }
2484
+ // We ony support a single active blocker at the moment since we don't have
2810
2485
  // any compelling use cases for multi-blocker yet
2811
-
2812
-
2813
2486
  if (blockerFunctions.size > 1) {
2814
2487
  warning(false, "A router only supports one blocker at a time");
2815
2488
  }
2816
-
2817
2489
  let entries = Array.from(blockerFunctions.entries());
2818
2490
  let [blockerKey, blockerFunction] = entries[entries.length - 1];
2819
2491
  let blocker = state.blockers.get(blockerKey);
2820
-
2821
2492
  if (blocker && blocker.state === "proceeding") {
2822
2493
  // If the blocker is currently proceeding, we don't need to re-check
2823
2494
  // it and can let this navigation continue
2824
2495
  return;
2825
- } // At this point, we know we're unblocked/blocked so we need to check the
2496
+ }
2497
+ // At this point, we know we're unblocked/blocked so we need to check the
2826
2498
  // user-provided blocker function
2827
-
2828
-
2829
2499
  if (blockerFunction({
2830
2500
  currentLocation,
2831
2501
  nextLocation,
@@ -2834,7 +2504,6 @@ function createRouter(init) {
2834
2504
  return blockerKey;
2835
2505
  }
2836
2506
  }
2837
-
2838
2507
  function cancelActiveDeferreds(predicate) {
2839
2508
  let cancelledRouteIds = [];
2840
2509
  activeDeferreds.forEach((dfd, routeId) => {
@@ -2848,37 +2517,31 @@ function createRouter(init) {
2848
2517
  }
2849
2518
  });
2850
2519
  return cancelledRouteIds;
2851
- } // Opt in to capturing and reporting scroll positions during navigations,
2520
+ }
2521
+ // Opt in to capturing and reporting scroll positions during navigations,
2852
2522
  // used by the <ScrollRestoration> component
2853
-
2854
-
2855
2523
  function enableScrollRestoration(positions, getPosition, getKey) {
2856
2524
  savedScrollPositions = positions;
2857
2525
  getScrollPosition = getPosition;
2858
-
2859
- getScrollRestorationKey = getKey || (location => location.key); // Perform initial hydration scroll restoration, since we miss the boat on
2526
+ getScrollRestorationKey = getKey || (location => location.key);
2527
+ // Perform initial hydration scroll restoration, since we miss the boat on
2860
2528
  // the initial updateState() because we've not yet rendered <ScrollRestoration/>
2861
2529
  // and therefore have no savedScrollPositions available
2862
-
2863
-
2864
2530
  if (!initialScrollRestored && state.navigation === IDLE_NAVIGATION) {
2865
2531
  initialScrollRestored = true;
2866
2532
  let y = getSavedScrollPosition(state.location, state.matches);
2867
-
2868
2533
  if (y != null) {
2869
2534
  updateState({
2870
2535
  restoreScrollPosition: y
2871
2536
  });
2872
2537
  }
2873
2538
  }
2874
-
2875
2539
  return () => {
2876
2540
  savedScrollPositions = null;
2877
2541
  getScrollPosition = null;
2878
2542
  getScrollRestorationKey = null;
2879
2543
  };
2880
2544
  }
2881
-
2882
2545
  function saveScrollPosition(location, matches) {
2883
2546
  if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
2884
2547
  let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
@@ -2886,39 +2549,31 @@ function createRouter(init) {
2886
2549
  savedScrollPositions[key] = getScrollPosition();
2887
2550
  }
2888
2551
  }
2889
-
2890
2552
  function getSavedScrollPosition(location, matches) {
2891
2553
  if (savedScrollPositions && getScrollRestorationKey && getScrollPosition) {
2892
2554
  let userMatches = matches.map(m => createUseMatchesMatch(m, state.loaderData));
2893
2555
  let key = getScrollRestorationKey(location, userMatches) || location.key;
2894
2556
  let y = savedScrollPositions[key];
2895
-
2896
2557
  if (typeof y === "number") {
2897
2558
  return y;
2898
2559
  }
2899
2560
  }
2900
-
2901
2561
  return null;
2902
2562
  }
2903
-
2904
2563
  function _internalSetRoutes(newRoutes) {
2905
2564
  manifest = {};
2906
2565
  inFlightDataRoutes = convertRoutesToDataRoutes(newRoutes, mapRouteProperties, undefined, manifest);
2907
2566
  }
2908
-
2909
2567
  router = {
2910
2568
  get basename() {
2911
2569
  return basename;
2912
2570
  },
2913
-
2914
2571
  get state() {
2915
2572
  return state;
2916
2573
  },
2917
-
2918
2574
  get routes() {
2919
2575
  return dataRoutes;
2920
2576
  },
2921
-
2922
2577
  initialize,
2923
2578
  subscribe,
2924
2579
  enableScrollRestoration,
@@ -2941,31 +2596,28 @@ function createRouter(init) {
2941
2596
  _internalSetRoutes
2942
2597
  };
2943
2598
  return router;
2944
- } //#endregion
2599
+ }
2600
+ //#endregion
2945
2601
  ////////////////////////////////////////////////////////////////////////////////
2946
2602
  //#region createStaticHandler
2947
2603
  ////////////////////////////////////////////////////////////////////////////////
2948
-
2949
2604
  const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
2950
2605
  function createStaticHandler(routes, opts) {
2951
2606
  invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
2952
2607
  let manifest = {};
2953
2608
  let basename = (opts ? opts.basename : null) || "/";
2954
2609
  let mapRouteProperties;
2955
-
2956
2610
  if (opts != null && opts.mapRouteProperties) {
2957
2611
  mapRouteProperties = opts.mapRouteProperties;
2958
2612
  } else if (opts != null && opts.detectErrorBoundary) {
2959
2613
  // If they are still using the deprecated version, wrap it with the new API
2960
2614
  let detectErrorBoundary = opts.detectErrorBoundary;
2961
-
2962
2615
  mapRouteProperties = route => ({
2963
2616
  hasErrorBoundary: detectErrorBoundary(route)
2964
2617
  });
2965
2618
  } else {
2966
2619
  mapRouteProperties = defaultMapRouteProperties;
2967
2620
  }
2968
-
2969
2621
  let dataRoutes = convertRoutesToDataRoutes(routes, mapRouteProperties, undefined, manifest);
2970
2622
  /**
2971
2623
  * The query() method is intended for document requests, in which we want to
@@ -2986,7 +2638,6 @@ function createStaticHandler(routes, opts) {
2986
2638
  * propagate that out and return the raw Response so the HTTP server can
2987
2639
  * return it directly.
2988
2640
  */
2989
-
2990
2641
  async function query(request, _temp2) {
2991
2642
  let {
2992
2643
  requestContext
@@ -2994,8 +2645,8 @@ function createStaticHandler(routes, opts) {
2994
2645
  let url = new URL(request.url);
2995
2646
  let method = request.method;
2996
2647
  let location = createLocation("", createPath(url), null, "default");
2997
- let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
2998
-
2648
+ let matches = matchRoutes(dataRoutes, location, basename);
2649
+ // SSR supports HEAD requests while SPA doesn't
2999
2650
  if (!isValidMethod(method) && method !== "HEAD") {
3000
2651
  let error = getInternalRouterError(405, {
3001
2652
  method
@@ -3041,16 +2692,13 @@ function createStaticHandler(routes, opts) {
3041
2692
  activeDeferreds: null
3042
2693
  };
3043
2694
  }
3044
-
3045
2695
  let result = await queryImpl(request, location, matches, requestContext);
3046
-
3047
2696
  if (isResponse(result)) {
3048
2697
  return result;
3049
- } // When returning StaticHandlerContext, we patch back in the location here
2698
+ }
2699
+ // When returning StaticHandlerContext, we patch back in the location here
3050
2700
  // since we need it for React Context. But this helps keep our submit and
3051
2701
  // loadRouteData operating on a Request instead of a Location
3052
-
3053
-
3054
2702
  return _extends({
3055
2703
  location,
3056
2704
  basename
@@ -3076,8 +2724,6 @@ function createStaticHandler(routes, opts) {
3076
2724
  * code. Examples here are 404 and 405 errors that occur prior to reaching
3077
2725
  * any user-defined loaders.
3078
2726
  */
3079
-
3080
-
3081
2727
  async function queryRoute(request, _temp3) {
3082
2728
  let {
3083
2729
  routeId,
@@ -3086,8 +2732,8 @@ function createStaticHandler(routes, opts) {
3086
2732
  let url = new URL(request.url);
3087
2733
  let method = request.method;
3088
2734
  let location = createLocation("", createPath(url), null, "default");
3089
- let matches = matchRoutes(dataRoutes, location, basename); // SSR supports HEAD requests while SPA doesn't
3090
-
2735
+ let matches = matchRoutes(dataRoutes, location, basename);
2736
+ // SSR supports HEAD requests while SPA doesn't
3091
2737
  if (!isValidMethod(method) && method !== "HEAD" && method !== "OPTIONS") {
3092
2738
  throw getInternalRouterError(405, {
3093
2739
  method
@@ -3097,9 +2743,7 @@ function createStaticHandler(routes, opts) {
3097
2743
  pathname: location.pathname
3098
2744
  });
3099
2745
  }
3100
-
3101
2746
  let match = routeId ? matches.find(m => m.route.id === routeId) : getTargetMatch(matches, location);
3102
-
3103
2747
  if (routeId && !match) {
3104
2748
  throw getInternalRouterError(403, {
3105
2749
  pathname: location.pathname,
@@ -3111,52 +2755,39 @@ function createStaticHandler(routes, opts) {
3111
2755
  pathname: location.pathname
3112
2756
  });
3113
2757
  }
3114
-
3115
2758
  let result = await queryImpl(request, location, matches, requestContext, match);
3116
-
3117
2759
  if (isResponse(result)) {
3118
2760
  return result;
3119
2761
  }
3120
-
3121
2762
  let error = result.errors ? Object.values(result.errors)[0] : undefined;
3122
-
3123
2763
  if (error !== undefined) {
3124
2764
  // If we got back result.errors, that means the loader/action threw
3125
2765
  // _something_ that wasn't a Response, but it's not guaranteed/required
3126
2766
  // to be an `instanceof Error` either, so we have to use throw here to
3127
2767
  // preserve the "error" state outside of queryImpl.
3128
2768
  throw error;
3129
- } // Pick off the right state value to return
3130
-
3131
-
2769
+ }
2770
+ // Pick off the right state value to return
3132
2771
  if (result.actionData) {
3133
2772
  return Object.values(result.actionData)[0];
3134
2773
  }
3135
-
3136
2774
  if (result.loaderData) {
3137
2775
  var _result$activeDeferre;
3138
-
3139
2776
  let data = Object.values(result.loaderData)[0];
3140
-
3141
2777
  if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {
3142
2778
  data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];
3143
2779
  }
3144
-
3145
2780
  return data;
3146
2781
  }
3147
-
3148
2782
  return undefined;
3149
2783
  }
3150
-
3151
2784
  async function queryImpl(request, location, matches, requestContext, routeMatch) {
3152
2785
  invariant(request.signal, "query()/queryRoute() requests must contain an AbortController signal");
3153
-
3154
2786
  try {
3155
2787
  if (isMutationMethod(request.method.toLowerCase())) {
3156
2788
  let result = await submit(request, matches, routeMatch || getTargetMatch(matches, location), requestContext, routeMatch != null);
3157
2789
  return result;
3158
2790
  }
3159
-
3160
2791
  let result = await loadRouteData(request, matches, requestContext, routeMatch);
3161
2792
  return isResponse(result) ? result : _extends({}, result, {
3162
2793
  actionData: null,
@@ -3170,47 +2801,38 @@ function createStaticHandler(routes, opts) {
3170
2801
  if (e.type === ResultType.error && !isRedirectResponse(e.response)) {
3171
2802
  throw e.response;
3172
2803
  }
3173
-
3174
2804
  return e.response;
3175
- } // Redirects are always returned since they don't propagate to catch
2805
+ }
2806
+ // Redirects are always returned since they don't propagate to catch
3176
2807
  // boundaries
3177
-
3178
-
3179
2808
  if (isRedirectResponse(e)) {
3180
2809
  return e;
3181
2810
  }
3182
-
3183
2811
  throw e;
3184
2812
  }
3185
2813
  }
3186
-
3187
2814
  async function submit(request, matches, actionMatch, requestContext, isRouteRequest) {
3188
2815
  let result;
3189
-
3190
2816
  if (!actionMatch.route.action && !actionMatch.route.lazy) {
3191
2817
  let error = getInternalRouterError(405, {
3192
2818
  method: request.method,
3193
2819
  pathname: new URL(request.url).pathname,
3194
2820
  routeId: actionMatch.route.id
3195
2821
  });
3196
-
3197
2822
  if (isRouteRequest) {
3198
2823
  throw error;
3199
2824
  }
3200
-
3201
2825
  result = {
3202
2826
  type: ResultType.error,
3203
2827
  error
3204
2828
  };
3205
2829
  } else {
3206
2830
  result = await callLoaderOrAction("action", request, actionMatch, matches, manifest, mapRouteProperties, basename, true, isRouteRequest, requestContext);
3207
-
3208
2831
  if (request.signal.aborted) {
3209
2832
  let method = isRouteRequest ? "queryRoute" : "query";
3210
2833
  throw new Error(method + "() call aborted");
3211
2834
  }
3212
2835
  }
3213
-
3214
2836
  if (isRedirectResult(result)) {
3215
2837
  // Uhhhh - this should never happen, we should always throw these from
3216
2838
  // callLoaderOrAction, but the type narrowing here keeps TS happy and we
@@ -3223,29 +2845,24 @@ function createStaticHandler(routes, opts) {
3223
2845
  }
3224
2846
  });
3225
2847
  }
3226
-
3227
2848
  if (isDeferredResult(result)) {
3228
2849
  let error = getInternalRouterError(400, {
3229
2850
  type: "defer-action"
3230
2851
  });
3231
-
3232
2852
  if (isRouteRequest) {
3233
2853
  throw error;
3234
2854
  }
3235
-
3236
2855
  result = {
3237
2856
  type: ResultType.error,
3238
2857
  error
3239
2858
  };
3240
2859
  }
3241
-
3242
2860
  if (isRouteRequest) {
3243
2861
  // Note: This should only be non-Response values if we get here, since
3244
2862
  // isRouteRequest should throw any Response received in callLoaderOrAction
3245
2863
  if (isErrorResult(result)) {
3246
2864
  throw result.error;
3247
2865
  }
3248
-
3249
2866
  return {
3250
2867
  matches: [actionMatch],
3251
2868
  loaderData: {},
@@ -3261,15 +2878,14 @@ function createStaticHandler(routes, opts) {
3261
2878
  activeDeferreds: null
3262
2879
  };
3263
2880
  }
3264
-
3265
2881
  if (isErrorResult(result)) {
3266
2882
  // Store off the pending error - we use it to determine which loaders
3267
2883
  // to call and will commit it when we complete the navigation
3268
2884
  let boundaryMatch = findNearestBoundary(matches, actionMatch.route.id);
3269
2885
  let context = await loadRouteData(request, matches, requestContext, undefined, {
3270
2886
  [boundaryMatch.route.id]: result.error
3271
- }); // action status codes take precedence over loader status codes
3272
-
2887
+ });
2888
+ // action status codes take precedence over loader status codes
3273
2889
  return _extends({}, context, {
3274
2890
  statusCode: isRouteErrorResponse(result.error) ? result.error.status : 500,
3275
2891
  actionData: null,
@@ -3277,9 +2893,8 @@ function createStaticHandler(routes, opts) {
3277
2893
  [actionMatch.route.id]: result.headers
3278
2894
  } : {})
3279
2895
  });
3280
- } // Create a GET request for the loaders
3281
-
3282
-
2896
+ }
2897
+ // Create a GET request for the loaders
3283
2898
  let loaderRequest = new Request(request.url, {
3284
2899
  headers: request.headers,
3285
2900
  redirect: request.redirect,
@@ -3297,10 +2912,9 @@ function createStaticHandler(routes, opts) {
3297
2912
  } : {})
3298
2913
  });
3299
2914
  }
3300
-
3301
2915
  async function loadRouteData(request, matches, requestContext, routeMatch, pendingActionError) {
3302
- let isRouteRequest = routeMatch != null; // Short circuit if we have no loaders to run (queryRoute())
3303
-
2916
+ let isRouteRequest = routeMatch != null;
2917
+ // Short circuit if we have no loaders to run (queryRoute())
3304
2918
  if (isRouteRequest && !(routeMatch != null && routeMatch.route.loader) && !(routeMatch != null && routeMatch.route.lazy)) {
3305
2919
  throw getInternalRouterError(400, {
3306
2920
  method: request.method,
@@ -3308,10 +2922,9 @@ function createStaticHandler(routes, opts) {
3308
2922
  routeId: routeMatch == null ? void 0 : routeMatch.route.id
3309
2923
  });
3310
2924
  }
3311
-
3312
2925
  let requestMatches = routeMatch ? [routeMatch] : getLoaderMatchesUntilBoundary(matches, Object.keys(pendingActionError || {})[0]);
3313
- let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy); // Short circuit if we have no loaders to run (query())
3314
-
2926
+ let matchesToLoad = requestMatches.filter(m => m.route.loader || m.route.lazy);
2927
+ // Short circuit if we have no loaders to run (query())
3315
2928
  if (matchesToLoad.length === 0) {
3316
2929
  return {
3317
2930
  matches,
@@ -3325,18 +2938,15 @@ function createStaticHandler(routes, opts) {
3325
2938
  activeDeferreds: null
3326
2939
  };
3327
2940
  }
3328
-
3329
2941
  let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, manifest, mapRouteProperties, basename, true, isRouteRequest, requestContext))]);
3330
-
3331
2942
  if (request.signal.aborted) {
3332
2943
  let method = isRouteRequest ? "queryRoute" : "query";
3333
2944
  throw new Error(method + "() call aborted");
3334
- } // Process and commit output from loaders
3335
-
3336
-
2945
+ }
2946
+ // Process and commit output from loaders
3337
2947
  let activeDeferreds = new Map();
3338
- let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client
3339
-
2948
+ let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds);
2949
+ // Add a null for any non-loader matches for proper revalidation on the client
3340
2950
  let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));
3341
2951
  matches.forEach(match => {
3342
2952
  if (!executedLoaders.has(match.route.id)) {
@@ -3348,22 +2958,20 @@ function createStaticHandler(routes, opts) {
3348
2958
  activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null
3349
2959
  });
3350
2960
  }
3351
-
3352
2961
  return {
3353
2962
  dataRoutes,
3354
2963
  query,
3355
2964
  queryRoute
3356
2965
  };
3357
- } //#endregion
2966
+ }
2967
+ //#endregion
3358
2968
  ////////////////////////////////////////////////////////////////////////////////
3359
2969
  //#region Helpers
3360
2970
  ////////////////////////////////////////////////////////////////////////////////
3361
-
3362
2971
  /**
3363
2972
  * Given an existing StaticHandlerContext and an error thrown at render time,
3364
2973
  * provide an updated StaticHandlerContext suitable for a second SSR render
3365
2974
  */
3366
-
3367
2975
  function getStaticContextFromError(routes, context, error) {
3368
2976
  let newContext = _extends({}, context, {
3369
2977
  statusCode: 500,
@@ -3371,28 +2979,22 @@ function getStaticContextFromError(routes, context, error) {
3371
2979
  [context._deepestRenderedBoundaryId || routes[0].id]: error
3372
2980
  }
3373
2981
  });
3374
-
3375
2982
  return newContext;
3376
2983
  }
3377
-
3378
2984
  function isSubmissionNavigation(opts) {
3379
2985
  return opts != null && "formData" in opts;
3380
2986
  }
3381
-
3382
2987
  function normalizeTo(location, matches, basename, prependBasename, to, fromRouteId, relative) {
3383
2988
  let contextualMatches;
3384
2989
  let activeRouteMatch;
3385
-
3386
2990
  if (fromRouteId != null && relative !== "path") {
3387
2991
  // Grab matches up to the calling route so our route-relative logic is
3388
2992
  // relative to the correct source route. When using relative:path,
3389
2993
  // fromRouteId is ignored since that is always relative to the current
3390
2994
  // location path
3391
2995
  contextualMatches = [];
3392
-
3393
2996
  for (let match of matches) {
3394
2997
  contextualMatches.push(match);
3395
-
3396
2998
  if (match.route.id === fromRouteId) {
3397
2999
  activeRouteMatch = match;
3398
3000
  break;
@@ -3401,36 +3003,31 @@ function normalizeTo(location, matches, basename, prependBasename, to, fromRoute
3401
3003
  } else {
3402
3004
  contextualMatches = matches;
3403
3005
  activeRouteMatch = matches[matches.length - 1];
3404
- } // Resolve the relative path
3405
-
3406
-
3407
- let path = resolveTo(to ? to : ".", getPathContributingMatches(contextualMatches).map(m => m.pathnameBase), stripBasename(location.pathname, basename) || location.pathname, relative === "path"); // When `to` is not specified we inherit search/hash from the current
3006
+ }
3007
+ // Resolve the relative path
3008
+ let path = resolveTo(to ? to : ".", getPathContributingMatches(contextualMatches).map(m => m.pathnameBase), stripBasename(location.pathname, basename) || location.pathname, relative === "path");
3009
+ // When `to` is not specified we inherit search/hash from the current
3408
3010
  // location, unlike when to="." and we just inherit the path.
3409
3011
  // See https://github.com/remix-run/remix/issues/927
3410
-
3411
3012
  if (to == null) {
3412
3013
  path.search = location.search;
3413
3014
  path.hash = location.hash;
3414
- } // Add an ?index param for matched index routes if we don't already have one
3415
-
3416
-
3015
+ }
3016
+ // Add an ?index param for matched index routes if we don't already have one
3417
3017
  if ((to == null || to === "" || to === ".") && activeRouteMatch && activeRouteMatch.route.index && !hasNakedIndexQuery(path.search)) {
3418
3018
  path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
3419
- } // If we're operating within a basename, prepend it to the pathname. If
3019
+ }
3020
+ // If we're operating within a basename, prepend it to the pathname. If
3420
3021
  // this is a root navigation, then just use the raw basename which allows
3421
3022
  // the basename to have full control over the presence of a trailing slash
3422
3023
  // on root actions
3423
-
3424
-
3425
3024
  if (prependBasename && basename !== "/") {
3426
3025
  path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
3427
3026
  }
3428
-
3429
3027
  return createPath(path);
3430
- } // Normalize navigation options by converting formMethod=GET formData objects to
3028
+ }
3029
+ // Normalize navigation options by converting formMethod=GET formData objects to
3431
3030
  // URLSearchParams so they behave identically to links with query params
3432
-
3433
-
3434
3031
  function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
3435
3032
  // Return location verbatim on non-submission navigations
3436
3033
  if (!opts || !isSubmissionNavigation(opts)) {
@@ -3438,7 +3035,6 @@ function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
3438
3035
  path
3439
3036
  };
3440
3037
  }
3441
-
3442
3038
  if (opts.formMethod && !isValidMethod(opts.formMethod)) {
3443
3039
  return {
3444
3040
  path,
@@ -3446,11 +3042,9 @@ function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
3446
3042
  method: opts.formMethod
3447
3043
  })
3448
3044
  };
3449
- } // Create a Submission on non-GET navigations
3450
-
3451
-
3045
+ }
3046
+ // Create a Submission on non-GET navigations
3452
3047
  let submission;
3453
-
3454
3048
  if (opts.formData) {
3455
3049
  let formMethod = opts.formMethod || "get";
3456
3050
  submission = {
@@ -3459,53 +3053,45 @@ function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
3459
3053
  formEncType: opts && opts.formEncType || "application/x-www-form-urlencoded",
3460
3054
  formData: opts.formData
3461
3055
  };
3462
-
3463
3056
  if (isMutationMethod(submission.formMethod)) {
3464
3057
  return {
3465
3058
  path,
3466
3059
  submission
3467
3060
  };
3468
3061
  }
3469
- } // Flatten submission onto URLSearchParams for GET submissions
3470
-
3471
-
3062
+ }
3063
+ // Flatten submission onto URLSearchParams for GET submissions
3472
3064
  let parsedPath = parsePath(path);
3473
- let searchParams = convertFormDataToSearchParams(opts.formData); // On GET navigation submissions we can drop the ?index param from the
3065
+ let searchParams = convertFormDataToSearchParams(opts.formData);
3066
+ // On GET navigation submissions we can drop the ?index param from the
3474
3067
  // resulting location since all loaders will run. But fetcher GET submissions
3475
3068
  // only run a single loader so we need to preserve any incoming ?index params
3476
-
3477
3069
  if (isFetcher && parsedPath.search && hasNakedIndexQuery(parsedPath.search)) {
3478
3070
  searchParams.append("index", "");
3479
3071
  }
3480
-
3481
3072
  parsedPath.search = "?" + searchParams;
3482
3073
  return {
3483
3074
  path: createPath(parsedPath),
3484
3075
  submission
3485
3076
  };
3486
- } // Filter out all routes below any caught error as they aren't going to
3077
+ }
3078
+ // Filter out all routes below any caught error as they aren't going to
3487
3079
  // render so we don't need to load them
3488
-
3489
-
3490
3080
  function getLoaderMatchesUntilBoundary(matches, boundaryId) {
3491
3081
  let boundaryMatches = matches;
3492
-
3493
3082
  if (boundaryId) {
3494
3083
  let index = matches.findIndex(m => m.route.id === boundaryId);
3495
-
3496
3084
  if (index >= 0) {
3497
3085
  boundaryMatches = matches.slice(0, index);
3498
3086
  }
3499
3087
  }
3500
-
3501
3088
  return boundaryMatches;
3502
3089
  }
3503
-
3504
3090
  function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, fetchLoadMatches, routesToUse, basename, pendingActionData, pendingError) {
3505
3091
  let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined;
3506
3092
  let currentUrl = history.createURL(state.location);
3507
- let nextUrl = history.createURL(location); // Pick navigation matches that are net-new or qualify for revalidation
3508
-
3093
+ let nextUrl = history.createURL(location);
3094
+ // Pick navigation matches that are net-new or qualify for revalidation
3509
3095
  let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
3510
3096
  let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
3511
3097
  let navigationMatches = boundaryMatches.filter((match, index) => {
@@ -3513,20 +3099,17 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3513
3099
  // We haven't loaded this route yet so we don't know if it's got a loader!
3514
3100
  return true;
3515
3101
  }
3516
-
3517
3102
  if (match.route.loader == null) {
3518
3103
  return false;
3519
- } // Always call the loader on new route instances and pending defer cancellations
3520
-
3521
-
3104
+ }
3105
+ // Always call the loader on new route instances and pending defer cancellations
3522
3106
  if (isNewLoader(state.loaderData, state.matches[index], match) || cancelledDeferredRoutes.some(id => id === match.route.id)) {
3523
3107
  return true;
3524
- } // This is the default implementation for when we revalidate. If the route
3108
+ }
3109
+ // This is the default implementation for when we revalidate. If the route
3525
3110
  // provides it's own implementation, then we give them full control but
3526
3111
  // provide this value so they can leverage it if needed after they check
3527
3112
  // their own specific use cases
3528
-
3529
-
3530
3113
  let currentRouteMatch = state.matches[index];
3531
3114
  let nextRouteMatch = match;
3532
3115
  return shouldRevalidateLoader(match, _extends({
@@ -3536,23 +3119,25 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3536
3119
  nextParams: nextRouteMatch.params
3537
3120
  }, submission, {
3538
3121
  actionResult,
3539
- defaultShouldRevalidate: // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
3540
- isRevalidationRequired || // Clicked the same link, resubmitted a GET form
3541
- currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search || // Search params affect all loaders
3122
+ defaultShouldRevalidate:
3123
+ // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
3124
+ isRevalidationRequired ||
3125
+ // Clicked the same link, resubmitted a GET form
3126
+ currentUrl.pathname + currentUrl.search === nextUrl.pathname + nextUrl.search ||
3127
+ // Search params affect all loaders
3542
3128
  currentUrl.search !== nextUrl.search || isNewRouteInstance(currentRouteMatch, nextRouteMatch)
3543
3129
  }));
3544
- }); // Pick fetcher.loads that need to be revalidated
3545
-
3130
+ });
3131
+ // Pick fetcher.loads that need to be revalidated
3546
3132
  let revalidatingFetchers = [];
3547
3133
  fetchLoadMatches.forEach((f, key) => {
3548
3134
  // Don't revalidate if fetcher won't be present in the subsequent render
3549
3135
  if (!matches.some(m => m.route.id === f.routeId)) {
3550
3136
  return;
3551
3137
  }
3552
-
3553
- let fetcherMatches = matchRoutes(routesToUse, f.path, basename); // If the fetcher path no longer matches, push it in with null matches so
3138
+ let fetcherMatches = matchRoutes(routesToUse, f.path, basename);
3139
+ // If the fetcher path no longer matches, push it in with null matches so
3554
3140
  // we can trigger a 404 in callLoadersAndMaybeResolveData
3555
-
3556
3141
  if (!fetcherMatches) {
3557
3142
  revalidatingFetchers.push({
3558
3143
  key,
@@ -3564,9 +3149,7 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3564
3149
  });
3565
3150
  return;
3566
3151
  }
3567
-
3568
3152
  let fetcherMatch = getTargetMatch(fetcherMatches, f.path);
3569
-
3570
3153
  if (cancelledFetcherLoads.includes(key)) {
3571
3154
  revalidatingFetchers.push({
3572
3155
  key,
@@ -3577,12 +3160,11 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3577
3160
  controller: new AbortController()
3578
3161
  });
3579
3162
  return;
3580
- } // Revalidating fetchers are decoupled from the route matches since they
3163
+ }
3164
+ // Revalidating fetchers are decoupled from the route matches since they
3581
3165
  // hit a static href, so they _always_ check shouldRevalidate and the
3582
3166
  // default is strictly if a revalidation is explicitly required (action
3583
3167
  // submissions, useRevalidator, X-Remix-Revalidate).
3584
-
3585
-
3586
3168
  let shouldRevalidate = shouldRevalidateLoader(fetcherMatch, _extends({
3587
3169
  currentUrl,
3588
3170
  currentParams: state.matches[state.matches.length - 1].params,
@@ -3593,7 +3175,6 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3593
3175
  // Forced revalidation due to submission, useRevalidator, or X-Remix-Revalidate
3594
3176
  defaultShouldRevalidate: isRevalidationRequired
3595
3177
  }));
3596
-
3597
3178
  if (shouldRevalidate) {
3598
3179
  revalidatingFetchers.push({
3599
3180
  key,
@@ -3607,36 +3188,35 @@ function getMatchesToLoad(history, state, matches, submission, location, isReval
3607
3188
  });
3608
3189
  return [navigationMatches, revalidatingFetchers];
3609
3190
  }
3610
-
3611
3191
  function isNewLoader(currentLoaderData, currentMatch, match) {
3612
- let isNew = // [a] -> [a, b]
3613
- !currentMatch || // [a, b] -> [a, c]
3614
- match.route.id !== currentMatch.route.id; // Handle the case that we don't have data for a re-used route, potentially
3192
+ let isNew =
3193
+ // [a] -> [a, b]
3194
+ !currentMatch ||
3195
+ // [a, b] -> [a, c]
3196
+ match.route.id !== currentMatch.route.id;
3197
+ // Handle the case that we don't have data for a re-used route, potentially
3615
3198
  // from a prior error or from a cancelled pending deferred
3616
-
3617
- let isMissingData = currentLoaderData[match.route.id] === undefined; // Always load if this is a net-new route or we don't yet have data
3618
-
3199
+ let isMissingData = currentLoaderData[match.route.id] === undefined;
3200
+ // Always load if this is a net-new route or we don't yet have data
3619
3201
  return isNew || isMissingData;
3620
3202
  }
3621
-
3622
3203
  function isNewRouteInstance(currentMatch, match) {
3623
3204
  let currentPath = currentMatch.route.path;
3624
- return (// param change for this match, /users/123 -> /users/456
3625
- currentMatch.pathname !== match.pathname || // splat param changed, which is not present in match.path
3205
+ return (
3206
+ // param change for this match, /users/123 -> /users/456
3207
+ currentMatch.pathname !== match.pathname ||
3208
+ // splat param changed, which is not present in match.path
3626
3209
  // e.g. /files/images/avatar.jpg -> files/finances.xls
3627
3210
  currentPath != null && currentPath.endsWith("*") && currentMatch.params["*"] !== match.params["*"]
3628
3211
  );
3629
3212
  }
3630
-
3631
3213
  function shouldRevalidateLoader(loaderMatch, arg) {
3632
3214
  if (loaderMatch.route.shouldRevalidate) {
3633
3215
  let routeChoice = loaderMatch.route.shouldRevalidate(arg);
3634
-
3635
3216
  if (typeof routeChoice === "boolean") {
3636
3217
  return routeChoice;
3637
3218
  }
3638
3219
  }
3639
-
3640
3220
  return arg.defaultShouldRevalidate;
3641
3221
  }
3642
3222
  /**
@@ -3644,23 +3224,20 @@ function shouldRevalidateLoader(loaderMatch, arg) {
3644
3224
  * shouldRevalidate) and update the routeManifest in place which shares objects
3645
3225
  * with dataRoutes so those get updated as well.
3646
3226
  */
3647
-
3648
-
3649
3227
  async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
3650
3228
  if (!route.lazy) {
3651
3229
  return;
3652
3230
  }
3653
-
3654
- let lazyRoute = await route.lazy(); // If the lazy route function was executed and removed by another parallel
3231
+ let lazyRoute = await route.lazy();
3232
+ // If the lazy route function was executed and removed by another parallel
3655
3233
  // call then we can return - first lazy() to finish wins because the return
3656
3234
  // value of lazy is expected to be static
3657
-
3658
3235
  if (!route.lazy) {
3659
3236
  return;
3660
3237
  }
3661
-
3662
3238
  let routeToUpdate = manifest[route.id];
3663
- invariant(routeToUpdate, "No route found in manifest"); // Update the route in place. This should be safe because there's no way
3239
+ invariant(routeToUpdate, "No route found in manifest");
3240
+ // Update the route in place. This should be safe because there's no way
3664
3241
  // we could yet be sitting on this route as we can't get there without
3665
3242
  // resolving lazy() first.
3666
3243
  //
@@ -3668,52 +3245,43 @@ async function loadLazyRouteModule(route, mapRouteProperties, manifest) {
3668
3245
  // on the route being updated. The main concern boils down to "does this
3669
3246
  // mutation affect any ongoing navigations or any current state.matches
3670
3247
  // values?". If not, it should be safe to update in place.
3671
-
3672
3248
  let routeUpdates = {};
3673
-
3674
3249
  for (let lazyRouteProperty in lazyRoute) {
3675
3250
  let staticRouteValue = routeToUpdate[lazyRouteProperty];
3676
- let isPropertyStaticallyDefined = staticRouteValue !== undefined && // This property isn't static since it should always be updated based
3251
+ let isPropertyStaticallyDefined = staticRouteValue !== undefined &&
3252
+ // This property isn't static since it should always be updated based
3677
3253
  // on the route updates
3678
3254
  lazyRouteProperty !== "hasErrorBoundary";
3679
3255
  warning(!isPropertyStaticallyDefined, "Route \"" + routeToUpdate.id + "\" has a static property \"" + lazyRouteProperty + "\" " + "defined but its lazy function is also returning a value for this property. " + ("The lazy route property \"" + lazyRouteProperty + "\" will be ignored."));
3680
-
3681
3256
  if (!isPropertyStaticallyDefined && !immutableRouteKeys.has(lazyRouteProperty)) {
3682
3257
  routeUpdates[lazyRouteProperty] = lazyRoute[lazyRouteProperty];
3683
3258
  }
3684
- } // Mutate the route with the provided updates. Do this first so we pass
3259
+ }
3260
+ // Mutate the route with the provided updates. Do this first so we pass
3685
3261
  // the updated version to mapRouteProperties
3686
-
3687
-
3688
- Object.assign(routeToUpdate, routeUpdates); // Mutate the `hasErrorBoundary` property on the route based on the route
3262
+ Object.assign(routeToUpdate, routeUpdates);
3263
+ // Mutate the `hasErrorBoundary` property on the route based on the route
3689
3264
  // updates and remove the `lazy` function so we don't resolve the lazy
3690
3265
  // route again.
3691
-
3692
3266
  Object.assign(routeToUpdate, _extends({}, mapRouteProperties(routeToUpdate), {
3693
3267
  lazy: undefined
3694
3268
  }));
3695
3269
  }
3696
-
3697
3270
  async function callLoaderOrAction(type, request, match, matches, manifest, mapRouteProperties, basename, isStaticRequest, isRouteRequest, requestContext) {
3698
3271
  if (isStaticRequest === void 0) {
3699
3272
  isStaticRequest = false;
3700
3273
  }
3701
-
3702
3274
  if (isRouteRequest === void 0) {
3703
3275
  isRouteRequest = false;
3704
3276
  }
3705
-
3706
3277
  let resultType;
3707
3278
  let result;
3708
3279
  let onReject;
3709
-
3710
3280
  let runHandler = handler => {
3711
3281
  // Setup a promise we can race against so that abort signals short circuit
3712
3282
  let reject;
3713
3283
  let abortPromise = new Promise((_, r) => reject = r);
3714
-
3715
3284
  onReject = () => reject();
3716
-
3717
3285
  request.signal.addEventListener("abort", onReject);
3718
3286
  return Promise.race([handler({
3719
3287
  request,
@@ -3721,10 +3289,8 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3721
3289
  context: requestContext
3722
3290
  }), abortPromise]);
3723
3291
  };
3724
-
3725
3292
  try {
3726
3293
  let handler = match.route[type];
3727
-
3728
3294
  if (match.route.lazy) {
3729
3295
  if (handler) {
3730
3296
  // Run statically defined handler in parallel with lazy()
@@ -3734,7 +3300,6 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3734
3300
  // Load lazy route module, then run any returned handler
3735
3301
  await loadLazyRouteModule(match.route, mapRouteProperties, manifest);
3736
3302
  handler = match.route[type];
3737
-
3738
3303
  if (handler) {
3739
3304
  // Handler still run even if we got interrupted to maintain consistency
3740
3305
  // with un-abortable behavior of handler execution on non-lazy or
@@ -3766,7 +3331,6 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3766
3331
  } else {
3767
3332
  result = await runHandler(handler);
3768
3333
  }
3769
-
3770
3334
  invariant(result !== undefined, "You defined " + (type === "action" ? "an action" : "a loader") + " for route " + ("\"" + match.route.id + "\" but didn't return anything from your `" + type + "` ") + "function. Please return a value or `null`.");
3771
3335
  } catch (e) {
3772
3336
  resultType = ResultType.error;
@@ -3776,14 +3340,13 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3776
3340
  request.signal.removeEventListener("abort", onReject);
3777
3341
  }
3778
3342
  }
3779
-
3780
3343
  if (isResponse(result)) {
3781
- let status = result.status; // Process redirects
3782
-
3344
+ let status = result.status;
3345
+ // Process redirects
3783
3346
  if (redirectStatusCodes.has(status)) {
3784
3347
  let location = result.headers.get("Location");
3785
- invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header"); // Support relative routing in internal redirects
3786
-
3348
+ invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
3349
+ // Support relative routing in internal redirects
3787
3350
  if (!ABSOLUTE_URL_REGEX.test(location)) {
3788
3351
  location = normalizeTo(new URL(request.url), matches.slice(0, matches.indexOf(match) + 1), basename, true, location);
3789
3352
  } else if (!isStaticRequest) {
@@ -3793,32 +3356,28 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3793
3356
  let currentUrl = new URL(request.url);
3794
3357
  let url = location.startsWith("//") ? new URL(currentUrl.protocol + location) : new URL(location);
3795
3358
  let isSameBasename = stripBasename(url.pathname, basename) != null;
3796
-
3797
3359
  if (url.origin === currentUrl.origin && isSameBasename) {
3798
3360
  location = url.pathname + url.search + url.hash;
3799
3361
  }
3800
- } // Don't process redirects in the router during static requests requests.
3362
+ }
3363
+ // Don't process redirects in the router during static requests requests.
3801
3364
  // Instead, throw the Response and let the server handle it with an HTTP
3802
3365
  // redirect. We also update the Location header in place in this flow so
3803
3366
  // basename and relative routing is taken into account
3804
-
3805
-
3806
3367
  if (isStaticRequest) {
3807
3368
  result.headers.set("Location", location);
3808
3369
  throw result;
3809
3370
  }
3810
-
3811
3371
  return {
3812
3372
  type: ResultType.redirect,
3813
3373
  status,
3814
3374
  location,
3815
3375
  revalidate: result.headers.get("X-Remix-Revalidate") !== null
3816
3376
  };
3817
- } // For SSR single-route requests, we want to hand Responses back directly
3377
+ }
3378
+ // For SSR single-route requests, we want to hand Responses back directly
3818
3379
  // without unwrapping. We do this with the QueryRouteResponse wrapper
3819
3380
  // interface so we can know whether it was returned or thrown
3820
-
3821
-
3822
3381
  if (isRouteRequest) {
3823
3382
  // eslint-disable-next-line no-throw-literal
3824
3383
  throw {
@@ -3826,17 +3385,15 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3826
3385
  response: result
3827
3386
  };
3828
3387
  }
3829
-
3830
3388
  let data;
3831
- let contentType = result.headers.get("Content-Type"); // Check between word boundaries instead of startsWith() due to the last
3389
+ let contentType = result.headers.get("Content-Type");
3390
+ // Check between word boundaries instead of startsWith() due to the last
3832
3391
  // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
3833
-
3834
3392
  if (contentType && /\bapplication\/json\b/.test(contentType)) {
3835
3393
  data = await result.json();
3836
3394
  } else {
3837
3395
  data = await result.text();
3838
3396
  }
3839
-
3840
3397
  if (resultType === ResultType.error) {
3841
3398
  return {
3842
3399
  type: resultType,
@@ -3844,7 +3401,6 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3844
3401
  headers: result.headers
3845
3402
  };
3846
3403
  }
3847
-
3848
3404
  return {
3849
3405
  type: ResultType.data,
3850
3406
  data,
@@ -3852,17 +3408,14 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3852
3408
  headers: result.headers
3853
3409
  };
3854
3410
  }
3855
-
3856
3411
  if (resultType === ResultType.error) {
3857
3412
  return {
3858
3413
  type: resultType,
3859
3414
  error: result
3860
3415
  };
3861
3416
  }
3862
-
3863
3417
  if (isDeferredData(result)) {
3864
3418
  var _result$init, _result$init2;
3865
-
3866
3419
  return {
3867
3420
  type: ResultType.deferred,
3868
3421
  deferredData: result,
@@ -3870,90 +3423,78 @@ async function callLoaderOrAction(type, request, match, matches, manifest, mapRo
3870
3423
  headers: ((_result$init2 = result.init) == null ? void 0 : _result$init2.headers) && new Headers(result.init.headers)
3871
3424
  };
3872
3425
  }
3873
-
3874
3426
  return {
3875
3427
  type: ResultType.data,
3876
3428
  data: result
3877
3429
  };
3878
- } // Utility method for creating the Request instances for loaders/actions during
3430
+ }
3431
+ // Utility method for creating the Request instances for loaders/actions during
3879
3432
  // client-side navigations and fetches. During SSR we will always have a
3880
3433
  // Request instance from the static handler (query/queryRoute)
3881
-
3882
-
3883
3434
  function createClientSideRequest(history, location, signal, submission) {
3884
3435
  let url = history.createURL(stripHashFromPath(location)).toString();
3885
3436
  let init = {
3886
3437
  signal
3887
3438
  };
3888
-
3889
3439
  if (submission && isMutationMethod(submission.formMethod)) {
3890
3440
  let {
3891
3441
  formMethod,
3892
3442
  formEncType,
3893
3443
  formData
3894
- } = submission; // Didn't think we needed this but it turns out unlike other methods, patch
3444
+ } = submission;
3445
+ // Didn't think we needed this but it turns out unlike other methods, patch
3895
3446
  // won't be properly normalized to uppercase and results in a 405 error.
3896
3447
  // See: https://fetch.spec.whatwg.org/#concept-method
3897
-
3898
3448
  init.method = formMethod.toUpperCase();
3899
3449
  init.body = formEncType === "application/x-www-form-urlencoded" ? convertFormDataToSearchParams(formData) : formData;
3900
- } // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
3901
-
3902
-
3450
+ }
3451
+ // Content-Type is inferred (https://fetch.spec.whatwg.org/#dom-request)
3903
3452
  return new Request(url, init);
3904
3453
  }
3905
-
3906
3454
  function convertFormDataToSearchParams(formData) {
3907
3455
  let searchParams = new URLSearchParams();
3908
-
3909
3456
  for (let [key, value] of formData.entries()) {
3910
3457
  // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs
3911
3458
  searchParams.append(key, value instanceof File ? value.name : value);
3912
3459
  }
3913
-
3914
3460
  return searchParams;
3915
3461
  }
3916
-
3917
3462
  function processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds) {
3918
3463
  // Fill in loaderData/errors from our loaders
3919
3464
  let loaderData = {};
3920
3465
  let errors = null;
3921
3466
  let statusCode;
3922
3467
  let foundError = false;
3923
- let loaderHeaders = {}; // Process loader results into state.loaderData/state.errors
3924
-
3468
+ let loaderHeaders = {};
3469
+ // Process loader results into state.loaderData/state.errors
3925
3470
  results.forEach((result, index) => {
3926
3471
  let id = matchesToLoad[index].route.id;
3927
3472
  invariant(!isRedirectResult(result), "Cannot handle redirect results in processLoaderData");
3928
-
3929
3473
  if (isErrorResult(result)) {
3930
3474
  // Look upwards from the matched route for the closest ancestor
3931
3475
  // error boundary, defaulting to the root match
3932
3476
  let boundaryMatch = findNearestBoundary(matches, id);
3933
- let error = result.error; // If we have a pending action error, we report it at the highest-route
3477
+ let error = result.error;
3478
+ // If we have a pending action error, we report it at the highest-route
3934
3479
  // that throws a loader error, and then clear it out to indicate that
3935
3480
  // it was consumed
3936
-
3937
3481
  if (pendingError) {
3938
3482
  error = Object.values(pendingError)[0];
3939
3483
  pendingError = undefined;
3940
3484
  }
3941
-
3942
- errors = errors || {}; // Prefer higher error values if lower errors bubble to the same boundary
3943
-
3485
+ errors = errors || {};
3486
+ // Prefer higher error values if lower errors bubble to the same boundary
3944
3487
  if (errors[boundaryMatch.route.id] == null) {
3945
3488
  errors[boundaryMatch.route.id] = error;
3946
- } // Clear our any prior loaderData for the throwing route
3947
-
3948
-
3949
- loaderData[id] = undefined; // Once we find our first (highest) error, we set the status code and
3489
+ }
3490
+ // Clear our any prior loaderData for the throwing route
3491
+ loaderData[id] = undefined;
3492
+ // Once we find our first (highest) error, we set the status code and
3950
3493
  // prevent deeper status codes from overriding
3951
-
3952
3494
  if (!foundError) {
3953
3495
  foundError = true;
3954
3496
  statusCode = isRouteErrorResponse(result.error) ? result.error.status : 500;
3955
3497
  }
3956
-
3957
3498
  if (result.headers) {
3958
3499
  loaderHeaders[id] = result.headers;
3959
3500
  }
@@ -3963,27 +3504,24 @@ function processRouteLoaderData(matches, matchesToLoad, results, pendingError, a
3963
3504
  loaderData[id] = result.deferredData.data;
3964
3505
  } else {
3965
3506
  loaderData[id] = result.data;
3966
- } // Error status codes always override success status codes, but if all
3507
+ }
3508
+ // Error status codes always override success status codes, but if all
3967
3509
  // loaders are successful we take the deepest status code.
3968
-
3969
-
3970
3510
  if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
3971
3511
  statusCode = result.statusCode;
3972
3512
  }
3973
-
3974
3513
  if (result.headers) {
3975
3514
  loaderHeaders[id] = result.headers;
3976
3515
  }
3977
3516
  }
3978
- }); // If we didn't consume the pending action error (i.e., all loaders
3517
+ });
3518
+ // If we didn't consume the pending action error (i.e., all loaders
3979
3519
  // resolved), then consume it here. Also clear out any loaderData for the
3980
3520
  // throwing route
3981
-
3982
3521
  if (pendingError) {
3983
3522
  errors = pendingError;
3984
3523
  loaderData[Object.keys(pendingError)[0]] = undefined;
3985
3524
  }
3986
-
3987
3525
  return {
3988
3526
  loaderData,
3989
3527
  errors,
@@ -3991,13 +3529,12 @@ function processRouteLoaderData(matches, matchesToLoad, results, pendingError, a
3991
3529
  loaderHeaders
3992
3530
  };
3993
3531
  }
3994
-
3995
3532
  function processLoaderData(state, matches, matchesToLoad, results, pendingError, revalidatingFetchers, fetcherResults, activeDeferreds) {
3996
3533
  let {
3997
3534
  loaderData,
3998
3535
  errors
3999
- } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds); // Process results from our revalidating fetchers
4000
-
3536
+ } = processRouteLoaderData(matches, matchesToLoad, results, pendingError, activeDeferreds);
3537
+ // Process results from our revalidating fetchers
4001
3538
  for (let index = 0; index < revalidatingFetchers.length; index++) {
4002
3539
  let {
4003
3540
  key,
@@ -4005,20 +3542,18 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
4005
3542
  controller
4006
3543
  } = revalidatingFetchers[index];
4007
3544
  invariant(fetcherResults !== undefined && fetcherResults[index] !== undefined, "Did not find corresponding fetcher result");
4008
- let result = fetcherResults[index]; // Process fetcher non-redirect errors
4009
-
3545
+ let result = fetcherResults[index];
3546
+ // Process fetcher non-redirect errors
4010
3547
  if (controller && controller.signal.aborted) {
4011
3548
  // Nothing to do for aborted fetchers
4012
3549
  continue;
4013
3550
  } else if (isErrorResult(result)) {
4014
3551
  let boundaryMatch = findNearestBoundary(state.matches, match == null ? void 0 : match.route.id);
4015
-
4016
3552
  if (!(errors && errors[boundaryMatch.route.id])) {
4017
3553
  errors = _extends({}, errors, {
4018
3554
  [boundaryMatch.route.id]: result.error
4019
3555
  });
4020
3556
  }
4021
-
4022
3557
  state.fetchers.delete(key);
4023
3558
  } else if (isRedirectResult(result)) {
4024
3559
  // Should never get here, redirects should get processed above, but we
@@ -4041,19 +3576,15 @@ function processLoaderData(state, matches, matchesToLoad, results, pendingError,
4041
3576
  state.fetchers.set(key, doneFetcher);
4042
3577
  }
4043
3578
  }
4044
-
4045
3579
  return {
4046
3580
  loaderData,
4047
3581
  errors
4048
3582
  };
4049
3583
  }
4050
-
4051
3584
  function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
4052
3585
  let mergedLoaderData = _extends({}, newLoaderData);
4053
-
4054
3586
  for (let match of matches) {
4055
3587
  let id = match.route.id;
4056
-
4057
3588
  if (newLoaderData.hasOwnProperty(id)) {
4058
3589
  if (newLoaderData[id] !== undefined) {
4059
3590
  mergedLoaderData[id] = newLoaderData[id];
@@ -4063,24 +3594,20 @@ function mergeLoaderData(loaderData, newLoaderData, matches, errors) {
4063
3594
  // wasn't removed by HMR
4064
3595
  mergedLoaderData[id] = loaderData[id];
4065
3596
  }
4066
-
4067
3597
  if (errors && errors.hasOwnProperty(id)) {
4068
3598
  // Don't keep any loader data below the boundary
4069
3599
  break;
4070
3600
  }
4071
3601
  }
4072
-
4073
3602
  return mergedLoaderData;
4074
- } // Find the nearest error boundary, looking upwards from the leaf route (or the
3603
+ }
3604
+ // Find the nearest error boundary, looking upwards from the leaf route (or the
4075
3605
  // route specified by routeId) for the closest ancestor error boundary,
4076
3606
  // defaulting to the root match
4077
-
4078
-
4079
3607
  function findNearestBoundary(matches, routeId) {
4080
3608
  let eligibleMatches = routeId ? matches.slice(0, matches.findIndex(m => m.route.id === routeId) + 1) : [...matches];
4081
3609
  return eligibleMatches.reverse().find(m => m.route.hasErrorBoundary === true) || matches[0];
4082
3610
  }
4083
-
4084
3611
  function getShortCircuitMatches(routes) {
4085
3612
  // Prefer a root layout route if present, otherwise shim in a route object
4086
3613
  let route = routes.find(r => r.index || !r.path || r.path === "/") || {
@@ -4096,7 +3623,6 @@ function getShortCircuitMatches(routes) {
4096
3623
  route
4097
3624
  };
4098
3625
  }
4099
-
4100
3626
  function getInternalRouterError(status, _temp4) {
4101
3627
  let {
4102
3628
  pathname,
@@ -4106,10 +3632,8 @@ function getInternalRouterError(status, _temp4) {
4106
3632
  } = _temp4 === void 0 ? {} : _temp4;
4107
3633
  let statusText = "Unknown Server Error";
4108
3634
  let errorMessage = "Unknown @remix-run/router error";
4109
-
4110
3635
  if (status === 400) {
4111
3636
  statusText = "Bad Request";
4112
-
4113
3637
  if (method && pathname && routeId) {
4114
3638
  errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
4115
3639
  } else if (type === "defer-action") {
@@ -4123,40 +3647,33 @@ function getInternalRouterError(status, _temp4) {
4123
3647
  errorMessage = "No route matches URL \"" + pathname + "\"";
4124
3648
  } else if (status === 405) {
4125
3649
  statusText = "Method Not Allowed";
4126
-
4127
3650
  if (method && pathname && routeId) {
4128
3651
  errorMessage = "You made a " + method.toUpperCase() + " request to \"" + pathname + "\" but " + ("did not provide an `action` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
4129
3652
  } else if (method) {
4130
3653
  errorMessage = "Invalid request method \"" + method.toUpperCase() + "\"";
4131
3654
  }
4132
3655
  }
4133
-
4134
3656
  return new ErrorResponse(status || 500, statusText, new Error(errorMessage), true);
4135
- } // Find any returned redirect errors, starting from the lowest match
4136
-
4137
-
3657
+ }
3658
+ // Find any returned redirect errors, starting from the lowest match
4138
3659
  function findRedirect(results) {
4139
3660
  for (let i = results.length - 1; i >= 0; i--) {
4140
3661
  let result = results[i];
4141
-
4142
3662
  if (isRedirectResult(result)) {
4143
3663
  return result;
4144
3664
  }
4145
3665
  }
4146
3666
  }
4147
-
4148
3667
  function stripHashFromPath(path) {
4149
3668
  let parsedPath = typeof path === "string" ? parsePath(path) : path;
4150
3669
  return createPath(_extends({}, parsedPath, {
4151
3670
  hash: ""
4152
3671
  }));
4153
3672
  }
4154
-
4155
3673
  function isHashChangeOnly(a, b) {
4156
3674
  if (a.pathname !== b.pathname || a.search !== b.search) {
4157
3675
  return false;
4158
3676
  }
4159
-
4160
3677
  if (a.hash === "") {
4161
3678
  // /page -> /page#hash
4162
3679
  return b.hash !== "";
@@ -4166,70 +3683,56 @@ function isHashChangeOnly(a, b) {
4166
3683
  } else if (b.hash !== "") {
4167
3684
  // /page#hash -> /page#other
4168
3685
  return true;
4169
- } // If the hash is removed the browser will re-perform a request to the server
3686
+ }
3687
+ // If the hash is removed the browser will re-perform a request to the server
4170
3688
  // /page#hash -> /page
4171
-
4172
-
4173
3689
  return false;
4174
3690
  }
4175
-
4176
3691
  function isDeferredResult(result) {
4177
3692
  return result.type === ResultType.deferred;
4178
3693
  }
4179
-
4180
3694
  function isErrorResult(result) {
4181
3695
  return result.type === ResultType.error;
4182
3696
  }
4183
-
4184
3697
  function isRedirectResult(result) {
4185
3698
  return (result && result.type) === ResultType.redirect;
4186
3699
  }
4187
-
4188
3700
  function isDeferredData(value) {
4189
3701
  let deferred = value;
4190
3702
  return deferred && typeof deferred === "object" && typeof deferred.data === "object" && typeof deferred.subscribe === "function" && typeof deferred.cancel === "function" && typeof deferred.resolveData === "function";
4191
3703
  }
4192
-
4193
3704
  function isResponse(value) {
4194
3705
  return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined";
4195
3706
  }
4196
-
4197
3707
  function isRedirectResponse(result) {
4198
3708
  if (!isResponse(result)) {
4199
3709
  return false;
4200
3710
  }
4201
-
4202
3711
  let status = result.status;
4203
3712
  let location = result.headers.get("Location");
4204
3713
  return status >= 300 && status <= 399 && location != null;
4205
3714
  }
4206
-
4207
3715
  function isQueryRouteResponse(obj) {
4208
3716
  return obj && isResponse(obj.response) && (obj.type === ResultType.data || ResultType.error);
4209
3717
  }
4210
-
4211
3718
  function isValidMethod(method) {
4212
3719
  return validRequestMethods.has(method.toLowerCase());
4213
3720
  }
4214
-
4215
3721
  function isMutationMethod(method) {
4216
3722
  return validMutationMethods.has(method.toLowerCase());
4217
3723
  }
4218
-
4219
3724
  async function resolveDeferredResults(currentMatches, matchesToLoad, results, signals, isFetcher, currentLoaderData) {
4220
3725
  for (let index = 0; index < results.length; index++) {
4221
3726
  let result = results[index];
4222
- let match = matchesToLoad[index]; // If we don't have a match, then we can have a deferred result to do
3727
+ let match = matchesToLoad[index];
3728
+ // If we don't have a match, then we can have a deferred result to do
4223
3729
  // anything with. This is for revalidating fetchers where the route was
4224
3730
  // removed during HMR
4225
-
4226
3731
  if (!match) {
4227
3732
  continue;
4228
3733
  }
4229
-
4230
3734
  let currentMatch = currentMatches.find(m => m.route.id === match.route.id);
4231
3735
  let isRevalidatingLoader = currentMatch != null && !isNewRouteInstance(currentMatch, match) && (currentLoaderData && currentLoaderData[match.route.id]) !== undefined;
4232
-
4233
3736
  if (isDeferredResult(result) && (isFetcher || isRevalidatingLoader)) {
4234
3737
  // Note: we do not have to touch activeDeferreds here since we race them
4235
3738
  // against the signal in resolveDeferredData and they'll get aborted
@@ -4244,18 +3747,14 @@ async function resolveDeferredResults(currentMatches, matchesToLoad, results, si
4244
3747
  }
4245
3748
  }
4246
3749
  }
4247
-
4248
3750
  async function resolveDeferredData(result, signal, unwrap) {
4249
3751
  if (unwrap === void 0) {
4250
3752
  unwrap = false;
4251
3753
  }
4252
-
4253
3754
  let aborted = await result.deferredData.resolveData(signal);
4254
-
4255
3755
  if (aborted) {
4256
3756
  return;
4257
3757
  }
4258
-
4259
3758
  if (unwrap) {
4260
3759
  try {
4261
3760
  return {
@@ -4270,19 +3769,16 @@ async function resolveDeferredData(result, signal, unwrap) {
4270
3769
  };
4271
3770
  }
4272
3771
  }
4273
-
4274
3772
  return {
4275
3773
  type: ResultType.data,
4276
3774
  data: result.deferredData.data
4277
3775
  };
4278
3776
  }
4279
-
4280
3777
  function hasNakedIndexQuery(search) {
4281
3778
  return new URLSearchParams(search).getAll("index").some(v => v === "");
4282
- } // Note: This should match the format exported by useMatches, so if you change
3779
+ }
3780
+ // Note: This should match the format exported by useMatches, so if you change
4283
3781
  // this please also change that :) Eventually we'll DRY this up
4284
-
4285
-
4286
3782
  function createUseMatchesMatch(match, loaderData) {
4287
3783
  let {
4288
3784
  route,
@@ -4297,20 +3793,18 @@ function createUseMatchesMatch(match, loaderData) {
4297
3793
  handle: route.handle
4298
3794
  };
4299
3795
  }
4300
-
4301
3796
  function getTargetMatch(matches, location) {
4302
3797
  let search = typeof location === "string" ? parsePath(location).search : location.search;
4303
-
4304
3798
  if (matches[matches.length - 1].route.index && hasNakedIndexQuery(search || "")) {
4305
3799
  // Return the leaf index route when index is present
4306
3800
  return matches[matches.length - 1];
4307
- } // Otherwise grab the deepest "path contributing" match (ignoring index and
3801
+ }
3802
+ // Otherwise grab the deepest "path contributing" match (ignoring index and
4308
3803
  // pathless layout routes)
4309
-
4310
-
4311
3804
  let pathMatches = getPathContributingMatches(matches);
4312
3805
  return pathMatches[pathMatches.length - 1];
4313
- } //#endregion
3806
+ }
3807
+ //#endregion
4314
3808
 
4315
3809
  export { AbortedDeferredError, Action, ErrorResponse, IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, DeferredData as UNSAFE_DeferredData, convertRoutesToDataRoutes as UNSAFE_convertRoutesToDataRoutes, getPathContributingMatches as UNSAFE_getPathContributingMatches, invariant as UNSAFE_invariant, warning as UNSAFE_warning, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, parsePath, redirect, resolvePath, resolveTo, stripBasename };
4316
3810
  //# sourceMappingURL=router.js.map