@lwc/engine-core 2.35.2 → 2.37.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.
@@ -33,7 +33,6 @@ if (process.env.NODE_ENV === 'test-karma-lwc') {
33
33
  * SPDX-License-Identifier: MIT
34
34
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
35
35
  */
36
- /** Callbacks to invoke when reporting is enabled **/
37
36
  const onReportingEnabledCallbacks = [];
38
37
  /** The currently assigned reporting dispatcher. */
39
38
  let currentDispatcher$1 = shared.noop;
@@ -91,11 +90,11 @@ function onReportingEnabled(callback) {
91
90
  /**
92
91
  * Report to the current dispatcher, if there is one.
93
92
  * @param reportingEventId
94
- * @param vm
93
+ * @param payload - data to report
95
94
  */
96
- function report(reportingEventId, vm) {
95
+ function report(reportingEventId, payload) {
97
96
  if (enabled$1) {
98
- currentDispatcher$1(reportingEventId, vm.tagName, vm.idx);
97
+ currentDispatcher$1(reportingEventId, payload);
99
98
  }
100
99
  }
101
100
 
@@ -384,7 +383,7 @@ function parseStyleText(cssText) {
384
383
  // Make a shallow copy of an object but omit the given key
385
384
  function cloneAndOmitKey(object, keyToOmit) {
386
385
  const result = {};
387
- for (const key of Object.keys(object)) {
386
+ for (const key of shared.keys(object)) {
388
387
  if (key !== keyToOmit) {
389
388
  result[key] = object[key];
390
389
  }
@@ -394,7 +393,7 @@ function cloneAndOmitKey(object, keyToOmit) {
394
393
  function flattenStylesheets(stylesheets) {
395
394
  const list = [];
396
395
  for (const stylesheet of stylesheets) {
397
- if (!Array.isArray(stylesheet)) {
396
+ if (!shared.isArray(stylesheet)) {
398
397
  list.push(stylesheet);
399
398
  }
400
399
  else {
@@ -2673,6 +2672,10 @@ function checkVersionMismatch(func, type) {
2673
2672
  // stylesheets and templates do not have user-meaningful names, but components do
2674
2673
  const friendlyName = type === 'component' ? `${type} ${func.name}` : type;
2675
2674
  logError(`LWC WARNING: current engine is v${shared.LWC_VERSION}, but ${friendlyName} was compiled with v${version}.\nPlease update your compiled code or LWC engine so that the versions match.\nNo further warnings will appear.`);
2675
+ report(1 /* ReportingEventId.CompilerRuntimeVersionMismatch */, {
2676
+ compilerVersion: version,
2677
+ runtimeVersion: shared.LWC_VERSION,
2678
+ });
2676
2679
  }
2677
2680
  }
2678
2681
  }
@@ -4412,7 +4415,12 @@ function allocateInSlot(vm, children, owner) {
4412
4415
  } else if (isVScopedSlotFragment(vnode)) {
4413
4416
  slotName = vnode.slotName;
4414
4417
  }
4415
- const vnodes = cmpSlotsMapping[slotName] = cmpSlotsMapping[slotName] || [];
4418
+ // Can't use toString here because Symbol(1).toString() is 'Symbol(1)'
4419
+ // but elm.setAttribute('slot', Symbol(1)) is an error.
4420
+ // the following line also throws same error for symbols
4421
+ // Similar for Object.create(null)
4422
+ const normalizedSlotName = '' + slotName;
4423
+ const vnodes = cmpSlotsMapping[normalizedSlotName] = cmpSlotsMapping[normalizedSlotName] || [];
4416
4424
  shared.ArrayPush.call(vnodes, vnode);
4417
4425
  }
4418
4426
  vm.cmpSlots = {
@@ -5478,6 +5486,8 @@ function registerComponent(
5478
5486
  Ctor, { tmpl }) {
5479
5487
  if (shared.isFunction(Ctor)) {
5480
5488
  if (process.env.NODE_ENV !== 'production') {
5489
+ // There is no point in running this in production, because the version mismatch check relies
5490
+ // on code comments which are stripped out in production by minifiers
5481
5491
  checkVersionMismatch(Ctor, 'component');
5482
5492
  }
5483
5493
  signedTemplateMap.set(Ctor, tmpl);
@@ -5742,20 +5752,37 @@ function validateComponentStylesheets(vm, stylesheets) {
5742
5752
  }
5743
5753
  // Validate and flatten any stylesheets defined as `static stylesheets`
5744
5754
  function computeStylesheets(vm, ctor) {
5745
- if (features.lwcRuntimeFlags.ENABLE_PROGRAMMATIC_STYLESHEETS) {
5746
- const {
5755
+ warnOnStylesheetsMutation(ctor);
5756
+ const {
5757
+ stylesheets
5758
+ } = ctor;
5759
+ if (!shared.isUndefined(stylesheets)) {
5760
+ const valid = validateComponentStylesheets(vm, stylesheets);
5761
+ if (valid) {
5762
+ return flattenStylesheets(stylesheets);
5763
+ } else if (process.env.NODE_ENV !== 'production') {
5764
+ logError(`static stylesheets must be an array of CSS stylesheets. Found invalid stylesheets on <${vm.tagName}>`, vm);
5765
+ }
5766
+ }
5767
+ return null;
5768
+ }
5769
+ function warnOnStylesheetsMutation(ctor) {
5770
+ if (process.env.NODE_ENV !== 'production') {
5771
+ let {
5747
5772
  stylesheets
5748
5773
  } = ctor;
5749
- if (!shared.isUndefined(stylesheets)) {
5750
- const valid = validateComponentStylesheets(vm, stylesheets);
5751
- if (valid) {
5752
- return flattenStylesheets(stylesheets);
5753
- } else if (process.env.NODE_ENV !== 'production') {
5754
- logError(`static stylesheets must be an array of CSS stylesheets. Found invalid stylesheets on <${vm.tagName}>`, vm);
5774
+ shared.defineProperty(ctor, 'stylesheets', {
5775
+ enumerable: true,
5776
+ configurable: true,
5777
+ get() {
5778
+ return stylesheets;
5779
+ },
5780
+ set(newValue) {
5781
+ logWarnOnce(`Dynamically setting the "stylesheets" static property on ${ctor.name} ` + 'will not affect the stylesheets injected.');
5782
+ stylesheets = newValue;
5755
5783
  }
5756
- }
5784
+ });
5757
5785
  }
5758
- return null;
5759
5786
  }
5760
5787
  function computeShadowMode(vm, renderer) {
5761
5788
  const {
@@ -6131,7 +6158,7 @@ function forceRehydration(vm) {
6131
6158
  // The goal of this code is to detect invalid cross-root ARIA references in synthetic shadow DOM.
6132
6159
  // These invalid references should be fixed before the offending components can be migrated to native shadow DOM.
6133
6160
  // When invalid usage is detected, we warn in dev mode and call the reporting API if enabled.
6134
- // See: https://lwc.dev/guide/accessibility#link-ids-and-aria-attributes-from-different-templates
6161
+ // See: https://sfdc.co/synthetic-aria
6135
6162
  //
6136
6163
  // Use the unpatched native getElementById/querySelectorAll rather than the synthetic one
6137
6164
  const getElementById = shared.globalThis[shared.KEY__NATIVE_GET_ELEMENT_BY_ID];
@@ -6139,7 +6166,7 @@ const querySelectorAll = shared.globalThis[shared.KEY__NATIVE_QUERY_SELECTOR_ALL
6139
6166
  function isSyntheticShadowRootInstance(rootNode) {
6140
6167
  return rootNode !== document && shared.isTrue(rootNode.synthetic);
6141
6168
  }
6142
- function reportViolation(source, target, attrName) {
6169
+ function reportViolation$1(source, target, attrName) {
6143
6170
  // The vm is either for the source, the target, or both. Either one or both must be using synthetic
6144
6171
  // shadow for a violation to be detected.
6145
6172
  let vm = getAssociatedVMIfPresent(source.getRootNode().host);
@@ -6150,12 +6177,15 @@ function reportViolation(source, target, attrName) {
6150
6177
  // vm should never be undefined here, but just to be safe, bail out and don't report
6151
6178
  return;
6152
6179
  }
6153
- report(0 /* ReportingEventId.CrossRootAriaInSyntheticShadow */, vm);
6180
+ report(0 /* ReportingEventId.CrossRootAriaInSyntheticShadow */, {
6181
+ tagName: vm.tagName,
6182
+ attributeName: attrName,
6183
+ });
6154
6184
  if (process.env.NODE_ENV !== 'production') {
6155
6185
  // Avoid excessively logging to the console in the case of duplicates.
6156
6186
  logWarnOnce(`Element <${source.tagName.toLowerCase()}> uses attribute "${attrName}" to reference element ` +
6157
6187
  `<${target.tagName.toLowerCase()}>, which is not in the same shadow root. This will break in native shadow DOM. ` +
6158
- `For details, see: https://lwc.dev/guide/accessibility#link-ids-and-aria-attributes-from-different-templates`, vm);
6188
+ `For details, see: https://sfdc.co/synthetic-aria`, vm);
6159
6189
  }
6160
6190
  }
6161
6191
  function parseIdRefAttributeValue(attrValue) {
@@ -6182,7 +6212,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6182
6212
  const sourceElement = sourceElements[i];
6183
6213
  const sourceRoot = sourceElement.getRootNode();
6184
6214
  if (sourceRoot !== root) {
6185
- reportViolation(sourceElement, elm, idRefAttrName);
6215
+ reportViolation$1(sourceElement, elm, idRefAttrName);
6186
6216
  break;
6187
6217
  }
6188
6218
  }
@@ -6197,7 +6227,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6197
6227
  const targetRoot = target.getRootNode();
6198
6228
  if (targetRoot !== root) {
6199
6229
  // target element's shadow root is not the same as ours
6200
- reportViolation(elm, target, attrName);
6230
+ reportViolation$1(elm, target, attrName);
6201
6231
  }
6202
6232
  }
6203
6233
  }
@@ -6206,7 +6236,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6206
6236
  let enabled = false;
6207
6237
  // We want to avoid patching globals whenever possible, so this should be tree-shaken out in prod-mode and if
6208
6238
  // reporting is not enabled. It should also only run once
6209
- function enableDetection() {
6239
+ function enableDetection$1() {
6210
6240
  if (enabled) {
6211
6241
  return; // don't double-apply the patches
6212
6242
  }
@@ -6258,12 +6288,110 @@ function isSyntheticShadowLoaded() {
6258
6288
  if (process.env.IS_BROWSER && supportsCssEscape() && isSyntheticShadowLoaded()) {
6259
6289
  // Always run detection in dev mode, so we can at least print to the console
6260
6290
  if (process.env.NODE_ENV !== 'production') {
6261
- enableDetection();
6291
+ enableDetection$1();
6262
6292
  }
6263
6293
  else {
6264
6294
  // In prod mode, only enable detection if reporting is enabled
6265
- onReportingEnabled(enableDetection);
6295
+ onReportingEnabled(enableDetection$1);
6296
+ }
6297
+ }
6298
+
6299
+ /*
6300
+ * Copyright (c) 2018, salesforce.com, inc.
6301
+ * All rights reserved.
6302
+ * SPDX-License-Identifier: MIT
6303
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6304
+ */
6305
+ //
6306
+ // The goal of this code is to detect usages of non-standard reflected ARIA properties. These are caused by
6307
+ // legacy non-standard Element.prototype extensions added by the @lwc/aria-reflection package.
6308
+ //
6309
+ // See the README for @lwc/aria-reflection
6310
+ const NON_STANDARD_ARIA_PROPS = ['ariaActiveDescendant', 'ariaControls', 'ariaDescribedBy', 'ariaDetails', 'ariaErrorMessage', 'ariaFlowTo', 'ariaLabelledBy', 'ariaOwns'];
6311
+ function isLightningElement(elm) {
6312
+ // The former case is for `this.prop` (inside component) and the latter is for `element.prop` (outside component).
6313
+ // In both cases, we apply the non-standard prop even when the global polyfill is disabled, so this is kosher.
6314
+ return elm instanceof LightningElement || elm instanceof BaseBridgeElement;
6315
+ }
6316
+ function findVM(elm) {
6317
+ // If it's a shadow DOM component, then it has a host
6318
+ const {
6319
+ host
6320
+ } = elm.getRootNode();
6321
+ const vm = shared.isUndefined(host) ? undefined : getAssociatedVMIfPresent(host);
6322
+ if (!shared.isUndefined(vm)) {
6323
+ return vm;
6324
+ }
6325
+ // Else it might be a light DOM component. Walk up the tree trying to find the owner
6326
+ let parentElement = elm;
6327
+ while (!shared.isNull(parentElement = parentElement.parentElement)) {
6328
+ if (isLightningElement(parentElement)) {
6329
+ const vm = getAssociatedVMIfPresent(parentElement);
6330
+ if (!shared.isUndefined(vm)) {
6331
+ return vm;
6332
+ }
6333
+ }
6334
+ }
6335
+ // If we return undefined, it's because the element was rendered wholly outside a LightningElement
6336
+ }
6337
+
6338
+ function checkAndReportViolation(elm, prop) {
6339
+ if (!isLightningElement(elm)) {
6340
+ const vm = findVM(elm);
6341
+ if (process.env.NODE_ENV !== 'production') {
6342
+ logWarnOnce(`Element <${elm.tagName.toLowerCase()}> ` + (shared.isUndefined(vm) ? '' : `owned by <${vm.elm.tagName.toLowerCase()}> `) + `uses non-standard property "${prop}". This will be removed in a future version of LWC. ` + `See https://sfdc.co/deprecated-aria`);
6343
+ }
6344
+ report(2 /* ReportingEventId.NonStandardAriaReflection */, {
6345
+ tagName: vm === null || vm === void 0 ? void 0 : vm.tagName,
6346
+ propertyName: prop
6347
+ });
6348
+ }
6349
+ }
6350
+ function enableDetection() {
6351
+ const {
6352
+ prototype
6353
+ } = Element;
6354
+ for (const prop of NON_STANDARD_ARIA_PROPS) {
6355
+ const descriptor = shared.getOwnPropertyDescriptor(prototype, prop);
6356
+ // The descriptor should exist because the @lwc/aria-reflection polyfill has run by now.
6357
+ // This happens automatically because of the ordering of imports.
6358
+ if (process.env.NODE_ENV !== 'production') {
6359
+ /* istanbul ignore if */
6360
+ if (shared.isUndefined(descriptor) || shared.isUndefined(descriptor.get) || shared.isUndefined(descriptor.set)) {
6361
+ // should never happen
6362
+ throw new Error('detect-non-standard-aria.ts loaded before @lwc/aria-reflection');
6363
+ }
6364
+ }
6365
+ // @ts-ignore
6366
+ const {
6367
+ get,
6368
+ set
6369
+ } = descriptor;
6370
+ shared.defineProperty(prototype, prop, {
6371
+ get() {
6372
+ checkAndReportViolation(this, prop);
6373
+ return get.call(this);
6374
+ },
6375
+ set(val) {
6376
+ checkAndReportViolation(this, prop);
6377
+ return set.call(this, val);
6378
+ },
6379
+ configurable: true,
6380
+ enumerable: true
6381
+ });
6382
+ }
6383
+ }
6384
+ // No point in running this code if we're not in a browser, or if the global polyfill is not loaded
6385
+ if (process.env.IS_BROWSER) {
6386
+ if (!features.lwcRuntimeFlags.DISABLE_ARIA_REFLECTION_POLYFILL) {
6387
+ // Always run detection in dev mode, so we can at least print to the console
6388
+ if (process.env.NODE_ENV !== 'production') {
6389
+ enableDetection();
6390
+ } else {
6391
+ // In prod mode, only enable detection if reporting is enabled
6392
+ onReportingEnabled(enableDetection);
6266
6393
  }
6394
+ }
6267
6395
  }
6268
6396
 
6269
6397
  /*
@@ -6750,12 +6878,13 @@ function setHooks(hooks) {
6750
6878
  */
6751
6879
  // See @lwc/engine-core/src/framework/template.ts
6752
6880
  const TEMPLATE_PROPS = ['slots', 'stylesheetToken', 'stylesheets', 'renderMode'];
6753
- // Via https://www.npmjs.com/package/object-observer
6754
- const ARRAY_MUTATION_METHODS = ['pop', 'push', 'shift', 'unshift', 'reverse', 'sort', 'fill', 'splice', 'copyWithin'];
6755
6881
  // Expandos that may be placed on a stylesheet factory function, and which are meaningful to LWC at runtime
6756
- const STYLESHEET_FUNCTION_EXPANDOS = [
6882
+ const STYLESHEET_PROPS = [
6757
6883
  // SEE `KEY__SCOPED_CSS` in @lwc/style-compiler
6758
6884
  '$scoped$'];
6885
+ // Via https://www.npmjs.com/package/object-observer
6886
+ const ARRAY_MUTATION_METHODS = ['pop', 'push', 'shift', 'unshift', 'reverse', 'sort', 'fill', 'splice', 'copyWithin'];
6887
+ let mutationTrackingDisabled = false;
6759
6888
  function getOriginalArrayMethod(prop) {
6760
6889
  switch (prop) {
6761
6890
  case 'pop':
@@ -6778,7 +6907,20 @@ function getOriginalArrayMethod(prop) {
6778
6907
  return shared.ArrayCopyWithin;
6779
6908
  }
6780
6909
  }
6781
- let mutationWarningsSilenced = false;
6910
+ function reportViolation(type, eventId, prop) {
6911
+ if (process.env.NODE_ENV !== 'production') {
6912
+ logWarnOnce(`Mutating the "${prop}" property on a ${type} ` + `is deprecated and will be removed in a future version of LWC. ` + `See: https://sfdc.co/template-mutation`);
6913
+ }
6914
+ report(eventId, {
6915
+ propertyName: prop
6916
+ });
6917
+ }
6918
+ function reportTemplateViolation(prop) {
6919
+ reportViolation('template', 3 /* ReportingEventId.TemplateMutation */, prop);
6920
+ }
6921
+ function reportStylesheetViolation(prop) {
6922
+ reportViolation('stylesheet', 4 /* ReportingEventId.StylesheetMutation */, prop);
6923
+ }
6782
6924
  // Warn if the user tries to mutate a stylesheets array, e.g.:
6783
6925
  // `tmpl.stylesheets.push(someStylesheetFunction)`
6784
6926
  function warnOnArrayMutation(stylesheets) {
@@ -6787,7 +6929,7 @@ function warnOnArrayMutation(stylesheets) {
6787
6929
  for (const prop of ARRAY_MUTATION_METHODS) {
6788
6930
  const originalArrayMethod = getOriginalArrayMethod(prop);
6789
6931
  stylesheets[prop] = function arrayMutationWarningWrapper() {
6790
- logError(`Mutating the "stylesheets" array on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6932
+ reportTemplateViolation('stylesheets');
6791
6933
  // @ts-ignore
6792
6934
  return originalArrayMethod.apply(this, arguments);
6793
6935
  };
@@ -6796,8 +6938,7 @@ function warnOnArrayMutation(stylesheets) {
6796
6938
  // Warn if the user tries to mutate a stylesheet factory function, e.g.:
6797
6939
  // `stylesheet.$scoped$ = true`
6798
6940
  function warnOnStylesheetFunctionMutation(stylesheet) {
6799
- // We could warn on other properties, but in practice only certain expandos are meaningful to LWC at runtime
6800
- for (const prop of STYLESHEET_FUNCTION_EXPANDOS) {
6941
+ for (const prop of STYLESHEET_PROPS) {
6801
6942
  let value = stylesheet[prop];
6802
6943
  shared.defineProperty(stylesheet, prop, {
6803
6944
  enumerable: true,
@@ -6806,14 +6947,14 @@ function warnOnStylesheetFunctionMutation(stylesheet) {
6806
6947
  return value;
6807
6948
  },
6808
6949
  set(newValue) {
6809
- logError(`Dynamically setting the "${prop}" property on a stylesheet function ` + `is deprecated and may be removed in a future version of LWC.`);
6950
+ reportStylesheetViolation(prop);
6810
6951
  value = newValue;
6811
6952
  }
6812
6953
  });
6813
6954
  }
6814
6955
  }
6815
6956
  // Warn on either array or stylesheet (function) mutation, in a deeply-nested array
6816
- function warnOnStylesheetsMutation(stylesheets) {
6957
+ function trackStylesheetsMutation(stylesheets) {
6817
6958
  traverseStylesheets(stylesheets, subStylesheets => {
6818
6959
  if (shared.isArray(subStylesheets)) {
6819
6960
  warnOnArrayMutation(subStylesheets);
@@ -6840,7 +6981,70 @@ function traverseStylesheets(stylesheets, callback) {
6840
6981
  }
6841
6982
  }
6842
6983
  }
6984
+ function trackMutations(tmpl) {
6985
+ if (!shared.isUndefined(tmpl.stylesheets)) {
6986
+ trackStylesheetsMutation(tmpl.stylesheets);
6987
+ }
6988
+ for (const prop of TEMPLATE_PROPS) {
6989
+ let value = tmpl[prop];
6990
+ shared.defineProperty(tmpl, prop, {
6991
+ enumerable: true,
6992
+ configurable: true,
6993
+ get() {
6994
+ return value;
6995
+ },
6996
+ set(newValue) {
6997
+ if (!mutationTrackingDisabled) {
6998
+ reportTemplateViolation(prop);
6999
+ }
7000
+ value = newValue;
7001
+ }
7002
+ });
7003
+ }
7004
+ const originalDescriptor = shared.getOwnPropertyDescriptor(tmpl, 'stylesheetTokens');
7005
+ shared.defineProperty(tmpl, 'stylesheetTokens', {
7006
+ enumerable: true,
7007
+ configurable: true,
7008
+ get: originalDescriptor.get,
7009
+ set(value) {
7010
+ reportTemplateViolation('stylesheetTokens');
7011
+ // Avoid logging/reporting twice (for both stylesheetToken and stylesheetTokens)
7012
+ mutationTrackingDisabled = true;
7013
+ originalDescriptor.set.call(this, value);
7014
+ mutationTrackingDisabled = false;
7015
+ }
7016
+ });
7017
+ }
7018
+ function addLegacyStylesheetTokensShim(tmpl) {
7019
+ // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
7020
+ // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
7021
+ shared.defineProperty(tmpl, 'stylesheetTokens', {
7022
+ enumerable: true,
7023
+ configurable: true,
7024
+ get() {
7025
+ const {
7026
+ stylesheetToken
7027
+ } = this;
7028
+ if (shared.isUndefined(stylesheetToken)) {
7029
+ return stylesheetToken;
7030
+ }
7031
+ // Shim for the old `stylesheetTokens` property
7032
+ // See https://github.com/salesforce/lwc/pull/2332/files#diff-7901555acef29969adaa6583185b3e9bce475cdc6f23e799a54e0018cb18abaa
7033
+ return {
7034
+ hostAttribute: `${stylesheetToken}-host`,
7035
+ shadowAttribute: stylesheetToken
7036
+ };
7037
+ },
7038
+ set(value) {
7039
+ // If the value is null or some other exotic object, you would be broken anyway in the past
7040
+ // because the engine would try to access hostAttribute/shadowAttribute, which would throw an error.
7041
+ // However it may be undefined in newer versions of LWC, so we need to guard against that case.
7042
+ this.stylesheetToken = shared.isUndefined(value) ? undefined : value.shadowAttribute;
7043
+ }
7044
+ });
7045
+ }
6843
7046
  function freezeTemplate(tmpl) {
7047
+ // TODO [#2782]: remove this flag and delete the legacy behavior
6844
7048
  if (features.lwcRuntimeFlags.ENABLE_FROZEN_TEMPLATE) {
6845
7049
  // Deep freeze the template
6846
7050
  shared.freeze(tmpl);
@@ -6848,66 +7052,16 @@ function freezeTemplate(tmpl) {
6848
7052
  deepFreeze(tmpl.stylesheets);
6849
7053
  }
6850
7054
  } else {
6851
- // TODO [#2782]: remove this flag and delete the legacy behavior
6852
- // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
6853
- // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
6854
- shared.defineProperty(tmpl, 'stylesheetTokens', {
6855
- enumerable: true,
6856
- configurable: true,
6857
- get() {
6858
- const {
6859
- stylesheetToken
6860
- } = this;
6861
- if (shared.isUndefined(stylesheetToken)) {
6862
- return stylesheetToken;
6863
- }
6864
- // Shim for the old `stylesheetTokens` property
6865
- // See https://github.com/salesforce/lwc/pull/2332/files#diff-7901555acef29969adaa6583185b3e9bce475cdc6f23e799a54e0018cb18abaa
6866
- return {
6867
- hostAttribute: `${stylesheetToken}-host`,
6868
- shadowAttribute: stylesheetToken
6869
- };
6870
- },
6871
- set(value) {
6872
- // If the value is null or some other exotic object, you would be broken anyway in the past
6873
- // because the engine would try to access hostAttribute/shadowAttribute, which would throw an error.
6874
- // However it may be undefined in newer versions of LWC, so we need to guard against that case.
6875
- this.stylesheetToken = shared.isUndefined(value) ? undefined : value.shadowAttribute;
6876
- }
6877
- });
6878
- // When ENABLE_FROZEN_TEMPLATE is false, warn in dev mode whenever someone is mutating the template
7055
+ // template is not frozen - shim, report, and warn
7056
+ // this shim should be applied in both dev and prod
7057
+ addLegacyStylesheetTokensShim(tmpl);
7058
+ // When ENABLE_FROZEN_TEMPLATE is false, we want to warn in dev mode whenever someone is mutating the template
6879
7059
  if (process.env.NODE_ENV !== 'production') {
6880
- if (!shared.isUndefined(tmpl.stylesheets)) {
6881
- warnOnStylesheetsMutation(tmpl.stylesheets);
6882
- }
6883
- for (const prop of TEMPLATE_PROPS) {
6884
- let value = tmpl[prop];
6885
- shared.defineProperty(tmpl, prop, {
6886
- enumerable: true,
6887
- configurable: true,
6888
- get() {
6889
- return value;
6890
- },
6891
- set(newValue) {
6892
- if (!mutationWarningsSilenced) {
6893
- logError(`Dynamically setting the "${prop}" property on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6894
- }
6895
- value = newValue;
6896
- }
6897
- });
6898
- }
6899
- const originalDescriptor = shared.getOwnPropertyDescriptor(tmpl, 'stylesheetTokens');
6900
- shared.defineProperty(tmpl, 'stylesheetTokens', {
6901
- enumerable: true,
6902
- configurable: true,
6903
- get: originalDescriptor.get,
6904
- set(value) {
6905
- logError(`Dynamically setting the "stylesheetTokens" property on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6906
- // Avoid logging twice (for both stylesheetToken and stylesheetTokens)
6907
- mutationWarningsSilenced = true;
6908
- originalDescriptor.set.call(this, value);
6909
- mutationWarningsSilenced = false;
6910
- }
7060
+ trackMutations(tmpl);
7061
+ } else {
7062
+ // In prod mode, we only track mutations if reporting is enabled
7063
+ onReportingEnabled(() => {
7064
+ trackMutations(tmpl);
6911
7065
  });
6912
7066
  }
6913
7067
  }
@@ -6974,4 +7128,4 @@ exports.swapTemplate = swapTemplate;
6974
7128
  exports.track = track;
6975
7129
  exports.unwrap = unwrap;
6976
7130
  exports.wire = wire;
6977
- /* version: 2.35.2 */
7131
+ /* version: 2.37.0 */
@@ -1,7 +1,7 @@
1
1
  /* proxy-compat-disable */
2
2
  import { lwcRuntimeFlags } from '@lwc/features';
3
3
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
4
- import { noop, StringToLowerCase, isNull, ArrayPush as ArrayPush$1, ArrayJoin, isFrozen, isUndefined as isUndefined$1, defineProperty, ArrayIndexOf, ArraySplice, create, seal, isFunction as isFunction$1, hasOwnProperty as hasOwnProperty$1, forEach, keys, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, htmlPropertyToAttribute, ArraySlice, ArrayMap, isArray as isArray$1, KEY__SCOPED_CSS, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, htmlAttributeToProperty, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, ArrayUnshift, globalThis as globalThis$1, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, 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, forEach, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, assign, isObject, assert, freeze, KEY__SYNTHETIC_MODE, toString as toString$1, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, isFalse, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, htmlPropertyToAttribute, ArraySlice, ArrayMap, KEY__SCOPED_CSS, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, htmlAttributeToProperty, isString, StringSlice, isTrue, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, ArraySome, ArrayPop, isNumber, StringReplace, ArrayUnshift, globalThis as globalThis$1, KEY__NATIVE_GET_ELEMENT_BY_ID, KEY__NATIVE_QUERY_SELECTOR_ALL, ID_REFERENCING_ATTRIBUTES_SET, KEY__SHADOW_TOKEN, ArrayFilter, StringSplit, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift } from '@lwc/shared';
5
5
  import { applyAriaReflection } from '@lwc/aria-reflection';
6
6
 
7
7
  /*
@@ -32,7 +32,6 @@ if (process.env.NODE_ENV === 'test-karma-lwc') {
32
32
  * SPDX-License-Identifier: MIT
33
33
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
34
34
  */
35
- /** Callbacks to invoke when reporting is enabled **/
36
35
  const onReportingEnabledCallbacks = [];
37
36
  /** The currently assigned reporting dispatcher. */
38
37
  let currentDispatcher$1 = noop;
@@ -90,11 +89,11 @@ function onReportingEnabled(callback) {
90
89
  /**
91
90
  * Report to the current dispatcher, if there is one.
92
91
  * @param reportingEventId
93
- * @param vm
92
+ * @param payload - data to report
94
93
  */
95
- function report(reportingEventId, vm) {
94
+ function report(reportingEventId, payload) {
96
95
  if (enabled$1) {
97
- currentDispatcher$1(reportingEventId, vm.tagName, vm.idx);
96
+ currentDispatcher$1(reportingEventId, payload);
98
97
  }
99
98
  }
100
99
 
@@ -383,7 +382,7 @@ function parseStyleText(cssText) {
383
382
  // Make a shallow copy of an object but omit the given key
384
383
  function cloneAndOmitKey(object, keyToOmit) {
385
384
  const result = {};
386
- for (const key of Object.keys(object)) {
385
+ for (const key of keys(object)) {
387
386
  if (key !== keyToOmit) {
388
387
  result[key] = object[key];
389
388
  }
@@ -393,7 +392,7 @@ function cloneAndOmitKey(object, keyToOmit) {
393
392
  function flattenStylesheets(stylesheets) {
394
393
  const list = [];
395
394
  for (const stylesheet of stylesheets) {
396
- if (!Array.isArray(stylesheet)) {
395
+ if (!isArray$1(stylesheet)) {
397
396
  list.push(stylesheet);
398
397
  }
399
398
  else {
@@ -2672,6 +2671,10 @@ function checkVersionMismatch(func, type) {
2672
2671
  // stylesheets and templates do not have user-meaningful names, but components do
2673
2672
  const friendlyName = type === 'component' ? `${type} ${func.name}` : type;
2674
2673
  logError(`LWC WARNING: current engine is v${LWC_VERSION}, but ${friendlyName} was compiled with v${version}.\nPlease update your compiled code or LWC engine so that the versions match.\nNo further warnings will appear.`);
2674
+ report(1 /* ReportingEventId.CompilerRuntimeVersionMismatch */, {
2675
+ compilerVersion: version,
2676
+ runtimeVersion: LWC_VERSION,
2677
+ });
2675
2678
  }
2676
2679
  }
2677
2680
  }
@@ -4411,7 +4414,12 @@ function allocateInSlot(vm, children, owner) {
4411
4414
  } else if (isVScopedSlotFragment(vnode)) {
4412
4415
  slotName = vnode.slotName;
4413
4416
  }
4414
- const vnodes = cmpSlotsMapping[slotName] = cmpSlotsMapping[slotName] || [];
4417
+ // Can't use toString here because Symbol(1).toString() is 'Symbol(1)'
4418
+ // but elm.setAttribute('slot', Symbol(1)) is an error.
4419
+ // the following line also throws same error for symbols
4420
+ // Similar for Object.create(null)
4421
+ const normalizedSlotName = '' + slotName;
4422
+ const vnodes = cmpSlotsMapping[normalizedSlotName] = cmpSlotsMapping[normalizedSlotName] || [];
4415
4423
  ArrayPush$1.call(vnodes, vnode);
4416
4424
  }
4417
4425
  vm.cmpSlots = {
@@ -5477,6 +5485,8 @@ function registerComponent(
5477
5485
  Ctor, { tmpl }) {
5478
5486
  if (isFunction$1(Ctor)) {
5479
5487
  if (process.env.NODE_ENV !== 'production') {
5488
+ // There is no point in running this in production, because the version mismatch check relies
5489
+ // on code comments which are stripped out in production by minifiers
5480
5490
  checkVersionMismatch(Ctor, 'component');
5481
5491
  }
5482
5492
  signedTemplateMap.set(Ctor, tmpl);
@@ -5741,20 +5751,37 @@ function validateComponentStylesheets(vm, stylesheets) {
5741
5751
  }
5742
5752
  // Validate and flatten any stylesheets defined as `static stylesheets`
5743
5753
  function computeStylesheets(vm, ctor) {
5744
- if (lwcRuntimeFlags.ENABLE_PROGRAMMATIC_STYLESHEETS) {
5745
- const {
5754
+ warnOnStylesheetsMutation(ctor);
5755
+ const {
5756
+ stylesheets
5757
+ } = ctor;
5758
+ if (!isUndefined$1(stylesheets)) {
5759
+ const valid = validateComponentStylesheets(vm, stylesheets);
5760
+ if (valid) {
5761
+ return flattenStylesheets(stylesheets);
5762
+ } else if (process.env.NODE_ENV !== 'production') {
5763
+ logError(`static stylesheets must be an array of CSS stylesheets. Found invalid stylesheets on <${vm.tagName}>`, vm);
5764
+ }
5765
+ }
5766
+ return null;
5767
+ }
5768
+ function warnOnStylesheetsMutation(ctor) {
5769
+ if (process.env.NODE_ENV !== 'production') {
5770
+ let {
5746
5771
  stylesheets
5747
5772
  } = ctor;
5748
- if (!isUndefined$1(stylesheets)) {
5749
- const valid = validateComponentStylesheets(vm, stylesheets);
5750
- if (valid) {
5751
- return flattenStylesheets(stylesheets);
5752
- } else if (process.env.NODE_ENV !== 'production') {
5753
- logError(`static stylesheets must be an array of CSS stylesheets. Found invalid stylesheets on <${vm.tagName}>`, vm);
5773
+ defineProperty(ctor, 'stylesheets', {
5774
+ enumerable: true,
5775
+ configurable: true,
5776
+ get() {
5777
+ return stylesheets;
5778
+ },
5779
+ set(newValue) {
5780
+ logWarnOnce(`Dynamically setting the "stylesheets" static property on ${ctor.name} ` + 'will not affect the stylesheets injected.');
5781
+ stylesheets = newValue;
5754
5782
  }
5755
- }
5783
+ });
5756
5784
  }
5757
- return null;
5758
5785
  }
5759
5786
  function computeShadowMode(vm, renderer) {
5760
5787
  const {
@@ -6130,7 +6157,7 @@ function forceRehydration(vm) {
6130
6157
  // The goal of this code is to detect invalid cross-root ARIA references in synthetic shadow DOM.
6131
6158
  // These invalid references should be fixed before the offending components can be migrated to native shadow DOM.
6132
6159
  // When invalid usage is detected, we warn in dev mode and call the reporting API if enabled.
6133
- // See: https://lwc.dev/guide/accessibility#link-ids-and-aria-attributes-from-different-templates
6160
+ // See: https://sfdc.co/synthetic-aria
6134
6161
  //
6135
6162
  // Use the unpatched native getElementById/querySelectorAll rather than the synthetic one
6136
6163
  const getElementById = globalThis$1[KEY__NATIVE_GET_ELEMENT_BY_ID];
@@ -6138,7 +6165,7 @@ const querySelectorAll = globalThis$1[KEY__NATIVE_QUERY_SELECTOR_ALL];
6138
6165
  function isSyntheticShadowRootInstance(rootNode) {
6139
6166
  return rootNode !== document && isTrue(rootNode.synthetic);
6140
6167
  }
6141
- function reportViolation(source, target, attrName) {
6168
+ function reportViolation$1(source, target, attrName) {
6142
6169
  // The vm is either for the source, the target, or both. Either one or both must be using synthetic
6143
6170
  // shadow for a violation to be detected.
6144
6171
  let vm = getAssociatedVMIfPresent(source.getRootNode().host);
@@ -6149,12 +6176,15 @@ function reportViolation(source, target, attrName) {
6149
6176
  // vm should never be undefined here, but just to be safe, bail out and don't report
6150
6177
  return;
6151
6178
  }
6152
- report(0 /* ReportingEventId.CrossRootAriaInSyntheticShadow */, vm);
6179
+ report(0 /* ReportingEventId.CrossRootAriaInSyntheticShadow */, {
6180
+ tagName: vm.tagName,
6181
+ attributeName: attrName,
6182
+ });
6153
6183
  if (process.env.NODE_ENV !== 'production') {
6154
6184
  // Avoid excessively logging to the console in the case of duplicates.
6155
6185
  logWarnOnce(`Element <${source.tagName.toLowerCase()}> uses attribute "${attrName}" to reference element ` +
6156
6186
  `<${target.tagName.toLowerCase()}>, which is not in the same shadow root. This will break in native shadow DOM. ` +
6157
- `For details, see: https://lwc.dev/guide/accessibility#link-ids-and-aria-attributes-from-different-templates`, vm);
6187
+ `For details, see: https://sfdc.co/synthetic-aria`, vm);
6158
6188
  }
6159
6189
  }
6160
6190
  function parseIdRefAttributeValue(attrValue) {
@@ -6181,7 +6211,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6181
6211
  const sourceElement = sourceElements[i];
6182
6212
  const sourceRoot = sourceElement.getRootNode();
6183
6213
  if (sourceRoot !== root) {
6184
- reportViolation(sourceElement, elm, idRefAttrName);
6214
+ reportViolation$1(sourceElement, elm, idRefAttrName);
6185
6215
  break;
6186
6216
  }
6187
6217
  }
@@ -6196,7 +6226,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6196
6226
  const targetRoot = target.getRootNode();
6197
6227
  if (targetRoot !== root) {
6198
6228
  // target element's shadow root is not the same as ours
6199
- reportViolation(elm, target, attrName);
6229
+ reportViolation$1(elm, target, attrName);
6200
6230
  }
6201
6231
  }
6202
6232
  }
@@ -6205,7 +6235,7 @@ function detectSyntheticCrossRootAria(elm, attrName, attrValue) {
6205
6235
  let enabled = false;
6206
6236
  // We want to avoid patching globals whenever possible, so this should be tree-shaken out in prod-mode and if
6207
6237
  // reporting is not enabled. It should also only run once
6208
- function enableDetection() {
6238
+ function enableDetection$1() {
6209
6239
  if (enabled) {
6210
6240
  return; // don't double-apply the patches
6211
6241
  }
@@ -6257,12 +6287,110 @@ function isSyntheticShadowLoaded() {
6257
6287
  if (process.env.IS_BROWSER && supportsCssEscape() && isSyntheticShadowLoaded()) {
6258
6288
  // Always run detection in dev mode, so we can at least print to the console
6259
6289
  if (process.env.NODE_ENV !== 'production') {
6260
- enableDetection();
6290
+ enableDetection$1();
6261
6291
  }
6262
6292
  else {
6263
6293
  // In prod mode, only enable detection if reporting is enabled
6264
- onReportingEnabled(enableDetection);
6294
+ onReportingEnabled(enableDetection$1);
6295
+ }
6296
+ }
6297
+
6298
+ /*
6299
+ * Copyright (c) 2018, salesforce.com, inc.
6300
+ * All rights reserved.
6301
+ * SPDX-License-Identifier: MIT
6302
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6303
+ */
6304
+ //
6305
+ // The goal of this code is to detect usages of non-standard reflected ARIA properties. These are caused by
6306
+ // legacy non-standard Element.prototype extensions added by the @lwc/aria-reflection package.
6307
+ //
6308
+ // See the README for @lwc/aria-reflection
6309
+ const NON_STANDARD_ARIA_PROPS = ['ariaActiveDescendant', 'ariaControls', 'ariaDescribedBy', 'ariaDetails', 'ariaErrorMessage', 'ariaFlowTo', 'ariaLabelledBy', 'ariaOwns'];
6310
+ function isLightningElement(elm) {
6311
+ // The former case is for `this.prop` (inside component) and the latter is for `element.prop` (outside component).
6312
+ // In both cases, we apply the non-standard prop even when the global polyfill is disabled, so this is kosher.
6313
+ return elm instanceof LightningElement || elm instanceof BaseBridgeElement;
6314
+ }
6315
+ function findVM(elm) {
6316
+ // If it's a shadow DOM component, then it has a host
6317
+ const {
6318
+ host
6319
+ } = elm.getRootNode();
6320
+ const vm = isUndefined$1(host) ? undefined : getAssociatedVMIfPresent(host);
6321
+ if (!isUndefined$1(vm)) {
6322
+ return vm;
6323
+ }
6324
+ // Else it might be a light DOM component. Walk up the tree trying to find the owner
6325
+ let parentElement = elm;
6326
+ while (!isNull(parentElement = parentElement.parentElement)) {
6327
+ if (isLightningElement(parentElement)) {
6328
+ const vm = getAssociatedVMIfPresent(parentElement);
6329
+ if (!isUndefined$1(vm)) {
6330
+ return vm;
6331
+ }
6332
+ }
6333
+ }
6334
+ // If we return undefined, it's because the element was rendered wholly outside a LightningElement
6335
+ }
6336
+
6337
+ function checkAndReportViolation(elm, prop) {
6338
+ if (!isLightningElement(elm)) {
6339
+ const vm = findVM(elm);
6340
+ if (process.env.NODE_ENV !== 'production') {
6341
+ logWarnOnce(`Element <${elm.tagName.toLowerCase()}> ` + (isUndefined$1(vm) ? '' : `owned by <${vm.elm.tagName.toLowerCase()}> `) + `uses non-standard property "${prop}". This will be removed in a future version of LWC. ` + `See https://sfdc.co/deprecated-aria`);
6342
+ }
6343
+ report(2 /* ReportingEventId.NonStandardAriaReflection */, {
6344
+ tagName: vm === null || vm === void 0 ? void 0 : vm.tagName,
6345
+ propertyName: prop
6346
+ });
6347
+ }
6348
+ }
6349
+ function enableDetection() {
6350
+ const {
6351
+ prototype
6352
+ } = Element;
6353
+ for (const prop of NON_STANDARD_ARIA_PROPS) {
6354
+ const descriptor = getOwnPropertyDescriptor$1(prototype, prop);
6355
+ // The descriptor should exist because the @lwc/aria-reflection polyfill has run by now.
6356
+ // This happens automatically because of the ordering of imports.
6357
+ if (process.env.NODE_ENV !== 'production') {
6358
+ /* istanbul ignore if */
6359
+ if (isUndefined$1(descriptor) || isUndefined$1(descriptor.get) || isUndefined$1(descriptor.set)) {
6360
+ // should never happen
6361
+ throw new Error('detect-non-standard-aria.ts loaded before @lwc/aria-reflection');
6362
+ }
6363
+ }
6364
+ // @ts-ignore
6365
+ const {
6366
+ get,
6367
+ set
6368
+ } = descriptor;
6369
+ defineProperty(prototype, prop, {
6370
+ get() {
6371
+ checkAndReportViolation(this, prop);
6372
+ return get.call(this);
6373
+ },
6374
+ set(val) {
6375
+ checkAndReportViolation(this, prop);
6376
+ return set.call(this, val);
6377
+ },
6378
+ configurable: true,
6379
+ enumerable: true
6380
+ });
6381
+ }
6382
+ }
6383
+ // No point in running this code if we're not in a browser, or if the global polyfill is not loaded
6384
+ if (process.env.IS_BROWSER) {
6385
+ if (!lwcRuntimeFlags.DISABLE_ARIA_REFLECTION_POLYFILL) {
6386
+ // Always run detection in dev mode, so we can at least print to the console
6387
+ if (process.env.NODE_ENV !== 'production') {
6388
+ enableDetection();
6389
+ } else {
6390
+ // In prod mode, only enable detection if reporting is enabled
6391
+ onReportingEnabled(enableDetection);
6265
6392
  }
6393
+ }
6266
6394
  }
6267
6395
 
6268
6396
  /*
@@ -6749,12 +6877,13 @@ function setHooks(hooks) {
6749
6877
  */
6750
6878
  // See @lwc/engine-core/src/framework/template.ts
6751
6879
  const TEMPLATE_PROPS = ['slots', 'stylesheetToken', 'stylesheets', 'renderMode'];
6752
- // Via https://www.npmjs.com/package/object-observer
6753
- const ARRAY_MUTATION_METHODS = ['pop', 'push', 'shift', 'unshift', 'reverse', 'sort', 'fill', 'splice', 'copyWithin'];
6754
6880
  // Expandos that may be placed on a stylesheet factory function, and which are meaningful to LWC at runtime
6755
- const STYLESHEET_FUNCTION_EXPANDOS = [
6881
+ const STYLESHEET_PROPS = [
6756
6882
  // SEE `KEY__SCOPED_CSS` in @lwc/style-compiler
6757
6883
  '$scoped$'];
6884
+ // Via https://www.npmjs.com/package/object-observer
6885
+ const ARRAY_MUTATION_METHODS = ['pop', 'push', 'shift', 'unshift', 'reverse', 'sort', 'fill', 'splice', 'copyWithin'];
6886
+ let mutationTrackingDisabled = false;
6758
6887
  function getOriginalArrayMethod(prop) {
6759
6888
  switch (prop) {
6760
6889
  case 'pop':
@@ -6777,7 +6906,20 @@ function getOriginalArrayMethod(prop) {
6777
6906
  return ArrayCopyWithin;
6778
6907
  }
6779
6908
  }
6780
- let mutationWarningsSilenced = false;
6909
+ function reportViolation(type, eventId, prop) {
6910
+ if (process.env.NODE_ENV !== 'production') {
6911
+ logWarnOnce(`Mutating the "${prop}" property on a ${type} ` + `is deprecated and will be removed in a future version of LWC. ` + `See: https://sfdc.co/template-mutation`);
6912
+ }
6913
+ report(eventId, {
6914
+ propertyName: prop
6915
+ });
6916
+ }
6917
+ function reportTemplateViolation(prop) {
6918
+ reportViolation('template', 3 /* ReportingEventId.TemplateMutation */, prop);
6919
+ }
6920
+ function reportStylesheetViolation(prop) {
6921
+ reportViolation('stylesheet', 4 /* ReportingEventId.StylesheetMutation */, prop);
6922
+ }
6781
6923
  // Warn if the user tries to mutate a stylesheets array, e.g.:
6782
6924
  // `tmpl.stylesheets.push(someStylesheetFunction)`
6783
6925
  function warnOnArrayMutation(stylesheets) {
@@ -6786,7 +6928,7 @@ function warnOnArrayMutation(stylesheets) {
6786
6928
  for (const prop of ARRAY_MUTATION_METHODS) {
6787
6929
  const originalArrayMethod = getOriginalArrayMethod(prop);
6788
6930
  stylesheets[prop] = function arrayMutationWarningWrapper() {
6789
- logError(`Mutating the "stylesheets" array on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6931
+ reportTemplateViolation('stylesheets');
6790
6932
  // @ts-ignore
6791
6933
  return originalArrayMethod.apply(this, arguments);
6792
6934
  };
@@ -6795,8 +6937,7 @@ function warnOnArrayMutation(stylesheets) {
6795
6937
  // Warn if the user tries to mutate a stylesheet factory function, e.g.:
6796
6938
  // `stylesheet.$scoped$ = true`
6797
6939
  function warnOnStylesheetFunctionMutation(stylesheet) {
6798
- // We could warn on other properties, but in practice only certain expandos are meaningful to LWC at runtime
6799
- for (const prop of STYLESHEET_FUNCTION_EXPANDOS) {
6940
+ for (const prop of STYLESHEET_PROPS) {
6800
6941
  let value = stylesheet[prop];
6801
6942
  defineProperty(stylesheet, prop, {
6802
6943
  enumerable: true,
@@ -6805,14 +6946,14 @@ function warnOnStylesheetFunctionMutation(stylesheet) {
6805
6946
  return value;
6806
6947
  },
6807
6948
  set(newValue) {
6808
- logError(`Dynamically setting the "${prop}" property on a stylesheet function ` + `is deprecated and may be removed in a future version of LWC.`);
6949
+ reportStylesheetViolation(prop);
6809
6950
  value = newValue;
6810
6951
  }
6811
6952
  });
6812
6953
  }
6813
6954
  }
6814
6955
  // Warn on either array or stylesheet (function) mutation, in a deeply-nested array
6815
- function warnOnStylesheetsMutation(stylesheets) {
6956
+ function trackStylesheetsMutation(stylesheets) {
6816
6957
  traverseStylesheets(stylesheets, subStylesheets => {
6817
6958
  if (isArray$1(subStylesheets)) {
6818
6959
  warnOnArrayMutation(subStylesheets);
@@ -6839,7 +6980,70 @@ function traverseStylesheets(stylesheets, callback) {
6839
6980
  }
6840
6981
  }
6841
6982
  }
6983
+ function trackMutations(tmpl) {
6984
+ if (!isUndefined$1(tmpl.stylesheets)) {
6985
+ trackStylesheetsMutation(tmpl.stylesheets);
6986
+ }
6987
+ for (const prop of TEMPLATE_PROPS) {
6988
+ let value = tmpl[prop];
6989
+ defineProperty(tmpl, prop, {
6990
+ enumerable: true,
6991
+ configurable: true,
6992
+ get() {
6993
+ return value;
6994
+ },
6995
+ set(newValue) {
6996
+ if (!mutationTrackingDisabled) {
6997
+ reportTemplateViolation(prop);
6998
+ }
6999
+ value = newValue;
7000
+ }
7001
+ });
7002
+ }
7003
+ const originalDescriptor = getOwnPropertyDescriptor$1(tmpl, 'stylesheetTokens');
7004
+ defineProperty(tmpl, 'stylesheetTokens', {
7005
+ enumerable: true,
7006
+ configurable: true,
7007
+ get: originalDescriptor.get,
7008
+ set(value) {
7009
+ reportTemplateViolation('stylesheetTokens');
7010
+ // Avoid logging/reporting twice (for both stylesheetToken and stylesheetTokens)
7011
+ mutationTrackingDisabled = true;
7012
+ originalDescriptor.set.call(this, value);
7013
+ mutationTrackingDisabled = false;
7014
+ }
7015
+ });
7016
+ }
7017
+ function addLegacyStylesheetTokensShim(tmpl) {
7018
+ // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
7019
+ // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
7020
+ defineProperty(tmpl, 'stylesheetTokens', {
7021
+ enumerable: true,
7022
+ configurable: true,
7023
+ get() {
7024
+ const {
7025
+ stylesheetToken
7026
+ } = this;
7027
+ if (isUndefined$1(stylesheetToken)) {
7028
+ return stylesheetToken;
7029
+ }
7030
+ // Shim for the old `stylesheetTokens` property
7031
+ // See https://github.com/salesforce/lwc/pull/2332/files#diff-7901555acef29969adaa6583185b3e9bce475cdc6f23e799a54e0018cb18abaa
7032
+ return {
7033
+ hostAttribute: `${stylesheetToken}-host`,
7034
+ shadowAttribute: stylesheetToken
7035
+ };
7036
+ },
7037
+ set(value) {
7038
+ // If the value is null or some other exotic object, you would be broken anyway in the past
7039
+ // because the engine would try to access hostAttribute/shadowAttribute, which would throw an error.
7040
+ // However it may be undefined in newer versions of LWC, so we need to guard against that case.
7041
+ this.stylesheetToken = isUndefined$1(value) ? undefined : value.shadowAttribute;
7042
+ }
7043
+ });
7044
+ }
6842
7045
  function freezeTemplate(tmpl) {
7046
+ // TODO [#2782]: remove this flag and delete the legacy behavior
6843
7047
  if (lwcRuntimeFlags.ENABLE_FROZEN_TEMPLATE) {
6844
7048
  // Deep freeze the template
6845
7049
  freeze(tmpl);
@@ -6847,66 +7051,16 @@ function freezeTemplate(tmpl) {
6847
7051
  deepFreeze(tmpl.stylesheets);
6848
7052
  }
6849
7053
  } else {
6850
- // TODO [#2782]: remove this flag and delete the legacy behavior
6851
- // When ENABLE_FROZEN_TEMPLATE is false, then we shim stylesheetTokens on top of stylesheetToken for anyone who
6852
- // is accessing the old internal API (backwards compat). Details: https://salesforce.quip.com/v1rmAFu2cKAr
6853
- defineProperty(tmpl, 'stylesheetTokens', {
6854
- enumerable: true,
6855
- configurable: true,
6856
- get() {
6857
- const {
6858
- stylesheetToken
6859
- } = this;
6860
- if (isUndefined$1(stylesheetToken)) {
6861
- return stylesheetToken;
6862
- }
6863
- // Shim for the old `stylesheetTokens` property
6864
- // See https://github.com/salesforce/lwc/pull/2332/files#diff-7901555acef29969adaa6583185b3e9bce475cdc6f23e799a54e0018cb18abaa
6865
- return {
6866
- hostAttribute: `${stylesheetToken}-host`,
6867
- shadowAttribute: stylesheetToken
6868
- };
6869
- },
6870
- set(value) {
6871
- // If the value is null or some other exotic object, you would be broken anyway in the past
6872
- // because the engine would try to access hostAttribute/shadowAttribute, which would throw an error.
6873
- // However it may be undefined in newer versions of LWC, so we need to guard against that case.
6874
- this.stylesheetToken = isUndefined$1(value) ? undefined : value.shadowAttribute;
6875
- }
6876
- });
6877
- // When ENABLE_FROZEN_TEMPLATE is false, warn in dev mode whenever someone is mutating the template
7054
+ // template is not frozen - shim, report, and warn
7055
+ // this shim should be applied in both dev and prod
7056
+ addLegacyStylesheetTokensShim(tmpl);
7057
+ // When ENABLE_FROZEN_TEMPLATE is false, we want to warn in dev mode whenever someone is mutating the template
6878
7058
  if (process.env.NODE_ENV !== 'production') {
6879
- if (!isUndefined$1(tmpl.stylesheets)) {
6880
- warnOnStylesheetsMutation(tmpl.stylesheets);
6881
- }
6882
- for (const prop of TEMPLATE_PROPS) {
6883
- let value = tmpl[prop];
6884
- defineProperty(tmpl, prop, {
6885
- enumerable: true,
6886
- configurable: true,
6887
- get() {
6888
- return value;
6889
- },
6890
- set(newValue) {
6891
- if (!mutationWarningsSilenced) {
6892
- logError(`Dynamically setting the "${prop}" property on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6893
- }
6894
- value = newValue;
6895
- }
6896
- });
6897
- }
6898
- const originalDescriptor = getOwnPropertyDescriptor$1(tmpl, 'stylesheetTokens');
6899
- defineProperty(tmpl, 'stylesheetTokens', {
6900
- enumerable: true,
6901
- configurable: true,
6902
- get: originalDescriptor.get,
6903
- set(value) {
6904
- logError(`Dynamically setting the "stylesheetTokens" property on a template function ` + `is deprecated and may be removed in a future version of LWC.`);
6905
- // Avoid logging twice (for both stylesheetToken and stylesheetTokens)
6906
- mutationWarningsSilenced = true;
6907
- originalDescriptor.set.call(this, value);
6908
- mutationWarningsSilenced = false;
6909
- }
7059
+ trackMutations(tmpl);
7060
+ } else {
7061
+ // In prod mode, we only track mutations if reporting is enabled
7062
+ onReportingEnabled(() => {
7063
+ trackMutations(tmpl);
6910
7064
  });
6911
7065
  }
6912
7066
  }
@@ -6936,4 +7090,4 @@ function getComponentConstructor(elm) {
6936
7090
  }
6937
7091
 
6938
7092
  export { LightningElement, profilerControl as __unstable__ProfilerControl, reportingControl as __unstable__ReportingControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
6939
- /* version: 2.35.2 */
7093
+ /* version: 2.37.0 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lwc/engine-core",
3
- "version": "2.35.2",
3
+ "version": "2.37.0",
4
4
  "description": "Core LWC engine APIs.",
5
5
  "homepage": "https://lwc.dev/",
6
6
  "repository": {
@@ -24,9 +24,9 @@
24
24
  "types/"
25
25
  ],
26
26
  "dependencies": {
27
- "@lwc/aria-reflection": "2.35.2",
28
- "@lwc/features": "2.35.2",
29
- "@lwc/shared": "2.35.2"
27
+ "@lwc/aria-reflection": "2.37.0",
28
+ "@lwc/features": "2.37.0",
29
+ "@lwc/shared": "2.37.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "observable-membrane": "2.0.0"
@@ -1,7 +1,7 @@
1
1
  import { SlotSet } from './vm';
2
2
  import { LightningElementConstructor } from './base-lightning-element';
3
3
  import { VNode, VNodes, VElement, VText, VCustomElement, VComment, VElementData, VStatic, Key, VFragment, VScopedSlotFragment } from './vnodes';
4
- declare function ssf(slotName: string, factory: (value: any, key: any) => VFragment): VScopedSlotFragment;
4
+ declare function ssf(slotName: unknown, factory: (value: any, key: any) => VFragment): VScopedSlotFragment;
5
5
  declare function st(fragment: Element, key: Key): VStatic;
6
6
  declare function fr(key: Key, children: VNodes, stable: 0 | 1): VFragment;
7
7
  declare function h(sel: string, data: VElementData, children?: VNodes): VElement;
@@ -1,8 +1,38 @@
1
- import { VM } from './vm';
2
1
  export declare const enum ReportingEventId {
3
- CrossRootAriaInSyntheticShadow = 0
2
+ CrossRootAriaInSyntheticShadow = 0,
3
+ CompilerRuntimeVersionMismatch = 1,
4
+ NonStandardAriaReflection = 2,
5
+ TemplateMutation = 3,
6
+ StylesheetMutation = 4
4
7
  }
5
- type ReportingDispatcher = (reportingEventId: ReportingEventId, tagName: string, vmIndex: number) => void;
8
+ export interface BasePayload {
9
+ tagName?: string;
10
+ }
11
+ export interface CrossRootAriaInSyntheticShadowPayload extends BasePayload {
12
+ attributeName: string;
13
+ }
14
+ export interface CompilerRuntimeVersionMismatchPayload extends BasePayload {
15
+ compilerVersion: string;
16
+ runtimeVersion: string;
17
+ }
18
+ export interface NonStandardAriaReflectionPayload extends BasePayload {
19
+ propertyName: string;
20
+ }
21
+ export interface TemplateMutationPayload extends BasePayload {
22
+ propertyName: string;
23
+ }
24
+ export interface StylesheetMutationPayload extends BasePayload {
25
+ propertyName: string;
26
+ }
27
+ export type ReportingPayloadMapping = {
28
+ [ReportingEventId.CrossRootAriaInSyntheticShadow]: CrossRootAriaInSyntheticShadowPayload;
29
+ [ReportingEventId.CompilerRuntimeVersionMismatch]: CompilerRuntimeVersionMismatchPayload;
30
+ [ReportingEventId.NonStandardAriaReflection]: NonStandardAriaReflectionPayload;
31
+ [ReportingEventId.TemplateMutation]: TemplateMutationPayload;
32
+ [ReportingEventId.StylesheetMutation]: StylesheetMutationPayload;
33
+ };
34
+ export type ReportingDispatcher<T extends ReportingEventId = ReportingEventId> = (reportingEventId: T, payload: ReportingPayloadMapping[T]) => void;
35
+ /** Callbacks to invoke when reporting is enabled **/
6
36
  type OnReportingEnabledCallback = () => void;
7
37
  export declare const reportingControl: {
8
38
  /**
@@ -25,7 +55,7 @@ export declare function onReportingEnabled(callback: OnReportingEnabledCallback)
25
55
  /**
26
56
  * Report to the current dispatcher, if there is one.
27
57
  * @param reportingEventId
28
- * @param vm
58
+ * @param payload - data to report
29
59
  */
30
- export declare function report(reportingEventId: ReportingEventId, vm: VM): void;
60
+ export declare function report<T extends ReportingEventId>(reportingEventId: T, payload: ReportingPayloadMapping[T]): void;
31
61
  export {};
@@ -25,7 +25,7 @@ export interface BaseVNode {
25
25
  export interface VScopedSlotFragment extends BaseVNode {
26
26
  factory: (value: any, key: any) => VFragment;
27
27
  type: VNodeType.ScopedSlotFragment;
28
- slotName: string;
28
+ slotName: unknown;
29
29
  }
30
30
  export interface VStatic extends BaseVNode {
31
31
  type: VNodeType.Static;
package/types/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  import './testFeatureFlag';
2
2
  import './patches/detect-synthetic-cross-root-aria';
3
+ import './patches/detect-non-standard-aria';
3
4
  export * from './framework/main';
@@ -0,0 +1 @@
1
+ export {};