@lwc/engine-core 7.2.0 → 7.2.2

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Copyright (c) 2024 Salesforce, Inc.
3
3
  */
4
- import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArrayPop, create, isFalse, isFunction as isFunction$1, isObject, seal, isAPIFeatureEnabled, isArray as isArray$1, keys, hasOwnProperty as hasOwnProperty$1, entries, AriaPropNameToAttrNameMap, getPropertyDescriptor, forEach, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, ArraySplice, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, isNumber, StringReplace, StringTrim, htmlEscape, StringCharAt, ArrayUnshift, LOWEST_API_VERSION, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, arrayEvery, ArrayIncludes, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift } from '@lwc/shared';
4
+ import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArrayPop, create, isFalse, isFunction as isFunction$1, isObject, seal, isAPIFeatureEnabled, isArray as isArray$1, keys, hasOwnProperty as hasOwnProperty$1, entries, AriaPropNameToAttrNameMap, getPropertyDescriptor, forEach, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, ArraySplice, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, isNumber, StringReplace, StringTrim, ArrayFrom, htmlEscape, StringCharAt, ArrayUnshift, LOWEST_API_VERSION, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, arrayEvery, ArrayIncludes, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift } from '@lwc/shared';
5
5
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
6
6
 
7
7
  /*
@@ -151,7 +151,7 @@ function log(method, message, vm, once) {
151
151
  }
152
152
  alreadyLoggedMessages.add(msg);
153
153
  }
154
- // In Jest tests, reduce the warning and error verbosity by not printing the callstack
154
+ // In Vitest tests, reduce the warning and error verbosity by not printing the callstack
155
155
  if (process.env.NODE_ENV === 'test') {
156
156
  /* eslint-disable-next-line no-console */
157
157
  console[method](msg);
@@ -3129,15 +3129,22 @@ function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3129
3129
  function getStylesheetsContent(vm, template) {
3130
3130
  const { stylesheets, stylesheetToken } = template;
3131
3131
  const { stylesheets: vmStylesheets } = vm;
3132
- let content = [];
3133
- if (hasStyles(stylesheets)) {
3134
- content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3132
+ const hasTemplateStyles = hasStyles(stylesheets);
3133
+ const hasVmStyles = hasStyles(vmStylesheets);
3134
+ if (hasTemplateStyles) {
3135
+ const content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
3136
+ if (hasVmStyles) {
3137
+ // Slow path – merge the template styles and vm styles
3138
+ ArrayPush$1.apply(content, evaluateStylesheetsContent(vmStylesheets, stylesheetToken, vm));
3139
+ }
3140
+ return content;
3135
3141
  }
3136
- // VM (component) stylesheets apply after template stylesheets
3137
- if (hasStyles(vmStylesheets)) {
3138
- ArrayPush$1.apply(content, evaluateStylesheetsContent(vmStylesheets, stylesheetToken, vm));
3142
+ if (hasVmStyles) {
3143
+ // No template styles, so return vm styles directly
3144
+ return evaluateStylesheetsContent(vmStylesheets, stylesheetToken, vm);
3139
3145
  }
3140
- return content;
3146
+ // Fastest path - no styles, so return an empty array
3147
+ return EmptyArray;
3141
3148
  }
3142
3149
  // It might be worth caching this to avoid doing the lookup repeatedly, but
3143
3150
  // perf testing has not shown it to be a huge improvement yet:
@@ -5248,22 +5255,30 @@ function s(slotName, data, children, slotset) {
5248
5255
  if (renderMode === 0 /* RenderMode.Light */ &&
5249
5256
  isAPIFeatureEnabled(6 /* APIFeature.USE_LIGHT_DOM_SLOT_FORWARDING */, apiVersion) &&
5250
5257
  (isVBaseElement(vnode) || isVStatic(vnode)) &&
5251
- // We only need to copy the vnodes when the slot assignment changes, copying every time causes issues with
5252
- // disconnected/connected callback firing.
5253
5258
  vnode.slotAssignment !== data.slotAssignment) {
5254
- // When the light DOM slot assignment (slot attribute) changes we can't use the same reference
5255
- // to the vnode because the current way the diffing algo works, it will replace the original reference
5256
- // to the host element with a new one. This means the new element will be mounted and immediately unmounted.
5257
- // Creating a copy of the vnode to preserve a reference to the previous host element.
5258
- if (isUndefined$1(vnode.elm)) {
5259
- // vnode.elm is undefined during initial render.
5260
- // We don't need to clone at this point because it doesn't need to be unmounted.
5261
- vnode.slotAssignment = data.slotAssignment;
5262
- }
5263
- else {
5264
- // Clone when the vnode.elm is defined to ensure we don't lose reference to the previous element.
5265
- // This is specifically for slot forwarding.
5266
- clonedVNode = { ...vnode, slotAssignment: data.slotAssignment };
5259
+ // When the light DOM slot assignment (slot attribute) changes, we can't use the same reference
5260
+ // to the vnode because the current way the diffing algo works, it will replace the original
5261
+ // reference to the host element with a new one. This means the new element will be mounted and
5262
+ // immediately unmounted. Creating a copy of the vnode preserves a reference to the previous
5263
+ // host element.
5264
+ clonedVNode = { ...vnode, slotAssignment: data.slotAssignment };
5265
+ // For disconnectedCallback to work correctly in synthetic lifecycle mode, we need to link the
5266
+ // current VM's velements to the clone, so that when the VM unmounts, the clone also unmounts.
5267
+ // Note this only applies to VCustomElements, since those are the elements that we manually need
5268
+ // to call disconnectedCallback for, when running in synthetic lifecycle mode.
5269
+ //
5270
+ // You might think it would make more sense to add the clonedVNode to the same velements array
5271
+ // as the original vnode's VM (i.e. `vnode.owner.velements`) rather than the current VM (i.e.
5272
+ // `vmBeingRendered.velements`), but this actually might not trigger disconnectedCallback
5273
+ // in synthetic lifecycle mode. The reason for this is that a reactivity change may cause
5274
+ // the slottable component to unmount, but _not_ the slotter component (see issue #4446).
5275
+ //
5276
+ // If this occurs, then the slottable component (i.e .this component we are rendering right
5277
+ // now) is the one that needs to own the clone. Whereas if a reactivity change higher in the
5278
+ // tree causes the slotter to unmount, then the slottable will also unmount. So using the
5279
+ // current VM works either way.
5280
+ if (isVCustomElement(vnode)) {
5281
+ addVNodeToChildLWC(clonedVNode);
5267
5282
  }
5268
5283
  }
5269
5284
  // If the slot content is standard type, the content is static, no additional
@@ -5341,14 +5356,14 @@ function i(iterable, factory) {
5341
5356
  // TODO [#1276]: compiler should give us some sort of indicator when a vnodes collection is dynamic
5342
5357
  sc(list);
5343
5358
  const vmBeingRendered = getVMBeingRendered();
5344
- if (isUndefined$1(iterable) || iterable === null) {
5359
+ if (isUndefined$1(iterable) || isNull(iterable)) {
5345
5360
  if (process.env.NODE_ENV !== 'production') {
5346
- logError(`Invalid template iteration for value "${toString$1(iterable)}" in ${vmBeingRendered}. It must be an Array or an iterable Object.`, vmBeingRendered);
5361
+ logError(`Invalid template iteration for value \`${toString$1(iterable)}\` in ${vmBeingRendered}. It must be an array-like object.`, vmBeingRendered);
5347
5362
  }
5348
5363
  return list;
5349
5364
  }
5350
5365
  if (process.env.NODE_ENV !== 'production') {
5351
- assert.isFalse(isUndefined$1(iterable[SymbolIterator]), `Invalid template iteration for value \`${toString$1(iterable)}\` in ${vmBeingRendered}. It must be an array-like object and not \`null\` nor \`undefined\`.`);
5366
+ assert.isFalse(isUndefined$1(iterable[SymbolIterator]), `Invalid template iteration for value \`${toString$1(iterable)}\` in ${vmBeingRendered}. It must be an array-like object.`);
5352
5367
  }
5353
5368
  const iterator = iterable[SymbolIterator]();
5354
5369
  if (process.env.NODE_ENV !== 'production') {
@@ -5485,9 +5500,6 @@ function k(compilerKey, obj) {
5485
5500
  function gid(id) {
5486
5501
  const vmBeingRendered = getVMBeingRendered();
5487
5502
  if (isUndefined$1(id) || id === '') {
5488
- if (process.env.NODE_ENV !== 'production') {
5489
- logError(`Invalid id value "${id}". The id attribute must contain a non-empty string.`, vmBeingRendered);
5490
- }
5491
5503
  return id;
5492
5504
  }
5493
5505
  // We remove attributes when they are assigned a value of null
@@ -5504,11 +5516,6 @@ function gid(id) {
5504
5516
  function fid(url) {
5505
5517
  const vmBeingRendered = getVMBeingRendered();
5506
5518
  if (isUndefined$1(url) || url === '') {
5507
- if (process.env.NODE_ENV !== 'production') {
5508
- if (isUndefined$1(url)) {
5509
- logError(`Undefined url value for "href" or "xlink:href" attribute. Expected a non-empty string.`, vmBeingRendered);
5510
- }
5511
- }
5512
5519
  return url;
5513
5520
  }
5514
5521
  // We remove attributes when they are assigned a value of null
@@ -5793,6 +5800,44 @@ function logGlobalOperationEnd(opId, vm) {
5793
5800
  }
5794
5801
  }
5795
5802
 
5803
+ /*
5804
+ * Copyright (c) 2024, Salesforce, Inc.
5805
+ * All rights reserved.
5806
+ * SPDX-License-Identifier: MIT
5807
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
5808
+ */
5809
+ // HAS_SCOPED_STYLE | SHADOW_MODE_SYNTHETIC = 3
5810
+ const MAX_CACHE_KEY = 3;
5811
+ // Mapping of cacheKeys to `string[]` (assumed to come from a tagged template literal) to an Element.
5812
+ // Note that every unique tagged template literal will have a unique `string[]`. So by using `string[]`
5813
+ // as the WeakMap key, we effectively associate each Element with a unique tagged template literal.
5814
+ // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates
5815
+ // Also note that this array only needs to be large enough to account for the maximum possible cache key
5816
+ const fragmentCache = ArrayFrom({ length: MAX_CACHE_KEY + 1 }, () => new WeakMap());
5817
+ // Only used in LWC's Karma tests
5818
+ if (process.env.NODE_ENV === 'test-karma-lwc') {
5819
+ window.__lwcResetFragmentCache = () => {
5820
+ for (let i = 0; i < fragmentCache.length; i++) {
5821
+ fragmentCache[i] = new WeakMap();
5822
+ }
5823
+ };
5824
+ }
5825
+ function checkIsBrowser() {
5826
+ // The fragment cache only serves prevent calling innerHTML multiple times which doesn't happen on the server.
5827
+ /* istanbul ignore next */
5828
+ if (!process.env.IS_BROWSER) {
5829
+ throw new Error('The fragment cache is intended to only be used in @lwc/engine-dom, not @lwc/engine-server');
5830
+ }
5831
+ }
5832
+ function getFromFragmentCache(cacheKey, strings) {
5833
+ checkIsBrowser();
5834
+ return fragmentCache[cacheKey].get(strings);
5835
+ }
5836
+ function setInFragmentCache(cacheKey, strings, element) {
5837
+ checkIsBrowser();
5838
+ fragmentCache[cacheKey].set(strings, element);
5839
+ }
5840
+
5796
5841
  /*
5797
5842
  * Copyright (c) 2024, Salesforce, Inc.
5798
5843
  * All rights reserved.
@@ -5936,43 +5981,24 @@ function serializeClassAttribute(part, classToken) {
5936
5981
  const computedClassName = `${classToken} ${keys(classMap).join(' ')}`.trim();
5937
5982
  return computedClassName.length ? ` class="${htmlEscape(computedClassName, true)}"` : '';
5938
5983
  }
5939
- // This should be a no-op outside of LWC's Karma tests, where it's not needed
5940
- let registerFragmentCache = noop;
5941
- // Only used in LWC's Karma tests
5942
- if (process.env.NODE_ENV === 'test-karma-lwc') {
5943
- // Keep track of fragmentCaches, so we can clear them in LWC's Karma tests
5944
- const fragmentCaches = [];
5945
- registerFragmentCache = (fragmentCache) => {
5946
- fragmentCaches.push(fragmentCache);
5947
- };
5948
- window.__lwcResetFragmentCaches = () => {
5949
- for (const fragmentCache of fragmentCaches) {
5950
- for (const key of keys(fragmentCache)) {
5951
- delete fragmentCache[key];
5952
- }
5953
- }
5954
- };
5955
- }
5956
5984
  function buildParseFragmentFn(createFragmentFn) {
5957
- return (strings, ...keys) => {
5958
- const cache = create(null);
5959
- registerFragmentCache(cache);
5960
- return function (parts) {
5985
+ return function parseFragment(strings, ...keys) {
5986
+ return function applyFragmentParts(parts) {
5961
5987
  const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5962
5988
  const hasStyleToken = !isUndefined$1(stylesheetToken);
5963
5989
  const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
5964
5990
  const hasLegacyToken = lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS && !isUndefined$1(legacyStylesheetToken);
5965
5991
  let cacheKey = 0;
5966
5992
  if (hasStyleToken && hasScopedStyles) {
5967
- cacheKey |= 1 /* FragmentCache.HAS_SCOPED_STYLE */;
5993
+ cacheKey |= 1 /* FragmentCacheKey.HAS_SCOPED_STYLE */;
5968
5994
  }
5969
5995
  if (hasStyleToken && isSyntheticShadow) {
5970
- cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
5996
+ cacheKey |= 2 /* FragmentCacheKey.SHADOW_MODE_SYNTHETIC */;
5971
5997
  }
5972
5998
  // Cache is only here to prevent calling innerHTML multiple times which doesn't happen on the server.
5973
5999
  if (process.env.IS_BROWSER) {
5974
6000
  // Disable this on the server to prevent cache poisoning when expressions are used.
5975
- const cached = cache[cacheKey];
6001
+ const cached = getFromFragmentCache(cacheKey, strings);
5976
6002
  if (!isUndefined$1(cached)) {
5977
6003
  return cached;
5978
6004
  }
@@ -6012,8 +6038,12 @@ function buildParseFragmentFn(createFragmentFn) {
6012
6038
  }
6013
6039
  }
6014
6040
  htmlFragment += strings[strings.length - 1];
6015
- cache[cacheKey] = createFragmentFn(htmlFragment, renderer);
6016
- return cache[cacheKey];
6041
+ const element = createFragmentFn(htmlFragment, renderer);
6042
+ // Cache is only here to prevent calling innerHTML multiple times which doesn't happen on the server.
6043
+ if (process.env.IS_BROWSER) {
6044
+ setInFragmentCache(cacheKey, strings, element);
6045
+ }
6046
+ return element;
6017
6047
  };
6018
6048
  };
6019
6049
  }
@@ -6548,6 +6578,8 @@ function computeShadowMode(def, owner, renderer, hydrated) {
6548
6578
  // on, but components running in actual native shadow mode
6549
6579
  (process.env.NODE_ENV === 'test-karma-lwc' &&
6550
6580
  process.env.FORCE_NATIVE_SHADOW_MODE_FOR_TEST) ||
6581
+ // If synthetic shadow is explicitly disabled, use pure-native
6582
+ lwcRuntimeFlags.DISABLE_SYNTHETIC_SHADOW ||
6551
6583
  // hydration only supports native shadow
6552
6584
  isTrue(hydrated)) {
6553
6585
  return 0 /* ShadowMode.Native */;
@@ -8044,5 +8076,5 @@ function readonly(obj) {
8044
8076
  }
8045
8077
 
8046
8078
  export { LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, computeShadowAndRenderMode, connectRootElement, createContextProviderWithRegister, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentAPIVersion, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerTemplate, runFormAssociatedCallback, runFormDisabledCallback, runFormResetCallback, runFormStateRestoreCallback, sanitizeAttribute, setHooks, shouldBeFormAssociated, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
8047
- /** version: 7.2.0 */
8079
+ /** version: 7.2.2 */
8048
8080
  //# sourceMappingURL=index.js.map