@lwc/engine-core 3.3.3 → 3.4.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, isFalse, freeze, KEY__SYNTHETIC_MODE, assert, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, 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
 
@@ -2563,7 +2563,22 @@ function createAttributeChangedCallback(attributeToPropMap, superAttributeChange
2563
2563
  this[propName] = newValue;
2564
2564
  };
2565
2565
  }
2566
- function HTMLBridgeElementFactory(SuperClass, props, methods) {
2566
+ function createAccessorThatWarns(propName) {
2567
+ let prop;
2568
+ return {
2569
+ get() {
2570
+ 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.`);
2571
+ return prop;
2572
+ },
2573
+ set(value) {
2574
+ 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.`);
2575
+ prop = value;
2576
+ },
2577
+ enumerable: true,
2578
+ configurable: true,
2579
+ };
2580
+ }
2581
+ function HTMLBridgeElementFactory(SuperClass, publicProperties, methods, observedFields, proto) {
2567
2582
  const HTMLBridgeElement = class extends SuperClass {
2568
2583
  };
2569
2584
  // generating the hash table for attributes to avoid duplicate fields and facilitate validation
@@ -2572,9 +2587,30 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2572
2587
  const { attributeChangedCallback: superAttributeChangedCallback } = SuperClass.prototype;
2573
2588
  const { observedAttributes: superObservedAttributes = [] } = SuperClass;
2574
2589
  const descriptors = create(null);
2590
+ // present a hint message so that developers are aware that they have not decorated property with @api
2591
+ if (process.env.NODE_ENV !== 'production') {
2592
+ if (!isUndefined$1(proto) && !isNull(proto)) {
2593
+ const nonPublicPropertiesToWarnOn = new Set([
2594
+ // getters, setters, and methods
2595
+ ...keys(getOwnPropertyDescriptors(proto)),
2596
+ // class properties
2597
+ ...observedFields,
2598
+ ]
2599
+ // we don't want to override HTMLElement props because these are meaningful in other ways,
2600
+ // and can break tooling that expects it to be iterable or defined, e.g. Jest:
2601
+ // https://github.com/jestjs/jest/blob/b4c9587/packages/pretty-format/src/plugins/DOMElement.ts#L95
2602
+ // It also doesn't make sense to override e.g. "constructor".
2603
+ .filter((propName) => !(propName in HTMLElementPrototype)));
2604
+ for (const propName of nonPublicPropertiesToWarnOn) {
2605
+ if (ArrayIndexOf.call(publicProperties, propName) === -1) {
2606
+ descriptors[propName] = createAccessorThatWarns(propName);
2607
+ }
2608
+ }
2609
+ }
2610
+ }
2575
2611
  // 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];
2612
+ for (let i = 0, len = publicProperties.length; i < len; i += 1) {
2613
+ const propName = publicProperties[i];
2578
2614
  attributeToPropMap[htmlPropertyToAttribute(propName)] = propName;
2579
2615
  descriptors[propName] = {
2580
2616
  get: createGetter(propName),
@@ -2617,7 +2653,7 @@ function HTMLBridgeElementFactory(SuperClass, props, methods) {
2617
2653
  defineProperties(HTMLBridgeElement.prototype, descriptors);
2618
2654
  return HTMLBridgeElement;
2619
2655
  }
2620
- const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, getOwnPropertyNames$1(HTMLElementOriginalDescriptors), []);
2656
+ const BaseBridgeElement = HTMLBridgeElementFactory(HTMLElementConstructor, getOwnPropertyNames$1(HTMLElementOriginalDescriptors), [], [], null);
2621
2657
  if (process.env.IS_BROWSER) {
2622
2658
  // This ARIA reflection only really makes sense in the browser. On the server, there is no `renderedCallback()`,
2623
2659
  // so you cannot do e.g. `this.template.querySelector('x-child').ariaBusy = 'true'`. So we don't need to expose
@@ -2942,7 +2978,7 @@ function createComponentDef(Ctor) {
2942
2978
  let { connectedCallback, disconnectedCallback, renderedCallback, errorCallback, render } = proto;
2943
2979
  const superProto = getCtorProto(Ctor);
2944
2980
  const superDef = superProto !== LightningElement ? getComponentInternalDef(superProto) : lightingElementDef;
2945
- const bridge = HTMLBridgeElementFactory(superDef.bridge, keys(apiFields), keys(apiMethods));
2981
+ const bridge = HTMLBridgeElementFactory(superDef.bridge, keys(apiFields), keys(apiMethods), keys(observedFields), proto);
2946
2982
  const props = assign(create(null), superDef.props, apiFields);
2947
2983
  const propsConfig = assign(create(null), superDef.propsConfig, apiFieldsConfig);
2948
2984
  const methods = assign(create(null), superDef.methods, apiMethods);
@@ -3111,9 +3147,11 @@ function createInlineStyleVNode(content) {
3111
3147
  },
3112
3148
  }, [api.t(content)]);
3113
3149
  }
3114
- function updateStylesheetToken(vm, template) {
3150
+ // TODO [#3733]: remove support for legacy scope tokens
3151
+ function updateStylesheetToken(vm, template, legacy) {
3115
3152
  const { elm, context, renderMode, shadowMode, renderer: { getClassList, removeAttribute, setAttribute }, } = vm;
3116
- const { stylesheets: newStylesheets, stylesheetToken: newStylesheetToken } = template;
3153
+ const { stylesheets: newStylesheets } = template;
3154
+ const newStylesheetToken = legacy ? template.legacyStylesheetToken : template.stylesheetToken;
3117
3155
  const { stylesheets: newVmStylesheets } = vm;
3118
3156
  const isSyntheticShadow = renderMode === 1 /* RenderMode.Shadow */ && shadowMode === 1 /* ShadowMode.Synthetic */;
3119
3157
  const { hasScopedStyles } = context;
@@ -3121,7 +3159,19 @@ function updateStylesheetToken(vm, template) {
3121
3159
  let newHasTokenInClass;
3122
3160
  let newHasTokenInAttribute;
3123
3161
  // Reset the styling token applied to the host element.
3124
- const { stylesheetToken: oldToken, hasTokenInClass: oldHasTokenInClass, hasTokenInAttribute: oldHasTokenInAttribute, } = context;
3162
+ let oldToken;
3163
+ let oldHasTokenInClass;
3164
+ let oldHasTokenInAttribute;
3165
+ if (legacy) {
3166
+ oldToken = context.legacyStylesheetToken;
3167
+ oldHasTokenInClass = context.hasLegacyTokenInClass;
3168
+ oldHasTokenInAttribute = context.hasLegacyTokenInAttribute;
3169
+ }
3170
+ else {
3171
+ oldToken = context.stylesheetToken;
3172
+ oldHasTokenInClass = context.hasTokenInClass;
3173
+ oldHasTokenInAttribute = context.hasTokenInAttribute;
3174
+ }
3125
3175
  if (!isUndefined$1(oldToken)) {
3126
3176
  if (oldHasTokenInClass) {
3127
3177
  getClassList(elm).remove(makeHostToken(oldToken));
@@ -3149,9 +3199,16 @@ function updateStylesheetToken(vm, template) {
3149
3199
  }
3150
3200
  }
3151
3201
  // Update the styling tokens present on the context object.
3152
- context.stylesheetToken = newToken;
3153
- context.hasTokenInClass = newHasTokenInClass;
3154
- context.hasTokenInAttribute = newHasTokenInAttribute;
3202
+ if (legacy) {
3203
+ context.legacyStylesheetToken = newToken;
3204
+ context.hasLegacyTokenInClass = newHasTokenInClass;
3205
+ context.hasLegacyTokenInAttribute = newHasTokenInAttribute;
3206
+ }
3207
+ else {
3208
+ context.stylesheetToken = newToken;
3209
+ context.hasTokenInClass = newHasTokenInClass;
3210
+ context.hasTokenInAttribute = newHasTokenInAttribute;
3211
+ }
3155
3212
  }
3156
3213
  function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
3157
3214
  const content = [];
@@ -3239,9 +3296,12 @@ function getNearestShadowComponent(vm) {
3239
3296
  * this returns the unique token for that scoped stylesheet. Otherwise
3240
3297
  * it returns null.
3241
3298
  */
3242
- function getScopeTokenClass(owner) {
3299
+ // TODO [#3733]: remove support for legacy scope tokens
3300
+ function getScopeTokenClass(owner, legacy) {
3243
3301
  const { cmpTemplate, context } = owner;
3244
- return (context.hasScopedStyles && (cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) || null;
3302
+ return ((context.hasScopedStyles &&
3303
+ (legacy ? cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.legacyStylesheetToken : cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken)) ||
3304
+ null);
3245
3305
  }
3246
3306
  /**
3247
3307
  * This function returns the host style token for a custom element if it
@@ -3959,18 +4019,35 @@ function patchElementPropsAndAttrs$1(oldVnode, vnode, renderer) {
3959
4019
  patchProps(oldVnode, vnode, renderer);
3960
4020
  }
3961
4021
  function applyStyleScoping(elm, owner, renderer) {
4022
+ const { getClassList } = renderer;
3962
4023
  // Set the class name for `*.scoped.css` style scoping.
3963
- const scopeToken = getScopeTokenClass(owner);
4024
+ const scopeToken = getScopeTokenClass(owner, /* legacy */ false);
3964
4025
  if (!isNull(scopeToken)) {
3965
- const { getClassList } = renderer;
3966
4026
  // TODO [#2762]: this dot notation with add is probably problematic
3967
4027
  // probably we should have a renderer api for just the add operation
3968
4028
  getClassList(elm).add(scopeToken);
3969
4029
  }
4030
+ // TODO [#3733]: remove support for legacy scope tokens
4031
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4032
+ const legacyScopeToken = getScopeTokenClass(owner, /* legacy */ true);
4033
+ if (!isNull(legacyScopeToken)) {
4034
+ // TODO [#2762]: this dot notation with add is probably problematic
4035
+ // probably we should have a renderer api for just the add operation
4036
+ getClassList(elm).add(legacyScopeToken);
4037
+ }
4038
+ }
3970
4039
  // Set property element for synthetic shadow DOM style scoping.
3971
4040
  const { stylesheetToken: syntheticToken } = owner.context;
3972
- if (owner.shadowMode === 1 /* ShadowMode.Synthetic */ && !isUndefined$1(syntheticToken)) {
3973
- elm.$shadowToken$ = syntheticToken;
4041
+ if (owner.shadowMode === 1 /* ShadowMode.Synthetic */) {
4042
+ if (!isUndefined$1(syntheticToken)) {
4043
+ elm.$shadowToken$ = syntheticToken;
4044
+ }
4045
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
4046
+ const legacyToken = owner.context.legacyStylesheetToken;
4047
+ if (!isUndefined$1(legacyToken)) {
4048
+ elm.$legacyShadowToken$ = legacyToken;
4049
+ }
4050
+ }
3974
4051
  }
3975
4052
  }
3976
4053
  function applyDomManual(elm, vnode) {
@@ -4997,9 +5074,10 @@ function buildParseFragmentFn(createFragmentFn) {
4997
5074
  return (strings, ...keys) => {
4998
5075
  const cache = create(null);
4999
5076
  return function () {
5000
- const { context: { hasScopedStyles, stylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5077
+ const { context: { hasScopedStyles, stylesheetToken, legacyStylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
5001
5078
  const hasStyleToken = !isUndefined$1(stylesheetToken);
5002
5079
  const isSyntheticShadow = shadowMode === 1 /* ShadowMode.Synthetic */;
5080
+ const hasLegacyToken = lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS && !isUndefined$1(legacyStylesheetToken);
5003
5081
  let cacheKey = 0;
5004
5082
  if (hasStyleToken && hasScopedStyles) {
5005
5083
  cacheKey |= 1 /* FragmentCache.HAS_SCOPED_STYLE */;
@@ -5007,12 +5085,19 @@ function buildParseFragmentFn(createFragmentFn) {
5007
5085
  if (hasStyleToken && isSyntheticShadow) {
5008
5086
  cacheKey |= 2 /* FragmentCache.SHADOW_MODE_SYNTHETIC */;
5009
5087
  }
5088
+ if (hasLegacyToken) {
5089
+ // This isn't strictly required for prod, but it's required for our karma tests
5090
+ // since the lwcRuntimeFlag may change over time
5091
+ cacheKey |= 4 /* FragmentCache.HAS_LEGACY_SCOPE_TOKEN */;
5092
+ }
5010
5093
  if (!isUndefined$1(cache[cacheKey])) {
5011
5094
  return cache[cacheKey];
5012
5095
  }
5013
- const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '';
5014
- const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetToken}"` : '';
5015
- const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '';
5096
+ // If legacy stylesheet tokens are required, then add them to the rendered string
5097
+ const stylesheetTokenToRender = stylesheetToken + (hasLegacyToken ? ` ${legacyStylesheetToken}` : '');
5098
+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetTokenToRender : '';
5099
+ const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetTokenToRender}"` : '';
5100
+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetTokenToRender : '';
5016
5101
  let htmlFragment = '';
5017
5102
  for (let i = 0, n = keys.length; i < n; i++) {
5018
5103
  switch (keys[i]) {
@@ -5088,7 +5173,10 @@ function evaluateTemplate(vm, html) {
5088
5173
  // Set the computeHasScopedStyles property in the context, to avoid recomputing it repeatedly.
5089
5174
  context.hasScopedStyles = computeHasScopedStyles(html, vm);
5090
5175
  // Update the scoping token on the host element.
5091
- updateStylesheetToken(vm, html);
5176
+ updateStylesheetToken(vm, html, /* legacy */ false);
5177
+ if (lwcRuntimeFlags.ENABLE_LEGACY_SCOPE_TOKENS) {
5178
+ updateStylesheetToken(vm, html, /* legacy */ true);
5179
+ }
5092
5180
  // Evaluate, create stylesheet and cache the produced VNode for future
5093
5181
  // re-rendering.
5094
5182
  const stylesheetsContent = getStylesheetsContent(vm, html);
@@ -5426,6 +5514,9 @@ function createVM(elm, ctor, renderer, options) {
5426
5514
  stylesheetToken: undefined,
5427
5515
  hasTokenInClass: undefined,
5428
5516
  hasTokenInAttribute: undefined,
5517
+ legacyStylesheetToken: undefined,
5518
+ hasLegacyTokenInClass: undefined,
5519
+ hasLegacyTokenInAttribute: undefined,
5429
5520
  hasScopedStyles: undefined,
5430
5521
  styleVNodes: null,
5431
5522
  tplCache: EmptyObject,
@@ -6446,7 +6537,8 @@ function validateClassAttr(vnode, elm, renderer) {
6446
6537
  const { data, owner } = vnode;
6447
6538
  let { className, classMap } = data;
6448
6539
  const { getProperty, getClassList, getAttribute } = renderer;
6449
- const scopedToken = getScopeTokenClass(owner);
6540
+ // we don't care about legacy for hydration. it's a new use case
6541
+ const scopedToken = getScopeTokenClass(owner, /* legacy */ false);
6450
6542
  const stylesheetTokenHost = isVCustomElement(vnode) ? getStylesheetTokenHost(vnode) : null;
6451
6543
  // Classnames for scoped CSS are added directly to the DOM during rendering,
6452
6544
  // or to the VDOM on the server in the case of SSR. As such, these classnames
@@ -6856,5 +6948,5 @@ function readonly(obj) {
6856
6948
  }
6857
6949
 
6858
6950
  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 */
6951
+ /** version: 3.4.0 */
6860
6952
  //# sourceMappingURL=index.js.map