@lwc/engine-core 8.1.1 → 8.1.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/framework/api.d.ts +2 -1
- package/dist/framework/main.d.ts +1 -1
- package/dist/framework/sanitized-html-content.d.ts +29 -0
- package/dist/framework/utils.d.ts +0 -3
- package/dist/index.cjs.js +102 -47
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +102 -47
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/framework/api.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SlotSet } from './vm';
|
|
2
2
|
import { LightningElementConstructor } from './base-lightning-element';
|
|
3
3
|
import { Key, VComment, VCustomElement, VElement, VElementData, VFragment, VNode, VNodes, VScopedSlotFragment, VStatic, VStaticPart, VStaticPartData, VText } from './vnodes';
|
|
4
|
+
import { SanitizedHtmlContent } from './sanitized-html-content';
|
|
4
5
|
declare function sp(partId: number, data: VStaticPartData | null, text: string | null): VStaticPart;
|
|
5
6
|
declare function ssf(slotName: unknown, factory: (value: any, key: any) => VFragment): VScopedSlotFragment;
|
|
6
7
|
declare function st(fragmentFactory: (parts?: VStaticPart[]) => Element, key: Key, parts?: VStaticPart[]): VStatic;
|
|
@@ -45,7 +46,7 @@ export type SanitizeHtmlContentHook = (content: unknown) => string;
|
|
|
45
46
|
* @param newHookImpl
|
|
46
47
|
*/
|
|
47
48
|
export declare function setSanitizeHtmlContentHook(newHookImpl: SanitizeHtmlContentHook): void;
|
|
48
|
-
declare function shc(content: unknown):
|
|
49
|
+
declare function shc(content: unknown): SanitizedHtmlContent;
|
|
49
50
|
/**
|
|
50
51
|
* [ncls] - Normalize class name attribute.
|
|
51
52
|
*
|
package/dist/framework/main.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export { getComponentConstructor } from './get-component-constructor';
|
|
|
20
20
|
export type { RendererAPI, LifecycleCallback } from './renderer';
|
|
21
21
|
export type { Stylesheets } from './stylesheet';
|
|
22
22
|
export type { Template } from './template';
|
|
23
|
-
export type { ConfigValue as WireConfigValue, ContextConsumer as WireContextConsumer, ContextProvider as WireContextProvider, ContextValue as WireContextValue, DataCallback, WireAdapter, WireAdapterConstructor, WireAdapterSchemaValue, WireContextSubscriptionPayload, WireContextSubscriptionCallback, } from './wiring';
|
|
23
|
+
export type { ConfigValue as WireConfigValue, ContextConsumer as WireContextConsumer, ContextProvider as WireContextProvider, ContextValue as WireContextValue, DataCallback as WireDataCallback, WireAdapter, WireAdapterConstructor, WireAdapterSchemaValue, WireContextSubscriptionPayload, WireContextSubscriptionCallback, } from './wiring';
|
|
24
24
|
export type { FormRestoreState, FormRestoreReason } from './vm';
|
|
25
25
|
export { LightningElement } from './base-lightning-element';
|
|
26
26
|
export { default as api } from './decorators/api';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RendererAPI } from './renderer';
|
|
2
|
+
declare const sanitizedHtmlContentSymbol: unique symbol;
|
|
3
|
+
export type SanitizedHtmlContent = {
|
|
4
|
+
[sanitizedHtmlContentSymbol]: unknown;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Wrap a pre-sanitized string designated for `.innerHTML` via `lwc:inner-html`
|
|
8
|
+
* as an object with a Symbol that only we have access to.
|
|
9
|
+
* @param sanitizedString
|
|
10
|
+
* @returns SanitizedHtmlContent
|
|
11
|
+
*/
|
|
12
|
+
export declare function createSanitizedHtmlContent(sanitizedString: unknown): SanitizedHtmlContent;
|
|
13
|
+
/**
|
|
14
|
+
* Safely call setProperty on an Element while handling any SanitizedHtmlContent objects correctly
|
|
15
|
+
*
|
|
16
|
+
* @param setProperty - renderer.setProperty
|
|
17
|
+
* @param elm - Element
|
|
18
|
+
* @param key - key to set
|
|
19
|
+
* @param value - value to set
|
|
20
|
+
*/
|
|
21
|
+
export declare function safelySetProperty(setProperty: RendererAPI['setProperty'], elm: Element, key: string, value: any): void;
|
|
22
|
+
/**
|
|
23
|
+
* Given two objects (likely either a string or a SanitizedHtmlContent object), return true if their
|
|
24
|
+
* string values are equivalent.
|
|
25
|
+
* @param first
|
|
26
|
+
* @param second
|
|
27
|
+
*/
|
|
28
|
+
export declare function isSanitizedHtmlContentEqual(first: any, second: any): boolean;
|
|
29
|
+
export {};
|
|
@@ -6,9 +6,6 @@ export declare const EmptyObject: any;
|
|
|
6
6
|
export declare const EmptyArray: never[];
|
|
7
7
|
export declare function addCallbackToNextTick(callback: Callback): void;
|
|
8
8
|
export declare function guid(): string;
|
|
9
|
-
export declare function parseStyleText(cssText: string): {
|
|
10
|
-
[name: string]: string;
|
|
11
|
-
};
|
|
12
9
|
export declare function cloneAndOmitKey(object: {
|
|
13
10
|
[key: string]: any;
|
|
14
11
|
}, keyToOmit: string): {
|
package/dist/index.cjs.js
CHANGED
|
@@ -221,23 +221,6 @@ function guid() {
|
|
|
221
221
|
}
|
|
222
222
|
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
|
223
223
|
}
|
|
224
|
-
// Borrowed from Vue template compiler.
|
|
225
|
-
// https://github.com/vuejs/vue/blob/531371b818b0e31a989a06df43789728f23dc4e8/src/platforms/web/util/style.js#L5-L16
|
|
226
|
-
const DECLARATION_DELIMITER = /;(?![^(]*\))/g;
|
|
227
|
-
const PROPERTY_DELIMITER = /:(.+)/;
|
|
228
|
-
function parseStyleText(cssText) {
|
|
229
|
-
const styleMap = {};
|
|
230
|
-
const declarations = cssText.split(DECLARATION_DELIMITER);
|
|
231
|
-
for (const declaration of declarations) {
|
|
232
|
-
if (declaration) {
|
|
233
|
-
const [prop, value] = declaration.split(PROPERTY_DELIMITER);
|
|
234
|
-
if (prop !== undefined && value !== undefined) {
|
|
235
|
-
styleMap[prop.trim()] = value.trim();
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return styleMap;
|
|
240
|
-
}
|
|
241
224
|
// Make a shallow copy of an object but omit the given key
|
|
242
225
|
function cloneAndOmitKey(object, keyToOmit) {
|
|
243
226
|
const result = {};
|
|
@@ -3937,6 +3920,65 @@ function isVStaticPartText(vnode) {
|
|
|
3937
3920
|
return vnode.type === 0 /* VStaticPartType.Text */;
|
|
3938
3921
|
}
|
|
3939
3922
|
|
|
3923
|
+
const sanitizedHtmlContentSymbol = Symbol('lwc-get-sanitized-html-content');
|
|
3924
|
+
function isSanitizedHtmlContent(object) {
|
|
3925
|
+
return shared.isObject(object) && !shared.isNull(object) && sanitizedHtmlContentSymbol in object;
|
|
3926
|
+
}
|
|
3927
|
+
function unwrapIfNecessary(object) {
|
|
3928
|
+
return isSanitizedHtmlContent(object) ? object[sanitizedHtmlContentSymbol] : object;
|
|
3929
|
+
}
|
|
3930
|
+
/**
|
|
3931
|
+
* Wrap a pre-sanitized string designated for `.innerHTML` via `lwc:inner-html`
|
|
3932
|
+
* as an object with a Symbol that only we have access to.
|
|
3933
|
+
* @param sanitizedString
|
|
3934
|
+
* @returns SanitizedHtmlContent
|
|
3935
|
+
*/
|
|
3936
|
+
function createSanitizedHtmlContent(sanitizedString) {
|
|
3937
|
+
return shared.create(null, {
|
|
3938
|
+
[sanitizedHtmlContentSymbol]: {
|
|
3939
|
+
value: sanitizedString,
|
|
3940
|
+
configurable: false,
|
|
3941
|
+
writable: false,
|
|
3942
|
+
},
|
|
3943
|
+
});
|
|
3944
|
+
}
|
|
3945
|
+
/**
|
|
3946
|
+
* Safely call setProperty on an Element while handling any SanitizedHtmlContent objects correctly
|
|
3947
|
+
*
|
|
3948
|
+
* @param setProperty - renderer.setProperty
|
|
3949
|
+
* @param elm - Element
|
|
3950
|
+
* @param key - key to set
|
|
3951
|
+
* @param value - value to set
|
|
3952
|
+
*/
|
|
3953
|
+
function safelySetProperty(setProperty, elm, key, value) {
|
|
3954
|
+
// See W-16614337
|
|
3955
|
+
// we support setting innerHTML to `undefined` because it's inherently safe
|
|
3956
|
+
if ((key === 'innerHTML' || key === 'outerHTML') && !shared.isUndefined(value)) {
|
|
3957
|
+
if (isSanitizedHtmlContent(value)) {
|
|
3958
|
+
// it's a SanitizedHtmlContent object
|
|
3959
|
+
setProperty(elm, key, value[sanitizedHtmlContentSymbol]);
|
|
3960
|
+
}
|
|
3961
|
+
else {
|
|
3962
|
+
// not a SanitizedHtmlContent object
|
|
3963
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3964
|
+
logWarn(`Cannot set property "${key}". Instead, use lwc:inner-html or lwc:dom-manual.`);
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
}
|
|
3968
|
+
else {
|
|
3969
|
+
setProperty(elm, key, value);
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
/**
|
|
3973
|
+
* Given two objects (likely either a string or a SanitizedHtmlContent object), return true if their
|
|
3974
|
+
* string values are equivalent.
|
|
3975
|
+
* @param first
|
|
3976
|
+
* @param second
|
|
3977
|
+
*/
|
|
3978
|
+
function isSanitizedHtmlContentEqual(first, second) {
|
|
3979
|
+
return unwrapIfNecessary(first) === unwrapIfNecessary(second);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3940
3982
|
/*
|
|
3941
3983
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
3942
3984
|
* All rights reserved.
|
|
@@ -3967,7 +4009,7 @@ function patchAttributes(oldVnode, vnode, renderer) {
|
|
|
3967
4009
|
// Use kebabCaseToCamelCase directly because we don't want to set props like `ariaLabel` or `tabIndex`
|
|
3968
4010
|
// on a custom element versus just using the more reliable attribute format.
|
|
3969
4011
|
if (external && (propName = shared.kebabCaseToCamelCase(key)) in elm) {
|
|
3970
|
-
setProperty
|
|
4012
|
+
safelySetProperty(setProperty, elm, propName, cur);
|
|
3971
4013
|
}
|
|
3972
4014
|
else if (shared.StringCharCodeAt.call(key, 3) === ColonCharCode) {
|
|
3973
4015
|
// Assume xml namespace
|
|
@@ -4047,7 +4089,7 @@ function patchProps(oldVnode, vnode, renderer) {
|
|
|
4047
4089
|
logWarn(`Unknown public property "${key}" of element <${elm.tagName.toLowerCase()}>. This is either a typo on the corresponding attribute "${shared.htmlPropertyToAttribute(key)}", or the attribute does not exist in this browser or DOM implementation.`);
|
|
4048
4090
|
}
|
|
4049
4091
|
}
|
|
4050
|
-
setProperty
|
|
4092
|
+
safelySetProperty(setProperty, elm, key, cur);
|
|
4051
4093
|
}
|
|
4052
4094
|
}
|
|
4053
4095
|
}
|
|
@@ -5755,7 +5797,8 @@ function setSanitizeHtmlContentHook(newHookImpl) {
|
|
|
5755
5797
|
}
|
|
5756
5798
|
// [s]anitize [h]tml [c]ontent
|
|
5757
5799
|
function shc(content) {
|
|
5758
|
-
|
|
5800
|
+
const sanitizedString = sanitizeHtmlContentHook(content);
|
|
5801
|
+
return createSanitizedHtmlContent(sanitizedString);
|
|
5759
5802
|
}
|
|
5760
5803
|
/**
|
|
5761
5804
|
* [ncls] - Normalize class name attribute.
|
|
@@ -7598,31 +7641,41 @@ function textNodeContentsAreEqual(node, vnode, renderer) {
|
|
|
7598
7641
|
// Any attribute names specified in that array will not be validated, and the
|
|
7599
7642
|
// LWC runtime will assume that VDOM attrs and DOM attrs are in sync.
|
|
7600
7643
|
function getValidationPredicate(elm, renderer, optOutStaticProp) {
|
|
7601
|
-
// `data-lwc-host-mutated` is a special attribute added by the SSR engine itself,
|
|
7602
|
-
//
|
|
7644
|
+
// `data-lwc-host-mutated` is a special attribute added by the SSR engine itself, which automatically detects
|
|
7645
|
+
// host mutations during `connectedCallback`.
|
|
7603
7646
|
const hostMutatedValue = renderer.getAttribute(elm, 'data-lwc-host-mutated');
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
}
|
|
7608
|
-
if (shared.isUndefined(optOutStaticProp)) {
|
|
7609
|
-
return (_attrName) => true;
|
|
7610
|
-
}
|
|
7647
|
+
const detectedHostMutations = shared.isString(hostMutatedValue)
|
|
7648
|
+
? new Set(shared.StringSplit.call(hostMutatedValue, / /))
|
|
7649
|
+
: undefined;
|
|
7611
7650
|
// If validationOptOut is true, no attributes will be checked for correctness
|
|
7612
7651
|
// and the runtime will assume VDOM attrs and DOM attrs are in sync.
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7652
|
+
const fullOptOut = shared.isTrue(optOutStaticProp);
|
|
7653
|
+
// If validationOptOut is an array of strings, attributes specified in the array will be "opted out". Attributes
|
|
7654
|
+
// not specified in the array will still be validated.
|
|
7655
|
+
const isValidArray = shared.isArray(optOutStaticProp) && shared.arrayEvery(optOutStaticProp, shared.isString);
|
|
7656
|
+
const conditionalOptOut = isValidArray ? new Set(optOutStaticProp) : undefined;
|
|
7657
|
+
if (process.env.NODE_ENV !== 'production' &&
|
|
7658
|
+
!shared.isUndefined(optOutStaticProp) &&
|
|
7659
|
+
!shared.isTrue(optOutStaticProp) &&
|
|
7660
|
+
!isValidArray) {
|
|
7661
|
+
logWarn('`validationOptOut` must be `true` or an array of attributes that should not be validated.');
|
|
7662
|
+
}
|
|
7663
|
+
return (attrName) => {
|
|
7664
|
+
// Component wants to opt out of all validation
|
|
7665
|
+
if (fullOptOut) {
|
|
7666
|
+
return false;
|
|
7667
|
+
}
|
|
7668
|
+
// Mutations were automatically detected and should be ignored
|
|
7669
|
+
if (!shared.isUndefined(detectedHostMutations) && detectedHostMutations.has(attrName)) {
|
|
7670
|
+
return false;
|
|
7671
|
+
}
|
|
7672
|
+
// Component explicitly wants to opt out of certain validations, regardless of auto-detection
|
|
7673
|
+
if (!shared.isUndefined(conditionalOptOut) && conditionalOptOut.has(attrName)) {
|
|
7674
|
+
return false;
|
|
7675
|
+
}
|
|
7676
|
+
// Attribute must be validated
|
|
7677
|
+
return true;
|
|
7678
|
+
};
|
|
7626
7679
|
}
|
|
7627
7680
|
function hydrateText(node, vnode, renderer) {
|
|
7628
7681
|
if (!hasCorrectNodeType(vnode, node, 3 /* EnvNodeTypes.TEXT */, renderer)) {
|
|
@@ -7653,6 +7706,8 @@ function hydrateComment(node, vnode, renderer) {
|
|
|
7653
7706
|
}
|
|
7654
7707
|
}
|
|
7655
7708
|
const { setProperty } = renderer;
|
|
7709
|
+
// We only set the `nodeValue` property here (on a comment), so we don't need
|
|
7710
|
+
// to sanitize the content as HTML using `safelySetProperty`
|
|
7656
7711
|
setProperty(node, NODE_VALUE_PROP, vnode.text ?? null);
|
|
7657
7712
|
vnode.elm = node;
|
|
7658
7713
|
return node;
|
|
@@ -7699,7 +7754,7 @@ function hydrateElement(elm, vnode, renderer) {
|
|
|
7699
7754
|
const { data: { props }, } = vnode;
|
|
7700
7755
|
const { getProperty } = renderer;
|
|
7701
7756
|
if (!shared.isUndefined(props) && !shared.isUndefined(props.innerHTML)) {
|
|
7702
|
-
if (getProperty(elm, 'innerHTML')
|
|
7757
|
+
if (isSanitizedHtmlContentEqual(getProperty(elm, 'innerHTML'), props.innerHTML)) {
|
|
7703
7758
|
// Do a shallow clone since VNodeData may be shared across VNodes due to hoist optimization
|
|
7704
7759
|
vnode.data = {
|
|
7705
7760
|
...vnode.data,
|
|
@@ -7984,12 +8039,12 @@ function validateStyleAttr(vnode, elm, data, renderer) {
|
|
|
7984
8039
|
vnodeStyle = style;
|
|
7985
8040
|
}
|
|
7986
8041
|
else if (!shared.isUndefined(styleDecls)) {
|
|
7987
|
-
const parsedVnodeStyle = parseStyleText(elmStyle);
|
|
8042
|
+
const parsedVnodeStyle = shared.parseStyleText(elmStyle);
|
|
7988
8043
|
const expectedStyle = [];
|
|
7989
8044
|
// styleMap is used when style is set to static value.
|
|
7990
8045
|
for (let i = 0, n = styleDecls.length; i < n; i++) {
|
|
7991
8046
|
const [prop, value, important] = styleDecls[i];
|
|
7992
|
-
expectedStyle.push(`${prop}: ${value + (important ? ' important
|
|
8047
|
+
expectedStyle.push(`${prop}: ${value + (important ? ' !important' : '')};`);
|
|
7993
8048
|
const parsedPropValue = parsedVnodeStyle[prop];
|
|
7994
8049
|
if (shared.isUndefined(parsedPropValue)) {
|
|
7995
8050
|
nodesAreCompatible = false;
|
|
@@ -8004,7 +8059,7 @@ function validateStyleAttr(vnode, elm, data, renderer) {
|
|
|
8004
8059
|
if (shared.keys(parsedVnodeStyle).length > styleDecls.length) {
|
|
8005
8060
|
nodesAreCompatible = false;
|
|
8006
8061
|
}
|
|
8007
|
-
vnodeStyle = shared.ArrayJoin.call(expectedStyle, '
|
|
8062
|
+
vnodeStyle = shared.ArrayJoin.call(expectedStyle, ' ');
|
|
8008
8063
|
}
|
|
8009
8064
|
if (!nodesAreCompatible) {
|
|
8010
8065
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -8416,5 +8471,5 @@ exports.swapTemplate = swapTemplate;
|
|
|
8416
8471
|
exports.track = track;
|
|
8417
8472
|
exports.unwrap = unwrap;
|
|
8418
8473
|
exports.wire = wire;
|
|
8419
|
-
/** version: 8.1.
|
|
8474
|
+
/** version: 8.1.3 */
|
|
8420
8475
|
//# sourceMappingURL=index.cjs.js.map
|