@barefootjs/client 0.21.3 → 0.21.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/runtime/index.js
CHANGED
|
@@ -656,6 +656,21 @@ function isInsideNestedCommentScope(element, scope) {
|
|
|
656
656
|
}
|
|
657
657
|
return false;
|
|
658
658
|
}
|
|
659
|
+
function isInsideNestedChildScope(element, root) {
|
|
660
|
+
let current = element;
|
|
661
|
+
while (current !== root) {
|
|
662
|
+
const parent = current.parentNode;
|
|
663
|
+
if (!parent)
|
|
664
|
+
return false;
|
|
665
|
+
if (parent !== root && parent.nodeType === Node.ELEMENT_NODE && parent.hasAttribute(BF_SCOPE)) {
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
if (isTopLevelCommentScopeNode(current))
|
|
669
|
+
return true;
|
|
670
|
+
current = parent;
|
|
671
|
+
}
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
659
674
|
function isTopLevelCommentScopeNode(node) {
|
|
660
675
|
const parent = node.parentNode;
|
|
661
676
|
if (!parent)
|
|
@@ -760,7 +775,14 @@ function qsa(el, selector) {
|
|
|
760
775
|
}
|
|
761
776
|
if (el.matches(selector))
|
|
762
777
|
return el;
|
|
763
|
-
|
|
778
|
+
const first = el.querySelector(selector);
|
|
779
|
+
if (!first || !isInsideNestedChildScope(first, el))
|
|
780
|
+
return first;
|
|
781
|
+
for (const candidate of el.querySelectorAll(selector)) {
|
|
782
|
+
if (candidate !== first && !isInsideNestedChildScope(candidate, el))
|
|
783
|
+
return candidate;
|
|
784
|
+
}
|
|
785
|
+
return null;
|
|
764
786
|
}
|
|
765
787
|
function splitTopLevelCommas(selector) {
|
|
766
788
|
const out = [];
|
package/dist/runtime/query.d.ts
CHANGED
|
@@ -61,6 +61,12 @@ export declare function findCondTarget(scope: Element, selector: string): Elemen
|
|
|
61
61
|
* then its descendants. Unlike querySelector() which only searches descendants,
|
|
62
62
|
* this also matches the root element.
|
|
63
63
|
*
|
|
64
|
+
* Descendant candidates that fall inside a nested child component's own
|
|
65
|
+
* scope are skipped (`isInsideNestedChildScope`) — compiler slot IDs
|
|
66
|
+
* (`bf="sN"`) are assigned independently per component file, so a slot
|
|
67
|
+
* number can coincidentally collide between `el`'s own template and a
|
|
68
|
+
* child component mounted somewhere inside it (#2316).
|
|
69
|
+
*
|
|
64
70
|
* Used by compiler-generated code for event binding and attribute updates
|
|
65
71
|
* on loop items where the target may be the loop item's root element itself.
|
|
66
72
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/runtime/query.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,sFAAsF;AACtF,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAGJ,CAAA;AAqCnC;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,GAAG,IAAI,CAoDhB;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/runtime/query.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,sFAAsF;AACtF,eAAO,MAAM,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAGJ,CAAA;AAqCnC;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,GAAG,IAAI,CAoDhB;AA2ND;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,GAAG,IAAI,CAiChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAW/E;AAuBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAsCxE;AA+CD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAU9E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAO1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAO7E;AAED;;;;;GAKG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAE9E;AAkDD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,GAAG,IAAI,CAehB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAiB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAkBnE;AAyDD;;;;;;;GAOG;AACH,wBAAgB,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAkC3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAS3D;AAED,OAAO,EAAE,oBAAoB,IAAI,MAAM,EAAE,CAAA"}
|
|
@@ -1064,6 +1064,21 @@ function isInsideNestedCommentScope(element, scope) {
|
|
|
1064
1064
|
}
|
|
1065
1065
|
return false;
|
|
1066
1066
|
}
|
|
1067
|
+
function isInsideNestedChildScope(element, root) {
|
|
1068
|
+
let current = element;
|
|
1069
|
+
while (current !== root) {
|
|
1070
|
+
const parent = current.parentNode;
|
|
1071
|
+
if (!parent)
|
|
1072
|
+
return false;
|
|
1073
|
+
if (parent !== root && parent.nodeType === Node.ELEMENT_NODE && parent.hasAttribute(BF_SCOPE)) {
|
|
1074
|
+
return true;
|
|
1075
|
+
}
|
|
1076
|
+
if (isTopLevelCommentScopeNode(current))
|
|
1077
|
+
return true;
|
|
1078
|
+
current = parent;
|
|
1079
|
+
}
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1067
1082
|
function isTopLevelCommentScopeNode(node) {
|
|
1068
1083
|
const parent = node.parentNode;
|
|
1069
1084
|
if (!parent)
|
|
@@ -1168,7 +1183,14 @@ function qsa(el, selector) {
|
|
|
1168
1183
|
}
|
|
1169
1184
|
if (el.matches(selector))
|
|
1170
1185
|
return el;
|
|
1171
|
-
|
|
1186
|
+
const first = el.querySelector(selector);
|
|
1187
|
+
if (!first || !isInsideNestedChildScope(first, el))
|
|
1188
|
+
return first;
|
|
1189
|
+
for (const candidate of el.querySelectorAll(selector)) {
|
|
1190
|
+
if (candidate !== first && !isInsideNestedChildScope(candidate, el))
|
|
1191
|
+
return candidate;
|
|
1192
|
+
}
|
|
1193
|
+
return null;
|
|
1172
1194
|
}
|
|
1173
1195
|
function splitTopLevelCommas(selector) {
|
|
1174
1196
|
const out = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.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.21.
|
|
58
|
+
"@barefootjs/shared": "0.21.4"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|
package/src/runtime/query.ts
CHANGED
|
@@ -251,6 +251,48 @@ function isInsideNestedCommentScope(element: Element, scope: Element): boolean {
|
|
|
251
251
|
return false
|
|
252
252
|
}
|
|
253
253
|
|
|
254
|
+
/**
|
|
255
|
+
* True if `element` sits inside a nested child component's own scope
|
|
256
|
+
* boundary somewhere on the path up to `root` — a plain `[bf-s]` element
|
|
257
|
+
* (a regular child component's root) or a fragment-rooted child's
|
|
258
|
+
* comment-scope range mounted as a sibling along that path.
|
|
259
|
+
*
|
|
260
|
+
* Generalizes `isInsideNestedCommentScope` (which only catches the
|
|
261
|
+
* comment-scope case) to also catch plain `bf-s` boundaries, for `qsa()`
|
|
262
|
+
* — the loose, unfiltered sibling of `find()`'s `belongsToScope`-gated
|
|
263
|
+
* search. Unlike `belongsToScope`, this walks up to `root` by object
|
|
264
|
+
* identity rather than requiring `root` itself to carry `bf-s`: `qsa()`'s
|
|
265
|
+
* roots include `insert()`'s whole-component branch scope (which does
|
|
266
|
+
* carry `bf-s`) but also loop-item template clones (which normally don't),
|
|
267
|
+
* so a `.closest('[bf-s]') === root` check can't be reused here.
|
|
268
|
+
*
|
|
269
|
+
* Without this, a slot number that happens to collide between a component
|
|
270
|
+
* and a nested child mounted earlier in its DOM (compiler slot IDs are
|
|
271
|
+
* assigned independently per component file, so collisions are expected)
|
|
272
|
+
* makes `qsa()` return the child's element instead of the component's own.
|
|
273
|
+
*
|
|
274
|
+
* Deliberately does NOT reject `element` itself for carrying `bf-s`
|
|
275
|
+
* (unlike `belongsToScope`'s own-scope check) — `qsa()` doubles as the
|
|
276
|
+
* lookup for a nested child component's *own* scope root (e.g. compiled
|
|
277
|
+
* `qsa(parentScope, '[bf-h="X"][bf-m="sN"], [bf-s$="_sN"]')` calls feeding
|
|
278
|
+
* `initChild()`), and that target legitimately carries `bf-s`. Only an
|
|
279
|
+
* *intermediate* `bf-s` between `element` and `root` — i.e. `element`
|
|
280
|
+
* nested inside some other, unrelated child scope — disqualifies it.
|
|
281
|
+
*/
|
|
282
|
+
function isInsideNestedChildScope(element: Element, root: Element): boolean {
|
|
283
|
+
let current: Node = element
|
|
284
|
+
while (current !== root) {
|
|
285
|
+
const parent: Node | null = current.parentNode
|
|
286
|
+
if (!parent) return false
|
|
287
|
+
if (parent !== root && parent.nodeType === Node.ELEMENT_NODE && (parent as Element).hasAttribute(BF_SCOPE)) {
|
|
288
|
+
return true
|
|
289
|
+
}
|
|
290
|
+
if (isTopLevelCommentScopeNode(current)) return true
|
|
291
|
+
current = parent
|
|
292
|
+
}
|
|
293
|
+
return false
|
|
294
|
+
}
|
|
295
|
+
|
|
254
296
|
/**
|
|
255
297
|
* True if `node` falls inside a `<!--bf-scope:...-->` … `<!--bf-/scope:...-->`
|
|
256
298
|
* range among its own siblings — i.e. `node` is (or is inside) a top-level
|
|
@@ -409,6 +451,12 @@ function findInPortals(scopeId: string, selector: string): Element | null {
|
|
|
409
451
|
* then its descendants. Unlike querySelector() which only searches descendants,
|
|
410
452
|
* this also matches the root element.
|
|
411
453
|
*
|
|
454
|
+
* Descendant candidates that fall inside a nested child component's own
|
|
455
|
+
* scope are skipped (`isInsideNestedChildScope`) — compiler slot IDs
|
|
456
|
+
* (`bf="sN"`) are assigned independently per component file, so a slot
|
|
457
|
+
* number can coincidentally collide between `el`'s own template and a
|
|
458
|
+
* child component mounted somewhere inside it (#2316).
|
|
459
|
+
*
|
|
412
460
|
* Used by compiler-generated code for event binding and attribute updates
|
|
413
461
|
* on loop items where the target may be the loop item's root element itself.
|
|
414
462
|
*/
|
|
@@ -437,7 +485,19 @@ export function qsa(el: Element | null, selector: string): Element | null {
|
|
|
437
485
|
return qsaChildScope(el, selector)
|
|
438
486
|
}
|
|
439
487
|
if (el.matches(selector)) return el
|
|
440
|
-
|
|
488
|
+
|
|
489
|
+
// Fast path: the overwhelmingly common case has no nested-child-scope
|
|
490
|
+
// collision, so a single querySelector() (matching the old behavior)
|
|
491
|
+
// resolves it without the cost of enumerating every match. Only fall
|
|
492
|
+
// back to the full querySelectorAll() scan — needed to skip past a
|
|
493
|
+
// rejected candidate to the next DOM-order match — when the first hit
|
|
494
|
+
// actually turns out to belong to a nested child scope.
|
|
495
|
+
const first = el.querySelector(selector)
|
|
496
|
+
if (!first || !isInsideNestedChildScope(first, el)) return first
|
|
497
|
+
for (const candidate of el.querySelectorAll(selector)) {
|
|
498
|
+
if (candidate !== first && !isInsideNestedChildScope(candidate, el)) return candidate
|
|
499
|
+
}
|
|
500
|
+
return null
|
|
441
501
|
}
|
|
442
502
|
|
|
443
503
|
/** Split a CSS selector list on top-level commas, ignoring commas inside
|