@stacksjs/stx 0.2.110 → 0.2.112
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/cli.js +734 -643
- package/dist/expressions.js +6 -1
- package/dist/includes.js +8 -8
- package/dist/parser/directive-parser.d.ts +15 -0
- package/dist/parser/directive-parser.js +10 -0
- package/dist/pwa.js +466 -375
- package/dist/signal-processing.js +62 -56
- package/dist/signals.js +107 -13
- package/dist/ssg.js +555 -464
- package/dist/style-scoping.d.ts +0 -3
- package/dist/style-scoping.js +4 -3
- package/dist/variable-extractor.js +1 -1
- package/dist/web-components/css-scoping.js +33 -0
- package/package.json +5 -5
|
@@ -199,68 +199,74 @@ function isBalancedForTag(inner, tag) {
|
|
|
199
199
|
return !0;
|
|
200
200
|
}
|
|
201
201
|
export function convertSignalDirectivesToAttributes(template, context) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
continue;
|
|
218
|
-
const condition = output.substring(exprStart, i - 1).trim(), afterCondition = i;
|
|
219
|
-
let ifDepth = 1, endIdx = afterCondition;
|
|
220
|
-
const endifRegex = /@(if\s*\(|endif)/g;
|
|
221
|
-
endifRegex.lastIndex = afterCondition;
|
|
222
|
-
let endMatch;
|
|
223
|
-
while ((endMatch = endifRegex.exec(output)) !== null)
|
|
224
|
-
if (endMatch[1].startsWith("if"))
|
|
225
|
-
ifDepth++;
|
|
226
|
-
else if (endMatch[1] === "endif") {
|
|
227
|
-
ifDepth--;
|
|
228
|
-
if (ifDepth === 0) {
|
|
229
|
-
endIdx = endMatch.index + endMatch[0].length;
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
202
|
+
const signalNames = extractClientSignalNames(template);
|
|
203
|
+
function convert(input) {
|
|
204
|
+
let output = input;
|
|
205
|
+
const ifDirectiveStart = /@if\s*\(/g;
|
|
206
|
+
let match;
|
|
207
|
+
const replacements = [];
|
|
208
|
+
while ((match = ifDirectiveStart.exec(output)) !== null) {
|
|
209
|
+
const startIdx = match.index, exprStart = startIdx + match[0].length;
|
|
210
|
+
let depth = 1, i = exprStart;
|
|
211
|
+
while (i < output.length && depth > 0) {
|
|
212
|
+
if (output[i] === "(")
|
|
213
|
+
depth++;
|
|
214
|
+
else if (output[i] === ")")
|
|
215
|
+
depth--;
|
|
216
|
+
i++;
|
|
232
217
|
}
|
|
233
|
-
|
|
234
|
-
continue;
|
|
235
|
-
const content = output.substring(afterCondition, endIdx - 6).trim();
|
|
236
|
-
let replacement;
|
|
237
|
-
if (hasTopLevelElseBranch(content)) {
|
|
238
|
-
const parsed = findIfBlocks(output.substring(startIdx, endIdx));
|
|
239
|
-
if (parsed.length === 0)
|
|
218
|
+
if (depth !== 0)
|
|
240
219
|
continue;
|
|
241
|
-
const
|
|
242
|
-
|
|
220
|
+
const condition = output.substring(exprStart, i - 1).trim(), afterCondition = i;
|
|
221
|
+
let ifDepth = 1, endIdx = afterCondition;
|
|
222
|
+
const endifRegex = /@(if\s*\(|endif)/g;
|
|
223
|
+
endifRegex.lastIndex = afterCondition;
|
|
224
|
+
let endMatch;
|
|
225
|
+
while ((endMatch = endifRegex.exec(output)) !== null)
|
|
226
|
+
if (endMatch[1].startsWith("if"))
|
|
227
|
+
ifDepth++;
|
|
228
|
+
else if (endMatch[1] === "endif") {
|
|
229
|
+
ifDepth--;
|
|
230
|
+
if (ifDepth === 0) {
|
|
231
|
+
endIdx = endMatch.index + endMatch[0].length;
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (ifDepth !== 0)
|
|
243
236
|
continue;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
237
|
+
const content = output.substring(afterCondition, endIdx - 6).trim();
|
|
238
|
+
let replacement;
|
|
239
|
+
if (hasTopLevelElseBranch(content)) {
|
|
240
|
+
const parsed = findIfBlocks(output.substring(startIdx, endIdx));
|
|
241
|
+
if (parsed.length === 0)
|
|
242
|
+
continue;
|
|
243
|
+
const valueBranches = parsed[0].branches.filter((b) => b.type !== "else");
|
|
244
|
+
if (!(valueBranches.length > 0 && valueBranches.every((b) => conditionIsClientReactive(b.condition, signalNames, context))))
|
|
245
|
+
continue;
|
|
246
|
+
replacement = parsed[0].branches.map((branch) => {
|
|
247
|
+
const branchContent = convert(branch.content);
|
|
248
|
+
if (branch.type === "elseif")
|
|
249
|
+
return branchToAttrElement(branchContent, "@else-if", branch.condition ?? "");
|
|
250
|
+
if (branch.type === "else")
|
|
251
|
+
return branchToAttrElement(branchContent, "@else");
|
|
252
|
+
return branchToAttrElement(branchContent, "@if", branch.condition ?? "");
|
|
253
|
+
}).join(`
|
|
251
254
|
`);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
255
|
+
} else {
|
|
256
|
+
if (!conditionIsClientReactive(condition, signalNames, context))
|
|
257
|
+
continue;
|
|
258
|
+
replacement = branchToAttrElement(convert(content), "@if", condition);
|
|
259
|
+
}
|
|
260
|
+
replacements.push({ start: startIdx, end: endIdx, replacement });
|
|
261
|
+
ifDirectiveStart.lastIndex = endIdx;
|
|
256
262
|
}
|
|
257
|
-
replacements.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
263
|
+
for (let i = replacements.length - 1;i >= 0; i--) {
|
|
264
|
+
const { start, end, replacement } = replacements[i];
|
|
265
|
+
output = output.substring(0, start) + replacement + output.substring(end);
|
|
266
|
+
}
|
|
267
|
+
return output;
|
|
262
268
|
}
|
|
263
|
-
return
|
|
269
|
+
return convert(template);
|
|
264
270
|
}
|
|
265
271
|
function evalLiteralCondition(expr) {
|
|
266
272
|
const trimmed = expr.trim();
|
package/dist/signals.js
CHANGED
|
@@ -1579,7 +1579,7 @@ catch (e) {
|
|
|
1579
1579
|
if (el.nodeType === Node.TEXT_NODE) {
|
|
1580
1580
|
const text = el.textContent;
|
|
1581
1581
|
if (text && text.includes('{{')) {
|
|
1582
|
-
const parts = text.split(/(\\{\\{[
|
|
1582
|
+
const parts = text.split(/(\\{\\{[\\s\\S]+?\\}\\})/g);
|
|
1583
1583
|
if (parts.length > 1) {
|
|
1584
1584
|
const fragment = document.createDocumentFragment();
|
|
1585
1585
|
const parentEl = el.parentNode;
|
|
@@ -1588,7 +1588,7 @@ catch (e) {
|
|
|
1588
1588
|
// through nested @if/@for processing where componentScope may be restored
|
|
1589
1589
|
const capturedScope = { ...scope, ...(findElementScope(parentEl) || {}), ...globalHelpers };
|
|
1590
1590
|
parts.forEach(part => {
|
|
1591
|
-
const match = part.match(/^\\{\\{\\s*(
|
|
1591
|
+
const match = part.match(/^\\{\\{\\s*([\\s\\S]+?)\\s*\\}\\}$/);
|
|
1592
1592
|
if (match) {
|
|
1593
1593
|
const expr = match[1];
|
|
1594
1594
|
// Skip placeholder expressions like __TITLE__ (build-time placeholders)
|
|
@@ -2388,6 +2388,13 @@ else {
|
|
|
2388
2388
|
}
|
|
2389
2389
|
|
|
2390
2390
|
let currentElements = [];
|
|
2391
|
+
// One entry per list item, each holding EVERY node that item rendered.
|
|
2392
|
+
// currentElements stays flat for transition snapshots, but the keyed
|
|
2393
|
+
// diff below must pair a key with all of its nodes: a template row
|
|
2394
|
+
// routinely yields several (an element plus its surrounding text nodes),
|
|
2395
|
+
// and indexing a flat list by key position then paired the wrong node
|
|
2396
|
+
// with each key, leaving the list rotated after an update.
|
|
2397
|
+
let currentGroups = [];
|
|
2391
2398
|
let currentKeys = [];
|
|
2392
2399
|
let loadingElement = null;
|
|
2393
2400
|
let emptyElement = null;
|
|
@@ -2529,6 +2536,7 @@ catch (e) {
|
|
|
2529
2536
|
// Dispose scopes registered by items before they leave the DOM (#1727).
|
|
2530
2537
|
currentElements.forEach(e => { disposeSubtreeScopes(e); e.remove(); });
|
|
2531
2538
|
currentElements = [];
|
|
2539
|
+
currentGroups = [];
|
|
2532
2540
|
currentKeys = [];
|
|
2533
2541
|
showLoading();
|
|
2534
2542
|
return;
|
|
@@ -2577,6 +2585,7 @@ catch (e) {
|
|
|
2577
2585
|
// Dispose scopes registered by items before they leave the DOM (#1727).
|
|
2578
2586
|
currentElements.forEach(e => { disposeSubtreeScopes(e); e.remove(); });
|
|
2579
2587
|
currentElements = [];
|
|
2588
|
+
currentGroups = [];
|
|
2580
2589
|
currentKeys = [];
|
|
2581
2590
|
hideEmpty();
|
|
2582
2591
|
return;
|
|
@@ -2617,6 +2626,7 @@ catch (e) {
|
|
|
2617
2626
|
// Dispose scopes registered by items before they leave the DOM (#1727).
|
|
2618
2627
|
currentElements.forEach(e => { disposeSubtreeScopes(e); e.remove(); });
|
|
2619
2628
|
currentElements = [];
|
|
2629
|
+
currentGroups = [];
|
|
2620
2630
|
currentKeys = [];
|
|
2621
2631
|
if (emptyExpr) {
|
|
2622
2632
|
const emptyContent = evalLazy(emptyExpr);
|
|
@@ -2651,11 +2661,12 @@ catch (e) {
|
|
|
2651
2661
|
for (let i = 0; i < currentKeys.length; i++) {
|
|
2652
2662
|
const k = currentKeys[i];
|
|
2653
2663
|
if (!oldKeyMap.has(k)) oldKeyMap.set(k, []);
|
|
2654
|
-
oldKeyMap.get(k).push(
|
|
2664
|
+
oldKeyMap.get(k).push(currentGroups[i] || []);
|
|
2655
2665
|
}
|
|
2656
2666
|
|
|
2657
2667
|
// Build new element list, reusing existing DOM nodes by key
|
|
2658
2668
|
const newElements = [];
|
|
2669
|
+
const newGroups = [];
|
|
2659
2670
|
const usedKeys = new Set();
|
|
2660
2671
|
|
|
2661
2672
|
for (let i = 0; i < list.length; i++) {
|
|
@@ -2663,10 +2674,12 @@ catch (e) {
|
|
|
2663
2674
|
const existing = oldKeyMap.get(key);
|
|
2664
2675
|
|
|
2665
2676
|
if (existing && existing.length > 0 && !usedKeys.has(key)) {
|
|
2666
|
-
// Reuse
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2677
|
+
// Reuse this item's nodes \u2014 move the whole group into position, in
|
|
2678
|
+
// order, so a multi-node row stays contiguous and correctly ordered.
|
|
2679
|
+
const group = existing.shift();
|
|
2680
|
+
group.forEach(el => parent.insertBefore(el, placeholder));
|
|
2681
|
+
newElements.push(...group);
|
|
2682
|
+
newGroups.push(group);
|
|
2670
2683
|
usedKeys.add(key);
|
|
2671
2684
|
// Update the item signal so bindings re-evaluate with new data.
|
|
2672
2685
|
// This is the fix for #1669 \u2014 without this, reused elements show
|
|
@@ -2681,14 +2694,16 @@ catch (e) {
|
|
|
2681
2694
|
const elements = createItemElements(list[i], i, key);
|
|
2682
2695
|
elements.forEach(el => { parent.insertBefore(el, placeholder); if (tgReady) tgEnter(el, tgName); });
|
|
2683
2696
|
newElements.push(...elements);
|
|
2697
|
+
newGroups.push(elements);
|
|
2684
2698
|
}
|
|
2685
2699
|
}
|
|
2686
2700
|
|
|
2687
2701
|
// Remove old elements whose keys are no longer in the list.
|
|
2688
2702
|
// Dispose any scopes registered inside removed items before the
|
|
2689
2703
|
// remove() call (#1727).
|
|
2690
|
-
for (const [key,
|
|
2704
|
+
for (const [key, groups] of oldKeyMap) {
|
|
2691
2705
|
if (!usedKeys.has(key)) {
|
|
2706
|
+
const elements = groups.flat();
|
|
2692
2707
|
// In a transition group, run the leave animation and let it remove the
|
|
2693
2708
|
// node; otherwise remove immediately. Scopes are disposed up-front
|
|
2694
2709
|
// either way (their destroy hooks shouldn't wait on a CSS transition).
|
|
@@ -2698,6 +2713,7 @@ catch (e) {
|
|
|
2698
2713
|
}
|
|
2699
2714
|
|
|
2700
2715
|
currentElements = newElements;
|
|
2716
|
+
currentGroups = newGroups;
|
|
2701
2717
|
currentKeys = newKeys;
|
|
2702
2718
|
|
|
2703
2719
|
// \u2500\u2500 <TransitionGroup> play (#1742) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
@@ -2775,6 +2791,18 @@ catch (e) {
|
|
|
2775
2791
|
b.placeholder = document.createComment('stx-if-chain');
|
|
2776
2792
|
parent.insertBefore(b.placeholder, b.el);
|
|
2777
2793
|
b.el.removeAttribute(b.attr);
|
|
2794
|
+
// A <template> branch (the wrapper convertSignalDirectivesToAttributes
|
|
2795
|
+
// emits for a multi-child / text branch) is INERT \u2014 inserting the element
|
|
2796
|
+
// renders nothing, its content lives in a document fragment. Clone that
|
|
2797
|
+
// content ONCE into a stable node set we toggle in and out, exactly as
|
|
2798
|
+
// bindIf/bindFor already do for template elements. An element branch is
|
|
2799
|
+
// its own single node. Without this, a multi-element @else / @else-if
|
|
2800
|
+
// branch rendered blank the moment the markup was well-formed enough to
|
|
2801
|
+
// survive as a real <template> (the #1784 markup fix). See #1784.
|
|
2802
|
+
b.isTemplate = b.el.tagName === 'TEMPLATE';
|
|
2803
|
+
b.nodes = b.isTemplate
|
|
2804
|
+
? Array.prototype.slice.call(b.el.content.cloneNode(true).childNodes)
|
|
2805
|
+
: [b.el];
|
|
2778
2806
|
b.el.remove();
|
|
2779
2807
|
b.childrenProcessed = false;
|
|
2780
2808
|
});
|
|
@@ -2858,13 +2886,16 @@ catch (e2) {
|
|
|
2858
2886
|
// components under reactive conditionals (#1737). Permanent disposal is
|
|
2859
2887
|
// still handled by bindFor (item removal) and cleanupContainer (SPA nav).
|
|
2860
2888
|
if (currentIdx !== -1) {
|
|
2861
|
-
chain[currentIdx].
|
|
2889
|
+
chain[currentIdx].nodes.forEach(function (n) { if (n.parentNode) n.parentNode.removeChild(n); });
|
|
2862
2890
|
}
|
|
2863
2891
|
|
|
2864
2892
|
// Insert + process the newly-picked branch.
|
|
2865
2893
|
if (pickedIdx !== -1) {
|
|
2866
2894
|
var pick = chain[pickedIdx];
|
|
2867
|
-
|
|
2895
|
+
// Insert this branch's node(s) before the placeholder's next sibling.
|
|
2896
|
+
// The anchor is captured once so the nodes stack in source order.
|
|
2897
|
+
var anchor = pick.placeholder.nextSibling;
|
|
2898
|
+
pick.nodes.forEach(function (n) { pick.placeholder.parentNode.insertBefore(n, anchor); });
|
|
2868
2899
|
pick.el.__stx_shown_at = performance.now();
|
|
2869
2900
|
if (!pick.childrenProcessed) {
|
|
2870
2901
|
pick.childrenProcessed = true;
|
|
@@ -2874,9 +2905,12 @@ catch (e2) {
|
|
|
2874
2905
|
(function (branch) {
|
|
2875
2906
|
setTimeout(function () {
|
|
2876
2907
|
var childScope = { ...capturedComponentScope, ...(branch.capturedElementScope || {}), ...globalHelpers };
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2908
|
+
branch.nodes.forEach(function (n) {
|
|
2909
|
+
if (n.nodeType !== 1) return; // whitespace/text between template children
|
|
2910
|
+
processElement(n, childScope);
|
|
2911
|
+
n.removeAttribute('x-cloak');
|
|
2912
|
+
n.querySelectorAll('[x-cloak]').forEach(function (c) { c.removeAttribute('x-cloak'); });
|
|
2913
|
+
});
|
|
2880
2914
|
}, 0);
|
|
2881
2915
|
})(pick);
|
|
2882
2916
|
}
|
|
@@ -4847,6 +4881,10 @@ else {
|
|
|
4847
4881
|
processedScopes.add(el);
|
|
4848
4882
|
|
|
4849
4883
|
const scopeVars = window.stx._scopes && window.stx._scopes[scopeId];
|
|
4884
|
+
// Record the element this scope is bound to so cleanupContainer can tell a
|
|
4885
|
+
// dead registry entry (element replaced by an SPA swap) from a live one.
|
|
4886
|
+
// See sweepOrphanedScopes / #1775.
|
|
4887
|
+
if (scopeVars) scopeVars.__el = el;
|
|
4850
4888
|
|
|
4851
4889
|
// Deferred island (#1746): its setup script (type="stx/island") hasn't run
|
|
4852
4890
|
// yet, so the scope isn't registered. Arm the hydration trigger anyway \u2014
|
|
@@ -5006,6 +5044,54 @@ catch (e) {
|
|
|
5006
5044
|
}
|
|
5007
5045
|
}
|
|
5008
5046
|
|
|
5047
|
+
// Reclaim registry entries whose element is gone from the document.
|
|
5048
|
+
//
|
|
5049
|
+
// disposeSubtreeScopes only deletes scopes found UNDER the cleanup container,
|
|
5050
|
+
// so two shapes leaked forever across SPA navigation (#1775): components
|
|
5051
|
+
// rendered outside the swap container (an @include in the layout, above
|
|
5052
|
+
// <main>), and elements already detached by the time cleanup ran its
|
|
5053
|
+
// querySelectorAll. Each round-trip re-ran the include scripts under fresh
|
|
5054
|
+
// scope ids while the previous ids stayed in window.stx._scopes \u2014 ~4 orphans
|
|
5055
|
+
// per hop, unbounded, each retaining that scope's vars, signals and closures.
|
|
5056
|
+
//
|
|
5057
|
+
// The sweep is deliberately CONSERVATIVE \u2014 an over-eager delete is the #1737
|
|
5058
|
+
// failure (a scope removed from the registry cannot be recreated: its setup
|
|
5059
|
+
// IIFE ran once at page load), which is strictly worse than a leak. An entry
|
|
5060
|
+
// is dropped only when all three hold:
|
|
5061
|
+
// 1. the runtime actually bound it to an element (__el recorded),
|
|
5062
|
+
// 2. that element is no longer connected to the document, and
|
|
5063
|
+
// 3. neither it nor any ancestor is retained by a live conditional.
|
|
5064
|
+
// Entries with no __el (e.g. a scope whose element still sits inside untouched
|
|
5065
|
+
// <template> content, never inserted) are left alone \u2014 we can't prove they're
|
|
5066
|
+
// dead, and a later clone re-uses that registration.
|
|
5067
|
+
function sweepOrphanedScopes() {
|
|
5068
|
+
if (!window.stx || !window.stx._scopes) return;
|
|
5069
|
+
var scopes = window.stx._scopes;
|
|
5070
|
+
for (var id in scopes) {
|
|
5071
|
+
if (!Object.prototype.hasOwnProperty.call(scopes, id)) continue;
|
|
5072
|
+
var entry = scopes[id];
|
|
5073
|
+
if (!entry) continue;
|
|
5074
|
+
var el = entry.__el;
|
|
5075
|
+
if (!el || el.isConnected) continue;
|
|
5076
|
+
// Detached but RETAINED: :if toggles keep their element (bindIf re-inserts
|
|
5077
|
+
// the SAME node) and :if/:else chains keep their branches. Parent links
|
|
5078
|
+
// inside a detached subtree stay intact, so walking up from the scope
|
|
5079
|
+
// element still finds the conditional that owns it.
|
|
5080
|
+
var retained = false;
|
|
5081
|
+
for (var p = el; p; p = p.parentNode) {
|
|
5082
|
+
if (p.__stx_if_bound || p.__stx_chain_member) { retained = true; break; }
|
|
5083
|
+
}
|
|
5084
|
+
if (retained) continue;
|
|
5085
|
+
if (entry.__destroyCallbacks && Array.isArray(entry.__destroyCallbacks)) {
|
|
5086
|
+
for (var k = 0; k < entry.__destroyCallbacks.length; k++) {
|
|
5087
|
+
try { entry.__destroyCallbacks[k](); }
|
|
5088
|
+
catch (e) { console.warn('[stx] scope destroy error:', e); }
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
delete scopes[id];
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5009
5095
|
// ==========================================================================
|
|
5010
5096
|
// Container Cleanup (for SPA navigation)
|
|
5011
5097
|
// ==========================================================================
|
|
@@ -5073,6 +5159,11 @@ catch (e) { console.warn('[stx] destroy hook error:', e); }
|
|
|
5073
5159
|
// through disposeSubtreeScopes so the same walk runs for SPA
|
|
5074
5160
|
// navigation and for :if/:for-driven unmount (see #1727).
|
|
5075
5161
|
disposeSubtreeScopes(container);
|
|
5162
|
+
|
|
5163
|
+
// 4. Reclaim entries the container walk can't see \u2014 components rendered
|
|
5164
|
+
// outside the swap container, or already detached before step 3 ran its
|
|
5165
|
+
// querySelectorAll. Without this the registry grew every navigation (#1775).
|
|
5166
|
+
sweepOrphanedScopes();
|
|
5076
5167
|
}
|
|
5077
5168
|
|
|
5078
5169
|
// Re-initialize components after SPA content swap.
|
|
@@ -5168,6 +5259,9 @@ catch (e) { console.warn('[stx] destroy callback error:', e); }
|
|
|
5168
5259
|
document.body.querySelectorAll('[data-stx-scope]').forEach(function(el) {
|
|
5169
5260
|
var scopeId = el.getAttribute('data-stx-scope');
|
|
5170
5261
|
var scopeVars = window.stx._scopes && window.stx._scopes[scopeId];
|
|
5262
|
+
// Record the bound element for the orphan sweep (#1775) \u2014 see the
|
|
5263
|
+
// DOMContentLoaded walk above for the rationale.
|
|
5264
|
+
if (scopeVars) scopeVars.__el = el;
|
|
5171
5265
|
// Deferred island reached via SPA navigation (#1746): its setup script is
|
|
5172
5266
|
// inert (type="stx/island"), so the scope isn't registered yet. Arm the
|
|
5173
5267
|
// hydration trigger (deferHydration) instead of skipping it \u2014 mirrors the
|