@lwc/engine-core 3.3.3 → 3.5.0

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, isFalse, freeze, KEY__SYNTHETIC_MODE, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, getOwnPropertyNames as getOwnPropertyNames$1, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, kebabCaseToCamelCase, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, 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, 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, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, 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
  import { applyAriaReflection } from '@lwc/aria-reflection';
6
6
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
7
7
 
@@ -519,8 +519,8 @@ function lockDomMutation() {
519
519
  assertNotProd(); // this method should never leak to prod
520
520
  isDomMutationAllowed = false;
521
521
  }
522
- function logMissingPortalError(name, type) {
523
- return logError(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
522
+ function logMissingPortalWarn(name, type) {
523
+ return logWarn(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
524
524
  }
525
525
  function patchElementWithRestrictions(elm, options) {
526
526
  assertNotProd(); // this method should never leak to prod
@@ -545,14 +545,14 @@ function patchElementWithRestrictions(elm, options) {
545
545
  assign(descriptors, {
546
546
  appendChild: generateDataDescriptor({
547
547
  value(aChild) {
548
- logMissingPortalError('appendChild', 'method');
548
+ logMissingPortalWarn('appendChild', 'method');
549
549
  return appendChild.call(this, aChild);
550
550
  },
551
551
  }),
552
552
  insertBefore: generateDataDescriptor({
553
553
  value(newNode, referenceNode) {
554
554
  if (!isDomMutationAllowed) {
555
- logMissingPortalError('insertBefore', 'method');
555
+ logMissingPortalWarn('insertBefore', 'method');
556
556
  }
557
557
  return insertBefore.call(this, newNode, referenceNode);
558
558
  },
@@ -560,14 +560,14 @@ function patchElementWithRestrictions(elm, options) {
560
560
  removeChild: generateDataDescriptor({
561
561
  value(aChild) {
562
562
  if (!isDomMutationAllowed) {
563
- logMissingPortalError('removeChild', 'method');
563
+ logMissingPortalWarn('removeChild', 'method');
564
564
  }
565
565
  return removeChild.call(this, aChild);
566
566
  },
567
567
  }),
568
568
  replaceChild: generateDataDescriptor({
569
569
  value(newChild, oldChild) {
570
- logMissingPortalError('replaceChild', 'method');
570
+ logMissingPortalWarn('replaceChild', 'method');
571
571
  return replaceChild.call(this, newChild, oldChild);
572
572
  },
573
573
  }),
@@ -577,7 +577,7 @@ function patchElementWithRestrictions(elm, options) {
577
577
  },
578
578
  set(value) {
579
579
  if (!isDomMutationAllowed) {
580
- logMissingPortalError('nodeValue', 'property');
580
+ logMissingPortalWarn('nodeValue', 'property');
581
581
  }
582
582
  originalNodeValueDescriptor.set.call(this, value);
583
583
  },
@@ -587,7 +587,7 @@ function patchElementWithRestrictions(elm, options) {
587
587
  return originalTextContentDescriptor.get.call(this);
588
588
  },
589
589
  set(value) {
590
- logMissingPortalError('textContent', 'property');
590
+ logMissingPortalWarn('textContent', 'property');
591
591
  originalTextContentDescriptor.set.call(this, value);
592
592
  },
593
593
  }),
@@ -596,7 +596,7 @@ function patchElementWithRestrictions(elm, options) {
596
596
  return originalInnerHTMLDescriptor.get.call(this);
597
597
  },
598
598
  set(value) {
599
- logMissingPortalError('innerHTML', 'property');
599
+ logMissingPortalWarn('innerHTML', 'property');
600
600
  return originalInnerHTMLDescriptor.set.call(this, value);
601
601
  },
602
602
  }),
@@ -1454,7 +1454,51 @@ function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
1454
1454
  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.`);
1455
1455
  }
1456
1456
  }
1457
- const supportsElementInternals = typeof ElementInternals !== 'undefined';
1457
+ // List of properties on ElementInternals that are formAssociated can be found in the spec:
1458
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-elements
1459
+ const formAssociatedProps = new Set([
1460
+ 'setFormValue',
1461
+ 'form',
1462
+ 'setValidity',
1463
+ 'willValidate',
1464
+ 'validity',
1465
+ 'validationMessage',
1466
+ 'checkValidity',
1467
+ 'reportValidity',
1468
+ 'labels',
1469
+ ]);
1470
+ // Verify that access to a form-associated property of the ElementInternals proxy has formAssociated set in the LWC.
1471
+ function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1472
+ if (formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1473
+ //Note this error message mirrors Chrome and Firefox error messages, in Safari the error is slightly different.
1474
+ throw new DOMException(`Failed to execute '${propertyKey}' on 'ElementInternals': The target element is not a form-associated custom element.`);
1475
+ }
1476
+ }
1477
+ // Wrap all ElementInternal objects in a proxy to prevent form association when `formAssociated` is not set on an LWC.
1478
+ // This is needed because the 1UpgradeableConstructor1 always sets `formAssociated=true`, which means all
1479
+ // ElementInternal objects will have form-associated properties set when an LWC is placed in a form.
1480
+ // We are doing this to guard against customers taking a dependency on form elements being associated to ElementInternals
1481
+ // when 'formAssociated' has not been set on the LWC.
1482
+ function createElementInternalsProxy(elementInternals, isFormAssociated) {
1483
+ const elementInternalsProxy = new Proxy(elementInternals, {
1484
+ set(target, propertyKey, newValue) {
1485
+ // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1486
+ assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1487
+ return Reflect.set(target, propertyKey, newValue);
1488
+ },
1489
+ get(target, propertyKey) {
1490
+ // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1491
+ assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1492
+ const internalsPropertyValue = Reflect.get(target, propertyKey);
1493
+ // Bind the property value to the target so that function invocations are called with the
1494
+ // correct context ('this' value).
1495
+ return typeof internalsPropertyValue === 'function'
1496
+ ? internalsPropertyValue.bind(target)
1497
+ : internalsPropertyValue;
1498
+ },
1499
+ });
1500
+ return elementInternalsProxy;
1501
+ }
1458
1502
  // @ts-ignore
1459
1503
  LightningElement.prototype = {
1460
1504
  constructor: LightningElement,
@@ -1548,15 +1592,13 @@ LightningElement.prototype = {
1548
1592
  },
1549
1593
  attachInternals() {
1550
1594
  const vm = getAssociatedVM(this);
1551
- const { elm, renderer: { attachInternals }, } = vm;
1552
- if (isFalse(supportsElementInternals)) {
1553
- // Browsers that don't support attachInternals will need to be polyfilled before LWC is loaded.
1554
- throw new Error('attachInternals API is not supported in this browser environment.');
1555
- }
1556
- if (vm.renderMode === 0 /* RenderMode.Light */ || vm.shadowMode === 1 /* ShadowMode.Synthetic */) {
1595
+ const { elm, def: { formAssociated }, renderer: { attachInternals }, } = vm;
1596
+ if (vm.shadowMode === 1 /* ShadowMode.Synthetic */) {
1557
1597
  throw new Error('attachInternals API is not supported in light DOM or synthetic shadow.');
1558
1598
  }
1559
- return attachInternals(elm);
1599
+ const internals = attachInternals(elm);
1600
+ // #TODO[2970]: remove proxy once `UpgradeableConstructor` has been removed
1601
+ return createElementInternalsProxy(internals, Boolean(formAssociated));
1560
1602
  },
1561
1603
  get isConnected() {
1562
1604
  const vm = getAssociatedVM(this);
@@ -2563,7 +2605,22 @@ function createAttributeChangedCallback(attributeToPropMap, superAttributeChange
2563
2605
  this[propName] = newValue;
2564
2606
  };
2565
2607
  }
2566
- function HTMLBridgeElementFactory(SuperClass, props, methods) {
2608
+ function createAccessorThatWarns(propName) {
2609
+ let prop;
2610
+ return {
2611
+ get() {
2612
+ logWarn(`The property "${propName}" is not publicly accessible. Add the @api annotation to the property declaration or getter/setter in the component to make it accessible.`);
2613
+ return prop;
2614
+ },
2615
+ set(value) {
2616
+ logWarn(`The property "${propName}" is not publicly accessible. Add the @api annotation to the property declaration or getter/setter in the component to make it accessible.`);
2617
+ prop = value;
2618
+ },
2619
+ enumerable: true,
2620
+ configurable: true,
2621
+ };
2622
+ }
2623
+ function HTMLBridgeElementFactory(SuperClass, publicProperties, methods, observedFields, proto) {
2567
2624
  const HTMLBridgeElement = class extends SuperClass {
2568
2625
  };
2569
2626
  // generating the hash table for attributes to avoid duplicate fields and facilitate validation
@@ -2572,9 +2629,30 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2572
2629
  const { attributeChangedCallback: superAttributeChangedCallback } = SuperClass.prototype;
2573
2630
  const { observedAttributes: superObservedAttributes = [] } = SuperClass;
2574
2631
  const descriptors = create(null);
2632
+ // present a hint message so that developers are aware that they have not decorated property with @api
2633
+ if (process.env.NODE_ENV !== 'production') {
2634
+ if (!isUndefined$1(proto) && !isNull(proto)) {
2635
+ const nonPublicPropertiesToWarnOn = new Set([
2636
+ // getters, setters, and methods
2637
+ ...keys(getOwnPropertyDescriptors(proto)),
2638
+ // class properties
2639
+ ...observedFields,
2640
+ ]
2641
+ // we don't want to override HTMLElement props because these are meaningful in other ways,
2642
+ // and can break tooling that expects it to be iterable or defined, e.g. Jest:
2643
+ // https://github.com/jestjs/jest/blob/b4c9587/packages/pretty-format/src/plugins/DOMElement.ts#L95
2644
+ // It also doesn't make sense to override e.g. "constructor".
2645
+ .filter((propName) => !(propName in HTMLElementPrototype)));
2646
+ for (const propName of nonPublicPropertiesToWarnOn) {
2647
+ if (ArrayIndexOf.call(publicProperties, propName) === -1) {
2648
+ descriptors[propName] = createAccessorThatWarns(propName);
2649
+ }
2650
+ }
2651
+ }
2652
+ }
2575
2653
  // expose getters and setters for each public props on the new Element Bridge
2576
- for (let i = 0, len = props.length; i < len; i += 1) {
2577
- const propName = props[i];
2654
+ for (let i = 0, len = publicProperties.length; i < len; i += 1) {
2655
+ const propName = publicProperties[i];
2578
2656
  attributeToPropMap[htmlPropertyToAttribute(propName)] = propName;
2579
2657
  descriptors[propName] = {
2580
2658
  get: createGetter(propName),
@@ -2601,9 +2679,26 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2601
2679
  };
2602
2680
  // To avoid leaking private component details, accessing internals from outside a component is not allowed.
2603
2681
  descriptors.attachInternals = {
2682
+ set() {
2683
+ if (process.env.NODE_ENV !== 'production') {
2684
+ logWarn('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2685
+ }
2686
+ },
2604
2687
  get() {
2605
2688
  if (process.env.NODE_ENV !== 'production') {
2606
- logError('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2689
+ logWarn('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2690
+ }
2691
+ },
2692
+ };
2693
+ descriptors.formAssociated = {
2694
+ set() {
2695
+ if (process.env.NODE_ENV !== 'production') {
2696
+ logWarn('formAssociated cannot be accessed outside of a component. Set the value within the component class.');
2697
+ }
2698
+ },
2699
+ get() {
2700
+ if (process.env.NODE_ENV !== 'production') {
2701
+ logWarn('formAssociated cannot be accessed outside of a component. Set the value within the component class.');
2607
2702
  }
2608
2703
  },
2609
2704
  };
@@ -2617,7 +2712,7 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2617
2712
  defineProperties(HTMLBridgeElement.prototype, descriptors);
2618
2713
  return HTMLBridgeElement;
2619
2714
  }
2620
- const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, getOwnPropertyNames$1(HTMLElementOriginalDescriptors), []);
2715
+ const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, getOwnPropertyNames$1(HTMLElementOriginalDescriptors), [], [], null);
2621
2716
  if (process.env.IS_BROWSER) {
2622
2717
  // This ARIA reflection only really makes sense in the browser. On the server, there is no `renderedCallback()`,
2623
2718
  // so you cannot do e.g. `this.template.querySelector('x-child').ariaBusy = 'true'`. So we don't need to expose
@@ -2915,7 +3010,7 @@ function getCtorProto(Ctor) {
2915
3010
  return proto;
2916
3011
  }
2917
3012
  function createComponentDef(Ctor) {
2918
- const { shadowSupportMode: ctorShadowSupportMode, renderMode: ctorRenderMode } = Ctor;
3013
+ const { shadowSupportMode: ctorShadowSupportMode, renderMode: ctorRenderMode, formAssociated: ctorFormAssociated, } = Ctor;
2919
3014
  if (process.env.NODE_ENV !== 'production') {
2920
3015
  const ctorName = Ctor.name;
2921
3016
  // Removing the following assert until https://bugs.webkit.org/show_bug.cgi?id=190140 is fixed.
@@ -2939,10 +3034,10 @@ function createComponentDef(Ctor) {
2939
3034
  const decoratorsMeta = getDecoratorsMeta(Ctor);
2940
3035
  const { apiFields, apiFieldsConfig, apiMethods, wiredFields, wiredMethods, observedFields } = decoratorsMeta;
2941
3036
  const proto = Ctor.prototype;
2942
- let { connectedCallback, disconnectedCallback, renderedCallback, errorCallback, render } = proto;
3037
+ let { connectedCallback, disconnectedCallback, renderedCallback, errorCallback, formAssociatedCallback, formResetCallback, formDisabledCallback, formStateRestoreCallback, render, } = proto;
2943
3038
  const superProto = getCtorProto(Ctor);
2944
3039
  const superDef = superProto !== LightningElement ? getComponentInternalDef(superProto) : lightingElementDef;
2945
- const bridge = HTMLBridgeElementFactory(superDef.bridge, keys(apiFields), keys(apiMethods));
3040
+ const bridge = HTMLBridgeElementFactory(superDef.bridge, keys(apiFields), keys(apiMethods), keys(observedFields), proto);
2946
3041
  const props = assign(create(null), superDef.props, apiFields);
2947
3042
  const propsConfig = assign(create(null), superDef.propsConfig, apiFieldsConfig);
2948
3043
  const methods = assign(create(null), superDef.methods, apiMethods);
@@ -2951,6 +3046,10 @@ function createComponentDef(Ctor) {
2951
3046
  disconnectedCallback = disconnectedCallback || superDef.disconnectedCallback;
2952
3047
  renderedCallback = renderedCallback || superDef.renderedCallback;
2953
3048
  errorCallback = errorCallback || superDef.errorCallback;
3049
+ formAssociatedCallback = formAssociatedCallback || superDef.formAssociatedCallback;
3050
+ formResetCallback = formResetCallback || superDef.formResetCallback;
3051
+ formDisabledCallback = formDisabledCallback || superDef.formDisabledCallback;
3052
+ formStateRestoreCallback = formStateRestoreCallback || superDef.formStateRestoreCallback;
2954
3053
  render = render || superDef.render;
2955
3054
  let shadowSupportMode = superDef.shadowSupportMode;
2956
3055
  if (!isUndefined$1(ctorShadowSupportMode)) {
@@ -2960,6 +3059,10 @@ function createComponentDef(Ctor) {
2960
3059
  if (!isUndefined$1(ctorRenderMode)) {
2961
3060
  renderMode = ctorRenderMode === 'light' ? 0 /* RenderMode.Light */ : 1 /* RenderMode.Shadow */;
2962
3061
  }
3062
+ let formAssociated = superDef.formAssociated;
3063
+ if (!isUndefined$1(ctorFormAssociated)) {
3064
+ formAssociated = ctorFormAssociated;
3065
+ }
2963
3066
  const template = getComponentRegisteredTemplate(Ctor) || superDef.template;
2964
3067
  const name = Ctor.name || superDef.name;
2965
3068
  // installing observed fields into the prototype.
@@ -2975,10 +3078,15 @@ function createComponentDef(Ctor) {
2975
3078
  template,
2976
3079
  renderMode,
2977
3080
  shadowSupportMode,
3081
+ formAssociated,
2978
3082
  connectedCallback,
2979
3083
  disconnectedCallback,
2980
- renderedCallback,
2981
3084
  errorCallback,
3085
+ formAssociatedCallback,
3086
+ formDisabledCallback,
3087
+ formResetCallback,
3088
+ formStateRestoreCallback,
3089
+ renderedCallback,
2982
3090
  render,
2983
3091
  };
2984
3092
  // This is a no-op unless Lightning DevTools are enabled.
@@ -3055,6 +3163,7 @@ const lightingElementDef = {
3055
3163
  methods: EmptyObject,
3056
3164
  renderMode: 1 /* RenderMode.Shadow */,
3057
3165
  shadowSupportMode: "reset" /* ShadowSupportMode.Default */,
3166
+ formAssociated: undefined,
3058
3167
  wire: EmptyObject,
3059
3168
  bridge: BaseBridgeElement,
3060
3169
  template: defaultEmptyTemplate,
@@ -3111,9 +3220,11 @@ function createInlineStyleVNode(content) {
3111
3220
  },
3112
3221
  }, [api.t(content)]);
3113
3222
  }
3114
- function updateStylesheetToken(vm, template) {
3223
+ // TODO [#3733]: remove support for legacy scope tokens
3224
+ function updateStylesheetToken(vm, template, legacy) {
3115
3225
  const { elm, context, renderMode, shadowMode, renderer: { getClassList, removeAttribute, setAttribute }, } = vm;
3116
- const { stylesheets: newStylesheets, stylesheetToken: newStylesheetToken } = template;
3226
+ const { stylesheets: newStylesheets } = template;
3227
+ const newStylesheetToken = legacy ? template.legacyStylesheetToken : template.stylesheetToken;
3117
3228
  const { stylesheets: newVmStylesheets } = vm;
3118
3229
  const isSyntheticShadow = renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */;
3119
3230
  const { hasScopedStyles } = context;
@@ -3121,7 +3232,19 @@ function updateStylesheetToken(vm, template) {
3121
3232
  let newHasTokenInClass;
3122
3233
  let newHasTokenInAttribute;
3123
3234
  // Reset the styling token applied to the host element.
3124
- const { stylesheetToken: oldToken, hasTokenInClass: oldHasTokenInClass, hasTokenInAttribute: oldHasTokenInAttribute, } = context;
3235
+ let oldToken;
3236
+ let oldHasTokenInClass;
3237
+ let oldHasTokenInAttribute;
3238
+ if (legacy) {
3239
+ oldToken = context.legacyStylesheetToken;
3240
+ oldHasTokenInClass = context.hasLegacyTokenInClass;
3241
+ oldHasTokenInAttribute = context.hasLegacyTokenInAttribute;
3242
+ }
3243
+ else {
3244
+ oldToken = context.stylesheetToken;
3245
+ oldHasTokenInClass = context.hasTokenInClass;
3246
+ oldHasTokenInAttribute = context.hasTokenInAttribute;
3247
+ }
3125
3248
  if (!isUndefined$1(oldToken)) {
3126
3249
  if (oldHasTokenInClass) {
3127
3250
  getClassList(elm).remove(makeHostToken(oldToken));
@@ -3149,9 +3272,16 @@ function updateStylesheetToken(vm, template) {
3149
3272
  }
3150
3273
  }
3151
3274
  // Update the styling tokens present on the context object.
3152
- context.stylesheetToken = newToken;
3153
- context.hasTokenInClass = newHasTokenInClass;
3154
- context.hasTokenInAttribute = newHasTokenInAttribute;
3275
+ if (legacy) {
3276
+ context.legacyStylesheetToken = newToken;
3277
+ context.hasLegacyTokenInClass = newHasTokenInClass;
3278
+ context.hasLegacyTokenInAttribute = newHasTokenInAttribute;
3279
+ }
3280
+ else {
3281
+ context.stylesheetToken = newToken;
3282
+ context.hasTokenInClass = newHasTokenInClass;
3283
+ context.hasTokenInAttribute = newHasTokenInAttribute;
3284
+ }
3155
3285
  }
3156
3286
  function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3157
3287
  const content = [];
@@ -3239,9 +3369,12 @@ function getNearestShadowComponent(vm) {
3239
3369
  * this returns the unique token for that scoped stylesheet. Otherwise
3240
3370
  * it returns null.
3241
3371
  */
3242
- function getScopeTokenClass(owner) {
3372
+ // TODO [#3733]: remove support for legacy scope tokens
3373
+ function getScopeTokenClass(owner, legacy) {
3243
3374
  const { cmpTemplate, context } = owner;
3244
- return (context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) || null;
3375
+ return ((context.hasScopedStyles &&
3376
+ (legacy ? cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.legacyStylesheetToken : cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) ||
3377
+ null);
3245
3378
  }
3246
3379
  /**
3247
3380
  * This function returns the host style token for a custom element if it
@@ -3740,6 +3873,10 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
3740
3873
  };
3741
3874
  let connectedCallback;
3742
3875
  let disconnectedCallback;
3876
+ let formAssociatedCallback;
3877
+ let formDisabledCallback;
3878
+ let formResetCallback;
3879
+ let formStateRestoreCallback;
3743
3880
  if (lwcRuntimeFlags.ENABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE) {
3744
3881
  connectedCallback = (elm) => {
3745
3882
  connectRootElement(elm);
@@ -3747,13 +3884,25 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
3747
3884
  disconnectedCallback = (elm) => {
3748
3885
  disconnectRootElement(elm);
3749
3886
  };
3887
+ formAssociatedCallback = (elm) => {
3888
+ runFormAssociatedCallback(elm);
3889
+ };
3890
+ formDisabledCallback = (elm) => {
3891
+ runFormDisabledCallback(elm);
3892
+ };
3893
+ formResetCallback = (elm) => {
3894
+ runFormResetCallback(elm);
3895
+ };
3896
+ formStateRestoreCallback = (elm) => {
3897
+ runFormStateRestoreCallback(elm);
3898
+ };
3750
3899
  }
3751
3900
  // Should never get a tag with upper case letter at this point; the compiler
3752
3901
  // should produce only tags with lowercase letters. However, the Java
3753
3902
  // compiler may generate tagnames with uppercase letters so - for backwards
3754
3903
  // compatibility, we lower case the tagname here.
3755
3904
  const normalizedTagname = sel.toLowerCase();
3756
- const elm = createCustomElement(normalizedTagname, upgradeCallback, connectedCallback, disconnectedCallback);
3905
+ const elm = createCustomElement(normalizedTagname, upgradeCallback, connectedCallback, disconnectedCallback, formAssociatedCallback, formDisabledCallback, formResetCallback, formStateRestoreCallback);
3757
3906
  vnode.elm = elm;
3758
3907
  vnode.vm = vm;
3759
3908
  linkNodeToShadow(elm, owner, renderer);
@@ -3959,18 +4108,35 @@ function patchElementPropsAndAttrs$1(oldVnode, vnode, renderer) {
3959
4108
  patchProps(oldVnode, vnode, renderer);
3960
4109
  }
3961
4110
  function applyStyleScoping(elm, owner, renderer) {
4111
+ const { getClassList } = renderer;
3962
4112
  // Set the class name for `*.scoped.css` style scoping.
3963
- const scopeToken = getScopeTokenClass(owner);
4113
+ const scopeToken = getScopeTokenClass(owner, /* legacy */ false);
3964
4114
  if (!isNull(scopeToken)) {
3965
- const { getClassList } = renderer;
3966
4115
  // TODO [#2762]: this dot notation with add is probably problematic
3967
4116
  // probably we should have a renderer api for just the add operation
3968
4117
  getClassList(elm).add(scopeToken);
3969
4118
  }
4119
+ // TODO [#3733]: remove support for legacy scope tokens
4120
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4121
+ const legacyScopeToken = getScopeTokenClass(owner, /* legacy */ true);
4122
+ if (!isNull(legacyScopeToken)) {
4123
+ // TODO [#2762]: this dot notation with add is probably problematic
4124
+ // probably we should have a renderer api for just the add operation
4125
+ getClassList(elm).add(legacyScopeToken);
4126
+ }
4127
+ }
3970
4128
  // Set property element for synthetic shadow DOM style scoping.
3971
4129
  const { stylesheetToken: syntheticToken } = owner.context;
3972
- if (owner.shadowMode === 1 /* ShadowMode.Synthetic */ && !isUndefined$1(syntheticToken)) {
3973
- elm.$shadowToken$ = syntheticToken;
4130
+ if (owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
4131
+ if (!isUndefined$1(syntheticToken)) {
4132
+ elm.$shadowToken$ = syntheticToken;
4133
+ }
4134
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4135
+ const legacyToken = owner.context.legacyStylesheetToken;
4136
+ if (!isUndefined$1(legacyToken)) {
4137
+ elm.$legacyShadowToken$ = legacyToken;
4138
+ }
4139
+ }
3974
4140
  }
3975
4141
  }
3976
4142
  function applyDomManual(elm, vnode) {
@@ -4997,9 +5163,10 @@ function buildParseFragmentFn(createFragmentFn) {
4997
5163
  return (strings, ...keys) => {
4998
5164
  const cache = create(null);
4999
5165
  return function () {
5000
- const { context: { hasScopedStyles, stylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5166
+ const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5001
5167
  const hasStyleToken = !isUndefined$1(stylesheetToken);
5002
5168
  const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
5169
+ const hasLegacyToken = lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS && !isUndefined$1(legacyStylesheetToken);
5003
5170
  let cacheKey = 0;
5004
5171
  if (hasStyleToken && hasScopedStyles) {
5005
5172
  cacheKey |= 1 /* FragmentCache.HAS_SCOPED_STYLE */;
@@ -5007,12 +5174,19 @@ function buildParseFragmentFn(createFragmentFn) {
5007
5174
  if (hasStyleToken && isSyntheticShadow) {
5008
5175
  cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
5009
5176
  }
5177
+ if (hasLegacyToken) {
5178
+ // This isn't strictly required for prod, but it's required for our karma tests
5179
+ // since the lwcRuntimeFlag may change over time
5180
+ cacheKey |= 4 /* FragmentCache.HAS_LEGACY_SCOPE_TOKEN */;
5181
+ }
5010
5182
  if (!isUndefined$1(cache[cacheKey])) {
5011
5183
  return cache[cacheKey];
5012
5184
  }
5013
- const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '';
5014
- const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetToken}"` : '';
5015
- const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '';
5185
+ // If legacy stylesheet tokens are required, then add them to the rendered string
5186
+ const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
5187
+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetTokenToRender : '';
5188
+ const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetTokenToRender}"` : '';
5189
+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetTokenToRender : '';
5016
5190
  let htmlFragment = '';
5017
5191
  for (let i = 0, n = keys.length; i < n; i++) {
5018
5192
  switch (keys[i]) {
@@ -5088,7 +5262,10 @@ function evaluateTemplate(vm, html) {
5088
5262
  // Set the computeHasScopedStyles property in the context, to avoid recomputing it repeatedly.
5089
5263
  context.hasScopedStyles = computeHasScopedStyles(html, vm);
5090
5264
  // Update the scoping token on the host element.
5091
- updateStylesheetToken(vm, html);
5265
+ updateStylesheetToken(vm, html, /* legacy */ false);
5266
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
5267
+ updateStylesheetToken(vm, html, /* legacy */ true);
5268
+ }
5092
5269
  // Evaluate, create stylesheet and cache the produced VNode for future
5093
5270
  // re-rendering.
5094
5271
  const stylesheetsContent = getStylesheetsContent(vm, html);
@@ -5426,6 +5603,9 @@ function createVM(elm, ctor, renderer, options) {
5426
5603
  stylesheetToken: undefined,
5427
5604
  hasTokenInClass: undefined,
5428
5605
  hasTokenInAttribute: undefined,
5606
+ legacyStylesheetToken: undefined,
5607
+ hasLegacyTokenInClass: undefined,
5608
+ hasLegacyTokenInAttribute: undefined,
5429
5609
  hasScopedStyles: undefined,
5430
5610
  styleVNodes: null,
5431
5611
  tplCache: EmptyObject,
@@ -5850,6 +6030,48 @@ function forceRehydration(vm) {
5850
6030
  scheduleRehydration(vm);
5851
6031
  }
5852
6032
  }
6033
+ function runFormAssociatedCustomElementCallback(vm, faceCb) {
6034
+ const { renderMode, shadowMode, def: { formAssociated }, } = vm;
6035
+ // Technically the UpgradableConstructor always sets `static formAssociated = true` but silently fail here to match browser behavior.
6036
+ if (isUndefined$1(formAssociated) || isFalse(formAssociated)) {
6037
+ if (process.env.NODE_ENV !== 'production') {
6038
+ logWarn(`Form associated lifecycle methods must have the 'static formAssociated' value set in the component's prototype chain.`);
6039
+ }
6040
+ return;
6041
+ }
6042
+ if (shadowMode === 1 /* ShadowMode.Synthetic */ && renderMode !== 0 /* RenderMode.Light */) {
6043
+ throw new Error('Form associated lifecycle methods are not available in synthetic shadow. Please use native shadow or light DOM.');
6044
+ }
6045
+ invokeComponentCallback(vm, faceCb);
6046
+ }
6047
+ function runFormAssociatedCallback(elm) {
6048
+ const vm = getAssociatedVM(elm);
6049
+ const { formAssociatedCallback } = vm.def;
6050
+ if (!isUndefined$1(formAssociatedCallback)) {
6051
+ runFormAssociatedCustomElementCallback(vm, formAssociatedCallback);
6052
+ }
6053
+ }
6054
+ function runFormDisabledCallback(elm) {
6055
+ const vm = getAssociatedVM(elm);
6056
+ const { formDisabledCallback } = vm.def;
6057
+ if (!isUndefined$1(formDisabledCallback)) {
6058
+ runFormAssociatedCustomElementCallback(vm, formDisabledCallback);
6059
+ }
6060
+ }
6061
+ function runFormResetCallback(elm) {
6062
+ const vm = getAssociatedVM(elm);
6063
+ const { formResetCallback } = vm.def;
6064
+ if (!isUndefined$1(formResetCallback)) {
6065
+ runFormAssociatedCustomElementCallback(vm, formResetCallback);
6066
+ }
6067
+ }
6068
+ function runFormStateRestoreCallback(elm) {
6069
+ const vm = getAssociatedVM(elm);
6070
+ const { formStateRestoreCallback } = vm.def;
6071
+ if (!isUndefined$1(formStateRestoreCallback)) {
6072
+ runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
6073
+ }
6074
+ }
5853
6075
 
5854
6076
  /*
5855
6077
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6446,7 +6668,8 @@ function validateClassAttr(vnode, elm, renderer) {
6446
6668
  const { data, owner } = vnode;
6447
6669
  let { className, classMap } = data;
6448
6670
  const { getProperty, getClassList, getAttribute } = renderer;
6449
- const scopedToken = getScopeTokenClass(owner);
6671
+ // we don't care about legacy for hydration. it's a new use case
6672
+ const scopedToken = getScopeTokenClass(owner, /* legacy */ false);
6450
6673
  const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
6451
6674
  // Classnames for scoped CSS are added directly to the DOM during rendering,
6452
6675
  // or to the VDOM on the server in the case of SSR. As such, these classnames
@@ -6761,7 +6984,7 @@ function trackMutations(tmpl) {
6761
6984
  }
6762
6985
  function addLegacyStylesheetTokensShim(tmpl) {
6763
6986
  // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
6764
- // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
6987
+ // is accessing the old internal API (backwards compat). Details: W-14210169
6765
6988
  defineProperty(tmpl, 'stylesheetTokens', {
6766
6989
  enumerable: true,
6767
6990
  configurable: true,
@@ -6855,6 +7078,6 @@ function readonly(obj) {
6855
7078
  return getReadOnlyProxy(obj);
6856
7079
  }
6857
7080
 
6858
- 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, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
6859
- /** version: 3.3.3 */
7081
+ 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 };
7082
+ /** version: 3.5.0 */
6860
7083
  //# sourceMappingURL=index.js.map