@remix-run/router 1.2.1 → 1.3.0-pre.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @remix-run/router v1.2.1
2
+ * @remix-run/router v1.3.0-pre.0
3
3
  *
4
4
  * Copyright (c) Remix Software Inc.
5
5
  *
@@ -98,6 +98,10 @@
98
98
  return location;
99
99
  }
100
100
 
101
+ function createHref(to) {
102
+ return typeof to === "string" ? to : createPath(to);
103
+ }
104
+
101
105
  let history = {
102
106
  get index() {
103
107
  return index;
@@ -111,8 +115,10 @@
111
115
  return getCurrentLocation();
112
116
  },
113
117
 
114
- createHref(to) {
115
- return typeof to === "string" ? to : createPath(to);
118
+ createHref,
119
+
120
+ createURL(to) {
121
+ return new URL(createHref(to), "http://localhost");
116
122
  },
117
123
 
118
124
  encodeLocation(to) {
@@ -391,15 +397,6 @@
391
397
 
392
398
  return parsedPath;
393
399
  }
394
- function createClientSideURL(location) {
395
- // window.location.origin is "null" (the literal string value) in Firefox
396
- // under certain conditions, notably when serving from a local HTML file
397
- // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
398
- let base = typeof window !== "undefined" && typeof window.location !== "undefined" && window.location.origin !== "null" ? window.location.origin : window.location.href;
399
- let href = typeof location === "string" ? location : createPath(location);
400
- invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
401
- return new URL(href, base);
402
- }
403
400
 
404
401
  function getUrlBasedHistory(getLocation, createHref, validateLocation, options) {
405
402
  if (options === void 0) {
@@ -464,6 +461,16 @@
464
461
  }
465
462
  }
466
463
 
464
+ function createURL(to) {
465
+ // window.location.origin is "null" (the literal string value) in Firefox
466
+ // under certain conditions, notably when serving from a local HTML file
467
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
468
+ let base = window.location.origin !== "null" ? window.location.origin : window.location.href;
469
+ let href = typeof to === "string" ? to : createPath(to);
470
+ invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
471
+ return new URL(href, base);
472
+ }
473
+
467
474
  let history = {
468
475
  get action() {
469
476
  return action;
@@ -490,9 +497,11 @@
490
497
  return createHref(window, to);
491
498
  },
492
499
 
500
+ createURL,
501
+
493
502
  encodeLocation(to) {
494
503
  // Encode a Location the same way window.location would
495
- let url = createClientSideURL(typeof to === "string" ? to : createPath(to));
504
+ let url = createURL(to);
496
505
  return {
497
506
  pathname: url.pathname,
498
507
  search: url.search,
@@ -809,13 +818,32 @@
809
818
  path = path.replace(/\*$/, "/*");
810
819
  }
811
820
 
812
- return path.replace(/^:(\w+)/g, (_, key) => {
813
- invariant(params[key] != null, "Missing \":" + key + "\" param");
814
- return params[key];
815
- }).replace(/\/:(\w+)/g, (_, key) => {
816
- invariant(params[key] != null, "Missing \":" + key + "\" param");
817
- return "/" + params[key];
818
- }).replace(/(\/?)\*/, (_, prefix, __, str) => {
821
+ return path.replace(/^:(\w+)(\??)/g, (_, key, optional) => {
822
+ let param = params[key];
823
+
824
+ if (optional === "?") {
825
+ return param == null ? "" : param;
826
+ }
827
+
828
+ if (param == null) {
829
+ invariant(false, "Missing \":" + key + "\" param");
830
+ }
831
+
832
+ return param;
833
+ }).replace(/\/:(\w+)(\??)/g, (_, key, optional) => {
834
+ let param = params[key];
835
+
836
+ if (optional === "?") {
837
+ return param == null ? "" : "/" + param;
838
+ }
839
+
840
+ if (param == null) {
841
+ invariant(false, "Missing \":" + key + "\" param");
842
+ }
843
+
844
+ return "/" + param;
845
+ }) // Remove any optional markers from optional static segments
846
+ .replace(/\?/g, "").replace(/(\/?)\*/, (_, prefix, __, str) => {
819
847
  const star = "*";
820
848
 
821
849
  if (params[star] == null) {
@@ -1162,9 +1190,10 @@
1162
1190
  };
1163
1191
  class AbortedDeferredError extends Error {}
1164
1192
  class DeferredData {
1165
- constructor(data) {
1166
- this.pendingKeys = new Set();
1167
- this.subscriber = undefined;
1193
+ constructor(data, responseInit) {
1194
+ this.pendingKeysSet = new Set();
1195
+ this.subscribers = new Set();
1196
+ this.deferredKeys = [];
1168
1197
  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
1169
1198
  // cancellation
1170
1199
 
@@ -1183,6 +1212,7 @@
1183
1212
  [key]: this.trackPromise(key, value)
1184
1213
  });
1185
1214
  }, {});
1215
+ this.init = responseInit;
1186
1216
  }
1187
1217
 
1188
1218
  trackPromise(key, value) {
@@ -1190,7 +1220,8 @@
1190
1220
  return value;
1191
1221
  }
1192
1222
 
1193
- this.pendingKeys.add(key); // We store a little wrapper promise that will be extended with
1223
+ this.deferredKeys.push(key);
1224
+ this.pendingKeysSet.add(key); // We store a little wrapper promise that will be extended with
1194
1225
  // _data/_error props upon resolve/reject
1195
1226
 
1196
1227
  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
@@ -1212,39 +1243,41 @@
1212
1243
  return Promise.reject(error);
1213
1244
  }
1214
1245
 
1215
- this.pendingKeys.delete(key);
1246
+ this.pendingKeysSet.delete(key);
1216
1247
 
1217
1248
  if (this.done) {
1218
1249
  // Nothing left to abort!
1219
1250
  this.unlistenAbortSignal();
1220
1251
  }
1221
1252
 
1222
- const subscriber = this.subscriber;
1223
-
1224
1253
  if (error) {
1225
1254
  Object.defineProperty(promise, "_error", {
1226
1255
  get: () => error
1227
1256
  });
1228
- subscriber && subscriber(false);
1257
+ this.emit(false, key);
1229
1258
  return Promise.reject(error);
1230
1259
  }
1231
1260
 
1232
1261
  Object.defineProperty(promise, "_data", {
1233
1262
  get: () => data
1234
1263
  });
1235
- subscriber && subscriber(false);
1264
+ this.emit(false, key);
1236
1265
  return data;
1237
1266
  }
1238
1267
 
1268
+ emit(aborted, settledKey) {
1269
+ this.subscribers.forEach(subscriber => subscriber(aborted, settledKey));
1270
+ }
1271
+
1239
1272
  subscribe(fn) {
1240
- this.subscriber = fn;
1273
+ this.subscribers.add(fn);
1274
+ return () => this.subscribers.delete(fn);
1241
1275
  }
1242
1276
 
1243
1277
  cancel() {
1244
1278
  this.controller.abort();
1245
- this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));
1246
- let subscriber = this.subscriber;
1247
- subscriber && subscriber(true);
1279
+ this.pendingKeysSet.forEach((v, k) => this.pendingKeysSet.delete(k));
1280
+ this.emit(true);
1248
1281
  }
1249
1282
 
1250
1283
  async resolveData(signal) {
@@ -1269,7 +1302,7 @@
1269
1302
  }
1270
1303
 
1271
1304
  get done() {
1272
- return this.pendingKeys.size === 0;
1305
+ return this.pendingKeysSet.size === 0;
1273
1306
  }
1274
1307
 
1275
1308
  get unwrappedData() {
@@ -1282,6 +1315,10 @@
1282
1315
  }, {});
1283
1316
  }
1284
1317
 
1318
+ get pendingKeys() {
1319
+ return Array.from(this.pendingKeysSet);
1320
+ }
1321
+
1285
1322
  }
1286
1323
 
1287
1324
  function isTrackedPromise(value) {
@@ -1300,9 +1337,16 @@
1300
1337
  return value._data;
1301
1338
  }
1302
1339
 
1303
- function defer(data) {
1304
- return new DeferredData(data);
1305
- }
1340
+ const defer = function defer(data, init) {
1341
+ if (init === void 0) {
1342
+ init = {};
1343
+ }
1344
+
1345
+ let responseInit = typeof init === "number" ? {
1346
+ status: init
1347
+ } : init;
1348
+ return new DeferredData(data, responseInit);
1349
+ };
1306
1350
 
1307
1351
  /**
1308
1352
  * A redirect response. Sets the status code and the `Location` header.
@@ -1728,7 +1772,7 @@
1728
1772
 
1729
1773
 
1730
1774
  pendingNavigationController = new AbortController();
1731
- let request = createClientSideRequest(location, pendingNavigationController.signal, opts && opts.submission);
1775
+ let request = createClientSideRequest(init.history, location, pendingNavigationController.signal, opts && opts.submission);
1732
1776
  let pendingActionData;
1733
1777
  let pendingError;
1734
1778
 
@@ -1869,7 +1913,9 @@
1869
1913
  }
1870
1914
 
1871
1915
  if (isDeferredResult(result)) {
1872
- throw new Error("defer() is not supported in actions");
1916
+ throw getInternalRouterError(400, {
1917
+ type: "defer-action"
1918
+ });
1873
1919
  }
1874
1920
 
1875
1921
  return {
@@ -1906,7 +1952,7 @@
1906
1952
  formData: loadingNavigation.formData,
1907
1953
  formEncType: loadingNavigation.formEncType
1908
1954
  } : undefined;
1909
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
1955
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, activeSubmission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches); // Cancel pending deferreds for no-longer-matched routes or routes we're
1910
1956
  // about to reload. Note that if this is an action reload we would have
1911
1957
  // already cancelled all pending deferreds so this would be a no-op
1912
1958
 
@@ -2088,7 +2134,7 @@
2088
2134
  }); // Call the action for the fetcher
2089
2135
 
2090
2136
  let abortController = new AbortController();
2091
- let fetchRequest = createClientSideRequest(path, abortController.signal, submission);
2137
+ let fetchRequest = createClientSideRequest(init.history, path, abortController.signal, submission);
2092
2138
  fetchControllers.set(key, abortController);
2093
2139
  let actionResult = await callLoaderOrAction("action", fetchRequest, match, requestMatches, router.basename);
2094
2140
 
@@ -2129,13 +2175,15 @@
2129
2175
  }
2130
2176
 
2131
2177
  if (isDeferredResult(actionResult)) {
2132
- invariant(false, "defer() is not supported in actions");
2178
+ throw getInternalRouterError(400, {
2179
+ type: "defer-action"
2180
+ });
2133
2181
  } // Start the data load for current matches, or the next location if we're
2134
2182
  // in the middle of a navigation
2135
2183
 
2136
2184
 
2137
2185
  let nextLocation = state.navigation.location || state.location;
2138
- let revalidationRequest = createClientSideRequest(nextLocation, abortController.signal);
2186
+ let revalidationRequest = createClientSideRequest(init.history, nextLocation, abortController.signal);
2139
2187
  let matches = state.navigation.state !== "idle" ? matchRoutes(dataRoutes, state.navigation.location, init.basename) : state.matches;
2140
2188
  invariant(matches, "Didn't find any matches after fetcher action");
2141
2189
  let loadId = ++incrementingLoadId;
@@ -2149,7 +2197,7 @@
2149
2197
  });
2150
2198
 
2151
2199
  state.fetchers.set(key, loadFetcher);
2152
- let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
2200
+ let [matchesToLoad, revalidatingFetchers] = getMatchesToLoad(init.history, state, matches, submission, nextLocation, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, {
2153
2201
  [match.route.id]: actionResult.data
2154
2202
  }, undefined, // No need to send through errors since we short circuit above
2155
2203
  fetchLoadMatches); // Put all revalidating fetchers into the loading state, except for the
@@ -2262,9 +2310,9 @@
2262
2310
  }); // Call the loader for this fetcher route match
2263
2311
 
2264
2312
  let abortController = new AbortController();
2265
- let fetchRequest = createClientSideRequest(path, abortController.signal);
2313
+ let fetchRequest = createClientSideRequest(init.history, path, abortController.signal);
2266
2314
  fetchControllers.set(key, abortController);
2267
- let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported or fetcher loads, await everything and treat it
2315
+ let result = await callLoaderOrAction("loader", fetchRequest, match, matches, router.basename); // Deferred isn't supported for fetcher loads, await everything and treat it
2268
2316
  // as a normal load. resolveDeferredData will return undefined if this
2269
2317
  // fetcher gets aborted, so we just leave result untouched and short circuit
2270
2318
  // below if that happens
@@ -2364,7 +2412,7 @@
2364
2412
  invariant(redirectLocation, "Expected a location on the redirect navigation"); // Check if this an external redirect that goes to a new origin
2365
2413
 
2366
2414
  if (typeof ((_window = window) == null ? void 0 : _window.location) !== "undefined") {
2367
- let newOrigin = createClientSideURL(redirect.location).origin;
2415
+ let newOrigin = init.history.createURL(redirect.location).origin;
2368
2416
 
2369
2417
  if (window.location.origin !== newOrigin) {
2370
2418
  if (replace) {
@@ -2430,7 +2478,7 @@
2430
2478
  // accordingly
2431
2479
  let results = await Promise.all([...matchesToLoad.map(match => callLoaderOrAction("loader", request, match, matches, router.basename)), ...fetchersToLoad.map(_ref8 => {
2432
2480
  let [, href, match, fetchMatches] = _ref8;
2433
- return callLoaderOrAction("loader", createClientSideRequest(href, request.signal), match, fetchMatches, router.basename);
2481
+ return callLoaderOrAction("loader", createClientSideRequest(init.history, href, request.signal), match, fetchMatches, router.basename);
2434
2482
  })]);
2435
2483
  let loaderResults = results.slice(0, matchesToLoad.length);
2436
2484
  let fetcherResults = results.slice(matchesToLoad.length);
@@ -2639,6 +2687,7 @@
2639
2687
  //#region createStaticHandler
2640
2688
  ////////////////////////////////////////////////////////////////////////////////
2641
2689
 
2690
+ const UNSAFE_DEFERRED_SYMBOL = Symbol("deferred");
2642
2691
  function createStaticHandler(routes, opts) {
2643
2692
  invariant(routes.length > 0, "You must provide a non-empty routes array to createStaticHandler");
2644
2693
  let dataRoutes = convertRoutesToDataRoutes(routes);
@@ -2691,7 +2740,8 @@
2691
2740
  },
2692
2741
  statusCode: error.status,
2693
2742
  loaderHeaders: {},
2694
- actionHeaders: {}
2743
+ actionHeaders: {},
2744
+ activeDeferreds: null
2695
2745
  };
2696
2746
  } else if (!matches) {
2697
2747
  let error = getInternalRouterError(404, {
@@ -2712,7 +2762,8 @@
2712
2762
  },
2713
2763
  statusCode: error.status,
2714
2764
  loaderHeaders: {},
2715
- actionHeaders: {}
2765
+ actionHeaders: {},
2766
+ activeDeferreds: null
2716
2767
  };
2717
2768
  }
2718
2769
 
@@ -2803,8 +2854,23 @@
2803
2854
  } // Pick off the right state value to return
2804
2855
 
2805
2856
 
2806
- let routeData = [result.actionData, result.loaderData].find(v => v);
2807
- return Object.values(routeData || {})[0];
2857
+ if (result.actionData) {
2858
+ return Object.values(result.actionData)[0];
2859
+ }
2860
+
2861
+ if (result.loaderData) {
2862
+ var _result$activeDeferre;
2863
+
2864
+ let data = Object.values(result.loaderData)[0];
2865
+
2866
+ if ((_result$activeDeferre = result.activeDeferreds) != null && _result$activeDeferre[match.route.id]) {
2867
+ data[UNSAFE_DEFERRED_SYMBOL] = result.activeDeferreds[match.route.id];
2868
+ }
2869
+
2870
+ return data;
2871
+ }
2872
+
2873
+ return undefined;
2808
2874
  }
2809
2875
 
2810
2876
  async function queryImpl(request, location, matches, requestContext, routeMatch) {
@@ -2884,7 +2950,18 @@
2884
2950
  }
2885
2951
 
2886
2952
  if (isDeferredResult(result)) {
2887
- throw new Error("defer() is not supported in actions");
2953
+ let error = getInternalRouterError(400, {
2954
+ type: "defer-action"
2955
+ });
2956
+
2957
+ if (isRouteRequest) {
2958
+ throw error;
2959
+ }
2960
+
2961
+ result = {
2962
+ type: ResultType.error,
2963
+ error
2964
+ };
2888
2965
  }
2889
2966
 
2890
2967
  if (isRouteRequest) {
@@ -2905,7 +2982,8 @@
2905
2982
  // return the raw Response or value
2906
2983
  statusCode: 200,
2907
2984
  loaderHeaders: {},
2908
- actionHeaders: {}
2985
+ actionHeaders: {},
2986
+ activeDeferreds: null
2909
2987
  };
2910
2988
  }
2911
2989
 
@@ -2968,7 +3046,8 @@
2968
3046
  }), {}),
2969
3047
  errors: pendingActionError || null,
2970
3048
  statusCode: 200,
2971
- loaderHeaders: {}
3049
+ loaderHeaders: {},
3050
+ activeDeferreds: null
2972
3051
  };
2973
3052
  }
2974
3053
 
@@ -2977,27 +3056,21 @@
2977
3056
  if (request.signal.aborted) {
2978
3057
  let method = isRouteRequest ? "queryRoute" : "query";
2979
3058
  throw new Error(method + "() call aborted");
2980
- }
3059
+ } // Process and commit output from loaders
2981
3060
 
2982
- let executedLoaders = new Set();
2983
- results.forEach((result, i) => {
2984
- executedLoaders.add(matchesToLoad[i].route.id); // Can't do anything with these without the Remix side of things, so just
2985
- // cancel them for now
2986
3061
 
2987
- if (isDeferredResult(result)) {
2988
- result.deferredData.cancel();
2989
- }
2990
- }); // Process and commit output from loaders
2991
-
2992
- let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError); // Add a null for any non-loader matches for proper revalidation on the client
3062
+ let activeDeferreds = new Map();
3063
+ let context = processRouteLoaderData(matches, matchesToLoad, results, pendingActionError, activeDeferreds); // Add a null for any non-loader matches for proper revalidation on the client
2993
3064
 
3065
+ let executedLoaders = new Set(matchesToLoad.map(match => match.route.id));
2994
3066
  matches.forEach(match => {
2995
3067
  if (!executedLoaders.has(match.route.id)) {
2996
3068
  context.loaderData[match.route.id] = null;
2997
3069
  }
2998
3070
  });
2999
3071
  return _extends({}, context, {
3000
- matches
3072
+ matches,
3073
+ activeDeferreds: activeDeferreds.size > 0 ? Object.fromEntries(activeDeferreds.entries()) : null
3001
3074
  });
3002
3075
  }
3003
3076
 
@@ -3116,13 +3189,13 @@
3116
3189
  return boundaryMatches;
3117
3190
  }
3118
3191
 
3119
- function getMatchesToLoad(state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
3192
+ function getMatchesToLoad(history, state, matches, submission, location, isRevalidationRequired, cancelledDeferredRoutes, cancelledFetcherLoads, pendingActionData, pendingError, fetchLoadMatches) {
3120
3193
  let actionResult = pendingError ? Object.values(pendingError)[0] : pendingActionData ? Object.values(pendingActionData)[0] : undefined; // Pick navigation matches that are net-new or qualify for revalidation
3121
3194
 
3122
3195
  let boundaryId = pendingError ? Object.keys(pendingError)[0] : undefined;
3123
3196
  let boundaryMatches = getLoaderMatchesUntilBoundary(matches, boundaryId);
3124
3197
  let navigationMatches = boundaryMatches.filter((match, index) => match.route.loader != null && (isNewLoader(state.loaderData, state.matches[index], match) || // If this route had a pending deferred cancelled it must be revalidated
3125
- cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
3198
+ cancelledDeferredRoutes.some(id => id === match.route.id) || shouldRevalidateLoader(history, state.location, state.matches[index], submission, location, match, isRevalidationRequired, actionResult))); // Pick fetcher.loads that need to be revalidated
3126
3199
 
3127
3200
  let revalidatingFetchers = [];
3128
3201
  fetchLoadMatches && fetchLoadMatches.forEach((_ref10, key) => {
@@ -3132,7 +3205,7 @@
3132
3205
  if (cancelledFetcherLoads.includes(key)) {
3133
3206
  revalidatingFetchers.push([key, href, match, fetchMatches]);
3134
3207
  } else if (isRevalidationRequired) {
3135
- let shouldRevalidate = shouldRevalidateLoader(href, match, submission, href, match, isRevalidationRequired, actionResult);
3208
+ let shouldRevalidate = shouldRevalidateLoader(history, href, match, submission, href, match, isRevalidationRequired, actionResult);
3136
3209
 
3137
3210
  if (shouldRevalidate) {
3138
3211
  revalidatingFetchers.push([key, href, match, fetchMatches]);
@@ -3162,10 +3235,10 @@
3162
3235
  );
3163
3236
  }
3164
3237
 
3165
- function shouldRevalidateLoader(currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
3166
- let currentUrl = createClientSideURL(currentLocation);
3238
+ function shouldRevalidateLoader(history, currentLocation, currentMatch, submission, location, match, isRevalidationRequired, actionResult) {
3239
+ let currentUrl = history.createURL(currentLocation);
3167
3240
  let currentParams = currentMatch.params;
3168
- let nextUrl = createClientSideURL(location);
3241
+ let nextUrl = history.createURL(location);
3169
3242
  let nextParams = match.params; // This is the default implementation as to when we revalidate. If the route
3170
3243
  // provides it's own implementation, then we give them full control but
3171
3244
  // provide this value so they can leverage it if needed after they check
@@ -3242,7 +3315,7 @@
3242
3315
  if (redirectStatusCodes.has(status)) {
3243
3316
  let location = result.headers.get("Location");
3244
3317
  invariant(location, "Redirects returned/thrown from loaders/actions must have a Location header");
3245
- let isAbsolute = /^[a-z+]+:\/\//i.test(location) || location.startsWith("//"); // Support relative routing in internal redirects
3318
+ let isAbsolute = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i.test(location); // Support relative routing in internal redirects
3246
3319
 
3247
3320
  if (!isAbsolute) {
3248
3321
  let activeMatches = matches.slice(0, matches.indexOf(match) + 1);
@@ -3335,8 +3408,8 @@
3335
3408
  // Request instance from the static handler (query/queryRoute)
3336
3409
 
3337
3410
 
3338
- function createClientSideRequest(location, signal, submission) {
3339
- let url = createClientSideURL(stripHashFromPath(location)).toString();
3411
+ function createClientSideRequest(history, location, signal, submission) {
3412
+ let url = history.createURL(stripHashFromPath(location)).toString();
3340
3413
  let init = {
3341
3414
  signal
3342
3415
  };
@@ -3409,13 +3482,16 @@
3409
3482
  if (result.headers) {
3410
3483
  loaderHeaders[id] = result.headers;
3411
3484
  }
3412
- } else if (isDeferredResult(result)) {
3413
- activeDeferreds && activeDeferreds.set(id, result.deferredData);
3414
- loaderData[id] = result.deferredData.data; // TODO: Add statusCode/headers once we wire up streaming in Remix
3415
3485
  } else {
3416
- loaderData[id] = result.data; // Error status codes always override success status codes, but if all
3486
+ if (isDeferredResult(result)) {
3487
+ activeDeferreds.set(id, result.deferredData);
3488
+ loaderData[id] = result.deferredData.data;
3489
+ } else {
3490
+ loaderData[id] = result.data;
3491
+ } // Error status codes always override success status codes, but if all
3417
3492
  // loaders are successful we take the deepest status code.
3418
3493
 
3494
+
3419
3495
  if (result.statusCode != null && result.statusCode !== 200 && !foundError) {
3420
3496
  statusCode = result.statusCode;
3421
3497
  }
@@ -3465,11 +3541,11 @@
3465
3541
  } else if (isRedirectResult(result)) {
3466
3542
  // Should never get here, redirects should get processed above, but we
3467
3543
  // keep this to type narrow to a success result in the else
3468
- throw new Error("Unhandled fetcher revalidation redirect");
3544
+ invariant(false, "Unhandled fetcher revalidation redirect");
3469
3545
  } else if (isDeferredResult(result)) {
3470
3546
  // Should never get here, deferred data should be awaited for fetchers
3471
3547
  // in resolveDeferredResults
3472
- throw new Error("Unhandled fetcher deferred data");
3548
+ invariant(false, "Unhandled fetcher deferred data");
3473
3549
  } else {
3474
3550
  let doneFetcher = {
3475
3551
  state: "idle",
@@ -3541,7 +3617,8 @@
3541
3617
  let {
3542
3618
  pathname,
3543
3619
  routeId,
3544
- method
3620
+ method,
3621
+ type
3545
3622
  } = _temp4 === void 0 ? {} : _temp4;
3546
3623
  let statusText = "Unknown Server Error";
3547
3624
  let errorMessage = "Unknown @remix-run/router error";
@@ -3551,6 +3628,8 @@
3551
3628
 
3552
3629
  if (method && pathname && routeId) {
3553
3630
  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.";
3631
+ } else if (type === "defer-action") {
3632
+ errorMessage = "defer() is not supported in actions";
3554
3633
  } else {
3555
3634
  errorMessage = "Cannot submit binary form data using GET";
3556
3635
  }
@@ -3724,6 +3803,8 @@
3724
3803
  exports.ErrorResponse = ErrorResponse;
3725
3804
  exports.IDLE_FETCHER = IDLE_FETCHER;
3726
3805
  exports.IDLE_NAVIGATION = IDLE_NAVIGATION;
3806
+ exports.UNSAFE_DEFERRED_SYMBOL = UNSAFE_DEFERRED_SYMBOL;
3807
+ exports.UNSAFE_DeferredData = DeferredData;
3727
3808
  exports.UNSAFE_convertRoutesToDataRoutes = convertRoutesToDataRoutes;
3728
3809
  exports.UNSAFE_getPathContributingMatches = getPathContributingMatches;
3729
3810
  exports.createBrowserHistory = createBrowserHistory;