@lwc/engine-core 3.7.1 → 3.7.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) 2023 salesforce.com, inc.
3
3
  */
4
- 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, globalThis as globalThis$1, forEach, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, freeze, KEY__SYNTHETIC_MODE, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, ArrayShift, ArrayUnshift, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, 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 } from '@lwc/shared';
4
+ 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, globalThis as globalThis$1, forEach, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, freeze, KEY__SYNTHETIC_MODE, isString, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, getOwnPropertyDescriptors, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, StringSlice, ArrayShift, ArrayUnshift, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, 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 } from '@lwc/shared';
5
5
  import { applyAriaReflection } from '@lwc/aria-reflection';
6
6
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
7
7
 
@@ -1454,12 +1454,31 @@ const formAssociatedProps = new Set([
1454
1454
  'labels',
1455
1455
  ]);
1456
1456
  // Verify that access to a form-associated property of the ElementInternals proxy has formAssociated set in the LWC.
1457
- function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1458
- if (formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1457
+ function verifyPropForFormAssociation(propertyKey, isFormAssociated) {
1458
+ if (isString(propertyKey) && formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1459
1459
  //Note this error message mirrors Chrome and Firefox error messages, in Safari the error is slightly different.
1460
1460
  throw new DOMException(`Failed to execute '${propertyKey}' on 'ElementInternals': The target element is not a form-associated custom element.`);
1461
1461
  }
1462
1462
  }
1463
+ const elementInternalsAccessorAllowList = new Set(['shadowRoot', 'role', ...formAssociatedProps]);
1464
+ // Prevent access to properties not defined in the HTML spec in case browsers decide to
1465
+ // provide new APIs that provide access to form associated properties.
1466
+ // This can be removed along with UpgradeableConstructor.
1467
+ function isAllowedElementInternalAccessor(propertyKey) {
1468
+ let isAllowedAccessor = false;
1469
+ // As of this writing all ElementInternal property keys as described in the spec are implemented with strings
1470
+ // in Chrome, Firefox, and Safari
1471
+ if (isString(propertyKey)) {
1472
+ // Allow list is based on HTML spec:
1473
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#the-elementinternals-interface
1474
+ isAllowedAccessor =
1475
+ elementInternalsAccessorAllowList.has(propertyKey) || /^aria/.test(propertyKey);
1476
+ if (!isAllowedAccessor && process.env.NODE_ENV !== 'production') {
1477
+ logWarn('Only properties defined in the ElementInternals HTML spec are available.');
1478
+ }
1479
+ }
1480
+ return isAllowedAccessor;
1481
+ }
1463
1482
  // Wrap all ElementInternal objects in a proxy to prevent form association when `formAssociated` is not set on an LWC.
1464
1483
  // This is needed because the 1UpgradeableConstructor1 always sets `formAssociated=true`, which means all
1465
1484
  // ElementInternal objects will have form-associated properties set when an LWC is placed in a form.
@@ -1468,19 +1487,28 @@ function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1468
1487
  function createElementInternalsProxy(elementInternals, isFormAssociated) {
1469
1488
  const elementInternalsProxy = new Proxy(elementInternals, {
1470
1489
  set(target, propertyKey, newValue) {
1471
- // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1472
- assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1473
- return Reflect.set(target, propertyKey, newValue);
1490
+ if (isAllowedElementInternalAccessor(propertyKey)) {
1491
+ // Verify that formAssociated is set for form associated properties
1492
+ verifyPropForFormAssociation(propertyKey, isFormAssociated);
1493
+ return Reflect.set(target, propertyKey, newValue);
1494
+ }
1495
+ // As of this writing ElementInternals do not have non-string properties that can be set.
1496
+ return false;
1474
1497
  },
1475
1498
  get(target, propertyKey) {
1476
- // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1477
- assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1478
- const internalsPropertyValue = Reflect.get(target, propertyKey);
1479
- // Bind the property value to the target so that function invocations are called with the
1480
- // correct context ('this' value).
1481
- return typeof internalsPropertyValue === 'function'
1482
- ? internalsPropertyValue.bind(target)
1483
- : internalsPropertyValue;
1499
+ if (
1500
+ // Pass through Object.prototype methods such as toString()
1501
+ hasOwnProperty$1.call(Object.prototype, propertyKey) ||
1502
+ // As of this writing, ElementInternals only uses Symbol.toStringTag which is called
1503
+ // on Object.hasOwnProperty invocations
1504
+ Symbol.for('Symbol.toStringTag') === propertyKey ||
1505
+ // ElementInternals allow listed properties
1506
+ isAllowedElementInternalAccessor(propertyKey)) {
1507
+ // Verify that formAssociated is set for form associated properties
1508
+ verifyPropForFormAssociation(propertyKey, isFormAssociated);
1509
+ const propertyValue = Reflect.get(target, propertyKey);
1510
+ return isFunction$1(propertyValue) ? propertyValue.bind(target) : propertyValue;
1511
+ }
1484
1512
  },
1485
1513
  });
1486
1514
  return elementInternalsProxy;
@@ -3764,8 +3792,9 @@ function traverseAndSetElements(root, parts, renderer) {
3764
3792
  * @param root - the root element
3765
3793
  * @param vnode - the parent VStatic
3766
3794
  * @param renderer - the renderer to use
3795
+ * @param mount - true this is a first (mount) render as opposed to a subsequent (patch) render
3767
3796
  */
3768
- function applyStaticParts(root, vnode, renderer) {
3797
+ function applyStaticParts(root, vnode, renderer, mount) {
3769
3798
  // On the server, we don't support ref (because it relies on renderedCallback), nor do we
3770
3799
  // support event listeners (no interactivity), so traversing parts makes no sense
3771
3800
  if (!process.env.IS_BROWSER) {
@@ -3775,11 +3804,17 @@ function applyStaticParts(root, vnode, renderer) {
3775
3804
  if (isUndefined$1(parts)) {
3776
3805
  return;
3777
3806
  }
3778
- traverseAndSetElements(root, parts, renderer); // this adds `part.elm` to each `part`
3807
+ // This adds `part.elm` to each `part`. We have to do this on every mount/patch because the `parts`
3808
+ // array is recreated from scratch every time, so each `part.elm` is now undefined.
3809
+ // TODO [#3800]: avoid calling traverseAndSetElements on every re-render
3810
+ traverseAndSetElements(root, parts, renderer);
3811
+ // Currently only event listeners and refs are supported for static vnodes
3779
3812
  for (const part of parts) {
3780
- // Event listeners are only applied once when mounting, so they are allowed for static vnodes
3781
- applyEventListeners(part, renderer);
3782
- // Refs are allowed as well
3813
+ if (mount) {
3814
+ // Event listeners only need to be applied once when mounting
3815
+ applyEventListeners(part, renderer);
3816
+ }
3817
+ // Refs must be updated after every render due to refVNodes getting reset before every render
3783
3818
  applyRefs(part, owner);
3784
3819
  }
3785
3820
  }
@@ -3826,7 +3861,7 @@ function patch(n1, n2, parent, renderer) {
3826
3861
  patchComment(n1, n2, renderer);
3827
3862
  break;
3828
3863
  case 4 /* VNodeType.Static */:
3829
- n2.elm = n1.elm;
3864
+ patchStatic(n1, n2, renderer);
3830
3865
  break;
3831
3866
  case 5 /* VNodeType.Fragment */:
3832
3867
  patchFragment(n1, n2, parent, renderer);
@@ -3924,6 +3959,11 @@ function mountElement(vnode, parent, anchor, renderer) {
3924
3959
  insertNode(elm, parent, anchor, renderer);
3925
3960
  mountVNodes(vnode.children, elm, renderer, null);
3926
3961
  }
3962
+ function patchStatic(n1, n2, renderer) {
3963
+ const elm = (n2.elm = n1.elm);
3964
+ // The `refs` object is blown away in every re-render, so we always need to re-apply them
3965
+ applyStaticParts(elm, n2, renderer, false);
3966
+ }
3927
3967
  function patchElement(n1, n2, renderer) {
3928
3968
  const elm = (n2.elm = n1.elm);
3929
3969
  patchElementPropsAndAttrsAndRefs$1(n1, n2, renderer);
@@ -3943,7 +3983,7 @@ function mountStatic(vnode, parent, anchor, renderer) {
3943
3983
  }
3944
3984
  }
3945
3985
  insertNode(elm, parent, anchor, renderer);
3946
- applyStaticParts(elm, vnode, renderer);
3986
+ applyStaticParts(elm, vnode, renderer, true);
3947
3987
  }
3948
3988
  function mountCustomElement(vnode, parent, anchor, renderer) {
3949
3989
  const { sel, owner } = vnode;
@@ -5369,8 +5409,6 @@ function evaluateTemplate(vm, html) {
5369
5409
  // add the VM to the list of host VMs that can be re-rendered if html is swapped
5370
5410
  setActiveVM(vm);
5371
5411
  }
5372
- // reset the refs; they will be set during the tmpl() instantiation
5373
- vm.refVNodes = html.hasRefs ? create(null) : null;
5374
5412
  // right before producing the vnodes, we clear up all internal references
5375
5413
  // to custom elements from the template.
5376
5414
  vm.velements = [];
@@ -5871,6 +5909,8 @@ function rehydrate(vm) {
5871
5909
  }
5872
5910
  function patchShadowRoot(vm, newCh) {
5873
5911
  const { renderRoot, children: oldCh, renderer } = vm;
5912
+ // reset the refs; they will be set during `patchChildren`
5913
+ resetRefVNodes(vm);
5874
5914
  // caching the new children collection
5875
5915
  vm.children = newCh;
5876
5916
  if (newCh.length > 0 || oldCh.length > 0) {
@@ -6168,6 +6208,10 @@ function runFormStateRestoreCallback(elm) {
6168
6208
  runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
6169
6209
  }
6170
6210
  }
6211
+ function resetRefVNodes(vm) {
6212
+ const { cmpTemplate } = vm;
6213
+ vm.refVNodes = !isNull(cmpTemplate) && cmpTemplate.hasRefs ? create(null) : null;
6214
+ }
6171
6215
 
6172
6216
  /*
6173
6217
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6454,6 +6498,8 @@ function hydrateRoot(vm) {
6454
6498
  function hydrateVM(vm) {
6455
6499
  const children = renderComponent(vm);
6456
6500
  vm.children = children;
6501
+ // reset the refs; they will be set during `hydrateChildren`
6502
+ resetRefVNodes(vm);
6457
6503
  const { renderRoot: parentNode, renderer: { getFirstChild }, } = vm;
6458
6504
  hydrateChildren(getFirstChild(parentNode), children, parentNode, vm);
6459
6505
  runRenderedCallback(vm);
@@ -6562,7 +6608,7 @@ function hydrateStaticElement(elm, vnode, renderer) {
6562
6608
  return handleMismatch(elm, vnode, renderer);
6563
6609
  }
6564
6610
  vnode.elm = elm;
6565
- applyStaticParts(elm, vnode, renderer);
6611
+ applyStaticParts(elm, vnode, renderer, true);
6566
6612
  return elm;
6567
6613
  }
6568
6614
  function hydrateFragment(elm, vnode, renderer) {
@@ -7177,5 +7223,5 @@ function readonly(obj) {
7177
7223
  }
7178
7224
 
7179
7225
  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, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
7180
- /** version: 3.7.1 */
7226
+ /** version: 3.7.2 */
7181
7227
  //# sourceMappingURL=index.js.map