@lwc/engine-core 2.37.2 → 2.37.3
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/engine-core.cjs.js +48 -6
- package/dist/engine-core.js +49 -7
- package/package.json +4 -4
- package/types/framework/vnodes.d.ts +1 -1
package/dist/engine-core.cjs.js
CHANGED
|
@@ -6231,15 +6231,44 @@ function hydrateNode(node, vnode, renderer) {
|
|
|
6231
6231
|
return renderer.nextSibling(hydratedNode);
|
|
6232
6232
|
}
|
|
6233
6233
|
const NODE_VALUE_PROP = 'nodeValue';
|
|
6234
|
+
const PARENT_NODE_PROP = 'parentNode';
|
|
6235
|
+
const TAG_NAME_PROP = 'tagName';
|
|
6236
|
+
function textNodeContentsAreEqual(node, vnode, renderer) {
|
|
6237
|
+
const { getProperty } = renderer;
|
|
6238
|
+
const nodeValue = getProperty(node, NODE_VALUE_PROP);
|
|
6239
|
+
if (nodeValue === vnode.text) {
|
|
6240
|
+
return true;
|
|
6241
|
+
}
|
|
6242
|
+
// Special case for empty text nodes – these are serialized differently on the server
|
|
6243
|
+
// See https://github.com/salesforce/lwc/pull/2656
|
|
6244
|
+
if (nodeValue === '\u200D' && vnode.text === '') {
|
|
6245
|
+
return true;
|
|
6246
|
+
}
|
|
6247
|
+
// Special case for text nodes inside `<style>` tags – these are escaped when rendered server-size,
|
|
6248
|
+
// but not when generated by the engine client-side.
|
|
6249
|
+
const parentNode = getProperty(node, PARENT_NODE_PROP);
|
|
6250
|
+
// Should never be null, but just to be safe, we check.
|
|
6251
|
+
/* istanbul ignore else */
|
|
6252
|
+
if (!shared.isNull(parentNode)) {
|
|
6253
|
+
const tagName = getProperty(parentNode, TAG_NAME_PROP);
|
|
6254
|
+
// If the tagName is STYLE, then the following condition should always be true.
|
|
6255
|
+
// The LWC compiler blocks using `<style>`s inside of templates, so it should be impossible
|
|
6256
|
+
// for component authors to render different `<style>` text content on the client and server.
|
|
6257
|
+
// But just to be safe, we check.
|
|
6258
|
+
/* istanbul ignore next */
|
|
6259
|
+
if (tagName === 'STYLE' && shared.htmlEscape(vnode.text) === nodeValue) {
|
|
6260
|
+
return true;
|
|
6261
|
+
}
|
|
6262
|
+
}
|
|
6263
|
+
return false;
|
|
6264
|
+
}
|
|
6234
6265
|
function hydrateText(node, vnode, renderer) {
|
|
6235
6266
|
var _a;
|
|
6236
6267
|
if (!hasCorrectNodeType(vnode, node, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
6237
6268
|
return handleMismatch(node, vnode, renderer);
|
|
6238
6269
|
}
|
|
6239
6270
|
if (process.env.NODE_ENV !== 'production') {
|
|
6240
|
-
|
|
6241
|
-
const nodeValue = getProperty(node, NODE_VALUE_PROP);
|
|
6242
|
-
if (nodeValue !== vnode.text && !(nodeValue === '\u200D' && vnode.text === '')) {
|
|
6271
|
+
if (!textNodeContentsAreEqual(node, vnode, renderer)) {
|
|
6243
6272
|
logWarn('Hydration mismatch: text values do not match, will recover from the difference', vnode.owner);
|
|
6244
6273
|
}
|
|
6245
6274
|
}
|
|
@@ -6419,6 +6448,19 @@ function isMatchingElement(vnode, elm, renderer) {
|
|
|
6419
6448
|
const hasIncompatibleStyle = validateStyleAttr(vnode, elm, renderer);
|
|
6420
6449
|
return hasIncompatibleAttrs && hasIncompatibleClass && hasIncompatibleStyle;
|
|
6421
6450
|
}
|
|
6451
|
+
function attributeValuesAreEqual(vnodeValue, value) {
|
|
6452
|
+
const vnodeValueAsString = String(vnodeValue);
|
|
6453
|
+
if (vnodeValueAsString === value) {
|
|
6454
|
+
return true;
|
|
6455
|
+
}
|
|
6456
|
+
// If the expected value is null, this means that the attribute does not exist. In that case,
|
|
6457
|
+
// we accept any nullish value (undefined or null).
|
|
6458
|
+
if (shared.isNull(value) && (shared.isUndefined(vnodeValue) || shared.isNull(vnodeValue))) {
|
|
6459
|
+
return true;
|
|
6460
|
+
}
|
|
6461
|
+
// In all other cases, the two values are not considered equal
|
|
6462
|
+
return false;
|
|
6463
|
+
}
|
|
6422
6464
|
function validateAttrs(vnode, elm, renderer) {
|
|
6423
6465
|
const { data: { attrs = {} }, } = vnode;
|
|
6424
6466
|
let nodesAreCompatible = true;
|
|
@@ -6428,10 +6470,10 @@ function validateAttrs(vnode, elm, renderer) {
|
|
|
6428
6470
|
const { owner } = vnode;
|
|
6429
6471
|
const { getAttribute } = renderer;
|
|
6430
6472
|
const elmAttrValue = getAttribute(elm, attrName);
|
|
6431
|
-
if (
|
|
6473
|
+
if (!attributeValuesAreEqual(attrValue, elmAttrValue)) {
|
|
6432
6474
|
if (process.env.NODE_ENV !== 'production') {
|
|
6433
6475
|
const { getProperty } = renderer;
|
|
6434
|
-
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, owner);
|
|
6476
|
+
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found ${shared.isNull(elmAttrValue) ? 'null' : `"${elmAttrValue}"`}`, owner);
|
|
6435
6477
|
}
|
|
6436
6478
|
nodesAreCompatible = false;
|
|
6437
6479
|
}
|
|
@@ -6864,4 +6906,4 @@ exports.swapTemplate = swapTemplate;
|
|
|
6864
6906
|
exports.track = track;
|
|
6865
6907
|
exports.unwrap = unwrap;
|
|
6866
6908
|
exports.wire = wire;
|
|
6867
|
-
/* version: 2.37.
|
|
6909
|
+
/* version: 2.37.3 */
|
package/dist/engine-core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* proxy-compat-disable */
|
|
2
|
-
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArraySplice, create, seal, isArray as isArray$1, isFunction as isFunction$1, keys, hasOwnProperty as hasOwnProperty$1, forEach, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, htmlAttributeToProperty, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, ArrayUnshift, globalThis as globalThis$1, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift } from '@lwc/shared';
|
|
2
|
+
import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArraySplice, create, seal, isArray as isArray$1, isFunction as isFunction$1, keys, hasOwnProperty as hasOwnProperty$1, forEach, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, htmlAttributeToProperty, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, ArrayUnshift, globalThis as globalThis$1, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, htmlEscape, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift } from '@lwc/shared';
|
|
3
3
|
import { applyAriaReflection } from '@lwc/aria-reflection';
|
|
4
4
|
export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
|
|
5
5
|
|
|
@@ -6229,15 +6229,44 @@ function hydrateNode(node, vnode, renderer) {
|
|
|
6229
6229
|
return renderer.nextSibling(hydratedNode);
|
|
6230
6230
|
}
|
|
6231
6231
|
const NODE_VALUE_PROP = 'nodeValue';
|
|
6232
|
+
const PARENT_NODE_PROP = 'parentNode';
|
|
6233
|
+
const TAG_NAME_PROP = 'tagName';
|
|
6234
|
+
function textNodeContentsAreEqual(node, vnode, renderer) {
|
|
6235
|
+
const { getProperty } = renderer;
|
|
6236
|
+
const nodeValue = getProperty(node, NODE_VALUE_PROP);
|
|
6237
|
+
if (nodeValue === vnode.text) {
|
|
6238
|
+
return true;
|
|
6239
|
+
}
|
|
6240
|
+
// Special case for empty text nodes – these are serialized differently on the server
|
|
6241
|
+
// See https://github.com/salesforce/lwc/pull/2656
|
|
6242
|
+
if (nodeValue === '\u200D' && vnode.text === '') {
|
|
6243
|
+
return true;
|
|
6244
|
+
}
|
|
6245
|
+
// Special case for text nodes inside `<style>` tags – these are escaped when rendered server-size,
|
|
6246
|
+
// but not when generated by the engine client-side.
|
|
6247
|
+
const parentNode = getProperty(node, PARENT_NODE_PROP);
|
|
6248
|
+
// Should never be null, but just to be safe, we check.
|
|
6249
|
+
/* istanbul ignore else */
|
|
6250
|
+
if (!isNull(parentNode)) {
|
|
6251
|
+
const tagName = getProperty(parentNode, TAG_NAME_PROP);
|
|
6252
|
+
// If the tagName is STYLE, then the following condition should always be true.
|
|
6253
|
+
// The LWC compiler blocks using `<style>`s inside of templates, so it should be impossible
|
|
6254
|
+
// for component authors to render different `<style>` text content on the client and server.
|
|
6255
|
+
// But just to be safe, we check.
|
|
6256
|
+
/* istanbul ignore next */
|
|
6257
|
+
if (tagName === 'STYLE' && htmlEscape(vnode.text) === nodeValue) {
|
|
6258
|
+
return true;
|
|
6259
|
+
}
|
|
6260
|
+
}
|
|
6261
|
+
return false;
|
|
6262
|
+
}
|
|
6232
6263
|
function hydrateText(node, vnode, renderer) {
|
|
6233
6264
|
var _a;
|
|
6234
6265
|
if (!hasCorrectNodeType(vnode, node, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
6235
6266
|
return handleMismatch(node, vnode, renderer);
|
|
6236
6267
|
}
|
|
6237
6268
|
if (process.env.NODE_ENV !== 'production') {
|
|
6238
|
-
|
|
6239
|
-
const nodeValue = getProperty(node, NODE_VALUE_PROP);
|
|
6240
|
-
if (nodeValue !== vnode.text && !(nodeValue === '\u200D' && vnode.text === '')) {
|
|
6269
|
+
if (!textNodeContentsAreEqual(node, vnode, renderer)) {
|
|
6241
6270
|
logWarn('Hydration mismatch: text values do not match, will recover from the difference', vnode.owner);
|
|
6242
6271
|
}
|
|
6243
6272
|
}
|
|
@@ -6417,6 +6446,19 @@ function isMatchingElement(vnode, elm, renderer) {
|
|
|
6417
6446
|
const hasIncompatibleStyle = validateStyleAttr(vnode, elm, renderer);
|
|
6418
6447
|
return hasIncompatibleAttrs && hasIncompatibleClass && hasIncompatibleStyle;
|
|
6419
6448
|
}
|
|
6449
|
+
function attributeValuesAreEqual(vnodeValue, value) {
|
|
6450
|
+
const vnodeValueAsString = String(vnodeValue);
|
|
6451
|
+
if (vnodeValueAsString === value) {
|
|
6452
|
+
return true;
|
|
6453
|
+
}
|
|
6454
|
+
// If the expected value is null, this means that the attribute does not exist. In that case,
|
|
6455
|
+
// we accept any nullish value (undefined or null).
|
|
6456
|
+
if (isNull(value) && (isUndefined$1(vnodeValue) || isNull(vnodeValue))) {
|
|
6457
|
+
return true;
|
|
6458
|
+
}
|
|
6459
|
+
// In all other cases, the two values are not considered equal
|
|
6460
|
+
return false;
|
|
6461
|
+
}
|
|
6420
6462
|
function validateAttrs(vnode, elm, renderer) {
|
|
6421
6463
|
const { data: { attrs = {} }, } = vnode;
|
|
6422
6464
|
let nodesAreCompatible = true;
|
|
@@ -6426,10 +6468,10 @@ function validateAttrs(vnode, elm, renderer) {
|
|
|
6426
6468
|
const { owner } = vnode;
|
|
6427
6469
|
const { getAttribute } = renderer;
|
|
6428
6470
|
const elmAttrValue = getAttribute(elm, attrName);
|
|
6429
|
-
if (
|
|
6471
|
+
if (!attributeValuesAreEqual(attrValue, elmAttrValue)) {
|
|
6430
6472
|
if (process.env.NODE_ENV !== 'production') {
|
|
6431
6473
|
const { getProperty } = renderer;
|
|
6432
|
-
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, owner);
|
|
6474
|
+
logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found ${isNull(elmAttrValue) ? 'null' : `"${elmAttrValue}"`}`, owner);
|
|
6433
6475
|
}
|
|
6434
6476
|
nodesAreCompatible = false;
|
|
6435
6477
|
}
|
|
@@ -6825,4 +6867,4 @@ function getComponentConstructor(elm) {
|
|
|
6825
6867
|
}
|
|
6826
6868
|
|
|
6827
6869
|
export { LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
|
|
6828
|
-
/* version: 2.37.
|
|
6870
|
+
/* version: 2.37.3 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lwc/engine-core",
|
|
3
|
-
"version": "2.37.
|
|
3
|
+
"version": "2.37.3",
|
|
4
4
|
"description": "Core LWC engine APIs.",
|
|
5
5
|
"homepage": "https://lwc.dev/",
|
|
6
6
|
"repository": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"types/"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@lwc/aria-reflection": "2.37.
|
|
28
|
-
"@lwc/features": "2.37.
|
|
29
|
-
"@lwc/shared": "2.37.
|
|
27
|
+
"@lwc/aria-reflection": "2.37.3",
|
|
28
|
+
"@lwc/features": "2.37.3",
|
|
29
|
+
"@lwc/shared": "2.37.3"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"observable-membrane": "2.0.0"
|
|
@@ -68,7 +68,7 @@ export interface VCustomElement extends VBaseElement {
|
|
|
68
68
|
}
|
|
69
69
|
export interface VNodeData {
|
|
70
70
|
readonly props?: Readonly<Record<string, any>>;
|
|
71
|
-
readonly attrs?: Readonly<Record<string, string | number | boolean>>;
|
|
71
|
+
readonly attrs?: Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
72
72
|
readonly className?: string;
|
|
73
73
|
readonly style?: string;
|
|
74
74
|
readonly classMap?: Readonly<Record<string, boolean>>;
|