@solidjs/web 2.0.0-beta.21 → 2.0.0-beta.22

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.cjs CHANGED
@@ -282,9 +282,24 @@ function setProperty(node, name, value) {
282
282
  if (isHydrating(node)) return;
283
283
  node[name] = value;
284
284
  }
285
+ let claimHandlers = null;
286
+ function registerElementClaim(handler) {
287
+ (claimHandlers || (claimHandlers = [])).push(handler);
288
+ return () => {
289
+ const index = claimHandlers.indexOf(handler);
290
+ index > -1 && claimHandlers.splice(index, 1);
291
+ };
292
+ }
293
+ function claimElement(node) {
294
+ if (claimHandlers !== null) {
295
+ for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
296
+ }
297
+ return node;
298
+ }
285
299
  function setAttribute(node, name, value) {
286
300
  if (isHydrating(node)) return;
287
301
  if (value == null || value === false) node.removeAttribute(name);else node.setAttribute(name, value === true ? "" : value);
302
+ if (claimHandlers !== null && (name === "href" || name === "action")) claimElement(node);
288
303
  }
289
304
  function setAttributeNS(node, namespace, name, value) {
290
305
  if (isHydrating(node)) return;
@@ -1130,6 +1145,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1130
1145
  function isResponseEnvelope(value) {
1131
1146
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1132
1147
  }
1148
+ const HREF = Symbol.for("solid.Href");
1149
+ function isHref(value) {
1150
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1151
+ }
1133
1152
  function initWithRevalidate(init) {
1134
1153
  const {
1135
1154
  revalidate,
@@ -1143,6 +1162,9 @@ function initWithRevalidate(init) {
1143
1162
  };
1144
1163
  }
1145
1164
  function redirect(url, init = 302) {
1165
+ if (typeof url !== "string" && !isHref(url)) {
1166
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1167
+ }
1146
1168
  const {
1147
1169
  responseInit,
1148
1170
  headers
@@ -1152,7 +1174,7 @@ function redirect(url, init = 302) {
1152
1174
  if (responseInit.status === undefined) {
1153
1175
  responseInit.status = 302;
1154
1176
  }
1155
- headers.set("Location", url);
1177
+ headers.set("Location", String(url));
1156
1178
  return new Response(null, {
1157
1179
  ...responseInit,
1158
1180
  headers
@@ -1341,6 +1363,7 @@ exports.DOMElements = DOMElements;
1341
1363
  exports.DOMWithState = DOMWithState;
1342
1364
  exports.DelegatedEvents = DelegatedEvents;
1343
1365
  exports.Dynamic = Dynamic;
1366
+ exports.HREF = HREF;
1344
1367
  exports.HydrationScript = voidFn;
1345
1368
  exports.MathMLElements = MathMLElements;
1346
1369
  exports.Namespaces = Namespaces;
@@ -1354,6 +1377,7 @@ exports.acquireAsset = acquireAsset;
1354
1377
  exports.addEvent = addEvent;
1355
1378
  exports.applyRef = applyRef;
1356
1379
  exports.assign = assign;
1380
+ exports.claimElement = claimElement;
1357
1381
  exports.className = className;
1358
1382
  exports.delegateEvents = delegateEvents;
1359
1383
  exports.dynamic = dynamic;
@@ -1374,6 +1398,7 @@ exports.hydrate = hydrate;
1374
1398
  exports.insert = insert;
1375
1399
  exports.installHydrationRuntime = installHydrationRuntime;
1376
1400
  exports.isDev = isDev;
1401
+ exports.isHref = isHref;
1377
1402
  exports.isResponseEnvelope = isResponseEnvelope;
1378
1403
  exports.isServer = isServer;
1379
1404
  exports.memo = memo;
@@ -1382,6 +1407,7 @@ exports.redirect = redirect;
1382
1407
  exports.ref = ref;
1383
1408
  exports.registerDelegatedContainer = registerDelegatedContainer;
1384
1409
  exports.registerDelegatedRoot = registerDelegatedRoot;
1410
+ exports.registerElementClaim = registerElementClaim;
1385
1411
  exports.reload = reload;
1386
1412
  exports.render = render;
1387
1413
  exports.renderToStream = renderToStream;
package/dist/dev.js CHANGED
@@ -281,9 +281,24 @@ function setProperty(node, name, value) {
281
281
  if (isHydrating(node)) return;
282
282
  node[name] = value;
283
283
  }
284
+ let claimHandlers = null;
285
+ function registerElementClaim(handler) {
286
+ (claimHandlers || (claimHandlers = [])).push(handler);
287
+ return () => {
288
+ const index = claimHandlers.indexOf(handler);
289
+ index > -1 && claimHandlers.splice(index, 1);
290
+ };
291
+ }
292
+ function claimElement(node) {
293
+ if (claimHandlers !== null) {
294
+ for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
295
+ }
296
+ return node;
297
+ }
284
298
  function setAttribute(node, name, value) {
285
299
  if (isHydrating(node)) return;
286
300
  if (value == null || value === false) node.removeAttribute(name);else node.setAttribute(name, value === true ? "" : value);
301
+ if (claimHandlers !== null && (name === "href" || name === "action")) claimElement(node);
287
302
  }
288
303
  function setAttributeNS(node, namespace, name, value) {
289
304
  if (isHydrating(node)) return;
@@ -1129,6 +1144,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1129
1144
  function isResponseEnvelope(value) {
1130
1145
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1131
1146
  }
1147
+ const HREF = Symbol.for("solid.Href");
1148
+ function isHref(value) {
1149
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1150
+ }
1132
1151
  function initWithRevalidate(init) {
1133
1152
  const {
1134
1153
  revalidate,
@@ -1142,6 +1161,9 @@ function initWithRevalidate(init) {
1142
1161
  };
1143
1162
  }
1144
1163
  function redirect(url, init = 302) {
1164
+ if (typeof url !== "string" && !isHref(url)) {
1165
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1166
+ }
1145
1167
  const {
1146
1168
  responseInit,
1147
1169
  headers
@@ -1151,7 +1173,7 @@ function redirect(url, init = 302) {
1151
1173
  if (responseInit.status === undefined) {
1152
1174
  responseInit.status = 302;
1153
1175
  }
1154
- headers.set("Location", url);
1176
+ headers.set("Location", String(url));
1155
1177
  return new Response(null, {
1156
1178
  ...responseInit,
1157
1179
  headers
@@ -1282,4 +1304,4 @@ function createElement(tagName, is = undefined) {
1282
1304
  });
1283
1305
  }
1284
1306
 
1285
- export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
1307
+ export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
package/dist/server.cjs CHANGED
@@ -1272,6 +1272,13 @@ function getRequestEvent() {
1272
1272
  function renderToStringAsync(code, options = {}) {
1273
1273
  return new Promise(resolve => renderToStream(code, options).then(resolve));
1274
1274
  }
1275
+ function registerElementClaim() {
1276
+ return noopCleanup;
1277
+ }
1278
+ function noopCleanup() {}
1279
+ function claimElement(node) {
1280
+ return node;
1281
+ }
1275
1282
  function notSup() {
1276
1283
  throw new Error("Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.");
1277
1284
  }
@@ -1287,6 +1294,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1287
1294
  function isResponseEnvelope(value) {
1288
1295
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1289
1296
  }
1297
+ const HREF = Symbol.for("solid.Href");
1298
+ function isHref(value) {
1299
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1300
+ }
1290
1301
  function initWithRevalidate(init) {
1291
1302
  const {
1292
1303
  revalidate,
@@ -1300,6 +1311,9 @@ function initWithRevalidate(init) {
1300
1311
  };
1301
1312
  }
1302
1313
  function redirect(url, init = 302) {
1314
+ if (typeof url !== "string" && !isHref(url)) {
1315
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1316
+ }
1303
1317
  const {
1304
1318
  responseInit,
1305
1319
  headers
@@ -1309,7 +1323,7 @@ function redirect(url, init = 302) {
1309
1323
  if (responseInit.status === undefined) {
1310
1324
  responseInit.status = 302;
1311
1325
  }
1312
- headers.set("Location", url);
1326
+ headers.set("Location", String(url));
1313
1327
  return new Response(null, {
1314
1328
  ...responseInit,
1315
1329
  headers
@@ -1454,6 +1468,7 @@ exports.DOMElements = DOMElements;
1454
1468
  exports.DOMWithState = DOMWithState;
1455
1469
  exports.DelegatedEvents = DelegatedEvents;
1456
1470
  exports.Dynamic = Dynamic;
1471
+ exports.HREF = HREF;
1457
1472
  exports.HydrationScript = HydrationScript;
1458
1473
  exports.MathMLElements = MathMLElements;
1459
1474
  exports.Namespaces = Namespaces;
@@ -1467,6 +1482,7 @@ exports.acquireAsset = notSup;
1467
1482
  exports.addEvent = notSup;
1468
1483
  exports.applyRef = applyRef;
1469
1484
  exports.assign = notSup;
1485
+ exports.claimElement = claimElement;
1470
1486
  exports.className = notSup;
1471
1487
  exports.delegateEvents = notSup;
1472
1488
  exports.dynamic = dynamic;
@@ -1484,6 +1500,7 @@ exports.getRequestEvent = getRequestEvent;
1484
1500
  exports.hydrate = notSup;
1485
1501
  exports.insert = notSup;
1486
1502
  exports.isDev = isDev;
1503
+ exports.isHref = isHref;
1487
1504
  exports.isResponseEnvelope = isResponseEnvelope;
1488
1505
  exports.isServer = isServer;
1489
1506
  exports.memo = memo;
@@ -1491,6 +1508,7 @@ exports.redirect = redirect;
1491
1508
  exports.ref = notSup;
1492
1509
  exports.registerDelegatedContainer = notSup;
1493
1510
  exports.registerDelegatedRoot = notSup;
1511
+ exports.registerElementClaim = registerElementClaim;
1494
1512
  exports.reload = reload;
1495
1513
  exports.render = notSup;
1496
1514
  exports.renderToStream = renderToStream;
package/dist/server.js CHANGED
@@ -1271,6 +1271,13 @@ function getRequestEvent() {
1271
1271
  function renderToStringAsync(code, options = {}) {
1272
1272
  return new Promise(resolve => renderToStream(code, options).then(resolve));
1273
1273
  }
1274
+ function registerElementClaim() {
1275
+ return noopCleanup;
1276
+ }
1277
+ function noopCleanup() {}
1278
+ function claimElement(node) {
1279
+ return node;
1280
+ }
1274
1281
  function notSup() {
1275
1282
  throw new Error("Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.");
1276
1283
  }
@@ -1286,6 +1293,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1286
1293
  function isResponseEnvelope(value) {
1287
1294
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1288
1295
  }
1296
+ const HREF = Symbol.for("solid.Href");
1297
+ function isHref(value) {
1298
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1299
+ }
1289
1300
  function initWithRevalidate(init) {
1290
1301
  const {
1291
1302
  revalidate,
@@ -1299,6 +1310,9 @@ function initWithRevalidate(init) {
1299
1310
  };
1300
1311
  }
1301
1312
  function redirect(url, init = 302) {
1313
+ if (typeof url !== "string" && !isHref(url)) {
1314
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1315
+ }
1302
1316
  const {
1303
1317
  responseInit,
1304
1318
  headers
@@ -1308,7 +1322,7 @@ function redirect(url, init = 302) {
1308
1322
  if (responseInit.status === undefined) {
1309
1323
  responseInit.status = 302;
1310
1324
  }
1311
- headers.set("Location", url);
1325
+ headers.set("Location", String(url));
1312
1326
  return new Response(null, {
1313
1327
  ...responseInit,
1314
1328
  headers
@@ -1387,4 +1401,4 @@ function Portal(props) {
1387
1401
  return undefined;
1388
1402
  }
1389
1403
 
1390
- export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
1404
+ export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
package/dist/web.cjs CHANGED
@@ -277,9 +277,24 @@ function setProperty(node, name, value) {
277
277
  if (isHydrating(node)) return;
278
278
  node[name] = value;
279
279
  }
280
+ let claimHandlers = null;
281
+ function registerElementClaim(handler) {
282
+ (claimHandlers || (claimHandlers = [])).push(handler);
283
+ return () => {
284
+ const index = claimHandlers.indexOf(handler);
285
+ index > -1 && claimHandlers.splice(index, 1);
286
+ };
287
+ }
288
+ function claimElement(node) {
289
+ if (claimHandlers !== null) {
290
+ for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
291
+ }
292
+ return node;
293
+ }
280
294
  function setAttribute(node, name, value) {
281
295
  if (isHydrating(node)) return;
282
296
  if (value == null || value === false) node.removeAttribute(name);else node.setAttribute(name, value === true ? "" : value);
297
+ if (claimHandlers !== null && (name === "href" || name === "action")) claimElement(node);
283
298
  }
284
299
  function setAttributeNS(node, namespace, name, value) {
285
300
  if (isHydrating(node)) return;
@@ -1073,6 +1088,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1073
1088
  function isResponseEnvelope(value) {
1074
1089
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1075
1090
  }
1091
+ const HREF = Symbol.for("solid.Href");
1092
+ function isHref(value) {
1093
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1094
+ }
1076
1095
  function initWithRevalidate(init) {
1077
1096
  const {
1078
1097
  revalidate,
@@ -1086,6 +1105,9 @@ function initWithRevalidate(init) {
1086
1105
  };
1087
1106
  }
1088
1107
  function redirect(url, init = 302) {
1108
+ if (typeof url !== "string" && !isHref(url)) {
1109
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1110
+ }
1089
1111
  const {
1090
1112
  responseInit,
1091
1113
  headers
@@ -1095,7 +1117,7 @@ function redirect(url, init = 302) {
1095
1117
  if (responseInit.status === undefined) {
1096
1118
  responseInit.status = 302;
1097
1119
  }
1098
- headers.set("Location", url);
1120
+ headers.set("Location", String(url));
1099
1121
  return new Response(null, {
1100
1122
  ...responseInit,
1101
1123
  headers
@@ -1279,6 +1301,7 @@ exports.DOMElements = DOMElements;
1279
1301
  exports.DOMWithState = DOMWithState;
1280
1302
  exports.DelegatedEvents = DelegatedEvents;
1281
1303
  exports.Dynamic = Dynamic;
1304
+ exports.HREF = HREF;
1282
1305
  exports.HydrationScript = voidFn;
1283
1306
  exports.MathMLElements = MathMLElements;
1284
1307
  exports.Namespaces = Namespaces;
@@ -1292,6 +1315,7 @@ exports.acquireAsset = acquireAsset;
1292
1315
  exports.addEvent = addEvent;
1293
1316
  exports.applyRef = applyRef;
1294
1317
  exports.assign = assign;
1318
+ exports.claimElement = claimElement;
1295
1319
  exports.className = className;
1296
1320
  exports.delegateEvents = delegateEvents;
1297
1321
  exports.dynamic = dynamic;
@@ -1312,6 +1336,7 @@ exports.hydrate = hydrate;
1312
1336
  exports.insert = insert;
1313
1337
  exports.installHydrationRuntime = installHydrationRuntime;
1314
1338
  exports.isDev = isDev;
1339
+ exports.isHref = isHref;
1315
1340
  exports.isResponseEnvelope = isResponseEnvelope;
1316
1341
  exports.isServer = isServer;
1317
1342
  exports.memo = memo;
@@ -1320,6 +1345,7 @@ exports.redirect = redirect;
1320
1345
  exports.ref = ref;
1321
1346
  exports.registerDelegatedContainer = registerDelegatedContainer;
1322
1347
  exports.registerDelegatedRoot = registerDelegatedRoot;
1348
+ exports.registerElementClaim = registerElementClaim;
1323
1349
  exports.reload = reload;
1324
1350
  exports.render = render;
1325
1351
  exports.renderToStream = renderToStream;
package/dist/web.js CHANGED
@@ -276,9 +276,24 @@ function setProperty(node, name, value) {
276
276
  if (isHydrating(node)) return;
277
277
  node[name] = value;
278
278
  }
279
+ let claimHandlers = null;
280
+ function registerElementClaim(handler) {
281
+ (claimHandlers || (claimHandlers = [])).push(handler);
282
+ return () => {
283
+ const index = claimHandlers.indexOf(handler);
284
+ index > -1 && claimHandlers.splice(index, 1);
285
+ };
286
+ }
287
+ function claimElement(node) {
288
+ if (claimHandlers !== null) {
289
+ for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
290
+ }
291
+ return node;
292
+ }
279
293
  function setAttribute(node, name, value) {
280
294
  if (isHydrating(node)) return;
281
295
  if (value == null || value === false) node.removeAttribute(name);else node.setAttribute(name, value === true ? "" : value);
296
+ if (claimHandlers !== null && (name === "href" || name === "action")) claimElement(node);
282
297
  }
283
298
  function setAttributeNS(node, namespace, name, value) {
284
299
  if (isHydrating(node)) return;
@@ -1072,6 +1087,10 @@ ResponseEnvelope.prototype[ENVELOPE] = true;
1072
1087
  function isResponseEnvelope(value) {
1073
1088
  return !!(value && typeof value === "object" && value[ENVELOPE]);
1074
1089
  }
1090
+ const HREF = Symbol.for("solid.Href");
1091
+ function isHref(value) {
1092
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
1093
+ }
1075
1094
  function initWithRevalidate(init) {
1076
1095
  const {
1077
1096
  revalidate,
@@ -1085,6 +1104,9 @@ function initWithRevalidate(init) {
1085
1104
  };
1086
1105
  }
1087
1106
  function redirect(url, init = 302) {
1107
+ if (typeof url !== "string" && !isHref(url)) {
1108
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1109
+ }
1088
1110
  const {
1089
1111
  responseInit,
1090
1112
  headers
@@ -1094,7 +1116,7 @@ function redirect(url, init = 302) {
1094
1116
  if (responseInit.status === undefined) {
1095
1117
  responseInit.status = 302;
1096
1118
  }
1097
- headers.set("Location", url);
1119
+ headers.set("Location", String(url));
1098
1120
  return new Response(null, {
1099
1121
  ...responseInit,
1100
1122
  headers
@@ -1220,4 +1242,4 @@ function createElement(tagName, is = undefined) {
1220
1242
  });
1221
1243
  }
1222
1244
 
1223
- export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
1245
+ export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@solidjs/web",
3
3
  "description": "Solid's web runtime: client rendering, hydration, SSR, and DOM-specific control flow (Portal, Dynamic).",
4
- "version": "2.0.0-beta.21",
4
+ "version": "2.0.0-beta.22",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",
7
7
  "homepage": "https://solidjs.com",
@@ -224,10 +224,10 @@
224
224
  "seroval-plugins": "~1.5.4"
225
225
  },
226
226
  "peerDependencies": {
227
- "solid-js": "^2.0.0-beta.21"
227
+ "solid-js": "^2.0.0-beta.22"
228
228
  },
229
229
  "devDependencies": {
230
- "solid-js": "2.0.0-beta.21"
230
+ "solid-js": "2.0.0-beta.22"
231
231
  },
232
232
  "scripts": {
233
233
  "build": "npm-run-all -nl build:clean types:copy-jsx build:js",
@@ -85,6 +85,31 @@ function withMeta(fn, meta) {
85
85
  return fn;
86
86
  }
87
87
  const FUNCTION_HEADER = "X-Server-Function-Id";
88
+ const ERROR_HEADER = "X-Server-Function-Error";
89
+ const ERROR_HEADER_MARKER = "=?1?";
90
+ const NEEDS_ENCODING = /[^\x20-\x7e\xa0-\xff]/;
91
+ function encodeErrorHeaderValue(value) {
92
+ let stripped = String(value).replace(/[\r\n]+/g, "");
93
+ if (!NEEDS_ENCODING.test(stripped) && !stripped.startsWith(ERROR_HEADER_MARKER) && stripped === stripped.trim()) {
94
+ return stripped;
95
+ }
96
+ if (typeof stripped.toWellFormed === "function") {
97
+ stripped = stripped.toWellFormed();
98
+ } else {
99
+ stripped = stripped.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
100
+ }
101
+ return ERROR_HEADER_MARKER + encodeURIComponent(stripped);
102
+ }
103
+ function decodeErrorHeaderValue(value) {
104
+ if (typeof value !== "string" || !value.startsWith(ERROR_HEADER_MARKER)) {
105
+ return value;
106
+ }
107
+ try {
108
+ return decodeURIComponent(value.slice(ERROR_HEADER_MARKER.length));
109
+ } catch {
110
+ return value;
111
+ }
112
+ }
88
113
  const INSTANCE_HEADER = "X-Server-Function-Instance";
89
114
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
90
115
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
@@ -372,7 +397,7 @@ async function fetchServerFunction(base, id, options, args, meta) {
372
397
  await consumer(payload.data, {
373
398
  response
374
399
  });
375
- if (response.headers.has("X-Server-Function-Error") && !response.headers.has("Location") && !response.headers.has("X-Revalidate")) {
400
+ if (response.headers.has(ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has("X-Revalidate")) {
376
401
  throw payload.value;
377
402
  }
378
403
  return payload.value;
@@ -382,22 +407,22 @@ async function fetchServerFunction(base, id, options, args, meta) {
382
407
  return response;
383
408
  }
384
409
  const result = await decodeResponse(response.clone());
385
- if (response.headers.has("X-Server-Function-Error")) {
410
+ if (response.headers.has(ERROR_HEADER)) {
386
411
  throw result;
387
412
  }
388
413
  return result;
389
414
  }
390
- function createServerReference(id, name) {
415
+ function createServerReference(id, name, base) {
391
416
  const metadata = name === undefined ? {} : {
392
417
  name
393
418
  };
394
- const fn = (...args) => fetchServerFunction(config.endpoint, id, {}, args, metadata);
419
+ const fn = (...args) => fetchServerFunction(base || config.endpoint, id, {}, args, metadata);
395
420
  fn[SERVER_FUNCTION_METADATA] = metadata;
396
421
  return new Proxy(fn, {
397
422
  get(target, prop) {
398
423
  if (prop === "id") return id;
399
424
  if (prop === "url") {
400
- return `${config.endpoint}?id=${encodeURIComponent(id)}`;
425
+ return base || `${config.endpoint}?id=${encodeURIComponent(id)}`;
401
426
  }
402
427
  return target[prop];
403
428
  }
@@ -434,13 +459,16 @@ function registerServerReference() {
434
459
  throw new Error("registerServerReference must not be called in the client build");
435
460
  }
436
461
 
462
+ exports.ERROR_HEADER = ERROR_HEADER;
437
463
  exports.FUNCTION_HEADER = FUNCTION_HEADER;
438
464
  exports.GET = GET;
439
465
  exports.INSTANCE_HEADER = INSTANCE_HEADER;
440
466
  exports.SINGLE_FLIGHT_HEADER = SINGLE_FLIGHT_HEADER;
441
467
  exports.configureServerFunctionsClient = configureServerFunctionsClient;
442
468
  exports.createServerReference = createServerReference;
469
+ exports.decodeErrorHeaderValue = decodeErrorHeaderValue;
443
470
  exports.decodeResponse = decodeResponse;
471
+ exports.encodeErrorHeaderValue = encodeErrorHeaderValue;
444
472
  exports.getServerFunctionMetadata = getServerFunctionMetadata;
445
473
  exports.isServerFunction = isServerFunction;
446
474
  exports.registerServerReference = registerServerReference;
@@ -83,6 +83,31 @@ function withMeta(fn, meta) {
83
83
  return fn;
84
84
  }
85
85
  const FUNCTION_HEADER = "X-Server-Function-Id";
86
+ const ERROR_HEADER = "X-Server-Function-Error";
87
+ const ERROR_HEADER_MARKER = "=?1?";
88
+ const NEEDS_ENCODING = /[^\x20-\x7e\xa0-\xff]/;
89
+ function encodeErrorHeaderValue(value) {
90
+ let stripped = String(value).replace(/[\r\n]+/g, "");
91
+ if (!NEEDS_ENCODING.test(stripped) && !stripped.startsWith(ERROR_HEADER_MARKER) && stripped === stripped.trim()) {
92
+ return stripped;
93
+ }
94
+ if (typeof stripped.toWellFormed === "function") {
95
+ stripped = stripped.toWellFormed();
96
+ } else {
97
+ stripped = stripped.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
98
+ }
99
+ return ERROR_HEADER_MARKER + encodeURIComponent(stripped);
100
+ }
101
+ function decodeErrorHeaderValue(value) {
102
+ if (typeof value !== "string" || !value.startsWith(ERROR_HEADER_MARKER)) {
103
+ return value;
104
+ }
105
+ try {
106
+ return decodeURIComponent(value.slice(ERROR_HEADER_MARKER.length));
107
+ } catch {
108
+ return value;
109
+ }
110
+ }
86
111
  const INSTANCE_HEADER = "X-Server-Function-Instance";
87
112
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
88
113
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
@@ -370,7 +395,7 @@ async function fetchServerFunction(base, id, options, args, meta) {
370
395
  await consumer(payload.data, {
371
396
  response
372
397
  });
373
- if (response.headers.has("X-Server-Function-Error") && !response.headers.has("Location") && !response.headers.has("X-Revalidate")) {
398
+ if (response.headers.has(ERROR_HEADER) && !response.headers.has("Location") && !response.headers.has("X-Revalidate")) {
374
399
  throw payload.value;
375
400
  }
376
401
  return payload.value;
@@ -380,22 +405,22 @@ async function fetchServerFunction(base, id, options, args, meta) {
380
405
  return response;
381
406
  }
382
407
  const result = await decodeResponse(response.clone());
383
- if (response.headers.has("X-Server-Function-Error")) {
408
+ if (response.headers.has(ERROR_HEADER)) {
384
409
  throw result;
385
410
  }
386
411
  return result;
387
412
  }
388
- function createServerReference(id, name) {
413
+ function createServerReference(id, name, base) {
389
414
  const metadata = name === undefined ? {} : {
390
415
  name
391
416
  };
392
- const fn = (...args) => fetchServerFunction(config.endpoint, id, {}, args, metadata);
417
+ const fn = (...args) => fetchServerFunction(base || config.endpoint, id, {}, args, metadata);
393
418
  fn[SERVER_FUNCTION_METADATA] = metadata;
394
419
  return new Proxy(fn, {
395
420
  get(target, prop) {
396
421
  if (prop === "id") return id;
397
422
  if (prop === "url") {
398
- return `${config.endpoint}?id=${encodeURIComponent(id)}`;
423
+ return base || `${config.endpoint}?id=${encodeURIComponent(id)}`;
399
424
  }
400
425
  return target[prop];
401
426
  }
@@ -432,4 +457,4 @@ function registerServerReference() {
432
457
  throw new Error("registerServerReference must not be called in the client build");
433
458
  }
434
459
 
435
- export { FUNCTION_HEADER, GET, INSTANCE_HEADER, SINGLE_FLIGHT_HEADER, configureServerFunctionsClient, createServerReference, decodeResponse, getServerFunctionMetadata, isServerFunction, registerServerReference, subscribeFlightData, withMeta };
460
+ export { ERROR_HEADER, FUNCTION_HEADER, GET, INSTANCE_HEADER, SINGLE_FLIGHT_HEADER, configureServerFunctionsClient, createServerReference, decodeErrorHeaderValue, decodeResponse, encodeErrorHeaderValue, getServerFunctionMetadata, isServerFunction, registerServerReference, subscribeFlightData, withMeta };
@@ -88,6 +88,31 @@ function withMeta(fn, meta) {
88
88
  return fn;
89
89
  }
90
90
  const FUNCTION_HEADER = "X-Server-Function-Id";
91
+ const ERROR_HEADER = "X-Server-Function-Error";
92
+ const ERROR_HEADER_MARKER = "=?1?";
93
+ const NEEDS_ENCODING = /[^\x20-\x7e\xa0-\xff]/;
94
+ function encodeErrorHeaderValue(value) {
95
+ let stripped = String(value).replace(/[\r\n]+/g, "");
96
+ if (!NEEDS_ENCODING.test(stripped) && !stripped.startsWith(ERROR_HEADER_MARKER) && stripped === stripped.trim()) {
97
+ return stripped;
98
+ }
99
+ if (typeof stripped.toWellFormed === "function") {
100
+ stripped = stripped.toWellFormed();
101
+ } else {
102
+ stripped = stripped.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
103
+ }
104
+ return ERROR_HEADER_MARKER + encodeURIComponent(stripped);
105
+ }
106
+ function decodeErrorHeaderValue(value) {
107
+ if (typeof value !== "string" || !value.startsWith(ERROR_HEADER_MARKER)) {
108
+ return value;
109
+ }
110
+ try {
111
+ return decodeURIComponent(value.slice(ERROR_HEADER_MARKER.length));
112
+ } catch {
113
+ return value;
114
+ }
115
+ }
91
116
  const INSTANCE_HEADER = "X-Server-Function-Instance";
92
117
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
93
118
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
@@ -400,7 +425,8 @@ function resolveFunctionId(request, url) {
400
425
  }
401
426
  async function parseArguments(request, url, instance, codec) {
402
427
  const parsed = [];
403
- if (!instance || request.method === "GET") {
428
+ const bodyFormat = request.method === "POST" ? request.headers.get(BODY_FORMAT_HEADER) : null;
429
+ if (!instance || request.method === "GET" || bodyFormat !== BodyFormat.Serialized) {
404
430
  const args = url.searchParams.get("args");
405
431
  if (args) {
406
432
  const result = args.startsWith(";0x") ? await deserializeString(args, codec) : JSON.parse(args);
@@ -410,9 +436,8 @@ async function parseArguments(request, url, instance, codec) {
410
436
  }
411
437
  }
412
438
  if (request.method === "POST" && request.body !== null) {
413
- const format = request.headers.get(BODY_FORMAT_HEADER);
414
439
  const decoded = await extractBody(request.clone(), codec);
415
- if (format === BodyFormat.Serialized) {
440
+ if (bodyFormat === BodyFormat.Serialized) {
416
441
  return decoded;
417
442
  }
418
443
  parsed.push(decoded);
@@ -470,12 +495,11 @@ async function handleServerFunctionRequest(request, options = {}) {
470
495
  status: 404
471
496
  });
472
497
  }
473
- const allowedMethod = METHODS.get(functionId) || "POST";
474
- if (request.method === "GET" !== (allowedMethod === "GET")) {
498
+ if (request.method === "GET" && METHODS.get(functionId) !== "GET") {
475
499
  return new Response(process.env.NODE_ENV === "development" ? `Method not allowed for server function: ${functionId}` : null, {
476
500
  status: 405,
477
501
  headers: {
478
- Allow: allowedMethod
502
+ Allow: "POST"
479
503
  }
480
504
  });
481
505
  }
@@ -594,7 +618,7 @@ async function handleServerFunctionRequest(request, options = {}) {
594
618
  thrown: true
595
619
  });
596
620
  }
597
- headers.set("X-Server-Function-Error", "true");
621
+ headers.set(ERROR_HEADER, "true");
598
622
  if (!instance) {
599
623
  if (options.handleNoJS) return options.handleNoJS(x, request, parsed, true);
600
624
  if (x instanceof Response) return x;
@@ -609,18 +633,21 @@ async function handleServerFunctionRequest(request, options = {}) {
609
633
  });
610
634
  }
611
635
  const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
612
- headers.set("X-Server-Function-Error", error.replace(/[\r\n]+/g, ""));
636
+ headers.set(ERROR_HEADER, encodeErrorHeaderValue(error));
613
637
  return encodeResult(x, headers, 200, codec);
614
638
  }
615
639
  }
616
640
 
641
+ exports.ERROR_HEADER = ERROR_HEADER;
617
642
  exports.FUNCTION_HEADER = FUNCTION_HEADER;
618
643
  exports.GET = GET;
619
644
  exports.INSTANCE_HEADER = INSTANCE_HEADER;
620
645
  exports.SINGLE_FLIGHT_HEADER = SINGLE_FLIGHT_HEADER;
621
646
  exports.configureServerFunctionsServer = configureServerFunctionsServer;
622
647
  exports.createServerReference = createServerReference;
648
+ exports.decodeErrorHeaderValue = decodeErrorHeaderValue;
623
649
  exports.decodeResponse = decodeResponse;
650
+ exports.encodeErrorHeaderValue = encodeErrorHeaderValue;
624
651
  exports.getServerFunction = getServerFunction;
625
652
  exports.getServerFunctionMeta = getServerFunctionMeta;
626
653
  exports.getServerFunctionMetadata = getServerFunctionMetadata;
@@ -86,6 +86,31 @@ function withMeta(fn, meta) {
86
86
  return fn;
87
87
  }
88
88
  const FUNCTION_HEADER = "X-Server-Function-Id";
89
+ const ERROR_HEADER = "X-Server-Function-Error";
90
+ const ERROR_HEADER_MARKER = "=?1?";
91
+ const NEEDS_ENCODING = /[^\x20-\x7e\xa0-\xff]/;
92
+ function encodeErrorHeaderValue(value) {
93
+ let stripped = String(value).replace(/[\r\n]+/g, "");
94
+ if (!NEEDS_ENCODING.test(stripped) && !stripped.startsWith(ERROR_HEADER_MARKER) && stripped === stripped.trim()) {
95
+ return stripped;
96
+ }
97
+ if (typeof stripped.toWellFormed === "function") {
98
+ stripped = stripped.toWellFormed();
99
+ } else {
100
+ stripped = stripped.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "\uFFFD");
101
+ }
102
+ return ERROR_HEADER_MARKER + encodeURIComponent(stripped);
103
+ }
104
+ function decodeErrorHeaderValue(value) {
105
+ if (typeof value !== "string" || !value.startsWith(ERROR_HEADER_MARKER)) {
106
+ return value;
107
+ }
108
+ try {
109
+ return decodeURIComponent(value.slice(ERROR_HEADER_MARKER.length));
110
+ } catch {
111
+ return value;
112
+ }
113
+ }
89
114
  const INSTANCE_HEADER = "X-Server-Function-Instance";
90
115
  const BODY_FORMAT_HEADER = "X-Server-Function-Format";
91
116
  const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
@@ -398,7 +423,8 @@ function resolveFunctionId(request, url) {
398
423
  }
399
424
  async function parseArguments(request, url, instance, codec) {
400
425
  const parsed = [];
401
- if (!instance || request.method === "GET") {
426
+ const bodyFormat = request.method === "POST" ? request.headers.get(BODY_FORMAT_HEADER) : null;
427
+ if (!instance || request.method === "GET" || bodyFormat !== BodyFormat.Serialized) {
402
428
  const args = url.searchParams.get("args");
403
429
  if (args) {
404
430
  const result = args.startsWith(";0x") ? await deserializeString(args, codec) : JSON.parse(args);
@@ -408,9 +434,8 @@ async function parseArguments(request, url, instance, codec) {
408
434
  }
409
435
  }
410
436
  if (request.method === "POST" && request.body !== null) {
411
- const format = request.headers.get(BODY_FORMAT_HEADER);
412
437
  const decoded = await extractBody(request.clone(), codec);
413
- if (format === BodyFormat.Serialized) {
438
+ if (bodyFormat === BodyFormat.Serialized) {
414
439
  return decoded;
415
440
  }
416
441
  parsed.push(decoded);
@@ -468,12 +493,11 @@ async function handleServerFunctionRequest(request, options = {}) {
468
493
  status: 404
469
494
  });
470
495
  }
471
- const allowedMethod = METHODS.get(functionId) || "POST";
472
- if (request.method === "GET" !== (allowedMethod === "GET")) {
496
+ if (request.method === "GET" && METHODS.get(functionId) !== "GET") {
473
497
  return new Response(process.env.NODE_ENV === "development" ? `Method not allowed for server function: ${functionId}` : null, {
474
498
  status: 405,
475
499
  headers: {
476
- Allow: allowedMethod
500
+ Allow: "POST"
477
501
  }
478
502
  });
479
503
  }
@@ -592,7 +616,7 @@ async function handleServerFunctionRequest(request, options = {}) {
592
616
  thrown: true
593
617
  });
594
618
  }
595
- headers.set("X-Server-Function-Error", "true");
619
+ headers.set(ERROR_HEADER, "true");
596
620
  if (!instance) {
597
621
  if (options.handleNoJS) return options.handleNoJS(x, request, parsed, true);
598
622
  if (x instanceof Response) return x;
@@ -607,9 +631,9 @@ async function handleServerFunctionRequest(request, options = {}) {
607
631
  });
608
632
  }
609
633
  const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true";
610
- headers.set("X-Server-Function-Error", error.replace(/[\r\n]+/g, ""));
634
+ headers.set(ERROR_HEADER, encodeErrorHeaderValue(error));
611
635
  return encodeResult(x, headers, 200, codec);
612
636
  }
613
637
  }
614
638
 
615
- export { FUNCTION_HEADER, GET, INSTANCE_HEADER, SINGLE_FLIGHT_HEADER, configureServerFunctionsServer, createServerReference, decodeResponse, getServerFunction, getServerFunctionMeta, getServerFunctionMetadata, handleServerFunctionRequest, isServerFunction, registerServerFunction, registerServerReference, subscribeFlightData, withMeta };
639
+ export { ERROR_HEADER, FUNCTION_HEADER, GET, INSTANCE_HEADER, SINGLE_FLIGHT_HEADER, configureServerFunctionsServer, createServerReference, decodeErrorHeaderValue, decodeResponse, encodeErrorHeaderValue, getServerFunction, getServerFunctionMeta, getServerFunctionMetadata, handleServerFunctionRequest, isServerFunction, registerServerFunction, registerServerReference, subscribeFlightData, withMeta };
package/types/client.d.ts CHANGED
@@ -66,6 +66,24 @@ export function assign(
66
66
  ): void;
67
67
  export function setAttribute(node: Element, name: string, value: string): void;
68
68
  export function setAttributeNS(node: Element, namespace: string, name: string, value: string): void;
69
+ /**
70
+ * Register a consumer for compiler-emitted element claims. Compiled DOM
71
+ * output claims navigation-relevant elements (`a[href]`, `form[action]`) at
72
+ * creation, and compiler-owned writes to `href`/`action` re-invoke the same
73
+ * handlers — so handlers must be idempotent and must check the element's
74
+ * relevance themselves (rechecks can fire for any element whose
75
+ * `href`/`action` is written, e.g. `<link href>`). Handlers run under the
76
+ * reactive owner current at element creation; scope per-element state and
77
+ * cleanup through your own reactive system. Dormant until registered —
78
+ * without a handler the emitted claims are null checks. Returns an
79
+ * unregister function.
80
+ */
81
+ export function registerElementClaim(handler: (element: Element) => void): () => void;
82
+ /**
83
+ * Claim `node` for registered consumers (see `registerElementClaim`).
84
+ * Emitted by the compiler at element creation; idempotent by contract.
85
+ */
86
+ export function claimElement<T extends Element>(node: T): T;
69
87
  export function className(node: Element, value: JSX.ClassValue, prev?: JSX.ClassValue): void;
70
88
  export function setProperty(node: Element, name: string, value: any): void;
71
89
  export function setStyleProperty(node: Element, name: string, value: any): void;
package/types/jsx.d.ts CHANGED
@@ -1120,7 +1120,7 @@ export namespace JSX {
1120
1120
 
1121
1121
  interface AnchorHTMLAttributes<T> extends HTMLAttributes<T> {
1122
1122
  download?: string | EnumeratedAcceptsEmpty | RemoveAttribute;
1123
- href?: string | RemoveAttribute;
1123
+ href?: string | SerializableAttributeValue | RemoveAttribute;
1124
1124
  hreflang?: string | RemoveAttribute;
1125
1125
  ping?: string | RemoveAttribute;
1126
1126
  referrerpolicy?: HTMLReferrerPolicy | RemoveAttribute;
@@ -1128,6 +1128,21 @@ export namespace JSX {
1128
1128
  target?: "_self" | "_blank" | "_parent" | "_top" | (string & {}) | RemoveAttribute;
1129
1129
  type?: string | RemoveAttribute;
1130
1130
 
1131
+ // Client-side navigation contract. These attributes are inert markup on
1132
+ // their own — a routing integration that delegates anchor clicks (e.g.
1133
+ // @solidjs/router) reads them off the element at event time. Typed here
1134
+ // so plain `<a>` elements participate without per-router augmentation.
1135
+ /** Marks the anchor as a client-navigation link when the integration requires explicit opt-in. */
1136
+ link?: BooleanAttribute | RemoveAttribute;
1137
+ /** Serialized (JSON) history state pushed alongside the navigation. */
1138
+ state?: string | RemoveAttribute;
1139
+ /** Suppress scroll restoration/reset after the navigation. */
1140
+ noScroll?: BooleanAttribute | RemoveAttribute;
1141
+ /** Replace the current history entry instead of pushing a new one. */
1142
+ replace?: BooleanAttribute | RemoveAttribute;
1143
+ /** Route preload intent; `"false"` disables the integration's default eager preload. */
1144
+ preload?: boolean | "false" | RemoveAttribute;
1145
+
1131
1146
  /** @experimental */
1132
1147
  attributionsrc?: string | RemoveAttribute;
1133
1148
 
@@ -1147,7 +1162,7 @@ export namespace JSX {
1147
1162
  alt?: string | RemoveAttribute;
1148
1163
  coords?: string | RemoveAttribute;
1149
1164
  download?: string | EnumeratedAcceptsEmpty | RemoveAttribute;
1150
- href?: string | RemoveAttribute;
1165
+ href?: string | SerializableAttributeValue | RemoveAttribute;
1151
1166
  ping?: string | RemoveAttribute;
1152
1167
  referrerpolicy?: HTMLReferrerPolicy | RemoveAttribute;
1153
1168
  rel?: string | RemoveAttribute;
@@ -23,6 +23,32 @@ export class ResponseEnvelope<T = unknown> {
23
23
  */
24
24
  export function isResponseEnvelope(value: unknown): value is ResponseEnvelope;
25
25
 
26
+ /**
27
+ * Registered-symbol brand (`Symbol.for("solid.Href")`) marking URL-bearing
28
+ * values. Declared `unique symbol` type-side; the runtime value is the
29
+ * registered symbol, so separately bundled copies agree on identity.
30
+ */
31
+ export declare const HREF: unique symbol;
32
+
33
+ /**
34
+ * A URL-bearing value: coerces to its URL via `toString()` and carries the
35
+ * `HREF` registered-symbol brand. Integrations mint these (e.g. a router's
36
+ * typed path objects answer the brand from their proxy) and URL-accepting
37
+ * APIs like `redirect()` accept them alongside plain strings. The brand is
38
+ * what makes the type meaningful — every object has `toString()`.
39
+ */
40
+ export interface Href {
41
+ [HREF]: true;
42
+ toString(): string;
43
+ }
44
+
45
+ /**
46
+ * Whether `value` is an `Href`-branded URL-bearing value. Registered-symbol
47
+ * check, so it stays correct across duplicated module instances — same
48
+ * rationale as `isResponseEnvelope`.
49
+ */
50
+ export function isHref(value: unknown): value is Href;
51
+
26
52
  /** `ResponseInit` accepted by the response helpers, plus `revalidate`. */
27
53
  export interface ResponseHelperInit extends ResponseInit {
28
54
  /**
@@ -51,7 +77,7 @@ export interface ResponseHelperInit extends ResponseInit {
51
77
  * }
52
78
  * ```
53
79
  */
54
- export function redirect(url: string, init?: number | ResponseHelperInit): Response;
80
+ export function redirect(url: string | Href, init?: number | ResponseHelperInit): Response;
55
81
 
56
82
  /**
57
83
  * Empty response requesting revalidation of the named cache keys — all of
@@ -2,10 +2,13 @@ import { JSONCodecOptions } from "../serializer.js";
2
2
  import { ServerFunction, ServerFunctionMetadata } from "./shared.js";
3
3
 
4
4
  export {
5
+ ERROR_HEADER,
5
6
  FUNCTION_HEADER,
6
7
  INSTANCE_HEADER,
7
8
  SINGLE_FLIGHT_HEADER,
9
+ decodeErrorHeaderValue,
8
10
  decodeResponse,
11
+ encodeErrorHeaderValue,
9
12
  getServerFunctionMetadata,
10
13
  isServerFunction,
11
14
  subscribeFlightData,
@@ -97,10 +100,11 @@ export function configureServerFunctionsClient(config?: ServerFunctionsClientCon
97
100
  *
98
101
  * The declaration rides the metadata channel
99
102
  * (`getServerFunctionMetadata(fn)?.method === "GET"`) for routers and
100
- * integrations to detect, and the server enforces it: GET-declared
101
- * functions accept GET requests (and only GET), everything else answers
102
- * 405. Server-side the wrapper is identity-flavored SSR calls stay
103
- * in-process.
103
+ * integrations to detect, and the server honors it: GET-declared functions
104
+ * accept GET requests in addition to the default POST transport (declaring
105
+ * GET grants, it does not revoke); functions that never declared GET answer
106
+ * GET requests with 405. Server-side the wrapper is identity-flavored — SSR
107
+ * calls stay in-process.
104
108
  *
105
109
  * Wrap the reference at its declaration; the compiler round-trips the call
106
110
  * in both builds:
@@ -123,9 +127,16 @@ export function GET<A extends readonly any[], R>(
123
127
  * source name as the trailing argument (dev-only metadata seeded on the
124
128
  * metadata channel; never emitted in production). Not meant for
125
129
  * hand-written code.
130
+ *
131
+ * The optional `base` targets calls at that url verbatim instead of the
132
+ * configured endpoint — for integrations reconstructing a callable from a
133
+ * server-rendered action url (e.g. a router intercepting a form submit whose
134
+ * `action="/_server?id=...&args=..."` came off the wire): bound arguments
135
+ * stay in the query string, where the server reads them for natural-encoding
136
+ * bodies (FormData, urlencoded).
126
137
  * @internal
127
138
  */
128
- export function createServerReference(id: string, name?: string): ServerFunction;
139
+ export function createServerReference(id: string, name?: string, base?: string): ServerFunction;
129
140
 
130
141
  /**
131
142
  * Compiler ABI — only ever referenced by server-mode compiler output;
@@ -3,10 +3,13 @@ import { JSONCodecOptions } from "../serializer.js";
3
3
  import { RequestEvent } from "../server.js";
4
4
 
5
5
  export {
6
+ ERROR_HEADER,
6
7
  FUNCTION_HEADER,
7
8
  INSTANCE_HEADER,
8
9
  SINGLE_FLIGHT_HEADER,
10
+ decodeErrorHeaderValue,
9
11
  decodeResponse,
12
+ encodeErrorHeaderValue,
10
13
  getServerFunctionMetadata,
11
14
  isServerFunction,
12
15
  subscribeFlightData,
@@ -194,8 +197,9 @@ export function createServerReference<T extends any[], R>(
194
197
  * declaration on the reference's metadata channel
195
198
  * (`getServerFunctionMetadata(fn)?.method === "GET"`) and records the
196
199
  * declared method for the function's id so `handleServerFunctionRequest`
197
- * enforces it: GET-declared functions accept GET requests (and only GET),
198
- * everything else answers 405.
200
+ * honors it: GET-declared functions accept GET requests in addition to the
201
+ * default POST transport (declaring GET grants, it does not revoke);
202
+ * functions that never declared GET answer GET requests with 405.
199
203
  *
200
204
  * Wrap the reference at its declaration; the compiler round-trips the call
201
205
  * in both builds:
@@ -282,9 +286,9 @@ export interface HandleServerFunctionOptions {
282
286
 
283
287
  /**
284
288
  * Web-standard HTTP handler for server function calls: resolves the
285
- * function id from the request, enforces the declared method (405 when the
286
- * request method contradicts a `GET` declaration or uses GET without
287
- * one), decodes arguments, runs the function under a request-event scope,
289
+ * function id from the request, gates GET dispatch on the declaration (405
290
+ * for a GET request to a function that never declared `GET`; POST is always
291
+ * accepted), decodes arguments, runs the function under a request-event scope,
288
292
  * and encodes the result (forwarding redirect/revalidation metadata
289
293
  * through headers). Mount it on the endpoint the client transport targets
290
294
  * (default `/_server`); platform adapters (h3, express, ...) convert their
@@ -38,6 +38,35 @@ export const FUNCTION_HEADER: string;
38
38
  */
39
39
  export const INSTANCE_HEADER: string;
40
40
 
41
+ /**
42
+ * Response header marking a thrown server-function error
43
+ * (`"X-Server-Function-Error"`). The client transport rejects with the
44
+ * decoded body when it is present (unless redirect/revalidation metadata
45
+ * marks the response as control flow). The value carries the error's
46
+ * message — `"true"` for thrown control-flow responses and non-Error
47
+ * values — encoded with `encodeErrorHeaderValue`, so integrations reading
48
+ * it must pass it through `decodeErrorHeaderValue`.
49
+ */
50
+ export const ERROR_HEADER: string;
51
+
52
+ /**
53
+ * Encodes an error message for the `ERROR_HEADER` value. HTTP header values
54
+ * are latin1 ByteStrings — `Headers.set` throws on code points above U+00FF
55
+ * — so plain printable-latin1 messages ride verbatim (ASCII stays
56
+ * byte-identical on the wire) and everything else (CJK, emoji, controls)
57
+ * travels percent-encoded behind a marker. `decodeErrorHeaderValue`
58
+ * round-trips the message exactly, astral-plane characters included (lone
59
+ * surrogates are replaced with U+FFFD — they cannot survive UTF-8 anyway).
60
+ */
61
+ export function encodeErrorHeaderValue(value: string): string;
62
+
63
+ /**
64
+ * Decodes an `ERROR_HEADER` value produced by `encodeErrorHeaderValue`:
65
+ * marked values are percent-decoded, everything else (including values from
66
+ * peers that never encode) passes through untouched.
67
+ */
68
+ export function decodeErrorHeaderValue(value: string): string;
69
+
41
70
  /**
42
71
  * Header driving the single-flight protocol on both legs
43
72
  * (`"X-Single-Flight"`). On the request it opts the call into data
package/types/server.d.ts CHANGED
@@ -205,6 +205,14 @@ export function setAttribute(node: Element, name: string, value: string): void;
205
205
  /** @deprecated not supported on the server side */
206
206
  export function setAttributeNS(node: Element, namespace: string, name: string, value: string): void;
207
207
 
208
+ /**
209
+ * Server no-op: element claims are a client-only concern, but consumers may
210
+ * register isomorphically. Returns a no-op unregister function.
211
+ */
212
+ export function registerElementClaim(handler: (element: Element) => void): () => void;
213
+ /** Server no-op: returns `node` unchanged. Claims never fire during SSR. */
214
+ export function claimElement<T extends Element>(node: T): T;
215
+
208
216
  /** @deprecated not supported on the server side */
209
217
  export function addEvent(node: Element, name: string, handler: () => void, delegate: boolean): void;
210
218
 
@@ -66,6 +66,24 @@ export function assign(
66
66
  ): void;
67
67
  export function setAttribute(node: Element, name: string, value: string): void;
68
68
  export function setAttributeNS(node: Element, namespace: string, name: string, value: string): void;
69
+ /**
70
+ * Register a consumer for compiler-emitted element claims. Compiled DOM
71
+ * output claims navigation-relevant elements (`a[href]`, `form[action]`) at
72
+ * creation, and compiler-owned writes to `href`/`action` re-invoke the same
73
+ * handlers — so handlers must be idempotent and must check the element's
74
+ * relevance themselves (rechecks can fire for any element whose
75
+ * `href`/`action` is written, e.g. `<link href>`). Handlers run under the
76
+ * reactive owner current at element creation; scope per-element state and
77
+ * cleanup through your own reactive system. Dormant until registered —
78
+ * without a handler the emitted claims are null checks. Returns an
79
+ * unregister function.
80
+ */
81
+ export function registerElementClaim(handler: (element: Element) => void): () => void;
82
+ /**
83
+ * Claim `node` for registered consumers (see `registerElementClaim`).
84
+ * Emitted by the compiler at element creation; idempotent by contract.
85
+ */
86
+ export function claimElement<T extends Element>(node: T): T;
69
87
  export function className(node: Element, value: JSX.ClassValue, prev?: JSX.ClassValue): void;
70
88
  export function setProperty(node: Element, name: string, value: any): void;
71
89
  export function setStyleProperty(node: Element, name: string, value: any): void;
@@ -1120,7 +1120,7 @@ export namespace JSX {
1120
1120
 
1121
1121
  interface AnchorHTMLAttributes<T> extends HTMLAttributes<T> {
1122
1122
  download?: string | EnumeratedAcceptsEmpty | RemoveAttribute;
1123
- href?: string | RemoveAttribute;
1123
+ href?: string | SerializableAttributeValue | RemoveAttribute;
1124
1124
  hreflang?: string | RemoveAttribute;
1125
1125
  ping?: string | RemoveAttribute;
1126
1126
  referrerpolicy?: HTMLReferrerPolicy | RemoveAttribute;
@@ -1128,6 +1128,21 @@ export namespace JSX {
1128
1128
  target?: "_self" | "_blank" | "_parent" | "_top" | (string & {}) | RemoveAttribute;
1129
1129
  type?: string | RemoveAttribute;
1130
1130
 
1131
+ // Client-side navigation contract. These attributes are inert markup on
1132
+ // their own — a routing integration that delegates anchor clicks (e.g.
1133
+ // @solidjs/router) reads them off the element at event time. Typed here
1134
+ // so plain `<a>` elements participate without per-router augmentation.
1135
+ /** Marks the anchor as a client-navigation link when the integration requires explicit opt-in. */
1136
+ link?: BooleanAttribute | RemoveAttribute;
1137
+ /** Serialized (JSON) history state pushed alongside the navigation. */
1138
+ state?: string | RemoveAttribute;
1139
+ /** Suppress scroll restoration/reset after the navigation. */
1140
+ noScroll?: BooleanAttribute | RemoveAttribute;
1141
+ /** Replace the current history entry instead of pushing a new one. */
1142
+ replace?: BooleanAttribute | RemoveAttribute;
1143
+ /** Route preload intent; `"false"` disables the integration's default eager preload. */
1144
+ preload?: boolean | "false" | RemoveAttribute;
1145
+
1131
1146
  /** @experimental */
1132
1147
  attributionsrc?: string | RemoveAttribute;
1133
1148
 
@@ -1147,7 +1162,7 @@ export namespace JSX {
1147
1162
  alt?: string | RemoveAttribute;
1148
1163
  coords?: string | RemoveAttribute;
1149
1164
  download?: string | EnumeratedAcceptsEmpty | RemoveAttribute;
1150
- href?: string | RemoveAttribute;
1165
+ href?: string | SerializableAttributeValue | RemoveAttribute;
1151
1166
  ping?: string | RemoveAttribute;
1152
1167
  referrerpolicy?: HTMLReferrerPolicy | RemoveAttribute;
1153
1168
  rel?: string | RemoveAttribute;
@@ -23,6 +23,32 @@ export class ResponseEnvelope<T = unknown> {
23
23
  */
24
24
  export function isResponseEnvelope(value: unknown): value is ResponseEnvelope;
25
25
 
26
+ /**
27
+ * Registered-symbol brand (`Symbol.for("solid.Href")`) marking URL-bearing
28
+ * values. Declared `unique symbol` type-side; the runtime value is the
29
+ * registered symbol, so separately bundled copies agree on identity.
30
+ */
31
+ export declare const HREF: unique symbol;
32
+
33
+ /**
34
+ * A URL-bearing value: coerces to its URL via `toString()` and carries the
35
+ * `HREF` registered-symbol brand. Integrations mint these (e.g. a router's
36
+ * typed path objects answer the brand from their proxy) and URL-accepting
37
+ * APIs like `redirect()` accept them alongside plain strings. The brand is
38
+ * what makes the type meaningful — every object has `toString()`.
39
+ */
40
+ export interface Href {
41
+ [HREF]: true;
42
+ toString(): string;
43
+ }
44
+
45
+ /**
46
+ * Whether `value` is an `Href`-branded URL-bearing value. Registered-symbol
47
+ * check, so it stays correct across duplicated module instances — same
48
+ * rationale as `isResponseEnvelope`.
49
+ */
50
+ export function isHref(value: unknown): value is Href;
51
+
26
52
  /** `ResponseInit` accepted by the response helpers, plus `revalidate`. */
27
53
  export interface ResponseHelperInit extends ResponseInit {
28
54
  /**
@@ -51,7 +77,7 @@ export interface ResponseHelperInit extends ResponseInit {
51
77
  * }
52
78
  * ```
53
79
  */
54
- export function redirect(url: string, init?: number | ResponseHelperInit): Response;
80
+ export function redirect(url: string | Href, init?: number | ResponseHelperInit): Response;
55
81
 
56
82
  /**
57
83
  * Empty response requesting revalidation of the named cache keys — all of
@@ -2,10 +2,13 @@ import { JSONCodecOptions } from "../serializer.cjs";
2
2
  import { ServerFunction, ServerFunctionMetadata } from "./shared.cjs";
3
3
 
4
4
  export {
5
+ ERROR_HEADER,
5
6
  FUNCTION_HEADER,
6
7
  INSTANCE_HEADER,
7
8
  SINGLE_FLIGHT_HEADER,
9
+ decodeErrorHeaderValue,
8
10
  decodeResponse,
11
+ encodeErrorHeaderValue,
9
12
  getServerFunctionMetadata,
10
13
  isServerFunction,
11
14
  subscribeFlightData,
@@ -97,10 +100,11 @@ export function configureServerFunctionsClient(config?: ServerFunctionsClientCon
97
100
  *
98
101
  * The declaration rides the metadata channel
99
102
  * (`getServerFunctionMetadata(fn)?.method === "GET"`) for routers and
100
- * integrations to detect, and the server enforces it: GET-declared
101
- * functions accept GET requests (and only GET), everything else answers
102
- * 405. Server-side the wrapper is identity-flavored SSR calls stay
103
- * in-process.
103
+ * integrations to detect, and the server honors it: GET-declared functions
104
+ * accept GET requests in addition to the default POST transport (declaring
105
+ * GET grants, it does not revoke); functions that never declared GET answer
106
+ * GET requests with 405. Server-side the wrapper is identity-flavored — SSR
107
+ * calls stay in-process.
104
108
  *
105
109
  * Wrap the reference at its declaration; the compiler round-trips the call
106
110
  * in both builds:
@@ -123,9 +127,16 @@ export function GET<A extends readonly any[], R>(
123
127
  * source name as the trailing argument (dev-only metadata seeded on the
124
128
  * metadata channel; never emitted in production). Not meant for
125
129
  * hand-written code.
130
+ *
131
+ * The optional `base` targets calls at that url verbatim instead of the
132
+ * configured endpoint — for integrations reconstructing a callable from a
133
+ * server-rendered action url (e.g. a router intercepting a form submit whose
134
+ * `action="/_server?id=...&args=..."` came off the wire): bound arguments
135
+ * stay in the query string, where the server reads them for natural-encoding
136
+ * bodies (FormData, urlencoded).
126
137
  * @internal
127
138
  */
128
- export function createServerReference(id: string, name?: string): ServerFunction;
139
+ export function createServerReference(id: string, name?: string, base?: string): ServerFunction;
129
140
 
130
141
  /**
131
142
  * Compiler ABI — only ever referenced by server-mode compiler output;
@@ -3,10 +3,13 @@ import { JSONCodecOptions } from "../serializer.cjs";
3
3
  import { RequestEvent } from "../server.cjs";
4
4
 
5
5
  export {
6
+ ERROR_HEADER,
6
7
  FUNCTION_HEADER,
7
8
  INSTANCE_HEADER,
8
9
  SINGLE_FLIGHT_HEADER,
10
+ decodeErrorHeaderValue,
9
11
  decodeResponse,
12
+ encodeErrorHeaderValue,
10
13
  getServerFunctionMetadata,
11
14
  isServerFunction,
12
15
  subscribeFlightData,
@@ -194,8 +197,9 @@ export function createServerReference<T extends any[], R>(
194
197
  * declaration on the reference's metadata channel
195
198
  * (`getServerFunctionMetadata(fn)?.method === "GET"`) and records the
196
199
  * declared method for the function's id so `handleServerFunctionRequest`
197
- * enforces it: GET-declared functions accept GET requests (and only GET),
198
- * everything else answers 405.
200
+ * honors it: GET-declared functions accept GET requests in addition to the
201
+ * default POST transport (declaring GET grants, it does not revoke);
202
+ * functions that never declared GET answer GET requests with 405.
199
203
  *
200
204
  * Wrap the reference at its declaration; the compiler round-trips the call
201
205
  * in both builds:
@@ -282,9 +286,9 @@ export interface HandleServerFunctionOptions {
282
286
 
283
287
  /**
284
288
  * Web-standard HTTP handler for server function calls: resolves the
285
- * function id from the request, enforces the declared method (405 when the
286
- * request method contradicts a `GET` declaration or uses GET without
287
- * one), decodes arguments, runs the function under a request-event scope,
289
+ * function id from the request, gates GET dispatch on the declaration (405
290
+ * for a GET request to a function that never declared `GET`; POST is always
291
+ * accepted), decodes arguments, runs the function under a request-event scope,
288
292
  * and encodes the result (forwarding redirect/revalidation metadata
289
293
  * through headers). Mount it on the endpoint the client transport targets
290
294
  * (default `/_server`); platform adapters (h3, express, ...) convert their
@@ -38,6 +38,35 @@ export const FUNCTION_HEADER: string;
38
38
  */
39
39
  export const INSTANCE_HEADER: string;
40
40
 
41
+ /**
42
+ * Response header marking a thrown server-function error
43
+ * (`"X-Server-Function-Error"`). The client transport rejects with the
44
+ * decoded body when it is present (unless redirect/revalidation metadata
45
+ * marks the response as control flow). The value carries the error's
46
+ * message — `"true"` for thrown control-flow responses and non-Error
47
+ * values — encoded with `encodeErrorHeaderValue`, so integrations reading
48
+ * it must pass it through `decodeErrorHeaderValue`.
49
+ */
50
+ export const ERROR_HEADER: string;
51
+
52
+ /**
53
+ * Encodes an error message for the `ERROR_HEADER` value. HTTP header values
54
+ * are latin1 ByteStrings — `Headers.set` throws on code points above U+00FF
55
+ * — so plain printable-latin1 messages ride verbatim (ASCII stays
56
+ * byte-identical on the wire) and everything else (CJK, emoji, controls)
57
+ * travels percent-encoded behind a marker. `decodeErrorHeaderValue`
58
+ * round-trips the message exactly, astral-plane characters included (lone
59
+ * surrogates are replaced with U+FFFD — they cannot survive UTF-8 anyway).
60
+ */
61
+ export function encodeErrorHeaderValue(value: string): string;
62
+
63
+ /**
64
+ * Decodes an `ERROR_HEADER` value produced by `encodeErrorHeaderValue`:
65
+ * marked values are percent-decoded, everything else (including values from
66
+ * peers that never encode) passes through untouched.
67
+ */
68
+ export function decodeErrorHeaderValue(value: string): string;
69
+
41
70
  /**
42
71
  * Header driving the single-flight protocol on both legs
43
72
  * (`"X-Single-Flight"`). On the request it opts the call into data
@@ -205,6 +205,14 @@ export function setAttribute(node: Element, name: string, value: string): void;
205
205
  /** @deprecated not supported on the server side */
206
206
  export function setAttributeNS(node: Element, namespace: string, name: string, value: string): void;
207
207
 
208
+ /**
209
+ * Server no-op: element claims are a client-only concern, but consumers may
210
+ * register isomorphically. Returns a no-op unregister function.
211
+ */
212
+ export function registerElementClaim(handler: (element: Element) => void): () => void;
213
+ /** Server no-op: returns `node` unchanged. Claims never fire during SSR. */
214
+ export function claimElement<T extends Element>(node: T): T;
215
+
208
216
  /** @deprecated not supported on the server side */
209
217
  export function addEvent(node: Element, name: string, handler: () => void, delegate: boolean): void;
210
218