@livetemplate/client 0.8.37 → 0.8.39
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/README.md +11 -1
- package/dist/dom/event-delegation.d.ts +1 -1
- package/dist/dom/event-delegation.d.ts.map +1 -1
- package/dist/dom/event-delegation.js +79 -0
- package/dist/dom/event-delegation.js.map +1 -1
- package/dist/livetemplate-client.browser.js +5 -5
- package/dist/livetemplate-client.browser.js.map +4 -4
- package/dist/livetemplate-client.d.ts +12 -0
- package/dist/livetemplate-client.d.ts.map +1 -1
- package/dist/livetemplate-client.js +199 -24
- package/dist/livetemplate-client.js.map +1 -1
- package/dist/state/range-dom-applier.d.ts +124 -0
- package/dist/state/range-dom-applier.d.ts.map +1 -0
- package/dist/state/range-dom-applier.js +510 -0
- package/dist/state/range-dom-applier.js.map +1 -0
- package/dist/state/tree-renderer.d.ts +32 -1
- package/dist/state/tree-renderer.d.ts.map +1 -1
- package/dist/state/tree-renderer.js +81 -54
- package/dist/state/tree-renderer.js.map +1 -1
- package/dist/tests/event-delegation.test.js +354 -0
- package/dist/tests/event-delegation.test.js.map +1 -1
- package/dist/tests/range-dom-applier.test.d.ts +2 -0
- package/dist/tests/range-dom-applier.test.d.ts.map +1 -0
- package/dist/tests/range-dom-applier.test.js +581 -0
- package/dist/tests/range-dom-applier.test.js.map +1 -0
- package/dist/tests/tree-renderer.test.js +61 -0
- package/dist/tests/tree-renderer.test.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range-dom-applier.d.ts","sourceRoot":"","sources":["../../state/range-dom-applier.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAShD,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AACjE,eAAO,MAAM,kBAAkB,2BAA2B,CAAC;AAE3D,KAAK,YAAY,GAAG,CAClB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,CAAC,EAAE,MAAM,KACf,MAAM,CAAC;AAEZ,KAAK,eAAe,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAC/D,KAAK,WAAW,GAAG,CAAC,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;AACzC,KAAK,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,YAAY,CAAC;IACzB,oBAAoB,EAAE,eAAe,CAAC;IACtC;;;;;;;;OAQG;IACH,UAAU,EAAE,YAAY,CAAC;IACzB;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAGd,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,cAAc,CAA8B;gBAEvB,GAAG,EAAE,sBAAsB;IAExD,UAAU,IAAI,IAAI;IAIlB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIvC;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,GAAG,IAAI;IAsBjB;;;;OAIG;IACH,gBAAgB,CACd,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,GAAG,EACnB,SAAS,EAAE,MAAM,GAChB,cAAc;IAuDjB;;;;;OAKG;IACH,KAAK,CACH,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,eAAe,EAC3B,eAAe,CAAC,EAAE,GAAG,GACpB,OAAO,GAAG,IAAI;IAsHjB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAqBtC,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,cAAc;IA2DtB,OAAO,CAAC,gBAAgB;IAyBxB,OAAO,CAAC,WAAW;IAiBnB,OAAO,CAAC,YAAY;IAiBpB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY;IA2CpB,OAAO,CAAC,cAAc;IAiBtB;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,kBAAkB;IAa1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,iBAAiB;CAS1B"}
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.RangeDomApplier = exports.TARGETED_SKIP_ATTR = exports.TARGETED_APPLIED_ATTR = void 0;
|
|
7
|
+
const morphdom_1 = __importDefault(require("morphdom"));
|
|
8
|
+
const KEY_ATTRIBUTES = ["data-key", "data-lvt-key"];
|
|
9
|
+
// Pre-compile attribute-presence regexes once at module load — these were
|
|
10
|
+
// previously rebuilt on every staticsContainKeyAttribute call (per static
|
|
11
|
+
// segment, per attribute) which showed up in profiling on initial render.
|
|
12
|
+
const KEY_ATTR_REGEXES = KEY_ATTRIBUTES.map((attr) => new RegExp(`(?:^|[\\s<])${attr}\\s*=`));
|
|
13
|
+
exports.TARGETED_APPLIED_ATTR = "data-lvt-targeted-applied";
|
|
14
|
+
exports.TARGETED_SKIP_ATTR = "data-lvt-targeted-skip";
|
|
15
|
+
/**
|
|
16
|
+
* Applies range diff ops directly to the live DOM, bypassing full HTML
|
|
17
|
+
* reconstruction + morphdom diff. Designed to handle the common case where
|
|
18
|
+
* a 10k-row range receives a single-row mutation; the targeted path turns
|
|
19
|
+
* what would be a 5+ second morphdom walk into a sub-millisecond DOM op.
|
|
20
|
+
*
|
|
21
|
+
* The applier is opt-in per range: `canApplyTargeted` checks that the
|
|
22
|
+
* range has data-key emission, no nested-range items, and a resolvable
|
|
23
|
+
* container element. When any check fails, the caller falls back to the
|
|
24
|
+
* existing applyUpdate → reconstructFromTree → morphdom path.
|
|
25
|
+
*/
|
|
26
|
+
class RangeDomApplier {
|
|
27
|
+
constructor(ctx) {
|
|
28
|
+
this.ctx = ctx;
|
|
29
|
+
this.containerCache = new Map();
|
|
30
|
+
}
|
|
31
|
+
invalidate() {
|
|
32
|
+
this.containerCache.clear();
|
|
33
|
+
}
|
|
34
|
+
invalidatePath(rangePath) {
|
|
35
|
+
this.containerCache.delete(rangePath);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Locate the live container element for a range path. The container is
|
|
39
|
+
* the parent element of items rendered with data-key. Cached per path;
|
|
40
|
+
* cache invalidated automatically when a cached element becomes detached.
|
|
41
|
+
*
|
|
42
|
+
* Resolution order:
|
|
43
|
+
* 1. Cached container (if still connected to the wrapper).
|
|
44
|
+
* 2. `wrapper.querySelector('[data-key="anyKnownItemKey"]').parentElement`.
|
|
45
|
+
*
|
|
46
|
+
* The original implementation also fell back to an unscoped
|
|
47
|
+
* `wrapper.querySelector('[data-key]')` walk, but that could return a
|
|
48
|
+
* container belonging to a *different* keyed range when the wrapper has
|
|
49
|
+
* more than one — silently mutating the wrong DOM subtree on subsequent
|
|
50
|
+
* ops. We now prefer to fail closed (return null → caller falls back to
|
|
51
|
+
* full rebuild) over mutating an unrelated container.
|
|
52
|
+
*/
|
|
53
|
+
findContainer(wrapper, rangePath, anyKnownItemKey) {
|
|
54
|
+
const cached = this.containerCache.get(rangePath);
|
|
55
|
+
if (cached && cached.isConnected && wrapper.contains(cached)) {
|
|
56
|
+
return cached;
|
|
57
|
+
}
|
|
58
|
+
if (cached) {
|
|
59
|
+
this.containerCache.delete(rangePath);
|
|
60
|
+
}
|
|
61
|
+
if (anyKnownItemKey === undefined) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const sample = this.findItemByKey(wrapper, anyKnownItemKey);
|
|
65
|
+
if (!sample || !sample.parentElement) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const container = sample.parentElement;
|
|
69
|
+
this.containerCache.set(rangePath, container);
|
|
70
|
+
return container;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Decide whether a range update can take the targeted-apply path.
|
|
74
|
+
* Returns the resolved container in the success case so the caller
|
|
75
|
+
* can pass it to `apply` without re-resolving.
|
|
76
|
+
*/
|
|
77
|
+
canApplyTargeted(wrapper, rangeStructure, rangePath) {
|
|
78
|
+
if (!rangeStructure || typeof rangeStructure !== "object") {
|
|
79
|
+
return { ok: false, reason: "no range structure" };
|
|
80
|
+
}
|
|
81
|
+
if (!Array.isArray(rangeStructure.s) || rangeStructure.s.length === 0) {
|
|
82
|
+
return { ok: false, reason: "no statics" };
|
|
83
|
+
}
|
|
84
|
+
const allStatics = [rangeStructure.s];
|
|
85
|
+
if (rangeStructure.sm && typeof rangeStructure.sm === "object") {
|
|
86
|
+
for (const sm of Object.values(rangeStructure.sm)) {
|
|
87
|
+
if (Array.isArray(sm)) {
|
|
88
|
+
allStatics.push(sm);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const hasKeyInStatics = allStatics.some((arr) => this.staticsContainKeyAttribute(arr));
|
|
93
|
+
if (!hasKeyInStatics) {
|
|
94
|
+
return { ok: false, reason: "no data-key attribute in statics" };
|
|
95
|
+
}
|
|
96
|
+
const items = rangeStructure.d;
|
|
97
|
+
if (Array.isArray(items)) {
|
|
98
|
+
for (const item of items) {
|
|
99
|
+
if (this.itemHasNestedRange(item)) {
|
|
100
|
+
return { ok: false, reason: "nested-range item" };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const sampleKey = this.extractItemKey(items?.[0], rangeStructure);
|
|
105
|
+
const container = this.findContainer(wrapper, rangePath, sampleKey);
|
|
106
|
+
if (!container) {
|
|
107
|
+
return { ok: false, reason: "container not found in DOM" };
|
|
108
|
+
}
|
|
109
|
+
// Walk up from container through wrapper (inclusive) — if any element
|
|
110
|
+
// on the path is lvt-ignore'd, the targeted-apply path would mutate
|
|
111
|
+
// DOM inside an ignored subtree while morphdom would have skipped it,
|
|
112
|
+
// violating the lvt-ignore contract.
|
|
113
|
+
let cur = container;
|
|
114
|
+
while (cur) {
|
|
115
|
+
if (cur.hasAttribute("lvt-ignore")) {
|
|
116
|
+
return { ok: false, reason: "lvt-ignore ancestor" };
|
|
117
|
+
}
|
|
118
|
+
if (cur === wrapper)
|
|
119
|
+
break;
|
|
120
|
+
cur = cur.parentElement;
|
|
121
|
+
}
|
|
122
|
+
return { ok: true, container, containerKey: sampleKey };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Apply a single targeted op to the live DOM. Returns the affected
|
|
126
|
+
* container element so the caller can mark it for the morphdom skip
|
|
127
|
+
* mechanism. Returns null if the op could not be applied (caller
|
|
128
|
+
* should fall back to full-rebuild for the next render).
|
|
129
|
+
*/
|
|
130
|
+
apply(wrapper, targetedOp, morphdomOptions) {
|
|
131
|
+
const { rangePath, ops, statics, staticsMap } = targetedOp;
|
|
132
|
+
const sampleKey = this.firstKnownKey(ops);
|
|
133
|
+
const container = this.findContainer(wrapper, rangePath, sampleKey);
|
|
134
|
+
if (!container) {
|
|
135
|
+
this.ctx.logger.debug(`[RangeDomApplier] container not found for range ${rangePath}; cannot apply`);
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
let allOpsSucceeded = true;
|
|
139
|
+
for (const op of ops) {
|
|
140
|
+
if (!Array.isArray(op) || op.length < 1)
|
|
141
|
+
continue;
|
|
142
|
+
const opType = op[0];
|
|
143
|
+
try {
|
|
144
|
+
let opOK = true;
|
|
145
|
+
switch (opType) {
|
|
146
|
+
case "r":
|
|
147
|
+
opOK = this.applyRemove(container, op[1]);
|
|
148
|
+
break;
|
|
149
|
+
case "u":
|
|
150
|
+
opOK = this.applyUpdateRow(container, op[1], statics, staticsMap, rangePath, morphdomOptions);
|
|
151
|
+
break;
|
|
152
|
+
case "i":
|
|
153
|
+
opOK = this.applyInsertAfter(container, op[1], op[2], statics, staticsMap, rangePath);
|
|
154
|
+
break;
|
|
155
|
+
case "a":
|
|
156
|
+
opOK = this.applyAppend(container, op[1], statics, staticsMap, rangePath);
|
|
157
|
+
break;
|
|
158
|
+
case "p":
|
|
159
|
+
opOK = this.applyPrepend(container, op[1], statics, staticsMap, rangePath);
|
|
160
|
+
break;
|
|
161
|
+
case "o":
|
|
162
|
+
opOK = this.applyReorder(container, op[1]);
|
|
163
|
+
break;
|
|
164
|
+
default:
|
|
165
|
+
// Forward-compat: an unrecognised op type means we can't
|
|
166
|
+
// reason about the DOM mutation. Treat as failure so the
|
|
167
|
+
// caller falls back to a full morphdom rebuild from
|
|
168
|
+
// treeState (which the server-emitted unknown op type
|
|
169
|
+
// presumably already mutated correctly).
|
|
170
|
+
this.ctx.logger.warn(`[RangeDomApplier] unknown op type ${opType}; falling back`);
|
|
171
|
+
opOK = false;
|
|
172
|
+
}
|
|
173
|
+
if (!opOK) {
|
|
174
|
+
allOpsSucceeded = false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
this.ctx.logger.error(`[RangeDomApplier] op ${opType} failed for range ${rangePath}`, err);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// If any per-op method silently no-op'd because of stale state
|
|
183
|
+
// (e.g. `u` for a row that's no longer in the DOM, `i` with a
|
|
184
|
+
// missing anchor), we MUST signal failure so the caller falls back
|
|
185
|
+
// to a full rebuild — otherwise the live DOM stays out of sync with
|
|
186
|
+
// treeState and morphdom would skip the subtree (TARGETED_APPLIED
|
|
187
|
+
// marker tells it to).
|
|
188
|
+
//
|
|
189
|
+
// Note: earlier ops in this batch that succeeded are NOT rolled back.
|
|
190
|
+
// No rollback is needed because `treeState` was already mutated to
|
|
191
|
+
// its complete post-op state by `applyDifferentialOpsToRange` BEFORE
|
|
192
|
+
// this method ran. The caller's fallback path re-renders from
|
|
193
|
+
// `treeState.renderState()` and runs morphdom over the full HTML —
|
|
194
|
+
// morphdom reconciles whatever partial DOM mutations we made toward
|
|
195
|
+
// the authoritative end state.
|
|
196
|
+
if (!allOpsSucceeded) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
// Observability hook: increment a global counter so E2E tests can
|
|
200
|
+
// assert the targeted-apply path was actually taken (vs silently
|
|
201
|
+
// hitting the fallback). Opt-in: tests must initialize the property
|
|
202
|
+
// first (e.g. `window.__lvtTargetedHits = 0`); production never sets
|
|
203
|
+
// it so the increment is skipped and we don't pollute the window
|
|
204
|
+
// object outside of test environments.
|
|
205
|
+
if (typeof window !== "undefined" &&
|
|
206
|
+
"__lvtTargetedHits" in window) {
|
|
207
|
+
window.__lvtTargetedHits++;
|
|
208
|
+
}
|
|
209
|
+
return container;
|
|
210
|
+
}
|
|
211
|
+
cleanupMarkers(wrapper) {
|
|
212
|
+
const applied = wrapper.querySelectorAll(`[${exports.TARGETED_APPLIED_ATTR}]`);
|
|
213
|
+
applied.forEach((el) => el.removeAttribute(exports.TARGETED_APPLIED_ATTR));
|
|
214
|
+
if (wrapper.hasAttribute(exports.TARGETED_APPLIED_ATTR)) {
|
|
215
|
+
wrapper.removeAttribute(exports.TARGETED_APPLIED_ATTR);
|
|
216
|
+
}
|
|
217
|
+
const skip = wrapper.querySelectorAll(`[${exports.TARGETED_SKIP_ATTR}]`);
|
|
218
|
+
skip.forEach((el) => el.removeAttribute(exports.TARGETED_SKIP_ATTR));
|
|
219
|
+
if (wrapper.hasAttribute(exports.TARGETED_SKIP_ATTR)) {
|
|
220
|
+
wrapper.removeAttribute(exports.TARGETED_SKIP_ATTR);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// --- per-op implementations -----------------------------------------------
|
|
224
|
+
//
|
|
225
|
+
// Each per-op method returns `boolean`:
|
|
226
|
+
// true → the live DOM is now consistent with the new treeState
|
|
227
|
+
// false → silent no-op (e.g. row not found, item state unavailable);
|
|
228
|
+
// the caller should invalidate the targeted-apply marker and
|
|
229
|
+
// fall back to a full rebuild
|
|
230
|
+
applyRemove(container, key) {
|
|
231
|
+
const row = this.findItemByKey(container, key);
|
|
232
|
+
if (!row) {
|
|
233
|
+
// r is idempotent: if the row is already gone, treeState's post-op
|
|
234
|
+
// view (also without the row) matches the DOM. No fallback needed.
|
|
235
|
+
this.ctx.logger.debug(`[RangeDomApplier] r: row with key ${key} not found (idempotent no-op)`);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
this.fireHookOnSubtree(row, "lvt-destroyed");
|
|
239
|
+
row.remove();
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
applyUpdateRow(container, key, statics, staticsMap, rangePath, morphdomOptions) {
|
|
243
|
+
const row = this.findItemByKey(container, key);
|
|
244
|
+
if (!row) {
|
|
245
|
+
this.ctx.logger.debug(`[RangeDomApplier] u: row with key ${key} not found in DOM; falling back`);
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
const itemIdx = this.indexOfChild(container, row);
|
|
249
|
+
const item = this.lookupCurrentItem(rangePath, key);
|
|
250
|
+
if (!item) {
|
|
251
|
+
this.ctx.logger.debug(`[RangeDomApplier] u: item state for key ${key} not available; falling back`);
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
const newHtml = this.ctx.renderItem(item, itemIdx, statics, staticsMap, rangePath);
|
|
255
|
+
const newRow = this.parseSingleRow(newHtml);
|
|
256
|
+
if (!newRow) {
|
|
257
|
+
this.ctx.logger.warn(`[RangeDomApplier] u: failed to parse rendered row HTML; falling back`);
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
if (morphdomOptions) {
|
|
261
|
+
// Override childrenOnly: the main morphdom call uses childrenOnly:true
|
|
262
|
+
// because it's diffing the wrapper's children. For a single-row morph
|
|
263
|
+
// we MUST diff the row element itself too (its attributes — class,
|
|
264
|
+
// style, aria, etc. — are produced by statics+dynamics and may have
|
|
265
|
+
// changed). Reuse the same callbacks for behavioral consistency.
|
|
266
|
+
(0, morphdom_1.default)(row, newRow, { ...morphdomOptions, childrenOnly: false });
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// No morphdom options provided — fall back to wholesale replacement.
|
|
270
|
+
// morphdom's onNodeAdded / onBeforeNodeDiscarded callbacks would
|
|
271
|
+
// normally fire lvt-mounted/lvt-destroyed hooks for us; here we have
|
|
272
|
+
// to fire them manually on both sides AND notify the host so its
|
|
273
|
+
// nodesAddedThisRender counter sees the new subtree (otherwise the
|
|
274
|
+
// post-render directive scans would skip wiring listeners on it).
|
|
275
|
+
this.fireHookOnSubtree(row, "lvt-destroyed");
|
|
276
|
+
row.replaceWith(newRow);
|
|
277
|
+
this.ctx.onNodeAdded?.(newRow);
|
|
278
|
+
this.fireHookOnSubtree(newRow, "lvt-mounted");
|
|
279
|
+
}
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
applyInsertAfter(container, afterKey, items, statics, staticsMap, rangePath) {
|
|
283
|
+
const anchor = this.findItemByKey(container, afterKey);
|
|
284
|
+
if (!anchor) {
|
|
285
|
+
this.ctx.logger.debug(`[RangeDomApplier] i: anchor key ${afterKey} not found; falling back`);
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
return this.renderItemsAtomic(items, statics, staticsMap, rangePath, this.indexOfChild(container, anchor) + 1, (frag) => container.insertBefore(frag, anchor.nextSibling));
|
|
289
|
+
}
|
|
290
|
+
applyAppend(container, items, statics, staticsMap, rangePath) {
|
|
291
|
+
return this.renderItemsAtomic(items, statics, staticsMap, rangePath, container.children.length, (frag) => container.appendChild(frag));
|
|
292
|
+
}
|
|
293
|
+
applyPrepend(container, items, statics, staticsMap, rangePath) {
|
|
294
|
+
return this.renderItemsAtomic(items, statics, staticsMap, rangePath, 0, (frag) => container.insertBefore(frag, container.firstChild));
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Render N items into a scratch DocumentFragment, splicing them into the
|
|
298
|
+
* live DOM only if ALL renders succeeded. On partial failure no DOM
|
|
299
|
+
* mutation happens and the caller falls back to a full rebuild — this
|
|
300
|
+
* avoids `lvt-mounted` firing on items that morphdom is then about to
|
|
301
|
+
* re-add (which would double-fire the hook).
|
|
302
|
+
*/
|
|
303
|
+
renderItemsAtomic(items, statics, staticsMap, rangePath, baseIdx, splice) {
|
|
304
|
+
const list = Array.isArray(items) ? items : [items];
|
|
305
|
+
const scratch = document.createDocumentFragment();
|
|
306
|
+
const newRows = [];
|
|
307
|
+
for (let i = 0; i < list.length; i++) {
|
|
308
|
+
const newRow = this.renderAndParse(list[i], baseIdx + i, statics, staticsMap, rangePath);
|
|
309
|
+
if (!newRow) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
scratch.appendChild(newRow);
|
|
313
|
+
newRows.push(newRow);
|
|
314
|
+
}
|
|
315
|
+
splice(scratch);
|
|
316
|
+
for (const row of newRows) {
|
|
317
|
+
this.ctx.onNodeAdded?.(row);
|
|
318
|
+
this.fireHookOnSubtree(row, "lvt-mounted");
|
|
319
|
+
}
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Reorder existing children to match `newKeyOrder`. Protocol assumption:
|
|
324
|
+
* the server emits the *full* new key order (mirrors the assumption in
|
|
325
|
+
* `applyDifferentialOpsToRange`'s "o" case in tree-renderer). When the
|
|
326
|
+
* new order is shorter than the current child set, we treat the missing
|
|
327
|
+
* keys as removals and fire `lvt-destroyed` on each dropped subtree
|
|
328
|
+
* (so user teardown — timer cancellation, observer disconnect, etc. —
|
|
329
|
+
* still runs) plus log a warning surfacing the protocol mismatch.
|
|
330
|
+
*/
|
|
331
|
+
applyReorder(container, newKeyOrder) {
|
|
332
|
+
if (!Array.isArray(newKeyOrder))
|
|
333
|
+
return false;
|
|
334
|
+
const byKey = new Map();
|
|
335
|
+
Array.from(container.children).forEach((child) => {
|
|
336
|
+
for (const attr of KEY_ATTRIBUTES) {
|
|
337
|
+
const k = child.getAttribute(attr);
|
|
338
|
+
if (k !== null) {
|
|
339
|
+
byKey.set(k, child);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
const fragment = document.createDocumentFragment();
|
|
345
|
+
const newKeySet = new Set(newKeyOrder);
|
|
346
|
+
for (const key of newKeyOrder) {
|
|
347
|
+
const el = byKey.get(key);
|
|
348
|
+
if (el) {
|
|
349
|
+
fragment.appendChild(el);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Fire lvt-destroyed on children that aren't in the new order. The
|
|
353
|
+
// protocol normally sends the FULL key order, but if a partial reorder
|
|
354
|
+
// ever lands here, user-defined teardown (timer cancellation, observer
|
|
355
|
+
// disconnect, etc.) must still run.
|
|
356
|
+
if (newKeySet.size < byKey.size) {
|
|
357
|
+
this.ctx.logger.warn(`[RangeDomApplier] o: newKeyOrder (${newKeySet.size}) shorter than existing children (${byKey.size}); ${byKey.size - newKeySet.size} children will be dropped`);
|
|
358
|
+
for (const [k, el] of byKey) {
|
|
359
|
+
if (!newKeySet.has(k)) {
|
|
360
|
+
this.fireHookOnSubtree(el, "lvt-destroyed");
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
container.replaceChildren(fragment);
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
// --- helpers --------------------------------------------------------------
|
|
368
|
+
renderAndParse(item, itemIdx, statics, staticsMap, rangePath) {
|
|
369
|
+
const html = this.ctx.renderItem(item, itemIdx, statics, staticsMap, rangePath);
|
|
370
|
+
return this.parseSingleRow(html);
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Parse a string of HTML containing a single root element and return it.
|
|
374
|
+
* Uses <template> so orphan table-cell content (`<tr>`, `<td>`, etc.)
|
|
375
|
+
* is tolerated by the parser.
|
|
376
|
+
*/
|
|
377
|
+
parseSingleRow(html) {
|
|
378
|
+
const template = document.createElement("template");
|
|
379
|
+
template.innerHTML = html.trim();
|
|
380
|
+
const first = template.content.firstElementChild;
|
|
381
|
+
return first ?? null;
|
|
382
|
+
}
|
|
383
|
+
findItemByKey(scope, key) {
|
|
384
|
+
let escaped;
|
|
385
|
+
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
386
|
+
escaped = CSS.escape(key);
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
// CSS.escape polyfill is incomplete: only handles `"` and `\`.
|
|
390
|
+
// Keys containing other CSS special chars ([], (), :, ., #, >, ~,
|
|
391
|
+
// whitespace, etc.) would produce a malformed selector and miss the
|
|
392
|
+
// match. Warn so it's visible in test logs rather than silently
|
|
393
|
+
// returning null and looking like the row simply doesn't exist.
|
|
394
|
+
if (/[\[\]():.#>~+*=^$|! \t\n\r]/.test(key)) {
|
|
395
|
+
this.ctx.logger.warn(`[RangeDomApplier] CSS.escape unavailable; key "${key}" contains characters that need escaping. Lookup may miss the row.`);
|
|
396
|
+
}
|
|
397
|
+
escaped = key.replace(/(["\\])/g, "\\$1");
|
|
398
|
+
}
|
|
399
|
+
for (const attr of KEY_ATTRIBUTES) {
|
|
400
|
+
const el = scope.querySelector(`[${attr}="${escaped}"]`);
|
|
401
|
+
if (el)
|
|
402
|
+
return el;
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
indexOfChild(container, child) {
|
|
407
|
+
let i = 0;
|
|
408
|
+
let cur = container.firstElementChild;
|
|
409
|
+
while (cur) {
|
|
410
|
+
if (cur === child)
|
|
411
|
+
return i;
|
|
412
|
+
i++;
|
|
413
|
+
cur = cur.nextElementSibling;
|
|
414
|
+
}
|
|
415
|
+
return -1;
|
|
416
|
+
}
|
|
417
|
+
firstKnownKey(ops) {
|
|
418
|
+
for (const op of ops) {
|
|
419
|
+
if (!Array.isArray(op) || op.length < 2)
|
|
420
|
+
continue;
|
|
421
|
+
const t = op[0];
|
|
422
|
+
if (t === "r" || t === "u" || t === "i") {
|
|
423
|
+
return typeof op[1] === "string" ? op[1] : undefined;
|
|
424
|
+
}
|
|
425
|
+
if (t === "o" && Array.isArray(op[1]) && op[1].length > 0) {
|
|
426
|
+
return typeof op[1][0] === "string" ? op[1][0] : undefined;
|
|
427
|
+
}
|
|
428
|
+
// For a/p ops there's no DOM-resident key in op[1], but the new
|
|
429
|
+
// items themselves carry `_k`. Sample the first to give
|
|
430
|
+
// findContainer something to walk to (rare cold-cache case;
|
|
431
|
+
// canApplyTargeted normally warms the cache via existing.d[0]
|
|
432
|
+
// before apply runs, so in practice the cache hit covers this).
|
|
433
|
+
if (t === "a" || t === "p") {
|
|
434
|
+
const items = Array.isArray(op[1]) ? op[1] : [op[1]];
|
|
435
|
+
for (const it of items) {
|
|
436
|
+
if (it && typeof it === "object" && it._k !== undefined) {
|
|
437
|
+
return String(it._k);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
staticsContainKeyAttribute(statics) {
|
|
445
|
+
// Reduces false positives vs. plain `s.includes('data-key=')`:
|
|
446
|
+
// - requires word boundary before the attr name (excludes longer
|
|
447
|
+
// attribute names like `data-keystone=`, `my-data-key=`)
|
|
448
|
+
// - requires `=` to follow optional whitespace (excludes
|
|
449
|
+
// `data-key-something`)
|
|
450
|
+
//
|
|
451
|
+
// Known limitation: cannot distinguish a real attribute from
|
|
452
|
+
// `data-key=` appearing inside a quoted attribute value (e.g.
|
|
453
|
+
// `title='see data-key=foo'`). Such cases would still match. False
|
|
454
|
+
// positives are safe — `findContainer` just fails to locate by key,
|
|
455
|
+
// canApplyTargeted falls back to full rebuild — but they cost a
|
|
456
|
+
// render of wasted work. Real-world templates with `data-key` in
|
|
457
|
+
// attribute values are vanishingly rare.
|
|
458
|
+
for (const s of statics) {
|
|
459
|
+
if (typeof s !== "string")
|
|
460
|
+
continue;
|
|
461
|
+
for (const re of KEY_ATTR_REGEXES) {
|
|
462
|
+
if (re.test(s)) {
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
itemHasNestedRange(item) {
|
|
470
|
+
if (!item || typeof item !== "object")
|
|
471
|
+
return false;
|
|
472
|
+
for (const [key, val] of Object.entries(item)) {
|
|
473
|
+
if (key.startsWith("_"))
|
|
474
|
+
continue;
|
|
475
|
+
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
476
|
+
const v = val;
|
|
477
|
+
if (Array.isArray(v.d) && Array.isArray(v.s))
|
|
478
|
+
return true;
|
|
479
|
+
if (this.itemHasNestedRange(v))
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
extractItemKey(item, rangeStructure) {
|
|
486
|
+
if (!item || typeof item !== "object")
|
|
487
|
+
return undefined;
|
|
488
|
+
if (item._k !== undefined)
|
|
489
|
+
return String(item._k);
|
|
490
|
+
const idKey = rangeStructure?.m?.idKey;
|
|
491
|
+
if (idKey && item[idKey] !== undefined)
|
|
492
|
+
return String(item[idKey]);
|
|
493
|
+
return undefined;
|
|
494
|
+
}
|
|
495
|
+
lookupCurrentItem(rangePath, key) {
|
|
496
|
+
// O(N) over range.d via the context callback (linear scan in
|
|
497
|
+
// livetemplate-client.ts). Bounded cost per `u` op: one walk per
|
|
498
|
+
// updated row per render. At N=10k that's ~50µs in JS — acceptable.
|
|
499
|
+
return this.ctx.itemLookup(rangePath, key);
|
|
500
|
+
}
|
|
501
|
+
fireHookOnSubtree(root, hookName) {
|
|
502
|
+
if (root.hasAttribute(hookName)) {
|
|
503
|
+
this.ctx.executeLifecycleHook(root, hookName);
|
|
504
|
+
}
|
|
505
|
+
const descendants = root.querySelectorAll(`[${hookName}]`);
|
|
506
|
+
descendants.forEach((el) => this.ctx.executeLifecycleHook(el, hookName));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
exports.RangeDomApplier = RangeDomApplier;
|
|
510
|
+
//# sourceMappingURL=range-dom-applier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"range-dom-applier.js","sourceRoot":"","sources":["../../state/range-dom-applier.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import type { TreeNode, UpdateResult } from "../types";
|
|
2
2
|
import type { Logger } from "../utils/logger";
|
|
3
|
+
/**
|
|
4
|
+
* Optional context for `applyUpdate` that opts into per-op targeted DOM
|
|
5
|
+
* mutation. When `canApplyTargeted` returns true for a top-level diff-op
|
|
6
|
+
* key, applyUpdate mutates treeState in place (no deepClone) and emits
|
|
7
|
+
* a `TargetedRangeOp` in the result. The caller is then responsible for
|
|
8
|
+
* applying the op directly to the live DOM (typically via RangeDomApplier).
|
|
9
|
+
*
|
|
10
|
+
* The corresponding range subtree is replaced in `result.html` with a
|
|
11
|
+
* `<!--lvt-targeted-skip:${rangePath}-->` placeholder so that morphdom
|
|
12
|
+
* can be told to short-circuit that subtree.
|
|
13
|
+
*/
|
|
14
|
+
export interface ApplyUpdateOptions {
|
|
15
|
+
canApplyTargeted?: (rangeStructure: any, rangePath: string) => boolean;
|
|
16
|
+
}
|
|
3
17
|
/**
|
|
4
18
|
* Handles tree state management and HTML reconstruction logic for LiveTemplate.
|
|
5
19
|
*/
|
|
@@ -9,10 +23,17 @@ export declare class TreeRenderer {
|
|
|
9
23
|
private rangeState;
|
|
10
24
|
private rangeIdKeys;
|
|
11
25
|
constructor(logger: Logger);
|
|
12
|
-
applyUpdate(update: TreeNode): UpdateResult;
|
|
26
|
+
applyUpdate(update: TreeNode, opts?: ApplyUpdateOptions): UpdateResult;
|
|
13
27
|
reset(): void;
|
|
14
28
|
getTreeState(): TreeNode;
|
|
15
29
|
getStaticStructure(): string[] | null;
|
|
30
|
+
/**
|
|
31
|
+
* Re-render the current treeState as full HTML, with no targeted-apply
|
|
32
|
+
* skip placeholders. Used by `LiveTemplateClient.updateDOM` as a fallback
|
|
33
|
+
* when one or more targeted-apply DOM mutations failed: the treeState is
|
|
34
|
+
* authoritative, so a full rebuild + morphdom pass restores consistency.
|
|
35
|
+
*/
|
|
36
|
+
renderState(): string;
|
|
16
37
|
private deepMergeTreeNodes;
|
|
17
38
|
/**
|
|
18
39
|
* Applies differential operations to the provided range structure in-place.
|
|
@@ -23,6 +44,16 @@ export declare class TreeRenderer {
|
|
|
23
44
|
private reconstructFromTree;
|
|
24
45
|
private renderValue;
|
|
25
46
|
private renderRangeStructure;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a single range item to HTML by interleaving its dynamic slots
|
|
49
|
+
* with the range's statics. Honors per-item statics (`_sk` lookup in
|
|
50
|
+
* `staticsMap`) when present.
|
|
51
|
+
*
|
|
52
|
+
* Used by `renderRangeStructure` and `renderItemsWithStatics` for full
|
|
53
|
+
* range rendering, and by `range-dom-applier` to render a single new
|
|
54
|
+
* or updated item for targeted DOM mutations.
|
|
55
|
+
*/
|
|
56
|
+
renderRangeItem(item: any, itemIdx: number, statics: string[], staticsMap?: Record<string, string[]>, statePath?: string): string;
|
|
26
57
|
private applyDifferentialOperations;
|
|
27
58
|
private getCurrentRangeStructure;
|
|
28
59
|
private renderItemsWithStatics;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-renderer.d.ts","sourceRoot":"","sources":["../../state/tree-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"tree-renderer.d.ts","sourceRoot":"","sources":["../../state/tree-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,QAAQ,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CACxE;AAoHD;;GAEG;AACH,qBAAa,YAAY;IAKX,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJnC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,WAAW,CAA8B;gBAEpB,MAAM,EAAE,MAAM;IAE3C,WAAW,CACT,MAAM,EAAE,QAAQ,EAChB,IAAI,CAAC,EAAE,kBAAkB,GACxB,YAAY;IA0Ef,KAAK,IAAI,IAAI;IAMb,YAAY,IAAI,QAAQ;IAIxB,kBAAkB,IAAI,MAAM,EAAE,GAAG,IAAI;IAIrC;;;;;OAKG;IACH,WAAW,IAAI,MAAM;IAIrB,OAAO,CAAC,kBAAkB;IAmF1B;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAoKnC,OAAO,CAAC,mBAAmB;IA4C3B,OAAO,CAAC,WAAW;IAgGnB,OAAO,CAAC,oBAAoB;IAqC5B;;;;;;;;OAQG;IACH,eAAe,CACb,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACrC,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM;IA8BT,OAAO,CAAC,2BAA2B;IAgJnC,OAAO,CAAC,wBAAwB;IAqBhC,OAAO,CAAC,sBAAsB;IAwB9B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,kBAAkB;IAW1B;;;;;OAKG;IACH,OAAO,CAAC,cAAc;CAGvB"}
|