@lwc/engine-core 5.1.1-alpha.0 → 5.2.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.
@@ -1,4 +1,3 @@
1
1
  import { RendererAPI } from '../renderer';
2
- import { VBaseElement, VStatic } from '../vnodes';
2
+ import { VBaseElement } from '../vnodes';
3
3
  export declare function patchAttributes(oldVnode: VBaseElement | null, vnode: VBaseElement, renderer: RendererAPI): void;
4
- export declare function patchSlotAssignment(oldVnode: VBaseElement | VStatic | null, vnode: VBaseElement | VStatic, renderer: RendererAPI): void;
@@ -1,10 +1,12 @@
1
+ import { ShadowMode } from './vm';
1
2
  export declare const enum ReportingEventId {
2
3
  CrossRootAriaInSyntheticShadow = "CrossRootAriaInSyntheticShadow",
3
4
  CompilerRuntimeVersionMismatch = "CompilerRuntimeVersionMismatch",
4
5
  NonStandardAriaReflection = "NonStandardAriaReflection",
5
6
  TemplateMutation = "TemplateMutation",
6
7
  StylesheetMutation = "StylesheetMutation",
7
- ConnectedCallbackWhileDisconnected = "ConnectedCallbackWhileDisconnected"
8
+ ConnectedCallbackWhileDisconnected = "ConnectedCallbackWhileDisconnected",
9
+ ShadowModeUsage = "ShadowModeUsage"
8
10
  }
9
11
  export interface BasePayload {
10
12
  tagName?: string;
@@ -29,6 +31,9 @@ export interface StylesheetMutationPayload extends BasePayload {
29
31
  }
30
32
  export interface ConnectedCallbackWhileDisconnectedPayload extends BasePayload {
31
33
  }
34
+ export interface ShadowModeUsagePayload extends BasePayload {
35
+ mode: ShadowMode;
36
+ }
32
37
  export type ReportingPayloadMapping = {
33
38
  [ReportingEventId.CrossRootAriaInSyntheticShadow]: CrossRootAriaInSyntheticShadowPayload;
34
39
  [ReportingEventId.CompilerRuntimeVersionMismatch]: CompilerRuntimeVersionMismatchPayload;
@@ -36,6 +41,7 @@ export type ReportingPayloadMapping = {
36
41
  [ReportingEventId.TemplateMutation]: TemplateMutationPayload;
37
42
  [ReportingEventId.StylesheetMutation]: StylesheetMutationPayload;
38
43
  [ReportingEventId.ConnectedCallbackWhileDisconnected]: ConnectedCallbackWhileDisconnectedPayload;
44
+ [ReportingEventId.ShadowModeUsage]: ShadowModeUsagePayload;
39
45
  };
40
46
  export type ReportingDispatcher<T extends ReportingEventId = ReportingEventId> = (reportingEventId: T, payload: ReportingPayloadMapping[T]) => void;
41
47
  /** Callbacks to invoke when reporting is enabled **/
@@ -0,0 +1 @@
1
+ export declare function applyShadowMigrateMode(shadowRoot: ShadowRoot): void;
@@ -83,6 +83,8 @@ export interface VM<N = HostNode, E = HostElement> {
83
83
  /** Rendering operations associated with the VM */
84
84
  renderMode: RenderMode;
85
85
  shadowMode: ShadowMode;
86
+ /** True if shadow migrate mode is in effect, i.e. this is native with synthetic-like modifications */
87
+ shadowMigrateMode: boolean;
86
88
  /** The component creation index. */
87
89
  idx: number;
88
90
  /** Component state, analogous to Element.isConnected */
@@ -40,7 +40,6 @@ export interface VStatic extends BaseVNode {
40
40
  readonly fragment: Element;
41
41
  readonly parts: VStaticPart[] | undefined;
42
42
  elm: Element | undefined;
43
- slotAssignment: string | undefined;
44
43
  }
45
44
  export interface VFragment extends BaseVNode, BaseVParent {
46
45
  sel: undefined;
@@ -66,7 +65,6 @@ export interface VBaseElement extends BaseVNode, BaseVParent {
66
65
  data: VElementData;
67
66
  elm: Element | undefined;
68
67
  key: Key;
69
- slotAssignment: string | undefined;
70
68
  }
71
69
  export interface VElement extends VBaseElement {
72
70
  type: VNodeType.Element;
@@ -95,11 +93,9 @@ export interface VElementData extends VNodeData {
95
93
  readonly external?: boolean;
96
94
  readonly ref?: string;
97
95
  readonly slotData?: any;
98
- readonly slotAssignment?: string;
99
96
  }
100
97
  export declare function isVBaseElement(vnode: VNode): vnode is VElement | VCustomElement;
101
98
  export declare function isSameVnode(vnode1: VNode, vnode2: VNode): boolean;
102
99
  export declare function isVCustomElement(vnode: VNode | VBaseElement): vnode is VCustomElement;
103
100
  export declare function isVFragment(vnode: VNode): vnode is VFragment;
104
101
  export declare function isVScopedSlotFragment(vnode: VNode): vnode is VScopedSlotFragment;
105
- export declare function isVStatic(vnode: VNode): vnode is VStatic;
package/dist/index.cjs.js CHANGED
@@ -1354,6 +1354,77 @@ function markLockerLiveObject(obj) {
1354
1354
  }
1355
1355
  }
1356
1356
 
1357
+ /*
1358
+ * Copyright (c) 2023, salesforce.com, inc.
1359
+ * All rights reserved.
1360
+ * SPDX-License-Identifier: MIT
1361
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1362
+ */
1363
+ let globalStylesheet;
1364
+ function isStyleElement(elm) {
1365
+ return elm.tagName === 'STYLE';
1366
+ }
1367
+ async function fetchStylesheet(elm) {
1368
+ if (isStyleElement(elm)) {
1369
+ return elm.textContent;
1370
+ }
1371
+ else {
1372
+ // <link>
1373
+ const { href } = elm;
1374
+ try {
1375
+ return await (await fetch(href)).text();
1376
+ }
1377
+ catch (err) {
1378
+ logWarnOnce(`Ignoring cross-origin stylesheet in migrate mode: ${href}`);
1379
+ // ignore errors with cross-origin stylesheets - nothing we can do for those
1380
+ return '';
1381
+ }
1382
+ }
1383
+ }
1384
+ function initGlobalStylesheet() {
1385
+ const stylesheet = new CSSStyleSheet();
1386
+ const elmsToPromises = new Map();
1387
+ let lastSeenLength = 0;
1388
+ const copyToGlobalStylesheet = () => {
1389
+ const elms = document.head.querySelectorAll('style:not([data-rendered-by-lwc]),link[rel="stylesheet"]');
1390
+ if (elms.length === lastSeenLength) {
1391
+ return; // nothing to update
1392
+ }
1393
+ lastSeenLength = elms.length;
1394
+ const promises = [...elms].map((elm) => {
1395
+ let promise = elmsToPromises.get(elm);
1396
+ if (!promise) {
1397
+ // Cache the promise
1398
+ promise = fetchStylesheet(elm);
1399
+ elmsToPromises.set(elm, promise);
1400
+ }
1401
+ return promise;
1402
+ });
1403
+ Promise.all(promises).then((stylesheetTexts) => {
1404
+ // When replaceSync() is called, the entire contents of the constructable stylesheet are replaced
1405
+ // with the copied+concatenated styles. This means that any shadow root's adoptedStyleSheets that
1406
+ // contains this constructable stylesheet will immediately get the new styles.
1407
+ stylesheet.replaceSync(stylesheetTexts.join('\n'));
1408
+ });
1409
+ };
1410
+ const headObserver = new MutationObserver(copyToGlobalStylesheet);
1411
+ // By observing only the childList, note that we are not covering the case where someone changes an `href`
1412
+ // on an existing <link>`, or the textContent on an existing `<style>`. This is assumed to be an uncommon
1413
+ // case and not worth covering.
1414
+ headObserver.observe(document.head, {
1415
+ childList: true,
1416
+ });
1417
+ copyToGlobalStylesheet();
1418
+ return stylesheet;
1419
+ }
1420
+ function applyShadowMigrateMode(shadowRoot) {
1421
+ if (!globalStylesheet) {
1422
+ globalStylesheet = initGlobalStylesheet();
1423
+ }
1424
+ shadowRoot.synthetic = true; // pretend to be synthetic mode
1425
+ shadowRoot.adoptedStyleSheets.push(globalStylesheet);
1426
+ }
1427
+
1357
1428
  /*
1358
1429
  * Copyright (c) 2018, salesforce.com, inc.
1359
1430
  * All rights reserved.
@@ -1481,6 +1552,11 @@ function doAttachShadow(vm) {
1481
1552
  if (process.env.NODE_ENV !== 'production') {
1482
1553
  patchShadowRootWithRestrictions(shadowRoot);
1483
1554
  }
1555
+ if (process.env.IS_BROWSER &&
1556
+ lwcRuntimeFlags.ENABLE_FORCE_SHADOW_MIGRATE_MODE &&
1557
+ vm.shadowMigrateMode) {
1558
+ applyShadowMigrateMode(shadowRoot);
1559
+ }
1484
1560
  return shadowRoot;
1485
1561
  }
1486
1562
  function warnIfInvokedDuringConstruction(vm, methodOrPropName) {
@@ -3244,8 +3320,8 @@ function getComponentDef(Ctor) {
3244
3320
  for (const key in props) {
3245
3321
  // avoid leaking the reference to the public props descriptors
3246
3322
  publicProps[key] = {
3247
- config: propsConfig[key] || 0,
3248
- type: "any" /* PropDefType.any */,
3323
+ config: propsConfig[key] || 0, // a property by default
3324
+ type: "any" /* PropDefType.any */, // no type inference for public services
3249
3325
  attr: shared.htmlPropertyToAttribute(key),
3250
3326
  };
3251
3327
  }
@@ -3274,7 +3350,7 @@ function makeHostToken(token) {
3274
3350
  }
3275
3351
  function createInlineStyleVNode(content) {
3276
3352
  return api.h('style', {
3277
- key: 'style',
3353
+ key: 'style', // special key
3278
3354
  attrs: {
3279
3355
  type: 'text/css',
3280
3356
  },
@@ -3507,9 +3583,6 @@ function isVFragment(vnode) {
3507
3583
  function isVScopedSlotFragment(vnode) {
3508
3584
  return vnode.type === 6 /* VNodeType.ScopedSlotFragment */;
3509
3585
  }
3510
- function isVStatic(vnode) {
3511
- return vnode.type === 4 /* VNodeType.Static */;
3512
- }
3513
3586
 
3514
3587
  /*
3515
3588
  * Copyright (c) 2018, salesforce.com, inc.
@@ -3558,19 +3631,6 @@ function patchAttributes(oldVnode, vnode, renderer) {
3558
3631
  }
3559
3632
  }
3560
3633
  }
3561
- function patchSlotAssignment(oldVnode, vnode, renderer) {
3562
- if ((oldVnode === null || oldVnode === void 0 ? void 0 : oldVnode.slotAssignment) === vnode.slotAssignment) {
3563
- return;
3564
- }
3565
- const { elm } = vnode;
3566
- const { setAttribute, removeAttribute } = renderer;
3567
- if (shared.isUndefined(vnode.slotAssignment) || shared.isNull(vnode.slotAssignment)) {
3568
- removeAttribute(elm, 'slot');
3569
- }
3570
- else {
3571
- setAttribute(elm, 'slot', vnode.slotAssignment);
3572
- }
3573
- }
3574
3634
 
3575
3635
  /*
3576
3636
  * Copyright (c) 2018, salesforce.com, inc.
@@ -4020,8 +4080,6 @@ function mountElement(vnode, parent, anchor, renderer) {
4020
4080
  }
4021
4081
  function patchStatic(n1, n2, renderer) {
4022
4082
  const elm = (n2.elm = n1.elm);
4023
- // slotAssignments can only apply to the top level element, never to a static part.
4024
- patchSlotAssignment(n1, n2, renderer);
4025
4083
  // The `refs` object is blown away in every re-render, so we always need to re-apply them
4026
4084
  applyStaticParts(elm, n2, renderer, false);
4027
4085
  }
@@ -4043,8 +4101,6 @@ function mountStatic(vnode, parent, anchor, renderer) {
4043
4101
  elm[shared.KEY__SHADOW_STATIC] = true;
4044
4102
  }
4045
4103
  }
4046
- // slotAssignments can only apply to the top level element, never to a static part.
4047
- patchSlotAssignment(null, vnode, renderer);
4048
4104
  insertNode(elm, parent, anchor, renderer);
4049
4105
  applyStaticParts(elm, vnode, renderer, true);
4050
4106
  }
@@ -4270,7 +4326,6 @@ function patchElementPropsAndAttrsAndRefs$1(oldVnode, vnode, renderer) {
4270
4326
  patchStyleAttribute(oldVnode, vnode, renderer);
4271
4327
  patchAttributes(oldVnode, vnode, renderer);
4272
4328
  patchProps(oldVnode, vnode, renderer);
4273
- patchSlotAssignment(oldVnode, vnode, renderer);
4274
4329
  // The `refs` object is blown away in every re-render, so we always need to re-apply them
4275
4330
  applyRefs(vnode, vnode.owner);
4276
4331
  }
@@ -4424,7 +4479,7 @@ function createViewModelHook(elm, vnode, renderer) {
4424
4479
  return vm;
4425
4480
  }
4426
4481
  function allocateInSlot(vm, children, owner) {
4427
- var _a;
4482
+ var _a, _b;
4428
4483
  const { cmpSlots: { slotAssignments: oldSlotsMapping }, } = vm;
4429
4484
  const cmpSlotsMapping = shared.create(null);
4430
4485
  // Collect all slots into cmpSlotsMapping
@@ -4434,8 +4489,8 @@ function allocateInSlot(vm, children, owner) {
4434
4489
  continue;
4435
4490
  }
4436
4491
  let slotName = '';
4437
- if (isVBaseElement(vnode) || isVStatic(vnode)) {
4438
- slotName = (_a = vnode.slotAssignment) !== null && _a !== void 0 ? _a : '';
4492
+ if (isVBaseElement(vnode)) {
4493
+ slotName = (_b = (_a = vnode.data.attrs) === null || _a === void 0 ? void 0 : _a.slot) !== null && _b !== void 0 ? _b : '';
4439
4494
  }
4440
4495
  else if (isVScopedSlotFragment(vnode)) {
4441
4496
  slotName = vnode.slotName;
@@ -4705,7 +4760,6 @@ function st(fragment, key, parts) {
4705
4760
  fragment,
4706
4761
  owner,
4707
4762
  parts,
4708
- slotAssignment: undefined,
4709
4763
  };
4710
4764
  return vnode;
4711
4765
  }
@@ -4750,7 +4804,7 @@ function h(sel, data, children = EmptyArray) {
4750
4804
  }
4751
4805
  });
4752
4806
  }
4753
- const { key, slotAssignment } = data;
4807
+ const { key } = data;
4754
4808
  const vnode = {
4755
4809
  type: 2 /* VNodeType.Element */,
4756
4810
  sel,
@@ -4759,7 +4813,6 @@ function h(sel, data, children = EmptyArray) {
4759
4813
  elm: undefined,
4760
4814
  key,
4761
4815
  owner: vmBeingRendered,
4762
- slotAssignment,
4763
4816
  };
4764
4817
  return vnode;
4765
4818
  }
@@ -4784,8 +4837,6 @@ function s(slotName, data, children, slotset) {
4784
4837
  shared.assert.isTrue(shared.isObject(data), `s() 2nd argument data must be an object.`);
4785
4838
  shared.assert.isTrue(shared.isArray(children), `h() 3rd argument children must be an array.`);
4786
4839
  }
4787
- const vmBeingRendered = getVMBeingRendered();
4788
- const { renderMode } = vmBeingRendered;
4789
4840
  if (!shared.isUndefined(slotset) &&
4790
4841
  !shared.isUndefined(slotset.slotAssignments) &&
4791
4842
  !shared.isUndefined(slotset.slotAssignments[slotName]) &&
@@ -4808,6 +4859,7 @@ function s(slotName, data, children, slotset) {
4808
4859
  }
4809
4860
  // If the passed slot content is factory, evaluate it and add the produced vnodes
4810
4861
  if (assignedNodeIsScopedSlot) {
4862
+ const vmBeingRenderedInception = getVMBeingRendered();
4811
4863
  // Evaluate in the scope of the slot content's owner
4812
4864
  // if a slotset is provided, there will always be an owner. The only case where owner is
4813
4865
  // undefined is for root components, but root components cannot accept slotted content
@@ -4821,32 +4873,20 @@ function s(slotName, data, children, slotset) {
4821
4873
  });
4822
4874
  }
4823
4875
  finally {
4824
- setVMBeingRendered(vmBeingRendered);
4876
+ setVMBeingRendered(vmBeingRenderedInception);
4825
4877
  }
4826
4878
  }
4827
4879
  else {
4828
- // This block is for standard slots (non-scoped slots)
4829
- let clonedVNode;
4830
- if (renderMode === 0 /* RenderMode.Light */ &&
4831
- (isVBaseElement(vnode) || isVStatic(vnode)) &&
4832
- // We only need to copy the vnodes when the slot assignment changes, copying every time causes issues with
4833
- // disconnected/connected callback firing.
4834
- vnode.slotAssignment !== data.slotAssignment) {
4835
- // When the light DOM slot assignment (slot attribute) changes we can't use the same reference
4836
- // to the vnode because the current way the diffing algo works, it will replace the original reference
4837
- // to the host element with a new one. This means the new element will be mounted and immediately unmounted.
4838
- // Creating a copy of the vnode to preserve a reference to the previous host element.
4839
- clonedVNode = Object.assign(Object.assign({}, vnode), { slotAssignment: data.slotAssignment });
4840
- }
4841
4880
  // If the slot content is standard type, the content is static, no additional
4842
4881
  // processing needed on the vnode
4843
- shared.ArrayPush.call(newChildren, clonedVNode !== null && clonedVNode !== void 0 ? clonedVNode : vnode);
4882
+ shared.ArrayPush.call(newChildren, vnode);
4844
4883
  }
4845
4884
  }
4846
4885
  }
4847
4886
  children = newChildren;
4848
4887
  }
4849
- const { shadowMode, apiVersion } = vmBeingRendered;
4888
+ const vmBeingRendered = getVMBeingRendered();
4889
+ const { renderMode, shadowMode, apiVersion } = vmBeingRendered;
4850
4890
  if (renderMode === 0 /* RenderMode.Light */) {
4851
4891
  // light DOM slots - backwards-compatible behavior uses flattening, new behavior uses fragments
4852
4892
  if (shared.isAPIFeatureEnabled(2 /* APIFeature.USE_FRAGMENTS_FOR_LIGHT_DOM_SLOTS */, apiVersion)) {
@@ -4888,7 +4928,7 @@ function c(sel, Ctor, data, children = EmptyArray) {
4888
4928
  });
4889
4929
  }
4890
4930
  }
4891
- const { key, slotAssignment } = data;
4931
+ const { key } = data;
4892
4932
  let elm, aChildren, vm;
4893
4933
  const vnode = {
4894
4934
  type: 3 /* VNodeType.CustomElement */,
@@ -4897,10 +4937,9 @@ function c(sel, Ctor, data, children = EmptyArray) {
4897
4937
  children,
4898
4938
  elm,
4899
4939
  key,
4900
- slotAssignment,
4901
4940
  ctor: Ctor,
4902
4941
  owner: vmBeingRendered,
4903
- mode: 'open',
4942
+ mode: 'open', // TODO [#1294]: this should be defined in Ctor
4904
4943
  aChildren,
4905
4944
  vm,
4906
4945
  };
@@ -5804,6 +5843,7 @@ function createVM(elm, ctor, renderer, options) {
5804
5843
  // Properties set right after VM creation.
5805
5844
  tro: null,
5806
5845
  shadowMode: null,
5846
+ shadowMigrateMode: false,
5807
5847
  stylesheets: null,
5808
5848
  // Properties set by the LightningElement constructor.
5809
5849
  component: null,
@@ -5819,8 +5859,22 @@ function createVM(elm, ctor, renderer, options) {
5819
5859
  vm.debugInfo = shared.create(null);
5820
5860
  }
5821
5861
  vm.stylesheets = computeStylesheets(vm, def.ctor);
5822
- vm.shadowMode = computeShadowMode(def, vm.owner, renderer);
5862
+ const computedShadowMode = computeShadowMode(def, vm.owner, renderer);
5863
+ if (lwcRuntimeFlags.ENABLE_FORCE_SHADOW_MIGRATE_MODE) {
5864
+ vm.shadowMode = 0 /* ShadowMode.Native */;
5865
+ vm.shadowMigrateMode = computedShadowMode === 1 /* ShadowMode.Synthetic */;
5866
+ }
5867
+ else {
5868
+ vm.shadowMode = computedShadowMode;
5869
+ }
5823
5870
  vm.tro = getTemplateReactiveObserver(vm);
5871
+ // We don't need to report the shadow mode if we're rendering in light DOM
5872
+ if (isReportingEnabled() && vm.renderMode === 1 /* RenderMode.Shadow */) {
5873
+ report("ShadowModeUsage" /* ReportingEventId.ShadowModeUsage */, {
5874
+ tagName: vm.tagName,
5875
+ mode: vm.shadowMode,
5876
+ });
5877
+ }
5824
5878
  if (process.env.NODE_ENV !== 'production') {
5825
5879
  vm.toString = () => {
5826
5880
  return `[object:vm ${def.name} (${vm.idx})]`;
@@ -5904,7 +5958,8 @@ function computeShadowMode(def, owner, renderer) {
5904
5958
  }
5905
5959
  const { isSyntheticShadowDefined } = renderer;
5906
5960
  let shadowMode;
5907
- if (isSyntheticShadowDefined) {
5961
+ // If ENABLE_FORCE_SHADOW_MIGRATE_MODE is true, then ShadowMode.Synthetic here will mean "force-migrate" mode.
5962
+ if (isSyntheticShadowDefined || lwcRuntimeFlags.ENABLE_FORCE_SHADOW_MIGRATE_MODE) {
5908
5963
  if (def.renderMode === 0 /* RenderMode.Light */) {
5909
5964
  // ShadowMode.Native implies "not synthetic shadow" which is consistent with how
5910
5965
  // everything defaults to native when the synthetic shadow polyfill is unavailable.
@@ -7363,5 +7418,5 @@ exports.swapTemplate = swapTemplate;
7363
7418
  exports.track = track;
7364
7419
  exports.unwrap = unwrap;
7365
7420
  exports.wire = wire;
7366
- /** version: 5.1.0 */
7421
+ /** version: 5.2.0 */
7367
7422
  //# sourceMappingURL=index.cjs.js.map