@lwc/engine-core 8.8.0 → 8.10.0-alpha.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 +4 -4
- package/dist/framework/base-bridge-element.d.ts +1 -1
- package/dist/framework/base-lightning-element.d.ts +4 -13
- package/dist/framework/check-version-mismatch.d.ts +2 -2
- package/dist/framework/component.d.ts +6 -6
- package/dist/framework/decorators/register.d.ts +2 -2
- package/dist/framework/def.d.ts +7 -5
- package/dist/framework/freeze-template.d.ts +1 -1
- package/dist/framework/get-component-constructor.d.ts +1 -1
- package/dist/framework/hot-swaps.d.ts +3 -3
- package/dist/framework/hydration.d.ts +1 -1
- package/dist/framework/invoker.d.ts +3 -3
- package/dist/framework/modules/attrs.d.ts +2 -2
- package/dist/framework/modules/computed-class-attr.d.ts +2 -2
- package/dist/framework/modules/computed-style-attr.d.ts +3 -3
- package/dist/framework/modules/events.d.ts +2 -2
- package/dist/framework/modules/props.d.ts +2 -2
- package/dist/framework/modules/refs.d.ts +2 -2
- package/dist/framework/modules/static-class-attr.d.ts +2 -2
- package/dist/framework/modules/static-parts.d.ts +2 -2
- package/dist/framework/modules/static-style-attr.d.ts +2 -2
- package/dist/framework/modules/text.d.ts +2 -2
- package/dist/framework/mutation-logger.d.ts +2 -2
- package/dist/framework/mutation-tracker.d.ts +3 -2
- package/dist/framework/profiler.d.ts +2 -1
- package/dist/framework/rendering.d.ts +3 -3
- package/dist/framework/reporting.d.ts +1 -1
- package/dist/framework/secure-template.d.ts +1 -1
- package/dist/framework/stylesheet.d.ts +3 -3
- package/dist/framework/template.d.ts +3 -3
- package/dist/framework/update-component-value.d.ts +1 -1
- package/dist/framework/utils.d.ts +1 -1
- package/dist/framework/vm.d.ts +7 -8
- package/dist/framework/wiring/context.d.ts +2 -2
- package/dist/framework/wiring/wiring.d.ts +1 -1
- package/dist/index.cjs.js +201 -85
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +202 -86
- package/dist/index.js.map +1 -1
- package/dist/libs/aria-reflection/attr-reflection.d.ts +2 -0
- package/dist/libs/reflection/aria-reflection.d.ts +1 -0
- package/dist/libs/reflection/attr-reflection.d.ts +2 -0
- package/dist/libs/reflection/index.d.ts +2 -0
- package/dist/shared/error.d.ts +1 -1
- package/dist/shared/format.d.ts +1 -1
- package/dist/shared/logger.d.ts +1 -1
- package/package.json +5 -5
package/dist/index.cjs.js
CHANGED
|
@@ -685,6 +685,129 @@ for (const [propName, attrName] of shared.entries(shared.AriaPropNameToAttrNameM
|
|
|
685
685
|
}
|
|
686
686
|
}
|
|
687
687
|
|
|
688
|
+
/*
|
|
689
|
+
* Copyright (c) 2024, Salesforce, Inc.
|
|
690
|
+
* All rights reserved.
|
|
691
|
+
* SPDX-License-Identifier: MIT
|
|
692
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
693
|
+
*/
|
|
694
|
+
/**
|
|
695
|
+
* Descriptor for IDL attribute reflections that merely reflect the string, e.g. `title`.
|
|
696
|
+
*/
|
|
697
|
+
const stringDescriptor = (attrName) => ({
|
|
698
|
+
configurable: true,
|
|
699
|
+
enumerable: true,
|
|
700
|
+
get() {
|
|
701
|
+
return this.getAttribute(attrName);
|
|
702
|
+
},
|
|
703
|
+
set(newValue) {
|
|
704
|
+
const currentValue = this.getAttribute(attrName);
|
|
705
|
+
const normalizedValue = String(newValue);
|
|
706
|
+
if (normalizedValue !== currentValue) {
|
|
707
|
+
this.setAttribute(attrName, normalizedValue);
|
|
708
|
+
}
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
/** Descriptor for a boolean that checks for `attr="true"` or `attr="false"`, e.g. `spellcheck` and `draggable`. */
|
|
712
|
+
const explicitBooleanDescriptor = (attrName, defaultValue) => ({
|
|
713
|
+
configurable: true,
|
|
714
|
+
enumerable: true,
|
|
715
|
+
get() {
|
|
716
|
+
const value = this.getAttribute(attrName);
|
|
717
|
+
if (value === null)
|
|
718
|
+
return defaultValue;
|
|
719
|
+
// spellcheck=false => false, everything else => true
|
|
720
|
+
// draggable=true => true, everything else => false
|
|
721
|
+
return value.toLowerCase() === String(defaultValue) ? defaultValue : !defaultValue;
|
|
722
|
+
},
|
|
723
|
+
set(newValue) {
|
|
724
|
+
const currentValue = this.getAttribute(attrName);
|
|
725
|
+
const normalizedValue = String(Boolean(newValue));
|
|
726
|
+
if (normalizedValue !== currentValue) {
|
|
727
|
+
this.setAttribute(attrName, normalizedValue);
|
|
728
|
+
}
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
/**
|
|
732
|
+
* Descriptor for a "true" boolean attribute that checks solely for presence, e.g. `hidden`.
|
|
733
|
+
*/
|
|
734
|
+
const booleanAttributeDescriptor = (attrName) => ({
|
|
735
|
+
configurable: true,
|
|
736
|
+
enumerable: true,
|
|
737
|
+
get() {
|
|
738
|
+
return this.hasAttribute(attrName);
|
|
739
|
+
},
|
|
740
|
+
set(newValue) {
|
|
741
|
+
const hasAttribute = this.hasAttribute(attrName);
|
|
742
|
+
if (newValue) {
|
|
743
|
+
if (!hasAttribute) {
|
|
744
|
+
this.setAttribute(attrName, '');
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
if (hasAttribute) {
|
|
749
|
+
this.removeAttribute(attrName);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
},
|
|
753
|
+
});
|
|
754
|
+
/**
|
|
755
|
+
* Descriptor for ARIA reflections, e.g. `ariaLabel` and `role`.
|
|
756
|
+
*/
|
|
757
|
+
const ariaDescriptor = (attrName) => ({
|
|
758
|
+
configurable: true,
|
|
759
|
+
enumerable: true,
|
|
760
|
+
get() {
|
|
761
|
+
return this.getAttribute(attrName);
|
|
762
|
+
},
|
|
763
|
+
set(newValue) {
|
|
764
|
+
const currentValue = this.getAttribute(attrName);
|
|
765
|
+
if (newValue !== currentValue) {
|
|
766
|
+
// TODO [#3284]: According to the spec, IDL nullable type values
|
|
767
|
+
// (null and undefined) should remove the attribute; however, we
|
|
768
|
+
// only do so in the case of null for historical reasons.
|
|
769
|
+
if (shared.isNull(newValue)) {
|
|
770
|
+
this.removeAttribute(attrName);
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
this.setAttribute(attrName, shared.toString(newValue));
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
},
|
|
777
|
+
});
|
|
778
|
+
const tabIndexDescriptor = () => ({
|
|
779
|
+
configurable: true,
|
|
780
|
+
enumerable: true,
|
|
781
|
+
get() {
|
|
782
|
+
const str = this.getAttribute('tabindex');
|
|
783
|
+
const num = Number(str);
|
|
784
|
+
return isFinite(num) ? Math.trunc(num) : -1;
|
|
785
|
+
},
|
|
786
|
+
set(newValue) {
|
|
787
|
+
const currentValue = this.getAttribute('tabindex');
|
|
788
|
+
const num = Number(newValue);
|
|
789
|
+
const normalizedValue = isFinite(num) ? String(Math.trunc(num)) : '0';
|
|
790
|
+
if (normalizedValue !== currentValue) {
|
|
791
|
+
this.setAttribute('tabindex', shared.toString(newValue));
|
|
792
|
+
}
|
|
793
|
+
},
|
|
794
|
+
});
|
|
795
|
+
const descriptors = {
|
|
796
|
+
accessKey: stringDescriptor('accesskey'),
|
|
797
|
+
dir: stringDescriptor('dir'),
|
|
798
|
+
draggable: explicitBooleanDescriptor('draggable', true),
|
|
799
|
+
hidden: booleanAttributeDescriptor('hidden'),
|
|
800
|
+
id: stringDescriptor('id'),
|
|
801
|
+
lang: stringDescriptor('lang'),
|
|
802
|
+
spellcheck: explicitBooleanDescriptor('spellcheck', false),
|
|
803
|
+
tabIndex: tabIndexDescriptor(),
|
|
804
|
+
title: stringDescriptor('title'),
|
|
805
|
+
};
|
|
806
|
+
// Add descriptors for ARIA attributes
|
|
807
|
+
for (const [attrName, propName] of shared.entries(shared.AriaAttrNameToPropNameMap)) {
|
|
808
|
+
descriptors[propName] = ariaDescriptor(attrName);
|
|
809
|
+
}
|
|
810
|
+
|
|
688
811
|
/*
|
|
689
812
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
690
813
|
* All rights reserved.
|
|
@@ -948,6 +1071,12 @@ function patchCustomElementWithRestrictions(elm) {
|
|
|
948
1071
|
shared.setPrototypeOf(elm, shared.create(elmProto, restrictionsDescriptors));
|
|
949
1072
|
}
|
|
950
1073
|
|
|
1074
|
+
/*
|
|
1075
|
+
* Copyright (c) 2018, salesforce.com, inc.
|
|
1076
|
+
* All rights reserved.
|
|
1077
|
+
* SPDX-License-Identifier: MIT
|
|
1078
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
1079
|
+
*/
|
|
951
1080
|
function updateComponentValue(vm, key, newValue) {
|
|
952
1081
|
const { cmpFields } = vm;
|
|
953
1082
|
if (newValue !== cmpFields[key]) {
|
|
@@ -2088,7 +2217,7 @@ if (process.env.IS_BROWSER) {
|
|
|
2088
2217
|
else {
|
|
2089
2218
|
// On the server, we cannot use createBridgeToElementDescriptor because getAttribute/setAttribute are
|
|
2090
2219
|
// not supported on HTMLElement. So apply the polyfill directly on top of LightningElement
|
|
2091
|
-
shared.defineProperties(LightningElement.prototype,
|
|
2220
|
+
shared.defineProperties(LightningElement.prototype, descriptors);
|
|
2092
2221
|
}
|
|
2093
2222
|
shared.defineProperties(LightningElement.prototype, lightningBasedDescriptors);
|
|
2094
2223
|
shared.defineProperty(LightningElement, 'CustomElementConstructor', {
|
|
@@ -2099,6 +2228,12 @@ shared.defineProperty(LightningElement, 'CustomElementConstructor', {
|
|
|
2099
2228
|
configurable: true,
|
|
2100
2229
|
});
|
|
2101
2230
|
|
|
2231
|
+
/*
|
|
2232
|
+
* Copyright (c) 2018, salesforce.com, inc.
|
|
2233
|
+
* All rights reserved.
|
|
2234
|
+
* SPDX-License-Identifier: MIT
|
|
2235
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
2236
|
+
*/
|
|
2102
2237
|
function createObservedFieldPropertyDescriptor(key) {
|
|
2103
2238
|
return {
|
|
2104
2239
|
get() {
|
|
@@ -2832,6 +2967,12 @@ function checkVersionMismatch(func, type) {
|
|
|
2832
2967
|
}
|
|
2833
2968
|
}
|
|
2834
2969
|
|
|
2970
|
+
/*
|
|
2971
|
+
* Copyright (c) 2018, salesforce.com, inc.
|
|
2972
|
+
* All rights reserved.
|
|
2973
|
+
* SPDX-License-Identifier: MIT
|
|
2974
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
2975
|
+
*/
|
|
2835
2976
|
const signedTemplateSet = new Set();
|
|
2836
2977
|
function defaultEmptyTemplate() {
|
|
2837
2978
|
return [];
|
|
@@ -3163,7 +3304,13 @@ function updateStylesheetToken(vm, template, legacy) {
|
|
|
3163
3304
|
// Set the new styling token on the host element
|
|
3164
3305
|
if (!shared.isUndefined(newToken)) {
|
|
3165
3306
|
if (hasScopedStyles) {
|
|
3166
|
-
|
|
3307
|
+
const hostScopeTokenClass = makeHostToken(newToken);
|
|
3308
|
+
getClassList(elm).add(hostScopeTokenClass);
|
|
3309
|
+
if (!process.env.IS_BROWSER) {
|
|
3310
|
+
// This is only used in SSR to communicate to hydration that
|
|
3311
|
+
// this class should be treated specially for purposes of hydration mismatches.
|
|
3312
|
+
setAttribute(elm, 'data-lwc-host-scope-token', hostScopeTokenClass);
|
|
3313
|
+
}
|
|
3167
3314
|
newHasTokenInClass = true;
|
|
3168
3315
|
}
|
|
3169
3316
|
if (isSyntheticShadow) {
|
|
@@ -3300,21 +3447,6 @@ function getScopeTokenClass(owner, legacy) {
|
|
|
3300
3447
|
(legacy ? cmpTemplate?.legacyStylesheetToken : cmpTemplate?.stylesheetToken)) ||
|
|
3301
3448
|
null);
|
|
3302
3449
|
}
|
|
3303
|
-
/**
|
|
3304
|
-
* This function returns the host style token for a custom element if it
|
|
3305
|
-
* exists. Otherwise it returns null.
|
|
3306
|
-
*
|
|
3307
|
-
* A host style token is applied to the component if scoped styles are used.
|
|
3308
|
-
* @param vnode
|
|
3309
|
-
*/
|
|
3310
|
-
function getStylesheetTokenHost(vnode) {
|
|
3311
|
-
const { template } = getComponentInternalDef(vnode.ctor);
|
|
3312
|
-
const { vm } = vnode;
|
|
3313
|
-
const { stylesheetToken } = template;
|
|
3314
|
-
return !shared.isUndefined(stylesheetToken) && computeHasScopedStyles(template, vm)
|
|
3315
|
-
? makeHostToken(stylesheetToken)
|
|
3316
|
-
: null;
|
|
3317
|
-
}
|
|
3318
3450
|
function getNearestNativeShadowComponent(vm) {
|
|
3319
3451
|
const owner = getNearestShadowComponent(vm);
|
|
3320
3452
|
if (!shared.isNull(owner) && owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
|
|
@@ -3852,7 +3984,6 @@ function getComponentHtmlPrototype(Ctor) {
|
|
|
3852
3984
|
return def.bridge;
|
|
3853
3985
|
}
|
|
3854
3986
|
const lightingElementDef = {
|
|
3855
|
-
ctor: LightningElement,
|
|
3856
3987
|
name: LightningElement.name,
|
|
3857
3988
|
props: lightningBasedDescriptors,
|
|
3858
3989
|
propsConfig: EmptyObject,
|
|
@@ -5762,7 +5893,7 @@ function dc(Ctor, data, children = EmptyArray) {
|
|
|
5762
5893
|
return null;
|
|
5763
5894
|
}
|
|
5764
5895
|
if (!isComponentConstructor(Ctor)) {
|
|
5765
|
-
throw new Error(`Invalid constructor ${shared.toString(Ctor)} is not a LightningElement constructor.`);
|
|
5896
|
+
throw new Error(`Invalid constructor: "${shared.toString(Ctor)}" is not a LightningElement constructor.`);
|
|
5766
5897
|
}
|
|
5767
5898
|
// Look up the dynamic component's name at runtime once the constructor is available.
|
|
5768
5899
|
// This information is only known at runtime and is stored as part of registerComponent.
|
|
@@ -7598,7 +7729,7 @@ function hydrateRoot(vm) {
|
|
|
7598
7729
|
runConnectedCallback(vm);
|
|
7599
7730
|
hydrateVM(vm);
|
|
7600
7731
|
if (hasMismatch && process.env.NODE_ENV !== 'production') {
|
|
7601
|
-
|
|
7732
|
+
logWarn('Hydration completed with errors.', vm);
|
|
7602
7733
|
}
|
|
7603
7734
|
}
|
|
7604
7735
|
function hydrateVM(vm) {
|
|
@@ -7853,7 +7984,7 @@ expectAddlSiblings) {
|
|
|
7853
7984
|
if (process.env.NODE_ENV !== 'production') {
|
|
7854
7985
|
if (!hasWarned) {
|
|
7855
7986
|
hasWarned = true;
|
|
7856
|
-
|
|
7987
|
+
logWarn(`Hydration mismatch: incorrect number of rendered nodes. Client produced more nodes than the server.`, owner);
|
|
7857
7988
|
}
|
|
7858
7989
|
}
|
|
7859
7990
|
mount(childVnode, parentNode, renderer, nextNode);
|
|
@@ -7875,7 +8006,7 @@ expectAddlSiblings) {
|
|
|
7875
8006
|
hasMismatch = true;
|
|
7876
8007
|
if (process.env.NODE_ENV !== 'production') {
|
|
7877
8008
|
if (!hasWarned) {
|
|
7878
|
-
|
|
8009
|
+
logWarn(`Hydration mismatch: incorrect number of rendered nodes. Server rendered more nodes than the client.`, owner);
|
|
7879
8010
|
}
|
|
7880
8011
|
}
|
|
7881
8012
|
// nextSibling is mostly harmless, and since we don't have
|
|
@@ -7908,7 +8039,7 @@ function hasCorrectNodeType(vnode, node, nodeType, renderer) {
|
|
|
7908
8039
|
const { getProperty } = renderer;
|
|
7909
8040
|
if (getProperty(node, 'nodeType') !== nodeType) {
|
|
7910
8041
|
if (process.env.NODE_ENV !== 'production') {
|
|
7911
|
-
|
|
8042
|
+
logWarn('Hydration mismatch: incorrect node type received', vnode.owner);
|
|
7912
8043
|
}
|
|
7913
8044
|
return false;
|
|
7914
8045
|
}
|
|
@@ -7918,7 +8049,7 @@ function isMatchingElement(vnode, elm, renderer, shouldValidateAttr = () => true
|
|
|
7918
8049
|
const { getProperty } = renderer;
|
|
7919
8050
|
if (vnode.sel.toLowerCase() !== getProperty(elm, 'tagName').toLowerCase()) {
|
|
7920
8051
|
if (process.env.NODE_ENV !== 'production') {
|
|
7921
|
-
|
|
8052
|
+
logWarn(`Hydration mismatch: expecting element with tag "${vnode.sel.toLowerCase()}" but found "${getProperty(elm, 'tagName').toLowerCase()}".`, vnode.owner);
|
|
7922
8053
|
}
|
|
7923
8054
|
return false;
|
|
7924
8055
|
}
|
|
@@ -7959,7 +8090,7 @@ function validateAttrs(vnode, elm, data, renderer, shouldValidateAttr) {
|
|
|
7959
8090
|
if (!attributeValuesAreEqual(attrValue, elmAttrValue)) {
|
|
7960
8091
|
if (process.env.NODE_ENV !== 'production') {
|
|
7961
8092
|
const { getProperty } = renderer;
|
|
7962
|
-
|
|
8093
|
+
logWarn(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found ${shared.isNull(elmAttrValue) ? 'null' : `"${elmAttrValue}"`}`, vnode.owner);
|
|
7963
8094
|
}
|
|
7964
8095
|
nodesAreCompatible = false;
|
|
7965
8096
|
}
|
|
@@ -7970,78 +8101,63 @@ function validateClassAttr(vnode, elm, data, renderer) {
|
|
|
7970
8101
|
const { owner } = vnode;
|
|
7971
8102
|
// classMap is never available on VStaticPartData so it can default to undefined
|
|
7972
8103
|
// casting to prevent TS error.
|
|
7973
|
-
|
|
7974
|
-
const { getProperty
|
|
8104
|
+
const { className, classMap } = data;
|
|
8105
|
+
const { getProperty } = renderer;
|
|
8106
|
+
// ---------- Step 1: get the classes from the element and the vnode
|
|
8107
|
+
// Use a Set because we don't care to validate mismatches for 1) different ordering in SSR vs CSR, or 2)
|
|
8108
|
+
// duplicated class names. These don't have an effect on rendered styles.
|
|
8109
|
+
const elmClasses = new Set(shared.ArrayFrom(elm.classList));
|
|
8110
|
+
let vnodeClasses;
|
|
8111
|
+
if (!shared.isUndefined(className)) {
|
|
8112
|
+
// ignore empty spaces entirely, filter them out using `filter(..., Boolean)`
|
|
8113
|
+
vnodeClasses = new Set(shared.ArrayFilter.call(shared.StringSplit.call(className, /\s+/), Boolean));
|
|
8114
|
+
}
|
|
8115
|
+
else if (!shared.isUndefined(classMap)) {
|
|
8116
|
+
vnodeClasses = new Set(shared.keys(classMap));
|
|
8117
|
+
}
|
|
8118
|
+
else {
|
|
8119
|
+
vnodeClasses = new Set();
|
|
8120
|
+
}
|
|
8121
|
+
// ---------- Step 2: handle the scope tokens
|
|
7975
8122
|
// we don't care about legacy for hydration. it's a new use case
|
|
7976
|
-
const
|
|
7977
|
-
const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
|
|
8123
|
+
const scopeToken = getScopeTokenClass(owner, /* legacy */ false);
|
|
7978
8124
|
// Classnames for scoped CSS are added directly to the DOM during rendering,
|
|
7979
8125
|
// or to the VDOM on the server in the case of SSR. As such, these classnames
|
|
7980
8126
|
// are never present in VDOM nodes in the browser.
|
|
7981
8127
|
//
|
|
7982
8128
|
// Consequently, hydration mismatches will occur if scoped CSS token classnames
|
|
7983
8129
|
// are rendered during SSR. This needs to be accounted for when validating.
|
|
7984
|
-
if (!shared.isNull(
|
|
7985
|
-
|
|
7986
|
-
// The order of the className should be scopedToken className stylesheetTokenHost
|
|
7987
|
-
const classTokens = [scopedToken, className, stylesheetTokenHost];
|
|
7988
|
-
const classNames = shared.ArrayFilter.call(classTokens, (token) => !shared.isNull(token));
|
|
7989
|
-
className = shared.ArrayJoin.call(classNames, ' ');
|
|
7990
|
-
}
|
|
7991
|
-
else if (!shared.isUndefined(classMap)) {
|
|
7992
|
-
classMap = {
|
|
7993
|
-
...classMap,
|
|
7994
|
-
...(!shared.isNull(scopedToken) ? { [scopedToken]: true } : {}),
|
|
7995
|
-
...(!shared.isNull(stylesheetTokenHost) ? { [stylesheetTokenHost]: true } : {}),
|
|
7996
|
-
};
|
|
7997
|
-
}
|
|
7998
|
-
else {
|
|
7999
|
-
// The order of the className should be scopedToken stylesheetTokenHost
|
|
8000
|
-
const classTokens = [scopedToken, stylesheetTokenHost];
|
|
8001
|
-
const classNames = shared.ArrayFilter.call(classTokens, (token) => !shared.isNull(token));
|
|
8002
|
-
if (classNames.length) {
|
|
8003
|
-
className = shared.ArrayJoin.call(classNames, ' ');
|
|
8004
|
-
}
|
|
8005
|
-
}
|
|
8130
|
+
if (!shared.isNull(scopeToken)) {
|
|
8131
|
+
vnodeClasses.add(scopeToken);
|
|
8006
8132
|
}
|
|
8133
|
+
// This tells us which `*-host` scope token was rendered to the element's class.
|
|
8134
|
+
// For now we just ignore any mismatches involving this class.
|
|
8135
|
+
// TODO [#4866]: correctly validate the host scope token class
|
|
8136
|
+
const elmHostScopeToken = renderer.getAttribute(elm, 'data-lwc-host-scope-token');
|
|
8137
|
+
if (!shared.isNull(elmHostScopeToken)) {
|
|
8138
|
+
elmClasses.delete(elmHostScopeToken);
|
|
8139
|
+
vnodeClasses.delete(elmHostScopeToken);
|
|
8140
|
+
}
|
|
8141
|
+
// ---------- Step 3: check for compatibility
|
|
8007
8142
|
let nodesAreCompatible = true;
|
|
8008
|
-
|
|
8009
|
-
const elmClassName = getAttribute(elm, 'class');
|
|
8010
|
-
if (!shared.isUndefined(className) &&
|
|
8011
|
-
String(className) !== elmClassName &&
|
|
8012
|
-
// No mismatch if SSR `class` attribute is missing and CSR `class` is the empty string
|
|
8013
|
-
!(className === '' && shared.isNull(elmClassName))) {
|
|
8014
|
-
// className is used when class is bound to an expr.
|
|
8143
|
+
if (vnodeClasses.size !== elmClasses.size) {
|
|
8015
8144
|
nodesAreCompatible = false;
|
|
8016
|
-
// stringify for pretty-printing
|
|
8017
|
-
readableVnodeClassname = JSON.stringify(className);
|
|
8018
8145
|
}
|
|
8019
|
-
else
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
let computedClassName = '';
|
|
8023
|
-
// all classes from the vnode should be in the element.classList
|
|
8024
|
-
for (const name in classMap) {
|
|
8025
|
-
computedClassName += ' ' + name;
|
|
8026
|
-
if (!classList.contains(name)) {
|
|
8146
|
+
else {
|
|
8147
|
+
for (const vnodeClass of vnodeClasses) {
|
|
8148
|
+
if (!elmClasses.has(vnodeClass)) {
|
|
8027
8149
|
nodesAreCompatible = false;
|
|
8028
8150
|
}
|
|
8029
8151
|
}
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8152
|
+
for (const elmClass of elmClasses) {
|
|
8153
|
+
if (!vnodeClasses.has(elmClass)) {
|
|
8154
|
+
nodesAreCompatible = false;
|
|
8155
|
+
}
|
|
8034
8156
|
}
|
|
8035
8157
|
}
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
readableVnodeClassname = '""';
|
|
8040
|
-
}
|
|
8041
|
-
if (!nodesAreCompatible) {
|
|
8042
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
8043
|
-
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "class" has different values, expected ${readableVnodeClassname} but found ${JSON.stringify(elmClassName)}`, vnode.owner);
|
|
8044
|
-
}
|
|
8158
|
+
if (process.env.NODE_ENV !== 'production' && !nodesAreCompatible) {
|
|
8159
|
+
const prettyPrint = (set) => JSON.stringify(shared.ArrayJoin.call(shared.ArraySort.call(shared.ArrayFrom(set)), ' '));
|
|
8160
|
+
logWarn(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "class" has different values, expected ${prettyPrint(vnodeClasses)} but found ${prettyPrint(elmClasses)}`, vnode.owner);
|
|
8045
8161
|
}
|
|
8046
8162
|
return nodesAreCompatible;
|
|
8047
8163
|
}
|
|
@@ -8082,7 +8198,7 @@ function validateStyleAttr(vnode, elm, data, renderer) {
|
|
|
8082
8198
|
if (!nodesAreCompatible) {
|
|
8083
8199
|
if (process.env.NODE_ENV !== 'production') {
|
|
8084
8200
|
const { getProperty } = renderer;
|
|
8085
|
-
|
|
8201
|
+
logWarn(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "style" has different values, expected "${vnodeStyle}" but found "${elmStyle}".`, vnode.owner);
|
|
8086
8202
|
}
|
|
8087
8203
|
}
|
|
8088
8204
|
return nodesAreCompatible;
|
|
@@ -8108,7 +8224,7 @@ function areCompatibleStaticNodes(client, ssr, vnode, renderer) {
|
|
|
8108
8224
|
let isCompatibleElements = true;
|
|
8109
8225
|
if (getProperty(client, 'tagName') !== getProperty(ssr, 'tagName')) {
|
|
8110
8226
|
if (process.env.NODE_ENV !== 'production') {
|
|
8111
|
-
|
|
8227
|
+
logWarn(`Hydration mismatch: expecting element with tag "${getProperty(client, 'tagName').toLowerCase()}" but found "${getProperty(ssr, 'tagName').toLowerCase()}".`, owner);
|
|
8112
8228
|
}
|
|
8113
8229
|
return false;
|
|
8114
8230
|
}
|
|
@@ -8121,7 +8237,7 @@ function areCompatibleStaticNodes(client, ssr, vnode, renderer) {
|
|
|
8121
8237
|
// partId === 0 will always refer to the root element, this is guaranteed by the compiler.
|
|
8122
8238
|
if (parts?.[0].partId !== 0) {
|
|
8123
8239
|
if (process.env.NODE_ENV !== 'production') {
|
|
8124
|
-
|
|
8240
|
+
logWarn(`Mismatch hydrating element <${getProperty(client, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${getAttribute(client, attrName)}" but found "${getAttribute(ssr, attrName)}"`, owner);
|
|
8125
8241
|
}
|
|
8126
8242
|
isCompatibleElements = false;
|
|
8127
8243
|
}
|
|
@@ -8482,5 +8598,5 @@ exports.swapTemplate = swapTemplate;
|
|
|
8482
8598
|
exports.track = track;
|
|
8483
8599
|
exports.unwrap = unwrap;
|
|
8484
8600
|
exports.wire = wire;
|
|
8485
|
-
/** version: 8.
|
|
8601
|
+
/** version: 8.10.0-alpha.0 */
|
|
8486
8602
|
//# sourceMappingURL=index.cjs.js.map
|