@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.cjs.js CHANGED
@@ -523,8 +523,8 @@ function lockDomMutation() {
523
523
  assertNotProd(); // this method should never leak to prod
524
524
  isDomMutationAllowed = false;
525
525
  }
526
- function logMissingPortalError(name, type) {
527
- return logError(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
526
+ function logMissingPortalWarn(name, type) {
527
+ return logWarn(`The \`${name}\` ${type} is available only on elements that use the \`lwc:dom="manual"\` directive.`);
528
528
  }
529
529
  function patchElementWithRestrictions(elm, options) {
530
530
  assertNotProd(); // this method should never leak to prod
@@ -549,14 +549,14 @@ function patchElementWithRestrictions(elm, options) {
549
549
  shared.assign(descriptors, {
550
550
  appendChild: generateDataDescriptor({
551
551
  value(aChild) {
552
- logMissingPortalError('appendChild', 'method');
552
+ logMissingPortalWarn('appendChild', 'method');
553
553
  return appendChild.call(this, aChild);
554
554
  },
555
555
  }),
556
556
  insertBefore: generateDataDescriptor({
557
557
  value(newNode, referenceNode) {
558
558
  if (!isDomMutationAllowed) {
559
- logMissingPortalError('insertBefore', 'method');
559
+ logMissingPortalWarn('insertBefore', 'method');
560
560
  }
561
561
  return insertBefore.call(this, newNode, referenceNode);
562
562
  },
@@ -564,14 +564,14 @@ function patchElementWithRestrictions(elm, options) {
564
564
  removeChild: generateDataDescriptor({
565
565
  value(aChild) {
566
566
  if (!isDomMutationAllowed) {
567
- logMissingPortalError('removeChild', 'method');
567
+ logMissingPortalWarn('removeChild', 'method');
568
568
  }
569
569
  return removeChild.call(this, aChild);
570
570
  },
571
571
  }),
572
572
  replaceChild: generateDataDescriptor({
573
573
  value(newChild, oldChild) {
574
- logMissingPortalError('replaceChild', 'method');
574
+ logMissingPortalWarn('replaceChild', 'method');
575
575
  return replaceChild.call(this, newChild, oldChild);
576
576
  },
577
577
  }),
@@ -581,7 +581,7 @@ function patchElementWithRestrictions(elm, options) {
581
581
  },
582
582
  set(value) {
583
583
  if (!isDomMutationAllowed) {
584
- logMissingPortalError('nodeValue', 'property');
584
+ logMissingPortalWarn('nodeValue', 'property');
585
585
  }
586
586
  originalNodeValueDescriptor.set.call(this, value);
587
587
  },
@@ -591,7 +591,7 @@ function patchElementWithRestrictions(elm, options) {
591
591
  return originalTextContentDescriptor.get.call(this);
592
592
  },
593
593
  set(value) {
594
- logMissingPortalError('textContent', 'property');
594
+ logMissingPortalWarn('textContent', 'property');
595
595
  originalTextContentDescriptor.set.call(this, value);
596
596
  },
597
597
  }),
@@ -600,7 +600,7 @@ function patchElementWithRestrictions(elm, options) {
600
600
  return originalInnerHTMLDescriptor.get.call(this);
601
601
  },
602
602
  set(value) {
603
- logMissingPortalError('innerHTML', 'property');
603
+ logMissingPortalWarn('innerHTML', 'property');
604
604
  return originalInnerHTMLDescriptor.set.call(this, value);
605
605
  },
606
606
  }),
@@ -1458,7 +1458,51 @@ function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
1458
1458
  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.`);
1459
1459
  }
1460
1460
  }
1461
- const supportsElementInternals = typeof ElementInternals !== 'undefined';
1461
+ // List of properties on ElementInternals that are formAssociated can be found in the spec:
1462
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#form-associated-custom-elements
1463
+ const formAssociatedProps = new Set([
1464
+ 'setFormValue',
1465
+ 'form',
1466
+ 'setValidity',
1467
+ 'willValidate',
1468
+ 'validity',
1469
+ 'validationMessage',
1470
+ 'checkValidity',
1471
+ 'reportValidity',
1472
+ 'labels',
1473
+ ]);
1474
+ // Verify that access to a form-associated property of the ElementInternals proxy has formAssociated set in the LWC.
1475
+ function assertFormAssociatedPropertySet(propertyKey, isFormAssociated) {
1476
+ if (formAssociatedProps.has(propertyKey) && !isFormAssociated) {
1477
+ //Note this error message mirrors Chrome and Firefox error messages, in Safari the error is slightly different.
1478
+ throw new DOMException(`Failed to execute '${propertyKey}' on 'ElementInternals': The target element is not a form-associated custom element.`);
1479
+ }
1480
+ }
1481
+ // Wrap all ElementInternal objects in a proxy to prevent form association when `formAssociated` is not set on an LWC.
1482
+ // This is needed because the 1UpgradeableConstructor1 always sets `formAssociated=true`, which means all
1483
+ // ElementInternal objects will have form-associated properties set when an LWC is placed in a form.
1484
+ // We are doing this to guard against customers taking a dependency on form elements being associated to ElementInternals
1485
+ // when 'formAssociated' has not been set on the LWC.
1486
+ function createElementInternalsProxy(elementInternals, isFormAssociated) {
1487
+ const elementInternalsProxy = new Proxy(elementInternals, {
1488
+ set(target, propertyKey, newValue) {
1489
+ // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1490
+ assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1491
+ return Reflect.set(target, propertyKey, newValue);
1492
+ },
1493
+ get(target, propertyKey) {
1494
+ // ElementInternals implementation uses strings as property keys exclusively in chrome, firefox, and safari
1495
+ assertFormAssociatedPropertySet(propertyKey, isFormAssociated);
1496
+ const internalsPropertyValue = Reflect.get(target, propertyKey);
1497
+ // Bind the property value to the target so that function invocations are called with the
1498
+ // correct context ('this' value).
1499
+ return typeof internalsPropertyValue === 'function'
1500
+ ? internalsPropertyValue.bind(target)
1501
+ : internalsPropertyValue;
1502
+ },
1503
+ });
1504
+ return elementInternalsProxy;
1505
+ }
1462
1506
  // @ts-ignore
1463
1507
  LightningElement.prototype = {
1464
1508
  constructor: LightningElement,
@@ -1552,15 +1596,13 @@ LightningElement.prototype = {
1552
1596
  },
1553
1597
  attachInternals() {
1554
1598
  const vm = getAssociatedVM(this);
1555
- const { elm, renderer: { attachInternals }, } = vm;
1556
- if (shared.isFalse(supportsElementInternals)) {
1557
- // Browsers that don't support attachInternals will need to be polyfilled before LWC is loaded.
1558
- throw new Error('attachInternals API is not supported in this browser environment.');
1559
- }
1560
- if (vm.renderMode === 0 /* RenderMode.Light */ || vm.shadowMode === 1 /* ShadowMode.Synthetic */) {
1599
+ const { elm, def: { formAssociated }, renderer: { attachInternals }, } = vm;
1600
+ if (vm.shadowMode === 1 /* ShadowMode.Synthetic */) {
1561
1601
  throw new Error('attachInternals API is not supported in light DOM or synthetic shadow.');
1562
1602
  }
1563
- return attachInternals(elm);
1603
+ const internals = attachInternals(elm);
1604
+ // #TODO[2970]: remove proxy once `UpgradeableConstructor` has been removed
1605
+ return createElementInternalsProxy(internals, Boolean(formAssociated));
1564
1606
  },
1565
1607
  get isConnected() {
1566
1608
  const vm = getAssociatedVM(this);
@@ -2567,7 +2609,22 @@ function createAttributeChangedCallback(attributeToPropMap, superAttributeChange
2567
2609
  this[propName] = newValue;
2568
2610
  };
2569
2611
  }
2570
- function HTMLBridgeElementFactory(SuperClass, props, methods) {
2612
+ function createAccessorThatWarns(propName) {
2613
+ let prop;
2614
+ return {
2615
+ get() {
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
+ return prop;
2618
+ },
2619
+ set(value) {
2620
+ 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.`);
2621
+ prop = value;
2622
+ },
2623
+ enumerable: true,
2624
+ configurable: true,
2625
+ };
2626
+ }
2627
+ function HTMLBridgeElementFactory(SuperClass, publicProperties, methods, observedFields, proto) {
2571
2628
  const HTMLBridgeElement = class extends SuperClass {
2572
2629
  };
2573
2630
  // generating the hash table for attributes to avoid duplicate fields and facilitate validation
@@ -2576,9 +2633,30 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2576
2633
  const { attributeChangedCallback: superAttributeChangedCallback } = SuperClass.prototype;
2577
2634
  const { observedAttributes: superObservedAttributes = [] } = SuperClass;
2578
2635
  const descriptors = shared.create(null);
2636
+ // present a hint message so that developers are aware that they have not decorated property with @api
2637
+ if (process.env.NODE_ENV !== 'production') {
2638
+ if (!shared.isUndefined(proto) && !shared.isNull(proto)) {
2639
+ const nonPublicPropertiesToWarnOn = new Set([
2640
+ // getters, setters, and methods
2641
+ ...shared.keys(shared.getOwnPropertyDescriptors(proto)),
2642
+ // class properties
2643
+ ...observedFields,
2644
+ ]
2645
+ // we don't want to override HTMLElement props because these are meaningful in other ways,
2646
+ // and can break tooling that expects it to be iterable or defined, e.g. Jest:
2647
+ // https://github.com/jestjs/jest/blob/b4c9587/packages/pretty-format/src/plugins/DOMElement.ts#L95
2648
+ // It also doesn't make sense to override e.g. "constructor".
2649
+ .filter((propName) => !(propName in HTMLElementPrototype)));
2650
+ for (const propName of nonPublicPropertiesToWarnOn) {
2651
+ if (shared.ArrayIndexOf.call(publicProperties, propName) === -1) {
2652
+ descriptors[propName] = createAccessorThatWarns(propName);
2653
+ }
2654
+ }
2655
+ }
2656
+ }
2579
2657
  // expose getters and setters for each public props on the new Element Bridge
2580
- for (let i = 0, len = props.length; i < len; i += 1) {
2581
- const propName = props[i];
2658
+ for (let i = 0, len = publicProperties.length; i < len; i += 1) {
2659
+ const propName = publicProperties[i];
2582
2660
  attributeToPropMap[shared.htmlPropertyToAttribute(propName)] = propName;
2583
2661
  descriptors[propName] = {
2584
2662
  get: createGetter(propName),
@@ -2605,9 +2683,26 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2605
2683
  };
2606
2684
  // To avoid leaking private component details, accessing internals from outside a component is not allowed.
2607
2685
  descriptors.attachInternals = {
2686
+ set() {
2687
+ if (process.env.NODE_ENV !== 'production') {
2688
+ logWarn('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2689
+ }
2690
+ },
2608
2691
  get() {
2609
2692
  if (process.env.NODE_ENV !== 'production') {
2610
- logError('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2693
+ logWarn('attachInternals cannot be accessed outside of a component. Use this.attachInternals instead.');
2694
+ }
2695
+ },
2696
+ };
2697
+ descriptors.formAssociated = {
2698
+ set() {
2699
+ if (process.env.NODE_ENV !== 'production') {
2700
+ logWarn('formAssociated cannot be accessed outside of a component. Set the value within the component class.');
2701
+ }
2702
+ },
2703
+ get() {
2704
+ if (process.env.NODE_ENV !== 'production') {
2705
+ logWarn('formAssociated cannot be accessed outside of a component. Set the value within the component class.');
2611
2706
  }
2612
2707
  },
2613
2708
  };
@@ -2621,7 +2716,7 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2621
2716
  shared.defineProperties(HTMLBridgeElement.prototype, descriptors);
2622
2717
  return HTMLBridgeElement;
2623
2718
  }
2624
- const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, shared.getOwnPropertyNames(HTMLElementOriginalDescriptors), []);
2719
+ const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, shared.getOwnPropertyNames(HTMLElementOriginalDescriptors), [], [], null);
2625
2720
  if (process.env.IS_BROWSER) {
2626
2721
  // This ARIA reflection only really makes sense in the browser. On the server, there is no `renderedCallback()`,
2627
2722
  // so you cannot do e.g. `this.template.querySelector('x-child').ariaBusy = 'true'`. So we don't need to expose
@@ -2919,7 +3014,7 @@ function getCtorProto(Ctor) {
2919
3014
  return proto;
2920
3015
  }
2921
3016
  function createComponentDef(Ctor) {
2922
- const { shadowSupportMode: ctorShadowSupportMode, renderMode: ctorRenderMode } = Ctor;
3017
+ const { shadowSupportMode: ctorShadowSupportMode, renderMode: ctorRenderMode, formAssociated: ctorFormAssociated, } = Ctor;
2923
3018
  if (process.env.NODE_ENV !== 'production') {
2924
3019
  const ctorName = Ctor.name;
2925
3020
  // Removing the following assert until https://bugs.webkit.org/show_bug.cgi?id=190140 is fixed.
@@ -2943,10 +3038,10 @@ function createComponentDef(Ctor) {
2943
3038
  const decoratorsMeta = getDecoratorsMeta(Ctor);
2944
3039
  const { apiFields, apiFieldsConfig, apiMethods, wiredFields, wiredMethods, observedFields } = decoratorsMeta;
2945
3040
  const proto = Ctor.prototype;
2946
- let { connectedCallback, disconnectedCallback, renderedCallback, errorCallback, render } = proto;
3041
+ let { connectedCallback, disconnectedCallback, renderedCallback, errorCallback, formAssociatedCallback, formResetCallback, formDisabledCallback, formStateRestoreCallback, render, } = proto;
2947
3042
  const superProto = getCtorProto(Ctor);
2948
3043
  const superDef = superProto !== LightningElement ? getComponentInternalDef(superProto) : lightingElementDef;
2949
- const bridge = HTMLBridgeElementFactory(superDef.bridge, shared.keys(apiFields), shared.keys(apiMethods));
3044
+ const bridge = HTMLBridgeElementFactory(superDef.bridge, shared.keys(apiFields), shared.keys(apiMethods), shared.keys(observedFields), proto);
2950
3045
  const props = shared.assign(shared.create(null), superDef.props, apiFields);
2951
3046
  const propsConfig = shared.assign(shared.create(null), superDef.propsConfig, apiFieldsConfig);
2952
3047
  const methods = shared.assign(shared.create(null), superDef.methods, apiMethods);
@@ -2955,6 +3050,10 @@ function createComponentDef(Ctor) {
2955
3050
  disconnectedCallback = disconnectedCallback || superDef.disconnectedCallback;
2956
3051
  renderedCallback = renderedCallback || superDef.renderedCallback;
2957
3052
  errorCallback = errorCallback || superDef.errorCallback;
3053
+ formAssociatedCallback = formAssociatedCallback || superDef.formAssociatedCallback;
3054
+ formResetCallback = formResetCallback || superDef.formResetCallback;
3055
+ formDisabledCallback = formDisabledCallback || superDef.formDisabledCallback;
3056
+ formStateRestoreCallback = formStateRestoreCallback || superDef.formStateRestoreCallback;
2958
3057
  render = render || superDef.render;
2959
3058
  let shadowSupportMode = superDef.shadowSupportMode;
2960
3059
  if (!shared.isUndefined(ctorShadowSupportMode)) {
@@ -2964,6 +3063,10 @@ function createComponentDef(Ctor) {
2964
3063
  if (!shared.isUndefined(ctorRenderMode)) {
2965
3064
  renderMode = ctorRenderMode === 'light' ? 0 /* RenderMode.Light */ : 1 /* RenderMode.Shadow */;
2966
3065
  }
3066
+ let formAssociated = superDef.formAssociated;
3067
+ if (!shared.isUndefined(ctorFormAssociated)) {
3068
+ formAssociated = ctorFormAssociated;
3069
+ }
2967
3070
  const template = getComponentRegisteredTemplate(Ctor) || superDef.template;
2968
3071
  const name = Ctor.name || superDef.name;
2969
3072
  // installing observed fields into the prototype.
@@ -2979,10 +3082,15 @@ function createComponentDef(Ctor) {
2979
3082
  template,
2980
3083
  renderMode,
2981
3084
  shadowSupportMode,
3085
+ formAssociated,
2982
3086
  connectedCallback,
2983
3087
  disconnectedCallback,
2984
- renderedCallback,
2985
3088
  errorCallback,
3089
+ formAssociatedCallback,
3090
+ formDisabledCallback,
3091
+ formResetCallback,
3092
+ formStateRestoreCallback,
3093
+ renderedCallback,
2986
3094
  render,
2987
3095
  };
2988
3096
  // This is a no-op unless Lightning DevTools are enabled.
@@ -3059,6 +3167,7 @@ const lightingElementDef = {
3059
3167
  methods: EmptyObject,
3060
3168
  renderMode: 1 /* RenderMode.Shadow */,
3061
3169
  shadowSupportMode: "reset" /* ShadowSupportMode.Default */,
3170
+ formAssociated: undefined,
3062
3171
  wire: EmptyObject,
3063
3172
  bridge: BaseBridgeElement,
3064
3173
  template: defaultEmptyTemplate,
@@ -3115,9 +3224,11 @@ function createInlineStyleVNode(content) {
3115
3224
  },
3116
3225
  }, [api.t(content)]);
3117
3226
  }
3118
- function updateStylesheetToken(vm, template) {
3227
+ // TODO [#3733]: remove support for legacy scope tokens
3228
+ function updateStylesheetToken(vm, template, legacy) {
3119
3229
  const { elm, context, renderMode, shadowMode, renderer: { getClassList, removeAttribute, setAttribute }, } = vm;
3120
- const { stylesheets: newStylesheets, stylesheetToken: newStylesheetToken } = template;
3230
+ const { stylesheets: newStylesheets } = template;
3231
+ const newStylesheetToken = legacy ? template.legacyStylesheetToken : template.stylesheetToken;
3121
3232
  const { stylesheets: newVmStylesheets } = vm;
3122
3233
  const isSyntheticShadow = renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */;
3123
3234
  const { hasScopedStyles } = context;
@@ -3125,7 +3236,19 @@ function updateStylesheetToken(vm, template) {
3125
3236
  let newHasTokenInClass;
3126
3237
  let newHasTokenInAttribute;
3127
3238
  // Reset the styling token applied to the host element.
3128
- const { stylesheetToken: oldToken, hasTokenInClass: oldHasTokenInClass, hasTokenInAttribute: oldHasTokenInAttribute, } = context;
3239
+ let oldToken;
3240
+ let oldHasTokenInClass;
3241
+ let oldHasTokenInAttribute;
3242
+ if (legacy) {
3243
+ oldToken = context.legacyStylesheetToken;
3244
+ oldHasTokenInClass = context.hasLegacyTokenInClass;
3245
+ oldHasTokenInAttribute = context.hasLegacyTokenInAttribute;
3246
+ }
3247
+ else {
3248
+ oldToken = context.stylesheetToken;
3249
+ oldHasTokenInClass = context.hasTokenInClass;
3250
+ oldHasTokenInAttribute = context.hasTokenInAttribute;
3251
+ }
3129
3252
  if (!shared.isUndefined(oldToken)) {
3130
3253
  if (oldHasTokenInClass) {
3131
3254
  getClassList(elm).remove(makeHostToken(oldToken));
@@ -3153,9 +3276,16 @@ function updateStylesheetToken(vm, template) {
3153
3276
  }
3154
3277
  }
3155
3278
  // Update the styling tokens present on the context object.
3156
- context.stylesheetToken = newToken;
3157
- context.hasTokenInClass = newHasTokenInClass;
3158
- context.hasTokenInAttribute = newHasTokenInAttribute;
3279
+ if (legacy) {
3280
+ context.legacyStylesheetToken = newToken;
3281
+ context.hasLegacyTokenInClass = newHasTokenInClass;
3282
+ context.hasLegacyTokenInAttribute = newHasTokenInAttribute;
3283
+ }
3284
+ else {
3285
+ context.stylesheetToken = newToken;
3286
+ context.hasTokenInClass = newHasTokenInClass;
3287
+ context.hasTokenInAttribute = newHasTokenInAttribute;
3288
+ }
3159
3289
  }
3160
3290
  function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3161
3291
  const content = [];
@@ -3243,9 +3373,12 @@ function getNearestShadowComponent(vm) {
3243
3373
  * this returns the unique token for that scoped stylesheet. Otherwise
3244
3374
  * it returns null.
3245
3375
  */
3246
- function getScopeTokenClass(owner) {
3376
+ // TODO [#3733]: remove support for legacy scope tokens
3377
+ function getScopeTokenClass(owner, legacy) {
3247
3378
  const { cmpTemplate, context } = owner;
3248
- return (context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) || null;
3379
+ return ((context.hasScopedStyles &&
3380
+ (legacy ? cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.legacyStylesheetToken : cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) ||
3381
+ null);
3249
3382
  }
3250
3383
  /**
3251
3384
  * This function returns the host style token for a custom element if it
@@ -3744,6 +3877,10 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
3744
3877
  };
3745
3878
  let connectedCallback;
3746
3879
  let disconnectedCallback;
3880
+ let formAssociatedCallback;
3881
+ let formDisabledCallback;
3882
+ let formResetCallback;
3883
+ let formStateRestoreCallback;
3747
3884
  if (lwcRuntimeFlags.ENABLE_NATIVE_CUSTOM_ELEMENT_LIFECYCLE) {
3748
3885
  connectedCallback = (elm) => {
3749
3886
  connectRootElement(elm);
@@ -3751,13 +3888,25 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
3751
3888
  disconnectedCallback = (elm) => {
3752
3889
  disconnectRootElement(elm);
3753
3890
  };
3891
+ formAssociatedCallback = (elm) => {
3892
+ runFormAssociatedCallback(elm);
3893
+ };
3894
+ formDisabledCallback = (elm) => {
3895
+ runFormDisabledCallback(elm);
3896
+ };
3897
+ formResetCallback = (elm) => {
3898
+ runFormResetCallback(elm);
3899
+ };
3900
+ formStateRestoreCallback = (elm) => {
3901
+ runFormStateRestoreCallback(elm);
3902
+ };
3754
3903
  }
3755
3904
  // Should never get a tag with upper case letter at this point; the compiler
3756
3905
  // should produce only tags with lowercase letters. However, the Java
3757
3906
  // compiler may generate tagnames with uppercase letters so - for backwards
3758
3907
  // compatibility, we lower case the tagname here.
3759
3908
  const normalizedTagname = sel.toLowerCase();
3760
- const elm = createCustomElement(normalizedTagname, upgradeCallback, connectedCallback, disconnectedCallback);
3909
+ const elm = createCustomElement(normalizedTagname, upgradeCallback, connectedCallback, disconnectedCallback, formAssociatedCallback, formDisabledCallback, formResetCallback, formStateRestoreCallback);
3761
3910
  vnode.elm = elm;
3762
3911
  vnode.vm = vm;
3763
3912
  linkNodeToShadow(elm, owner, renderer);
@@ -3963,18 +4112,35 @@ function patchElementPropsAndAttrs$1(oldVnode, vnode, renderer) {
3963
4112
  patchProps(oldVnode, vnode, renderer);
3964
4113
  }
3965
4114
  function applyStyleScoping(elm, owner, renderer) {
4115
+ const { getClassList } = renderer;
3966
4116
  // Set the class name for `*.scoped.css` style scoping.
3967
- const scopeToken = getScopeTokenClass(owner);
4117
+ const scopeToken = getScopeTokenClass(owner, /* legacy */ false);
3968
4118
  if (!shared.isNull(scopeToken)) {
3969
- const { getClassList } = renderer;
3970
4119
  // TODO [#2762]: this dot notation with add is probably problematic
3971
4120
  // probably we should have a renderer api for just the add operation
3972
4121
  getClassList(elm).add(scopeToken);
3973
4122
  }
4123
+ // TODO [#3733]: remove support for legacy scope tokens
4124
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4125
+ const legacyScopeToken = getScopeTokenClass(owner, /* legacy */ true);
4126
+ if (!shared.isNull(legacyScopeToken)) {
4127
+ // TODO [#2762]: this dot notation with add is probably problematic
4128
+ // probably we should have a renderer api for just the add operation
4129
+ getClassList(elm).add(legacyScopeToken);
4130
+ }
4131
+ }
3974
4132
  // Set property element for synthetic shadow DOM style scoping.
3975
4133
  const { stylesheetToken: syntheticToken } = owner.context;
3976
- if (owner.shadowMode === 1 /* ShadowMode.Synthetic */ && !shared.isUndefined(syntheticToken)) {
3977
- elm.$shadowToken$ = syntheticToken;
4134
+ if (owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
4135
+ if (!shared.isUndefined(syntheticToken)) {
4136
+ elm.$shadowToken$ = syntheticToken;
4137
+ }
4138
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4139
+ const legacyToken = owner.context.legacyStylesheetToken;
4140
+ if (!shared.isUndefined(legacyToken)) {
4141
+ elm.$legacyShadowToken$ = legacyToken;
4142
+ }
4143
+ }
3978
4144
  }
3979
4145
  }
3980
4146
  function applyDomManual(elm, vnode) {
@@ -5001,9 +5167,10 @@ function buildParseFragmentFn(createFragmentFn) {
5001
5167
  return (strings, ...keys) => {
5002
5168
  const cache = shared.create(null);
5003
5169
  return function () {
5004
- const { context: { hasScopedStyles, stylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5170
+ const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5005
5171
  const hasStyleToken = !shared.isUndefined(stylesheetToken);
5006
5172
  const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
5173
+ const hasLegacyToken = lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS && !shared.isUndefined(legacyStylesheetToken);
5007
5174
  let cacheKey = 0;
5008
5175
  if (hasStyleToken && hasScopedStyles) {
5009
5176
  cacheKey |= 1 /* FragmentCache.HAS_SCOPED_STYLE */;
@@ -5011,12 +5178,19 @@ function buildParseFragmentFn(createFragmentFn) {
5011
5178
  if (hasStyleToken && isSyntheticShadow) {
5012
5179
  cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
5013
5180
  }
5181
+ if (hasLegacyToken) {
5182
+ // This isn't strictly required for prod, but it's required for our karma tests
5183
+ // since the lwcRuntimeFlag may change over time
5184
+ cacheKey |= 4 /* FragmentCache.HAS_LEGACY_SCOPE_TOKEN */;
5185
+ }
5014
5186
  if (!shared.isUndefined(cache[cacheKey])) {
5015
5187
  return cache[cacheKey];
5016
5188
  }
5017
- const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '';
5018
- const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetToken}"` : '';
5019
- const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '';
5189
+ // If legacy stylesheet tokens are required, then add them to the rendered string
5190
+ const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
5191
+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetTokenToRender : '';
5192
+ const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetTokenToRender}"` : '';
5193
+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetTokenToRender : '';
5020
5194
  let htmlFragment = '';
5021
5195
  for (let i = 0, n = keys.length; i < n; i++) {
5022
5196
  switch (keys[i]) {
@@ -5092,7 +5266,10 @@ function evaluateTemplate(vm, html) {
5092
5266
  // Set the computeHasScopedStyles property in the context, to avoid recomputing it repeatedly.
5093
5267
  context.hasScopedStyles = computeHasScopedStyles(html, vm);
5094
5268
  // Update the scoping token on the host element.
5095
- updateStylesheetToken(vm, html);
5269
+ updateStylesheetToken(vm, html, /* legacy */ false);
5270
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
5271
+ updateStylesheetToken(vm, html, /* legacy */ true);
5272
+ }
5096
5273
  // Evaluate, create stylesheet and cache the produced VNode for future
5097
5274
  // re-rendering.
5098
5275
  const stylesheetsContent = getStylesheetsContent(vm, html);
@@ -5430,6 +5607,9 @@ function createVM(elm, ctor, renderer, options) {
5430
5607
  stylesheetToken: undefined,
5431
5608
  hasTokenInClass: undefined,
5432
5609
  hasTokenInAttribute: undefined,
5610
+ legacyStylesheetToken: undefined,
5611
+ hasLegacyTokenInClass: undefined,
5612
+ hasLegacyTokenInAttribute: undefined,
5433
5613
  hasScopedStyles: undefined,
5434
5614
  styleVNodes: null,
5435
5615
  tplCache: EmptyObject,
@@ -5854,6 +6034,48 @@ function forceRehydration(vm) {
5854
6034
  scheduleRehydration(vm);
5855
6035
  }
5856
6036
  }
6037
+ function runFormAssociatedCustomElementCallback(vm, faceCb) {
6038
+ const { renderMode, shadowMode, def: { formAssociated }, } = vm;
6039
+ // Technically the UpgradableConstructor always sets `static formAssociated = true` but silently fail here to match browser behavior.
6040
+ if (shared.isUndefined(formAssociated) || shared.isFalse(formAssociated)) {
6041
+ if (process.env.NODE_ENV !== 'production') {
6042
+ logWarn(`Form associated lifecycle methods must have the 'static formAssociated' value set in the component's prototype chain.`);
6043
+ }
6044
+ return;
6045
+ }
6046
+ if (shadowMode === 1 /* ShadowMode.Synthetic */ && renderMode !== 0 /* RenderMode.Light */) {
6047
+ throw new Error('Form associated lifecycle methods are not available in synthetic shadow. Please use native shadow or light DOM.');
6048
+ }
6049
+ invokeComponentCallback(vm, faceCb);
6050
+ }
6051
+ function runFormAssociatedCallback(elm) {
6052
+ const vm = getAssociatedVM(elm);
6053
+ const { formAssociatedCallback } = vm.def;
6054
+ if (!shared.isUndefined(formAssociatedCallback)) {
6055
+ runFormAssociatedCustomElementCallback(vm, formAssociatedCallback);
6056
+ }
6057
+ }
6058
+ function runFormDisabledCallback(elm) {
6059
+ const vm = getAssociatedVM(elm);
6060
+ const { formDisabledCallback } = vm.def;
6061
+ if (!shared.isUndefined(formDisabledCallback)) {
6062
+ runFormAssociatedCustomElementCallback(vm, formDisabledCallback);
6063
+ }
6064
+ }
6065
+ function runFormResetCallback(elm) {
6066
+ const vm = getAssociatedVM(elm);
6067
+ const { formResetCallback } = vm.def;
6068
+ if (!shared.isUndefined(formResetCallback)) {
6069
+ runFormAssociatedCustomElementCallback(vm, formResetCallback);
6070
+ }
6071
+ }
6072
+ function runFormStateRestoreCallback(elm) {
6073
+ const vm = getAssociatedVM(elm);
6074
+ const { formStateRestoreCallback } = vm.def;
6075
+ if (!shared.isUndefined(formStateRestoreCallback)) {
6076
+ runFormAssociatedCustomElementCallback(vm, formStateRestoreCallback);
6077
+ }
6078
+ }
5857
6079
 
5858
6080
  /*
5859
6081
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6450,7 +6672,8 @@ function validateClassAttr(vnode, elm, renderer) {
6450
6672
  const { data, owner } = vnode;
6451
6673
  let { className, classMap } = data;
6452
6674
  const { getProperty, getClassList, getAttribute } = renderer;
6453
- const scopedToken = getScopeTokenClass(owner);
6675
+ // we don't care about legacy for hydration. it's a new use case
6676
+ const scopedToken = getScopeTokenClass(owner, /* legacy */ false);
6454
6677
  const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
6455
6678
  // Classnames for scoped CSS are added directly to the DOM during rendering,
6456
6679
  // or to the VDOM on the server in the case of SSR. As such, these classnames
@@ -6765,7 +6988,7 @@ function trackMutations(tmpl) {
6765
6988
  }
6766
6989
  function addLegacyStylesheetTokensShim(tmpl) {
6767
6990
  // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
6768
- // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
6991
+ // is accessing the old internal API (backwards compat). Details: W-14210169
6769
6992
  shared.defineProperty(tmpl, 'stylesheetTokens', {
6770
6993
  enumerable: true,
6771
6994
  configurable: true,
@@ -6890,6 +7113,10 @@ exports.readonly = readonly;
6890
7113
  exports.registerComponent = registerComponent;
6891
7114
  exports.registerDecorators = registerDecorators;
6892
7115
  exports.registerTemplate = registerTemplate;
7116
+ exports.runFormAssociatedCallback = runFormAssociatedCallback;
7117
+ exports.runFormDisabledCallback = runFormDisabledCallback;
7118
+ exports.runFormResetCallback = runFormResetCallback;
7119
+ exports.runFormStateRestoreCallback = runFormStateRestoreCallback;
6893
7120
  exports.sanitizeAttribute = sanitizeAttribute;
6894
7121
  exports.setHooks = setHooks;
6895
7122
  exports.swapComponent = swapComponent;
@@ -6898,5 +7125,5 @@ exports.swapTemplate = swapTemplate;
6898
7125
  exports.track = track;
6899
7126
  exports.unwrap = unwrap;
6900
7127
  exports.wire = wire;
6901
- /** version: 3.3.3 */
7128
+ /** version: 3.5.0 */
6902
7129
  //# sourceMappingURL=index.cjs.js.map