@microsoft/fast-element 2.8.5 → 2.9.1
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/CHANGELOG.json +31 -1
- package/CHANGELOG.md +18 -2
- package/dist/dts/components/hydration.d.ts +12 -1
- package/dist/esm/components/hydration.js +42 -2
- package/dist/esm/debug.js +3 -0
- package/dist/esm/hydration/target-builder.js +23 -9
- package/dist/fast-element.debug.js +67 -11
- package/dist/fast-element.debug.min.js +2 -2
- package/dist/fast-element.js +64 -11
- package/dist/fast-element.min.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,37 @@
|
|
|
2
2
|
"name": "@microsoft/fast-element",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "Tue,
|
|
5
|
+
"date": "Tue, 16 Dec 2025 21:27:19 GMT",
|
|
6
|
+
"version": "2.9.1",
|
|
7
|
+
"tag": "@microsoft/fast-element_v2.9.1",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "863023+radium-v@users.noreply.github.com",
|
|
12
|
+
"package": "@microsoft/fast-element",
|
|
13
|
+
"commit": "2c8de46fbde0440593f559cd2ddd8d7c6248f68d",
|
|
14
|
+
"comment": "fix: correct hydration marker indexes for templates with host bindings"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Mon, 08 Dec 2025 19:47:51 GMT",
|
|
21
|
+
"version": "2.9.0",
|
|
22
|
+
"tag": "@microsoft/fast-element_v2.9.0",
|
|
23
|
+
"comments": {
|
|
24
|
+
"minor": [
|
|
25
|
+
{
|
|
26
|
+
"author": "863023+radium-v@users.noreply.github.com",
|
|
27
|
+
"package": "@microsoft/fast-element",
|
|
28
|
+
"commit": "1e21fa3cac5f940f639bf76311af291e1a368da1",
|
|
29
|
+
"comment": "feat: add support for compact attribute binding markers"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Tue, 02 Dec 2025 21:46:59 GMT",
|
|
6
36
|
"version": "2.8.5",
|
|
7
37
|
"tag": "@microsoft/fast-element_v2.8.5",
|
|
8
38
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Change Log - @microsoft/fast-element
|
|
2
2
|
|
|
3
|
-
<!-- This log was last generated on Tue,
|
|
3
|
+
<!-- This log was last generated on Tue, 16 Dec 2025 21:27:19 GMT and should not be manually modified. -->
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 2.9.1
|
|
8
|
+
|
|
9
|
+
Tue, 16 Dec 2025 21:27:19 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- fix: correct hydration marker indexes for templates with host bindings (863023+radium-v@users.noreply.github.com)
|
|
14
|
+
|
|
15
|
+
## 2.9.0
|
|
16
|
+
|
|
17
|
+
Mon, 08 Dec 2025 19:47:51 GMT
|
|
18
|
+
|
|
19
|
+
### Minor changes
|
|
20
|
+
|
|
21
|
+
- feat: add support for compact attribute binding markers (863023+radium-v@users.noreply.github.com)
|
|
22
|
+
|
|
7
23
|
## 2.8.5
|
|
8
24
|
|
|
9
|
-
Tue, 02 Dec 2025 21:46:
|
|
25
|
+
Tue, 02 Dec 2025 21:46:59 GMT
|
|
10
26
|
|
|
11
27
|
### Patches
|
|
12
28
|
|
|
@@ -8,6 +8,7 @@ import type { HydrationView } from "../templating/view.js";
|
|
|
8
8
|
*/
|
|
9
9
|
export declare const HydrationMarkup: Readonly<{
|
|
10
10
|
attributeMarkerName: "data-fe-b";
|
|
11
|
+
compactAttributeMarkerName: "data-fe-c";
|
|
11
12
|
attributeBindingSeparator: " ";
|
|
12
13
|
contentBindingStartMarker(index: number, uniqueId: string): string;
|
|
13
14
|
contentBindingEndMarker(index: number, uniqueId: string): string;
|
|
@@ -22,15 +23,25 @@ export declare const HydrationMarkup: Readonly<{
|
|
|
22
23
|
/**
|
|
23
24
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
24
25
|
* attributes for the element, or null if no factories were found.
|
|
26
|
+
*
|
|
27
|
+
* This method parses the space-separated format: `data-fe-b="0 1 2"`.
|
|
25
28
|
*/
|
|
26
29
|
parseAttributeBinding(node: Element): null | number[];
|
|
27
30
|
/**
|
|
28
31
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
29
32
|
* attributes for the element, or null if no factories were found.
|
|
30
33
|
*
|
|
31
|
-
*
|
|
34
|
+
* This method parses the enumerated format: `data-fe-b-0`, `data-fe-b-1`, `data-fe-b-2`.
|
|
35
|
+
* This is an alternative format that uses separate attributes for each binding index.
|
|
32
36
|
*/
|
|
33
37
|
parseEnumeratedAttributeBinding(node: Element): null | number[];
|
|
38
|
+
/**
|
|
39
|
+
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
40
|
+
* attributes for the element, or null if no factories were found.
|
|
41
|
+
*
|
|
42
|
+
* This method parses the compact format: `data-fe-c-{index}-{count}`.
|
|
43
|
+
*/
|
|
44
|
+
parseCompactAttributeBinding(node: Element): null | number[];
|
|
34
45
|
/**
|
|
35
46
|
* Parses the ViewBehaviorFactory index from string data. Returns
|
|
36
47
|
* the binding index or null if the index cannot be retrieved.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FAST } from "../platform.js";
|
|
1
2
|
const bindingStartMarker = /fe-b\$\$start\$\$(\d+)\$\$(.+)\$\$fe-b/;
|
|
2
3
|
const bindingEndMarker = /fe-b\$\$end\$\$(\d+)\$\$(.+)\$\$fe-b/;
|
|
3
4
|
const repeatViewStartMarker = /fe-repeat\$\$start\$\$(\d+)\$\$fe-repeat/;
|
|
@@ -13,6 +14,7 @@ function isComment(node) {
|
|
|
13
14
|
*/
|
|
14
15
|
export const HydrationMarkup = Object.freeze({
|
|
15
16
|
attributeMarkerName: "data-fe-b",
|
|
17
|
+
compactAttributeMarkerName: "data-fe-c",
|
|
16
18
|
attributeBindingSeparator: " ",
|
|
17
19
|
contentBindingStartMarker(index, uniqueId) {
|
|
18
20
|
return `fe-b$$start$$${index}$$${uniqueId}$$fe-b`;
|
|
@@ -47,6 +49,8 @@ export const HydrationMarkup = Object.freeze({
|
|
|
47
49
|
/**
|
|
48
50
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
49
51
|
* attributes for the element, or null if no factories were found.
|
|
52
|
+
*
|
|
53
|
+
* This method parses the space-separated format: `data-fe-b="0 1 2"`.
|
|
50
54
|
*/
|
|
51
55
|
parseAttributeBinding(node) {
|
|
52
56
|
const attr = node.getAttribute(this.attributeMarkerName);
|
|
@@ -58,7 +62,8 @@ export const HydrationMarkup = Object.freeze({
|
|
|
58
62
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
59
63
|
* attributes for the element, or null if no factories were found.
|
|
60
64
|
*
|
|
61
|
-
*
|
|
65
|
+
* This method parses the enumerated format: `data-fe-b-0`, `data-fe-b-1`, `data-fe-b-2`.
|
|
66
|
+
* This is an alternative format that uses separate attributes for each binding index.
|
|
62
67
|
*/
|
|
63
68
|
parseEnumeratedAttributeBinding(node) {
|
|
64
69
|
const attrs = [];
|
|
@@ -71,12 +76,47 @@ export const HydrationMarkup = Object.freeze({
|
|
|
71
76
|
attrs.push(count);
|
|
72
77
|
}
|
|
73
78
|
else {
|
|
74
|
-
throw
|
|
79
|
+
throw FAST.error(1601 /* invalidAttributeMarkerName */, {
|
|
80
|
+
name: attr,
|
|
81
|
+
expectedFormat: `${prefix}<number>`,
|
|
82
|
+
});
|
|
75
83
|
}
|
|
76
84
|
}
|
|
77
85
|
}
|
|
78
86
|
return attrs.length === 0 ? null : attrs;
|
|
79
87
|
},
|
|
88
|
+
/**
|
|
89
|
+
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
90
|
+
* attributes for the element, or null if no factories were found.
|
|
91
|
+
*
|
|
92
|
+
* This method parses the compact format: `data-fe-c-{index}-{count}`.
|
|
93
|
+
*/
|
|
94
|
+
parseCompactAttributeBinding(node) {
|
|
95
|
+
const prefix = `${this.compactAttributeMarkerName}-`;
|
|
96
|
+
const attrName = node.getAttributeNames().find(name => name.startsWith(prefix));
|
|
97
|
+
if (!attrName) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const suffix = attrName.slice(prefix.length);
|
|
101
|
+
const parts = suffix.split("-");
|
|
102
|
+
const startIndex = parseInt(parts[0], 10);
|
|
103
|
+
const count = parseInt(parts[1], 10);
|
|
104
|
+
if (parts.length !== 2 ||
|
|
105
|
+
Number.isNaN(startIndex) ||
|
|
106
|
+
Number.isNaN(count) ||
|
|
107
|
+
startIndex < 0 ||
|
|
108
|
+
count < 1) {
|
|
109
|
+
throw FAST.error(1604 /* invalidCompactAttributeMarkerName */, {
|
|
110
|
+
name: attrName,
|
|
111
|
+
expectedFormat: `${this.compactAttributeMarkerName}-{index}-{count}`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
const indexes = [];
|
|
115
|
+
for (let i = 0; i < count; i++) {
|
|
116
|
+
indexes.push(startIndex + i);
|
|
117
|
+
}
|
|
118
|
+
return indexes;
|
|
119
|
+
},
|
|
80
120
|
/**
|
|
81
121
|
* Parses the ViewBehaviorFactory index from string data. Returns
|
|
82
122
|
* the binding index or null if the index cannot be retrieved.
|
package/dist/esm/debug.js
CHANGED
|
@@ -35,6 +35,9 @@ const debugMessages = {
|
|
|
35
35
|
[1512 /* noDefaultResolver */]: "'${key}' not registered. Did you forget to add @singleton()?",
|
|
36
36
|
[1513 /* cyclicDependency */]: "Cyclic dependency found '${name}'.",
|
|
37
37
|
[1514 /* connectUpdateRequiresController */]: "Injected properties that are updated on changes to DOM connectivity require the target object to be an instance of FASTElement.",
|
|
38
|
+
[1601 /* invalidAttributeMarkerName */]: "Invalid attribute marker name: ${name}. Expected format is ${expectedFormat}.",
|
|
39
|
+
[1602 /* invalidCompactAttributeMarkerValues */]: "Invalid compact attribute marker values in ${markerName}. Both index and count must be positive integers.",
|
|
40
|
+
[1604 /* invalidCompactAttributeMarkerName */]: "Invalid compact attribute marker name: ${name}. Expected format is ${expectedFormat}.",
|
|
38
41
|
};
|
|
39
42
|
const allPlaceholders = /(\$\{\w+?})/g;
|
|
40
43
|
const placeholder = /\$\{(\w+?)}/g;
|
|
@@ -52,6 +52,7 @@ function isShadowRoot(node) {
|
|
|
52
52
|
export function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
53
53
|
const range = createRangeForNodes(firstNode, lastNode);
|
|
54
54
|
const treeRoot = range.commonAncestorContainer;
|
|
55
|
+
const hydrationIndexOffset = getHydrationIndexOffset(factories);
|
|
55
56
|
const walker = document.createTreeWalker(treeRoot, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_COMMENT + NodeFilter.SHOW_TEXT, {
|
|
56
57
|
acceptNode(node) {
|
|
57
58
|
return range.comparePoint(node, 0) === 0
|
|
@@ -65,11 +66,11 @@ export function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
|
65
66
|
while (node !== null) {
|
|
66
67
|
switch (node.nodeType) {
|
|
67
68
|
case Node.ELEMENT_NODE: {
|
|
68
|
-
targetElement(node, factories, targets);
|
|
69
|
+
targetElement(node, factories, targets, hydrationIndexOffset);
|
|
69
70
|
break;
|
|
70
71
|
}
|
|
71
72
|
case Node.COMMENT_NODE: {
|
|
72
|
-
targetComment(node, walker, factories, targets, boundaries);
|
|
73
|
+
targetComment(node, walker, factories, targets, boundaries, hydrationIndexOffset);
|
|
73
74
|
break;
|
|
74
75
|
}
|
|
75
76
|
}
|
|
@@ -78,21 +79,22 @@ export function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
|
78
79
|
range.detach();
|
|
79
80
|
return { targets, boundaries };
|
|
80
81
|
}
|
|
81
|
-
function targetElement(node, factories, targets) {
|
|
82
|
-
var _a;
|
|
82
|
+
function targetElement(node, factories, targets, hydrationIndexOffset) {
|
|
83
|
+
var _a, _b;
|
|
83
84
|
// Check for attributes and map any factories.
|
|
84
|
-
const attrFactoryIds = (_a = HydrationMarkup.parseAttributeBinding(node)) !== null && _a !== void 0 ? _a : HydrationMarkup.parseEnumeratedAttributeBinding(node);
|
|
85
|
+
const attrFactoryIds = (_b = (_a = HydrationMarkup.parseAttributeBinding(node)) !== null && _a !== void 0 ? _a : HydrationMarkup.parseEnumeratedAttributeBinding(node)) !== null && _b !== void 0 ? _b : HydrationMarkup.parseCompactAttributeBinding(node);
|
|
85
86
|
if (attrFactoryIds !== null) {
|
|
86
87
|
for (const id of attrFactoryIds) {
|
|
87
|
-
|
|
88
|
+
const factory = factories[id + hydrationIndexOffset];
|
|
89
|
+
if (!factory) {
|
|
88
90
|
throw new HydrationTargetElementError(`HydrationView was unable to successfully target factory on ${node.nodeName} inside ${node.getRootNode().host.nodeName}. This likely indicates a template mismatch between SSR rendering and hydration.`, factories, node);
|
|
89
91
|
}
|
|
90
|
-
targetFactory(
|
|
92
|
+
targetFactory(factory, node, targets);
|
|
91
93
|
}
|
|
92
94
|
node.removeAttribute(HydrationMarkup.attributeMarkerName);
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
|
-
function targetComment(node, walker, factories, targets, boundaries) {
|
|
97
|
+
function targetComment(node, walker, factories, targets, boundaries, hydrationIndexOffset) {
|
|
96
98
|
if (HydrationMarkup.isElementBoundaryStartMarker(node)) {
|
|
97
99
|
skipToElementBoundaryEndMarker(node, walker);
|
|
98
100
|
return;
|
|
@@ -103,7 +105,7 @@ function targetComment(node, walker, factories, targets, boundaries) {
|
|
|
103
105
|
return;
|
|
104
106
|
}
|
|
105
107
|
const [index, id] = parsed;
|
|
106
|
-
const factory = factories[index];
|
|
108
|
+
const factory = factories[index + hydrationIndexOffset];
|
|
107
109
|
const nodes = [];
|
|
108
110
|
let current = walker.nextSibling();
|
|
109
111
|
node.data = "";
|
|
@@ -167,6 +169,18 @@ function skipToElementBoundaryEndMarker(node, walker) {
|
|
|
167
169
|
current = walker.nextSibling();
|
|
168
170
|
}
|
|
169
171
|
}
|
|
172
|
+
function getHydrationIndexOffset(factories) {
|
|
173
|
+
let offset = 0;
|
|
174
|
+
for (let i = 0, ii = factories.length; i < ii; ++i) {
|
|
175
|
+
if (factories[i].targetNodeId === "h") {
|
|
176
|
+
offset++;
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return offset;
|
|
183
|
+
}
|
|
170
184
|
export function targetFactory(factory, node, targets) {
|
|
171
185
|
if (factory.targetNodeId === undefined) {
|
|
172
186
|
// Dev error, this shouldn't ever be thrown
|
|
@@ -35,6 +35,9 @@ const debugMessages = {
|
|
|
35
35
|
[1512 /* noDefaultResolver */]: "'${key}' not registered. Did you forget to add @singleton()?",
|
|
36
36
|
[1513 /* cyclicDependency */]: "Cyclic dependency found '${name}'.",
|
|
37
37
|
[1514 /* connectUpdateRequiresController */]: "Injected properties that are updated on changes to DOM connectivity require the target object to be an instance of FASTElement.",
|
|
38
|
+
[1601 /* invalidAttributeMarkerName */]: "Invalid attribute marker name: ${name}. Expected format is ${expectedFormat}.",
|
|
39
|
+
[1602 /* invalidCompactAttributeMarkerValues */]: "Invalid compact attribute marker values in ${markerName}. Both index and count must be positive integers.",
|
|
40
|
+
[1604 /* invalidCompactAttributeMarkerName */]: "Invalid compact attribute marker name: ${name}. Expected format is ${expectedFormat}.",
|
|
38
41
|
};
|
|
39
42
|
const allPlaceholders = /(\$\{\w+?})/g;
|
|
40
43
|
const placeholder = /\$\{(\w+?)}/g;
|
|
@@ -2333,6 +2336,7 @@ function isComment$1(node) {
|
|
|
2333
2336
|
*/
|
|
2334
2337
|
const HydrationMarkup = Object.freeze({
|
|
2335
2338
|
attributeMarkerName: "data-fe-b",
|
|
2339
|
+
compactAttributeMarkerName: "data-fe-c",
|
|
2336
2340
|
attributeBindingSeparator: " ",
|
|
2337
2341
|
contentBindingStartMarker(index, uniqueId) {
|
|
2338
2342
|
return `fe-b$$start$$${index}$$${uniqueId}$$fe-b`;
|
|
@@ -2367,6 +2371,8 @@ const HydrationMarkup = Object.freeze({
|
|
|
2367
2371
|
/**
|
|
2368
2372
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
2369
2373
|
* attributes for the element, or null if no factories were found.
|
|
2374
|
+
*
|
|
2375
|
+
* This method parses the space-separated format: `data-fe-b="0 1 2"`.
|
|
2370
2376
|
*/
|
|
2371
2377
|
parseAttributeBinding(node) {
|
|
2372
2378
|
const attr = node.getAttribute(this.attributeMarkerName);
|
|
@@ -2378,7 +2384,8 @@ const HydrationMarkup = Object.freeze({
|
|
|
2378
2384
|
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
2379
2385
|
* attributes for the element, or null if no factories were found.
|
|
2380
2386
|
*
|
|
2381
|
-
*
|
|
2387
|
+
* This method parses the enumerated format: `data-fe-b-0`, `data-fe-b-1`, `data-fe-b-2`.
|
|
2388
|
+
* This is an alternative format that uses separate attributes for each binding index.
|
|
2382
2389
|
*/
|
|
2383
2390
|
parseEnumeratedAttributeBinding(node) {
|
|
2384
2391
|
const attrs = [];
|
|
@@ -2391,12 +2398,47 @@ const HydrationMarkup = Object.freeze({
|
|
|
2391
2398
|
attrs.push(count);
|
|
2392
2399
|
}
|
|
2393
2400
|
else {
|
|
2394
|
-
throw
|
|
2401
|
+
throw FAST.error(1601 /* invalidAttributeMarkerName */, {
|
|
2402
|
+
name: attr,
|
|
2403
|
+
expectedFormat: `${prefix}<number>`,
|
|
2404
|
+
});
|
|
2395
2405
|
}
|
|
2396
2406
|
}
|
|
2397
2407
|
}
|
|
2398
2408
|
return attrs.length === 0 ? null : attrs;
|
|
2399
2409
|
},
|
|
2410
|
+
/**
|
|
2411
|
+
* Returns the indexes of the ViewBehaviorFactories affecting
|
|
2412
|
+
* attributes for the element, or null if no factories were found.
|
|
2413
|
+
*
|
|
2414
|
+
* This method parses the compact format: `data-fe-c-{index}-{count}`.
|
|
2415
|
+
*/
|
|
2416
|
+
parseCompactAttributeBinding(node) {
|
|
2417
|
+
const prefix = `${this.compactAttributeMarkerName}-`;
|
|
2418
|
+
const attrName = node.getAttributeNames().find(name => name.startsWith(prefix));
|
|
2419
|
+
if (!attrName) {
|
|
2420
|
+
return null;
|
|
2421
|
+
}
|
|
2422
|
+
const suffix = attrName.slice(prefix.length);
|
|
2423
|
+
const parts = suffix.split("-");
|
|
2424
|
+
const startIndex = parseInt(parts[0], 10);
|
|
2425
|
+
const count = parseInt(parts[1], 10);
|
|
2426
|
+
if (parts.length !== 2 ||
|
|
2427
|
+
Number.isNaN(startIndex) ||
|
|
2428
|
+
Number.isNaN(count) ||
|
|
2429
|
+
startIndex < 0 ||
|
|
2430
|
+
count < 1) {
|
|
2431
|
+
throw FAST.error(1604 /* invalidCompactAttributeMarkerName */, {
|
|
2432
|
+
name: attrName,
|
|
2433
|
+
expectedFormat: `${this.compactAttributeMarkerName}-{index}-{count}`,
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
const indexes = [];
|
|
2437
|
+
for (let i = 0; i < count; i++) {
|
|
2438
|
+
indexes.push(startIndex + i);
|
|
2439
|
+
}
|
|
2440
|
+
return indexes;
|
|
2441
|
+
},
|
|
2400
2442
|
/**
|
|
2401
2443
|
* Parses the ViewBehaviorFactory index from string data. Returns
|
|
2402
2444
|
* the binding index or null if the index cannot be retrieved.
|
|
@@ -2686,6 +2728,7 @@ function isShadowRoot(node) {
|
|
|
2686
2728
|
function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
2687
2729
|
const range = createRangeForNodes(firstNode, lastNode);
|
|
2688
2730
|
const treeRoot = range.commonAncestorContainer;
|
|
2731
|
+
const hydrationIndexOffset = getHydrationIndexOffset(factories);
|
|
2689
2732
|
const walker = document.createTreeWalker(treeRoot, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_COMMENT + NodeFilter.SHOW_TEXT, {
|
|
2690
2733
|
acceptNode(node) {
|
|
2691
2734
|
return range.comparePoint(node, 0) === 0
|
|
@@ -2699,11 +2742,11 @@ function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
|
2699
2742
|
while (node !== null) {
|
|
2700
2743
|
switch (node.nodeType) {
|
|
2701
2744
|
case Node.ELEMENT_NODE: {
|
|
2702
|
-
targetElement(node, factories, targets);
|
|
2745
|
+
targetElement(node, factories, targets, hydrationIndexOffset);
|
|
2703
2746
|
break;
|
|
2704
2747
|
}
|
|
2705
2748
|
case Node.COMMENT_NODE: {
|
|
2706
|
-
targetComment(node, walker, factories, targets, boundaries);
|
|
2749
|
+
targetComment(node, walker, factories, targets, boundaries, hydrationIndexOffset);
|
|
2707
2750
|
break;
|
|
2708
2751
|
}
|
|
2709
2752
|
}
|
|
@@ -2712,21 +2755,22 @@ function buildViewBindingTargets(firstNode, lastNode, factories) {
|
|
|
2712
2755
|
range.detach();
|
|
2713
2756
|
return { targets, boundaries };
|
|
2714
2757
|
}
|
|
2715
|
-
function targetElement(node, factories, targets) {
|
|
2716
|
-
var _a;
|
|
2758
|
+
function targetElement(node, factories, targets, hydrationIndexOffset) {
|
|
2759
|
+
var _a, _b;
|
|
2717
2760
|
// Check for attributes and map any factories.
|
|
2718
|
-
const attrFactoryIds = (_a = HydrationMarkup.parseAttributeBinding(node)) !== null && _a !== void 0 ? _a : HydrationMarkup.parseEnumeratedAttributeBinding(node);
|
|
2761
|
+
const attrFactoryIds = (_b = (_a = HydrationMarkup.parseAttributeBinding(node)) !== null && _a !== void 0 ? _a : HydrationMarkup.parseEnumeratedAttributeBinding(node)) !== null && _b !== void 0 ? _b : HydrationMarkup.parseCompactAttributeBinding(node);
|
|
2719
2762
|
if (attrFactoryIds !== null) {
|
|
2720
2763
|
for (const id of attrFactoryIds) {
|
|
2721
|
-
|
|
2764
|
+
const factory = factories[id + hydrationIndexOffset];
|
|
2765
|
+
if (!factory) {
|
|
2722
2766
|
throw new HydrationTargetElementError(`HydrationView was unable to successfully target factory on ${node.nodeName} inside ${node.getRootNode().host.nodeName}. This likely indicates a template mismatch between SSR rendering and hydration.`, factories, node);
|
|
2723
2767
|
}
|
|
2724
|
-
targetFactory(
|
|
2768
|
+
targetFactory(factory, node, targets);
|
|
2725
2769
|
}
|
|
2726
2770
|
node.removeAttribute(HydrationMarkup.attributeMarkerName);
|
|
2727
2771
|
}
|
|
2728
2772
|
}
|
|
2729
|
-
function targetComment(node, walker, factories, targets, boundaries) {
|
|
2773
|
+
function targetComment(node, walker, factories, targets, boundaries, hydrationIndexOffset) {
|
|
2730
2774
|
if (HydrationMarkup.isElementBoundaryStartMarker(node)) {
|
|
2731
2775
|
skipToElementBoundaryEndMarker(node, walker);
|
|
2732
2776
|
return;
|
|
@@ -2737,7 +2781,7 @@ function targetComment(node, walker, factories, targets, boundaries) {
|
|
|
2737
2781
|
return;
|
|
2738
2782
|
}
|
|
2739
2783
|
const [index, id] = parsed;
|
|
2740
|
-
const factory = factories[index];
|
|
2784
|
+
const factory = factories[index + hydrationIndexOffset];
|
|
2741
2785
|
const nodes = [];
|
|
2742
2786
|
let current = walker.nextSibling();
|
|
2743
2787
|
node.data = "";
|
|
@@ -2801,6 +2845,18 @@ function skipToElementBoundaryEndMarker(node, walker) {
|
|
|
2801
2845
|
current = walker.nextSibling();
|
|
2802
2846
|
}
|
|
2803
2847
|
}
|
|
2848
|
+
function getHydrationIndexOffset(factories) {
|
|
2849
|
+
let offset = 0;
|
|
2850
|
+
for (let i = 0, ii = factories.length; i < ii; ++i) {
|
|
2851
|
+
if (factories[i].targetNodeId === "h") {
|
|
2852
|
+
offset++;
|
|
2853
|
+
}
|
|
2854
|
+
else {
|
|
2855
|
+
break;
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
return offset;
|
|
2859
|
+
}
|
|
2804
2860
|
function targetFactory(factory, node, targets) {
|
|
2805
2861
|
if (factory.targetNodeId === undefined) {
|
|
2806
2862
|
// Dev error, this shouldn't ever be thrown
|