@solidjs/web 2.0.0-beta.24 → 2.0.0-beta.26

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.
@@ -1183,7 +1183,12 @@ function createFrameSink(emit, frame) {
1183
1183
  version
1184
1184
  } = frame;
1185
1185
  const styledKeys = new Set();
1186
+ const regionKeys = new Map();
1187
+ const frameOf = key => regionKeys.get(key) || id;
1186
1188
  return {
1189
+ tagRegion(key, childId) {
1190
+ if (!regionKeys.has(key)) regionKeys.set(key, childId);
1191
+ },
1187
1192
  shell(html, meta = {}) {
1188
1193
  if (meta.preloads && meta.preloads.size) {
1189
1194
  const styles = [];
@@ -1231,13 +1236,14 @@ function createFrameSink(emit, frame) {
1231
1236
  }
1232
1237
  },
1233
1238
  fragment(key, value, meta = {}) {
1239
+ const fid = frameOf(key);
1234
1240
  const links = meta.styles && meta.styles.links || [];
1235
1241
  const inline = meta.styles && meta.styles.inline || [];
1236
1242
  if (links.length || inline.length) {
1237
1243
  if (links.length) styledKeys.add(key);
1238
1244
  const chunk = {
1239
1245
  type: "assets",
1240
- id,
1246
+ id: fid,
1241
1247
  version,
1242
1248
  key
1243
1249
  };
@@ -1253,7 +1259,7 @@ function createFrameSink(emit, frame) {
1253
1259
  }
1254
1260
  emit({
1255
1261
  type: "fragment",
1256
- id,
1262
+ id: fid,
1257
1263
  version,
1258
1264
  key,
1259
1265
  html: value
@@ -1261,7 +1267,7 @@ function createFrameSink(emit, frame) {
1261
1267
  if (meta.error) {
1262
1268
  emit({
1263
1269
  type: "error",
1264
- id,
1270
+ id: fid,
1265
1271
  version,
1266
1272
  key,
1267
1273
  error: {
@@ -1272,7 +1278,7 @@ function createFrameSink(emit, frame) {
1272
1278
  if (!meta.revealGroup) {
1273
1279
  emit({
1274
1280
  type: "reveal",
1275
- id,
1281
+ id: fid,
1276
1282
  version,
1277
1283
  keys: [key],
1278
1284
  waitForStyles: !!links.length
@@ -1280,17 +1286,26 @@ function createFrameSink(emit, frame) {
1280
1286
  }
1281
1287
  },
1282
1288
  reveal(keys, meta = {}) {
1283
- let waitForStyles = false;
1284
- for (const key of keys) if (styledKeys.has(key)) waitForStyles = true;
1285
- const chunk = {
1286
- type: "reveal",
1287
- id,
1288
- version,
1289
- keys,
1290
- waitForStyles
1291
- };
1292
- if (meta.fallback) chunk.fallback = true;
1293
- emit(chunk);
1289
+ const byFrame = new Map();
1290
+ for (const key of keys) {
1291
+ const fid = frameOf(key);
1292
+ let group = byFrame.get(fid);
1293
+ if (!group) byFrame.set(fid, group = []);
1294
+ group.push(key);
1295
+ }
1296
+ for (const [fid, groupKeys] of byFrame) {
1297
+ let waitForStyles = false;
1298
+ for (const key of groupKeys) if (styledKeys.has(key)) waitForStyles = true;
1299
+ const chunk = {
1300
+ type: "reveal",
1301
+ id: fid,
1302
+ version,
1303
+ keys: groupKeys,
1304
+ waitForStyles
1305
+ };
1306
+ if (meta.fallback) chunk.fallback = true;
1307
+ emit(chunk);
1308
+ }
1294
1309
  },
1295
1310
  asset(type, url) {
1296
1311
  if (type !== "module") return;
@@ -1404,6 +1419,22 @@ function slotRange(occurrence) {
1404
1419
  t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`
1405
1420
  };
1406
1421
  }
1422
+ const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
1423
+ function encodeOccurrenceKey(key) {
1424
+ return String(key).replace(OCCURRENCE_UNSAFE, c => {
1425
+ const code = c.codePointAt(0);
1426
+ return "%" + (code < 16 ? "0" : "") + code.toString(16);
1427
+ });
1428
+ }
1429
+ function occurrenceId(prop, raw, counts) {
1430
+ const k = raw.$key;
1431
+ if (typeof k === "string" || typeof k === "number") {
1432
+ return `${prop}#${encodeOccurrenceKey(k)}`;
1433
+ }
1434
+ const n = counts[prop] || 0;
1435
+ counts[prop] = n + 1;
1436
+ return `${prop}#${n}`;
1437
+ }
1407
1438
  function createDocumentSlotProps(clientProps, frameId) {
1408
1439
  const counts = Object.create(null);
1409
1440
  const getters = new Map();
@@ -1440,36 +1471,37 @@ function createDocumentSlotProps(clientProps, frameId) {
1440
1471
  });
1441
1472
  }
1442
1473
  const raw = callArgs[0];
1443
- let occurrence;
1444
- const k = raw.$key;
1445
- if (typeof k === "string" || typeof k === "number") {
1446
- occurrence = `${prop}#${k}`;
1447
- } else {
1448
- const n = counts[prop] || 0;
1449
- counts[prop] = n + 1;
1450
- occurrence = `${prop}#${n}`;
1451
- }
1474
+ const occurrence = occurrenceId(prop, raw, counts);
1452
1475
  const slot = clientProps[prop];
1453
1476
  if (typeof slot !== "function") return range(occurrence, undefined);
1454
1477
  const resolved = {};
1455
- const regions = [];
1478
+ const vals = {};
1456
1479
  for (const key of Object.keys(raw)) {
1457
- const value = raw[key];
1458
- if (key !== "$key" && isServerContent(value)) {
1480
+ if (key === "$key") continue;
1481
+ let value = raw[key];
1482
+ for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
1483
+ vals[key] = value;
1484
+ }
1485
+ const regions = [];
1486
+ for (const key of Object.keys(vals)) {
1487
+ const value = vals[key];
1488
+ if (isServerContent(value)) {
1459
1489
  const childId = `${frameId}.${occurrence}.${key}`;
1460
1490
  const region = {
1461
1491
  key,
1462
1492
  childId,
1463
1493
  value,
1464
- used: false
1494
+ used: false,
1495
+ locked: false
1465
1496
  };
1466
1497
  regions.push(region);
1467
1498
  resolved[key] = () => {
1499
+ if (region.locked) return [];
1468
1500
  region.used = true;
1469
1501
  return [{
1470
- t: `<!--frame:${childId}:start-->`
1502
+ t: frameElementOpen(childId)
1471
1503
  }, value, {
1472
- t: `<!--frame:${childId}:end-->`
1504
+ t: FRAME_ELEMENT_CLOSE
1473
1505
  }];
1474
1506
  };
1475
1507
  } else {
@@ -1479,12 +1511,10 @@ function createDocumentSlotProps(clientProps, frameId) {
1479
1511
  const out = scoped(occurrence, () => range(occurrence, slot(resolved)));
1480
1512
  const unused = regions.filter(r => !r.used);
1481
1513
  if (solidJs.sharedConfig.context) {
1482
- const rendered = renderedHtmlOf(out);
1483
1514
  const args = {};
1484
1515
  let any = false;
1485
- for (const key of Object.keys(raw)) {
1486
- const value = raw[key];
1487
- if (key === "$key") continue;
1516
+ for (const key of Object.keys(vals)) {
1517
+ const value = vals[key];
1488
1518
  const region = regions.find(r => r.key === key);
1489
1519
  if (region) {
1490
1520
  if (!region.used) {
@@ -1496,16 +1526,12 @@ function createDocumentSlotProps(clientProps, frameId) {
1496
1526
  continue;
1497
1527
  }
1498
1528
  if (isServerContent(value)) continue;
1499
- const t = typeof value;
1500
- if ((t === "string" || t === "number") && rendered !== null) {
1501
- const needle = t === "string" ? solidJs.sharedConfig.context.escape(String(value)) : String(value);
1502
- if (needle !== "" && rendered.includes(needle)) continue;
1503
- }
1504
1529
  args[key] = value;
1505
1530
  any = true;
1506
1531
  }
1507
1532
  if (any) solidJs.sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, args);
1508
1533
  for (const region of unused) {
1534
+ region.locked = true;
1509
1535
  solidJs.sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(solidJs.sharedConfig.context, region.value));
1510
1536
  }
1511
1537
  }
@@ -1517,28 +1543,26 @@ function createDocumentSlotProps(clientProps, frameId) {
1517
1543
  }
1518
1544
  });
1519
1545
  }
1546
+ const FRAME_TAG = "dx-frame";
1547
+ const FRAME_ID_ATTR = "data-fid";
1548
+ function frameElementOpen(id) {
1549
+ const escaped = solidJs.sharedConfig.context ? solidJs.sharedConfig.context.escape(String(id), true) : String(id);
1550
+ return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
1551
+ }
1552
+ const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
1520
1553
  function frameTransformDirectResult(value, {
1521
1554
  id
1522
1555
  }) {
1523
1556
  if (typeof value !== "function") return value;
1524
1557
  const component = value;
1525
1558
  const wrapped = props => [{
1526
- t: `<!--frame:${id}:start-->`
1559
+ t: frameElementOpen(id)
1527
1560
  }, serverOwned(() => component(createDocumentSlotProps(props, id))), {
1528
- t: `<!--frame:${id}:end-->`
1561
+ t: FRAME_ELEMENT_CLOSE
1529
1562
  }];
1530
1563
  wrapped[SERVER_COMPONENT] = id;
1531
1564
  return wrapped;
1532
1565
  }
1533
- function renderedHtmlOf(out) {
1534
- try {
1535
- const res = solidJs.sharedConfig.context.resolve(out);
1536
- if (res && res.t && (!res.h || !res.h.length)) {
1537
- return res.t[0].replace(/<!--[^>]*-->/g, "").replace(/ _hk=("[^"]*"|[^\s>]+)/g, "");
1538
- }
1539
- } catch (e) {}
1540
- return null;
1541
- }
1542
1566
  function resolveRegionHtml(ctx, node) {
1543
1567
  const res = ctx.resolve(node);
1544
1568
  if (!res || !res.t) return String(res ?? "");
@@ -1613,37 +1637,41 @@ function createSlotProps(sink, frame) {
1613
1637
  return slotRange(prop);
1614
1638
  }
1615
1639
  const raw = callArgs[0];
1616
- let occurrence;
1617
- const k = raw.$key;
1618
- if (typeof k === "string" || typeof k === "number") {
1619
- occurrence = `${prop}#${k}`;
1620
- } else {
1621
- const n = counts[prop] || 0;
1622
- counts[prop] = n + 1;
1623
- occurrence = `${prop}#${n}`;
1624
- }
1640
+ const occurrence = occurrenceId(prop, raw, counts);
1625
1641
  const args = {};
1626
1642
  for (const key of Object.keys(raw)) {
1627
- const value = raw[key];
1628
- const t = typeof value;
1629
- if (value == null || t === "string" || t === "number" || t === "boolean") {
1630
- args[key] = value;
1631
- } else if (isServerContent(value)) {
1632
- const resolved = solidJs.sharedConfig.context.resolve(value);
1633
- if (resolved.h.length) {
1634
- throw new Error("Async server content in slot args is not supported yet (arg '" + key + "' of " + occurrence + "). Move the async read above the slot or into a fragment.");
1643
+ if (key === "$key") continue;
1644
+ const childId = `${frame.id}.${occurrence}.${key}`;
1645
+ const ctx = solidJs.sharedConfig.context;
1646
+ const origRegister = ctx.registerFragment;
1647
+ ctx.registerFragment = (fragKey, fragOptions) => {
1648
+ sink.tagRegion(fragKey, childId);
1649
+ return origRegister.call(ctx, fragKey, fragOptions);
1650
+ };
1651
+ try {
1652
+ let value = raw[key];
1653
+ for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
1654
+ const t = typeof value;
1655
+ if (value == null || t === "string" || t === "number" || t === "boolean") {
1656
+ args[key] = value;
1657
+ } else if (isServerContent(value)) {
1658
+ const resolved = ctx.resolve(value);
1659
+ if (resolved.h.length) {
1660
+ throw new Error("Async server content in a slot arg needs a boundary (arg '" + key + "' of " + occurrence + "). Wrap the async read in a <Suspense>, or move it above the slot.");
1661
+ }
1662
+ sink.region(childId, resolved.t[0]);
1663
+ args[key] = {
1664
+ $frame: childId
1665
+ };
1666
+ } else {
1667
+ const ref = `arg:${occurrence}:${key}`;
1668
+ ctx.serialize(ref, value);
1669
+ args[key] = {
1670
+ $ref: ref
1671
+ };
1635
1672
  }
1636
- const childId = `${frame.id}.${occurrence}.${key}`;
1637
- sink.region(childId, resolved.t[0]);
1638
- args[key] = {
1639
- $frame: childId
1640
- };
1641
- } else {
1642
- const ref = `arg:${occurrence}:${key}`;
1643
- solidJs.sharedConfig.context.serialize(ref, value);
1644
- args[key] = {
1645
- $ref: ref
1646
- };
1673
+ } finally {
1674
+ ctx.registerFragment = origRegister;
1647
1675
  }
1648
1676
  }
1649
1677
  sink.slot(occurrence, args);
@@ -1181,7 +1181,12 @@ function createFrameSink(emit, frame) {
1181
1181
  version
1182
1182
  } = frame;
1183
1183
  const styledKeys = new Set();
1184
+ const regionKeys = new Map();
1185
+ const frameOf = key => regionKeys.get(key) || id;
1184
1186
  return {
1187
+ tagRegion(key, childId) {
1188
+ if (!regionKeys.has(key)) regionKeys.set(key, childId);
1189
+ },
1185
1190
  shell(html, meta = {}) {
1186
1191
  if (meta.preloads && meta.preloads.size) {
1187
1192
  const styles = [];
@@ -1229,13 +1234,14 @@ function createFrameSink(emit, frame) {
1229
1234
  }
1230
1235
  },
1231
1236
  fragment(key, value, meta = {}) {
1237
+ const fid = frameOf(key);
1232
1238
  const links = meta.styles && meta.styles.links || [];
1233
1239
  const inline = meta.styles && meta.styles.inline || [];
1234
1240
  if (links.length || inline.length) {
1235
1241
  if (links.length) styledKeys.add(key);
1236
1242
  const chunk = {
1237
1243
  type: "assets",
1238
- id,
1244
+ id: fid,
1239
1245
  version,
1240
1246
  key
1241
1247
  };
@@ -1251,7 +1257,7 @@ function createFrameSink(emit, frame) {
1251
1257
  }
1252
1258
  emit({
1253
1259
  type: "fragment",
1254
- id,
1260
+ id: fid,
1255
1261
  version,
1256
1262
  key,
1257
1263
  html: value
@@ -1259,7 +1265,7 @@ function createFrameSink(emit, frame) {
1259
1265
  if (meta.error) {
1260
1266
  emit({
1261
1267
  type: "error",
1262
- id,
1268
+ id: fid,
1263
1269
  version,
1264
1270
  key,
1265
1271
  error: {
@@ -1270,7 +1276,7 @@ function createFrameSink(emit, frame) {
1270
1276
  if (!meta.revealGroup) {
1271
1277
  emit({
1272
1278
  type: "reveal",
1273
- id,
1279
+ id: fid,
1274
1280
  version,
1275
1281
  keys: [key],
1276
1282
  waitForStyles: !!links.length
@@ -1278,17 +1284,26 @@ function createFrameSink(emit, frame) {
1278
1284
  }
1279
1285
  },
1280
1286
  reveal(keys, meta = {}) {
1281
- let waitForStyles = false;
1282
- for (const key of keys) if (styledKeys.has(key)) waitForStyles = true;
1283
- const chunk = {
1284
- type: "reveal",
1285
- id,
1286
- version,
1287
- keys,
1288
- waitForStyles
1289
- };
1290
- if (meta.fallback) chunk.fallback = true;
1291
- emit(chunk);
1287
+ const byFrame = new Map();
1288
+ for (const key of keys) {
1289
+ const fid = frameOf(key);
1290
+ let group = byFrame.get(fid);
1291
+ if (!group) byFrame.set(fid, group = []);
1292
+ group.push(key);
1293
+ }
1294
+ for (const [fid, groupKeys] of byFrame) {
1295
+ let waitForStyles = false;
1296
+ for (const key of groupKeys) if (styledKeys.has(key)) waitForStyles = true;
1297
+ const chunk = {
1298
+ type: "reveal",
1299
+ id: fid,
1300
+ version,
1301
+ keys: groupKeys,
1302
+ waitForStyles
1303
+ };
1304
+ if (meta.fallback) chunk.fallback = true;
1305
+ emit(chunk);
1306
+ }
1292
1307
  },
1293
1308
  asset(type, url) {
1294
1309
  if (type !== "module") return;
@@ -1402,6 +1417,22 @@ function slotRange(occurrence) {
1402
1417
  t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`
1403
1418
  };
1404
1419
  }
1420
+ const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
1421
+ function encodeOccurrenceKey(key) {
1422
+ return String(key).replace(OCCURRENCE_UNSAFE, c => {
1423
+ const code = c.codePointAt(0);
1424
+ return "%" + (code < 16 ? "0" : "") + code.toString(16);
1425
+ });
1426
+ }
1427
+ function occurrenceId(prop, raw, counts) {
1428
+ const k = raw.$key;
1429
+ if (typeof k === "string" || typeof k === "number") {
1430
+ return `${prop}#${encodeOccurrenceKey(k)}`;
1431
+ }
1432
+ const n = counts[prop] || 0;
1433
+ counts[prop] = n + 1;
1434
+ return `${prop}#${n}`;
1435
+ }
1405
1436
  function createDocumentSlotProps(clientProps, frameId) {
1406
1437
  const counts = Object.create(null);
1407
1438
  const getters = new Map();
@@ -1438,36 +1469,37 @@ function createDocumentSlotProps(clientProps, frameId) {
1438
1469
  });
1439
1470
  }
1440
1471
  const raw = callArgs[0];
1441
- let occurrence;
1442
- const k = raw.$key;
1443
- if (typeof k === "string" || typeof k === "number") {
1444
- occurrence = `${prop}#${k}`;
1445
- } else {
1446
- const n = counts[prop] || 0;
1447
- counts[prop] = n + 1;
1448
- occurrence = `${prop}#${n}`;
1449
- }
1472
+ const occurrence = occurrenceId(prop, raw, counts);
1450
1473
  const slot = clientProps[prop];
1451
1474
  if (typeof slot !== "function") return range(occurrence, undefined);
1452
1475
  const resolved = {};
1453
- const regions = [];
1476
+ const vals = {};
1454
1477
  for (const key of Object.keys(raw)) {
1455
- const value = raw[key];
1456
- if (key !== "$key" && isServerContent(value)) {
1478
+ if (key === "$key") continue;
1479
+ let value = raw[key];
1480
+ for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
1481
+ vals[key] = value;
1482
+ }
1483
+ const regions = [];
1484
+ for (const key of Object.keys(vals)) {
1485
+ const value = vals[key];
1486
+ if (isServerContent(value)) {
1457
1487
  const childId = `${frameId}.${occurrence}.${key}`;
1458
1488
  const region = {
1459
1489
  key,
1460
1490
  childId,
1461
1491
  value,
1462
- used: false
1492
+ used: false,
1493
+ locked: false
1463
1494
  };
1464
1495
  regions.push(region);
1465
1496
  resolved[key] = () => {
1497
+ if (region.locked) return [];
1466
1498
  region.used = true;
1467
1499
  return [{
1468
- t: `<!--frame:${childId}:start-->`
1500
+ t: frameElementOpen(childId)
1469
1501
  }, value, {
1470
- t: `<!--frame:${childId}:end-->`
1502
+ t: FRAME_ELEMENT_CLOSE
1471
1503
  }];
1472
1504
  };
1473
1505
  } else {
@@ -1477,12 +1509,10 @@ function createDocumentSlotProps(clientProps, frameId) {
1477
1509
  const out = scoped(occurrence, () => range(occurrence, slot(resolved)));
1478
1510
  const unused = regions.filter(r => !r.used);
1479
1511
  if (sharedConfig.context) {
1480
- const rendered = renderedHtmlOf(out);
1481
1512
  const args = {};
1482
1513
  let any = false;
1483
- for (const key of Object.keys(raw)) {
1484
- const value = raw[key];
1485
- if (key === "$key") continue;
1514
+ for (const key of Object.keys(vals)) {
1515
+ const value = vals[key];
1486
1516
  const region = regions.find(r => r.key === key);
1487
1517
  if (region) {
1488
1518
  if (!region.used) {
@@ -1494,16 +1524,12 @@ function createDocumentSlotProps(clientProps, frameId) {
1494
1524
  continue;
1495
1525
  }
1496
1526
  if (isServerContent(value)) continue;
1497
- const t = typeof value;
1498
- if ((t === "string" || t === "number") && rendered !== null) {
1499
- const needle = t === "string" ? sharedConfig.context.escape(String(value)) : String(value);
1500
- if (needle !== "" && rendered.includes(needle)) continue;
1501
- }
1502
1527
  args[key] = value;
1503
1528
  any = true;
1504
1529
  }
1505
1530
  if (any) sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, args);
1506
1531
  for (const region of unused) {
1532
+ region.locked = true;
1507
1533
  sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(sharedConfig.context, region.value));
1508
1534
  }
1509
1535
  }
@@ -1515,28 +1541,26 @@ function createDocumentSlotProps(clientProps, frameId) {
1515
1541
  }
1516
1542
  });
1517
1543
  }
1544
+ const FRAME_TAG = "dx-frame";
1545
+ const FRAME_ID_ATTR = "data-fid";
1546
+ function frameElementOpen(id) {
1547
+ const escaped = sharedConfig.context ? sharedConfig.context.escape(String(id), true) : String(id);
1548
+ return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
1549
+ }
1550
+ const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
1518
1551
  function frameTransformDirectResult(value, {
1519
1552
  id
1520
1553
  }) {
1521
1554
  if (typeof value !== "function") return value;
1522
1555
  const component = value;
1523
1556
  const wrapped = props => [{
1524
- t: `<!--frame:${id}:start-->`
1557
+ t: frameElementOpen(id)
1525
1558
  }, serverOwned(() => component(createDocumentSlotProps(props, id))), {
1526
- t: `<!--frame:${id}:end-->`
1559
+ t: FRAME_ELEMENT_CLOSE
1527
1560
  }];
1528
1561
  wrapped[SERVER_COMPONENT] = id;
1529
1562
  return wrapped;
1530
1563
  }
1531
- function renderedHtmlOf(out) {
1532
- try {
1533
- const res = sharedConfig.context.resolve(out);
1534
- if (res && res.t && (!res.h || !res.h.length)) {
1535
- return res.t[0].replace(/<!--[^>]*-->/g, "").replace(/ _hk=("[^"]*"|[^\s>]+)/g, "");
1536
- }
1537
- } catch (e) {}
1538
- return null;
1539
- }
1540
1564
  function resolveRegionHtml(ctx, node) {
1541
1565
  const res = ctx.resolve(node);
1542
1566
  if (!res || !res.t) return String(res ?? "");
@@ -1611,37 +1635,41 @@ function createSlotProps(sink, frame) {
1611
1635
  return slotRange(prop);
1612
1636
  }
1613
1637
  const raw = callArgs[0];
1614
- let occurrence;
1615
- const k = raw.$key;
1616
- if (typeof k === "string" || typeof k === "number") {
1617
- occurrence = `${prop}#${k}`;
1618
- } else {
1619
- const n = counts[prop] || 0;
1620
- counts[prop] = n + 1;
1621
- occurrence = `${prop}#${n}`;
1622
- }
1638
+ const occurrence = occurrenceId(prop, raw, counts);
1623
1639
  const args = {};
1624
1640
  for (const key of Object.keys(raw)) {
1625
- const value = raw[key];
1626
- const t = typeof value;
1627
- if (value == null || t === "string" || t === "number" || t === "boolean") {
1628
- args[key] = value;
1629
- } else if (isServerContent(value)) {
1630
- const resolved = sharedConfig.context.resolve(value);
1631
- if (resolved.h.length) {
1632
- throw new Error("Async server content in slot args is not supported yet (arg '" + key + "' of " + occurrence + "). Move the async read above the slot or into a fragment.");
1641
+ if (key === "$key") continue;
1642
+ const childId = `${frame.id}.${occurrence}.${key}`;
1643
+ const ctx = sharedConfig.context;
1644
+ const origRegister = ctx.registerFragment;
1645
+ ctx.registerFragment = (fragKey, fragOptions) => {
1646
+ sink.tagRegion(fragKey, childId);
1647
+ return origRegister.call(ctx, fragKey, fragOptions);
1648
+ };
1649
+ try {
1650
+ let value = raw[key];
1651
+ for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
1652
+ const t = typeof value;
1653
+ if (value == null || t === "string" || t === "number" || t === "boolean") {
1654
+ args[key] = value;
1655
+ } else if (isServerContent(value)) {
1656
+ const resolved = ctx.resolve(value);
1657
+ if (resolved.h.length) {
1658
+ throw new Error("Async server content in a slot arg needs a boundary (arg '" + key + "' of " + occurrence + "). Wrap the async read in a <Suspense>, or move it above the slot.");
1659
+ }
1660
+ sink.region(childId, resolved.t[0]);
1661
+ args[key] = {
1662
+ $frame: childId
1663
+ };
1664
+ } else {
1665
+ const ref = `arg:${occurrence}:${key}`;
1666
+ ctx.serialize(ref, value);
1667
+ args[key] = {
1668
+ $ref: ref
1669
+ };
1633
1670
  }
1634
- const childId = `${frame.id}.${occurrence}.${key}`;
1635
- sink.region(childId, resolved.t[0]);
1636
- args[key] = {
1637
- $frame: childId
1638
- };
1639
- } else {
1640
- const ref = `arg:${occurrence}:${key}`;
1641
- sharedConfig.context.serialize(ref, value);
1642
- args[key] = {
1643
- $ref: ref
1644
- };
1671
+ } finally {
1672
+ ctx.registerFragment = origRegister;
1645
1673
  }
1646
1674
  }
1647
1675
  sink.slot(occurrence, args);