@lwc/engine-core 2.24.0 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3003,167 +3003,270 @@ function getComponentDef(Ctor) {
3003
3003
  * SPDX-License-Identifier: MIT
3004
3004
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3005
3005
  */
3006
+
3006
3007
  function makeHostToken(token) {
3007
- return `${token}-host`;
3008
+ return `${token}-host`;
3008
3009
  }
3010
+
3009
3011
  function createInlineStyleVNode(content) {
3010
- return api.h('style', {
3011
- key: 'style',
3012
- attrs: {
3013
- type: 'text/css',
3014
- },
3015
- }, [api.t(content)]);
3012
+ return api.h('style', {
3013
+ key: 'style',
3014
+ attrs: {
3015
+ type: 'text/css'
3016
+ }
3017
+ }, [api.t(content)]);
3016
3018
  }
3019
+
3017
3020
  function updateStylesheetToken(vm, template) {
3018
- const { elm, context, renderMode, shadowMode, renderer: { getClassList, removeAttribute, setAttribute }, } = vm;
3019
- const { stylesheets: newStylesheets, stylesheetToken: newStylesheetToken } = template;
3020
- const isSyntheticShadow = renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */;
3021
- const { hasScopedStyles } = context;
3022
- let newToken;
3023
- let newHasTokenInClass;
3024
- let newHasTokenInAttribute;
3025
- // Reset the styling token applied to the host element.
3026
- const { stylesheetToken: oldToken, hasTokenInClass: oldHasTokenInClass, hasTokenInAttribute: oldHasTokenInAttribute, } = context;
3027
- if (!shared.isUndefined(oldToken)) {
3028
- if (oldHasTokenInClass) {
3029
- getClassList(elm).remove(makeHostToken(oldToken));
3030
- }
3031
- if (oldHasTokenInAttribute) {
3032
- removeAttribute(elm, makeHostToken(oldToken));
3033
- }
3034
- }
3035
- // Apply the new template styling token to the host element, if the new template has any
3036
- // associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
3037
- if (!shared.isUndefined(newStylesheets) && newStylesheets.length !== 0) {
3038
- newToken = newStylesheetToken;
3039
- }
3040
- // Set the new styling token on the host element
3041
- if (!shared.isUndefined(newToken)) {
3042
- if (hasScopedStyles) {
3043
- getClassList(elm).add(makeHostToken(newToken));
3044
- newHasTokenInClass = true;
3045
- }
3046
- if (isSyntheticShadow) {
3047
- setAttribute(elm, makeHostToken(newToken), '');
3048
- newHasTokenInAttribute = true;
3049
- }
3050
- }
3051
- // Update the styling tokens present on the context object.
3052
- context.stylesheetToken = newToken;
3053
- context.hasTokenInClass = newHasTokenInClass;
3054
- context.hasTokenInAttribute = newHasTokenInAttribute;
3021
+ const {
3022
+ elm,
3023
+ context,
3024
+ renderMode,
3025
+ shadowMode,
3026
+ renderer: {
3027
+ getClassList,
3028
+ removeAttribute,
3029
+ setAttribute
3030
+ }
3031
+ } = vm;
3032
+ const {
3033
+ stylesheets: newStylesheets,
3034
+ stylesheetToken: newStylesheetToken
3035
+ } = template;
3036
+ const isSyntheticShadow = renderMode === 1
3037
+ /* RenderMode.Shadow */
3038
+ && shadowMode === 1
3039
+ /* ShadowMode.Synthetic */
3040
+ ;
3041
+ const {
3042
+ hasScopedStyles
3043
+ } = context;
3044
+ let newToken;
3045
+ let newHasTokenInClass;
3046
+ let newHasTokenInAttribute; // Reset the styling token applied to the host element.
3047
+
3048
+ const {
3049
+ stylesheetToken: oldToken,
3050
+ hasTokenInClass: oldHasTokenInClass,
3051
+ hasTokenInAttribute: oldHasTokenInAttribute
3052
+ } = context;
3053
+
3054
+ if (!shared.isUndefined(oldToken)) {
3055
+ if (oldHasTokenInClass) {
3056
+ getClassList(elm).remove(makeHostToken(oldToken));
3057
+ }
3058
+
3059
+ if (oldHasTokenInAttribute) {
3060
+ removeAttribute(elm, makeHostToken(oldToken));
3061
+ }
3062
+ } // Apply the new template styling token to the host element, if the new template has any
3063
+ // associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
3064
+
3065
+
3066
+ if (!shared.isUndefined(newStylesheets) && newStylesheets.length !== 0) {
3067
+ newToken = newStylesheetToken;
3068
+ } // Set the new styling token on the host element
3069
+
3070
+
3071
+ if (!shared.isUndefined(newToken)) {
3072
+ if (hasScopedStyles) {
3073
+ getClassList(elm).add(makeHostToken(newToken));
3074
+ newHasTokenInClass = true;
3075
+ }
3076
+
3077
+ if (isSyntheticShadow) {
3078
+ setAttribute(elm, makeHostToken(newToken), '');
3079
+ newHasTokenInAttribute = true;
3080
+ }
3081
+ } // Update the styling tokens present on the context object.
3082
+
3083
+
3084
+ context.stylesheetToken = newToken;
3085
+ context.hasTokenInClass = newHasTokenInClass;
3086
+ context.hasTokenInAttribute = newHasTokenInAttribute;
3055
3087
  }
3088
+
3056
3089
  function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3057
- const content = [];
3058
- let root;
3059
- for (let i = 0; i < stylesheets.length; i++) {
3060
- let stylesheet = stylesheets[i];
3061
- if (shared.isArray(stylesheet)) {
3062
- shared.ArrayPush.apply(content, evaluateStylesheetsContent(stylesheet, stylesheetToken, vm));
3090
+ const content = [];
3091
+ let root;
3092
+
3093
+ for (let i = 0; i < stylesheets.length; i++) {
3094
+ let stylesheet = stylesheets[i];
3095
+
3096
+ if (shared.isArray(stylesheet)) {
3097
+ shared.ArrayPush.apply(content, evaluateStylesheetsContent(stylesheet, stylesheetToken, vm));
3098
+ } else {
3099
+ if (process.env.NODE_ENV !== 'production') {
3100
+ // Check for compiler version mismatch in dev mode only
3101
+ checkVersionMismatch(stylesheet, 'stylesheet'); // in dev-mode, we support hot swapping of stylesheet, which means that
3102
+ // the component instance might be attempting to use an old version of
3103
+ // the stylesheet, while internally, we have a replacement for it.
3104
+
3105
+ stylesheet = getStyleOrSwappedStyle(stylesheet);
3106
+ }
3107
+
3108
+ const isScopedCss = stylesheet[shared.KEY__SCOPED_CSS];
3109
+
3110
+ if (features.lwcRuntimeFlags.DISABLE_LIGHT_DOM_UNSCOPED_CSS) {
3111
+ if (!isScopedCss && vm.renderMode === 0
3112
+ /* RenderMode.Light */
3113
+ ) {
3114
+ logError('Unscoped CSS is not supported in Light DOM. Please use scoped CSS (*.scoped.css) instead of unscoped CSS (*.css).');
3115
+ continue;
3063
3116
  }
3064
- else {
3065
- if (process.env.NODE_ENV !== 'production') {
3066
- // Check for compiler version mismatch in dev mode only
3067
- checkVersionMismatch(stylesheet, 'stylesheet');
3068
- // in dev-mode, we support hot swapping of stylesheet, which means that
3069
- // the component instance might be attempting to use an old version of
3070
- // the stylesheet, while internally, we have a replacement for it.
3071
- stylesheet = getStyleOrSwappedStyle(stylesheet);
3072
- }
3073
- const isScopedCss = stylesheet[shared.KEY__SCOPED_CSS];
3074
- // Apply the scope token only if the stylesheet itself is scoped, or if we're rendering synthetic shadow.
3075
- const scopeToken = isScopedCss ||
3076
- (vm.shadowMode === 1 /* ShadowMode.Synthetic */ && vm.renderMode === 1 /* RenderMode.Shadow */)
3077
- ? stylesheetToken
3078
- : undefined;
3079
- // Use the actual `:host` selector if we're rendering global CSS for light DOM, or if we're rendering
3080
- // native shadow DOM. Synthetic shadow DOM never uses `:host`.
3081
- const useActualHostSelector = vm.renderMode === 0 /* RenderMode.Light */
3082
- ? !isScopedCss
3083
- : vm.shadowMode === 0 /* ShadowMode.Native */;
3084
- // Use the native :dir() pseudoclass only in native shadow DOM. Otherwise, in synthetic shadow,
3085
- // we use an attribute selector on the host to simulate :dir().
3086
- let useNativeDirPseudoclass;
3087
- if (vm.renderMode === 1 /* RenderMode.Shadow */) {
3088
- useNativeDirPseudoclass = vm.shadowMode === 0 /* ShadowMode.Native */;
3089
- }
3090
- else {
3091
- // Light DOM components should only render `[dir]` if they're inside of a synthetic shadow root.
3092
- // At the top level (root is null) or inside of a native shadow root, they should use `:dir()`.
3093
- if (shared.isUndefined(root)) {
3094
- // Only calculate the root once as necessary
3095
- root = getNearestShadowComponent(vm);
3096
- }
3097
- useNativeDirPseudoclass = shared.isNull(root) || root.shadowMode === 0 /* ShadowMode.Native */;
3098
- }
3099
- shared.ArrayPush.call(content, stylesheet(scopeToken, useActualHostSelector, useNativeDirPseudoclass));
3117
+ } // Apply the scope token only if the stylesheet itself is scoped, or if we're rendering synthetic shadow.
3118
+
3119
+
3120
+ const scopeToken = isScopedCss || vm.shadowMode === 1
3121
+ /* ShadowMode.Synthetic */
3122
+ && vm.renderMode === 1
3123
+ /* RenderMode.Shadow */
3124
+ ? stylesheetToken : undefined; // Use the actual `:host` selector if we're rendering global CSS for light DOM, or if we're rendering
3125
+ // native shadow DOM. Synthetic shadow DOM never uses `:host`.
3126
+
3127
+ const useActualHostSelector = vm.renderMode === 0
3128
+ /* RenderMode.Light */
3129
+ ? !isScopedCss : vm.shadowMode === 0
3130
+ /* ShadowMode.Native */
3131
+ ; // Use the native :dir() pseudoclass only in native shadow DOM. Otherwise, in synthetic shadow,
3132
+ // we use an attribute selector on the host to simulate :dir().
3133
+
3134
+ let useNativeDirPseudoclass;
3135
+
3136
+ if (vm.renderMode === 1
3137
+ /* RenderMode.Shadow */
3138
+ ) {
3139
+ useNativeDirPseudoclass = vm.shadowMode === 0
3140
+ /* ShadowMode.Native */
3141
+ ;
3142
+ } else {
3143
+ // Light DOM components should only render `[dir]` if they're inside of a synthetic shadow root.
3144
+ // At the top level (root is null) or inside of a native shadow root, they should use `:dir()`.
3145
+ if (shared.isUndefined(root)) {
3146
+ // Only calculate the root once as necessary
3147
+ root = getNearestShadowComponent(vm);
3100
3148
  }
3149
+
3150
+ useNativeDirPseudoclass = shared.isNull(root) || root.shadowMode === 0
3151
+ /* ShadowMode.Native */
3152
+ ;
3153
+ }
3154
+
3155
+ shared.ArrayPush.call(content, stylesheet(scopeToken, useActualHostSelector, useNativeDirPseudoclass));
3101
3156
  }
3102
- return content;
3157
+ }
3158
+
3159
+ return content;
3103
3160
  }
3161
+
3104
3162
  function getStylesheetsContent(vm, template) {
3105
- const { stylesheets, stylesheetToken } = template;
3106
- let content = [];
3107
- if (!shared.isUndefined(stylesheets) && stylesheets.length !== 0) {
3108
- content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3109
- }
3110
- return content;
3111
- }
3112
- // It might be worth caching this to avoid doing the lookup repeatedly, but
3163
+ const {
3164
+ stylesheets,
3165
+ stylesheetToken
3166
+ } = template;
3167
+ let content = [];
3168
+
3169
+ if (!shared.isUndefined(stylesheets) && stylesheets.length !== 0) {
3170
+ content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3171
+ }
3172
+
3173
+ return content;
3174
+ } // It might be worth caching this to avoid doing the lookup repeatedly, but
3113
3175
  // perf testing has not shown it to be a huge improvement yet:
3114
3176
  // https://github.com/salesforce/lwc/pull/2460#discussion_r691208892
3177
+
3115
3178
  function getNearestShadowComponent(vm) {
3116
- let owner = vm;
3117
- while (!shared.isNull(owner)) {
3118
- if (owner.renderMode === 1 /* RenderMode.Shadow */) {
3119
- return owner;
3120
- }
3121
- owner = owner.owner;
3179
+ let owner = vm;
3180
+
3181
+ while (!shared.isNull(owner)) {
3182
+ if (owner.renderMode === 1
3183
+ /* RenderMode.Shadow */
3184
+ ) {
3185
+ return owner;
3122
3186
  }
3123
- return owner;
3187
+
3188
+ owner = owner.owner;
3189
+ }
3190
+
3191
+ return owner;
3124
3192
  }
3125
3193
  /**
3126
3194
  * If the component that is currently being rendered uses scoped styles,
3127
3195
  * this returns the unique token for that scoped stylesheet. Otherwise
3128
3196
  * it returns null.
3129
3197
  */
3198
+
3199
+
3130
3200
  function getScopeTokenClass(owner) {
3131
- const { cmpTemplate, context } = owner;
3132
- return (context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) || null;
3201
+ const {
3202
+ cmpTemplate,
3203
+ context
3204
+ } = owner;
3205
+ return context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken) || null;
3133
3206
  }
3134
- function getNearestNativeShadowComponent(vm) {
3135
- const owner = getNearestShadowComponent(vm);
3136
- if (!shared.isNull(owner) && owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
3137
- // Synthetic-within-native is impossible. So if the nearest shadow component is
3138
- // synthetic, we know we won't find a native component if we go any further.
3139
- return null;
3207
+ /**
3208
+ * This function returns the host style token for a custom element if it
3209
+ * exists. Otherwise it returns null.
3210
+ */
3211
+
3212
+ function getStylesheetTokenHost(vnode) {
3213
+ const {
3214
+ template: {
3215
+ stylesheetToken
3140
3216
  }
3141
- return owner;
3217
+ } = getComponentInternalDef(vnode.ctor);
3218
+ return !shared.isUndefined(stylesheetToken) ? makeHostToken(stylesheetToken) : null;
3219
+ }
3220
+
3221
+ function getNearestNativeShadowComponent(vm) {
3222
+ const owner = getNearestShadowComponent(vm);
3223
+
3224
+ if (!shared.isNull(owner) && owner.shadowMode === 1
3225
+ /* ShadowMode.Synthetic */
3226
+ ) {
3227
+ // Synthetic-within-native is impossible. So if the nearest shadow component is
3228
+ // synthetic, we know we won't find a native component if we go any further.
3229
+ return null;
3230
+ }
3231
+
3232
+ return owner;
3142
3233
  }
3234
+
3143
3235
  function createStylesheet(vm, stylesheets) {
3144
- const { renderMode, shadowMode, renderer: { insertStylesheet }, } = vm;
3145
- if (renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */) {
3146
- for (let i = 0; i < stylesheets.length; i++) {
3147
- insertStylesheet(stylesheets[i]);
3148
- }
3149
- }
3150
- else if (!process.env.IS_BROWSER || vm.hydrated) {
3151
- // Note: We need to ensure that during hydration, the stylesheets method is the same as those in ssr.
3152
- // This works in the client, because the stylesheets are created, and cached in the VM
3153
- // the first time the VM renders.
3154
- // native shadow or light DOM, SSR
3155
- return shared.ArrayMap.call(stylesheets, createInlineStyleVNode);
3236
+ const {
3237
+ renderMode,
3238
+ shadowMode,
3239
+ renderer: {
3240
+ insertStylesheet
3156
3241
  }
3157
- else {
3158
- // native shadow or light DOM, DOM renderer
3159
- const root = getNearestNativeShadowComponent(vm);
3160
- // null root means a global style
3161
- const target = shared.isNull(root) ? undefined : root.shadowRoot;
3162
- for (let i = 0; i < stylesheets.length; i++) {
3163
- insertStylesheet(stylesheets[i], target);
3164
- }
3242
+ } = vm;
3243
+
3244
+ if (renderMode === 1
3245
+ /* RenderMode.Shadow */
3246
+ && shadowMode === 1
3247
+ /* ShadowMode.Synthetic */
3248
+ ) {
3249
+ for (let i = 0; i < stylesheets.length; i++) {
3250
+ insertStylesheet(stylesheets[i]);
3251
+ }
3252
+ } else if (!process.env.IS_BROWSER || vm.hydrated) {
3253
+ // Note: We need to ensure that during hydration, the stylesheets method is the same as those in ssr.
3254
+ // This works in the client, because the stylesheets are created, and cached in the VM
3255
+ // the first time the VM renders.
3256
+ // native shadow or light DOM, SSR
3257
+ return shared.ArrayMap.call(stylesheets, createInlineStyleVNode);
3258
+ } else {
3259
+ // native shadow or light DOM, DOM renderer
3260
+ const root = getNearestNativeShadowComponent(vm); // null root means a global style
3261
+
3262
+ const target = shared.isNull(root) ? undefined : root.shadowRoot;
3263
+
3264
+ for (let i = 0; i < stylesheets.length; i++) {
3265
+ insertStylesheet(stylesheets[i], target);
3165
3266
  }
3166
- return null;
3267
+ }
3268
+
3269
+ return null;
3167
3270
  }
3168
3271
 
3169
3272
  /*
@@ -3248,6 +3351,9 @@ function isVBaseElement(vnode) {
3248
3351
  function isSameVnode(vnode1, vnode2) {
3249
3352
  return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
3250
3353
  }
3354
+ function isVCustomElement(vnode) {
3355
+ return vnode.type === 3 /* VNodeType.CustomElement */;
3356
+ }
3251
3357
 
3252
3358
  /*
3253
3359
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6541,6 +6647,7 @@ function validateClassAttr(vnode, elm, renderer) {
6541
6647
  let { className, classMap } = data;
6542
6648
  const { getProperty, getClassList } = renderer;
6543
6649
  const scopedToken = getScopeTokenClass(owner);
6650
+ const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
6544
6651
  // Classnames for scoped CSS are added directly to the DOM during rendering,
6545
6652
  // or to the VDOM on the server in the case of SSR. As such, these classnames
6546
6653
  // are never present in VDOM nodes in the browser.
@@ -6549,10 +6656,17 @@ function validateClassAttr(vnode, elm, renderer) {
6549
6656
  // are rendered during SSR. This needs to be accounted for when validating.
6550
6657
  if (scopedToken) {
6551
6658
  if (!shared.isUndefined(className)) {
6552
- className = `${scopedToken} ${className}`;
6659
+ className = shared.isNull(stylesheetTokenHost)
6660
+ ? `${scopedToken} ${className}`
6661
+ : `${scopedToken} ${className} ${stylesheetTokenHost}`;
6553
6662
  }
6554
6663
  else if (!shared.isUndefined(classMap)) {
6555
- classMap = Object.assign(Object.assign({}, classMap), { [scopedToken]: true });
6664
+ classMap = Object.assign(Object.assign(Object.assign({}, classMap), { [scopedToken]: true }), (shared.isNull(stylesheetTokenHost) ? {} : { [stylesheetTokenHost]: true }));
6665
+ }
6666
+ else {
6667
+ className = shared.isNull(stylesheetTokenHost)
6668
+ ? `${scopedToken}`
6669
+ : `${scopedToken} ${stylesheetTokenHost}`;
6556
6670
  }
6557
6671
  }
6558
6672
  let nodesAreCompatible = true;
@@ -6833,4 +6947,4 @@ exports.swapTemplate = swapTemplate;
6833
6947
  exports.track = track;
6834
6948
  exports.unwrap = unwrap;
6835
6949
  exports.wire = wire;
6836
- /* version: 2.24.0 */
6950
+ /* version: 2.25.1 */
@@ -3000,167 +3000,270 @@ function getComponentDef(Ctor) {
3000
3000
  * SPDX-License-Identifier: MIT
3001
3001
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3002
3002
  */
3003
+
3003
3004
  function makeHostToken(token) {
3004
- return `${token}-host`;
3005
+ return `${token}-host`;
3005
3006
  }
3007
+
3006
3008
  function createInlineStyleVNode(content) {
3007
- return api.h('style', {
3008
- key: 'style',
3009
- attrs: {
3010
- type: 'text/css',
3011
- },
3012
- }, [api.t(content)]);
3009
+ return api.h('style', {
3010
+ key: 'style',
3011
+ attrs: {
3012
+ type: 'text/css'
3013
+ }
3014
+ }, [api.t(content)]);
3013
3015
  }
3016
+
3014
3017
  function updateStylesheetToken(vm, template) {
3015
- const { elm, context, renderMode, shadowMode, renderer: { getClassList, removeAttribute, setAttribute }, } = vm;
3016
- const { stylesheets: newStylesheets, stylesheetToken: newStylesheetToken } = template;
3017
- const isSyntheticShadow = renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */;
3018
- const { hasScopedStyles } = context;
3019
- let newToken;
3020
- let newHasTokenInClass;
3021
- let newHasTokenInAttribute;
3022
- // Reset the styling token applied to the host element.
3023
- const { stylesheetToken: oldToken, hasTokenInClass: oldHasTokenInClass, hasTokenInAttribute: oldHasTokenInAttribute, } = context;
3024
- if (!isUndefined$1(oldToken)) {
3025
- if (oldHasTokenInClass) {
3026
- getClassList(elm).remove(makeHostToken(oldToken));
3027
- }
3028
- if (oldHasTokenInAttribute) {
3029
- removeAttribute(elm, makeHostToken(oldToken));
3030
- }
3031
- }
3032
- // Apply the new template styling token to the host element, if the new template has any
3033
- // associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
3034
- if (!isUndefined$1(newStylesheets) && newStylesheets.length !== 0) {
3035
- newToken = newStylesheetToken;
3036
- }
3037
- // Set the new styling token on the host element
3038
- if (!isUndefined$1(newToken)) {
3039
- if (hasScopedStyles) {
3040
- getClassList(elm).add(makeHostToken(newToken));
3041
- newHasTokenInClass = true;
3042
- }
3043
- if (isSyntheticShadow) {
3044
- setAttribute(elm, makeHostToken(newToken), '');
3045
- newHasTokenInAttribute = true;
3046
- }
3047
- }
3048
- // Update the styling tokens present on the context object.
3049
- context.stylesheetToken = newToken;
3050
- context.hasTokenInClass = newHasTokenInClass;
3051
- context.hasTokenInAttribute = newHasTokenInAttribute;
3018
+ const {
3019
+ elm,
3020
+ context,
3021
+ renderMode,
3022
+ shadowMode,
3023
+ renderer: {
3024
+ getClassList,
3025
+ removeAttribute,
3026
+ setAttribute
3027
+ }
3028
+ } = vm;
3029
+ const {
3030
+ stylesheets: newStylesheets,
3031
+ stylesheetToken: newStylesheetToken
3032
+ } = template;
3033
+ const isSyntheticShadow = renderMode === 1
3034
+ /* RenderMode.Shadow */
3035
+ && shadowMode === 1
3036
+ /* ShadowMode.Synthetic */
3037
+ ;
3038
+ const {
3039
+ hasScopedStyles
3040
+ } = context;
3041
+ let newToken;
3042
+ let newHasTokenInClass;
3043
+ let newHasTokenInAttribute; // Reset the styling token applied to the host element.
3044
+
3045
+ const {
3046
+ stylesheetToken: oldToken,
3047
+ hasTokenInClass: oldHasTokenInClass,
3048
+ hasTokenInAttribute: oldHasTokenInAttribute
3049
+ } = context;
3050
+
3051
+ if (!isUndefined$1(oldToken)) {
3052
+ if (oldHasTokenInClass) {
3053
+ getClassList(elm).remove(makeHostToken(oldToken));
3054
+ }
3055
+
3056
+ if (oldHasTokenInAttribute) {
3057
+ removeAttribute(elm, makeHostToken(oldToken));
3058
+ }
3059
+ } // Apply the new template styling token to the host element, if the new template has any
3060
+ // associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
3061
+
3062
+
3063
+ if (!isUndefined$1(newStylesheets) && newStylesheets.length !== 0) {
3064
+ newToken = newStylesheetToken;
3065
+ } // Set the new styling token on the host element
3066
+
3067
+
3068
+ if (!isUndefined$1(newToken)) {
3069
+ if (hasScopedStyles) {
3070
+ getClassList(elm).add(makeHostToken(newToken));
3071
+ newHasTokenInClass = true;
3072
+ }
3073
+
3074
+ if (isSyntheticShadow) {
3075
+ setAttribute(elm, makeHostToken(newToken), '');
3076
+ newHasTokenInAttribute = true;
3077
+ }
3078
+ } // Update the styling tokens present on the context object.
3079
+
3080
+
3081
+ context.stylesheetToken = newToken;
3082
+ context.hasTokenInClass = newHasTokenInClass;
3083
+ context.hasTokenInAttribute = newHasTokenInAttribute;
3052
3084
  }
3085
+
3053
3086
  function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3054
- const content = [];
3055
- let root;
3056
- for (let i = 0; i < stylesheets.length; i++) {
3057
- let stylesheet = stylesheets[i];
3058
- if (isArray$1(stylesheet)) {
3059
- ArrayPush$1.apply(content, evaluateStylesheetsContent(stylesheet, stylesheetToken, vm));
3087
+ const content = [];
3088
+ let root;
3089
+
3090
+ for (let i = 0; i < stylesheets.length; i++) {
3091
+ let stylesheet = stylesheets[i];
3092
+
3093
+ if (isArray$1(stylesheet)) {
3094
+ ArrayPush$1.apply(content, evaluateStylesheetsContent(stylesheet, stylesheetToken, vm));
3095
+ } else {
3096
+ if (process.env.NODE_ENV !== 'production') {
3097
+ // Check for compiler version mismatch in dev mode only
3098
+ checkVersionMismatch(stylesheet, 'stylesheet'); // in dev-mode, we support hot swapping of stylesheet, which means that
3099
+ // the component instance might be attempting to use an old version of
3100
+ // the stylesheet, while internally, we have a replacement for it.
3101
+
3102
+ stylesheet = getStyleOrSwappedStyle(stylesheet);
3103
+ }
3104
+
3105
+ const isScopedCss = stylesheet[KEY__SCOPED_CSS];
3106
+
3107
+ if (lwcRuntimeFlags.DISABLE_LIGHT_DOM_UNSCOPED_CSS) {
3108
+ if (!isScopedCss && vm.renderMode === 0
3109
+ /* RenderMode.Light */
3110
+ ) {
3111
+ logError('Unscoped CSS is not supported in Light DOM. Please use scoped CSS (*.scoped.css) instead of unscoped CSS (*.css).');
3112
+ continue;
3060
3113
  }
3061
- else {
3062
- if (process.env.NODE_ENV !== 'production') {
3063
- // Check for compiler version mismatch in dev mode only
3064
- checkVersionMismatch(stylesheet, 'stylesheet');
3065
- // in dev-mode, we support hot swapping of stylesheet, which means that
3066
- // the component instance might be attempting to use an old version of
3067
- // the stylesheet, while internally, we have a replacement for it.
3068
- stylesheet = getStyleOrSwappedStyle(stylesheet);
3069
- }
3070
- const isScopedCss = stylesheet[KEY__SCOPED_CSS];
3071
- // Apply the scope token only if the stylesheet itself is scoped, or if we're rendering synthetic shadow.
3072
- const scopeToken = isScopedCss ||
3073
- (vm.shadowMode === 1 /* ShadowMode.Synthetic */ && vm.renderMode === 1 /* RenderMode.Shadow */)
3074
- ? stylesheetToken
3075
- : undefined;
3076
- // Use the actual `:host` selector if we're rendering global CSS for light DOM, or if we're rendering
3077
- // native shadow DOM. Synthetic shadow DOM never uses `:host`.
3078
- const useActualHostSelector = vm.renderMode === 0 /* RenderMode.Light */
3079
- ? !isScopedCss
3080
- : vm.shadowMode === 0 /* ShadowMode.Native */;
3081
- // Use the native :dir() pseudoclass only in native shadow DOM. Otherwise, in synthetic shadow,
3082
- // we use an attribute selector on the host to simulate :dir().
3083
- let useNativeDirPseudoclass;
3084
- if (vm.renderMode === 1 /* RenderMode.Shadow */) {
3085
- useNativeDirPseudoclass = vm.shadowMode === 0 /* ShadowMode.Native */;
3086
- }
3087
- else {
3088
- // Light DOM components should only render `[dir]` if they're inside of a synthetic shadow root.
3089
- // At the top level (root is null) or inside of a native shadow root, they should use `:dir()`.
3090
- if (isUndefined$1(root)) {
3091
- // Only calculate the root once as necessary
3092
- root = getNearestShadowComponent(vm);
3093
- }
3094
- useNativeDirPseudoclass = isNull(root) || root.shadowMode === 0 /* ShadowMode.Native */;
3095
- }
3096
- ArrayPush$1.call(content, stylesheet(scopeToken, useActualHostSelector, useNativeDirPseudoclass));
3114
+ } // Apply the scope token only if the stylesheet itself is scoped, or if we're rendering synthetic shadow.
3115
+
3116
+
3117
+ const scopeToken = isScopedCss || vm.shadowMode === 1
3118
+ /* ShadowMode.Synthetic */
3119
+ && vm.renderMode === 1
3120
+ /* RenderMode.Shadow */
3121
+ ? stylesheetToken : undefined; // Use the actual `:host` selector if we're rendering global CSS for light DOM, or if we're rendering
3122
+ // native shadow DOM. Synthetic shadow DOM never uses `:host`.
3123
+
3124
+ const useActualHostSelector = vm.renderMode === 0
3125
+ /* RenderMode.Light */
3126
+ ? !isScopedCss : vm.shadowMode === 0
3127
+ /* ShadowMode.Native */
3128
+ ; // Use the native :dir() pseudoclass only in native shadow DOM. Otherwise, in synthetic shadow,
3129
+ // we use an attribute selector on the host to simulate :dir().
3130
+
3131
+ let useNativeDirPseudoclass;
3132
+
3133
+ if (vm.renderMode === 1
3134
+ /* RenderMode.Shadow */
3135
+ ) {
3136
+ useNativeDirPseudoclass = vm.shadowMode === 0
3137
+ /* ShadowMode.Native */
3138
+ ;
3139
+ } else {
3140
+ // Light DOM components should only render `[dir]` if they're inside of a synthetic shadow root.
3141
+ // At the top level (root is null) or inside of a native shadow root, they should use `:dir()`.
3142
+ if (isUndefined$1(root)) {
3143
+ // Only calculate the root once as necessary
3144
+ root = getNearestShadowComponent(vm);
3097
3145
  }
3146
+
3147
+ useNativeDirPseudoclass = isNull(root) || root.shadowMode === 0
3148
+ /* ShadowMode.Native */
3149
+ ;
3150
+ }
3151
+
3152
+ ArrayPush$1.call(content, stylesheet(scopeToken, useActualHostSelector, useNativeDirPseudoclass));
3098
3153
  }
3099
- return content;
3154
+ }
3155
+
3156
+ return content;
3100
3157
  }
3158
+
3101
3159
  function getStylesheetsContent(vm, template) {
3102
- const { stylesheets, stylesheetToken } = template;
3103
- let content = [];
3104
- if (!isUndefined$1(stylesheets) && stylesheets.length !== 0) {
3105
- content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3106
- }
3107
- return content;
3108
- }
3109
- // It might be worth caching this to avoid doing the lookup repeatedly, but
3160
+ const {
3161
+ stylesheets,
3162
+ stylesheetToken
3163
+ } = template;
3164
+ let content = [];
3165
+
3166
+ if (!isUndefined$1(stylesheets) && stylesheets.length !== 0) {
3167
+ content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3168
+ }
3169
+
3170
+ return content;
3171
+ } // It might be worth caching this to avoid doing the lookup repeatedly, but
3110
3172
  // perf testing has not shown it to be a huge improvement yet:
3111
3173
  // https://github.com/salesforce/lwc/pull/2460#discussion_r691208892
3174
+
3112
3175
  function getNearestShadowComponent(vm) {
3113
- let owner = vm;
3114
- while (!isNull(owner)) {
3115
- if (owner.renderMode === 1 /* RenderMode.Shadow */) {
3116
- return owner;
3117
- }
3118
- owner = owner.owner;
3176
+ let owner = vm;
3177
+
3178
+ while (!isNull(owner)) {
3179
+ if (owner.renderMode === 1
3180
+ /* RenderMode.Shadow */
3181
+ ) {
3182
+ return owner;
3119
3183
  }
3120
- return owner;
3184
+
3185
+ owner = owner.owner;
3186
+ }
3187
+
3188
+ return owner;
3121
3189
  }
3122
3190
  /**
3123
3191
  * If the component that is currently being rendered uses scoped styles,
3124
3192
  * this returns the unique token for that scoped stylesheet. Otherwise
3125
3193
  * it returns null.
3126
3194
  */
3195
+
3196
+
3127
3197
  function getScopeTokenClass(owner) {
3128
- const { cmpTemplate, context } = owner;
3129
- return (context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) || null;
3198
+ const {
3199
+ cmpTemplate,
3200
+ context
3201
+ } = owner;
3202
+ return context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken) || null;
3130
3203
  }
3131
- function getNearestNativeShadowComponent(vm) {
3132
- const owner = getNearestShadowComponent(vm);
3133
- if (!isNull(owner) && owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
3134
- // Synthetic-within-native is impossible. So if the nearest shadow component is
3135
- // synthetic, we know we won't find a native component if we go any further.
3136
- return null;
3204
+ /**
3205
+ * This function returns the host style token for a custom element if it
3206
+ * exists. Otherwise it returns null.
3207
+ */
3208
+
3209
+ function getStylesheetTokenHost(vnode) {
3210
+ const {
3211
+ template: {
3212
+ stylesheetToken
3137
3213
  }
3138
- return owner;
3214
+ } = getComponentInternalDef(vnode.ctor);
3215
+ return !isUndefined$1(stylesheetToken) ? makeHostToken(stylesheetToken) : null;
3216
+ }
3217
+
3218
+ function getNearestNativeShadowComponent(vm) {
3219
+ const owner = getNearestShadowComponent(vm);
3220
+
3221
+ if (!isNull(owner) && owner.shadowMode === 1
3222
+ /* ShadowMode.Synthetic */
3223
+ ) {
3224
+ // Synthetic-within-native is impossible. So if the nearest shadow component is
3225
+ // synthetic, we know we won't find a native component if we go any further.
3226
+ return null;
3227
+ }
3228
+
3229
+ return owner;
3139
3230
  }
3231
+
3140
3232
  function createStylesheet(vm, stylesheets) {
3141
- const { renderMode, shadowMode, renderer: { insertStylesheet }, } = vm;
3142
- if (renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */) {
3143
- for (let i = 0; i < stylesheets.length; i++) {
3144
- insertStylesheet(stylesheets[i]);
3145
- }
3146
- }
3147
- else if (!process.env.IS_BROWSER || vm.hydrated) {
3148
- // Note: We need to ensure that during hydration, the stylesheets method is the same as those in ssr.
3149
- // This works in the client, because the stylesheets are created, and cached in the VM
3150
- // the first time the VM renders.
3151
- // native shadow or light DOM, SSR
3152
- return ArrayMap.call(stylesheets, createInlineStyleVNode);
3233
+ const {
3234
+ renderMode,
3235
+ shadowMode,
3236
+ renderer: {
3237
+ insertStylesheet
3153
3238
  }
3154
- else {
3155
- // native shadow or light DOM, DOM renderer
3156
- const root = getNearestNativeShadowComponent(vm);
3157
- // null root means a global style
3158
- const target = isNull(root) ? undefined : root.shadowRoot;
3159
- for (let i = 0; i < stylesheets.length; i++) {
3160
- insertStylesheet(stylesheets[i], target);
3161
- }
3239
+ } = vm;
3240
+
3241
+ if (renderMode === 1
3242
+ /* RenderMode.Shadow */
3243
+ && shadowMode === 1
3244
+ /* ShadowMode.Synthetic */
3245
+ ) {
3246
+ for (let i = 0; i < stylesheets.length; i++) {
3247
+ insertStylesheet(stylesheets[i]);
3248
+ }
3249
+ } else if (!process.env.IS_BROWSER || vm.hydrated) {
3250
+ // Note: We need to ensure that during hydration, the stylesheets method is the same as those in ssr.
3251
+ // This works in the client, because the stylesheets are created, and cached in the VM
3252
+ // the first time the VM renders.
3253
+ // native shadow or light DOM, SSR
3254
+ return ArrayMap.call(stylesheets, createInlineStyleVNode);
3255
+ } else {
3256
+ // native shadow or light DOM, DOM renderer
3257
+ const root = getNearestNativeShadowComponent(vm); // null root means a global style
3258
+
3259
+ const target = isNull(root) ? undefined : root.shadowRoot;
3260
+
3261
+ for (let i = 0; i < stylesheets.length; i++) {
3262
+ insertStylesheet(stylesheets[i], target);
3162
3263
  }
3163
- return null;
3264
+ }
3265
+
3266
+ return null;
3164
3267
  }
3165
3268
 
3166
3269
  /*
@@ -3245,6 +3348,9 @@ function isVBaseElement(vnode) {
3245
3348
  function isSameVnode(vnode1, vnode2) {
3246
3349
  return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel;
3247
3350
  }
3351
+ function isVCustomElement(vnode) {
3352
+ return vnode.type === 3 /* VNodeType.CustomElement */;
3353
+ }
3248
3354
 
3249
3355
  /*
3250
3356
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6538,6 +6644,7 @@ function validateClassAttr(vnode, elm, renderer) {
6538
6644
  let { className, classMap } = data;
6539
6645
  const { getProperty, getClassList } = renderer;
6540
6646
  const scopedToken = getScopeTokenClass(owner);
6647
+ const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
6541
6648
  // Classnames for scoped CSS are added directly to the DOM during rendering,
6542
6649
  // or to the VDOM on the server in the case of SSR. As such, these classnames
6543
6650
  // are never present in VDOM nodes in the browser.
@@ -6546,10 +6653,17 @@ function validateClassAttr(vnode, elm, renderer) {
6546
6653
  // are rendered during SSR. This needs to be accounted for when validating.
6547
6654
  if (scopedToken) {
6548
6655
  if (!isUndefined$1(className)) {
6549
- className = `${scopedToken} ${className}`;
6656
+ className = isNull(stylesheetTokenHost)
6657
+ ? `${scopedToken} ${className}`
6658
+ : `${scopedToken} ${className} ${stylesheetTokenHost}`;
6550
6659
  }
6551
6660
  else if (!isUndefined$1(classMap)) {
6552
- classMap = Object.assign(Object.assign({}, classMap), { [scopedToken]: true });
6661
+ classMap = Object.assign(Object.assign(Object.assign({}, classMap), { [scopedToken]: true }), (isNull(stylesheetTokenHost) ? {} : { [stylesheetTokenHost]: true }));
6662
+ }
6663
+ else {
6664
+ className = isNull(stylesheetTokenHost)
6665
+ ? `${scopedToken}`
6666
+ : `${scopedToken} ${stylesheetTokenHost}`;
6553
6667
  }
6554
6668
  }
6555
6669
  let nodesAreCompatible = true;
@@ -6793,4 +6907,4 @@ function getComponentConstructor(elm) {
6793
6907
  }
6794
6908
 
6795
6909
  export { LightningElement, profilerControl as __unstable__ProfilerControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, getUpgradableConstructor, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
6796
- /* version: 2.24.0 */
6910
+ /* version: 2.25.1 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lwc/engine-core",
3
- "version": "2.24.0",
3
+ "version": "2.25.1",
4
4
  "description": "Core LWC engine APIs.",
5
5
  "homepage": "https://lwc.dev/",
6
6
  "repository": {
@@ -24,8 +24,8 @@
24
24
  "types/"
25
25
  ],
26
26
  "dependencies": {
27
- "@lwc/features": "2.24.0",
28
- "@lwc/shared": "2.24.0"
27
+ "@lwc/features": "2.25.1",
28
+ "@lwc/shared": "2.25.1"
29
29
  },
30
30
  "devDependencies": {
31
31
  "observable-membrane": "2.0.0"
@@ -1,6 +1,6 @@
1
1
  import { VM } from './vm';
2
2
  import { Template } from './template';
3
- import { VNode } from './vnodes';
3
+ import { VCustomElement, VNode } from './vnodes';
4
4
  /**
5
5
  * Function producing style based on a host and a shadow selector. This function is invoked by
6
6
  * the engine with different values depending on the mode that the component is running on.
@@ -20,4 +20,9 @@ export declare function getStylesheetsContent(vm: VM, template: Template): strin
20
20
  * it returns null.
21
21
  */
22
22
  export declare function getScopeTokenClass(owner: VM): string | null;
23
+ /**
24
+ * This function returns the host style token for a custom element if it
25
+ * exists. Otherwise it returns null.
26
+ */
27
+ export declare function getStylesheetTokenHost(vnode: VCustomElement): string | null;
23
28
  export declare function createStylesheet(vm: VM, stylesheets: string[]): VNode[] | null;
@@ -80,3 +80,4 @@ export interface VElementData extends VNodeData {
80
80
  }
81
81
  export declare function isVBaseElement(vnode: VNode): vnode is VElement | VCustomElement;
82
82
  export declare function isSameVnode(vnode1: VNode, vnode2: VNode): boolean;
83
+ export declare function isVCustomElement(vnode: VBaseElement): vnode is VCustomElement;