@lwc/engine-core 6.3.3 → 6.4.0
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/utils.d.ts +0 -20
- package/dist/framework/vm.d.ts +8 -6
- package/dist/framework/vnodes.d.ts +19 -1
- package/dist/index.cjs.js +353 -110
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +354 -111
- 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
|
/*
|
|
@@ -499,29 +499,6 @@ function assertNotProd() {
|
|
|
499
499
|
throw new ReferenceError();
|
|
500
500
|
}
|
|
501
501
|
}
|
|
502
|
-
// Temporary fix for when the LWC v5 compiler is used in conjunction with a v6+ engine
|
|
503
|
-
// The old compiler format used the "slot" attribute in the `data` bag, whereas the new
|
|
504
|
-
// format uses the special `slotAssignment` key.
|
|
505
|
-
// This should be removed when the LWC v5 compiler is not used anywhere where it could be mismatched
|
|
506
|
-
// with another LWC engine version.
|
|
507
|
-
// TODO [#3974]: remove temporary logic to support v5 compiler + v6+ engine
|
|
508
|
-
function applyTemporaryCompilerV5SlotFix(data) {
|
|
509
|
-
if (lwcRuntimeFlags.DISABLE_TEMPORARY_V5_COMPILER_SUPPORT) {
|
|
510
|
-
return data;
|
|
511
|
-
}
|
|
512
|
-
const { attrs } = data;
|
|
513
|
-
if (!isUndefined$1(attrs)) {
|
|
514
|
-
const { slot } = attrs;
|
|
515
|
-
if (!isUndefined$1(slot) && !isNull(slot)) {
|
|
516
|
-
return {
|
|
517
|
-
...data,
|
|
518
|
-
attrs: cloneAndOmitKey(attrs, 'slot'),
|
|
519
|
-
slotAssignment: String(slot),
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return data;
|
|
524
|
-
}
|
|
525
502
|
function shouldBeFormAssociated(Ctor) {
|
|
526
503
|
const ctorFormAssociated = Boolean(Ctor.formAssociated);
|
|
527
504
|
const apiVersion = getComponentAPIVersion(Ctor);
|
|
@@ -3668,6 +3645,12 @@ function isVScopedSlotFragment(vnode) {
|
|
|
3668
3645
|
function isVStatic(vnode) {
|
|
3669
3646
|
return vnode.type === 4 /* VNodeType.Static */;
|
|
3670
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
|
+
}
|
|
3671
3654
|
|
|
3672
3655
|
/*
|
|
3673
3656
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -3677,7 +3660,8 @@ function isVStatic(vnode) {
|
|
|
3677
3660
|
*/
|
|
3678
3661
|
const ColonCharCode = 58;
|
|
3679
3662
|
function patchAttributes(oldVnode, vnode, renderer) {
|
|
3680
|
-
const {
|
|
3663
|
+
const { data, elm } = vnode;
|
|
3664
|
+
const { attrs } = data;
|
|
3681
3665
|
if (isUndefined$1(attrs)) {
|
|
3682
3666
|
return;
|
|
3683
3667
|
}
|
|
@@ -3686,7 +3670,8 @@ function patchAttributes(oldVnode, vnode, renderer) {
|
|
|
3686
3670
|
if (oldAttrs === attrs) {
|
|
3687
3671
|
return;
|
|
3688
3672
|
}
|
|
3689
|
-
|
|
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;
|
|
3690
3675
|
const { setAttribute, removeAttribute, setProperty } = renderer;
|
|
3691
3676
|
for (const key in attrs) {
|
|
3692
3677
|
const cur = attrs[key];
|
|
@@ -3790,8 +3775,7 @@ function patchProps(oldVnode, vnode, renderer) {
|
|
|
3790
3775
|
*/
|
|
3791
3776
|
const classNameToClassMap = create(null);
|
|
3792
3777
|
function getMapFromClassName(className) {
|
|
3793
|
-
|
|
3794
|
-
if (className == null) {
|
|
3778
|
+
if (isUndefined$1(className) || isNull(className) || className === '') {
|
|
3795
3779
|
return EmptyObject;
|
|
3796
3780
|
}
|
|
3797
3781
|
// computed class names must be string
|
|
@@ -3830,10 +3814,16 @@ function patchClassAttribute(oldVnode, vnode, renderer) {
|
|
|
3830
3814
|
if (oldClass === newClass) {
|
|
3831
3815
|
return;
|
|
3832
3816
|
}
|
|
3833
|
-
const { getClassList } = renderer;
|
|
3834
|
-
const classList = getClassList(elm);
|
|
3835
3817
|
const newClassMap = getMapFromClassName(newClass);
|
|
3836
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);
|
|
3837
3827
|
let name;
|
|
3838
3828
|
for (name in oldClassMap) {
|
|
3839
3829
|
// remove only if it is not in the new class collection and it is not set from within the instance
|
|
@@ -3855,8 +3845,13 @@ function patchClassAttribute(oldVnode, vnode, renderer) {
|
|
|
3855
3845
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3856
3846
|
*/
|
|
3857
3847
|
// The style property is a string when defined via an expression in the template.
|
|
3858
|
-
function patchStyleAttribute(oldVnode, vnode, renderer) {
|
|
3848
|
+
function patchStyleAttribute(oldVnode, vnode, renderer, owner) {
|
|
3859
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
|
+
}
|
|
3860
3855
|
const oldStyle = isNull(oldVnode) ? undefined : oldVnode.data.style;
|
|
3861
3856
|
if (oldStyle === newStyle) {
|
|
3862
3857
|
return;
|
|
@@ -3877,8 +3872,8 @@ function patchStyleAttribute(oldVnode, vnode, renderer) {
|
|
|
3877
3872
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3878
3873
|
*/
|
|
3879
3874
|
function applyEventListeners(vnode, renderer) {
|
|
3880
|
-
const { elm } = vnode;
|
|
3881
|
-
const on =
|
|
3875
|
+
const { elm, data } = vnode;
|
|
3876
|
+
const { on } = data;
|
|
3882
3877
|
if (isUndefined$1(on)) {
|
|
3883
3878
|
return;
|
|
3884
3879
|
}
|
|
@@ -3955,12 +3950,47 @@ function applyRefs(vnode, owner) {
|
|
|
3955
3950
|
refVNodes[ref] = vnode;
|
|
3956
3951
|
}
|
|
3957
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
|
+
|
|
3958
3982
|
/*
|
|
3959
3983
|
* Copyright (c) 2023, salesforce.com, inc.
|
|
3960
3984
|
* All rights reserved.
|
|
3961
3985
|
* SPDX-License-Identifier: MIT
|
|
3962
3986
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
3963
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
|
+
*/
|
|
3964
3994
|
function traverseAndSetElements(root, parts, renderer) {
|
|
3965
3995
|
const numParts = parts.length;
|
|
3966
3996
|
// Optimization given that, in most cases, there will be one part, and it's just the root
|
|
@@ -4026,18 +4056,30 @@ function mountStaticParts(root, vnode, renderer) {
|
|
|
4026
4056
|
traverseAndSetElements(root, parts, renderer);
|
|
4027
4057
|
// Currently only event listeners and refs are supported for static vnodes
|
|
4028
4058
|
for (const part of parts) {
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
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
|
+
}
|
|
4033
4074
|
}
|
|
4034
4075
|
}
|
|
4035
4076
|
/**
|
|
4036
|
-
*
|
|
4077
|
+
* Updates the static elements based on the content of the VStaticParts
|
|
4037
4078
|
* @param n1 the previous VStatic vnode
|
|
4038
4079
|
* @param n2 the current VStatic vnode
|
|
4080
|
+
* @param renderer the renderer to use
|
|
4039
4081
|
*/
|
|
4040
|
-
function patchStaticParts(n1, n2) {
|
|
4082
|
+
function patchStaticParts(n1, n2, renderer) {
|
|
4041
4083
|
// On the server, we don't support ref (because it relies on renderedCallback), nor do we
|
|
4042
4084
|
// support event listeners (no interactivity), so traversing parts makes no sense
|
|
4043
4085
|
if (!process.env.IS_BROWSER) {
|
|
@@ -4052,12 +4094,49 @@ function patchStaticParts(n1, n2) {
|
|
|
4052
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.');
|
|
4053
4095
|
}
|
|
4054
4096
|
for (let i = 0; i < currParts.length; i++) {
|
|
4097
|
+
const prevPart = prevParts[i];
|
|
4055
4098
|
const part = currParts[i];
|
|
4056
4099
|
// Patch only occurs if the vnode is newly generated, which means the part.elm is always undefined
|
|
4057
4100
|
// Since the vnode and elements are the same we can safely assume that prevParts[i].elm is defined.
|
|
4058
|
-
part.elm =
|
|
4059
|
-
|
|
4060
|
-
|
|
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
|
+
}
|
|
4061
4140
|
}
|
|
4062
4141
|
}
|
|
4063
4142
|
|
|
@@ -4095,7 +4174,7 @@ function patch(n1, n2, parent, renderer) {
|
|
|
4095
4174
|
switch (n2.type) {
|
|
4096
4175
|
case 0 /* VNodeType.Text */:
|
|
4097
4176
|
// VText has no special capability, fallback to the owner's renderer
|
|
4098
|
-
|
|
4177
|
+
patchTextVNode(n1, n2, renderer);
|
|
4099
4178
|
break;
|
|
4100
4179
|
case 1 /* VNodeType.Comment */:
|
|
4101
4180
|
// VComment has no special capability, fallback to the owner's renderer
|
|
@@ -4142,12 +4221,6 @@ function mount(node, parent, renderer, anchor) {
|
|
|
4142
4221
|
break;
|
|
4143
4222
|
}
|
|
4144
4223
|
}
|
|
4145
|
-
function patchText(n1, n2, renderer) {
|
|
4146
|
-
n2.elm = n1.elm;
|
|
4147
|
-
if (n2.text !== n1.text) {
|
|
4148
|
-
updateTextContent(n2, renderer);
|
|
4149
|
-
}
|
|
4150
|
-
}
|
|
4151
4224
|
function mountText(vnode, parent, anchor, renderer) {
|
|
4152
4225
|
const { owner } = vnode;
|
|
4153
4226
|
const { createText } = renderer;
|
|
@@ -4160,7 +4233,7 @@ function patchComment(n1, n2, renderer) {
|
|
|
4160
4233
|
// FIXME: Comment nodes should be static, we shouldn't need to diff them together. However
|
|
4161
4234
|
// it is the case today.
|
|
4162
4235
|
if (n2.text !== n1.text) {
|
|
4163
|
-
updateTextContent(n2, renderer);
|
|
4236
|
+
updateTextContent$1(n2, renderer);
|
|
4164
4237
|
}
|
|
4165
4238
|
}
|
|
4166
4239
|
function mountComment(vnode, parent, anchor, renderer) {
|
|
@@ -4204,7 +4277,7 @@ function patchStatic(n1, n2, renderer) {
|
|
|
4204
4277
|
// slotAssignments can only apply to the top level element, never to a static part.
|
|
4205
4278
|
patchSlotAssignment(n1, n2, renderer);
|
|
4206
4279
|
// The `refs` object is blown away in every re-render, so we always need to re-apply them
|
|
4207
|
-
patchStaticParts(n1, n2);
|
|
4280
|
+
patchStaticParts(n1, n2, renderer);
|
|
4208
4281
|
}
|
|
4209
4282
|
function patchElement(n1, n2, renderer) {
|
|
4210
4283
|
const elm = (n2.elm = n1.elm);
|
|
@@ -4215,19 +4288,20 @@ function mountStatic(vnode, parent, anchor, renderer) {
|
|
|
4215
4288
|
const { owner } = vnode;
|
|
4216
4289
|
const { cloneNode, isSyntheticShadowDefined } = renderer;
|
|
4217
4290
|
const elm = (vnode.elm = cloneNode(vnode.fragment, true));
|
|
4291
|
+
// Define the root node shadow resolver
|
|
4218
4292
|
linkNodeToShadow(elm, owner, renderer);
|
|
4219
4293
|
applyElementRestrictions(elm, vnode);
|
|
4220
|
-
// Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
|
|
4221
4294
|
const { renderMode, shadowMode } = owner;
|
|
4222
4295
|
if (isSyntheticShadowDefined) {
|
|
4296
|
+
// Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
|
|
4223
4297
|
if (shadowMode === 1 /* ShadowMode.Synthetic */ || renderMode === 0 /* RenderMode.Light */) {
|
|
4224
4298
|
elm[KEY__SHADOW_STATIC] = true;
|
|
4225
4299
|
}
|
|
4226
4300
|
}
|
|
4227
4301
|
// slotAssignments can only apply to the top level element, never to a static part.
|
|
4228
4302
|
patchSlotAssignment(null, vnode, renderer);
|
|
4229
|
-
insertNode(elm, parent, anchor, renderer);
|
|
4230
4303
|
mountStaticParts(elm, vnode, renderer);
|
|
4304
|
+
insertNode(elm, parent, anchor, renderer);
|
|
4231
4305
|
}
|
|
4232
4306
|
function mountCustomElement(vnode, parent, anchor, renderer) {
|
|
4233
4307
|
const { sel, owner, ctor } = vnode;
|
|
@@ -4392,17 +4466,6 @@ function linkNodeToShadow(elm, owner, renderer) {
|
|
|
4392
4466
|
}
|
|
4393
4467
|
}
|
|
4394
4468
|
}
|
|
4395
|
-
function updateTextContent(vnode, renderer) {
|
|
4396
|
-
const { elm, text } = vnode;
|
|
4397
|
-
const { setText } = renderer;
|
|
4398
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
4399
|
-
unlockDomMutation();
|
|
4400
|
-
}
|
|
4401
|
-
setText(elm, text);
|
|
4402
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
4403
|
-
lockDomMutation();
|
|
4404
|
-
}
|
|
4405
|
-
}
|
|
4406
4469
|
function insertFragmentOrNode(vnode, parent, anchor, renderer) {
|
|
4407
4470
|
if (process.env.NODE_ENV !== 'production') {
|
|
4408
4471
|
unlockDomMutation();
|
|
@@ -4447,15 +4510,16 @@ function patchElementPropsAndAttrsAndRefs$1(oldVnode, vnode, renderer) {
|
|
|
4447
4510
|
applyStaticClassAttribute(vnode, renderer);
|
|
4448
4511
|
applyStaticStyleAttribute(vnode, renderer);
|
|
4449
4512
|
}
|
|
4513
|
+
const { owner } = vnode;
|
|
4450
4514
|
// Attrs need to be applied to element before props IE11 will wipe out value on radio inputs if
|
|
4451
4515
|
// value is set before type=radio.
|
|
4452
4516
|
patchClassAttribute(oldVnode, vnode, renderer);
|
|
4453
|
-
patchStyleAttribute(oldVnode, vnode, renderer);
|
|
4517
|
+
patchStyleAttribute(oldVnode, vnode, renderer, owner);
|
|
4454
4518
|
patchAttributes(oldVnode, vnode, renderer);
|
|
4455
4519
|
patchProps(oldVnode, vnode, renderer);
|
|
4456
4520
|
patchSlotAssignment(oldVnode, vnode, renderer);
|
|
4457
4521
|
// The `refs` object is blown away in every re-render, so we always need to re-apply them
|
|
4458
|
-
applyRefs(vnode,
|
|
4522
|
+
applyRefs(vnode, owner);
|
|
4459
4523
|
}
|
|
4460
4524
|
function applyStyleScoping(elm, owner, renderer) {
|
|
4461
4525
|
const { getClassList } = renderer;
|
|
@@ -4857,10 +4921,14 @@ function addVNodeToChildLWC(vnode) {
|
|
|
4857
4921
|
ArrayPush$1.call(getVMBeingRendered().velements, vnode);
|
|
4858
4922
|
}
|
|
4859
4923
|
// [s]tatic [p]art
|
|
4860
|
-
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 */;
|
|
4861
4927
|
return {
|
|
4928
|
+
type,
|
|
4862
4929
|
partId,
|
|
4863
4930
|
data,
|
|
4931
|
+
text,
|
|
4864
4932
|
elm: undefined, // elm is defined later
|
|
4865
4933
|
};
|
|
4866
4934
|
}
|
|
@@ -4877,8 +4945,9 @@ function ssf(slotName, factory) {
|
|
|
4877
4945
|
};
|
|
4878
4946
|
}
|
|
4879
4947
|
// [st]atic node
|
|
4880
|
-
function st(
|
|
4948
|
+
function st(fragmentFactory, key, parts) {
|
|
4881
4949
|
const owner = getVMBeingRendered();
|
|
4950
|
+
const fragment = fragmentFactory(parts);
|
|
4882
4951
|
const vnode = {
|
|
4883
4952
|
type: 4 /* VNodeType.Static */,
|
|
4884
4953
|
sel: undefined,
|
|
@@ -4920,9 +4989,6 @@ function h(sel, data, children = EmptyArray) {
|
|
|
4920
4989
|
// checking reserved internal data properties
|
|
4921
4990
|
assert.isFalse(data.className && data.classMap, `vnode.data.className and vnode.data.classMap ambiguous declaration.`);
|
|
4922
4991
|
assert.isFalse(data.styleDecls && data.style, `vnode.data.styleDecls and vnode.data.style ambiguous declaration.`);
|
|
4923
|
-
if (data.style && !isString(data.style)) {
|
|
4924
|
-
logError(`Invalid 'style' attribute passed to <${sel}> is ignored. This attribute must be a string value.`, vmBeingRendered);
|
|
4925
|
-
}
|
|
4926
4992
|
forEach.call(children, (childVnode) => {
|
|
4927
4993
|
if (childVnode != null) {
|
|
4928
4994
|
assert.isTrue('type' in childVnode &&
|
|
@@ -4932,8 +4998,6 @@ function h(sel, data, children = EmptyArray) {
|
|
|
4932
4998
|
}
|
|
4933
4999
|
});
|
|
4934
5000
|
}
|
|
4935
|
-
// TODO [#3974]: remove temporary logic to support v5 compiler + v6+ engine
|
|
4936
|
-
data = applyTemporaryCompilerV5SlotFix(data);
|
|
4937
5001
|
const { key, slotAssignment } = data;
|
|
4938
5002
|
const vnode = {
|
|
4939
5003
|
type: 2 /* VNodeType.Element */,
|
|
@@ -4970,8 +5034,6 @@ function s(slotName, data, children, slotset) {
|
|
|
4970
5034
|
}
|
|
4971
5035
|
const vmBeingRendered = getVMBeingRendered();
|
|
4972
5036
|
const { renderMode, apiVersion } = vmBeingRendered;
|
|
4973
|
-
// TODO [#3974]: remove temporary logic to support v5 compiler + v6+ engine
|
|
4974
|
-
data = applyTemporaryCompilerV5SlotFix(data);
|
|
4975
5037
|
if (!isUndefined$1(slotset) &&
|
|
4976
5038
|
!isUndefined$1(slotset.slotAssignments) &&
|
|
4977
5039
|
!isUndefined$1(slotset.slotAssignments[slotName]) &&
|
|
@@ -5075,8 +5137,6 @@ function c(sel, Ctor, data, children = EmptyArray) {
|
|
|
5075
5137
|
});
|
|
5076
5138
|
}
|
|
5077
5139
|
}
|
|
5078
|
-
// TODO [#3974]: remove temporary logic to support v5 compiler + v6+ engine
|
|
5079
|
-
data = applyTemporaryCompilerV5SlotFix(data);
|
|
5080
5140
|
const { key, slotAssignment } = data;
|
|
5081
5141
|
let elm, aChildren, vm;
|
|
5082
5142
|
const vnode = {
|
|
@@ -5138,16 +5198,19 @@ function i(iterable, factory) {
|
|
|
5138
5198
|
if (process.env.NODE_ENV !== 'production') {
|
|
5139
5199
|
const vnodes = isArray$1(vnode) ? vnode : [vnode];
|
|
5140
5200
|
forEach.call(vnodes, (childVnode) => {
|
|
5141
|
-
|
|
5201
|
+
// Check that the child vnode is either an element or VStatic
|
|
5202
|
+
if (!isNull(childVnode) && (isVBaseElement(childVnode) || isVStatic(childVnode))) {
|
|
5142
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;
|
|
5143
5206
|
if (isString(key) || isNumber(key)) {
|
|
5144
5207
|
if (keyMap[key] === 1 && isUndefined$1(iterationError)) {
|
|
5145
|
-
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.`;
|
|
5146
5209
|
}
|
|
5147
5210
|
keyMap[key] = 1;
|
|
5148
5211
|
}
|
|
5149
5212
|
else if (isUndefined$1(iterationError)) {
|
|
5150
|
-
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.`;
|
|
5151
5214
|
}
|
|
5152
5215
|
}
|
|
5153
5216
|
});
|
|
@@ -5546,6 +5609,111 @@ function validateLightDomTemplate(template, vm) {
|
|
|
5546
5609
|
}
|
|
5547
5610
|
}
|
|
5548
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
|
+
}
|
|
5549
5717
|
// This should be a no-op outside of LWC's Karma tests, where it's not needed
|
|
5550
5718
|
let registerFragmentCache = noop;
|
|
5551
5719
|
// Only used in LWC's Karma tests
|
|
@@ -5567,7 +5735,7 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5567
5735
|
return (strings, ...keys) => {
|
|
5568
5736
|
const cache = create(null);
|
|
5569
5737
|
registerFragmentCache(cache);
|
|
5570
|
-
return function () {
|
|
5738
|
+
return function (parts) {
|
|
5571
5739
|
const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
|
|
5572
5740
|
const hasStyleToken = !isUndefined$1(stylesheetToken);
|
|
5573
5741
|
const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
|
|
@@ -5579,14 +5747,27 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5579
5747
|
if (hasStyleToken && isSyntheticShadow) {
|
|
5580
5748
|
cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
|
|
5581
5749
|
}
|
|
5582
|
-
|
|
5583
|
-
|
|
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
|
+
}
|
|
5584
5757
|
}
|
|
5585
5758
|
// If legacy stylesheet tokens are required, then add them to the rendered string
|
|
5586
5759
|
const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
|
|
5587
5760
|
const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetTokenToRender : '';
|
|
5588
5761
|
const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetTokenToRender}"` : '';
|
|
5589
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);
|
|
5590
5771
|
let htmlFragment = '';
|
|
5591
5772
|
for (let i = 0, n = keys.length; i < n; i++) {
|
|
5592
5773
|
switch (keys[i]) {
|
|
@@ -5602,6 +5783,10 @@ function buildParseFragmentFn(createFragmentFn) {
|
|
|
5602
5783
|
case 3: // ${1}${2}
|
|
5603
5784
|
htmlFragment += strings[i] + classAttrToken + attrToken;
|
|
5604
5785
|
break;
|
|
5786
|
+
default: // expressions ${partId:attributeName/textId}
|
|
5787
|
+
htmlFragment +=
|
|
5788
|
+
strings[i] + serializeExpression(keys[i], exprClassToken);
|
|
5789
|
+
break;
|
|
5605
5790
|
}
|
|
5606
5791
|
}
|
|
5607
5792
|
htmlFragment += strings[strings.length - 1];
|
|
@@ -6484,25 +6669,25 @@ function forceRehydration(vm) {
|
|
|
6484
6669
|
scheduleRehydration(vm);
|
|
6485
6670
|
}
|
|
6486
6671
|
}
|
|
6487
|
-
function runFormAssociatedCustomElementCallback(vm, faceCb) {
|
|
6672
|
+
function runFormAssociatedCustomElementCallback(vm, faceCb, args) {
|
|
6488
6673
|
const { renderMode, shadowMode } = vm;
|
|
6489
6674
|
if (shadowMode === 1 /* ShadowMode.Synthetic */ && renderMode !== 0 /* RenderMode.Light */) {
|
|
6490
6675
|
throw new Error('Form associated lifecycle methods are not available in synthetic shadow. Please use native shadow or light DOM.');
|
|
6491
6676
|
}
|
|
6492
|
-
invokeComponentCallback(vm, faceCb);
|
|
6677
|
+
invokeComponentCallback(vm, faceCb, args);
|
|
6493
6678
|
}
|
|
6494
|
-
function runFormAssociatedCallback(elm) {
|
|
6679
|
+
function runFormAssociatedCallback(elm, form) {
|
|
6495
6680
|
const vm = getAssociatedVM(elm);
|
|
6496
6681
|
const { formAssociatedCallback } = vm.def;
|
|
6497
6682
|
if (!isUndefined$1(formAssociatedCallback)) {
|
|
6498
|
-
runFormAssociatedCustomElementCallback(vm, formAssociatedCallback);
|
|
6683
|
+
runFormAssociatedCustomElementCallback(vm, formAssociatedCallback, [form]);
|
|
6499
6684
|
}
|
|
6500
6685
|
}
|
|
6501
|
-
function runFormDisabledCallback(elm) {
|
|
6686
|
+
function runFormDisabledCallback(elm, disabled) {
|
|
6502
6687
|
const vm = getAssociatedVM(elm);
|
|
6503
6688
|
const { formDisabledCallback } = vm.def;
|
|
6504
6689
|
if (!isUndefined$1(formDisabledCallback)) {
|
|
6505
|
-
runFormAssociatedCustomElementCallback(vm, formDisabledCallback);
|
|
6690
|
+
runFormAssociatedCustomElementCallback(vm, formDisabledCallback, [disabled]);
|
|
6506
6691
|
}
|
|
6507
6692
|
}
|
|
6508
6693
|
function runFormResetCallback(elm) {
|
|
@@ -6512,11 +6697,11 @@ function runFormResetCallback(elm) {
|
|
|
6512
6697
|
runFormAssociatedCustomElementCallback(vm, formResetCallback);
|
|
6513
6698
|
}
|
|
6514
6699
|
}
|
|
6515
|
-
function runFormStateRestoreCallback(elm) {
|
|
6700
|
+
function runFormStateRestoreCallback(elm, state, reason) {
|
|
6516
6701
|
const vm = getAssociatedVM(elm);
|
|
6517
6702
|
const { formStateRestoreCallback } = vm.def;
|
|
6518
6703
|
if (!isUndefined$1(formStateRestoreCallback)) {
|
|
6519
|
-
runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
|
|
6704
|
+
runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback, [state, reason]);
|
|
6520
6705
|
}
|
|
6521
6706
|
}
|
|
6522
6707
|
function resetRefVNodes(vm) {
|
|
@@ -6884,9 +7069,12 @@ function hydrateText(node, vnode, renderer) {
|
|
|
6884
7069
|
if (!hasCorrectNodeType(vnode, node, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
6885
7070
|
return handleMismatch(node, vnode, renderer);
|
|
6886
7071
|
}
|
|
7072
|
+
return updateTextContent(node, vnode, vnode.owner, renderer);
|
|
7073
|
+
}
|
|
7074
|
+
function updateTextContent(node, vnode, owner, renderer) {
|
|
6887
7075
|
if (process.env.NODE_ENV !== 'production') {
|
|
6888
7076
|
if (!textNodeContentsAreEqual(node, vnode, renderer)) {
|
|
6889
|
-
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);
|
|
6890
7078
|
}
|
|
6891
7079
|
}
|
|
6892
7080
|
const { setText } = renderer;
|
|
@@ -6912,11 +7100,24 @@ function hydrateComment(node, vnode, renderer) {
|
|
|
6912
7100
|
}
|
|
6913
7101
|
function hydrateStaticElement(elm, vnode, renderer) {
|
|
6914
7102
|
if (!hasCorrectNodeType(vnode, elm, 1 /* EnvNodeTypes.ELEMENT */, renderer) ||
|
|
6915
|
-
!
|
|
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)) {
|
|
6916
7115
|
return handleMismatch(elm, vnode, renderer);
|
|
6917
7116
|
}
|
|
6918
7117
|
vnode.elm = elm;
|
|
6919
|
-
|
|
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);
|
|
6920
7121
|
return elm;
|
|
6921
7122
|
}
|
|
6922
7123
|
function hydrateFragment(elm, vnode, renderer) {
|
|
@@ -7092,12 +7293,13 @@ function isMatchingElement(vnode, elm, renderer, shouldValidateAttr = () => true
|
|
|
7092
7293
|
}
|
|
7093
7294
|
return false;
|
|
7094
7295
|
}
|
|
7095
|
-
const
|
|
7296
|
+
const { data } = vnode;
|
|
7297
|
+
const hasCompatibleAttrs = validateAttrs(vnode, elm, data, renderer, shouldValidateAttr);
|
|
7096
7298
|
const hasCompatibleClass = shouldValidateAttr('class')
|
|
7097
|
-
? validateClassAttr(vnode, elm, renderer)
|
|
7299
|
+
? validateClassAttr(vnode, elm, data, renderer)
|
|
7098
7300
|
: true;
|
|
7099
7301
|
const hasCompatibleStyle = shouldValidateAttr('style')
|
|
7100
|
-
? validateStyleAttr(vnode, elm, renderer)
|
|
7302
|
+
? validateStyleAttr(vnode, elm, data, renderer)
|
|
7101
7303
|
: true;
|
|
7102
7304
|
return hasCompatibleAttrs && hasCompatibleClass && hasCompatibleStyle;
|
|
7103
7305
|
}
|
|
@@ -7114,8 +7316,8 @@ function attributeValuesAreEqual(vnodeValue, value) {
|
|
|
7114
7316
|
// In all other cases, the two values are not considered equal
|
|
7115
7317
|
return false;
|
|
7116
7318
|
}
|
|
7117
|
-
function validateAttrs(vnode, elm, renderer, shouldValidateAttr) {
|
|
7118
|
-
const {
|
|
7319
|
+
function validateAttrs(vnode, elm, data, renderer, shouldValidateAttr) {
|
|
7320
|
+
const { attrs = {} } = data;
|
|
7119
7321
|
let nodesAreCompatible = true;
|
|
7120
7322
|
// Validate attributes, though we could always recovery from those by running the update mods.
|
|
7121
7323
|
// Note: intentionally ONLY matching vnodes.attrs to elm.attrs, in case SSR is adding extra attributes.
|
|
@@ -7123,21 +7325,22 @@ function validateAttrs(vnode, elm, renderer, shouldValidateAttr) {
|
|
|
7123
7325
|
if (!shouldValidateAttr(attrName)) {
|
|
7124
7326
|
continue;
|
|
7125
7327
|
}
|
|
7126
|
-
const { owner } = vnode;
|
|
7127
7328
|
const { getAttribute } = renderer;
|
|
7128
7329
|
const elmAttrValue = getAttribute(elm, attrName);
|
|
7129
7330
|
if (!attributeValuesAreEqual(attrValue, elmAttrValue)) {
|
|
7130
7331
|
if (process.env.NODE_ENV !== 'production') {
|
|
7131
7332
|
const { getProperty } = renderer;
|
|
7132
|
-
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);
|
|
7133
7334
|
}
|
|
7134
7335
|
nodesAreCompatible = false;
|
|
7135
7336
|
}
|
|
7136
7337
|
}
|
|
7137
7338
|
return nodesAreCompatible;
|
|
7138
7339
|
}
|
|
7139
|
-
function validateClassAttr(vnode, elm, renderer) {
|
|
7140
|
-
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.
|
|
7141
7344
|
let { className, classMap } = data;
|
|
7142
7345
|
const { getProperty, getClassList, getAttribute } = renderer;
|
|
7143
7346
|
// we don't care about legacy for hydration. it's a new use case
|
|
@@ -7210,8 +7413,9 @@ function validateClassAttr(vnode, elm, renderer) {
|
|
|
7210
7413
|
}
|
|
7211
7414
|
return nodesAreCompatible;
|
|
7212
7415
|
}
|
|
7213
|
-
function validateStyleAttr(vnode, elm, renderer) {
|
|
7214
|
-
|
|
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;
|
|
7215
7419
|
const { getAttribute } = renderer;
|
|
7216
7420
|
const elmStyle = getAttribute(elm, 'style') || '';
|
|
7217
7421
|
let vnodeStyle;
|
|
@@ -7251,7 +7455,7 @@ function validateStyleAttr(vnode, elm, renderer) {
|
|
|
7251
7455
|
}
|
|
7252
7456
|
return nodesAreCompatible;
|
|
7253
7457
|
}
|
|
7254
|
-
function
|
|
7458
|
+
function areCompatibleStaticNodes(client, ssr, vnode, renderer) {
|
|
7255
7459
|
const { getProperty, getAttribute } = renderer;
|
|
7256
7460
|
if (getProperty(client, 'nodeType') === 3 /* EnvNodeTypes.TEXT */) {
|
|
7257
7461
|
if (!hasCorrectNodeType(vnode, ssr, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
@@ -7268,24 +7472,63 @@ function areCompatibleNodes(client, ssr, vnode, renderer) {
|
|
|
7268
7472
|
if (!hasCorrectNodeType(vnode, ssr, 1 /* EnvNodeTypes.ELEMENT */, renderer)) {
|
|
7269
7473
|
return false;
|
|
7270
7474
|
}
|
|
7475
|
+
const { owner, parts } = vnode;
|
|
7271
7476
|
let isCompatibleElements = true;
|
|
7272
7477
|
if (getProperty(client, 'tagName') !== getProperty(ssr, 'tagName')) {
|
|
7273
7478
|
if (process.env.NODE_ENV !== 'production') {
|
|
7274
|
-
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);
|
|
7275
7480
|
}
|
|
7276
7481
|
return false;
|
|
7277
7482
|
}
|
|
7278
7483
|
const clientAttrsNames = getProperty(client, 'getAttributeNames').call(client);
|
|
7279
7484
|
clientAttrsNames.forEach((attrName) => {
|
|
7280
7485
|
if (getAttribute(client, attrName) !== getAttribute(ssr, attrName)) {
|
|
7281
|
-
if
|
|
7282
|
-
|
|
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;
|
|
7283
7495
|
}
|
|
7284
|
-
isCompatibleElements = false;
|
|
7285
7496
|
}
|
|
7286
7497
|
});
|
|
7287
7498
|
return isCompatibleElements;
|
|
7288
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
|
+
}
|
|
7289
7532
|
|
|
7290
7533
|
/*
|
|
7291
7534
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -7557,5 +7800,5 @@ function readonly(obj) {
|
|
|
7557
7800
|
}
|
|
7558
7801
|
|
|
7559
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 };
|
|
7560
|
-
/** version: 6.
|
|
7803
|
+
/** version: 6.4.0 */
|
|
7561
7804
|
//# sourceMappingURL=index.js.map
|