@solidjs/router 2.0.0-next.13 → 2.0.0-next.14

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.
@@ -35,6 +35,10 @@ export function setupNativeEvents({ preload = true, explicitLinks = false, actio
35
35
  if (a.hasAttribute("download") || (rel && rel.includes("external")))
36
36
  return;
37
37
  const url = svg ? new URL(href, document.baseURI) : new URL(href);
38
+ // Skip non-http(s) schemes (blob:, mailto:, tel:, data:, ...). blob: URLs
39
+ // inherit the page origin, so the origin check below won't reject them. #382
40
+ if (url.protocol !== "https:" && url.protocol !== "http:")
41
+ return;
38
42
  if (url.origin !== window.location.origin ||
39
43
  (basePath && url.pathname && !url.pathname.toLowerCase().startsWith(basePath.toLowerCase())))
40
44
  return;
@@ -1,7 +1,7 @@
1
1
  import { createSignal, getObserver, getOwner, onCleanup, sharedConfig } from "solid-js";
2
2
  import { getRequestEvent, isResponseEnvelope, isServer, REVALIDATE_HEADER } from "@solidjs/web";
3
3
  import { GET, decodeResponse, getServerFunctionMetadata, isServerFunction } from "@solidjs/web/server-functions";
4
- import { useRouter, useRoute, getIntent, getInPreloadFn } from "../routing.js";
4
+ import { useRouter, getIntent, getInPreloadFn } from "../routing.js";
5
5
  const LocationHeader = "Location";
6
6
  const PRELOAD_TIMEOUT = 5000;
7
7
  const CACHE_TIMEOUT = 180000;
@@ -59,7 +59,6 @@ export function query(fn, name) {
59
59
  const inPreloadFn = getInPreloadFn();
60
60
  const owner = getOwner();
61
61
  const router = owner ? useRouter() : undefined;
62
- const route = owner ? useRoute() : undefined;
63
62
  const navigate = router && router.navigatorFactory();
64
63
  const now = Date.now();
65
64
  const key = name + hashKey(args);
@@ -84,27 +83,17 @@ export function query(fn, name) {
84
83
  tracking = true;
85
84
  onCleanup(() => cached[4].count--);
86
85
  }
87
- // A read under a route section the in-flight navigation is leaving keeps
88
- // its invalidated value instead of refetching: this render is disposed at
89
- // commit and never paints, and refiring would put a second request on
90
- // what single flight promises is one. The entry stays a cache miss, so
91
- // the fetch happens at its next real use — a later navigation's preload
92
- // or read — unless the flight payload seeds it first. Retained sections
93
- // still refetch here, inside the navigation's transition, so the
94
- // redirect commits with fresh data.
95
- const leaving = cached && !cached[0] && route && router.leaving?.(route);
96
86
  if (cached &&
97
- (cached[0]
98
- ? isServer ||
99
- intent === "native" ||
100
- cached[4].count ||
101
- Date.now() - cached[0] < PRELOAD_TIMEOUT
102
- : leaving)) {
87
+ cached[0] &&
88
+ (isServer ||
89
+ intent === "native" ||
90
+ cached[4].count ||
91
+ Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
103
92
  if (tracking) {
104
93
  cached[4].count++;
105
94
  cached[4][0](); // track
106
95
  }
107
- if (!leaving && cached[3] === "preload" && intent !== "preload") {
96
+ if (cached[3] === "preload" && intent !== "preload") {
108
97
  cached[0] = now;
109
98
  }
110
99
  let res = cached[1];
@@ -113,7 +102,7 @@ export function query(fn, name) {
113
102
  "then" in cached[1]
114
103
  ? cached[1].then(handleResponse(false), handleResponse(true))
115
104
  : handleResponse(false)(cached[1]);
116
- !leaving && !isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
105
+ !isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
117
106
  }
118
107
  inPreloadFn && "then" in res && res.catch(() => { });
119
108
  return res;
package/dist/index.js CHANGED
@@ -336,6 +336,9 @@ function setupNativeEvents({
336
336
  const rel = (a.getAttribute("rel") || "").split(/\s+/);
337
337
  if (a.hasAttribute("download") || rel && rel.includes("external")) return;
338
338
  const url = svg ? new URL(href, document.baseURI) : new URL(href);
339
+ // Skip non-http(s) schemes (blob:, mailto:, tel:, data:, ...). blob: URLs
340
+ // inherit the page origin, so the origin check below won't reject them. #382
341
+ if (url.protocol !== "https:" && url.protocol !== "http:") return;
339
342
  if (url.origin !== window.location.origin || basePath && url.pathname && !url.pathname.toLowerCase().startsWith(basePath.toLowerCase())) return;
340
343
  return [a, url];
341
344
  }
@@ -1165,12 +1168,6 @@ function createRouterContext(integration, branches, getContext, options = {}) {
1165
1168
  get pendingTarget() {
1166
1169
  return lastTransitionTarget;
1167
1170
  },
1168
- leaving(route) {
1169
- const t = lastTransitionTarget;
1170
- if (!t || !route.retained) return false;
1171
- const pathname = t.value.split(/[?#]/, 1)[0];
1172
- return !route.retained(options.transformUrl ? options.transformUrl(pathname) : pathname);
1173
- },
1174
1171
  renderPath,
1175
1172
  parsePath,
1176
1173
  navigatorFactory,
@@ -1375,13 +1372,6 @@ function createRouteContext(router, parent, outlet, match, matches = () => [matc
1375
1372
  pattern,
1376
1373
  params,
1377
1374
  path,
1378
- retained(target) {
1379
- const m = match();
1380
- const p = m.route.matcher(target);
1381
- // params derive from the matched path, so equal paths mean this
1382
- // section instance (layouts match prefixes via partial matchers)
1383
- return !!p && p.path === m.path;
1384
- },
1385
1375
  outlet: () => component ? createComponent(component, {
1386
1376
  params,
1387
1377
  location,
@@ -2197,7 +2187,6 @@ function query(fn, name) {
2197
2187
  const inPreloadFn = getInPreloadFn();
2198
2188
  const owner = getOwner();
2199
2189
  const router = owner ? useRouter() : undefined;
2200
- const route = owner ? useRoute() : undefined;
2201
2190
  const navigate = router && router.navigatorFactory();
2202
2191
  const now = Date.now();
2203
2192
  const key = name + hashKey(args);
@@ -2221,28 +2210,18 @@ function query(fn, name) {
2221
2210
  tracking = true;
2222
2211
  onCleanup(() => cached[4].count--);
2223
2212
  }
2224
-
2225
- // A read under a route section the in-flight navigation is leaving keeps
2226
- // its invalidated value instead of refetching: this render is disposed at
2227
- // commit and never paints, and refiring would put a second request on
2228
- // what single flight promises is one. The entry stays a cache miss, so
2229
- // the fetch happens at its next real use — a later navigation's preload
2230
- // or read — unless the flight payload seeds it first. Retained sections
2231
- // still refetch here, inside the navigation's transition, so the
2232
- // redirect commits with fresh data.
2233
- const leaving = cached && !cached[0] && route && router.leaving?.(route);
2234
- if (cached && (cached[0] ? isServer || intent === "native" || cached[4].count || Date.now() - cached[0] < PRELOAD_TIMEOUT : leaving)) {
2213
+ if (cached && cached[0] && (isServer || intent === "native" || cached[4].count || Date.now() - cached[0] < PRELOAD_TIMEOUT)) {
2235
2214
  if (tracking) {
2236
2215
  cached[4].count++;
2237
2216
  cached[4][0](); // track
2238
2217
  }
2239
- if (!leaving && cached[3] === "preload" && intent !== "preload") {
2218
+ if (cached[3] === "preload" && intent !== "preload") {
2240
2219
  cached[0] = now;
2241
2220
  }
2242
2221
  let res = cached[1];
2243
2222
  if (intent !== "preload") {
2244
2223
  res = "then" in cached[1] ? cached[1].then(handleResponse(false), handleResponse(true)) : handleResponse(false)(cached[1]);
2245
- !leaving && !isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
2224
+ !isServer && intent === "navigate" && cached[4][1](cached[0]); // update version
2246
2225
  }
2247
2226
  inPreloadFn && "then" in res && res.catch(() => {});
2248
2227
  return res;
package/dist/routing.js CHANGED
@@ -621,13 +621,6 @@ export function createRouterContext(integration, branches, getContext, options =
621
621
  get pendingTarget() {
622
622
  return lastTransitionTarget;
623
623
  },
624
- leaving(route) {
625
- const t = lastTransitionTarget;
626
- if (!t || !route.retained)
627
- return false;
628
- const pathname = t.value.split(/[?#]/, 1)[0];
629
- return !route.retained(options.transformUrl ? options.transformUrl(pathname) : pathname);
630
- },
631
624
  renderPath,
632
625
  parsePath,
633
626
  navigatorFactory,
@@ -815,13 +808,6 @@ export function createRouteContext(router, parent, outlet, match, matches = () =
815
808
  pattern,
816
809
  params,
817
810
  path,
818
- retained(target) {
819
- const m = match();
820
- const p = m.route.matcher(target);
821
- // params derive from the matched path, so equal paths mean this
822
- // section instance (layouts match prefixes via partial matchers)
823
- return !!p && p.path === m.path;
824
- },
825
811
  outlet: () => component
826
812
  ? createComponent(component, {
827
813
  params,
package/dist/types.d.ts CHANGED
@@ -6,6 +6,7 @@ declare module "@solidjs/web" {
6
6
  status?: number;
7
7
  statusText?: string;
8
8
  headers: Headers;
9
+ committed?: boolean;
9
10
  };
10
11
  router?: {
11
12
  matches?: OutputMatch[];
@@ -244,8 +245,6 @@ export interface RouteContext {
244
245
  path: () => string;
245
246
  outlet: () => JSX.Element;
246
247
  resolvePath(to: string): string | undefined;
247
- /** Whether this route section still matches `target` (same matched path), i.e. survives a navigation there. Absent on the base route, which always survives. */
248
- retained?(target: string): boolean;
249
248
  }
250
249
  export interface RouterUtils {
251
250
  renderPath(path: string): string;
@@ -264,8 +263,6 @@ export interface RouterContext {
264
263
  isRouting: () => boolean;
265
264
  /** The target of the in-flight navigation transition, if any. Not reactive. */
266
265
  readonly pendingTarget?: LocationChange;
267
- /** Whether `route` is a section the in-flight navigation is leaving. False when no navigation is pending. */
268
- leaving?(route: RouteContext): boolean;
269
266
  matches: () => RouteMatch[];
270
267
  renderPath(path: string): string;
271
268
  parsePath(str: string): string;
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "Ryan Turnquist"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "2.0.0-next.13",
9
+ "version": "2.0.0-next.14",
10
10
  "homepage": "https://github.com/solidjs/solid-router#readme",
11
11
  "repository": {
12
12
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "sideEffects": false,
33
33
  "devDependencies": {
34
- "@solidjs/web": "2.0.0-beta.28",
34
+ "@solidjs/web": "2.0.0-beta.30",
35
35
  "@babel/core": "^7.26.0",
36
36
  "@babel/preset-typescript": "^7.26.0",
37
37
  "@changesets/cli": "^2.27.10",
@@ -40,19 +40,19 @@
40
40
  "@rollup/plugin-terser": "0.4.4",
41
41
  "@types/jest": "^29.5.14",
42
42
  "@types/node": "^22.10.0",
43
- "babel-preset-solid": "2.0.0-beta.28",
43
+ "babel-preset-solid": "2.0.0-beta.30",
44
44
  "jsdom": "^25.0.1",
45
45
  "prettier": "^3.4.1",
46
46
  "rollup": "^4.27.4",
47
- "solid-js": "2.0.0-beta.28",
47
+ "solid-js": "2.0.0-beta.30",
48
48
  "typescript": "^5.7.2",
49
49
  "vite": "^6.0.0",
50
50
  "vite-plugin-solid": "3.0.0-next.10",
51
51
  "vitest": "^2.1.6"
52
52
  },
53
53
  "peerDependencies": {
54
- "@solidjs/web": ">=2.0.0-beta.28 <2.0.0-experimental.0",
55
- "solid-js": ">=2.0.0-beta.28 <2.0.0-experimental.0"
54
+ "@solidjs/web": ">=2.0.0-beta.30 <2.0.0-experimental.0",
55
+ "solid-js": ">=2.0.0-beta.30 <2.0.0-experimental.0"
56
56
  },
57
57
  "scripts": {
58
58
  "build": "rm -rf dist && tsc && rollup -c",