@barefootjs/client 0.21.0 → 0.21.2
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 +37 -2
- package/dist/runtime/query.d.ts.map +1 -1
- package/dist/runtime/standalone.js +37 -2
- package/package.json +2 -2
- package/src/runtime/query.ts +63 -5
package/dist/runtime/index.js
CHANGED
|
@@ -640,7 +640,41 @@ function belongsToScope(element, scope) {
|
|
|
640
640
|
if (element.getAttribute(BF_SCOPE))
|
|
641
641
|
return false;
|
|
642
642
|
const nearestScope = element.closest(`[${BF_SCOPE}]`);
|
|
643
|
-
|
|
643
|
+
if (nearestScope !== scope)
|
|
644
|
+
return false;
|
|
645
|
+
return !isInsideNestedCommentScope(element, scope);
|
|
646
|
+
}
|
|
647
|
+
function isInsideNestedCommentScope(element, scope) {
|
|
648
|
+
let current = element;
|
|
649
|
+
while (current !== scope) {
|
|
650
|
+
const parent = current.parentNode;
|
|
651
|
+
if (!parent)
|
|
652
|
+
return false;
|
|
653
|
+
if (isTopLevelCommentScopeNode(current))
|
|
654
|
+
return true;
|
|
655
|
+
current = parent;
|
|
656
|
+
}
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
function isTopLevelCommentScopeNode(node) {
|
|
660
|
+
const parent = node.parentNode;
|
|
661
|
+
if (!parent)
|
|
662
|
+
return false;
|
|
663
|
+
let depth = 0;
|
|
664
|
+
let sib = parent.firstChild;
|
|
665
|
+
while (sib) {
|
|
666
|
+
if (sib === node)
|
|
667
|
+
return depth > 0;
|
|
668
|
+
if (sib.nodeType === Node.COMMENT_NODE) {
|
|
669
|
+
const value = sib.nodeValue ?? "";
|
|
670
|
+
if (value.startsWith(BF_SCOPE_COMMENT_PREFIX))
|
|
671
|
+
depth++;
|
|
672
|
+
else if (value.startsWith(BF_SCOPE_COMMENT_END_PREFIX) && depth > 0)
|
|
673
|
+
depth--;
|
|
674
|
+
}
|
|
675
|
+
sib = sib.nextSibling;
|
|
676
|
+
}
|
|
677
|
+
return false;
|
|
644
678
|
}
|
|
645
679
|
function isInCommentScopeRange(element, commentNode) {
|
|
646
680
|
const boundary = getCommentScopeBoundary(commentNode);
|
|
@@ -665,7 +699,8 @@ function find(scope, selector, ignoreScope) {
|
|
|
665
699
|
if (commentInfo) {
|
|
666
700
|
if (candidate.parentElement === commentInfo.commentNode.parentElement)
|
|
667
701
|
return candidate;
|
|
668
|
-
|
|
702
|
+
const nearestScope = candidate.closest(`[${BF_SCOPE}]`);
|
|
703
|
+
if (!nearestScope || !isInCommentScopeRange(nearestScope, commentInfo.commentNode))
|
|
669
704
|
return candidate;
|
|
670
705
|
} else {
|
|
671
706
|
if (belongsToScope(candidate, scope))
|
|
@@ -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;AAiLD;;;;;;;;;;GAUG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,OAAO,GAAG,IAAI,EACrB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,GAAG,IAAI,CAiChB;AAuBD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CA0BxE;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;AAmFD;;;;;;;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"}
|
|
@@ -1048,7 +1048,41 @@ function belongsToScope(element, scope) {
|
|
|
1048
1048
|
if (element.getAttribute(BF_SCOPE))
|
|
1049
1049
|
return false;
|
|
1050
1050
|
const nearestScope = element.closest(`[${BF_SCOPE}]`);
|
|
1051
|
-
|
|
1051
|
+
if (nearestScope !== scope)
|
|
1052
|
+
return false;
|
|
1053
|
+
return !isInsideNestedCommentScope(element, scope);
|
|
1054
|
+
}
|
|
1055
|
+
function isInsideNestedCommentScope(element, scope) {
|
|
1056
|
+
let current = element;
|
|
1057
|
+
while (current !== scope) {
|
|
1058
|
+
const parent = current.parentNode;
|
|
1059
|
+
if (!parent)
|
|
1060
|
+
return false;
|
|
1061
|
+
if (isTopLevelCommentScopeNode(current))
|
|
1062
|
+
return true;
|
|
1063
|
+
current = parent;
|
|
1064
|
+
}
|
|
1065
|
+
return false;
|
|
1066
|
+
}
|
|
1067
|
+
function isTopLevelCommentScopeNode(node) {
|
|
1068
|
+
const parent = node.parentNode;
|
|
1069
|
+
if (!parent)
|
|
1070
|
+
return false;
|
|
1071
|
+
let depth = 0;
|
|
1072
|
+
let sib = parent.firstChild;
|
|
1073
|
+
while (sib) {
|
|
1074
|
+
if (sib === node)
|
|
1075
|
+
return depth > 0;
|
|
1076
|
+
if (sib.nodeType === Node.COMMENT_NODE) {
|
|
1077
|
+
const value = sib.nodeValue ?? "";
|
|
1078
|
+
if (value.startsWith(BF_SCOPE_COMMENT_PREFIX))
|
|
1079
|
+
depth++;
|
|
1080
|
+
else if (value.startsWith(BF_SCOPE_COMMENT_END_PREFIX) && depth > 0)
|
|
1081
|
+
depth--;
|
|
1082
|
+
}
|
|
1083
|
+
sib = sib.nextSibling;
|
|
1084
|
+
}
|
|
1085
|
+
return false;
|
|
1052
1086
|
}
|
|
1053
1087
|
function isInCommentScopeRange(element, commentNode) {
|
|
1054
1088
|
const boundary = getCommentScopeBoundary(commentNode);
|
|
@@ -1073,7 +1107,8 @@ function find(scope, selector, ignoreScope) {
|
|
|
1073
1107
|
if (commentInfo) {
|
|
1074
1108
|
if (candidate.parentElement === commentInfo.commentNode.parentElement)
|
|
1075
1109
|
return candidate;
|
|
1076
|
-
|
|
1110
|
+
const nearestScope = candidate.closest(`[${BF_SCOPE}]`);
|
|
1111
|
+
if (!nearestScope || !isInCommentScopeRange(nearestScope, commentInfo.commentNode))
|
|
1077
1112
|
return candidate;
|
|
1078
1113
|
} else {
|
|
1079
1114
|
if (belongsToScope(candidate, scope))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/client",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.2",
|
|
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.2"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|
package/src/runtime/query.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { commentScopeRegistry, getCommentScopeBoundary } from './scope.ts'
|
|
10
10
|
import { hydratedScopes } from './hydration-state.ts'
|
|
11
|
-
import { BF_SCOPE, BF_SLOT, BF_PORTAL_OWNER, BF_PARENT_OWNED_PREFIX, BF_SCOPE_COMMENT_PREFIX } from '@barefootjs/shared'
|
|
11
|
+
import { BF_SCOPE, BF_SLOT, BF_PORTAL_OWNER, BF_PARENT_OWNED_PREFIX, BF_SCOPE_COMMENT_PREFIX, BF_SCOPE_COMMENT_END_PREFIX } from '@barefootjs/shared'
|
|
12
12
|
|
|
13
13
|
/** CSS attribute-value escape with a fallback for environments lacking CSS.escape. */
|
|
14
14
|
export const cssEscape: (s: string) => string =
|
|
@@ -222,7 +222,59 @@ function belongsToScope(element: Element, scope: Element): boolean {
|
|
|
222
222
|
|
|
223
223
|
// Check if nearest scope matches
|
|
224
224
|
const nearestScope = element.closest(`[${BF_SCOPE}]`)
|
|
225
|
-
|
|
225
|
+
if (nearestScope !== scope) return false
|
|
226
|
+
|
|
227
|
+
// A fragment-rooted child mounted between `element` and `scope` has no
|
|
228
|
+
// `bf-s` element of its own (#2302) — `closest()` walks straight past it
|
|
229
|
+
// to `scope`, so a slot search on `scope` can wrongly claim a descendant
|
|
230
|
+
// that actually belongs to that nested child's comment scope. Reject it.
|
|
231
|
+
return !isInsideNestedCommentScope(element, scope)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* True if some ancestor of `element` (strictly below `scope`) is a
|
|
236
|
+
* top-level node of a fragment-rooted child's `<!--bf-scope:...-->` range —
|
|
237
|
+
* i.e. `element` structurally belongs to a nested child component even
|
|
238
|
+
* though that child has no `bf-s`-attributed element for `.closest()` to
|
|
239
|
+
* stop at, and regardless of whether `commentScopeRegistry` has registered
|
|
240
|
+
* it yet (a parent's own slot lookups can run before its child-scope
|
|
241
|
+
* lookups register the child, #2302).
|
|
242
|
+
*/
|
|
243
|
+
function isInsideNestedCommentScope(element: Element, scope: Element): boolean {
|
|
244
|
+
let current: Node = element
|
|
245
|
+
while (current !== scope) {
|
|
246
|
+
const parent: Node | null = current.parentNode
|
|
247
|
+
if (!parent) return false
|
|
248
|
+
if (isTopLevelCommentScopeNode(current)) return true
|
|
249
|
+
current = parent
|
|
250
|
+
}
|
|
251
|
+
return false
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* True if `node` falls inside a `<!--bf-scope:...-->` … `<!--bf-/scope:...-->`
|
|
256
|
+
* range among its own siblings — i.e. `node` is (or is inside) a top-level
|
|
257
|
+
* element of a fragment-rooted child mounted as `node`'s sibling. Single
|
|
258
|
+
* left-to-right pass over the sibling list with a nesting depth counter, so
|
|
259
|
+
* a nested child's own begin/end pair doesn't prematurely close an outer
|
|
260
|
+
* one. Missing end markers (older SSR output) leave depth un-decremented,
|
|
261
|
+
* matching `getCommentScopeBoundary`'s legacy end-of-parent fallback.
|
|
262
|
+
*/
|
|
263
|
+
function isTopLevelCommentScopeNode(node: Node): boolean {
|
|
264
|
+
const parent = node.parentNode
|
|
265
|
+
if (!parent) return false
|
|
266
|
+
let depth = 0
|
|
267
|
+
let sib: Node | null = parent.firstChild
|
|
268
|
+
while (sib) {
|
|
269
|
+
if (sib === node) return depth > 0
|
|
270
|
+
if (sib.nodeType === Node.COMMENT_NODE) {
|
|
271
|
+
const value = (sib as Comment).nodeValue ?? ''
|
|
272
|
+
if (value.startsWith(BF_SCOPE_COMMENT_PREFIX)) depth++
|
|
273
|
+
else if (value.startsWith(BF_SCOPE_COMMENT_END_PREFIX) && depth > 0) depth--
|
|
274
|
+
}
|
|
275
|
+
sib = sib.nextSibling
|
|
276
|
+
}
|
|
277
|
+
return false
|
|
226
278
|
}
|
|
227
279
|
|
|
228
280
|
/**
|
|
@@ -271,10 +323,16 @@ export function find(
|
|
|
271
323
|
if (ignoreScope) return candidate
|
|
272
324
|
if (commentInfo) {
|
|
273
325
|
// Comment scope: top-level siblings in the comment range are always
|
|
274
|
-
// accepted (even if they have bf-s, like proxy elements).
|
|
275
|
-
//
|
|
326
|
+
// accepted (even if they have bf-s, like proxy elements). A descendant
|
|
327
|
+
// nested inside one of those siblings is accepted unless a *nested*
|
|
328
|
+
// child scope sits between it and this one — i.e. its nearest bf-s
|
|
329
|
+
// ancestor falls within this comment's own sibling range. An ancestor
|
|
330
|
+
// bf-s element outside that range doesn't disqualify the candidate:
|
|
331
|
+
// a fragment-root child mounted inside a normal parent island always
|
|
332
|
+
// has one, and `.closest()` alone can't tell the two apart (#2302).
|
|
276
333
|
if (candidate.parentElement === commentInfo.commentNode.parentElement) return candidate
|
|
277
|
-
|
|
334
|
+
const nearestScope = candidate.closest(`[${BF_SCOPE}]`)
|
|
335
|
+
if (!nearestScope || !isInCommentScopeRange(nearestScope, commentInfo.commentNode)) return candidate
|
|
278
336
|
} else {
|
|
279
337
|
if (belongsToScope(candidate, scope)) return candidate
|
|
280
338
|
}
|