@lwc/engine-core 3.7.1 → 3.7.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.
@@ -6,5 +6,6 @@ import { RendererAPI } from '../renderer';
6
6
  * @param root - the root element
7
7
  * @param vnode - the parent VStatic
8
8
  * @param renderer - the renderer to use
9
+ * @param mount - true this is a first (mount) render as opposed to a subsequent (patch) render
9
10
  */
10
- export declare function applyStaticParts(root: Element, vnode: VStatic, renderer: RendererAPI): void;
11
+ export declare function applyStaticParts(root: Element, vnode: VStatic, renderer: RendererAPI, mount: boolean): void;
@@ -43,6 +43,7 @@ export interface RendererAPI {
43
43
  insertStylesheet: (content: string, target?: ShadowRoot) => void;
44
44
  assertInstanceOfHTMLElement: (elm: any, msg: string) => void;
45
45
  createCustomElement: (tagName: string, upgradeCallback: LifecycleCallback, connectedCallback?: LifecycleCallback, disconnectedCallback?: LifecycleCallback, formAssociatedCallback?: LifecycleCallback, formDisabledCallback?: LifecycleCallback, formResetCallback?: LifecycleCallback, formStateRestoreCallback?: LifecycleCallback) => E;
46
+ defineCustomElement: (tagName: string, connectedCallback?: LifecycleCallback, disconnectedCallback?: LifecycleCallback) => void;
46
47
  ownerDocument(elm: E): Document;
47
48
  registerContextConsumer: (element: E, adapterContextToken: string, subscriptionPayload: WireContextSubscriptionPayload) => void;
48
49
  attachInternals: (elm: E) => ElementInternals;
@@ -172,4 +172,5 @@ export declare function runFormAssociatedCallback(elm: HTMLElement): void;
172
172
  export declare function runFormDisabledCallback(elm: HTMLElement): void;
173
173
  export declare function runFormResetCallback(elm: HTMLElement): void;
174
174
  export declare function runFormStateRestoreCallback(elm: HTMLElement): void;
175
+ export declare function resetRefVNodes(vm: VM): void;
175
176
  export {};
package/dist/index.cjs.js CHANGED
@@ -1458,12 +1458,31 @@ const formAssociatedProps = new Set([
1458
1458
  'labels',
1459
1459
  ]);
1460
1460
  // Verify that access to a form-associated property of the ElementInternals proxy has formAssociated set in the LWC.
1461
- function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1462
- if (formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1461
+ function verifyPropForFormAssociation(propertyKey, isFormAssociated) {
1462
+ if (shared.isString(propertyKey) && formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1463
1463
  //Note this error message mirrors Chrome and Firefox error messages, in Safari the error is slightly different.
1464
1464
  throw new DOMException(`Failed to execute '${propertyKey}' on 'ElementInternals': The target element is not a form-associated custom element.`);
1465
1465
  }
1466
1466
  }
1467
+ const elementInternalsAccessorAllowList = new Set(['shadowRoot', 'role', ...formAssociatedProps]);
1468
+ // Prevent access to properties not defined in the HTML spec in case browsers decide to
1469
+ // provide new APIs that provide access to form associated properties.
1470
+ // This can be removed along with UpgradeableConstructor.
1471
+ function isAllowedElementInternalAccessor(propertyKey) {
1472
+ let isAllowedAccessor = false;
1473
+ // As of this writing all ElementInternal property keys as described in the spec are implemented with strings
1474
+ // in Chrome, Firefox, and Safari
1475
+ if (shared.isString(propertyKey)) {
1476
+ // Allow list is based on HTML spec:
1477
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#the-elementinternals-interface
1478
+ isAllowedAccessor =
1479
+ elementInternalsAccessorAllowList.has(propertyKey) || /^aria/.test(propertyKey);
1480
+ if (!isAllowedAccessor && process.env.NODE_ENV !== 'production') {
1481
+ logWarn('Only properties defined in the ElementInternals HTML spec are available.');
1482
+ }
1483
+ }
1484
+ return isAllowedAccessor;
1485
+ }
1467
1486
  // Wrap all ElementInternal objects in a proxy to prevent form association when `formAssociated` is not set on an LWC.
1468
1487
  // This is needed because the 1UpgradeableConstructor1 always sets `formAssociated=true`, which means all
1469
1488
  // ElementInternal objects will have form-associated properties set when an LWC is placed in a form.
@@ -1472,19 +1491,28 @@ function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1472
1491
  function createElementInternalsProxy(elementInternals, isFormAssociated) {
1473
1492
  const elementInternalsProxy = new Proxy(elementInternals, {
1474
1493
  set(target, propertyKey, newValue) {
1475
- // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1476
- assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1477
- return Reflect.set(target, propertyKey, newValue);
1494
+ if (isAllowedElementInternalAccessor(propertyKey)) {
1495
+ // Verify that formAssociated is set for form associated properties
1496
+ verifyPropForFormAssociation(propertyKey, isFormAssociated);
1497
+ return Reflect.set(target, propertyKey, newValue);
1498
+ }
1499
+ // As of this writing ElementInternals do not have non-string properties that can be set.
1500
+ return false;
1478
1501
  },
1479
1502
  get(target, propertyKey) {
1480
- // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1481
- assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1482
- const internalsPropertyValue = Reflect.get(target, propertyKey);
1483
- // Bind the property value to the target so that function invocations are called with the
1484
- // correct context ('this' value).
1485
- return typeof internalsPropertyValue === 'function'
1486
- ? internalsPropertyValue.bind(target)
1487
- : internalsPropertyValue;
1503
+ if (
1504
+ // Pass through Object.prototype methods such as toString()
1505
+ shared.hasOwnProperty.call(Object.prototype, propertyKey) ||
1506
+ // As of this writing, ElementInternals only uses Symbol.toStringTag which is called
1507
+ // on Object.hasOwnProperty invocations
1508
+ Symbol.for('Symbol.toStringTag') === propertyKey ||
1509
+ // ElementInternals allow listed properties
1510
+ isAllowedElementInternalAccessor(propertyKey)) {
1511
+ // Verify that formAssociated is set for form associated properties
1512
+ verifyPropForFormAssociation(propertyKey, isFormAssociated);
1513
+ const propertyValue = Reflect.get(target, propertyKey);
1514
+ return shared.isFunction(propertyValue) ? propertyValue.bind(target) : propertyValue;
1515
+ }
1488
1516
  },
1489
1517
  });
1490
1518
  return elementInternalsProxy;
@@ -3768,8 +3796,9 @@ function traverseAndSetElements(root, parts, renderer) {
3768
3796
  * @param root - the root element
3769
3797
  * @param vnode - the parent VStatic
3770
3798
  * @param renderer - the renderer to use
3799
+ * @param mount - true this is a first (mount) render as opposed to a subsequent (patch) render
3771
3800
  */
3772
- function applyStaticParts(root, vnode, renderer) {
3801
+ function applyStaticParts(root, vnode, renderer, mount) {
3773
3802
  // On the server, we don't support ref (because it relies on renderedCallback), nor do we
3774
3803
  // support event listeners (no interactivity), so traversing parts makes no sense
3775
3804
  if (!process.env.IS_BROWSER) {
@@ -3779,11 +3808,17 @@ function applyStaticParts(root, vnode, renderer) {
3779
3808
  if (shared.isUndefined(parts)) {
3780
3809
  return;
3781
3810
  }
3782
- traverseAndSetElements(root, parts, renderer); // this adds `part.elm` to each `part`
3811
+ // This adds `part.elm` to each `part`. We have to do this on every mount/patch because the `parts`
3812
+ // array is recreated from scratch every time, so each `part.elm` is now undefined.
3813
+ // TODO [#3800]: avoid calling traverseAndSetElements on every re-render
3814
+ traverseAndSetElements(root, parts, renderer);
3815
+ // Currently only event listeners and refs are supported for static vnodes
3783
3816
  for (const part of parts) {
3784
- // Event listeners are only applied once when mounting, so they are allowed for static vnodes
3785
- applyEventListeners(part, renderer);
3786
- // Refs are allowed as well
3817
+ if (mount) {
3818
+ // Event listeners only need to be applied once when mounting
3819
+ applyEventListeners(part, renderer);
3820
+ }
3821
+ // Refs must be updated after every render due to refVNodes getting reset before every render
3787
3822
  applyRefs(part, owner);
3788
3823
  }
3789
3824
  }
@@ -3830,7 +3865,7 @@ function patch(n1, n2, parent, renderer) {
3830
3865
  patchComment(n1, n2, renderer);
3831
3866
  break;
3832
3867
  case 4 /* VNodeType.Static */:
3833
- n2.elm = n1.elm;
3868
+ patchStatic(n1, n2, renderer);
3834
3869
  break;
3835
3870
  case 5 /* VNodeType.Fragment */:
3836
3871
  patchFragment(n1, n2, parent, renderer);
@@ -3928,6 +3963,11 @@ function mountElement(vnode, parent, anchor, renderer) {
3928
3963
  insertNode(elm, parent, anchor, renderer);
3929
3964
  mountVNodes(vnode.children, elm, renderer, null);
3930
3965
  }
3966
+ function patchStatic(n1, n2, renderer) {
3967
+ const elm = (n2.elm = n1.elm);
3968
+ // The `refs` object is blown away in every re-render, so we always need to re-apply them
3969
+ applyStaticParts(elm, n2, renderer, false);
3970
+ }
3931
3971
  function patchElement(n1, n2, renderer) {
3932
3972
  const elm = (n2.elm = n1.elm);
3933
3973
  patchElementPropsAndAttrsAndRefs$1(n1, n2, renderer);
@@ -3947,7 +3987,7 @@ function mountStatic(vnode, parent, anchor, renderer) {
3947
3987
  }
3948
3988
  }
3949
3989
  insertNode(elm, parent, anchor, renderer);
3950
- applyStaticParts(elm, vnode, renderer);
3990
+ applyStaticParts(elm, vnode, renderer, true);
3951
3991
  }
3952
3992
  function mountCustomElement(vnode, parent, anchor, renderer) {
3953
3993
  const { sel, owner } = vnode;
@@ -5373,8 +5413,6 @@ function evaluateTemplate(vm, html) {
5373
5413
  // add the VM to the list of host VMs that can be re-rendered if html is swapped
5374
5414
  setActiveVM(vm);
5375
5415
  }
5376
- // reset the refs; they will be set during the tmpl() instantiation
5377
- vm.refVNodes = html.hasRefs ? shared.create(null) : null;
5378
5416
  // right before producing the vnodes, we clear up all internal references
5379
5417
  // to custom elements from the template.
5380
5418
  vm.velements = [];
@@ -5875,6 +5913,8 @@ function rehydrate(vm) {
5875
5913
  }
5876
5914
  function patchShadowRoot(vm, newCh) {
5877
5915
  const { renderRoot, children: oldCh, renderer } = vm;
5916
+ // reset the refs; they will be set during `patchChildren`
5917
+ resetRefVNodes(vm);
5878
5918
  // caching the new children collection
5879
5919
  vm.children = newCh;
5880
5920
  if (newCh.length > 0 || oldCh.length > 0) {
@@ -6172,6 +6212,10 @@ function runFormStateRestoreCallback(elm) {
6172
6212
  runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
6173
6213
  }
6174
6214
  }
6215
+ function resetRefVNodes(vm) {
6216
+ const { cmpTemplate } = vm;
6217
+ vm.refVNodes = !shared.isNull(cmpTemplate) && cmpTemplate.hasRefs ? shared.create(null) : null;
6218
+ }
6175
6219
 
6176
6220
  /*
6177
6221
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6458,6 +6502,8 @@ function hydrateRoot(vm) {
6458
6502
  function hydrateVM(vm) {
6459
6503
  const children = renderComponent(vm);
6460
6504
  vm.children = children;
6505
+ // reset the refs; they will be set during `hydrateChildren`
6506
+ resetRefVNodes(vm);
6461
6507
  const { renderRoot: parentNode, renderer: { getFirstChild }, } = vm;
6462
6508
  hydrateChildren(getFirstChild(parentNode), children, parentNode, vm);
6463
6509
  runRenderedCallback(vm);
@@ -6566,7 +6612,7 @@ function hydrateStaticElement(elm, vnode, renderer) {
6566
6612
  return handleMismatch(elm, vnode, renderer);
6567
6613
  }
6568
6614
  vnode.elm = elm;
6569
- applyStaticParts(elm, vnode, renderer);
6615
+ applyStaticParts(elm, vnode, renderer, true);
6570
6616
  return elm;
6571
6617
  }
6572
6618
  function hydrateFragment(elm, vnode, renderer) {
@@ -6624,6 +6670,8 @@ function hydrateCustomElement(elm, vnode, renderer) {
6624
6670
  return handleMismatch(elm, vnode, renderer);
6625
6671
  }
6626
6672
  const { sel, mode, ctor, owner } = vnode;
6673
+ const { defineCustomElement, getTagName } = renderer;
6674
+ defineCustomElement(shared.StringToLowerCase.call(getTagName(elm)));
6627
6675
  const vm = createVM(elm, ctor, renderer, {
6628
6676
  mode,
6629
6677
  owner,
@@ -7223,5 +7271,5 @@ exports.swapTemplate = swapTemplate;
7223
7271
  exports.track = track;
7224
7272
  exports.unwrap = unwrap;
7225
7273
  exports.wire = wire;
7226
- /** version: 3.7.1 */
7274
+ /** version: 3.7.3 */
7227
7275
  //# sourceMappingURL=index.cjs.js.map