@lwc/engine-core 6.3.0 → 6.3.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.
@@ -3,7 +3,7 @@ export { RenderMode, ShadowMode, connectRootElement, createVM, disconnectRootEle
3
3
  export { createContextProviderWithRegister } from './wiring';
4
4
  export { parseFragment, parseSVGFragment } from './template';
5
5
  export { hydrateRoot } from './hydration';
6
- export { registerComponent, getComponentAPIVersion } from './component';
6
+ export { registerComponent } from './component';
7
7
  export { registerTemplate } from './secure-template';
8
8
  export { registerDecorators } from './decorators/register';
9
9
  export { unwrap } from './membrane';
@@ -14,6 +14,8 @@ export { reportingControl as __unstable__ReportingControl } from './reporting';
14
14
  export { swapTemplate, swapComponent, swapStyle } from './hot-swaps';
15
15
  export { setHooks } from './overridable-hooks';
16
16
  export { freezeTemplate } from './freeze-template';
17
+ export { getComponentAPIVersion } from './component';
18
+ export { shouldBeFormAssociated } from './utils';
17
19
  export { getComponentConstructor } from './get-component-constructor';
18
20
  export type { RendererAPI, LifecycleCallback } from './renderer';
19
21
  export type { ConfigValue as WireConfigValue, ContextValue as WireContextValue, DataCallback, WireAdapter, WireAdapterConstructor, WireAdapterSchemaValue, WireContextSubscriptionPayload, WireContextSubscriptionCallback, } from './wiring';
@@ -42,8 +42,8 @@ export interface RendererAPI {
42
42
  isConnected: (node: N) => boolean;
43
43
  insertStylesheet: (content: string, target?: ShadowRoot) => void;
44
44
  assertInstanceOfHTMLElement: (elm: any, msg: string) => void;
45
- createCustomElement: (tagName: string, upgradeCallback: LifecycleCallback, useNativeLifecycle: boolean) => E;
46
- defineCustomElement: (tagName: string) => void;
45
+ createCustomElement: (tagName: string, upgradeCallback: LifecycleCallback, useNativeLifecycle: boolean, isFormAssociated: boolean) => E;
46
+ defineCustomElement: (tagName: string, isFormAssociated: boolean) => void;
47
47
  ownerDocument(elm: E): Document;
48
48
  registerContextConsumer: (element: E, adapterContextToken: string, subscriptionPayload: WireContextSubscriptionPayload) => void;
49
49
  attachInternals: (elm: E) => ElementInternals;
@@ -37,4 +37,5 @@ export declare function applyTemporaryCompilerV5SlotFix(data: VElementData): VEl
37
37
  svg?: boolean | undefined;
38
38
  renderer?: import("./renderer").RendererAPI | undefined;
39
39
  };
40
+ export declare function shouldBeFormAssociated(Ctor: LightningElementConstructor): boolean;
40
41
  export {};
package/dist/index.cjs.js CHANGED
@@ -526,6 +526,18 @@ function applyTemporaryCompilerV5SlotFix(data) {
526
526
  }
527
527
  return data;
528
528
  }
529
+ function shouldBeFormAssociated(Ctor) {
530
+ const ctorFormAssociated = Boolean(Ctor.formAssociated);
531
+ const apiVersion = getComponentAPIVersion(Ctor);
532
+ const apiFeatureEnabled = shared.isAPIFeatureEnabled(8 /* APIFeature.ENABLE_ELEMENT_INTERNALS_AND_FACE */, apiVersion);
533
+ if (process.env.NODE_ENV !== 'production' && ctorFormAssociated && !apiFeatureEnabled) {
534
+ const tagName = getComponentRegisteredName(Ctor);
535
+ logWarnOnce(`Component <${tagName}> set static formAssociated to true, but form ` +
536
+ `association is not enabled because the API version is ${apiVersion}. To enable form association, ` +
537
+ `update the LWC component API version to 61 or above. https://lwc.dev/guide/versioning`);
538
+ }
539
+ return ctorFormAssociated && apiFeatureEnabled;
540
+ }
529
541
 
530
542
  /*
531
543
  * Copyright (c) 2020, salesforce.com, inc.
@@ -1667,79 +1679,6 @@ function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
1667
1679
  logError(`this.${methodOrPropName} should not be called during the construction of the custom element for ${getComponentTag(vm)} because the element is not yet in the DOM or has no children yet.`);
1668
1680
  }
1669
1681
  }
1670
- // List of properties on ElementInternals that are formAssociated can be found in the spec:
1671
- // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-elements
1672
- const formAssociatedProps = new Set([
1673
- 'setFormValue',
1674
- 'form',
1675
- 'setValidity',
1676
- 'willValidate',
1677
- 'validity',
1678
- 'validationMessage',
1679
- 'checkValidity',
1680
- 'reportValidity',
1681
- 'labels',
1682
- ]);
1683
- // Verify that access to a form-associated property of the ElementInternals proxy has formAssociated set in the LWC.
1684
- function verifyPropForFormAssociation(propertyKey, isFormAssociated) {
1685
- if (shared.isString(propertyKey) && formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1686
- //Note this error message mirrors Chrome and Firefox error messages, in Safari the error is slightly different.
1687
- throw new DOMException(`Failed to execute '${propertyKey}' on 'ElementInternals': The target element is not a form-associated custom element.`);
1688
- }
1689
- }
1690
- const elementInternalsAccessorAllowList = new Set(['shadowRoot', 'role', ...formAssociatedProps]);
1691
- // Prevent access to properties not defined in the HTML spec in case browsers decide to
1692
- // provide new APIs that provide access to form associated properties.
1693
- // This can be removed along with UpgradeableConstructor.
1694
- function isAllowedElementInternalAccessor(propertyKey) {
1695
- let isAllowedAccessor = false;
1696
- // As of this writing all ElementInternal property keys as described in the spec are implemented with strings
1697
- // in Chrome, Firefox, and Safari
1698
- if (shared.isString(propertyKey)) {
1699
- // Allow list is based on HTML spec:
1700
- // https://html.spec.whatwg.org/multipage/custom-elements.html#the-elementinternals-interface
1701
- isAllowedAccessor =
1702
- elementInternalsAccessorAllowList.has(propertyKey) || /^aria/.test(propertyKey);
1703
- if (!isAllowedAccessor && process.env.NODE_ENV !== 'production') {
1704
- logWarn('Only properties defined in the ElementInternals HTML spec are available.');
1705
- }
1706
- }
1707
- return isAllowedAccessor;
1708
- }
1709
- // Wrap all ElementInternal objects in a proxy to prevent form association when `formAssociated` is not set on an LWC.
1710
- // This is needed because the 1UpgradeableConstructor1 always sets `formAssociated=true`, which means all
1711
- // ElementInternal objects will have form-associated properties set when an LWC is placed in a form.
1712
- // We are doing this to guard against customers taking a dependency on form elements being associated to ElementInternals
1713
- // when 'formAssociated' has not been set on the LWC.
1714
- function createElementInternalsProxy(elementInternals, isFormAssociated) {
1715
- const elementInternalsProxy = new Proxy(elementInternals, {
1716
- set(target, propertyKey, newValue) {
1717
- if (isAllowedElementInternalAccessor(propertyKey)) {
1718
- // Verify that formAssociated is set for form associated properties
1719
- verifyPropForFormAssociation(propertyKey, isFormAssociated);
1720
- return Reflect.set(target, propertyKey, newValue);
1721
- }
1722
- // As of this writing ElementInternals do not have non-string properties that can be set.
1723
- return false;
1724
- },
1725
- get(target, propertyKey) {
1726
- if (
1727
- // Pass through Object.prototype methods such as toString()
1728
- shared.hasOwnProperty.call(Object.prototype, propertyKey) ||
1729
- // As of this writing, ElementInternals only uses Symbol.toStringTag which is called
1730
- // on Object.hasOwnProperty invocations
1731
- Symbol.for('Symbol.toStringTag') === propertyKey ||
1732
- // ElementInternals allow listed properties
1733
- isAllowedElementInternalAccessor(propertyKey)) {
1734
- // Verify that formAssociated is set for form associated properties
1735
- verifyPropForFormAssociation(propertyKey, isFormAssociated);
1736
- const propertyValue = Reflect.get(target, propertyKey);
1737
- return shared.isFunction(propertyValue) ? propertyValue.bind(target) : propertyValue;
1738
- }
1739
- },
1740
- });
1741
- return elementInternalsProxy;
1742
- }
1743
1682
  // Type assertion because we need to build the prototype before it satisfies the interface.
1744
1683
  LightningElement.prototype = {
1745
1684
  constructor: LightningElement,
@@ -1833,13 +1772,16 @@ LightningElement.prototype = {
1833
1772
  },
1834
1773
  attachInternals() {
1835
1774
  const vm = getAssociatedVM(this);
1836
- const { elm, def: { formAssociated }, renderer: { attachInternals }, } = vm;
1775
+ const { elm, apiVersion, renderer: { attachInternals }, } = vm;
1776
+ if (!shared.isAPIFeatureEnabled(8 /* APIFeature.ENABLE_ELEMENT_INTERNALS_AND_FACE */, apiVersion)) {
1777
+ throw new Error(`The attachInternals API is only supported in API version 61 and above. ` +
1778
+ `The current version is ${apiVersion}. ` +
1779
+ `To use this API, update the LWC component API version. https://lwc.dev/guide/versioning`);
1780
+ }
1837
1781
  if (vm.shadowMode === 1 /* ShadowMode.Synthetic */) {
1838
- throw new Error('attachInternals API is not supported in light DOM or synthetic shadow.');
1782
+ throw new Error('attachInternals API is not supported in synthetic shadow.');
1839
1783
  }
1840
- const internals = attachInternals(elm);
1841
- // #TODO[2970]: remove proxy once `UpgradeableConstructor` has been removed
1842
- return createElementInternalsProxy(internals, Boolean(formAssociated));
1784
+ return attachInternals(elm);
1843
1785
  },
1844
1786
  get isConnected() {
1845
1787
  const vm = getAssociatedVM(this);
@@ -2077,11 +2019,10 @@ function createObservedFieldPropertyDescriptor(key) {
2077
2019
  */
2078
2020
  const AdapterToTokenMap = new Map();
2079
2021
  function createContextProviderWithRegister(adapter, registerContextProvider) {
2080
- let adapterContextToken = AdapterToTokenMap.get(adapter);
2081
- if (!shared.isUndefined(adapterContextToken)) {
2022
+ if (AdapterToTokenMap.has(adapter)) {
2082
2023
  throw new Error(`Adapter already has a context provider.`);
2083
2024
  }
2084
- adapterContextToken = guid();
2025
+ const adapterContextToken = guid();
2085
2026
  AdapterToTokenMap.set(adapter, adapterContextToken);
2086
2027
  const providers = new WeakSet();
2087
2028
  return (elmOrComponent, options) => {
@@ -4313,7 +4254,8 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
4313
4254
  // compatibility, we lower case the tagname here.
4314
4255
  const normalizedTagname = sel.toLowerCase();
4315
4256
  const useNativeLifecycle = shouldUseNativeCustomElementLifecycle(ctor);
4316
- const elm = createCustomElement(normalizedTagname, upgradeCallback, useNativeLifecycle);
4257
+ const isFormAssociated = shouldBeFormAssociated(ctor);
4258
+ const elm = createCustomElement(normalizedTagname, upgradeCallback, useNativeLifecycle, isFormAssociated);
4317
4259
  vnode.elm = elm;
4318
4260
  vnode.vm = vm;
4319
4261
  linkNodeToShadow(elm, owner, renderer);
@@ -6549,14 +6491,7 @@ function forceRehydration(vm) {
6549
6491
  }
6550
6492
  }
6551
6493
  function runFormAssociatedCustomElementCallback(vm, faceCb) {
6552
- const { renderMode, shadowMode, def: { formAssociated }, } = vm;
6553
- // Technically the UpgradableConstructor always sets `static formAssociated = true` but silently fail here to match browser behavior.
6554
- if (shared.isUndefined(formAssociated) || shared.isFalse(formAssociated)) {
6555
- if (process.env.NODE_ENV !== 'production') {
6556
- logWarn(`Form associated lifecycle methods must have the 'static formAssociated' value set in the component's prototype chain.`);
6557
- }
6558
- return;
6559
- }
6494
+ const { renderMode, shadowMode } = vm;
6560
6495
  if (shadowMode === 1 /* ShadowMode.Synthetic */ && renderMode !== 0 /* RenderMode.Light */) {
6561
6496
  throw new Error('Form associated lifecycle methods are not available in synthetic shadow. Please use native shadow or light DOM.');
6562
6497
  }
@@ -7049,7 +6984,8 @@ function hydrateCustomElement(elm, vnode, renderer) {
7049
6984
  }
7050
6985
  const { sel, mode, ctor, owner } = vnode;
7051
6986
  const { defineCustomElement, getTagName } = renderer;
7052
- defineCustomElement(shared.StringToLowerCase.call(getTagName(elm)));
6987
+ const isFormAssociated = shouldBeFormAssociated(ctor);
6988
+ defineCustomElement(shared.StringToLowerCase.call(getTagName(elm)), isFormAssociated);
7053
6989
  const vm = createVM(elm, ctor, renderer, {
7054
6990
  mode,
7055
6991
  owner,
@@ -7663,11 +7599,12 @@ exports.runFormResetCallback = runFormResetCallback;
7663
7599
  exports.runFormStateRestoreCallback = runFormStateRestoreCallback;
7664
7600
  exports.sanitizeAttribute = sanitizeAttribute;
7665
7601
  exports.setHooks = setHooks;
7602
+ exports.shouldBeFormAssociated = shouldBeFormAssociated;
7666
7603
  exports.swapComponent = swapComponent;
7667
7604
  exports.swapStyle = swapStyle;
7668
7605
  exports.swapTemplate = swapTemplate;
7669
7606
  exports.track = track;
7670
7607
  exports.unwrap = unwrap;
7671
7608
  exports.wire = wire;
7672
- /** version: 6.3.0 */
7609
+ /** version: 6.3.2 */
7673
7610
  //# sourceMappingURL=index.cjs.js.map