@lwc/engine-core 3.6.0 → 3.7.1

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,8 +1,9 @@
1
1
  import { SlotSet } from './vm';
2
2
  import { LightningElementConstructor } from './base-lightning-element';
3
- import { VNode, VNodes, VElement, VText, VCustomElement, VComment, VElementData, VStatic, Key, VFragment, VScopedSlotFragment, VStaticElementData } from './vnodes';
3
+ import { VNode, VNodes, VElement, VText, VCustomElement, VComment, VElementData, VStatic, Key, VFragment, VScopedSlotFragment, VStaticPart, VStaticPartData } from './vnodes';
4
+ declare function sp(partId: number, data: VStaticPartData): VStaticPart;
4
5
  declare function ssf(slotName: unknown, factory: (value: any, key: any) => VFragment): VScopedSlotFragment;
5
- declare function st(fragment: Element, key: Key, data?: VStaticElementData): VStatic;
6
+ declare function st(fragment: Element, key: Key, parts?: VStaticPart[]): VStatic;
6
7
  declare function fr(key: Key, children: VNodes, stable: 0 | 1): VFragment;
7
8
  declare function h(sel: string, data: VElementData, children?: VNodes): VElement;
8
9
  declare function ti(value: any): number;
@@ -56,6 +57,7 @@ declare const api: Readonly<{
56
57
  shc: typeof shc;
57
58
  ssf: typeof ssf;
58
59
  ddc: typeof ddc;
60
+ sp: typeof sp;
59
61
  }>;
60
62
  export default api;
61
63
  export type RenderAPI = typeof api;
@@ -1,3 +1,3 @@
1
1
  import { RendererAPI } from '../renderer';
2
- import { VBaseElement, VStatic } from '../vnodes';
3
- export declare function applyEventListeners(vnode: VBaseElement | VStatic, renderer: RendererAPI): void;
2
+ import { VBaseElement, VStaticPart } from '../vnodes';
3
+ export declare function applyEventListeners(vnode: VBaseElement | VStaticPart, renderer: RendererAPI): void;
@@ -0,0 +1,3 @@
1
+ import { VM } from '../vm';
2
+ import { VBaseElement, VStaticPart } from '../vnodes';
3
+ export declare function applyRefs(vnode: VBaseElement | VStaticPart, owner: VM): void;
@@ -0,0 +1,10 @@
1
+ import { VStatic } from '../vnodes';
2
+ import { RendererAPI } from '../renderer';
3
+ /**
4
+ * Given an array of static parts, do all the mounting required for these parts.
5
+ *
6
+ * @param root - the root element
7
+ * @param vnode - the parent VStatic
8
+ * @param renderer - the renderer to use
9
+ */
10
+ export declare function applyStaticParts(root: Element, vnode: VStatic, renderer: RendererAPI): void;
@@ -14,6 +14,7 @@ export interface RendererAPI {
14
14
  createText: (content: string) => N;
15
15
  createComment: (content: string) => N;
16
16
  nextSibling: (node: N) => N | null;
17
+ previousSibling: (node: N) => N | null;
17
18
  attachShadow: (element: E, options: ShadowRootInit) => N;
18
19
  getProperty: (node: N, key: string) => any;
19
20
  setProperty: (node: N, key: string, value: any) => void;
@@ -1,6 +1,4 @@
1
1
  import { StylesheetFactory, TemplateStylesheetFactories } from './stylesheet';
2
- import { VM } from './vm';
3
- import { VBaseElement, VStatic } from './vnodes';
4
2
  type Callback = () => void;
5
3
  export declare const SPACE_CHAR = 32;
6
4
  export declare const EmptyObject: any;
@@ -16,6 +14,5 @@ export declare function cloneAndOmitKey(object: {
16
14
  [key: string]: any;
17
15
  };
18
16
  export declare function flattenStylesheets(stylesheets: TemplateStylesheetFactories): StylesheetFactory[];
19
- export declare function setRefVNode(vm: VM, ref: string, vnode: VBaseElement | VStatic): void;
20
17
  export declare function assertNotProd(): void;
21
18
  export {};
@@ -3,7 +3,7 @@ import { Template } from './template';
3
3
  import { ComponentDef } from './def';
4
4
  import { LightningElement, LightningElementConstructor } from './base-lightning-element';
5
5
  import { ReactiveObserver } from './mutation-tracker';
6
- import { VNodes, VCustomElement, VNode, VBaseElement, VStatic } from './vnodes';
6
+ import { VNodes, VCustomElement, VNode, VBaseElement, VStaticPart } from './vnodes';
7
7
  import { TemplateStylesheetFactories } from './stylesheet';
8
8
  type ShadowRootMode = 'open' | 'closed';
9
9
  export interface TemplateCache {
@@ -62,7 +62,7 @@ export interface Context {
62
62
  wiredDisconnecting: Array<() => void>;
63
63
  }
64
64
  export type RefVNodes = {
65
- [name: string]: VBaseElement | VStatic;
65
+ [name: string]: VBaseElement | VStaticPart;
66
66
  };
67
67
  export interface VM<N = HostNode, E = HostElement> {
68
68
  /** The host element */
@@ -27,13 +27,18 @@ export interface VScopedSlotFragment extends BaseVNode {
27
27
  type: VNodeType.ScopedSlotFragment;
28
28
  slotName: unknown;
29
29
  }
30
- export type VStaticElementData = Pick<VElementData, 'on' | 'ref'>;
30
+ export interface VStaticPart {
31
+ readonly partId: number;
32
+ readonly data: VStaticPartData;
33
+ elm: Element | undefined;
34
+ }
35
+ export type VStaticPartData = Pick<VElementData, 'on' | 'ref'>;
31
36
  export interface VStatic extends BaseVNode {
32
37
  readonly type: VNodeType.Static;
33
38
  readonly sel: undefined;
34
39
  readonly key: Key;
35
40
  readonly fragment: Element;
36
- readonly data: VStaticElementData | undefined;
41
+ readonly parts: VStaticPart[] | undefined;
37
42
  elm: Element | undefined;
38
43
  }
39
44
  export interface VFragment extends BaseVNode, BaseVParent {
package/dist/index.cjs.js CHANGED
@@ -392,20 +392,6 @@ function flattenStylesheets(stylesheets) {
392
392
  }
393
393
  return list;
394
394
  }
395
- // Set a ref (lwc:ref) on a VM, from a template API
396
- function setRefVNode(vm, ref, vnode) {
397
- if (process.env.NODE_ENV !== 'production' && shared.isUndefined(vm.refVNodes)) {
398
- throw new Error('refVNodes must be defined when setting a ref');
399
- }
400
- // If this method is called, then vm.refVNodes is set as the template has refs.
401
- // If not, then something went wrong and we threw an error above.
402
- const refVNodes = vm.refVNodes;
403
- // In cases of conflict (two elements with the same ref), prefer, the last one,
404
- // in depth-first traversal order.
405
- if (!(ref in refVNodes) || refVNodes[ref].key < vnode.key) {
406
- refVNodes[ref] = vnode;
407
- }
408
- }
409
395
  // Throw an error if we're running in prod mode. Ensures code is truly removed from prod mode.
410
396
  function assertNotProd() {
411
397
  /* istanbul ignore if */
@@ -3702,6 +3688,106 @@ function applyStaticStyleAttribute(vnode, renderer) {
3702
3688
  }
3703
3689
  }
3704
3690
 
3691
+ /*
3692
+ * Copyright (c) 2023, salesforce.com, inc.
3693
+ * All rights reserved.
3694
+ * SPDX-License-Identifier: MIT
3695
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3696
+ */
3697
+ // Set a ref (lwc:ref) on a VM, from a template API
3698
+ function applyRefs(vnode, owner) {
3699
+ const { data } = vnode;
3700
+ const { ref } = data;
3701
+ if (shared.isUndefined(ref)) {
3702
+ return;
3703
+ }
3704
+ if (process.env.NODE_ENV !== 'production' && shared.isUndefined(owner.refVNodes)) {
3705
+ throw new Error('refVNodes must be defined when setting a ref');
3706
+ }
3707
+ // If this method is called, then vm.refVNodes is set as the template has refs.
3708
+ // If not, then something went wrong and we threw an error above.
3709
+ const refVNodes = owner.refVNodes;
3710
+ // In cases of conflict (two elements with the same ref), prefer the last one,
3711
+ // in depth-first traversal order. This happens automatically due to how we render
3712
+ refVNodes[ref] = vnode;
3713
+ }
3714
+
3715
+ /*
3716
+ * Copyright (c) 2023, salesforce.com, inc.
3717
+ * All rights reserved.
3718
+ * SPDX-License-Identifier: MIT
3719
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3720
+ */
3721
+ function traverseAndSetElements(root, parts, renderer) {
3722
+ const numParts = parts.length;
3723
+ // Optimization given that, in most cases, there will be one part, and it's just the root
3724
+ if (numParts === 1) {
3725
+ const firstPart = parts[0];
3726
+ if (firstPart.partId === 0) {
3727
+ // 0 means the root node
3728
+ firstPart.elm = root;
3729
+ return;
3730
+ }
3731
+ }
3732
+ const partIdsToParts = new Map();
3733
+ for (const staticPart of parts) {
3734
+ partIdsToParts.set(staticPart.partId, staticPart);
3735
+ }
3736
+ let numFoundParts = 0;
3737
+ const { previousSibling, getLastChild } = renderer;
3738
+ const stack = [root];
3739
+ let partId = -1;
3740
+ // Depth-first traversal. We assign a partId to each element, which is an integer based on traversal order.
3741
+ while (stack.length > 0) {
3742
+ const elm = shared.ArrayShift.call(stack);
3743
+ partId++;
3744
+ const part = partIdsToParts.get(partId);
3745
+ if (!shared.isUndefined(part)) {
3746
+ part.elm = elm;
3747
+ if (++numFoundParts === numParts) {
3748
+ return; // perf optimization - stop traversing once we've found everything we need
3749
+ }
3750
+ }
3751
+ // For depth-first traversal, prepend to the stack in reverse order
3752
+ // Note that we traverse using `*Child`/`*Sibling` rather than `children` because the browser uses a linked
3753
+ // list under the hood to represent the DOM tree, so it's faster to do this than to create an underlying array
3754
+ // by calling `children`.
3755
+ let child = getLastChild(elm);
3756
+ while (!shared.isNull(child)) {
3757
+ shared.ArrayUnshift.call(stack, child);
3758
+ child = previousSibling(child);
3759
+ }
3760
+ }
3761
+ if (process.env.NODE_ENV !== 'production') {
3762
+ shared.assert.isTrue(numFoundParts === numParts, `Should have found all parts by now. Found ${numFoundParts}, needed ${numParts}.`);
3763
+ }
3764
+ }
3765
+ /**
3766
+ * Given an array of static parts, do all the mounting required for these parts.
3767
+ *
3768
+ * @param root - the root element
3769
+ * @param vnode - the parent VStatic
3770
+ * @param renderer - the renderer to use
3771
+ */
3772
+ function applyStaticParts(root, vnode, renderer) {
3773
+ // On the server, we don't support ref (because it relies on renderedCallback), nor do we
3774
+ // support event listeners (no interactivity), so traversing parts makes no sense
3775
+ if (!process.env.IS_BROWSER) {
3776
+ return;
3777
+ }
3778
+ const { parts, owner } = vnode;
3779
+ if (shared.isUndefined(parts)) {
3780
+ return;
3781
+ }
3782
+ traverseAndSetElements(root, parts, renderer); // this adds `part.elm` to each `part`
3783
+ for (const part of parts) {
3784
+ // Event listeners are only applied once when mounting, so they are allowed for static vnodes
3785
+ applyEventListeners(part, renderer);
3786
+ // Refs are allowed as well
3787
+ applyRefs(part, owner);
3788
+ }
3789
+ }
3790
+
3705
3791
  /*
3706
3792
  * Copyright (c) 2018, salesforce.com, inc.
3707
3793
  * All rights reserved.
@@ -3838,13 +3924,13 @@ function mountElement(vnode, parent, anchor, renderer) {
3838
3924
  applyStyleScoping(elm, owner, renderer);
3839
3925
  applyDomManual(elm, vnode);
3840
3926
  applyElementRestrictions(elm, vnode);
3841
- patchElementPropsAndAttrs$1(null, vnode, renderer);
3927
+ patchElementPropsAndAttrsAndRefs$1(null, vnode, renderer);
3842
3928
  insertNode(elm, parent, anchor, renderer);
3843
3929
  mountVNodes(vnode.children, elm, renderer, null);
3844
3930
  }
3845
3931
  function patchElement(n1, n2, renderer) {
3846
3932
  const elm = (n2.elm = n1.elm);
3847
- patchElementPropsAndAttrs$1(n1, n2, renderer);
3933
+ patchElementPropsAndAttrsAndRefs$1(n1, n2, renderer);
3848
3934
  patchChildren(n1.children, n2.children, elm, renderer);
3849
3935
  }
3850
3936
  function mountStatic(vnode, parent, anchor, renderer) {
@@ -3861,8 +3947,7 @@ function mountStatic(vnode, parent, anchor, renderer) {
3861
3947
  }
3862
3948
  }
3863
3949
  insertNode(elm, parent, anchor, renderer);
3864
- // Event listeners are only applied once when mounting, so they are allowed for static vnodes
3865
- applyEventListeners(vnode, renderer);
3950
+ applyStaticParts(elm, vnode, renderer);
3866
3951
  }
3867
3952
  function mountCustomElement(vnode, parent, anchor, renderer) {
3868
3953
  const { sel, owner } = vnode;
@@ -3917,7 +4002,7 @@ function mountCustomElement(vnode, parent, anchor, renderer) {
3917
4002
  if (vm) {
3918
4003
  allocateChildren(vnode, vm);
3919
4004
  }
3920
- patchElementPropsAndAttrs$1(null, vnode, renderer);
4005
+ patchElementPropsAndAttrsAndRefs$1(null, vnode, renderer);
3921
4006
  insertNode(elm, parent, anchor, renderer);
3922
4007
  if (vm) {
3923
4008
  if (process.env.IS_BROWSER) {
@@ -3954,7 +4039,7 @@ function patchCustomElement(n1, n2, parent, renderer) {
3954
4039
  // Otherwise patch the existing component with new props/attrs/etc.
3955
4040
  const elm = (n2.elm = n1.elm);
3956
4041
  const vm = (n2.vm = n1.vm);
3957
- patchElementPropsAndAttrs$1(n1, n2, renderer);
4042
+ patchElementPropsAndAttrsAndRefs$1(n1, n2, renderer);
3958
4043
  if (!shared.isUndefined(vm)) {
3959
4044
  // in fallback mode, the allocation will always set children to
3960
4045
  // empty and delegate the real allocation to the slot elements
@@ -4101,7 +4186,7 @@ function removeNode(node, parent, renderer) {
4101
4186
  lockDomMutation();
4102
4187
  }
4103
4188
  }
4104
- function patchElementPropsAndAttrs$1(oldVnode, vnode, renderer) {
4189
+ function patchElementPropsAndAttrsAndRefs$1(oldVnode, vnode, renderer) {
4105
4190
  if (shared.isNull(oldVnode)) {
4106
4191
  applyEventListeners(vnode, renderer);
4107
4192
  applyStaticClassAttribute(vnode, renderer);
@@ -4113,6 +4198,8 @@ function patchElementPropsAndAttrs$1(oldVnode, vnode, renderer) {
4113
4198
  patchStyleAttribute(oldVnode, vnode, renderer);
4114
4199
  patchAttributes(oldVnode, vnode, renderer);
4115
4200
  patchProps(oldVnode, vnode, renderer);
4201
+ // The `refs` object is blown away in every re-render, so we always need to re-apply them
4202
+ applyRefs(vnode, vnode.owner);
4116
4203
  }
4117
4204
  function applyStyleScoping(elm, owner, renderer) {
4118
4205
  const { getClassList } = renderer;
@@ -4514,6 +4601,14 @@ const SymbolIterator = Symbol.iterator;
4514
4601
  function addVNodeToChildLWC(vnode) {
4515
4602
  shared.ArrayPush.call(getVMBeingRendered().velements, vnode);
4516
4603
  }
4604
+ // [s]tatic [p]art
4605
+ function sp(partId, data) {
4606
+ return {
4607
+ partId,
4608
+ data,
4609
+ elm: undefined, // elm is defined later
4610
+ };
4611
+ }
4517
4612
  // [s]coped [s]lot [f]actory
4518
4613
  function ssf(slotName, factory) {
4519
4614
  return {
@@ -4527,7 +4622,7 @@ function ssf(slotName, factory) {
4527
4622
  };
4528
4623
  }
4529
4624
  // [st]atic node
4530
- function st(fragment, key, data) {
4625
+ function st(fragment, key, parts) {
4531
4626
  const owner = getVMBeingRendered();
4532
4627
  const vnode = {
4533
4628
  type: 4 /* VNodeType.Static */,
@@ -4536,12 +4631,8 @@ function st(fragment, key, data) {
4536
4631
  elm: undefined,
4537
4632
  fragment,
4538
4633
  owner,
4539
- data,
4634
+ parts,
4540
4635
  };
4541
- const ref = data === null || data === void 0 ? void 0 : data.ref;
4542
- if (!shared.isUndefined(ref)) {
4543
- setRefVNode(owner, ref, vnode);
4544
- }
4545
4636
  return vnode;
4546
4637
  }
4547
4638
  // [fr]agment node
@@ -4583,7 +4674,7 @@ function h(sel, data, children = EmptyArray) {
4583
4674
  }
4584
4675
  });
4585
4676
  }
4586
- const { key, ref } = data;
4677
+ const { key } = data;
4587
4678
  const vnode = {
4588
4679
  type: 2 /* VNodeType.Element */,
4589
4680
  sel,
@@ -4593,9 +4684,6 @@ function h(sel, data, children = EmptyArray) {
4593
4684
  key,
4594
4685
  owner: vmBeingRendered,
4595
4686
  };
4596
- if (!shared.isUndefined(ref)) {
4597
- setRefVNode(vmBeingRendered, ref, vnode);
4598
- }
4599
4687
  return vnode;
4600
4688
  }
4601
4689
  // [t]ab[i]ndex function
@@ -4704,7 +4792,7 @@ function c(sel, Ctor, data, children = EmptyArray) {
4704
4792
  });
4705
4793
  }
4706
4794
  }
4707
- const { key, ref } = data;
4795
+ const { key } = data;
4708
4796
  let elm, aChildren, vm;
4709
4797
  const vnode = {
4710
4798
  type: 3 /* VNodeType.CustomElement */,
@@ -4720,9 +4808,6 @@ function c(sel, Ctor, data, children = EmptyArray) {
4720
4808
  vm,
4721
4809
  };
4722
4810
  addVNodeToChildLWC(vnode);
4723
- if (!shared.isUndefined(ref)) {
4724
- setRefVNode(vmBeingRendered, ref, vnode);
4725
- }
4726
4811
  return vnode;
4727
4812
  }
4728
4813
  // [i]terable node
@@ -5013,6 +5098,7 @@ const api = shared.freeze({
5013
5098
  shc,
5014
5099
  ssf,
5015
5100
  ddc,
5101
+ sp,
5016
5102
  });
5017
5103
 
5018
5104
  /*
@@ -6011,7 +6097,12 @@ function runWithBoundaryProtection(vm, owner, pre, job, post) {
6011
6097
  if (!shared.isUndefined(error)) {
6012
6098
  addErrorComponentStack(vm, error);
6013
6099
  const errorBoundaryVm = shared.isNull(owner) ? undefined : getErrorBoundaryVM(owner);
6014
- if (shared.isUndefined(errorBoundaryVm)) {
6100
+ // Error boundaries are not in effect when server-side rendering. `errorCallback`
6101
+ // is intended to allow recovery from errors - changing the state of a component
6102
+ // and instigating a re-render. That is at odds with the single-pass, synchronous
6103
+ // nature of SSR. For that reason, all errors bubble up to the `renderComponent`
6104
+ // call site.
6105
+ if (!process.env.IS_BROWSER || shared.isUndefined(errorBoundaryVm)) {
6015
6106
  throw error; // eslint-disable-line no-unsafe-finally
6016
6107
  }
6017
6108
  resetComponentRoot(vm); // remove offenders
@@ -6475,7 +6566,7 @@ function hydrateStaticElement(elm, vnode, renderer) {
6475
6566
  return handleMismatch(elm, vnode, renderer);
6476
6567
  }
6477
6568
  vnode.elm = elm;
6478
- applyEventListeners(vnode, renderer);
6569
+ applyStaticParts(elm, vnode, renderer);
6479
6570
  return elm;
6480
6571
  }
6481
6572
  function hydrateFragment(elm, vnode, renderer) {
@@ -6509,7 +6600,7 @@ function hydrateElement(elm, vnode, renderer) {
6509
6600
  }
6510
6601
  }
6511
6602
  }
6512
- patchElementPropsAndAttrs(vnode, renderer);
6603
+ patchElementPropsAndAttrsAndRefs(vnode, renderer);
6513
6604
  if (!isDomManual) {
6514
6605
  const { getFirstChild } = renderer;
6515
6606
  hydrateChildren(getFirstChild(elm), vnode.children, elm, owner);
@@ -6542,7 +6633,7 @@ function hydrateCustomElement(elm, vnode, renderer) {
6542
6633
  vnode.elm = elm;
6543
6634
  vnode.vm = vm;
6544
6635
  allocateChildren(vnode, vm);
6545
- patchElementPropsAndAttrs(vnode, renderer);
6636
+ patchElementPropsAndAttrsAndRefs(vnode, renderer);
6546
6637
  // Insert hook section:
6547
6638
  if (process.env.NODE_ENV !== 'production') {
6548
6639
  shared.assert.isTrue(vm.state === 0 /* VMState.created */, `${vm} cannot be recycled.`);
@@ -6607,9 +6698,11 @@ function handleMismatch(node, vnode, renderer) {
6607
6698
  removeNode(node, parentNode, renderer);
6608
6699
  return vnode.elm;
6609
6700
  }
6610
- function patchElementPropsAndAttrs(vnode, renderer) {
6701
+ function patchElementPropsAndAttrsAndRefs(vnode, renderer) {
6611
6702
  applyEventListeners(vnode, renderer);
6612
6703
  patchProps(null, vnode, renderer);
6704
+ // The `refs` object is blown away in every re-render, so we always need to re-apply them
6705
+ applyRefs(vnode, vnode.owner);
6613
6706
  }
6614
6707
  function hasCorrectNodeType(vnode, node, nodeType, renderer) {
6615
6708
  const { getProperty } = renderer;
@@ -7130,5 +7223,5 @@ exports.swapTemplate = swapTemplate;
7130
7223
  exports.track = track;
7131
7224
  exports.unwrap = unwrap;
7132
7225
  exports.wire = wire;
7133
- /** version: 3.6.0 */
7226
+ /** version: 3.7.1 */
7134
7227
  //# sourceMappingURL=index.cjs.js.map