@lwc/engine-core 6.3.4 → 6.4.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/dist/framework/api.d.ts +3 -3
- package/dist/framework/main.d.ts +1 -0
- package/dist/framework/modules/attrs.d.ts +2 -2
- package/dist/framework/modules/computed-class-attr.d.ts +3 -2
- package/dist/framework/modules/computed-style-attr.d.ts +3 -2
- package/dist/framework/modules/events.d.ts +2 -2
- package/dist/framework/modules/refs.d.ts +2 -2
- package/dist/framework/modules/static-parts.d.ts +17 -3
- package/dist/framework/modules/text.d.ts +5 -0
- package/dist/framework/template.d.ts +2 -2
- package/dist/framework/vm.d.ts +8 -6
- package/dist/framework/vnodes.d.ts +19 -1
- package/dist/index.cjs.js +353 -81
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +354 -82
- package/dist/index.js.map +1 -1
- package/dist/libs/signal-tracker/index.d.ts +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Copyright (c) 2024 Salesforce, Inc.
|
|
3
3
|
*/
|
|
4
|
-
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArraySplice, create, isFalse, isFunction as isFunction$1, isObject, seal, isAPIFeatureEnabled, isArray as isArray$1, keys, hasOwnProperty as hasOwnProperty$1, entries, AriaPropNameToAttrNameMap, getPropertyDescriptor, forEach, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, freeze, KEY__SYNTHETIC_MODE, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, ArrayShift, ArrayUnshift, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, LOWEST_API_VERSION, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, arrayEvery, ArrayIncludes, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse } from '@lwc/shared';
|
|
4
|
+
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArraySplice, create, isFalse, isFunction as isFunction$1, isObject, seal, isAPIFeatureEnabled, isArray as isArray$1, keys, hasOwnProperty as hasOwnProperty$1, entries, AriaPropNameToAttrNameMap, getPropertyDescriptor, forEach, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, freeze, KEY__SYNTHETIC_MODE, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, ArrayShift, ArrayUnshift, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, htmlEscape, StringCharAt, LOWEST_API_VERSION, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, arrayEvery, ArrayIncludes, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse } from '@lwc/shared';
|
|
5
5
|
export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
|
|
6
6
|
|
|
7
7
|
/*
|
|
@@ -3645,6 +3645,12 @@ function isVScopedSlotFragment(vnode) {
|
|
|
3645
3645
|
function isVStatic(vnode) {
|
|
3646
3646
|
return vnode.type === 4 /* VNodeType.Static */;
|
|
3647
3647
|
}
|
|
3648
|
+
function isVStaticPartElement(vnode) {
|
|
3649
|
+
return vnode.type === 1 /* VStaticPartType.Element */;
|
|
3650
|
+
}
|
|
3651
|
+
function isVStaticPartText(vnode) {
|
|
3652
|
+
return vnode.type === 0 /* VStaticPartType.Text */;
|
|
3653
|
+
}
|
|
3648
3654
|
|
|
3649
3655
|
/*
|
|
3650
3656
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -3654,7 +3660,8 @@ function isVStatic(vnode) {
|
|
|
3654
3660
|
*/
|
|
3655
3661
|
const ColonCharCode = 58;
|
|
3656
3662
|
function patchAttributes(oldVnode, vnode, renderer) {
|
|
3657
|
-
const {
|
|
3663
|
+
const { data, elm } = vnode;
|
|
3664
|
+
const { attrs } = data;
|
|
3658
3665
|
if (isUndefined$1(attrs)) {
|
|
3659
3666
|
return;
|
|
3660
3667
|
}
|
|
@@ -3663,7 +3670,8 @@ function patchAttributes(oldVnode, vnode, renderer) {
|
|
|
3663
3670
|
if (oldAttrs === attrs) {
|
|
3664
3671
|
return;
|
|
3665
3672
|
}
|
|
3666
|
-
|
|
3673
|
+
// Note VStaticPartData does not contain the external property so it will always default to false.
|
|
3674
|
+
const external = 'external' in data ? data.external : false;
|
|
3667
3675
|
const { setAttribute, removeAttribute, setProperty } = renderer;
|
|
3668
3676
|
for (const key in attrs) {
|
|
3669
3677
|
const cur = attrs[key];
|
|
@@ -3767,8 +3775,7 @@ function patchProps(oldVnode, vnode, renderer) {
|
|
|
3767
3775
|
*/
|
|
3768
3776
|
const classNameToClassMap = create(null);
|
|
3769
3777
|
function getMapFromClassName(className) {
|
|
3770
|
-
|
|
3771
|
-
if (className == null) {
|
|
3778
|
+
if (isUndefined$1(className) || isNull(className) || className === '') {
|
|
3772
3779
|
return EmptyObject;
|
|
3773
3780
|
}
|
|
3774
3781
|
// computed class names must be string
|
|
@@ -3807,10 +3814,16 @@ function patchClassAttribute(oldVnode, vnode, renderer) {
|
|
|
3807
3814
|
if (oldClass === newClass) {
|
|
3808
3815
|
return;
|
|
3809
3816
|
}
|
|
3810
|
-
const { getClassList } = renderer;
|
|
3811
|
-
const classList = getClassList(elm);
|
|
3812
3817
|
const newClassMap = getMapFromClassName(newClass);
|
|
3813
3818
|
const oldClassMap = getMapFromClassName(oldClass);
|
|
3819
|
+
if (oldClassMap === newClassMap) {
|
|
3820
|
+
// These objects are cached by className string (`classNameToClassMap`), so we can only get here if there is
|
|
3821
|
+
// a key collision due to types, e.g. oldClass is `undefined` and newClass is `""` (empty string), or oldClass
|
|
3822
|
+
// is `1` (number) and newClass is `"1"` (string).
|
|
3823
|
+
return;
|
|
3824
|
+
}
|
|
3825
|
+
const { getClassList } = renderer;
|
|
3826
|
+
const classList = getClassList(elm);
|
|
3814
3827
|
let name;
|
|
3815
3828
|
for (name in oldClassMap) {
|
|
3816
3829
|
// remove only if it is not in the new class collection and it is not set from within the instance
|
|
@@ -3832,8 +3845,13 @@ function patchClassAttribute(oldVnode, vnode, renderer) {
|
|
|
3832
3845
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3833
3846
|
*/
|
|
3834
3847
|
// The style property is a string when defined via an expression in the template.
|
|
3835
|
-
function patchStyleAttribute(oldVnode, vnode, renderer) {
|
|
3848
|
+
function patchStyleAttribute(oldVnode, vnode, renderer, owner) {
|
|
3836
3849
|
const { elm, data: { style: newStyle }, } = vnode;
|
|
3850
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3851
|
+
if (!isNull(newStyle) && !isUndefined$1(newStyle) && !isString(newStyle)) {
|
|
3852
|
+
logError(`Invalid 'style' attribute passed to <${elm.tagName.toLowerCase()}> is ignored. This attribute must be a string value.`, owner);
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3837
3855
|
const oldStyle = isNull(oldVnode) ? undefined : oldVnode.data.style;
|
|
3838
3856
|
if (oldStyle === newStyle) {
|
|
3839
3857
|
return;
|
|
@@ -3854,8 +3872,8 @@ function patchStyleAttribute(oldVnode, vnode, renderer) {
|
|
|
3854
3872
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3855
3873
|
*/
|
|
3856
3874
|
function applyEventListeners(vnode, renderer) {
|
|
3857
|
-
const { elm } = vnode;
|
|
3858
|
-
const on =
|
|
3875
|
+
const { elm, data } = vnode;
|
|
3876
|
+
const { on } = data;
|
|
3859
3877
|
if (isUndefined$1(on)) {
|
|
3860
3878
|
return;
|
|
3861
3879
|
}
|
|
@@ -3932,12 +3950,47 @@ function applyRefs(vnode, owner) {
|
|
|
3932
3950
|
refVNodes[ref] = vnode;
|
|
3933
3951
|
}
|
|
3934
3952
|
|
|
3953
|
+
/*
|
|
3954
|
+
* Copyright (c) 2024, salesforce.com, inc.
|
|
3955
|
+
* All rights reserved.
|
|
3956
|
+
* SPDX-License-Identifier: MIT
|
|
3957
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3958
|
+
*/
|
|
3959
|
+
function patchTextVNode(n1, n2, renderer) {
|
|
3960
|
+
n2.elm = n1.elm;
|
|
3961
|
+
if (n2.text !== n1.text) {
|
|
3962
|
+
updateTextContent$1(n2, renderer);
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
function patchTextVStaticPart(n1, n2, renderer) {
|
|
3966
|
+
if (isNull(n1) || n2.text !== n1.text) {
|
|
3967
|
+
updateTextContent$1(n2, renderer);
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
function updateTextContent$1(vnode, renderer) {
|
|
3971
|
+
const { elm, text } = vnode;
|
|
3972
|
+
const { setText } = renderer;
|
|
3973
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3974
|
+
unlockDomMutation();
|
|
3975
|
+
}
|
|
3976
|
+
setText(elm, text);
|
|
3977
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3978
|
+
lockDomMutation();
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3935
3982
|
/*
|
|
3936
3983
|
* Copyright (c) 2023, salesforce.com, inc.
|
|
3937
3984
|
* All rights reserved.
|
|
3938
3985
|
* SPDX-License-Identifier: MIT
|
|
3939
3986
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3940
3987
|
*/
|
|
3988
|
+
/**
|
|
3989
|
+
* Given an array of static parts, mounts the DOM element to the part based on the staticPartId
|
|
3990
|
+
* @param root the root element
|
|
3991
|
+
* @param parts an array of VStaticParts
|
|
3992
|
+
* @param renderer the renderer to use
|
|
3993
|
+
*/
|
|
3941
3994
|
function traverseAndSetElements(root, parts, renderer) {
|
|
3942
3995
|
const numParts = parts.length;
|
|
3943
3996
|
// Optimization given that, in most cases, there will be one part, and it's just the root
|
|
@@ -4003,18 +4056,30 @@ function mountStaticParts(root, vnode, renderer) {
|
|
|
4003
4056
|
traverseAndSetElements(root, parts, renderer);
|
|
4004
4057
|
// Currently only event listeners and refs are supported for static vnodes
|
|
4005
4058
|
for (const part of parts) {
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4059
|
+
if (isVStaticPartElement(part)) {
|
|
4060
|
+
// Event listeners only need to be applied once when mounting
|
|
4061
|
+
applyEventListeners(part, renderer);
|
|
4062
|
+
// Refs must be updated after every render due to refVNodes getting reset before every render
|
|
4063
|
+
applyRefs(part, owner);
|
|
4064
|
+
patchAttributes(null, part, renderer);
|
|
4065
|
+
patchClassAttribute(null, part, renderer);
|
|
4066
|
+
patchStyleAttribute(null, part, renderer, owner);
|
|
4067
|
+
}
|
|
4068
|
+
else {
|
|
4069
|
+
if (process.env.NODE_ENV !== 'production' && !isVStaticPartText(part)) {
|
|
4070
|
+
throw new Error(`LWC internal error, encountered unknown static part type: ${part.type}`);
|
|
4071
|
+
}
|
|
4072
|
+
patchTextVStaticPart(null, part, renderer);
|
|
4073
|
+
}
|
|
4010
4074
|
}
|
|
4011
4075
|
}
|
|
4012
4076
|
/**
|
|
4013
|
-
*
|
|
4077
|
+
* Updates the static elements based on the content of the VStaticParts
|
|
4014
4078
|
* @param n1 the previous VStatic vnode
|
|
4015
4079
|
* @param n2 the current VStatic vnode
|
|
4080
|
+
* @param renderer the renderer to use
|
|
4016
4081
|
*/
|
|
4017
|
-
function patchStaticParts(n1, n2) {
|
|
4082
|
+
function patchStaticParts(n1, n2, renderer) {
|
|
4018
4083
|
// On the server, we don't support ref (because it relies on renderedCallback), nor do we
|
|
4019
4084
|
// support event listeners (no interactivity), so traversing parts makes no sense
|
|
4020
4085
|
if (!process.env.IS_BROWSER) {
|
|
@@ -4029,12 +4094,49 @@ function patchStaticParts(n1, n2) {
|
|
|
4029
4094
|
assert.isTrue(currParts.length === prevParts?.length, 'Expected static parts to be the same for the same element. This is an error with the LWC framework itself.');
|
|
4030
4095
|
}
|
|
4031
4096
|
for (let i = 0; i < currParts.length; i++) {
|
|
4097
|
+
const prevPart = prevParts[i];
|
|
4032
4098
|
const part = currParts[i];
|
|
4033
4099
|
// Patch only occurs if the vnode is newly generated, which means the part.elm is always undefined
|
|
4034
4100
|
// Since the vnode and elements are the same we can safely assume that prevParts[i].elm is defined.
|
|
4035
|
-
part.elm =
|
|
4036
|
-
|
|
4037
|
-
|
|
4101
|
+
part.elm = prevPart.elm;
|
|
4102
|
+
if (process.env.NODE_ENV !== 'production' && prevPart.type !== part.type) {
|
|
4103
|
+
throw new Error(`LWC internal error, static part types do not match. Previous type was ${prevPart.type} and current type is ${part.type}`);
|
|
4104
|
+
}
|
|
4105
|
+
if (isVStaticPartElement(part)) {
|
|
4106
|
+
// Refs must be updated after every render due to refVNodes getting reset before every render
|
|
4107
|
+
applyRefs(part, currPartsOwner);
|
|
4108
|
+
patchAttributes(prevPart, part, renderer);
|
|
4109
|
+
patchClassAttribute(prevPart, part, renderer);
|
|
4110
|
+
patchStyleAttribute(prevPart, part, renderer, currPartsOwner);
|
|
4111
|
+
}
|
|
4112
|
+
else {
|
|
4113
|
+
patchTextVStaticPart(null, part, renderer);
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
}
|
|
4117
|
+
/**
|
|
4118
|
+
* Mounts the hydration specific attributes
|
|
4119
|
+
* @param vnode the parent VStatic node
|
|
4120
|
+
* @param renderer the renderer to use
|
|
4121
|
+
*/
|
|
4122
|
+
function hydrateStaticParts(vnode, renderer) {
|
|
4123
|
+
if (!process.env.IS_BROWSER) {
|
|
4124
|
+
return;
|
|
4125
|
+
}
|
|
4126
|
+
const { parts, owner } = vnode;
|
|
4127
|
+
if (isUndefined$1(parts)) {
|
|
4128
|
+
return;
|
|
4129
|
+
}
|
|
4130
|
+
// Note, hydration doesn't patch attributes because hydration validation occurs before this routine
|
|
4131
|
+
// which guarantees that the elements are the same.
|
|
4132
|
+
// We only need to apply the parts for things that cannot be done on the server.
|
|
4133
|
+
for (const part of parts) {
|
|
4134
|
+
if (isVStaticPartElement(part)) {
|
|
4135
|
+
// Event listeners only need to be applied once when mounting
|
|
4136
|
+
applyEventListeners(part, renderer);
|
|
4137
|
+
// Refs must be updated after every render due to refVNodes getting reset before every render
|
|
4138
|
+
applyRefs(part, owner);
|
|
4139
|
+
}
|
|
4038
4140
|
}
|
|
4039
4141
|
}
|
|
4040
4142
|
|
|
@@ -4072,7 +4174,7 @@ function patch(n1, n2, parent, renderer) {
|
|
|
4072
4174
|
switch (n2.type) {
|
|
4073
4175
|
case 0 /* VNodeType.Text */:
|
|
4074
4176
|
// VText has no special capability, fallback to the owner's renderer
|
|
4075
|
-
|
|
4177
|
+
patchTextVNode(n1, n2, renderer);
|
|
4076
4178
|
break;
|
|
4077
4179
|
case 1 /* VNodeType.Comment */:
|
|
4078
4180
|
// VComment has no special capability, fallback to the owner's renderer
|
|
@@ -4119,12 +4221,6 @@ function mount(node, parent, renderer, anchor) {
|
|
|
4119
4221
|
break;
|
|
4120
4222
|
}
|
|
4121
4223
|
}
|
|
4122
|
-
function patchText(n1, n2, renderer) {
|
|
4123
|
-
n2.elm = n1.elm;
|
|
4124
|
-
if (n2.text !== n1.text) {
|
|
4125
|
-
updateTextContent(n2, renderer);
|
|
4126
|
-
}
|
|
4127
|
-
}
|
|
4128
4224
|
function mountText(vnode, parent, anchor, renderer) {
|
|
4129
4225
|
const { owner } = vnode;
|
|
4130
4226
|
const { createText } = renderer;
|
|
@@ -4137,7 +4233,7 @@ function patchComment(n1, n2, renderer) {
|
|
|
4137
4233
|
// FIXME: Comment nodes should be static, we shouldn't need to diff them together. However
|
|
4138
4234
|
// it is the case today.
|
|
4139
4235
|
if (n2.text !== n1.text) {
|
|
4140
|
-
updateTextContent(n2, renderer);
|
|
4236
|
+
updateTextContent$1(n2, renderer);
|
|
4141
4237
|
}
|
|
4142
4238
|
}
|
|
4143
4239
|
function mountComment(vnode, parent, anchor, renderer) {
|
|
@@ -4181,7 +4277,7 @@ function patchStatic(n1, n2, renderer) {
|
|
|
4181
4277
|
// slotAssignments can only apply to the top level element, never to a static part.
|
|
4182
4278
|
patchSlotAssignment(n1, n2, renderer);
|
|
4183
4279
|
// The `refs` object is blown away in every re-render, so we always need to re-apply them
|
|
4184
|
-
patchStaticParts(n1, n2);
|
|
4280
|
+
patchStaticParts(n1, n2, renderer);
|
|
4185
4281
|
}
|
|
4186
4282
|
function patchElement(n1, n2, renderer) {
|
|
4187
4283
|
const elm = (n2.elm = n1.elm);
|
|
@@ -4192,19 +4288,20 @@ function mountStatic(vnode, parent, anchor, renderer) {
|
|
|
4192
4288
|
const { owner } = vnode;
|
|
4193
4289
|
const { cloneNode, isSyntheticShadowDefined } = renderer;
|
|
4194
4290
|
const elm = (vnode.elm = cloneNode(vnode.fragment, true));
|
|
4291
|
+
// Define the root node shadow resolver
|
|
4195
4292
|
linkNodeToShadow(elm, owner, renderer);
|
|
4196
4293
|
applyElementRestrictions(elm, vnode);
|
|
4197
|
-
// Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
|
|
4198
4294
|
const { renderMode, shadowMode } = owner;
|
|
4199
4295
|
if (isSyntheticShadowDefined) {
|
|
4296
|
+
// Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
|
|
4200
4297
|
if (shadowMode === 1 /* ShadowMode.Synthetic */ || renderMode === 0 /* RenderMode.Light */) {
|
|
4201
4298
|
elm[KEY__SHADOW_STATIC] = true;
|
|
4202
4299
|
}
|
|
4203
4300
|
}
|
|
4204
4301
|
// slotAssignments can only apply to the top level element, never to a static part.
|
|
4205
4302
|
patchSlotAssignment(null, vnode, renderer);
|
|
4206
|
-
insertNode(elm, parent, anchor, renderer);
|
|
4207
4303
|
mountStaticParts(elm, vnode, renderer);
|
|
4304
|
+
insertNode(elm, parent, anchor, renderer);
|
|
4208
4305
|
}
|
|
4209
4306
|
function mountCustomElement(vnode, parent, anchor, renderer) {
|
|
4210
4307
|
const { sel, owner, ctor } = vnode;
|
|
@@ -4369,17 +4466,6 @@ function linkNodeToShadow(elm, owner, renderer) {
|
|
|
4369
4466
|
}
|
|
4370
4467
|
}
|
|
4371
4468
|
}
|
|
4372
|
-
function updateTextContent(vnode, renderer) {
|
|
4373
|
-
const { elm, text } = vnode;
|
|
4374
|
-
const { setText } = renderer;
|
|
4375
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
4376
|
-
unlockDomMutation();
|
|
4377
|
-
}
|
|
4378
|
-
setText(elm, text);
|
|
4379
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
4380
|
-
lockDomMutation();
|
|
4381
|
-
}
|
|
4382
|
-
}
|
|
4383
4469
|
function insertFragmentOrNode(vnode, parent, anchor, renderer) {
|
|
4384
4470
|
if (process.env.NODE_ENV !== 'production') {
|
|
4385
4471
|
unlockDomMutation();
|
|
@@ -4424,15 +4510,16 @@ function patchElementPropsAndAttrsAndRefs$1(oldVnode, vnode, renderer) {
|
|
|
4424
4510
|
applyStaticClassAttribute(vnode, renderer);
|
|
4425
4511
|
applyStaticStyleAttribute(vnode, renderer);
|
|
4426
4512
|
}
|
|
4513
|
+
const { owner } = vnode;
|
|
4427
4514
|
// Attrs need to be applied to element before props IE11 will wipe out value on radio inputs if
|
|
4428
4515
|
// value is set before type=radio.
|
|
4429
4516
|
patchClassAttribute(oldVnode, vnode, renderer);
|
|
4430
|
-
patchStyleAttribute(oldVnode, vnode, renderer);
|
|
4517
|
+
patchStyleAttribute(oldVnode, vnode, renderer, owner);
|
|
4431
4518
|
patchAttributes(oldVnode, vnode, renderer);
|
|
4432
4519
|
patchProps(oldVnode, vnode, renderer);
|
|
4433
4520
|
patchSlotAssignment(oldVnode, vnode, renderer);
|
|
4434
4521
|
// The `refs` object is blown away in every re-render, so we always need to re-apply them
|
|
4435
|
-
applyRefs(vnode,
|
|
4522
|
+
applyRefs(vnode, owner);
|
|
4436
4523
|
}
|
|
4437
4524
|
function applyStyleScoping(elm, owner, renderer) {
|
|
4438
4525
|
const { getClassList } = renderer;
|
|
@@ -4834,10 +4921,14 @@ function addVNodeToChildLWC(vnode) {
|
|
|
4834
4921
|
ArrayPush$1.call(getVMBeingRendered().velements, vnode);
|
|
4835
4922
|
}
|
|
4836
4923
|
// [s]tatic [p]art
|
|
4837
|
-
function sp(partId, data) {
|
|
4924
|
+
function sp(partId, data, text) {
|
|
4925
|
+
// Static part will always have either text or data, it's guaranteed by the compiler.
|
|
4926
|
+
const type = isNull(text) ? 1 /* VStaticPartType.Element */ : 0 /* VStaticPartType.Text */;
|
|
4838
4927
|
return {
|
|
4928
|
+
type,
|
|
4839
4929
|
partId,
|
|
4840
4930
|
data,
|
|
4931
|
+
text,
|
|
4841
4932
|
elm: undefined, // elm is defined later
|
|
4842
4933
|
};
|
|
4843
4934
|
}
|
|
@@ -4854,8 +4945,9 @@ function ssf(slotName, factory) {
|
|
|
4854
4945
|
};
|
|
4855
4946
|
}
|
|
4856
4947
|
// [st]atic node
|
|
4857
|
-
function st(
|
|
4948
|
+
function st(fragmentFactory, key, parts) {
|
|
4858
4949
|
const owner = getVMBeingRendered();
|
|
4950
|
+
const fragment = fragmentFactory(parts);
|
|
4859
4951
|
const vnode = {
|
|
4860
4952
|
type: 4 /* VNodeType.Static */,
|
|
4861
4953
|
sel: undefined,
|
|
@@ -4897,9 +4989,6 @@ function h(sel, data, children = EmptyArray) {
|
|
|
4897
4989
|
// checking reserved internal data properties
|
|
4898
4990
|
assert.isFalse(data.className && data.classMap, `vnode.data.className and vnode.data.classMap ambiguous declaration.`);
|
|
4899
4991
|
assert.isFalse(data.styleDecls && data.style, `vnode.data.styleDecls and vnode.data.style ambiguous declaration.`);
|
|
4900
|
-
if (data.style && !isString(data.style)) {
|
|
4901
|
-
logError(`Invalid 'style' attribute passed to <${sel}> is ignored. This attribute must be a string value.`, vmBeingRendered);
|
|
4902
|
-
}
|
|
4903
4992
|
forEach.call(children, (childVnode) => {
|
|
4904
4993
|
if (childVnode != null) {
|
|
4905
4994
|
assert.isTrue('type' in childVnode &&
|
|
@@ -5109,16 +5198,19 @@ function i(iterable, factory) {
|
|
|
5109
5198
|
if (process.env.NODE_ENV !== 'production') {
|
|
5110
5199
|
const vnodes = isArray$1(vnode) ? vnode : [vnode];
|
|
5111
5200
|
forEach.call(vnodes, (childVnode) => {
|
|
5112
|
-
|
|
5201
|
+
// Check that the child vnode is either an element or VStatic
|
|
5202
|
+
if (!isNull(childVnode) && (isVBaseElement(childVnode) || isVStatic(childVnode))) {
|
|
5113
5203
|
const { key } = childVnode;
|
|
5204
|
+
// In @lwc/engine-server the fragment doesn't have a tagName, default to the VM's tagName.
|
|
5205
|
+
const { tagName } = vmBeingRendered;
|
|
5114
5206
|
if (isString(key) || isNumber(key)) {
|
|
5115
5207
|
if (keyMap[key] === 1 && isUndefined$1(iterationError)) {
|
|
5116
|
-
iterationError = `Duplicated "key" attribute value
|
|
5208
|
+
iterationError = `Duplicated "key" attribute value in "<${tagName}>" for item number ${j}. A key with value "${key}" appears more than once in the iteration. Key values must be unique numbers or strings.`;
|
|
5117
5209
|
}
|
|
5118
5210
|
keyMap[key] = 1;
|
|
5119
5211
|
}
|
|
5120
5212
|
else if (isUndefined$1(iterationError)) {
|
|
5121
|
-
iterationError = `Invalid "key" attribute value in "<${
|
|
5213
|
+
iterationError = `Invalid "key" attribute value in "<${tagName}>" for item number ${j}. Set a unique "key" value on all iterated child elements.`;
|
|
5122
5214
|
}
|
|
5123
5215
|
}
|
|
5124
5216
|
});
|
|
@@ -5517,6 +5609,111 @@ function validateLightDomTemplate(template, vm) {
|
|
|
5517
5609
|
}
|
|
5518
5610
|
}
|
|
5519
5611
|
}
|
|
5612
|
+
const browserExpressionSerializer = (partToken, classAttrToken) => {
|
|
5613
|
+
// This will insert the scoped style token as a static class attribute in the fragment
|
|
5614
|
+
// bypassing the need to call applyStyleScoping when mounting static parts.
|
|
5615
|
+
const type = StringCharAt.call(partToken, 0);
|
|
5616
|
+
switch (type) {
|
|
5617
|
+
case "c" /* STATIC_PART_TOKEN_ID.CLASS */:
|
|
5618
|
+
return classAttrToken;
|
|
5619
|
+
case "t" /* STATIC_PART_TOKEN_ID.TEXT */:
|
|
5620
|
+
// Using a single space here gives us a single empty text node
|
|
5621
|
+
return ' ';
|
|
5622
|
+
default:
|
|
5623
|
+
return '';
|
|
5624
|
+
}
|
|
5625
|
+
};
|
|
5626
|
+
const serializerNoop = () => {
|
|
5627
|
+
throw new Error('LWC internal error, attempted to serialize partToken without static parts');
|
|
5628
|
+
};
|
|
5629
|
+
// This function serializes the expressions generated by static content optimization.
|
|
5630
|
+
// Currently this is only needed for SSR.
|
|
5631
|
+
// TODO [#4078]: Split the implementation between @lwc/engine-dom and @lwc/engine-server
|
|
5632
|
+
function buildSerializeExpressionFn(parts) {
|
|
5633
|
+
if (process.env.IS_BROWSER) {
|
|
5634
|
+
return browserExpressionSerializer;
|
|
5635
|
+
}
|
|
5636
|
+
if (isUndefined$1(parts)) {
|
|
5637
|
+
// Technically this should not be reachable, if there are no parts there should be no partTokens
|
|
5638
|
+
// and this function should never be invoked.
|
|
5639
|
+
return serializerNoop;
|
|
5640
|
+
}
|
|
5641
|
+
const partIdsToParts = new Map();
|
|
5642
|
+
for (const staticPart of parts) {
|
|
5643
|
+
partIdsToParts.set(`${staticPart.partId}`, staticPart);
|
|
5644
|
+
}
|
|
5645
|
+
const parsePartToken = (partToken) => {
|
|
5646
|
+
// The partTokens are split into 3 section:
|
|
5647
|
+
// 1. The first character represents the expression type (attribute, class, style, or text).
|
|
5648
|
+
// 2. For attributes, the characters from index 1 to the first occurrence of a ':' is the partId.
|
|
5649
|
+
// 3. Everything after the first ':' represents the attribute name.
|
|
5650
|
+
// 4. For non-attributes everything from index 1 to the string length is the partId.
|
|
5651
|
+
// Ex, attribute: a0:data-name, a = an attribute, 0 = partId, data-name = attribute name.
|
|
5652
|
+
// Ex, style: s0, s = a style attribute, 0 = partId.
|
|
5653
|
+
const type = StringCharAt.call(partToken, 0);
|
|
5654
|
+
let delimiterIndex = partToken.length;
|
|
5655
|
+
let attrName = '';
|
|
5656
|
+
if (type === "a" /* STATIC_PART_TOKEN_ID.ATTRIBUTE */) {
|
|
5657
|
+
delimiterIndex = partToken.indexOf(':');
|
|
5658
|
+
// Only VStaticPartData.attrs have an attribute name
|
|
5659
|
+
attrName = partToken.substring(delimiterIndex + 1);
|
|
5660
|
+
}
|
|
5661
|
+
const partId = partToken.substring(1, delimiterIndex);
|
|
5662
|
+
const part = partIdsToParts.get(partId) ?? EmptyObject;
|
|
5663
|
+
return { type, part, attrName };
|
|
5664
|
+
};
|
|
5665
|
+
return (partToken, classToken) => {
|
|
5666
|
+
const { type, part, attrName } = parsePartToken(partToken);
|
|
5667
|
+
switch (type) {
|
|
5668
|
+
case "a" /* STATIC_PART_TOKEN_ID.ATTRIBUTE */:
|
|
5669
|
+
return serializeAttribute(part, attrName);
|
|
5670
|
+
case "c" /* STATIC_PART_TOKEN_ID.CLASS */: // class
|
|
5671
|
+
return serializeClassAttribute(part, classToken);
|
|
5672
|
+
case "s" /* STATIC_PART_TOKEN_ID.STYLE */: // style
|
|
5673
|
+
return serializeStyleAttribute(part);
|
|
5674
|
+
case "t" /* STATIC_PART_TOKEN_ID.TEXT */: // text
|
|
5675
|
+
return serializeTextContent(part);
|
|
5676
|
+
default:
|
|
5677
|
+
// This should not be reachable
|
|
5678
|
+
throw new Error(`LWC internal error, unrecognized part token during serialization ${partToken}`);
|
|
5679
|
+
}
|
|
5680
|
+
};
|
|
5681
|
+
}
|
|
5682
|
+
function serializeTextContent(part) {
|
|
5683
|
+
const { text } = part;
|
|
5684
|
+
if (text === '') {
|
|
5685
|
+
return '\u200D'; // Special serialization for empty text nodes
|
|
5686
|
+
}
|
|
5687
|
+
// Note the serialization logic doesn't need to validate against the style tag as in serializeTextContent
|
|
5688
|
+
// because style tags are always inserted through the engine.
|
|
5689
|
+
// User input of style tags are blocked, furthermore, all dynamic text is escaped at this point.
|
|
5690
|
+
return htmlEscape(text);
|
|
5691
|
+
}
|
|
5692
|
+
function serializeStyleAttribute(part) {
|
|
5693
|
+
const { data: { style }, } = part;
|
|
5694
|
+
// This is designed to mirror logic patchStyleAttribute
|
|
5695
|
+
return isString(style) && style.length ? ` style="${htmlEscape(style, true)}"` : '';
|
|
5696
|
+
}
|
|
5697
|
+
function serializeAttribute(part, name) {
|
|
5698
|
+
const { data: { attrs = {} }, } = part;
|
|
5699
|
+
const rawValue = attrs[name];
|
|
5700
|
+
let value = '';
|
|
5701
|
+
// The undefined and null checks here are designed to match patchAttributes routine.
|
|
5702
|
+
if (!isUndefined$1(rawValue) && !isNull(rawValue)) {
|
|
5703
|
+
const stringifiedValue = String(rawValue);
|
|
5704
|
+
value = stringifiedValue.length
|
|
5705
|
+
? ` ${name}="${htmlEscape(stringifiedValue, true)}"`
|
|
5706
|
+
: ` ${name}`;
|
|
5707
|
+
}
|
|
5708
|
+
return value;
|
|
5709
|
+
}
|
|
5710
|
+
function serializeClassAttribute(part, classToken) {
|
|
5711
|
+
const classMap = getMapFromClassName(part.data?.className);
|
|
5712
|
+
// Trim the leading and trailing whitespace here because classToken contains a leading space and
|
|
5713
|
+
// there will be a trailing space if classMap is empty.
|
|
5714
|
+
const computedClassName = `${classToken} ${keys(classMap).join(' ')}`.trim();
|
|
5715
|
+
return computedClassName.length ? ` class="${htmlEscape(computedClassName, true)}"` : '';
|
|
5716
|
+
}
|
|
5520
5717
|
// This should be a no-op outside of LWC's Karma tests, where it's not needed
|
|
5521
5718
|
let registerFragmentCache = noop;
|
|
5522
5719
|
// Only used in LWC's Karma tests
|
|
@@ -5538,7 +5735,7 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5538
5735
|
return (strings, ...keys) => {
|
|
5539
5736
|
const cache = create(null);
|
|
5540
5737
|
registerFragmentCache(cache);
|
|
5541
|
-
return function () {
|
|
5738
|
+
return function (parts) {
|
|
5542
5739
|
const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
|
|
5543
5740
|
const hasStyleToken = !isUndefined$1(stylesheetToken);
|
|
5544
5741
|
const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
|
|
@@ -5550,14 +5747,27 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5550
5747
|
if (hasStyleToken && isSyntheticShadow) {
|
|
5551
5748
|
cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
|
|
5552
5749
|
}
|
|
5553
|
-
|
|
5554
|
-
|
|
5750
|
+
// Cache is only here to prevent calling innerHTML multiple times which doesn't happen on the server.
|
|
5751
|
+
if (process.env.IS_BROWSER) {
|
|
5752
|
+
// Disable this on the server to prevent cache poisoning when expressions are used.
|
|
5753
|
+
const cached = cache[cacheKey];
|
|
5754
|
+
if (!isUndefined$1(cached)) {
|
|
5755
|
+
return cached;
|
|
5756
|
+
}
|
|
5555
5757
|
}
|
|
5556
5758
|
// If legacy stylesheet tokens are required, then add them to the rendered string
|
|
5557
5759
|
const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
|
|
5558
5760
|
const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetTokenToRender : '';
|
|
5559
5761
|
const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetTokenToRender}"` : '';
|
|
5560
5762
|
const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetTokenToRender : '';
|
|
5763
|
+
// In the browser, we provide the entire class attribute as a perf optimization to avoid applying it on mount.
|
|
5764
|
+
// The remaining class expression will be applied when the static parts are mounted.
|
|
5765
|
+
// In SSR, the entire class attribute (expression included) is assembled along with the fragment.
|
|
5766
|
+
// This is why in the browser we provide the entire class attribute and in SSR we only provide the class token.
|
|
5767
|
+
const exprClassToken = process.env.IS_BROWSER ? classAttrToken : classToken;
|
|
5768
|
+
// TODO [#3624]: The implementation of this function should be specific to @lwc/engine-dom and @lwc/engine-server.
|
|
5769
|
+
// Find a way to split this in a future refactor.
|
|
5770
|
+
const serializeExpression = buildSerializeExpressionFn(parts);
|
|
5561
5771
|
let htmlFragment = '';
|
|
5562
5772
|
for (let i = 0, n = keys.length; i < n; i++) {
|
|
5563
5773
|
switch (keys[i]) {
|
|
@@ -5573,6 +5783,10 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5573
5783
|
case 3: // ${1}${2}
|
|
5574
5784
|
htmlFragment += strings[i] + classAttrToken + attrToken;
|
|
5575
5785
|
break;
|
|
5786
|
+
default: // expressions ${partId:attributeName/textId}
|
|
5787
|
+
htmlFragment +=
|
|
5788
|
+
strings[i] + serializeExpression(keys[i], exprClassToken);
|
|
5789
|
+
break;
|
|
5576
5790
|
}
|
|
5577
5791
|
}
|
|
5578
5792
|
htmlFragment += strings[strings.length - 1];
|
|
@@ -6455,25 +6669,25 @@ function forceRehydration(vm) {
|
|
|
6455
6669
|
scheduleRehydration(vm);
|
|
6456
6670
|
}
|
|
6457
6671
|
}
|
|
6458
|
-
function runFormAssociatedCustomElementCallback(vm, faceCb) {
|
|
6672
|
+
function runFormAssociatedCustomElementCallback(vm, faceCb, args) {
|
|
6459
6673
|
const { renderMode, shadowMode } = vm;
|
|
6460
6674
|
if (shadowMode === 1 /* ShadowMode.Synthetic */ && renderMode !== 0 /* RenderMode.Light */) {
|
|
6461
6675
|
throw new Error('Form associated lifecycle methods are not available in synthetic shadow. Please use native shadow or light DOM.');
|
|
6462
6676
|
}
|
|
6463
|
-
invokeComponentCallback(vm, faceCb);
|
|
6677
|
+
invokeComponentCallback(vm, faceCb, args);
|
|
6464
6678
|
}
|
|
6465
|
-
function runFormAssociatedCallback(elm) {
|
|
6679
|
+
function runFormAssociatedCallback(elm, form) {
|
|
6466
6680
|
const vm = getAssociatedVM(elm);
|
|
6467
6681
|
const { formAssociatedCallback } = vm.def;
|
|
6468
6682
|
if (!isUndefined$1(formAssociatedCallback)) {
|
|
6469
|
-
runFormAssociatedCustomElementCallback(vm, formAssociatedCallback);
|
|
6683
|
+
runFormAssociatedCustomElementCallback(vm, formAssociatedCallback, [form]);
|
|
6470
6684
|
}
|
|
6471
6685
|
}
|
|
6472
|
-
function runFormDisabledCallback(elm) {
|
|
6686
|
+
function runFormDisabledCallback(elm, disabled) {
|
|
6473
6687
|
const vm = getAssociatedVM(elm);
|
|
6474
6688
|
const { formDisabledCallback } = vm.def;
|
|
6475
6689
|
if (!isUndefined$1(formDisabledCallback)) {
|
|
6476
|
-
runFormAssociatedCustomElementCallback(vm, formDisabledCallback);
|
|
6690
|
+
runFormAssociatedCustomElementCallback(vm, formDisabledCallback, [disabled]);
|
|
6477
6691
|
}
|
|
6478
6692
|
}
|
|
6479
6693
|
function runFormResetCallback(elm) {
|
|
@@ -6483,11 +6697,11 @@ function runFormResetCallback(elm) {
|
|
|
6483
6697
|
runFormAssociatedCustomElementCallback(vm, formResetCallback);
|
|
6484
6698
|
}
|
|
6485
6699
|
}
|
|
6486
|
-
function runFormStateRestoreCallback(elm) {
|
|
6700
|
+
function runFormStateRestoreCallback(elm, state, reason) {
|
|
6487
6701
|
const vm = getAssociatedVM(elm);
|
|
6488
6702
|
const { formStateRestoreCallback } = vm.def;
|
|
6489
6703
|
if (!isUndefined$1(formStateRestoreCallback)) {
|
|
6490
|
-
runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
|
|
6704
|
+
runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback, [state, reason]);
|
|
6491
6705
|
}
|
|
6492
6706
|
}
|
|
6493
6707
|
function resetRefVNodes(vm) {
|
|
@@ -6855,9 +7069,12 @@ function hydrateText(node, vnode, renderer) {
|
|
|
6855
7069
|
if (!hasCorrectNodeType(vnode, node, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
6856
7070
|
return handleMismatch(node, vnode, renderer);
|
|
6857
7071
|
}
|
|
7072
|
+
return updateTextContent(node, vnode, vnode.owner, renderer);
|
|
7073
|
+
}
|
|
7074
|
+
function updateTextContent(node, vnode, owner, renderer) {
|
|
6858
7075
|
if (process.env.NODE_ENV !== 'production') {
|
|
6859
7076
|
if (!textNodeContentsAreEqual(node, vnode, renderer)) {
|
|
6860
|
-
logWarn('Hydration mismatch: text values do not match, will recover from the difference',
|
|
7077
|
+
logWarn('Hydration mismatch: text values do not match, will recover from the difference', owner);
|
|
6861
7078
|
}
|
|
6862
7079
|
}
|
|
6863
7080
|
const { setText } = renderer;
|
|
@@ -6883,11 +7100,24 @@ function hydrateComment(node, vnode, renderer) {
|
|
|
6883
7100
|
}
|
|
6884
7101
|
function hydrateStaticElement(elm, vnode, renderer) {
|
|
6885
7102
|
if (!hasCorrectNodeType(vnode, elm, 1 /* EnvNodeTypes.ELEMENT */, renderer) ||
|
|
6886
|
-
!
|
|
7103
|
+
!areCompatibleStaticNodes(vnode.fragment, elm, vnode, renderer)) {
|
|
7104
|
+
return handleMismatch(elm, vnode, renderer);
|
|
7105
|
+
}
|
|
7106
|
+
return hydrateStaticElementParts(elm, vnode, renderer);
|
|
7107
|
+
}
|
|
7108
|
+
function hydrateStaticElementParts(elm, vnode, renderer) {
|
|
7109
|
+
const { parts } = vnode;
|
|
7110
|
+
if (!isUndefined$1(parts)) {
|
|
7111
|
+
// Elements must first be set on the static part to validate against.
|
|
7112
|
+
traverseAndSetElements(elm, parts, renderer);
|
|
7113
|
+
}
|
|
7114
|
+
if (!haveCompatibleStaticParts(vnode, renderer)) {
|
|
6887
7115
|
return handleMismatch(elm, vnode, renderer);
|
|
6888
7116
|
}
|
|
6889
7117
|
vnode.elm = elm;
|
|
6890
|
-
|
|
7118
|
+
// Hydration only requires applying event listeners and refs.
|
|
7119
|
+
// All other expressions should be applied during SSR or through the handleMismatch routine.
|
|
7120
|
+
hydrateStaticParts(vnode, renderer);
|
|
6891
7121
|
return elm;
|
|
6892
7122
|
}
|
|
6893
7123
|
function hydrateFragment(elm, vnode, renderer) {
|
|
@@ -7063,12 +7293,13 @@ function isMatchingElement(vnode, elm, renderer, shouldValidateAttr = () => true
|
|
|
7063
7293
|
}
|
|
7064
7294
|
return false;
|
|
7065
7295
|
}
|
|
7066
|
-
const
|
|
7296
|
+
const { data } = vnode;
|
|
7297
|
+
const hasCompatibleAttrs = validateAttrs(vnode, elm, data, renderer, shouldValidateAttr);
|
|
7067
7298
|
const hasCompatibleClass = shouldValidateAttr('class')
|
|
7068
|
-
? validateClassAttr(vnode, elm, renderer)
|
|
7299
|
+
? validateClassAttr(vnode, elm, data, renderer)
|
|
7069
7300
|
: true;
|
|
7070
7301
|
const hasCompatibleStyle = shouldValidateAttr('style')
|
|
7071
|
-
? validateStyleAttr(vnode, elm, renderer)
|
|
7302
|
+
? validateStyleAttr(vnode, elm, data, renderer)
|
|
7072
7303
|
: true;
|
|
7073
7304
|
return hasCompatibleAttrs && hasCompatibleClass && hasCompatibleStyle;
|
|
7074
7305
|
}
|
|
@@ -7085,8 +7316,8 @@ function attributeValuesAreEqual(vnodeValue, value) {
|
|
|
7085
7316
|
// In all other cases, the two values are not considered equal
|
|
7086
7317
|
return false;
|
|
7087
7318
|
}
|
|
7088
|
-
function validateAttrs(vnode, elm, renderer, shouldValidateAttr) {
|
|
7089
|
-
const {
|
|
7319
|
+
function validateAttrs(vnode, elm, data, renderer, shouldValidateAttr) {
|
|
7320
|
+
const { attrs = {} } = data;
|
|
7090
7321
|
let nodesAreCompatible = true;
|
|
7091
7322
|
// Validate attributes, though we could always recovery from those by running the update mods.
|
|
7092
7323
|
// Note: intentionally ONLY matching vnodes.attrs to elm.attrs, in case SSR is adding extra attributes.
|
|
@@ -7094,21 +7325,22 @@ function validateAttrs(vnode, elm, renderer, shouldValidateAttr) {
|
|
|
7094
7325
|
if (!shouldValidateAttr(attrName)) {
|
|
7095
7326
|
continue;
|
|
7096
7327
|
}
|
|
7097
|
-
const { owner } = vnode;
|
|
7098
7328
|
const { getAttribute } = renderer;
|
|
7099
7329
|
const elmAttrValue = getAttribute(elm, attrName);
|
|
7100
7330
|
if (!attributeValuesAreEqual(attrValue, elmAttrValue)) {
|
|
7101
7331
|
if (process.env.NODE_ENV !== 'production') {
|
|
7102
7332
|
const { getProperty } = renderer;
|
|
7103
|
-
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found ${isNull(elmAttrValue) ? 'null' : `"${elmAttrValue}"`}`, owner);
|
|
7333
|
+
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found ${isNull(elmAttrValue) ? 'null' : `"${elmAttrValue}"`}`, vnode.owner);
|
|
7104
7334
|
}
|
|
7105
7335
|
nodesAreCompatible = false;
|
|
7106
7336
|
}
|
|
7107
7337
|
}
|
|
7108
7338
|
return nodesAreCompatible;
|
|
7109
7339
|
}
|
|
7110
|
-
function validateClassAttr(vnode, elm, renderer) {
|
|
7111
|
-
const {
|
|
7340
|
+
function validateClassAttr(vnode, elm, data, renderer) {
|
|
7341
|
+
const { owner } = vnode;
|
|
7342
|
+
// classMap is never available on VStaticPartData so it can default to undefined
|
|
7343
|
+
// casting to prevent TS error.
|
|
7112
7344
|
let { className, classMap } = data;
|
|
7113
7345
|
const { getProperty, getClassList, getAttribute } = renderer;
|
|
7114
7346
|
// we don't care about legacy for hydration. it's a new use case
|
|
@@ -7181,8 +7413,9 @@ function validateClassAttr(vnode, elm, renderer) {
|
|
|
7181
7413
|
}
|
|
7182
7414
|
return nodesAreCompatible;
|
|
7183
7415
|
}
|
|
7184
|
-
function validateStyleAttr(vnode, elm, renderer) {
|
|
7185
|
-
|
|
7416
|
+
function validateStyleAttr(vnode, elm, data, renderer) {
|
|
7417
|
+
// Note styleDecls is always undefined for VStaticPartData, casting here to default it to undefined
|
|
7418
|
+
const { style, styleDecls } = data;
|
|
7186
7419
|
const { getAttribute } = renderer;
|
|
7187
7420
|
const elmStyle = getAttribute(elm, 'style') || '';
|
|
7188
7421
|
let vnodeStyle;
|
|
@@ -7222,7 +7455,7 @@ function validateStyleAttr(vnode, elm, renderer) {
|
|
|
7222
7455
|
}
|
|
7223
7456
|
return nodesAreCompatible;
|
|
7224
7457
|
}
|
|
7225
|
-
function
|
|
7458
|
+
function areCompatibleStaticNodes(client, ssr, vnode, renderer) {
|
|
7226
7459
|
const { getProperty, getAttribute } = renderer;
|
|
7227
7460
|
if (getProperty(client, 'nodeType') === 3 /* EnvNodeTypes.TEXT */) {
|
|
7228
7461
|
if (!hasCorrectNodeType(vnode, ssr, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
@@ -7239,24 +7472,63 @@ function areCompatibleNodes(client, ssr, vnode, renderer) {
|
|
|
7239
7472
|
if (!hasCorrectNodeType(vnode, ssr, 1 /* EnvNodeTypes.ELEMENT */, renderer)) {
|
|
7240
7473
|
return false;
|
|
7241
7474
|
}
|
|
7475
|
+
const { owner, parts } = vnode;
|
|
7242
7476
|
let isCompatibleElements = true;
|
|
7243
7477
|
if (getProperty(client, 'tagName') !== getProperty(ssr, 'tagName')) {
|
|
7244
7478
|
if (process.env.NODE_ENV !== 'production') {
|
|
7245
|
-
logError(`Hydration mismatch: expecting element with tag "${getProperty(client, 'tagName').toLowerCase()}" but found "${getProperty(ssr, 'tagName').toLowerCase()}".`,
|
|
7479
|
+
logError(`Hydration mismatch: expecting element with tag "${getProperty(client, 'tagName').toLowerCase()}" but found "${getProperty(ssr, 'tagName').toLowerCase()}".`, owner);
|
|
7246
7480
|
}
|
|
7247
7481
|
return false;
|
|
7248
7482
|
}
|
|
7249
7483
|
const clientAttrsNames = getProperty(client, 'getAttributeNames').call(client);
|
|
7250
7484
|
clientAttrsNames.forEach((attrName) => {
|
|
7251
7485
|
if (getAttribute(client, attrName) !== getAttribute(ssr, attrName)) {
|
|
7252
|
-
if
|
|
7253
|
-
|
|
7486
|
+
// Check if the root element attributes have expressions, if it does then we need to delegate hydration
|
|
7487
|
+
// validation to haveCompatibleStaticParts.
|
|
7488
|
+
// Note if there are no parts then it is a fully static fragment.
|
|
7489
|
+
// partId === 0 will always refer to the root element, this is guaranteed by the compiler.
|
|
7490
|
+
if (parts?.[0].partId !== 0) {
|
|
7491
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
7492
|
+
logError(`Mismatch hydrating element <${getProperty(client, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${getAttribute(client, attrName)}" but found "${getAttribute(ssr, attrName)}"`, owner);
|
|
7493
|
+
}
|
|
7494
|
+
isCompatibleElements = false;
|
|
7254
7495
|
}
|
|
7255
|
-
isCompatibleElements = false;
|
|
7256
7496
|
}
|
|
7257
7497
|
});
|
|
7258
7498
|
return isCompatibleElements;
|
|
7259
7499
|
}
|
|
7500
|
+
function haveCompatibleStaticParts(vnode, renderer) {
|
|
7501
|
+
const { parts, owner } = vnode;
|
|
7502
|
+
if (isUndefined$1(parts)) {
|
|
7503
|
+
return true;
|
|
7504
|
+
}
|
|
7505
|
+
// The validation here relies on 2 key invariants:
|
|
7506
|
+
// 1. It's never the case that `parts` is undefined on the server but defined on the client (or vice-versa)
|
|
7507
|
+
// 2. It's never the case that `parts` has one length on the server but another on the client
|
|
7508
|
+
for (const part of parts) {
|
|
7509
|
+
const { elm } = part;
|
|
7510
|
+
if (isVStaticPartElement(part)) {
|
|
7511
|
+
if (!hasCorrectNodeType(vnode, elm, 1 /* EnvNodeTypes.ELEMENT */, renderer)) {
|
|
7512
|
+
return false;
|
|
7513
|
+
}
|
|
7514
|
+
const { data } = part;
|
|
7515
|
+
const hasMatchingAttrs = validateAttrs(vnode, elm, data, renderer, () => true);
|
|
7516
|
+
const hasMatchingStyleAttr = validateStyleAttr(vnode, elm, data, renderer);
|
|
7517
|
+
const hasMatchingClass = validateClassAttr(vnode, elm, data, renderer);
|
|
7518
|
+
if (isFalse(hasMatchingAttrs && hasMatchingStyleAttr && hasMatchingClass)) {
|
|
7519
|
+
return false;
|
|
7520
|
+
}
|
|
7521
|
+
}
|
|
7522
|
+
else {
|
|
7523
|
+
// VStaticPartText
|
|
7524
|
+
if (!hasCorrectNodeType(vnode, elm, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
7525
|
+
return false;
|
|
7526
|
+
}
|
|
7527
|
+
updateTextContent(elm, part, owner, renderer);
|
|
7528
|
+
}
|
|
7529
|
+
}
|
|
7530
|
+
return true;
|
|
7531
|
+
}
|
|
7260
7532
|
|
|
7261
7533
|
/*
|
|
7262
7534
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -7528,5 +7800,5 @@ function readonly(obj) {
|
|
|
7528
7800
|
}
|
|
7529
7801
|
|
|
7530
7802
|
export { LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, computeShadowAndRenderMode, connectRootElement, createContextProviderWithRegister, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentAPIVersion, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerTemplate, runFormAssociatedCallback, runFormDisabledCallback, runFormResetCallback, runFormStateRestoreCallback, sanitizeAttribute, setHooks, shouldBeFormAssociated, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
|
|
7531
|
-
/** version: 6.
|
|
7803
|
+
/** version: 6.4.1 */
|
|
7532
7804
|
//# sourceMappingURL=index.js.map
|