@solidjs/web 2.0.0-rc.3 → 2.0.0-rc.4

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/dev.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createRenderEffect, createMemo, sharedConfig, enableHydration, untrack, runWithOwner, resetErrorHalt, enforceLoadingBoundary, createRoot, flatten, flush, createComponent, omit, createOwner, createSignal, $DEVCOMP, onCleanup, getOwner, createEffect } from 'solid-js';
1
+ import { createRenderEffect, createMemo, sharedConfig, enableHydration, untrack, runWithOwner, resetErrorHalt, enforceLoadingBoundary, createRoot, flatten, flush, getOwner, createOwner, patchableRaw, storeHasOptimisticFamily, storeIsShallow, registerRowOps, registerSlotPatch, onCleanup, registerPatch, createComponent, omit, createSignal, $DEVCOMP, createEffect } from 'solid-js';
2
2
  export { Errored, For, Hydration, Loading, Match, NoHydration, Repeat, Reveal, Show, Switch, createComponent, getOwner, merge as mergeProps, untrack } from 'solid-js';
3
3
 
4
4
  const DOMWithState = {
@@ -333,6 +333,10 @@ const waitAsset = promise => {
333
333
  }
334
334
  gate();
335
335
  };
336
+ let listDriver;
337
+ function installListDriver(driver) {
338
+ listDriver = driver;
339
+ }
336
340
  const $$EVENT_OWNER = "_$SOLID_EVENT_OWNER";
337
341
  const INNER_OWNED = {};
338
342
  const delegatedEvents = new Set();
@@ -616,11 +620,6 @@ function ref(fn, element) {
616
620
  const resolved = untrack(fn);
617
621
  runWithOwner(null, () => applyRef(resolved, element));
618
622
  }
619
- const PURE_ROW = Symbol.for("solid.pure-row");
620
- function rowProof(fn) {
621
- fn[PURE_ROW] = true;
622
- return fn;
623
- }
624
623
  function scope(fn) {
625
624
  fn.$s = true;
626
625
  return fn;
@@ -684,16 +683,16 @@ function stripTextSeparators(nodes) {
684
683
  nodes.length = j;
685
684
  return nodes;
686
685
  }
687
- function patchDriver(subject, body) {
688
- {
689
- effect(() => body(subject, subject, false), () => body(subject, undefined, true));
690
- }
691
- }
692
686
  function insert(parent, accessor, marker, initial, options) {
693
687
  const multi = marker !== undefined;
694
688
  const host = options && options.host;
695
689
  if (multi && !initial) initial = [];
696
690
  if (hydrationRt !== null) initial = hydrationRt.claimInitial(parent, multi, initial);
691
+ if (listDriver !== undefined && typeof accessor === "function" && accessor.$ll !== undefined) {
692
+ const listAccessor = accessor;
693
+ const owner = getOwner();
694
+ if (listDriver(parent, accessor, marker, () => runWithOwner(owner, () => insert(parent, () => listAccessor(), marker, marker !== undefined ? [] : undefined, options)))) return;
695
+ }
697
696
  if (typeof accessor !== "function") {
698
697
  accessor = normalize(accessor, initial, multi, true);
699
698
  if (typeof accessor !== "function") {
@@ -1172,6 +1171,15 @@ function hydrate(code, element, options = {}) {
1172
1171
  enableHydration();
1173
1172
  installHydrationRuntime();
1174
1173
  if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
1174
+ const head = (element.nodeType === 9 ? element : element.ownerDocument).head;
1175
+ if (head && element.contains(head)) {
1176
+ let n = head.firstChild;
1177
+ while (n && n.nodeType === 1 && n.hasAttribute("data-dh") && !n.hasAttribute("data-dhf")) {
1178
+ const next = n.nextSibling;
1179
+ head.appendChild(n);
1180
+ n = next;
1181
+ }
1182
+ }
1175
1183
  options.renderId ||= "";
1176
1184
  if (!globalThis._$HY.modules) globalThis._$HY.modules = {};
1177
1185
  if (!globalThis._$HY.loading) globalThis._$HY.loading = {};
@@ -1685,6 +1693,331 @@ function getHydrationKey() {
1685
1693
  }
1686
1694
  const RequestContext = Symbol();
1687
1695
 
1696
+ const PURE_ROW = Symbol.for("solid.pure-row");
1697
+ const arm = () => {
1698
+ installListDriver(driveList);
1699
+ };
1700
+ function rowProof(fn) {
1701
+ arm();
1702
+ fn[PURE_ROW] = true;
1703
+ return fn;
1704
+ }
1705
+ let rowCollector = null;
1706
+ const lisPositions = sources => {
1707
+ const n = sources.length;
1708
+ const tails = [];
1709
+ const tailsIdx = [];
1710
+ const prev = new Array(n).fill(-1);
1711
+ for (let j = 0; j < n; j++) {
1712
+ const v = sources[j];
1713
+ if (v === -1) continue;
1714
+ let lo = 0,
1715
+ hi = tails.length;
1716
+ while (lo < hi) {
1717
+ const mid = lo + hi >> 1;
1718
+ if (tails[mid] < v) lo = mid + 1;else hi = mid;
1719
+ }
1720
+ if (lo > 0) prev[j] = tailsIdx[lo - 1];
1721
+ tails[lo] = v;
1722
+ tailsIdx[lo] = j;
1723
+ }
1724
+ const stable = new Set();
1725
+ let k = tailsIdx.length ? tailsIdx[tails.length - 1] : -1;
1726
+ while (k >= 0) {
1727
+ stable.add(k);
1728
+ k = prev[k];
1729
+ }
1730
+ return stable;
1731
+ };
1732
+ const driveList = (parent, listFn, marker, lateClassic) => {
1733
+ const meta = listFn.$ll;
1734
+ if (meta.row?.[PURE_ROW] !== true) return false;
1735
+ if (typeof meta.keyed === "function") return false;
1736
+ const evalOwner = createOwner({
1737
+ id: "&each"
1738
+ });
1739
+ let subject = runWithOwner(evalOwner, () => untrack(meta.each));
1740
+ evalOwner.dispose();
1741
+ let raw = subject != null ? patchableRaw(subject) : undefined;
1742
+ if (raw === undefined || !Array.isArray(raw)) return false;
1743
+ const optimistic = storeHasOptimisticFamily(subject);
1744
+ if (optimistic) raw = untrack(() => Array.from(subject));
1745
+ const hydrating = !!sharedConfig.hydrating;
1746
+ if (hydrating && raw.length === 0) return false;
1747
+ let domRows;
1748
+ let rowIds;
1749
+ if (hydrating) {
1750
+ if (marker !== undefined) return false;
1751
+ domRows = Array.from(parent.children);
1752
+ if (domRows.length !== raw.length) return false;
1753
+ rowIds = new Array(raw.length);
1754
+ for (let i = 0; i < domRows.length; i++) {
1755
+ const key = domRows[i].getAttribute("_hk");
1756
+ if (key === null || !key.endsWith("0") || key.length < 2) return false;
1757
+ rowIds[i] = key.slice(0, -1);
1758
+ }
1759
+ }
1760
+ const rowFn = meta.row;
1761
+ const endAnchor = marker ?? null;
1762
+ const shallow = storeIsShallow(subject);
1763
+ let lastBodies = null;
1764
+ let lastUnbinds = null;
1765
+ const collectBind = (abs, build) => {
1766
+ const prevC = rowCollector;
1767
+ rowCollector = {
1768
+ row: shallow ? subject[abs] : undefined,
1769
+ bodies: [],
1770
+ unbinds: []
1771
+ };
1772
+ try {
1773
+ return build();
1774
+ } finally {
1775
+ lastBodies = rowCollector.bodies;
1776
+ lastUnbinds = rowCollector.unbinds;
1777
+ rowCollector = prevC;
1778
+ }
1779
+ };
1780
+ const listOwner = createOwner();
1781
+ let declined = false;
1782
+ const bindRow = (abs, claimId) => {
1783
+ {
1784
+ const o = listOwner;
1785
+ const prevChild = o._firstChild;
1786
+ const prevDisposal = o._disposal;
1787
+ const node = collectBind(abs, () => runWithOwner(listOwner, () => claimId !== undefined ? runWithOwner(createOwner({
1788
+ id: claimId
1789
+ }), () => untrack(() => rowFn(subject[abs]))) : untrack(() => rowFn(subject[abs]))));
1790
+ if (o._firstChild !== prevChild || o._disposal !== prevDisposal) {
1791
+ console.warn("A patch-mode list row created reactive computations or cleanups " + "during build (likely a handler/attribute value expression calling " + "createEffect/onCleanup). This work attaches to the LIST, not the " + "row, and will not dispose when the row is removed. Move owned " + "work into effects/refs (which opt the row out of patch mode).");
1792
+ }
1793
+ return node;
1794
+ }
1795
+ };
1796
+ let entries = new Array(raw.length);
1797
+ let rowBodies = shallow ? new Array(raw.length) : null;
1798
+ let rowUnbinds = new Array(raw.length);
1799
+ const runUnbinds = list => {
1800
+ if (list !== undefined) for (let u = 0; u < list.length; u++) list[u]();
1801
+ };
1802
+ const unbindAllRows = () => {
1803
+ for (let j = 0; j < rowUnbinds.length; j++) runUnbinds(rowUnbinds[j]);
1804
+ rowUnbinds = [];
1805
+ };
1806
+ let prevRaws = raw.slice();
1807
+ try {
1808
+ if (hydrating) {
1809
+ for (let i = 0; i < raw.length; i++) {
1810
+ entries[i] = bindRow(i, rowIds[i]);
1811
+ if (rowBodies !== null) rowBodies[i] = lastBodies;
1812
+ rowUnbinds[i] = lastUnbinds;
1813
+ }
1814
+ } else {
1815
+ for (let i = 0; i < raw.length; i++) {
1816
+ const node = bindRow(i);
1817
+ entries[i] = node;
1818
+ if (rowBodies !== null) rowBodies[i] = lastBodies;
1819
+ rowUnbinds[i] = lastUnbinds;
1820
+ parent.insertBefore(node, endAnchor);
1821
+ }
1822
+ }
1823
+ } catch (err) {
1824
+ unbindAllRows();
1825
+ runUnbinds(lastUnbinds ?? undefined);
1826
+ for (let j = 0; j < entries.length; j++) {
1827
+ const n = entries[j];
1828
+ if (n !== undefined && n.parentNode === parent) n.remove();
1829
+ }
1830
+ listOwner.dispose();
1831
+ throw err;
1832
+ }
1833
+ const identityOps = nextArr => {
1834
+ const keyOf = r => {
1835
+ const w = r != null ? patchableRaw(r) : undefined;
1836
+ return w !== undefined ? w : r;
1837
+ };
1838
+ const oldIndex = new Map();
1839
+ for (let j = 0; j < prevRaws.length; j++) {
1840
+ const k = keyOf(prevRaws[j]);
1841
+ const existing = oldIndex.get(k);
1842
+ if (existing === undefined) oldIndex.set(k, j);else if (Array.isArray(existing)) existing.push(j);else oldIndex.set(k, [existing, j]);
1843
+ }
1844
+ const sources = new Array(nextArr.length);
1845
+ for (let k = 0; k < nextArr.length; k++) {
1846
+ const m = oldIndex.get(keyOf(nextArr[k]));
1847
+ if (m === undefined) sources[k] = -1;else if (Array.isArray(m)) {
1848
+ sources[k] = m.shift();
1849
+ if (m.length === 1) oldIndex.set(keyOf(nextArr[k]), m[0]);
1850
+ } else {
1851
+ sources[k] = m;
1852
+ oldIndex.delete(keyOf(nextArr[k]));
1853
+ }
1854
+ }
1855
+ return {
1856
+ prefix: 0,
1857
+ sources
1858
+ };
1859
+ };
1860
+ let resyncNeeded = false;
1861
+ const applyOps = (next, ops) => {
1862
+ if (declined) return;
1863
+ if (resyncNeeded) ops = null;
1864
+ if (ops === null) ops = identityOps(next);
1865
+ const {
1866
+ prefix,
1867
+ sources
1868
+ } = ops;
1869
+ const built = new Array(sources.length);
1870
+ const builtBodies = rowBodies !== null ? new Array(sources.length) : null;
1871
+ const builtUnbinds = new Array(sources.length);
1872
+ let j = 0;
1873
+ try {
1874
+ for (; j < sources.length; j++) {
1875
+ const abs = prefix + j;
1876
+ const src = sources[j];
1877
+ if (src === -1 || refRebuild && src >= 0 && next[abs] !== prevRaws[src]) {
1878
+ built[j] = bindRow(abs);
1879
+ if (builtBodies !== null) builtBodies[j] = lastBodies;
1880
+ builtUnbinds[j] = lastUnbinds;
1881
+ }
1882
+ }
1883
+ } catch (err) {
1884
+ for (let k = 0; k < j; k++) runUnbinds(builtUnbinds[k]);
1885
+ runUnbinds(lastUnbinds ?? undefined);
1886
+ resyncNeeded = true;
1887
+ throw err;
1888
+ }
1889
+ const retained = new Set();
1890
+ for (let k = 0; k < sources.length; k++) {
1891
+ if (sources[k] >= 0 && built[k] === undefined) retained.add(sources[k]);
1892
+ }
1893
+ for (let k = prefix; k < entries.length; k++) {
1894
+ if (!retained.has(k)) {
1895
+ entries[k].remove();
1896
+ runUnbinds(rowUnbinds[k]);
1897
+ }
1898
+ }
1899
+ const newEntries = new Array(prefix + sources.length);
1900
+ const newBodies = rowBodies !== null ? new Array(prefix + sources.length) : null;
1901
+ const newUnbinds = new Array(prefix + sources.length);
1902
+ for (let i = 0; i < prefix; i++) {
1903
+ newEntries[i] = entries[i];
1904
+ if (newBodies !== null) newBodies[i] = rowBodies[i];
1905
+ newUnbinds[i] = rowUnbinds[i];
1906
+ }
1907
+ const stable = lisPositions(sources);
1908
+ let anchor = endAnchor;
1909
+ for (let k = sources.length - 1; k >= 0; k--) {
1910
+ const abs = prefix + k;
1911
+ const src = sources[k];
1912
+ let node;
1913
+ if (built[k] !== undefined) {
1914
+ node = built[k];
1915
+ if (newBodies !== null) newBodies[abs] = builtBodies[k];
1916
+ newUnbinds[abs] = builtUnbinds[k];
1917
+ parent.insertBefore(node, anchor);
1918
+ } else {
1919
+ node = entries[src];
1920
+ if (newBodies !== null) newBodies[abs] = rowBodies[src];
1921
+ newUnbinds[abs] = rowUnbinds[src];
1922
+ if (!stable.has(k)) parent.insertBefore(node, anchor);
1923
+ }
1924
+ newEntries[abs] = node;
1925
+ anchor = node;
1926
+ }
1927
+ entries = newEntries;
1928
+ if (newBodies !== null) rowBodies = newBodies;
1929
+ rowUnbinds = newUnbinds;
1930
+ prevRaws = next.slice();
1931
+ resyncNeeded = false;
1932
+ };
1933
+ let unbindOps = runWithOwner(listOwner, () => registerRowOps(subject, applyOps));
1934
+ const refRebuild = shallow && typeof meta.keyed !== "function";
1935
+ const rebuildSlot = i => {
1936
+ runUnbinds(rowUnbinds[i]);
1937
+ const old = entries[i];
1938
+ const node = bindRow(i);
1939
+ rowBodies[i] = lastBodies;
1940
+ rowUnbinds[i] = lastUnbinds;
1941
+ parent.insertBefore(node, old);
1942
+ old.remove();
1943
+ entries[i] = node;
1944
+ };
1945
+ const applySlot = (i, next, prev) => {
1946
+ if (declined) return;
1947
+ if (resyncNeeded) {
1948
+ const live = subject != null ? patchableRaw(subject) : undefined;
1949
+ if (live !== undefined && Array.isArray(live)) applyOps(live, null);
1950
+ return;
1951
+ }
1952
+ if (refRebuild) {
1953
+ rebuildSlot(i);
1954
+ prevRaws[i] = next;
1955
+ return;
1956
+ }
1957
+ const bodies = rowBodies[i];
1958
+ if (bodies !== undefined) {
1959
+ for (let b = 0; b < bodies.length; b++) bodies[b](next, prev, false);
1960
+ }
1961
+ prevRaws[i] = next;
1962
+ };
1963
+ let unbindSlots = shallow ? runWithOwner(listOwner, () => registerSlotPatch(subject, applySlot)) : null;
1964
+ runWithOwner(listOwner, () => effect(() => meta.each(), value => {
1965
+ if (declined || value === subject) return;
1966
+ const nextRaw = value != null ? patchableRaw(value) : undefined;
1967
+ unbindOps();
1968
+ unbindSlots?.();
1969
+ if (nextRaw !== undefined && Array.isArray(nextRaw) && storeIsShallow(value) !== shallow) {
1970
+ for (let j = 0; j < entries.length; j++) entries[j].remove();
1971
+ entries = [];
1972
+ prevRaws = [];
1973
+ unbindAllRows();
1974
+ subject = value;
1975
+ declined = true;
1976
+ listOwner.dispose();
1977
+ lateClassic?.();
1978
+ return;
1979
+ }
1980
+ if (nextRaw === undefined || !Array.isArray(nextRaw)) {
1981
+ for (let j = 0; j < entries.length; j++) entries[j].remove();
1982
+ entries = [];
1983
+ prevRaws = [];
1984
+ unbindAllRows();
1985
+ subject = value;
1986
+ declined = true;
1987
+ listOwner.dispose();
1988
+ lateClassic?.();
1989
+ return;
1990
+ }
1991
+ const swapOps = identityOps(nextRaw);
1992
+ subject = value;
1993
+ unbindOps = runWithOwner(listOwner, () => registerRowOps(subject, applyOps));
1994
+ if (shallow) unbindSlots = runWithOwner(listOwner, () => registerSlotPatch(subject, applySlot));
1995
+ applyOps(nextRaw, swapOps);
1996
+ }));
1997
+ onCleanup(() => {
1998
+ unbindOps();
1999
+ unbindSlots?.();
2000
+ unbindAllRows();
2001
+ listOwner.dispose();
2002
+ });
2003
+ return true;
2004
+ };
2005
+ const patchDriver = (subject, body) => {
2006
+ const raw = patchableRaw(subject);
2007
+ if (raw !== undefined) {
2008
+ if (!sharedConfig.hydrating) body(raw, undefined, true);
2009
+ const unbind = registerPatch(subject, body);
2010
+ if (rowCollector !== null) rowCollector.unbinds.push(unbind);
2011
+ else onCleanup(unbind);
2012
+ } else if (rowCollector !== null && subject === rowCollector.row) {
2013
+ rowCollector.bodies.push(body);
2014
+ if (!sharedConfig.hydrating) body(subject, undefined, true);
2015
+ } else {
2016
+ effect(() => body(subject, subject, false),
2017
+ () => untrack(() => body(subject, undefined, true)));
2018
+ }
2019
+ };
2020
+
1688
2021
  function throwInBrowser(func) {
1689
2022
  const err = new Error(`${func.name} is not supported in the browser, returning undefined`);
1690
2023
  console.error(err);
@@ -1795,7 +2128,8 @@ function redirect(url, init = 302) {
1795
2128
  if (responseInit.status === undefined) {
1796
2129
  responseInit.status = 302;
1797
2130
  }
1798
- headers.set("Location", String(url));
2131
+ const target = typeof url === "string" ? url : url[HREF];
2132
+ headers.set("Location", typeof target === "string" ? target : String(url));
1799
2133
  return new Response(null, {
1800
2134
  ...responseInit,
1801
2135
  headers
@@ -1969,4 +2303,4 @@ _moduleUrl) {
1969
2303
  function httpStatus(_code, _text) {}
1970
2304
  function httpHeader(_name, _value, _options) {}
1971
2305
 
1972
- export { ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, claimElementTree, className, clearFlashCookie, clientOnly, commitEventResponse, composeMiddleware, createRequestEvent, createResponseStub, createSSRResponse, delegateEvents, dynamic, dynamicProperty, effect, escape, generateHydrationScript, getDelegatedRoot, getExpectedRedirectStatus, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, markSafeError, memo, parseCookieHeader, patchDriver, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, resolveSSRNode, respond, rowProof, runHydrationEvents, scope, serializeCookie, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, useHead, waitAsset, warmAsset };
2306
+ export { ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, claimElementTree, className, clearFlashCookie, clientOnly, commitEventResponse, composeMiddleware, createRequestEvent, createResponseStub, createSSRResponse, delegateEvents, driveList, dynamic, dynamicProperty, effect, escape, generateHydrationScript, getDelegatedRoot, getExpectedRedirectStatus, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, hydrate, insert, installHydrationRuntime, installListDriver, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, listDriver, markSafeError, memo, parseCookieHeader, patchDriver, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, resolveSSRNode, respond, rowProof, runHydrationEvents, scope, serializeCookie, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, useHead, waitAsset, warmAsset };
package/dist/server.cjs CHANGED
@@ -251,7 +251,8 @@ function redirect(url, init = 302) {
251
251
  if (responseInit.status === undefined) {
252
252
  responseInit.status = 302;
253
253
  }
254
- headers.set("Location", String(url));
254
+ const target = typeof url === "string" ? url : url[HREF];
255
+ headers.set("Location", typeof target === "string" ? target : String(url));
255
256
  return new Response(null, {
256
257
  ...responseInit,
257
258
  headers
@@ -2479,7 +2480,7 @@ function ssrClaim(map) {
2479
2480
  function decodeSSREntities(s) {
2480
2481
  return s.indexOf("&") < 0 ? s : s.replace(/&quot;/g, '"').replace(/&lt;/g, "<").replace(/&amp;/g, "&");
2481
2482
  }
2482
- const SELECT_VALUE_ATTR = /\svalue="([^"]*)"/;
2483
+ const SELECT_VALUE_ATTR = /\svalue(?:="([^"]*)")?(?=[\s>]|$)/;
2483
2484
  function tagEnd(html, i) {
2484
2485
  for (let j = i + 1; j < html.length; j++) {
2485
2486
  const c = html.charCodeAt(j);
@@ -2531,7 +2532,7 @@ function resolveSSRSelectValues(html) {
2531
2532
  cand = html.indexOf("<select", e0 + 1);
2532
2533
  continue;
2533
2534
  }
2534
- const bound = decodeSSREntities(m[1]);
2535
+ const bound = decodeSSREntities(m[1] ?? "");
2535
2536
  const sel = {
2536
2537
  values: /\smultiple(?=[\s>=])/.test(open) ? bound.split(",") : [bound],
2537
2538
  strip: cand + m.index,
@@ -2568,7 +2569,7 @@ function resolveSSRSelectValues(html) {
2568
2569
  const attrs = html.slice(i + 7, e);
2569
2570
  if (/\sselected(?=[\s=]|$)/.test(attrs)) sel.defaulted = true;else {
2570
2571
  const vm = SELECT_VALUE_ATTR.exec(attrs);
2571
- const value = vm ? decodeSSREntities(vm[1]) : decodeSSREntities(optionText(html, e + 1)).replace(/\s+/g, " ").trim();
2572
+ const value = vm ? decodeSSREntities(vm[1] ?? "") : decodeSSREntities(optionText(html, e + 1)).replace(/\s+/g, " ").trim();
2572
2573
  if (sel.values.includes(value)) sel.marks.push(e);
2573
2574
  }
2574
2575
  }
package/dist/server.js CHANGED
@@ -250,7 +250,8 @@ function redirect(url, init = 302) {
250
250
  if (responseInit.status === undefined) {
251
251
  responseInit.status = 302;
252
252
  }
253
- headers.set("Location", String(url));
253
+ const target = typeof url === "string" ? url : url[HREF];
254
+ headers.set("Location", typeof target === "string" ? target : String(url));
254
255
  return new Response(null, {
255
256
  ...responseInit,
256
257
  headers
@@ -2478,7 +2479,7 @@ function ssrClaim(map) {
2478
2479
  function decodeSSREntities(s) {
2479
2480
  return s.indexOf("&") < 0 ? s : s.replace(/&quot;/g, '"').replace(/&lt;/g, "<").replace(/&amp;/g, "&");
2480
2481
  }
2481
- const SELECT_VALUE_ATTR = /\svalue="([^"]*)"/;
2482
+ const SELECT_VALUE_ATTR = /\svalue(?:="([^"]*)")?(?=[\s>]|$)/;
2482
2483
  function tagEnd(html, i) {
2483
2484
  for (let j = i + 1; j < html.length; j++) {
2484
2485
  const c = html.charCodeAt(j);
@@ -2530,7 +2531,7 @@ function resolveSSRSelectValues(html) {
2530
2531
  cand = html.indexOf("<select", e0 + 1);
2531
2532
  continue;
2532
2533
  }
2533
- const bound = decodeSSREntities(m[1]);
2534
+ const bound = decodeSSREntities(m[1] ?? "");
2534
2535
  const sel = {
2535
2536
  values: /\smultiple(?=[\s>=])/.test(open) ? bound.split(",") : [bound],
2536
2537
  strip: cand + m.index,
@@ -2567,7 +2568,7 @@ function resolveSSRSelectValues(html) {
2567
2568
  const attrs = html.slice(i + 7, e);
2568
2569
  if (/\sselected(?=[\s=]|$)/.test(attrs)) sel.defaulted = true;else {
2569
2570
  const vm = SELECT_VALUE_ATTR.exec(attrs);
2570
- const value = vm ? decodeSSREntities(vm[1]) : decodeSSREntities(optionText(html, e + 1)).replace(/\s+/g, " ").trim();
2571
+ const value = vm ? decodeSSREntities(vm[1] ?? "") : decodeSSREntities(optionText(html, e + 1)).replace(/\s+/g, " ").trim();
2571
2572
  if (sel.values.includes(value)) sel.marks.push(e);
2572
2573
  }
2573
2574
  }