@barefootjs/client 0.33.2 → 0.33.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/csr-adapter.js +17 -14
- package/dist/runtime/component.d.ts +27 -2
- package/dist/runtime/component.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +32 -24
- package/dist/runtime/map-array-lazy.d.ts +6 -1
- package/dist/runtime/map-array-lazy.d.ts.map +1 -1
- package/dist/runtime/map-array.d.ts +11 -1
- package/dist/runtime/map-array.d.ts.map +1 -1
- package/dist/runtime/standalone.js +32 -24
- package/package.json +2 -2
- package/src/runtime/component.ts +65 -11
- package/src/runtime/index.ts +1 -0
- package/src/runtime/map-array-lazy.ts +15 -4
- package/src/runtime/map-array.ts +50 -8
package/dist/csr-adapter.js
CHANGED
|
@@ -168754,7 +168754,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
168754
168754
|
});
|
|
168755
168755
|
|
|
168756
168756
|
// ../jsx/src/compiler.ts
|
|
168757
|
-
var
|
|
168757
|
+
var import_typescript25 = __toESM(require_typescript(), 1);
|
|
168758
168758
|
|
|
168759
168759
|
// ../jsx/src/analyzer.ts
|
|
168760
168760
|
var import_typescript9 = __toESM(require_typescript(), 1);
|
|
@@ -169998,11 +169998,14 @@ var KEYWORDS_AND_GLOBALS = new Set([
|
|
|
169998
169998
|
// ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
|
|
169999
169999
|
var import_typescript14 = __toESM(require_typescript(), 1);
|
|
170000
170000
|
|
|
170001
|
+
// ../jsx/src/ir-to-client-js/imports.ts
|
|
170002
|
+
var import_typescript16 = __toESM(require_typescript(), 1);
|
|
170003
|
+
|
|
170001
170004
|
// ../jsx/src/value-references.ts
|
|
170002
170005
|
var import_typescript15 = __toESM(require_typescript(), 1);
|
|
170003
170006
|
|
|
170004
170007
|
// ../jsx/src/relocate.ts
|
|
170005
|
-
var
|
|
170008
|
+
var import_typescript17 = __toESM(require_typescript(), 1);
|
|
170006
170009
|
|
|
170007
170010
|
// ../jsx/src/lowering-registry.ts
|
|
170008
170011
|
var plugins = [];
|
|
@@ -170181,10 +170184,10 @@ function formatDateLocalNames(metadata) {
|
|
|
170181
170184
|
}
|
|
170182
170185
|
|
|
170183
170186
|
// ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
|
|
170184
|
-
var
|
|
170187
|
+
var import_typescript18 = __toESM(require_typescript(), 1);
|
|
170185
170188
|
|
|
170186
170189
|
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
170187
|
-
var
|
|
170190
|
+
var import_typescript19 = __toESM(require_typescript(), 1);
|
|
170188
170191
|
var NO_PREAMBLE = {
|
|
170189
170192
|
lazySafe: true,
|
|
170190
170193
|
facts: { declaredNames: new Set, freeNames: new Set }
|
|
@@ -170234,7 +170237,7 @@ var INERT_BINDING_GLOBALS = new Set([
|
|
|
170234
170237
|
]);
|
|
170235
170238
|
|
|
170236
170239
|
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
170237
|
-
var
|
|
170240
|
+
var import_typescript20 = __toESM(require_typescript(), 1);
|
|
170238
170241
|
|
|
170239
170242
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
|
|
170240
170243
|
var NON_BUBBLING_EVENTS = new Set([
|
|
@@ -170249,7 +170252,7 @@ var NON_BUBBLING_EVENTS = new Set([
|
|
|
170249
170252
|
]);
|
|
170250
170253
|
|
|
170251
170254
|
// ../jsx/src/ir-to-client-js/rewrite-props-object.ts
|
|
170252
|
-
var
|
|
170255
|
+
var import_typescript21 = __toESM(require_typescript(), 1);
|
|
170253
170256
|
|
|
170254
170257
|
// ../jsx/src/ir-to-client-js/source-map.ts
|
|
170255
170258
|
var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
@@ -170340,20 +170343,20 @@ class SourceMapGenerator {
|
|
|
170340
170343
|
}
|
|
170341
170344
|
|
|
170342
170345
|
// ../jsx/src/preprocess-inline-jsx-callbacks.ts
|
|
170343
|
-
var
|
|
170346
|
+
var import_typescript22 = __toESM(require_typescript(), 1);
|
|
170344
170347
|
|
|
170345
170348
|
// ../jsx/src/ssr-defaults.ts
|
|
170346
|
-
var
|
|
170349
|
+
var import_typescript23 = __toESM(require_typescript(), 1);
|
|
170347
170350
|
var UNRESOLVED = Symbol("unresolved");
|
|
170348
170351
|
var NO_RETURN = Symbol("no-return");
|
|
170349
170352
|
|
|
170350
170353
|
// ../jsx/src/augment-inherited-props.ts
|
|
170351
|
-
var
|
|
170354
|
+
var import_typescript24 = __toESM(require_typescript(), 1);
|
|
170352
170355
|
|
|
170353
170356
|
// ../jsx/src/rich-type-refusal.ts
|
|
170354
170357
|
var EMPTY_BINDINGS2 = new Map;
|
|
170355
170358
|
// ../jsx/src/shared-program.ts
|
|
170356
|
-
var
|
|
170359
|
+
var import_typescript26 = __toESM(require_typescript(), 1);
|
|
170357
170360
|
// ../jsx/src/adapters/interface.ts
|
|
170358
170361
|
class BaseAdapter {
|
|
170359
170362
|
renderChildren(children) {
|
|
@@ -170635,7 +170638,7 @@ class JsxAdapter extends BaseAdapter {
|
|
|
170635
170638
|
}
|
|
170636
170639
|
|
|
170637
170640
|
// ../jsx/src/adapters/template-imports.ts
|
|
170638
|
-
var
|
|
170641
|
+
var import_typescript27 = __toESM(require_typescript(), 1);
|
|
170639
170642
|
var CLIENT_PACKAGE_SOURCES = new Set([
|
|
170640
170643
|
"@barefootjs/client",
|
|
170641
170644
|
"@barefootjs/client/runtime"
|
|
@@ -171028,11 +171031,11 @@ function registerBuiltinLoweringPlugins() {
|
|
|
171028
171031
|
registerLoweringPlugin(plugin);
|
|
171029
171032
|
}
|
|
171030
171033
|
// ../jsx/src/combine-client-js.ts
|
|
171031
|
-
var import_typescript27 = __toESM(require_typescript(), 1);
|
|
171032
|
-
// ../jsx/src/debug.ts
|
|
171033
171034
|
var import_typescript28 = __toESM(require_typescript(), 1);
|
|
171034
|
-
// ../jsx/src/
|
|
171035
|
+
// ../jsx/src/debug.ts
|
|
171035
171036
|
var import_typescript29 = __toESM(require_typescript(), 1);
|
|
171037
|
+
// ../jsx/src/profiler.ts
|
|
171038
|
+
var import_typescript30 = __toESM(require_typescript(), 1);
|
|
171036
171039
|
|
|
171037
171040
|
// ../jsx/src/index.ts
|
|
171038
171041
|
registerBuiltinLoweringPlugins();
|
|
@@ -105,8 +105,8 @@ export interface CreateComponentSlotInfo {
|
|
|
105
105
|
* `upsertChildItem` (qsa-item.ts) assert nothing — the narrowing is the
|
|
106
106
|
* signature's job, not theirs.
|
|
107
107
|
*/
|
|
108
|
-
export declare function createComponent(nameOrDef: string | ComponentDef, props: Record<string, unknown>, key: string | number | undefined, slot: CreateComponentSlotInfo | undefined, mountAt: Element): HTMLElement;
|
|
109
|
-
export declare function createComponent(nameOrDef: string | ComponentDef, props?: Record<string, unknown>, key?: string | number, slot?: CreateComponentSlotInfo, mountAt?: Element | null): HTMLElement | DocumentFragment;
|
|
108
|
+
export declare function createComponent(nameOrDef: string | ComponentDef, props: Record<string, unknown>, key: string | number | undefined, slot: CreateComponentSlotInfo | undefined, mountAt: Element, keyAttrName?: string): HTMLElement;
|
|
109
|
+
export declare function createComponent(nameOrDef: string | ComponentDef, props?: Record<string, unknown>, key?: string | number, slot?: CreateComponentSlotInfo, mountAt?: Element | null, keyAttrName?: string): HTMLElement | DocumentFragment;
|
|
110
110
|
/**
|
|
111
111
|
* Render a child component's template to an HTML string.
|
|
112
112
|
* Used by compiler-generated template functions when a stateless component
|
|
@@ -221,6 +221,31 @@ export declare function isBfMarkup(value: unknown): value is BfMarkup;
|
|
|
221
221
|
* is actually branded.
|
|
222
222
|
*/
|
|
223
223
|
export declare function escapeTextOrMarkup(value: unknown): string;
|
|
224
|
+
/**
|
|
225
|
+
* Nullish guard for a bare `${children}` passthrough splice
|
|
226
|
+
* (`ir-to-client-js/html-template.ts`'s no-`slotId` `'expression'` branches
|
|
227
|
+
* — the "bare `${...}` interpolations" the docstring above `escapeTextSlotExpr`
|
|
228
|
+
* describes) — #2775. The value here is ALREADY-STRINGIFIED MARKUP, not an
|
|
229
|
+
* arbitrary prop: `materializeComponent` (this file, "Template functions
|
|
230
|
+
* expect children as an HTML string, not an array") joins a component's
|
|
231
|
+
* `children` into an HTML string before the template lambda ever runs, so by
|
|
232
|
+
* the time this function sees the value it is either that HTML string or,
|
|
233
|
+
* when the caller passed none, simply `undefined` (the key is absent from
|
|
234
|
+
* the props object entirely). This function's ENTIRE job is that one
|
|
235
|
+
* nullish case: turn the absent/`null` value into `''`, same as SSR's
|
|
236
|
+
* `{props.children}` and the DSL adapters' `bf.string(children)` render it.
|
|
237
|
+
*
|
|
238
|
+
* Deliberately NOT `escapeTextOrMarkup`: that function falls back to
|
|
239
|
+
* `escapeText` for anything not `bfMarkup()`-branded, and a `children`
|
|
240
|
+
* string is never branded (it is a plain string built by
|
|
241
|
+
* `materializeComponent`, not compiler-escaped piece-by-piece the way a
|
|
242
|
+
* `bfMarkup()` value is) — routing `children` through it would HTML-escape
|
|
243
|
+
* real markup into visible `<span>`-style text on every call that
|
|
244
|
+
* actually has children, trading the no-children bug for a strictly worse
|
|
245
|
+
* with-children one. So: nullish becomes `''`; every other value is
|
|
246
|
+
* returned completely unescaped, exactly as it arrived.
|
|
247
|
+
*/
|
|
248
|
+
export declare function markupOrEmpty(value: unknown): string;
|
|
224
249
|
/**
|
|
225
250
|
* `escapeText`'s counterpart for a claimed 'markup' slot's REACTIVE write
|
|
226
251
|
* (slot unification A3 follow-up), where the value is a plain-JS expression
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAS9C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAExD;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,IAAI,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAA;AAsB9F,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI,CAI9E;AAQD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAQjD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH;;;GAGG;AACH;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,uBAAuB,GAAG,SAAS,EACzC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { mapArrayLazy, type LazyRowEntry, type LazyRowPlan } from './map-array-l
|
|
|
15
15
|
export { patchLeaf } from './patch-leaf.ts';
|
|
16
16
|
export { claimSlots, lazySlots, lazyClaimSlots, textOrNode, type SlotSpec, type ClaimPlan, type ClaimedSlots, type ClaimedSlotsRW, type SlotWriter } from './claim-slots.ts';
|
|
17
17
|
export { registerTemplate, getTemplate, hasTemplate, type TemplateFn } from './template.ts';
|
|
18
|
-
export { createComponent, mountRowRoot, renderChild, parseHTML, escapeAttr, escapeText, escapeTextOrNode, bfMarkup, isBfMarkup, escapeTextOrMarkup, type BfMarkup, } from './component.ts';
|
|
18
|
+
export { createComponent, mountRowRoot, renderChild, parseHTML, escapeAttr, escapeText, escapeTextOrNode, bfMarkup, isBfMarkup, escapeTextOrMarkup, markupOrEmpty, type BfMarkup, } from './component.ts';
|
|
19
19
|
export { applyRestAttrs } from './apply-rest-attrs.ts';
|
|
20
20
|
export { spreadAttrs } from './spread-attrs.ts';
|
|
21
21
|
export { styleToCss } from './style.ts';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime/index.js
CHANGED
|
@@ -1368,25 +1368,25 @@ function mountRowRoot(el) {
|
|
|
1368
1368
|
}
|
|
1369
1369
|
return el;
|
|
1370
1370
|
}
|
|
1371
|
-
function createComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1372
|
-
const element = materializeComponent(nameOrDef, props, key, slot, mountAt);
|
|
1371
|
+
function createComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1372
|
+
const element = materializeComponent(nameOrDef, props, key, slot, mountAt, keyAttrName2);
|
|
1373
1373
|
if (mountAt && mountAt.parentNode && element !== mountAt) {
|
|
1374
1374
|
mountAt.replaceWith(element);
|
|
1375
1375
|
}
|
|
1376
1376
|
return element;
|
|
1377
1377
|
}
|
|
1378
|
-
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1378
|
+
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1379
1379
|
if (props == null)
|
|
1380
1380
|
props = {};
|
|
1381
1381
|
const rowMount = mountAt ? null : takeRowMountPoint();
|
|
1382
1382
|
if (typeof nameOrDef !== "string") {
|
|
1383
|
-
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount);
|
|
1383
|
+
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount, keyAttrName2);
|
|
1384
1384
|
}
|
|
1385
1385
|
const name = nameOrDef;
|
|
1386
1386
|
const templateFn = getTemplate(name);
|
|
1387
1387
|
if (!templateFn) {
|
|
1388
1388
|
console.warn(`[BarefootJS] Template not found for component: ${name}`);
|
|
1389
|
-
return createPlaceholder(name, key);
|
|
1389
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1390
1390
|
}
|
|
1391
1391
|
const childrenDescriptor = Object.getOwnPropertyDescriptor(props, "children");
|
|
1392
1392
|
const childrenIsGetter = childrenDescriptor != null && typeof childrenDescriptor.get === "function";
|
|
@@ -1419,6 +1419,8 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1419
1419
|
_parentScopeId = scopeId;
|
|
1420
1420
|
} else if (slot?.parent) {
|
|
1421
1421
|
_parentScopeId = slot.parent;
|
|
1422
|
+
} else if (!_parentScopeId) {
|
|
1423
|
+
_parentScopeId = `${def?.name ?? name}_${generateId()}`;
|
|
1422
1424
|
}
|
|
1423
1425
|
let html;
|
|
1424
1426
|
try {
|
|
@@ -1431,11 +1433,11 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1431
1433
|
const element = isFragmentRoot ? roots.find((node) => node.nodeType === Node.ELEMENT_NODE) : roots[0];
|
|
1432
1434
|
if (isFragmentRoot && roots.length > 0 && !element) {
|
|
1433
1435
|
console.warn(`[BarefootJS] Fragment-root component ${name} rendered no element root; ` + "a scope needs at least one element to attach to. Wrap the content in an element.");
|
|
1434
|
-
return createPlaceholder(name, key);
|
|
1436
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1435
1437
|
}
|
|
1436
1438
|
if (!element) {
|
|
1437
1439
|
console.warn(`[BarefootJS] Template returned empty HTML for component: ${name}`);
|
|
1438
|
-
return createPlaceholder(name, key);
|
|
1440
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1439
1441
|
}
|
|
1440
1442
|
if (scopeId && !isFragmentRoot) {
|
|
1441
1443
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
@@ -1446,7 +1448,7 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1446
1448
|
element.setAttribute(BF_AT, slot.mount);
|
|
1447
1449
|
}
|
|
1448
1450
|
if (key !== undefined) {
|
|
1449
|
-
element.setAttribute(
|
|
1451
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
1450
1452
|
}
|
|
1451
1453
|
const fragmentComments = isFragmentRoot && scopeId ? {
|
|
1452
1454
|
start: document.createComment(`${BF_SCOPE_COMMENT_PREFIX}${scopeId}`),
|
|
@@ -1562,11 +1564,11 @@ var ROOT_HAS_BFS_PATTERN = /^<\w+[^>]*\sbf-s="/;
|
|
|
1562
1564
|
function generateId() {
|
|
1563
1565
|
return Math.random().toString(36).slice(2, 8);
|
|
1564
1566
|
}
|
|
1565
|
-
function createPlaceholder(name, key) {
|
|
1567
|
+
function createPlaceholder(name, key, keyAttrName2 = BF_KEY) {
|
|
1566
1568
|
const el = document.createElement("div");
|
|
1567
1569
|
el.setAttribute(BF_SCOPE, `${name}_placeholder`);
|
|
1568
1570
|
if (key !== undefined) {
|
|
1569
|
-
el.setAttribute(
|
|
1571
|
+
el.setAttribute(keyAttrName2, String(key));
|
|
1570
1572
|
}
|
|
1571
1573
|
el.textContent = `[${name}]`;
|
|
1572
1574
|
el.style.cssText = "color: red; border: 1px dashed red; padding: 4px;";
|
|
@@ -1615,6 +1617,9 @@ function escapeTextOrMarkup(value) {
|
|
|
1615
1617
|
return value[BF_MARKUP_BRAND];
|
|
1616
1618
|
return escapeText(value);
|
|
1617
1619
|
}
|
|
1620
|
+
function markupOrEmpty(value) {
|
|
1621
|
+
return value == null ? "" : value;
|
|
1622
|
+
}
|
|
1618
1623
|
function escapeTextOrNode(value) {
|
|
1619
1624
|
if (isBfMarkup(value))
|
|
1620
1625
|
return value[BF_MARKUP_BRAND];
|
|
@@ -1676,7 +1681,7 @@ function insertGetterChildren(element, children) {
|
|
|
1676
1681
|
element.appendChild(document.createTextNode(String(children)));
|
|
1677
1682
|
}
|
|
1678
1683
|
}
|
|
1679
|
-
function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
1684
|
+
function createComponentFromDef(def, props, key, mountAt, rowMount, keyAttrName2 = BF_KEY) {
|
|
1680
1685
|
if (!def.template) {
|
|
1681
1686
|
throw new Error("[BarefootJS] createComponent with ComponentDef requires a template function");
|
|
1682
1687
|
}
|
|
@@ -1693,7 +1698,7 @@ function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
|
1693
1698
|
const scopeId = `${name}_${generateId()}`;
|
|
1694
1699
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
1695
1700
|
if (key !== undefined) {
|
|
1696
|
-
element.setAttribute(
|
|
1701
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
1697
1702
|
}
|
|
1698
1703
|
if (mountAt) {
|
|
1699
1704
|
mountAt.replaceWith(element);
|
|
@@ -2075,7 +2080,7 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2075
2080
|
}
|
|
2076
2081
|
return { startMarker, primaryEl, extras, scopeComments, dispose, setItem };
|
|
2077
2082
|
}
|
|
2078
|
-
function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
2083
|
+
function mapArray(accessor, container, getKey, renderItem, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2079
2084
|
if (!container)
|
|
2080
2085
|
return;
|
|
2081
2086
|
const scopes = new Map;
|
|
@@ -2100,13 +2105,15 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2100
2105
|
if (!hydrated) {
|
|
2101
2106
|
hydrated = true;
|
|
2102
2107
|
const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2103
|
-
const needsHydration = existingRanges.length > 0
|
|
2108
|
+
const needsHydration = existingRanges.length > 0;
|
|
2104
2109
|
if (needsHydration) {
|
|
2105
2110
|
for (let i2 = 0;i2 < existingRanges.length && i2 < items.length; i2++) {
|
|
2106
2111
|
const range = existingRanges[i2];
|
|
2107
2112
|
const item = items[i2];
|
|
2108
2113
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2109
|
-
range.primaryEl.
|
|
2114
|
+
if (getKey && !range.primaryEl.getAttribute(keyAttrName2)) {
|
|
2115
|
+
range.primaryEl.setAttribute(keyAttrName2, key);
|
|
2116
|
+
}
|
|
2110
2117
|
const scope = createItemScope(item, i2, renderItem, range.primaryEl, range.extras, range.startMarker, range.scopeComments);
|
|
2111
2118
|
scopes.set(key, scope);
|
|
2112
2119
|
hydratedScopes.add(range.primaryEl);
|
|
@@ -2115,8 +2122,8 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2115
2122
|
const item = items[i2];
|
|
2116
2123
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2117
2124
|
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2118
|
-
if (!scope.primaryEl.
|
|
2119
|
-
scope.primaryEl.setAttribute(
|
|
2125
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2126
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2120
2127
|
scopes.set(key, scope);
|
|
2121
2128
|
insertScope(scope, container, anchor);
|
|
2122
2129
|
}
|
|
@@ -2141,7 +2148,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2141
2148
|
if (scopes.size === 0) {
|
|
2142
2149
|
const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2143
2150
|
for (const range of loopRanges) {
|
|
2144
|
-
const existingKey = range.primaryEl.
|
|
2151
|
+
const existingKey = range.primaryEl.getAttribute(keyAttrName2);
|
|
2145
2152
|
if (existingKey && !scopes.has(existingKey)) {
|
|
2146
2153
|
scopes.set(existingKey, {
|
|
2147
2154
|
startMarker: range.startMarker,
|
|
@@ -2199,8 +2206,8 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2199
2206
|
desiredOrder.push(existing);
|
|
2200
2207
|
} else {
|
|
2201
2208
|
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2202
|
-
if (!scope.primaryEl.
|
|
2203
|
-
scope.primaryEl.setAttribute(
|
|
2209
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2210
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2204
2211
|
scopes.set(key, scope);
|
|
2205
2212
|
desiredOrder.push(scope);
|
|
2206
2213
|
}
|
|
@@ -2396,7 +2403,7 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
|
|
|
2396
2403
|
}
|
|
2397
2404
|
// src/runtime/map-array-lazy.ts
|
|
2398
2405
|
import { createEffect as createEffect2, createSignal as createSignal2, untrack as untrack2 } from "@barefootjs/client/reactive";
|
|
2399
|
-
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
2406
|
+
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2400
2407
|
if (!container)
|
|
2401
2408
|
return;
|
|
2402
2409
|
const entries = new Map;
|
|
@@ -2435,8 +2442,8 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2435
2442
|
last: null
|
|
2436
2443
|
};
|
|
2437
2444
|
entry.primaryEl = untrack2(() => plan.createRow(entry, index));
|
|
2438
|
-
if (!entry.primaryEl.
|
|
2439
|
-
entry.primaryEl.setAttribute(
|
|
2445
|
+
if (getKey && !entry.primaryEl.getAttribute(keyAttrName2))
|
|
2446
|
+
entry.primaryEl.setAttribute(keyAttrName2, key);
|
|
2440
2447
|
markStranded();
|
|
2441
2448
|
return entry;
|
|
2442
2449
|
};
|
|
@@ -2458,7 +2465,7 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2458
2465
|
const shared = Math.min(doms.length, items.length);
|
|
2459
2466
|
for (let i2 = 0;i2 < shared; i2++) {
|
|
2460
2467
|
const el = doms[i2];
|
|
2461
|
-
const ssrKey = el.getAttribute(
|
|
2468
|
+
const ssrKey = el.getAttribute(keyAttrName2);
|
|
2462
2469
|
const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i2], i2) : String(i2);
|
|
2463
2470
|
const entry = { key, primaryEl: el, item: items[i2], refs: null, last: null };
|
|
2464
2471
|
entries.set(key, entry);
|
|
@@ -3405,6 +3412,7 @@ export {
|
|
|
3405
3412
|
onMount,
|
|
3406
3413
|
onCleanup,
|
|
3407
3414
|
mountRowRoot,
|
|
3415
|
+
markupOrEmpty,
|
|
3408
3416
|
mapArrayLazy,
|
|
3409
3417
|
mapArrayAnchored,
|
|
3410
3418
|
mapArray,
|
|
@@ -159,6 +159,11 @@ export interface LazyRowPlan<T> {
|
|
|
159
159
|
* @param plan - Compiler-emitted row plan (see {@link LazyRowPlan})
|
|
160
160
|
* @param markerId - Scoped loop marker id (`<!--bf-loop:<id>-->`), see #1087
|
|
161
161
|
* @param bfId - Profiler attribution id for the reconciler effect
|
|
162
|
+
* @param keyAttrName - The row-key attribute NAME this loop resolved at
|
|
163
|
+
* compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
|
|
164
|
+
* jsx-to-ir.ts). Defaults to `BF_KEY` (plain `'data-key'`),
|
|
165
|
+
* correct at the outermost loop; only a nested loop's
|
|
166
|
+
* compiled call passes a depth-suffixed name (#2753).
|
|
162
167
|
*/
|
|
163
|
-
export declare function mapArrayLazy<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, plan: LazyRowPlan<T>, markerId?: string, bfId?: string): void;
|
|
168
|
+
export declare function mapArrayLazy<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, plan: LazyRowPlan<T>, markerId?: string, bfId?: string, keyAttrName?: string): void;
|
|
164
169
|
//# sourceMappingURL=map-array-lazy.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-array-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkHG;AAMH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,WAAW,CAAA;IACtB,IAAI,EAAE,CAAC,CAAA;IACP,iFAAiF;IACjF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,qDAAqD;IACrD,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;gFAC4E;IAC5E,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAA;IAC7D;;;4EAGwE;IACxE,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;IACpD;;;;;;;qEAOiE;IACjE,UAAU,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CAC1E;AAED
|
|
1
|
+
{"version":3,"file":"map-array-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkHG;AAMH;;;GAGG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,WAAW,CAAA;IACtB,IAAI,EAAE,CAAC,CAAA;IACP,iFAAiF;IACjF,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,qDAAqD;IACrD,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B;gFAC4E;IAC5E,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAA;IAC7D;;;4EAGwE;IACxE,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAA;IACpD;;;;;;;qEAOiE;IACjE,UAAU,CAAC,CAAC,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;CAC1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,WAAW,GAAE,MAAe,GAC3B,IAAI,CA0SN"}
|
|
@@ -62,8 +62,18 @@ export declare function longestIncreasingSubsequenceIndices(arr: number[]): numb
|
|
|
62
62
|
* Receives item as signal accessor: item() returns current value.
|
|
63
63
|
* When `existing` is passed, initializes the SSR-rendered element and returns it.
|
|
64
64
|
* When `existing` is undefined, creates a new element and returns it.
|
|
65
|
+
* @param keyAttrName - The row-key attribute NAME this loop resolved at
|
|
66
|
+
* compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
|
|
67
|
+
* jsx-to-ir.ts) — `'data-key'` at the outermost loop,
|
|
68
|
+
* `'data-key-N'` N levels deep. Defaults to `BF_KEY`
|
|
69
|
+
* (plain `'data-key'`), correct for every depth-0 call
|
|
70
|
+
* site; only a nested loop's compiled call passes a
|
|
71
|
+
* depth-suffixed name (#2753 Shape B — see the "Why not
|
|
72
|
+
* stamp unconditionally" note below for why this
|
|
73
|
+
* replaced a hardcoded constant instead of just fixing
|
|
74
|
+
* the value).
|
|
65
75
|
*/
|
|
66
|
-
export declare function mapArray<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, renderItem: (item: () => T, index: number, existing?: HTMLElement) => HTMLElement, markerId?: string, bfId?: string): void;
|
|
76
|
+
export declare function mapArray<T>(accessor: () => T[], container: HTMLElement | null, getKey: ((item: T, index: number) => string) | null, renderItem: (item: () => T, index: number, existing?: HTMLElement) => HTMLElement, markerId?: string, bfId?: string, keyAttrName?: string): void;
|
|
67
77
|
/**
|
|
68
78
|
* Per-item scoped list rendering for whole-item conditionals (#1665).
|
|
69
79
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-array.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CA+BhD;AAyHD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA2B3E;AA4GD
|
|
1
|
+
{"version":3,"file":"map-array.d.ts","sourceRoot":"","sources":["../../src/runtime/map-array.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,WAAW,EACtB,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CA+BhD;AAyHD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mCAAmC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CA2B3E;AA4GD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EACxB,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,WAAW,KAAK,WAAW,EACjF,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,EACb,WAAW,GAAE,MAAe,GAC3B,IAAI,CAsUN;AAqHD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,QAAQ,EAAE,MAAM,CAAC,EAAE,EACnB,SAAS,EAAE,WAAW,GAAG,IAAI,EAC7B,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,IAAI,EACnD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,gBAAgB,GAAG,OAAO,EAC5F,QAAQ,CAAC,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CA+FN"}
|
|
@@ -1774,25 +1774,25 @@ function mountRowRoot(el) {
|
|
|
1774
1774
|
}
|
|
1775
1775
|
return el;
|
|
1776
1776
|
}
|
|
1777
|
-
function createComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1778
|
-
const element = materializeComponent(nameOrDef, props, key, slot, mountAt);
|
|
1777
|
+
function createComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1778
|
+
const element = materializeComponent(nameOrDef, props, key, slot, mountAt, keyAttrName2);
|
|
1779
1779
|
if (mountAt && mountAt.parentNode && element !== mountAt) {
|
|
1780
1780
|
mountAt.replaceWith(element);
|
|
1781
1781
|
}
|
|
1782
1782
|
return element;
|
|
1783
1783
|
}
|
|
1784
|
-
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
1784
|
+
function materializeComponent(nameOrDef, props = {}, key, slot, mountAt, keyAttrName2 = BF_KEY) {
|
|
1785
1785
|
if (props == null)
|
|
1786
1786
|
props = {};
|
|
1787
1787
|
const rowMount = mountAt ? null : takeRowMountPoint();
|
|
1788
1788
|
if (typeof nameOrDef !== "string") {
|
|
1789
|
-
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount);
|
|
1789
|
+
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount, keyAttrName2);
|
|
1790
1790
|
}
|
|
1791
1791
|
const name = nameOrDef;
|
|
1792
1792
|
const templateFn = getTemplate(name);
|
|
1793
1793
|
if (!templateFn) {
|
|
1794
1794
|
console.warn(`[BarefootJS] Template not found for component: ${name}`);
|
|
1795
|
-
return createPlaceholder(name, key);
|
|
1795
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1796
1796
|
}
|
|
1797
1797
|
const childrenDescriptor = Object.getOwnPropertyDescriptor(props, "children");
|
|
1798
1798
|
const childrenIsGetter = childrenDescriptor != null && typeof childrenDescriptor.get === "function";
|
|
@@ -1825,6 +1825,8 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1825
1825
|
_parentScopeId = scopeId;
|
|
1826
1826
|
} else if (slot?.parent) {
|
|
1827
1827
|
_parentScopeId = slot.parent;
|
|
1828
|
+
} else if (!_parentScopeId) {
|
|
1829
|
+
_parentScopeId = `${def?.name ?? name}_${generateId()}`;
|
|
1828
1830
|
}
|
|
1829
1831
|
let html;
|
|
1830
1832
|
try {
|
|
@@ -1837,11 +1839,11 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1837
1839
|
const element = isFragmentRoot ? roots.find((node) => node.nodeType === Node.ELEMENT_NODE) : roots[0];
|
|
1838
1840
|
if (isFragmentRoot && roots.length > 0 && !element) {
|
|
1839
1841
|
console.warn(`[BarefootJS] Fragment-root component ${name} rendered no element root; ` + "a scope needs at least one element to attach to. Wrap the content in an element.");
|
|
1840
|
-
return createPlaceholder(name, key);
|
|
1842
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1841
1843
|
}
|
|
1842
1844
|
if (!element) {
|
|
1843
1845
|
console.warn(`[BarefootJS] Template returned empty HTML for component: ${name}`);
|
|
1844
|
-
return createPlaceholder(name, key);
|
|
1846
|
+
return createPlaceholder(name, key, keyAttrName2);
|
|
1845
1847
|
}
|
|
1846
1848
|
if (scopeId && !isFragmentRoot) {
|
|
1847
1849
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
@@ -1852,7 +1854,7 @@ function materializeComponent(nameOrDef, props = {}, key, slot, mountAt) {
|
|
|
1852
1854
|
element.setAttribute(BF_AT, slot.mount);
|
|
1853
1855
|
}
|
|
1854
1856
|
if (key !== undefined) {
|
|
1855
|
-
element.setAttribute(
|
|
1857
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
1856
1858
|
}
|
|
1857
1859
|
const fragmentComments = isFragmentRoot && scopeId ? {
|
|
1858
1860
|
start: document.createComment(`${BF_SCOPE_COMMENT_PREFIX}${scopeId}`),
|
|
@@ -1968,11 +1970,11 @@ var ROOT_HAS_BFS_PATTERN = /^<\w+[^>]*\sbf-s="/;
|
|
|
1968
1970
|
function generateId() {
|
|
1969
1971
|
return Math.random().toString(36).slice(2, 8);
|
|
1970
1972
|
}
|
|
1971
|
-
function createPlaceholder(name, key) {
|
|
1973
|
+
function createPlaceholder(name, key, keyAttrName2 = BF_KEY) {
|
|
1972
1974
|
const el = document.createElement("div");
|
|
1973
1975
|
el.setAttribute(BF_SCOPE, `${name}_placeholder`);
|
|
1974
1976
|
if (key !== undefined) {
|
|
1975
|
-
el.setAttribute(
|
|
1977
|
+
el.setAttribute(keyAttrName2, String(key));
|
|
1976
1978
|
}
|
|
1977
1979
|
el.textContent = `[${name}]`;
|
|
1978
1980
|
el.style.cssText = "color: red; border: 1px dashed red; padding: 4px;";
|
|
@@ -2021,6 +2023,9 @@ function escapeTextOrMarkup(value) {
|
|
|
2021
2023
|
return value[BF_MARKUP_BRAND];
|
|
2022
2024
|
return escapeText(value);
|
|
2023
2025
|
}
|
|
2026
|
+
function markupOrEmpty(value) {
|
|
2027
|
+
return value == null ? "" : value;
|
|
2028
|
+
}
|
|
2024
2029
|
function escapeTextOrNode(value) {
|
|
2025
2030
|
if (isBfMarkup(value))
|
|
2026
2031
|
return value[BF_MARKUP_BRAND];
|
|
@@ -2082,7 +2087,7 @@ function insertGetterChildren(element, children) {
|
|
|
2082
2087
|
element.appendChild(document.createTextNode(String(children)));
|
|
2083
2088
|
}
|
|
2084
2089
|
}
|
|
2085
|
-
function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
2090
|
+
function createComponentFromDef(def, props, key, mountAt, rowMount, keyAttrName2 = BF_KEY) {
|
|
2086
2091
|
if (!def.template) {
|
|
2087
2092
|
throw new Error("[BarefootJS] createComponent with ComponentDef requires a template function");
|
|
2088
2093
|
}
|
|
@@ -2099,7 +2104,7 @@ function createComponentFromDef(def, props, key, mountAt, rowMount) {
|
|
|
2099
2104
|
const scopeId = `${name}_${generateId()}`;
|
|
2100
2105
|
element.setAttribute(BF_SCOPE, scopeId);
|
|
2101
2106
|
if (key !== undefined) {
|
|
2102
|
-
element.setAttribute(
|
|
2107
|
+
element.setAttribute(keyAttrName2, String(key));
|
|
2103
2108
|
}
|
|
2104
2109
|
if (mountAt) {
|
|
2105
2110
|
mountAt.replaceWith(element);
|
|
@@ -2480,7 +2485,7 @@ function createItemScope(item, index, renderItem, existingPrimary, existingExtra
|
|
|
2480
2485
|
}
|
|
2481
2486
|
return { startMarker, primaryEl, extras, scopeComments, dispose, setItem };
|
|
2482
2487
|
}
|
|
2483
|
-
function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
2488
|
+
function mapArray(accessor, container, getKey, renderItem, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2484
2489
|
if (!container)
|
|
2485
2490
|
return;
|
|
2486
2491
|
const scopes = new Map;
|
|
@@ -2505,13 +2510,15 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2505
2510
|
if (!hydrated) {
|
|
2506
2511
|
hydrated = true;
|
|
2507
2512
|
const existingRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2508
|
-
const needsHydration = existingRanges.length > 0
|
|
2513
|
+
const needsHydration = existingRanges.length > 0;
|
|
2509
2514
|
if (needsHydration) {
|
|
2510
2515
|
for (let i2 = 0;i2 < existingRanges.length && i2 < items.length; i2++) {
|
|
2511
2516
|
const range = existingRanges[i2];
|
|
2512
2517
|
const item = items[i2];
|
|
2513
2518
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2514
|
-
range.primaryEl.
|
|
2519
|
+
if (getKey && !range.primaryEl.getAttribute(keyAttrName2)) {
|
|
2520
|
+
range.primaryEl.setAttribute(keyAttrName2, key);
|
|
2521
|
+
}
|
|
2515
2522
|
const scope = createItemScope(item, i2, renderItem, range.primaryEl, range.extras, range.startMarker, range.scopeComments);
|
|
2516
2523
|
scopes.set(key, scope);
|
|
2517
2524
|
hydratedScopes.add(range.primaryEl);
|
|
@@ -2520,8 +2527,8 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2520
2527
|
const item = items[i2];
|
|
2521
2528
|
const key = getKey ? getKey(item, i2) : String(i2);
|
|
2522
2529
|
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2523
|
-
if (!scope.primaryEl.
|
|
2524
|
-
scope.primaryEl.setAttribute(
|
|
2530
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2531
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2525
2532
|
scopes.set(key, scope);
|
|
2526
2533
|
insertScope(scope, container, anchor);
|
|
2527
2534
|
}
|
|
@@ -2546,7 +2553,7 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2546
2553
|
if (scopes.size === 0) {
|
|
2547
2554
|
const loopRanges = startMarker ? findItemRanges(startMarker, endMarker) : Array.from(container.children).map((el) => ({ startMarker: null, primaryEl: el, extras: [], scopeComments: null }));
|
|
2548
2555
|
for (const range of loopRanges) {
|
|
2549
|
-
const existingKey = range.primaryEl.
|
|
2556
|
+
const existingKey = range.primaryEl.getAttribute(keyAttrName2);
|
|
2550
2557
|
if (existingKey && !scopes.has(existingKey)) {
|
|
2551
2558
|
scopes.set(existingKey, {
|
|
2552
2559
|
startMarker: range.startMarker,
|
|
@@ -2604,8 +2611,8 @@ function mapArray(accessor, container, getKey, renderItem, markerId, bfId) {
|
|
|
2604
2611
|
desiredOrder.push(existing);
|
|
2605
2612
|
} else {
|
|
2606
2613
|
const scope = createItemScope(item, i2, renderItem, undefined, undefined, undefined, undefined, { container, anchor });
|
|
2607
|
-
if (!scope.primaryEl.
|
|
2608
|
-
scope.primaryEl.setAttribute(
|
|
2614
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName2))
|
|
2615
|
+
scope.primaryEl.setAttribute(keyAttrName2, key);
|
|
2609
2616
|
scopes.set(key, scope);
|
|
2610
2617
|
desiredOrder.push(scope);
|
|
2611
2618
|
}
|
|
@@ -2800,7 +2807,7 @@ function mapArrayAnchored(accessor, container, getKey, renderItem, markerId, bfI
|
|
|
2800
2807
|
}, bfId);
|
|
2801
2808
|
}
|
|
2802
2809
|
// src/runtime/map-array-lazy.ts
|
|
2803
|
-
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
2810
|
+
function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId, keyAttrName2 = BF_KEY) {
|
|
2804
2811
|
if (!container)
|
|
2805
2812
|
return;
|
|
2806
2813
|
const entries = new Map;
|
|
@@ -2839,8 +2846,8 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2839
2846
|
last: null
|
|
2840
2847
|
};
|
|
2841
2848
|
entry.primaryEl = untrack(() => plan.createRow(entry, index));
|
|
2842
|
-
if (!entry.primaryEl.
|
|
2843
|
-
entry.primaryEl.setAttribute(
|
|
2849
|
+
if (getKey && !entry.primaryEl.getAttribute(keyAttrName2))
|
|
2850
|
+
entry.primaryEl.setAttribute(keyAttrName2, key);
|
|
2844
2851
|
markStranded();
|
|
2845
2852
|
return entry;
|
|
2846
2853
|
};
|
|
@@ -2862,7 +2869,7 @@ function mapArrayLazy(accessor, container, getKey, plan, markerId, bfId) {
|
|
|
2862
2869
|
const shared = Math.min(doms.length, items.length);
|
|
2863
2870
|
for (let i2 = 0;i2 < shared; i2++) {
|
|
2864
2871
|
const el = doms[i2];
|
|
2865
|
-
const ssrKey = el.getAttribute(
|
|
2872
|
+
const ssrKey = el.getAttribute(keyAttrName2);
|
|
2866
2873
|
const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i2], i2) : String(i2);
|
|
2867
2874
|
const entry = { key, primaryEl: el, item: items[i2], refs: null, last: null };
|
|
2868
2875
|
entries.set(key, entry);
|
|
@@ -3804,6 +3811,7 @@ export {
|
|
|
3804
3811
|
onMount,
|
|
3805
3812
|
onCleanup,
|
|
3806
3813
|
mountRowRoot,
|
|
3814
|
+
markupOrEmpty,
|
|
3807
3815
|
mapArrayLazy,
|
|
3808
3816
|
mapArrayAnchored,
|
|
3809
3817
|
mapArray,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.33.
|
|
3
|
+
"version": "0.33.4",
|
|
4
4
|
"description": "BarefootJS client package: reactive primitives (SSR-safe) plus browser runtime under the `/runtime` subpath (compiler target)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"directory": "packages/client"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@barefootjs/shared": "0.33.
|
|
58
|
+
"@barefootjs/shared": "0.33.4"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|
package/src/runtime/component.ts
CHANGED
|
@@ -178,6 +178,7 @@ export function createComponent(
|
|
|
178
178
|
key: string | number | undefined,
|
|
179
179
|
slot: CreateComponentSlotInfo | undefined,
|
|
180
180
|
mountAt: Element,
|
|
181
|
+
keyAttrName?: string,
|
|
181
182
|
): HTMLElement
|
|
182
183
|
export function createComponent(
|
|
183
184
|
nameOrDef: string | ComponentDef,
|
|
@@ -185,6 +186,7 @@ export function createComponent(
|
|
|
185
186
|
key?: string | number,
|
|
186
187
|
slot?: CreateComponentSlotInfo,
|
|
187
188
|
mountAt?: Element | null,
|
|
189
|
+
keyAttrName?: string,
|
|
188
190
|
): HTMLElement | DocumentFragment
|
|
189
191
|
export function createComponent(
|
|
190
192
|
nameOrDef: string | ComponentDef,
|
|
@@ -192,8 +194,9 @@ export function createComponent(
|
|
|
192
194
|
key?: string | number,
|
|
193
195
|
slot?: CreateComponentSlotInfo,
|
|
194
196
|
mountAt?: Element | null,
|
|
197
|
+
keyAttrName: string = BF_KEY,
|
|
195
198
|
): HTMLElement | DocumentFragment {
|
|
196
|
-
const element = materializeComponent(nameOrDef, props, key, slot, mountAt)
|
|
199
|
+
const element = materializeComponent(nameOrDef, props, key, slot, mountAt, keyAttrName)
|
|
197
200
|
// `mountAt` is an unconditional obligation: callers used to run
|
|
198
201
|
// `ph.replaceWith(comp)` themselves on every outcome, so every path that
|
|
199
202
|
// did NOT consume the placeholder still owes the replacement — a missing or
|
|
@@ -224,6 +227,7 @@ function materializeComponent(
|
|
|
224
227
|
key?: string | number,
|
|
225
228
|
slot?: CreateComponentSlotInfo,
|
|
226
229
|
mountAt?: Element | null,
|
|
230
|
+
keyAttrName: string = BF_KEY,
|
|
227
231
|
): HTMLElement | DocumentFragment {
|
|
228
232
|
// A bare callable shim invoked from user code (e.g. an object-literal
|
|
229
233
|
// value `LOGOS[id]()` whose arrow the compiler hoisted into a component)
|
|
@@ -235,7 +239,7 @@ function materializeComponent(
|
|
|
235
239
|
const rowMount = mountAt ? null : takeRowMountPoint()
|
|
236
240
|
// ComponentDef mode: use def directly instead of registry lookup
|
|
237
241
|
if (typeof nameOrDef !== 'string') {
|
|
238
|
-
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount)
|
|
242
|
+
return createComponentFromDef(nameOrDef, props, key, mountAt, rowMount, keyAttrName)
|
|
239
243
|
}
|
|
240
244
|
|
|
241
245
|
const name = nameOrDef
|
|
@@ -244,7 +248,7 @@ function materializeComponent(
|
|
|
244
248
|
const templateFn = getTemplate(name)
|
|
245
249
|
if (!templateFn) {
|
|
246
250
|
console.warn(`[BarefootJS] Template not found for component: ${name}`)
|
|
247
|
-
return createPlaceholder(name, key)
|
|
251
|
+
return createPlaceholder(name, key, keyAttrName)
|
|
248
252
|
}
|
|
249
253
|
|
|
250
254
|
// 2. Check for getter children.
|
|
@@ -328,11 +332,32 @@ function materializeComponent(
|
|
|
328
332
|
// #2444's `grandchild-composition` case). A comment wrapper keeps
|
|
329
333
|
// `scopeId === null` and falls through to `slot?.parent`, preserving the
|
|
330
334
|
// hoisted-children placeholder resolution (#1320).
|
|
335
|
+
//
|
|
336
|
+
// Third branch (#2757): a root-is-a-child-call wrapper mounted at the TOP
|
|
337
|
+
// LEVEL has neither. `scopeId` is null by design (step 4 — the parsed
|
|
338
|
+
// firstChild is the child's own already-scoped element, so we must not
|
|
339
|
+
// stamp over it) and a top-level `createComponent(name, {})` is passed no
|
|
340
|
+
// `slot`, so pre-#2757 `_parentScopeId` stayed null for the whole template
|
|
341
|
+
// eval and `renderChild` fell back to naming the child after ITSELF
|
|
342
|
+
// (`PairwiseRow_xyz_s2` where SSR and hydration both produce
|
|
343
|
+
// `PairwiseCase_xyz_s2`, and with no `bf-h`/`bf-m` at all). The wrapper
|
|
344
|
+
// still HAS a scope identity in the SSR convention — it just has no
|
|
345
|
+
// element of its own to carry it — so derive one here for threading only.
|
|
346
|
+
// Same split #2722 made for a genuine fragment root, which keeps a
|
|
347
|
+
// non-null `scopeId` purely so this threading works and skips only the
|
|
348
|
+
// ATTRIBUTE write in step 7.
|
|
349
|
+
//
|
|
350
|
+
// Why not derive unconditionally: guarded on `!_parentScopeId` so a
|
|
351
|
+
// wrapper materialized while an OUTER template eval is in flight keeps
|
|
352
|
+
// inheriting that caller's ambient scope rather than being renamed under a
|
|
353
|
+
// fresh random id. Only the genuinely-rootless mount is affected.
|
|
331
354
|
const prevParentScopeId = _parentScopeId
|
|
332
355
|
if (scopeId) {
|
|
333
356
|
_parentScopeId = scopeId
|
|
334
357
|
} else if (slot?.parent) {
|
|
335
358
|
_parentScopeId = slot.parent
|
|
359
|
+
} else if (!_parentScopeId) {
|
|
360
|
+
_parentScopeId = `${def?.name ?? name}_${generateId()}`
|
|
336
361
|
}
|
|
337
362
|
let html: string
|
|
338
363
|
try {
|
|
@@ -385,12 +410,12 @@ function materializeComponent(
|
|
|
385
410
|
`[BarefootJS] Fragment-root component ${name} rendered no element root; ` +
|
|
386
411
|
'a scope needs at least one element to attach to. Wrap the content in an element.',
|
|
387
412
|
)
|
|
388
|
-
return createPlaceholder(name, key)
|
|
413
|
+
return createPlaceholder(name, key, keyAttrName)
|
|
389
414
|
}
|
|
390
415
|
|
|
391
416
|
if (!element) {
|
|
392
417
|
console.warn(`[BarefootJS] Template returned empty HTML for component: ${name}`)
|
|
393
|
-
return createPlaceholder(name, key)
|
|
418
|
+
return createPlaceholder(name, key, keyAttrName)
|
|
394
419
|
}
|
|
395
420
|
|
|
396
421
|
// 7. Set scope ID and key attributes.
|
|
@@ -408,7 +433,7 @@ function materializeComponent(
|
|
|
408
433
|
element.setAttribute(BF_AT, slot.mount)
|
|
409
434
|
}
|
|
410
435
|
if (key !== undefined) {
|
|
411
|
-
element.setAttribute(
|
|
436
|
+
element.setAttribute(keyAttrName, String(key))
|
|
412
437
|
}
|
|
413
438
|
|
|
414
439
|
// 7a. Fragment-root boundary comments + registry (#2722).
|
|
@@ -722,8 +747,8 @@ export function renderChild(
|
|
|
722
747
|
const hostSuffix = (_parentScopeId && slotSuffix) ? `|h=${_parentScopeId}|m=${slotSuffix}` : ''
|
|
723
748
|
// #2732: `data-key` for a fragment-root loop row lands on the row's own
|
|
724
749
|
// first element — the same "first element, not first node" convention
|
|
725
|
-
// `IRElement.
|
|
726
|
-
//
|
|
750
|
+
// `IRElement.keyAttr` uses on the SSR side (jsx-to-ir.ts) — not on the
|
|
751
|
+
// comment above, which carries scope identity only. This keeps
|
|
727
752
|
// `mapArray`'s existing `primaryEl.dataset.key` read (map-array.ts)
|
|
728
753
|
// working unchanged for markup this function pre-builds (the pure-CSR
|
|
729
754
|
// `materializeComponent` template-string path, used when there is no
|
|
@@ -769,11 +794,11 @@ function generateId(): string {
|
|
|
769
794
|
/**
|
|
770
795
|
* Create a placeholder element when template is not found
|
|
771
796
|
*/
|
|
772
|
-
function createPlaceholder(name: string, key?: string | number): HTMLElement {
|
|
797
|
+
function createPlaceholder(name: string, key?: string | number, keyAttrName: string = BF_KEY): HTMLElement {
|
|
773
798
|
const el = document.createElement('div')
|
|
774
799
|
el.setAttribute(BF_SCOPE, `${name}_placeholder`)
|
|
775
800
|
if (key !== undefined) {
|
|
776
|
-
el.setAttribute(
|
|
801
|
+
el.setAttribute(keyAttrName, String(key))
|
|
777
802
|
}
|
|
778
803
|
el.textContent = `[${name}]`
|
|
779
804
|
el.style.cssText = 'color: red; border: 1px dashed red; padding: 4px;'
|
|
@@ -949,6 +974,34 @@ export function escapeTextOrMarkup(value: unknown): string {
|
|
|
949
974
|
return escapeText(value)
|
|
950
975
|
}
|
|
951
976
|
|
|
977
|
+
/**
|
|
978
|
+
* Nullish guard for a bare `${children}` passthrough splice
|
|
979
|
+
* (`ir-to-client-js/html-template.ts`'s no-`slotId` `'expression'` branches
|
|
980
|
+
* — the "bare `${...}` interpolations" the docstring above `escapeTextSlotExpr`
|
|
981
|
+
* describes) — #2775. The value here is ALREADY-STRINGIFIED MARKUP, not an
|
|
982
|
+
* arbitrary prop: `materializeComponent` (this file, "Template functions
|
|
983
|
+
* expect children as an HTML string, not an array") joins a component's
|
|
984
|
+
* `children` into an HTML string before the template lambda ever runs, so by
|
|
985
|
+
* the time this function sees the value it is either that HTML string or,
|
|
986
|
+
* when the caller passed none, simply `undefined` (the key is absent from
|
|
987
|
+
* the props object entirely). This function's ENTIRE job is that one
|
|
988
|
+
* nullish case: turn the absent/`null` value into `''`, same as SSR's
|
|
989
|
+
* `{props.children}` and the DSL adapters' `bf.string(children)` render it.
|
|
990
|
+
*
|
|
991
|
+
* Deliberately NOT `escapeTextOrMarkup`: that function falls back to
|
|
992
|
+
* `escapeText` for anything not `bfMarkup()`-branded, and a `children`
|
|
993
|
+
* string is never branded (it is a plain string built by
|
|
994
|
+
* `materializeComponent`, not compiler-escaped piece-by-piece the way a
|
|
995
|
+
* `bfMarkup()` value is) — routing `children` through it would HTML-escape
|
|
996
|
+
* real markup into visible `<span>`-style text on every call that
|
|
997
|
+
* actually has children, trading the no-children bug for a strictly worse
|
|
998
|
+
* with-children one. So: nullish becomes `''`; every other value is
|
|
999
|
+
* returned completely unescaped, exactly as it arrived.
|
|
1000
|
+
*/
|
|
1001
|
+
export function markupOrEmpty(value: unknown): string {
|
|
1002
|
+
return value == null ? '' : (value as string)
|
|
1003
|
+
}
|
|
1004
|
+
|
|
952
1005
|
/**
|
|
953
1006
|
* `escapeText`'s counterpart for a claimed 'markup' slot's REACTIVE write
|
|
954
1007
|
* (slot unification A3 follow-up), where the value is a plain-JS expression
|
|
@@ -1073,6 +1126,7 @@ function createComponentFromDef(
|
|
|
1073
1126
|
key?: string | number,
|
|
1074
1127
|
mountAt?: Element | null,
|
|
1075
1128
|
rowMount?: { container: Node; anchor: Node | null } | null,
|
|
1129
|
+
keyAttrName: string = BF_KEY,
|
|
1076
1130
|
): HTMLElement {
|
|
1077
1131
|
if (!def.template) {
|
|
1078
1132
|
throw new Error('[BarefootJS] createComponent with ComponentDef requires a template function')
|
|
@@ -1097,7 +1151,7 @@ function createComponentFromDef(
|
|
|
1097
1151
|
const scopeId = `${name}_${generateId()}`
|
|
1098
1152
|
element.setAttribute(BF_SCOPE, scopeId)
|
|
1099
1153
|
if (key !== undefined) {
|
|
1100
|
-
element.setAttribute(
|
|
1154
|
+
element.setAttribute(keyAttrName, String(key))
|
|
1101
1155
|
}
|
|
1102
1156
|
|
|
1103
1157
|
// Connect before init, for the same reason the registry path does (see
|
package/src/runtime/index.ts
CHANGED
|
@@ -166,6 +166,11 @@ export interface LazyRowPlan<T> {
|
|
|
166
166
|
* @param plan - Compiler-emitted row plan (see {@link LazyRowPlan})
|
|
167
167
|
* @param markerId - Scoped loop marker id (`<!--bf-loop:<id>-->`), see #1087
|
|
168
168
|
* @param bfId - Profiler attribution id for the reconciler effect
|
|
169
|
+
* @param keyAttrName - The row-key attribute NAME this loop resolved at
|
|
170
|
+
* compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
|
|
171
|
+
* jsx-to-ir.ts). Defaults to `BF_KEY` (plain `'data-key'`),
|
|
172
|
+
* correct at the outermost loop; only a nested loop's
|
|
173
|
+
* compiled call passes a depth-suffixed name (#2753).
|
|
169
174
|
*/
|
|
170
175
|
export function mapArrayLazy<T>(
|
|
171
176
|
accessor: () => T[],
|
|
@@ -174,6 +179,7 @@ export function mapArrayLazy<T>(
|
|
|
174
179
|
plan: LazyRowPlan<T>,
|
|
175
180
|
markerId?: string,
|
|
176
181
|
bfId?: string,
|
|
182
|
+
keyAttrName: string = BF_KEY,
|
|
177
183
|
): void {
|
|
178
184
|
if (!container) return
|
|
179
185
|
|
|
@@ -249,8 +255,11 @@ export function mapArrayLazy<T>(
|
|
|
249
255
|
* so it is wrapped in `untrack()`: it writes outer-involving bindings
|
|
250
256
|
* with current values (contract), and those signal reads must not
|
|
251
257
|
* subscribe the reconciler. The returned element is assigned to
|
|
252
|
-
* `entry.primaryEl`;
|
|
253
|
-
* (mirrors `mapArray`'s create path)
|
|
258
|
+
* `entry.primaryEl`; the row's key attribute is stamped if `createRow`
|
|
259
|
+
* didn't (mirrors `mapArray`'s create path) — only for a KEYED loop
|
|
260
|
+
* (#2753 Shape A: an unkeyed loop's rows carry no key attribute at all),
|
|
261
|
+
* using `keyAttrName` (Shape B: a nested loop's name is depth-suffixed,
|
|
262
|
+
* never the plain default `BF_KEY`).
|
|
254
263
|
*/
|
|
255
264
|
const createEntry = (item: T, index: number, key: string): LazyRowEntry<T> => {
|
|
256
265
|
const entry: LazyRowEntry<T> = {
|
|
@@ -263,7 +272,7 @@ export function mapArrayLazy<T>(
|
|
|
263
272
|
last: null,
|
|
264
273
|
}
|
|
265
274
|
entry.primaryEl = untrack(() => plan.createRow(entry, index))
|
|
266
|
-
if (!entry.primaryEl.
|
|
275
|
+
if (getKey && !entry.primaryEl.getAttribute(keyAttrName)) entry.primaryEl.setAttribute(keyAttrName, key)
|
|
267
276
|
markStranded()
|
|
268
277
|
return entry
|
|
269
278
|
}
|
|
@@ -294,7 +303,9 @@ export function mapArrayLazy<T>(
|
|
|
294
303
|
const el = doms[i]
|
|
295
304
|
// READ the SSR-rendered key (never write it on adopted rows);
|
|
296
305
|
// positional item pairing is sound by the §9.3(2) eligibility gate.
|
|
297
|
-
|
|
306
|
+
// `keyAttrName`, not the plain `BF_KEY` default — a nested loop's
|
|
307
|
+
// rows carry a depth-suffixed name (#2753 Shape B).
|
|
308
|
+
const ssrKey = el.getAttribute(keyAttrName)
|
|
298
309
|
const key = ssrKey !== null ? ssrKey : getKey ? getKey(items[i], i) : String(i)
|
|
299
310
|
const entry: LazyRowEntry<T> = { key, primaryEl: el, item: items[i], refs: null, last: null }
|
|
300
311
|
entries.set(key, entry)
|
package/src/runtime/map-array.ts
CHANGED
|
@@ -412,6 +412,16 @@ function createItemScope<T>(
|
|
|
412
412
|
* Receives item as signal accessor: item() returns current value.
|
|
413
413
|
* When `existing` is passed, initializes the SSR-rendered element and returns it.
|
|
414
414
|
* When `existing` is undefined, creates a new element and returns it.
|
|
415
|
+
* @param keyAttrName - The row-key attribute NAME this loop resolved at
|
|
416
|
+
* compile time (`IRElement.keyAttr`/`keyAttrName(loop.depth)`,
|
|
417
|
+
* jsx-to-ir.ts) — `'data-key'` at the outermost loop,
|
|
418
|
+
* `'data-key-N'` N levels deep. Defaults to `BF_KEY`
|
|
419
|
+
* (plain `'data-key'`), correct for every depth-0 call
|
|
420
|
+
* site; only a nested loop's compiled call passes a
|
|
421
|
+
* depth-suffixed name (#2753 Shape B — see the "Why not
|
|
422
|
+
* stamp unconditionally" note below for why this
|
|
423
|
+
* replaced a hardcoded constant instead of just fixing
|
|
424
|
+
* the value).
|
|
415
425
|
*/
|
|
416
426
|
export function mapArray<T>(
|
|
417
427
|
accessor: () => T[],
|
|
@@ -420,6 +430,7 @@ export function mapArray<T>(
|
|
|
420
430
|
renderItem: (item: () => T, index: number, existing?: HTMLElement) => HTMLElement,
|
|
421
431
|
markerId?: string,
|
|
422
432
|
bfId?: string,
|
|
433
|
+
keyAttrName: string = BF_KEY,
|
|
423
434
|
): void {
|
|
424
435
|
if (!container) return
|
|
425
436
|
|
|
@@ -460,18 +471,46 @@ export function mapArray<T>(
|
|
|
460
471
|
(el) => ({ startMarker: null, primaryEl: el as HTMLElement, extras: [] as HTMLElement[], scopeComments: null as ScopeCommentPair | null }),
|
|
461
472
|
)
|
|
462
473
|
|
|
463
|
-
//
|
|
464
|
-
//
|
|
465
|
-
//
|
|
474
|
+
// #2753 — why not read the DOM for a hydration signal: this branch
|
|
475
|
+
// runs at most ONCE per `mapArray` call (guarded by the closure-local
|
|
476
|
+
// `hydrated` flag, set true on the line above, before anything else
|
|
477
|
+
// can run), and `scopes` is a closure-local Map that is ALWAYS empty
|
|
478
|
+
// the first time this line runs — nothing sets it earlier. So "has
|
|
479
|
+
// this container already been adopted" is already fully answered by
|
|
480
|
+
// `existingRanges.length > 0` (there is DOM here from SSR/a prior
|
|
481
|
+
// render) with no attribute read at all. The attribute the old check
|
|
482
|
+
// read (`hasAttribute('data-key')`) was never a sound signal anyway:
|
|
483
|
+
// an unkeyed loop's rows legitimately carry no key attribute at all
|
|
484
|
+
// (Shape A), and a nested loop's rows carry a depth-suffixed name
|
|
485
|
+
// (`data-key-N`, Shape B) — so the plain-name probe either
|
|
486
|
+
// misdiagnosed a correctly-unkeyed row as "not yet hydrated", or
|
|
487
|
+
// missed a correctly-keyed nested row entirely. `scopes.size === 0`
|
|
488
|
+
// is not a second, independent signal here — it is ALWAYS true at
|
|
489
|
+
// this line, so the two-part `||` reduced to the first probe being
|
|
490
|
+
// moot: this is a behavior-preserving simplification, not a new rule.
|
|
466
491
|
const needsHydration = existingRanges.length > 0
|
|
467
|
-
&& (!existingRanges[0]?.primaryEl.hasAttribute('data-key') || scopes.size === 0)
|
|
468
492
|
if (needsHydration) {
|
|
469
493
|
// Hydrate in place: tag keys, create per-item scopes with renderItem(existing)
|
|
470
494
|
for (let i = 0; i < existingRanges.length && i < items.length; i++) {
|
|
471
495
|
const range = existingRanges[i]
|
|
472
496
|
const item = items[i]
|
|
473
497
|
const key = getKey ? getKey(item, i) : String(i)
|
|
474
|
-
|
|
498
|
+
// Only a KEYED loop gets a key attribute at all (Shape A) — SSR
|
|
499
|
+
// (or the static template this row cloned from) already carries
|
|
500
|
+
// the correct, depth-aware name (Shape B) when it applies, so this
|
|
501
|
+
// is a defensive backfill for a row that arrived without one, not
|
|
502
|
+
// the primary writer. A FALSY-value check (`getAttribute`, not
|
|
503
|
+
// `hasAttribute`) — not just presence — because a compiled
|
|
504
|
+
// template can bake the attribute PRESENT but empty for a shape
|
|
505
|
+
// whose key expression isn't ready at clone time (measured on the
|
|
506
|
+
// csr-mount leg of a keyed top-level loop); `hasAttribute` would
|
|
507
|
+
// wrongly treat that empty placeholder as "already correct" and
|
|
508
|
+
// skip the backfill this line exists to make. Reads the SAME name
|
|
509
|
+
// being written (not `dataset.key`, which only ever reads the
|
|
510
|
+
// plain, undepth-suffixed name).
|
|
511
|
+
if (getKey && !range.primaryEl.getAttribute(keyAttrName)) {
|
|
512
|
+
range.primaryEl.setAttribute(keyAttrName, key)
|
|
513
|
+
}
|
|
475
514
|
|
|
476
515
|
const scope = createItemScope(
|
|
477
516
|
item,
|
|
@@ -493,7 +532,7 @@ export function mapArray<T>(
|
|
|
493
532
|
// Final position is known here (append before the loop's trailing
|
|
494
533
|
// anchor), so the row can be mounted at it before its init runs.
|
|
495
534
|
const scope = createItemScope(item, i, renderItem, undefined, undefined, undefined, undefined, { container, anchor })
|
|
496
|
-
if (!scope.primaryEl.
|
|
535
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName)) scope.primaryEl.setAttribute(keyAttrName, key)
|
|
497
536
|
scopes.set(key, scope)
|
|
498
537
|
insertScope(scope, container, anchor)
|
|
499
538
|
}
|
|
@@ -522,7 +561,10 @@ export function mapArray<T>(
|
|
|
522
561
|
(el) => ({ startMarker: null, primaryEl: el as HTMLElement, extras: [] as HTMLElement[], scopeComments: null as ScopeCommentPair | null }),
|
|
523
562
|
)
|
|
524
563
|
for (const range of loopRanges) {
|
|
525
|
-
|
|
564
|
+
// `getAttribute(keyAttrName)`, not `dataset.key` — `dataset` only
|
|
565
|
+
// ever reads the plain, undepth-suffixed `data-key`, which misses a
|
|
566
|
+
// nested loop's `data-key-N` rows entirely (#2753 Shape B).
|
|
567
|
+
const existingKey = range.primaryEl.getAttribute(keyAttrName)
|
|
526
568
|
if (existingKey && !scopes.has(existingKey)) {
|
|
527
569
|
scopes.set(existingKey, {
|
|
528
570
|
startMarker: range.startMarker,
|
|
@@ -612,7 +654,7 @@ export function mapArray<T>(
|
|
|
612
654
|
// to its final position (it participates in the walk like any other
|
|
613
655
|
// attached scope, so the resulting order is unchanged).
|
|
614
656
|
const scope = createItemScope(item, i, renderItem, undefined, undefined, undefined, undefined, { container, anchor })
|
|
615
|
-
if (!scope.primaryEl.
|
|
657
|
+
if (getKey && !scope.primaryEl.getAttribute(keyAttrName)) scope.primaryEl.setAttribute(keyAttrName, key)
|
|
616
658
|
scopes.set(key, scope)
|
|
617
659
|
desiredOrder.push(scope)
|
|
618
660
|
}
|