@lwc/engine-core 2.7.4 → 2.10.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.
@@ -71,6 +71,31 @@ function parseStyleText(cssText) {
71
71
  }
72
72
 
73
73
  return styleMap;
74
+ } // Make a shallow copy of an object but omit the given key
75
+
76
+ function cloneAndOmitKey(object, keyToOmit) {
77
+ const result = {};
78
+
79
+ for (const key of Object.keys(object)) {
80
+ if (key !== keyToOmit) {
81
+ result[key] = object[key];
82
+ }
83
+ }
84
+
85
+ return result;
86
+ }
87
+ function flattenStylesheets(stylesheets) {
88
+ const list = [];
89
+
90
+ for (const stylesheet of stylesheets) {
91
+ if (!Array.isArray(stylesheet)) {
92
+ list.push(stylesheet);
93
+ } else {
94
+ list.push(...flattenStylesheets(stylesheet));
95
+ }
96
+ }
97
+
98
+ return list;
74
99
  }
75
100
 
76
101
  //
@@ -2765,6 +2790,45 @@ function getDecoratorsMeta(Ctor) {
2765
2790
  return shared.isUndefined(meta) ? defaultMeta : meta;
2766
2791
  }
2767
2792
 
2793
+ /*
2794
+ * Copyright (c) 2018, salesforce.com, inc.
2795
+ * All rights reserved.
2796
+ * SPDX-License-Identifier: MIT
2797
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
2798
+ */
2799
+ let warned = false;
2800
+
2801
+ if (process.env.NODE_ENV === 'development') {
2802
+ // @ts-ignore
2803
+ window.__lwcResetWarnedOnVersionMismatch = () => {
2804
+ warned = false;
2805
+ };
2806
+ }
2807
+
2808
+ function checkVersionMismatch(func, type) {
2809
+ const versionMatcher = func.toString().match(shared.LWC_VERSION_COMMENT_REGEX);
2810
+
2811
+ if (!shared.isNull(versionMatcher) && !warned) {
2812
+ const version = versionMatcher[1];
2813
+ const [major, minor] = version.split('.');
2814
+ const [expectedMajor, expectedMinor] = shared.LWC_VERSION.split('.');
2815
+
2816
+ if (major !== expectedMajor || minor !== expectedMinor) {
2817
+ warned = true; // only warn once to avoid flooding the console
2818
+ // stylesheets and templates do not have user-meaningful names, but components do
2819
+
2820
+ const friendlyName = type === 'component' ? `${type} ${func.name}` : type;
2821
+ 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.`);
2822
+ }
2823
+ }
2824
+ }
2825
+
2826
+ /*
2827
+ * Copyright (c) 2018, salesforce.com, inc.
2828
+ * All rights reserved.
2829
+ * SPDX-License-Identifier: MIT
2830
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
2831
+ */
2768
2832
  const signedTemplateSet = new Set();
2769
2833
  function defaultEmptyTemplate() {
2770
2834
  return [];
@@ -2773,12 +2837,27 @@ signedTemplateSet.add(defaultEmptyTemplate);
2773
2837
  function isTemplateRegistered(tpl) {
2774
2838
  return signedTemplateSet.has(tpl);
2775
2839
  }
2840
+
2841
+ function checkTemplateVersionMismatch(template) {
2842
+ checkVersionMismatch(template, 'template');
2843
+
2844
+ if (!shared.isUndefined(template.stylesheets)) {
2845
+ for (const stylesheet of flattenStylesheets(template.stylesheets)) {
2846
+ checkVersionMismatch(stylesheet, 'stylesheet');
2847
+ }
2848
+ }
2849
+ }
2776
2850
  /**
2777
2851
  * INTERNAL: This function can only be invoked by compiled code. The compiler
2778
2852
  * will prevent this function from being imported by userland code.
2779
2853
  */
2780
2854
 
2855
+
2781
2856
  function registerTemplate(tpl) {
2857
+ if (process.env.NODE_ENV !== 'production') {
2858
+ checkTemplateVersionMismatch(tpl);
2859
+ }
2860
+
2782
2861
  signedTemplateSet.add(tpl); // chaining this method as a way to wrap existing
2783
2862
  // assignment of templates easily, without too much transformation
2784
2863
 
@@ -3070,20 +3149,6 @@ function rehydrateHotComponent(Ctor) {
3070
3149
  return canRefreshAllInstances;
3071
3150
  }
3072
3151
 
3073
- function flattenStylesheets(stylesheets) {
3074
- const list = [];
3075
-
3076
- for (const stylesheet of stylesheets) {
3077
- if (!Array.isArray(stylesheet)) {
3078
- list.push(stylesheet);
3079
- } else {
3080
- list.push(...flattenStylesheets(stylesheet));
3081
- }
3082
- }
3083
-
3084
- return list;
3085
- }
3086
-
3087
3152
  function getTemplateOrSwappedTemplate(tpl) {
3088
3153
  if (process.env.NODE_ENV === 'production') {
3089
3154
  // this method should never leak to prod
@@ -3895,156 +3960,268 @@ function applyStaticStyleAttribute(vnode) {
3895
3960
  * SPDX-License-Identifier: MIT
3896
3961
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
3897
3962
  */
3898
- const TextHook = {
3899
- create: vnode => {
3900
- const {
3901
- owner
3902
- } = vnode;
3903
- const elm = createText(vnode.text);
3904
- linkNodeToShadow(elm, owner);
3905
- vnode.elm = elm;
3906
- },
3907
- update: updateNodeHook,
3908
- insert: insertNode,
3909
- move: insertNode,
3910
- remove: removeNode
3911
- };
3912
- const CommentHook = {
3913
- create: vnode => {
3914
- const {
3915
- owner,
3916
- text
3917
- } = vnode;
3918
- const elm = createComment(text);
3919
- linkNodeToShadow(elm, owner);
3920
- vnode.elm = elm;
3921
- },
3922
- update: updateNodeHook,
3923
- insert: insertNode,
3924
- move: insertNode,
3925
- remove: removeNode
3926
- }; // insert is called after update, which is used somewhere else (via a module)
3927
- // to mark the vm as inserted, that means we cannot use update as the main channel
3928
- // to rehydrate when dirty, because sometimes the element is not inserted just yet,
3929
- // which breaks some invariants. For that reason, we have the following for any
3930
- // Custom Element that is inserted via a template.
3931
-
3932
- const ElementHook = {
3933
- create: vnode => {
3934
- const {
3935
- sel,
3936
- owner,
3937
- data: {
3938
- svg
3939
- }
3940
- } = vnode;
3941
- const namespace = shared.isTrue(svg) ? shared.SVG_NAMESPACE : undefined;
3942
- const elm = createElement(sel, namespace);
3943
- linkNodeToShadow(elm, owner);
3944
- fallbackElmHook(elm, vnode);
3945
- vnode.elm = elm;
3946
- patchElementPropsAndAttrs$1(null, vnode);
3947
- },
3948
- update: (oldVnode, vnode) => {
3949
- patchElementPropsAndAttrs$1(oldVnode, vnode);
3950
- patchChildren(vnode.elm, oldVnode.children, vnode.children);
3951
- },
3952
- insert: (vnode, parentNode, referenceNode) => {
3953
- insertNode(vnode, parentNode, referenceNode);
3954
- createChildrenHook(vnode);
3955
- },
3956
- move: insertNode,
3957
- remove: (vnode, parentNode) => {
3958
- removeNode(vnode, parentNode);
3959
- removeChildren(vnode);
3963
+ function patchChildren(c1, c2, parent) {
3964
+ if (hasDynamicChildren(c2)) {
3965
+ updateDynamicChildren(c1, c2, parent);
3966
+ } else {
3967
+ updateStaticChildren(c1, c2, parent);
3968
+ }
3969
+ }
3970
+
3971
+ function patch(n1, n2) {
3972
+ if (n1 === n2) {
3973
+ return;
3960
3974
  }
3961
- };
3962
- const CustomElementHook = {
3963
- create: vnode => {
3964
- const {
3965
- sel,
3966
- owner
3967
- } = vnode;
3968
- const UpgradableConstructor = getUpgradableConstructor(sel);
3969
- /**
3970
- * Note: if the upgradable constructor does not expect, or throw when we new it
3971
- * with a callback as the first argument, we could implement a more advanced
3972
- * mechanism that only passes that argument if the constructor is known to be
3973
- * an upgradable custom element.
3974
- */
3975
-
3976
- let vm;
3977
- const elm = new UpgradableConstructor(elm => {
3978
- // the custom element from the registry is expecting an upgrade callback
3979
- vm = createViewModelHook(elm, vnode);
3980
- });
3981
- linkNodeToShadow(elm, owner);
3982
- vnode.elm = elm;
3983
3975
 
3984
- if (vm) {
3985
- allocateChildren(vnode, vm);
3986
- } else if (vnode.ctor !== UpgradableConstructor) {
3987
- throw new TypeError(`Incorrect Component Constructor`);
3976
+ if (process.env.NODE_ENV !== 'production') {
3977
+ if (!isSameVnode(n1, n2)) {
3978
+ throw new Error('Expected these VNodes to be the same: ' + JSON.stringify({
3979
+ sel: n1.sel,
3980
+ key: n1.key
3981
+ }) + ', ' + JSON.stringify({
3982
+ sel: n2.sel,
3983
+ key: n2.key
3984
+ }));
3988
3985
  }
3986
+ }
3989
3987
 
3990
- patchElementPropsAndAttrs$1(null, vnode);
3991
- },
3992
- update: (oldVnode, vnode) => {
3993
- patchElementPropsAndAttrs$1(oldVnode, vnode);
3994
- const vm = getAssociatedVMIfPresent(vnode.elm);
3988
+ switch (n2.type) {
3989
+ case 0
3990
+ /* Text */
3991
+ :
3992
+ patchText(n1, n2);
3993
+ break;
3995
3994
 
3996
- if (vm) {
3997
- // in fallback mode, the allocation will always set children to
3998
- // empty and delegate the real allocation to the slot elements
3999
- allocateChildren(vnode, vm);
4000
- } // in fallback mode, the children will be always empty, so, nothing
4001
- // will happen, but in native, it does allocate the light dom
3995
+ case 1
3996
+ /* Comment */
3997
+ :
3998
+ patchComment(n1, n2);
3999
+ break;
4002
4000
 
4001
+ case 2
4002
+ /* Element */
4003
+ :
4004
+ patchElement(n1, n2);
4005
+ break;
4003
4006
 
4004
- patchChildren(vnode.elm, oldVnode.children, vnode.children);
4007
+ case 3
4008
+ /* CustomElement */
4009
+ :
4010
+ patchCustomElement(n1, n2);
4011
+ break;
4012
+ }
4013
+ }
4005
4014
 
4006
- if (vm) {
4007
- if (process.env.NODE_ENV !== 'production') {
4008
- shared.assert.isTrue(shared.isArray(vnode.children), `Invalid vnode for a custom element, it must have children defined.`);
4009
- } // this will probably update the shadowRoot, but only if the vm is in a dirty state
4010
- // this is important to preserve the top to bottom synchronous rendering phase.
4015
+ function mount(node, parent, anchor) {
4016
+ switch (node.type) {
4017
+ case 0
4018
+ /* Text */
4019
+ :
4020
+ mountText(node, parent, anchor);
4021
+ break;
4011
4022
 
4023
+ case 1
4024
+ /* Comment */
4025
+ :
4026
+ mountComment(node, parent, anchor);
4027
+ break;
4028
+
4029
+ case 2
4030
+ /* Element */
4031
+ :
4032
+ mountElement(node, parent, anchor);
4033
+ break;
4034
+
4035
+ case 3
4036
+ /* CustomElement */
4037
+ :
4038
+ mountCustomElement(node, parent, anchor);
4039
+ break;
4040
+ }
4041
+ }
4042
+
4043
+ function patchText(n1, n2) {
4044
+ n2.elm = n1.elm;
4045
+
4046
+ if (n2.text !== n1.text) {
4047
+ updateTextContent(n2);
4048
+ }
4049
+ }
4050
+
4051
+ function mountText(node, parent, anchor) {
4052
+ const {
4053
+ owner
4054
+ } = node;
4055
+ const textNode = node.elm = createText(node.text);
4056
+ linkNodeToShadow(textNode, owner);
4057
+ insertNode(textNode, parent, anchor);
4058
+ }
4059
+
4060
+ function patchComment(n1, n2) {
4061
+ n2.elm = n1.elm; // FIXME: Comment nodes should be static, we shouldn't need to diff them together. However
4062
+ // it is the case today.
4063
+
4064
+ if (n2.text !== n1.text) {
4065
+ updateTextContent(n2);
4066
+ }
4067
+ }
4068
+
4069
+ function mountComment(node, parent, anchor) {
4070
+ const {
4071
+ owner
4072
+ } = node;
4073
+ const commentNode = node.elm = createComment(node.text);
4074
+ linkNodeToShadow(commentNode, owner);
4075
+ insertNode(commentNode, parent, anchor);
4076
+ }
4012
4077
 
4013
- rerenderVM(vm);
4078
+ function mountElement(vnode, parent, anchor) {
4079
+ const {
4080
+ sel,
4081
+ owner,
4082
+ data: {
4083
+ svg
4014
4084
  }
4015
- },
4016
- insert: (vnode, parentNode, referenceNode) => {
4017
- insertNode(vnode, parentNode, referenceNode);
4018
- const vm = getAssociatedVMIfPresent(vnode.elm);
4085
+ } = vnode;
4086
+ const namespace = shared.isTrue(svg) ? shared.SVG_NAMESPACE : undefined;
4087
+ const elm = createElement(sel, namespace);
4088
+ linkNodeToShadow(elm, owner);
4089
+ fallbackElmHook(elm, vnode);
4090
+ vnode.elm = elm;
4091
+ patchElementPropsAndAttrs$1(null, vnode);
4092
+ insertNode(elm, parent, anchor);
4093
+ mountVNodes(vnode.children, elm, null);
4094
+ }
4019
4095
 
4020
- if (vm) {
4021
- if (process.env.NODE_ENV !== 'production') {
4022
- shared.assert.isTrue(vm.state === 0
4023
- /* created */
4024
- , `${vm} cannot be recycled.`);
4025
- }
4096
+ function patchElement(n1, n2) {
4097
+ const elm = n2.elm = n1.elm;
4098
+ patchElementPropsAndAttrs$1(n1, n2);
4099
+ patchChildren(n1.children, n2.children, elm);
4100
+ }
4101
+
4102
+ function mountCustomElement(vnode, parent, anchor) {
4103
+ const {
4104
+ sel,
4105
+ owner
4106
+ } = vnode;
4107
+ const UpgradableConstructor = getUpgradableConstructor(sel);
4108
+ /**
4109
+ * Note: if the upgradable constructor does not expect, or throw when we new it
4110
+ * with a callback as the first argument, we could implement a more advanced
4111
+ * mechanism that only passes that argument if the constructor is known to be
4112
+ * an upgradable custom element.
4113
+ */
4114
+
4115
+ let vm;
4116
+ const elm = new UpgradableConstructor(elm => {
4117
+ // the custom element from the registry is expecting an upgrade callback
4118
+ vm = createViewModelHook(elm, vnode);
4119
+ });
4120
+ linkNodeToShadow(elm, owner);
4121
+ vnode.elm = elm;
4122
+ vnode.vm = vm;
4123
+
4124
+ if (vm) {
4125
+ allocateChildren(vnode, vm);
4126
+ } else if (vnode.ctor !== UpgradableConstructor) {
4127
+ throw new TypeError(`Incorrect Component Constructor`);
4128
+ }
4129
+
4130
+ patchElementPropsAndAttrs$1(null, vnode);
4131
+ insertNode(elm, parent, anchor);
4026
4132
 
4027
- runConnectedCallback(vm);
4133
+ if (vm) {
4134
+ if (process.env.NODE_ENV !== 'production') {
4135
+ shared.assert.isTrue(vm.state === 0
4136
+ /* created */
4137
+ , `${vm} cannot be recycled.`);
4028
4138
  }
4029
4139
 
4030
- createChildrenHook(vnode);
4140
+ runConnectedCallback(vm);
4141
+ }
4142
+
4143
+ mountVNodes(vnode.children, elm, null);
4031
4144
 
4032
- if (vm) {
4033
- appendVM(vm);
4145
+ if (vm) {
4146
+ appendVM(vm);
4147
+ }
4148
+ }
4149
+
4150
+ function patchCustomElement(n1, n2) {
4151
+ const elm = n2.elm = n1.elm;
4152
+ const vm = n2.vm = n1.vm;
4153
+ patchElementPropsAndAttrs$1(n1, n2);
4154
+
4155
+ if (!shared.isUndefined(vm)) {
4156
+ // in fallback mode, the allocation will always set children to
4157
+ // empty and delegate the real allocation to the slot elements
4158
+ allocateChildren(n2, vm);
4159
+ } // in fallback mode, the children will be always empty, so, nothing
4160
+ // will happen, but in native, it does allocate the light dom
4161
+
4162
+
4163
+ patchChildren(n1.children, n2.children, elm);
4164
+
4165
+ if (!shared.isUndefined(vm)) {
4166
+ // this will probably update the shadowRoot, but only if the vm is in a dirty state
4167
+ // this is important to preserve the top to bottom synchronous rendering phase.
4168
+ rerenderVM(vm);
4169
+ }
4170
+ }
4171
+
4172
+ function mountVNodes(vnodes, parent, anchor, start = 0, end = vnodes.length) {
4173
+ for (; start < end; ++start) {
4174
+ const vnode = vnodes[start];
4175
+
4176
+ if (isVNode(vnode)) {
4177
+ mount(vnode, parent, anchor);
4034
4178
  }
4035
- },
4036
- move: insertNode,
4037
- remove: (vnode, parentNode) => {
4038
- removeNode(vnode, parentNode);
4039
- const vm = getAssociatedVMIfPresent(vnode.elm);
4179
+ }
4180
+ }
4181
+
4182
+ function unmount(vnode, parent, doRemove = false) {
4183
+ const {
4184
+ type,
4185
+ elm
4186
+ } = vnode; // When unmounting a VNode subtree not all the elements have to removed from the DOM. The
4187
+ // subtree root, is the only element worth unmounting from the subtree.
4188
+
4189
+ if (doRemove) {
4190
+ removeNode(elm, parent);
4191
+ }
4040
4192
 
4041
- if (vm) {
4042
- // for custom elements we don't have to go recursively because the removeVM routine
4043
- // will take care of disconnecting any child VM attached to its shadow as well.
4044
- removeVM(vm);
4193
+ switch (type) {
4194
+ case 2
4195
+ /* Element */
4196
+ :
4197
+ unmountVNodes(vnode.children, elm);
4198
+ break;
4199
+
4200
+ case 3
4201
+ /* CustomElement */
4202
+ :
4203
+ {
4204
+ const {
4205
+ vm
4206
+ } = vnode; // No need to unmount the children here, `removeVM` will take care of removing the
4207
+ // children.
4208
+
4209
+ if (!shared.isUndefined(vm)) {
4210
+ removeVM(vm);
4211
+ }
4212
+ }
4213
+ }
4214
+ }
4215
+
4216
+ function unmountVNodes(vnodes, parent, doRemove = false, start = 0, end = vnodes.length) {
4217
+ for (; start < end; ++start) {
4218
+ const ch = vnodes[start];
4219
+
4220
+ if (isVNode(ch)) {
4221
+ unmount(ch, parent, doRemove);
4045
4222
  }
4046
4223
  }
4047
- };
4224
+ }
4048
4225
 
4049
4226
  function isVNode(vnode) {
4050
4227
  return vnode != null;
@@ -4089,43 +4266,41 @@ function linkNodeToShadow(elm, owner) {
4089
4266
  }
4090
4267
  }
4091
4268
 
4092
- function updateNodeHook(oldVnode, vnode) {
4269
+ function updateTextContent(vnode) {
4093
4270
  const {
4094
4271
  elm,
4095
4272
  text
4096
4273
  } = vnode;
4097
4274
 
4098
- if (oldVnode.text !== text) {
4099
- if (process.env.NODE_ENV !== 'production') {
4100
- unlockDomMutation();
4101
- }
4275
+ if (process.env.NODE_ENV !== 'production') {
4276
+ unlockDomMutation();
4277
+ }
4102
4278
 
4103
- setText(elm, text);
4279
+ setText(elm, text);
4104
4280
 
4105
- if (process.env.NODE_ENV !== 'production') {
4106
- lockDomMutation();
4107
- }
4281
+ if (process.env.NODE_ENV !== 'production') {
4282
+ lockDomMutation();
4108
4283
  }
4109
4284
  }
4110
4285
 
4111
- function insertNode(vnode, parentNode, referenceNode) {
4286
+ function insertNode(node, parent, anchor) {
4112
4287
  if (process.env.NODE_ENV !== 'production') {
4113
4288
  unlockDomMutation();
4114
4289
  }
4115
4290
 
4116
- insert(vnode.elm, parentNode, referenceNode);
4291
+ insert(node, parent, anchor);
4117
4292
 
4118
4293
  if (process.env.NODE_ENV !== 'production') {
4119
4294
  lockDomMutation();
4120
4295
  }
4121
4296
  }
4122
4297
 
4123
- function removeNode(vnode, parentNode) {
4298
+ function removeNode(node, parent) {
4124
4299
  if (process.env.NODE_ENV !== 'production') {
4125
4300
  unlockDomMutation();
4126
4301
  }
4127
4302
 
4128
- remove(vnode.elm, parentNode);
4303
+ remove(node, parent);
4129
4304
 
4130
4305
  if (process.env.NODE_ENV !== 'production') {
4131
4306
  lockDomMutation();
@@ -4170,11 +4345,13 @@ function fallbackElmHook(elm, vnode) {
4170
4345
  ) {
4171
4346
  // this element will now accept any manual content inserted into it
4172
4347
  observeElementChildNodes(elm);
4173
- } // when running in synthetic shadow mode, we need to set the shadowToken value
4174
- // into each element from the template, so they can be styled accordingly.
4175
-
4348
+ }
4176
4349
 
4177
- setElementShadowToken(elm, stylesheetToken);
4350
+ if (!shared.isUndefined(stylesheetToken)) {
4351
+ // when running in synthetic shadow mode, we need to set the shadowToken value
4352
+ // into each element from the template, so they can be styled accordingly.
4353
+ setElementShadowToken(elm, stylesheetToken);
4354
+ }
4178
4355
  }
4179
4356
 
4180
4357
  if (process.env.NODE_ENV !== 'production') {
@@ -4196,13 +4373,6 @@ function fallbackElmHook(elm, vnode) {
4196
4373
  }
4197
4374
  }
4198
4375
 
4199
- function patchChildren(parent, oldCh, newCh) {
4200
- if (hasDynamicChildren(newCh)) {
4201
- updateDynamicChildren(parent, oldCh, newCh);
4202
- } else {
4203
- updateStaticChildren(parent, oldCh, newCh);
4204
- }
4205
- }
4206
4376
  function allocateChildren(vnode, vm) {
4207
4377
  // A component with slots will re-render because:
4208
4378
  // 1- There is a change of the internal state.
@@ -4260,7 +4430,9 @@ function createViewModelHook(elm, vnode) {
4260
4430
  } = owner.context; // when running in synthetic shadow mode, we need to set the shadowToken value
4261
4431
  // into each element from the template, so they can be styled accordingly.
4262
4432
 
4263
- setElementShadowToken(elm, stylesheetToken);
4433
+ if (!shared.isUndefined(stylesheetToken)) {
4434
+ setElementShadowToken(elm, stylesheetToken);
4435
+ }
4264
4436
  }
4265
4437
 
4266
4438
  vm = createVM(elm, ctor, {
@@ -4276,40 +4448,6 @@ function createViewModelHook(elm, vnode) {
4276
4448
  return vm;
4277
4449
  }
4278
4450
 
4279
- function createChildrenHook(vnode) {
4280
- const {
4281
- elm,
4282
- children
4283
- } = vnode;
4284
-
4285
- for (let j = 0; j < children.length; ++j) {
4286
- const ch = children[j];
4287
-
4288
- if (ch != null) {
4289
- ch.hook.create(ch);
4290
- ch.hook.insert(ch, elm, null);
4291
- }
4292
- }
4293
- }
4294
-
4295
- function removeChildren(vnode) {
4296
- // this method only needs to search on child vnodes from template
4297
- // to trigger the remove hook just in case some of those children
4298
- // are custom elements.
4299
- const {
4300
- children,
4301
- elm
4302
- } = vnode;
4303
-
4304
- for (let j = 0, len = children.length; j < len; ++j) {
4305
- const ch = children[j];
4306
-
4307
- if (!shared.isNull(ch)) {
4308
- ch.hook.remove(ch, elm);
4309
- }
4310
- }
4311
- }
4312
-
4313
4451
  function allocateInSlot(vm, children) {
4314
4452
  var _a;
4315
4453
 
@@ -4406,28 +4544,7 @@ function createKeyToOldIdx(children, beginIdx, endIdx) {
4406
4544
  return map;
4407
4545
  }
4408
4546
 
4409
- function addVnodes(parentElm, before, vnodes, startIdx, endIdx) {
4410
- for (; startIdx <= endIdx; ++startIdx) {
4411
- const ch = vnodes[startIdx];
4412
-
4413
- if (isVNode(ch)) {
4414
- ch.hook.create(ch);
4415
- ch.hook.insert(ch, parentElm, before);
4416
- }
4417
- }
4418
- }
4419
-
4420
- function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
4421
- for (; startIdx <= endIdx; ++startIdx) {
4422
- const ch = vnodes[startIdx]; // text nodes do not have logic associated to them
4423
-
4424
- if (isVNode(ch)) {
4425
- ch.hook.remove(ch, parentElm);
4426
- }
4427
- }
4428
- }
4429
-
4430
- function updateDynamicChildren(parentElm, oldCh, newCh) {
4547
+ function updateDynamicChildren(oldCh, newCh, parent) {
4431
4548
  let oldStartIdx = 0;
4432
4549
  let newStartIdx = 0;
4433
4550
  let oldEndIdx = oldCh.length - 1;
@@ -4441,6 +4558,7 @@ function updateDynamicChildren(parentElm, oldCh, newCh) {
4441
4558
  let idxInOld;
4442
4559
  let elmToMove;
4443
4560
  let before;
4561
+ let clonedOldCh = false;
4444
4562
 
4445
4563
  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
4446
4564
  if (!isVNode(oldStartVnode)) {
@@ -4452,23 +4570,23 @@ function updateDynamicChildren(parentElm, oldCh, newCh) {
4452
4570
  } else if (!isVNode(newEndVnode)) {
4453
4571
  newEndVnode = newCh[--newEndIdx];
4454
4572
  } else if (isSameVnode(oldStartVnode, newStartVnode)) {
4455
- patchVnode(oldStartVnode, newStartVnode);
4573
+ patch(oldStartVnode, newStartVnode);
4456
4574
  oldStartVnode = oldCh[++oldStartIdx];
4457
4575
  newStartVnode = newCh[++newStartIdx];
4458
4576
  } else if (isSameVnode(oldEndVnode, newEndVnode)) {
4459
- patchVnode(oldEndVnode, newEndVnode);
4577
+ patch(oldEndVnode, newEndVnode);
4460
4578
  oldEndVnode = oldCh[--oldEndIdx];
4461
4579
  newEndVnode = newCh[--newEndIdx];
4462
4580
  } else if (isSameVnode(oldStartVnode, newEndVnode)) {
4463
4581
  // Vnode moved right
4464
- patchVnode(oldStartVnode, newEndVnode);
4465
- newEndVnode.hook.move(oldStartVnode, parentElm, nextSibling(oldEndVnode.elm));
4582
+ patch(oldStartVnode, newEndVnode);
4583
+ insertNode(oldStartVnode.elm, parent, nextSibling(oldEndVnode.elm));
4466
4584
  oldStartVnode = oldCh[++oldStartIdx];
4467
4585
  newEndVnode = newCh[--newEndIdx];
4468
4586
  } else if (isSameVnode(oldEndVnode, newStartVnode)) {
4469
4587
  // Vnode moved left
4470
- patchVnode(oldEndVnode, newStartVnode);
4471
- newStartVnode.hook.move(oldEndVnode, parentElm, oldStartVnode.elm);
4588
+ patch(oldEndVnode, newStartVnode);
4589
+ insertNode(newStartVnode.elm, parent, oldStartVnode.elm);
4472
4590
  oldEndVnode = oldCh[--oldEndIdx];
4473
4591
  newStartVnode = newCh[++newStartIdx];
4474
4592
  } else {
@@ -4480,8 +4598,7 @@ function updateDynamicChildren(parentElm, oldCh, newCh) {
4480
4598
 
4481
4599
  if (shared.isUndefined(idxInOld)) {
4482
4600
  // New element
4483
- newStartVnode.hook.create(newStartVnode);
4484
- newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
4601
+ mount(newStartVnode, parent, oldStartVnode.elm);
4485
4602
  newStartVnode = newCh[++newStartIdx];
4486
4603
  } else {
4487
4604
  elmToMove = oldCh[idxInOld];
@@ -4489,12 +4606,22 @@ function updateDynamicChildren(parentElm, oldCh, newCh) {
4489
4606
  if (isVNode(elmToMove)) {
4490
4607
  if (elmToMove.sel !== newStartVnode.sel) {
4491
4608
  // New element
4492
- newStartVnode.hook.create(newStartVnode);
4493
- newStartVnode.hook.insert(newStartVnode, parentElm, oldStartVnode.elm);
4609
+ mount(newStartVnode, parent, oldStartVnode.elm);
4494
4610
  } else {
4495
- patchVnode(elmToMove, newStartVnode);
4611
+ patch(elmToMove, newStartVnode); // Delete the old child, but copy the array since it is read-only.
4612
+ // The `oldCh` will be GC'ed after `updateDynamicChildren` is complete,
4613
+ // so we only care about the `oldCh` object inside this function.
4614
+ // To avoid cloning over and over again, we check `clonedOldCh`
4615
+ // and only clone once.
4616
+
4617
+ if (!clonedOldCh) {
4618
+ clonedOldCh = true;
4619
+ oldCh = [...oldCh];
4620
+ } // We've already cloned at least once, so it's no longer read-only
4621
+
4622
+
4496
4623
  oldCh[idxInOld] = undefined;
4497
- newStartVnode.hook.move(elmToMove, parentElm, oldStartVnode.elm);
4624
+ insertNode(elmToMove.elm, parent, oldStartVnode.elm);
4498
4625
  }
4499
4626
  }
4500
4627
 
@@ -4515,66 +4642,56 @@ function updateDynamicChildren(parentElm, oldCh, newCh) {
4515
4642
  } while (!isVNode(n) && i < newChEnd);
4516
4643
 
4517
4644
  before = isVNode(n) ? n.elm : null;
4518
- addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx);
4645
+ mountVNodes(newCh, parent, before, newStartIdx, newEndIdx + 1);
4519
4646
  } else {
4520
- removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
4647
+ unmountVNodes(oldCh, parent, true, oldStartIdx, oldEndIdx + 1);
4521
4648
  }
4522
4649
  }
4523
4650
  }
4524
4651
 
4525
- function updateStaticChildren(parentElm, oldCh, newCh) {
4526
- const oldChLength = oldCh.length;
4527
- const newChLength = newCh.length;
4652
+ function updateStaticChildren(c1, c2, parent) {
4653
+ const c1Length = c1.length;
4654
+ const c2Length = c2.length;
4528
4655
 
4529
- if (oldChLength === 0) {
4656
+ if (c1Length === 0) {
4530
4657
  // the old list is empty, we can directly insert anything new
4531
- addVnodes(parentElm, null, newCh, 0, newChLength);
4658
+ mountVNodes(c2, parent, null);
4532
4659
  return;
4533
4660
  }
4534
4661
 
4535
- if (newChLength === 0) {
4662
+ if (c2Length === 0) {
4536
4663
  // the old list is nonempty and the new list is empty so we can directly remove all old nodes
4537
4664
  // this is the case in which the dynamic children of an if-directive should be removed
4538
- removeVnodes(parentElm, oldCh, 0, oldChLength);
4665
+ unmountVNodes(c1, parent, true);
4539
4666
  return;
4540
4667
  } // if the old list is not empty, the new list MUST have the same
4541
4668
  // amount of nodes, that's why we call this static children
4542
4669
 
4543
4670
 
4544
- let referenceElm = null;
4671
+ let anchor = null;
4545
4672
 
4546
- for (let i = newChLength - 1; i >= 0; i -= 1) {
4547
- const vnode = newCh[i];
4548
- const oldVNode = oldCh[i];
4673
+ for (let i = c2Length - 1; i >= 0; i -= 1) {
4674
+ const n1 = c1[i];
4675
+ const n2 = c2[i];
4549
4676
 
4550
- if (vnode !== oldVNode) {
4551
- if (isVNode(oldVNode)) {
4552
- if (isVNode(vnode)) {
4553
- // both vnodes must be equivalent, and se just need to patch them
4554
- patchVnode(oldVNode, vnode);
4555
- referenceElm = vnode.elm;
4677
+ if (n2 !== n1) {
4678
+ if (isVNode(n1)) {
4679
+ if (isVNode(n2)) {
4680
+ // both vnodes are equivalent, and we just need to patch them
4681
+ patch(n1, n2);
4682
+ anchor = n2.elm;
4556
4683
  } else {
4557
4684
  // removing the old vnode since the new one is null
4558
- oldVNode.hook.remove(oldVNode, parentElm);
4685
+ unmount(n1, parent, true);
4559
4686
  }
4560
- } else if (isVNode(vnode)) {
4561
- // this condition is unnecessary
4562
- vnode.hook.create(vnode); // insert the new node one since the old one is null
4563
-
4564
- vnode.hook.insert(vnode, parentElm, referenceElm);
4565
- referenceElm = vnode.elm;
4687
+ } else if (isVNode(n2)) {
4688
+ mount(n2, parent, anchor);
4689
+ anchor = n2.elm;
4566
4690
  }
4567
4691
  }
4568
4692
  }
4569
4693
  }
4570
4694
 
4571
- function patchVnode(oldVnode, vnode) {
4572
- if (oldVnode !== vnode) {
4573
- vnode.elm = oldVnode.elm;
4574
- vnode.hook.update(oldVnode, vnode);
4575
- }
4576
- }
4577
-
4578
4695
  /*
4579
4696
  * Copyright (c) 2018, salesforce.com, inc.
4580
4697
  * All rights reserved.
@@ -4588,7 +4705,7 @@ function addVNodeToChildLWC(vnode) {
4588
4705
  } // [h]tml node
4589
4706
 
4590
4707
 
4591
- function h(sel, data, children) {
4708
+ function h(sel, data, children = EmptyArray) {
4592
4709
  const vmBeingRendered = getVMBeingRendered();
4593
4710
 
4594
4711
  if (process.env.NODE_ENV !== 'production') {
@@ -4624,7 +4741,6 @@ function h(sel, data, children) {
4624
4741
  children,
4625
4742
  elm,
4626
4743
  key,
4627
- hook: ElementHook,
4628
4744
  owner: vmBeingRendered
4629
4745
  };
4630
4746
  } // [t]ab[i]ndex function
@@ -4711,7 +4827,7 @@ function c(sel, Ctor, data, children = EmptyArray) {
4711
4827
  const {
4712
4828
  key
4713
4829
  } = data;
4714
- let elm;
4830
+ let elm, aChildren, vm;
4715
4831
  const vnode = {
4716
4832
  type: 3
4717
4833
  /* CustomElement */
@@ -4721,11 +4837,11 @@ function c(sel, Ctor, data, children = EmptyArray) {
4721
4837
  children,
4722
4838
  elm,
4723
4839
  key,
4724
- hook: CustomElementHook,
4725
4840
  ctor: Ctor,
4726
4841
  owner: vmBeingRendered,
4727
- mode: 'open' // TODO [#1294]: this should be defined in Ctor
4728
-
4842
+ mode: 'open',
4843
+ aChildren,
4844
+ vm
4729
4845
  };
4730
4846
  addVNodeToChildLWC(vnode);
4731
4847
  return vnode;
@@ -4855,7 +4971,6 @@ function t(text) {
4855
4971
  text,
4856
4972
  elm,
4857
4973
  key,
4858
- hook: TextHook,
4859
4974
  owner: getVMBeingRendered()
4860
4975
  };
4861
4976
  } // [co]mment node
@@ -4871,7 +4986,6 @@ function co(text) {
4871
4986
  text,
4872
4987
  elm,
4873
4988
  key,
4874
- hook: CommentHook,
4875
4989
  owner: getVMBeingRendered()
4876
4990
  };
4877
4991
  } // [d]ynamic text
@@ -4986,7 +5100,7 @@ let dynamicImportedComponentCounter = 0;
4986
5100
  * create a dynamic component via `<x-foo lwc:dynamic={Ctor}>`
4987
5101
  */
4988
5102
 
4989
- function dc(sel, Ctor, data, children) {
5103
+ function dc(sel, Ctor, data, children = EmptyArray) {
4990
5104
  if (process.env.NODE_ENV !== 'production') {
4991
5105
  shared.assert.isTrue(shared.isString(sel), `dc() 1st argument sel must be a string.`);
4992
5106
  shared.assert.isTrue(shared.isObject(data), `dc() 3nd argument data must be an object.`);
@@ -5010,10 +5124,14 @@ function dc(sel, Ctor, data, children) {
5010
5124
  } // the new vnode key is a mix of idx and compiler key, this is required by the diffing algo
5011
5125
  // to identify different constructors as vnodes with different keys to avoid reusing the
5012
5126
  // element used for previous constructors.
5127
+ // Shallow clone is necessary here becuase VElementData may be shared across VNodes due to
5128
+ // hoisting optimization.
5013
5129
 
5014
5130
 
5015
- data.key = `dc:${idx}:${data.key}`;
5016
- return c(sel, Ctor, data, children);
5131
+ const newData = Object.assign(Object.assign({}, data), {
5132
+ key: `dc:${idx}:${data.key}`
5133
+ });
5134
+ return c(sel, Ctor, newData, children);
5017
5135
  }
5018
5136
  /**
5019
5137
  * slow children collection marking mechanism. this API allows the compiler to signal
@@ -5133,12 +5251,14 @@ function updateStylesheetToken(vm, template) {
5133
5251
  hasTokenInAttribute: oldHasTokenInAttribute
5134
5252
  } = context;
5135
5253
 
5136
- if (oldHasTokenInClass) {
5137
- getClassList(elm).remove(makeHostToken(oldToken));
5138
- }
5254
+ if (!shared.isUndefined(oldToken)) {
5255
+ if (oldHasTokenInClass) {
5256
+ getClassList(elm).remove(makeHostToken(oldToken));
5257
+ }
5139
5258
 
5140
- if (oldHasTokenInAttribute) {
5141
- removeAttribute(elm, makeHostToken(oldToken));
5259
+ if (oldHasTokenInAttribute) {
5260
+ removeAttribute(elm, makeHostToken(oldToken));
5261
+ }
5142
5262
  } // Apply the new template styling token to the host element, if the new template has any
5143
5263
  // associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
5144
5264
 
@@ -5716,6 +5836,10 @@ const signedTemplateMap = new Map();
5716
5836
  function registerComponent(Ctor, {
5717
5837
  tmpl
5718
5838
  }) {
5839
+ if (process.env.NODE_ENV !== 'production') {
5840
+ checkVersionMismatch(Ctor, 'component');
5841
+ }
5842
+
5719
5843
  signedTemplateMap.set(Ctor, tmpl); // chaining this method as a way to wrap existing assignment of component constructor easily,
5720
5844
  // without too much transformation
5721
5845
 
@@ -5832,7 +5956,7 @@ function invokeServiceHook(vm, cbs) {
5832
5956
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
5833
5957
  */
5834
5958
 
5835
- function hydrate$1(vnode, node) {
5959
+ function hydrate(vnode, node) {
5836
5960
  switch (vnode.type) {
5837
5961
  case 0
5838
5962
  /* Text */
@@ -5864,16 +5988,18 @@ function hydrateText(vnode, node) {
5864
5988
  var _a;
5865
5989
 
5866
5990
  if (process.env.NODE_ENV !== 'production') {
5867
- // eslint-disable-next-line lwc-internal/no-global-node
5868
- validateNodeType(vnode, node, Node.TEXT_NODE);
5991
+ validateNodeType(vnode, node, 3
5992
+ /* TEXT */
5993
+ );
5994
+ const nodeValue = getProperty(node, 'nodeValue');
5869
5995
 
5870
- if (node.nodeValue !== vnode.text && !(node.nodeValue === '\u200D' && vnode.text === '')) {
5996
+ if (nodeValue !== vnode.text && !(nodeValue === '\u200D' && vnode.text === '')) {
5871
5997
  logWarn('Hydration mismatch: text values do not match, will recover from the difference', vnode.owner);
5872
5998
  }
5873
5999
  } // always set the text value to the one from the vnode.
5874
6000
 
5875
6001
 
5876
- node.nodeValue = (_a = vnode.text) !== null && _a !== void 0 ? _a : null;
6002
+ setText(node, (_a = vnode.text) !== null && _a !== void 0 ? _a : null);
5877
6003
  vnode.elm = node;
5878
6004
  }
5879
6005
 
@@ -5881,23 +6007,25 @@ function hydrateComment(vnode, node) {
5881
6007
  var _a;
5882
6008
 
5883
6009
  if (process.env.NODE_ENV !== 'production') {
5884
- // eslint-disable-next-line lwc-internal/no-global-node
5885
- validateNodeType(vnode, node, Node.COMMENT_NODE);
6010
+ validateNodeType(vnode, node, 8
6011
+ /* COMMENT */
6012
+ );
5886
6013
 
5887
- if (node.nodeValue !== vnode.text) {
6014
+ if (getProperty(node, 'nodeValue') !== vnode.text) {
5888
6015
  logWarn('Hydration mismatch: comment values do not match, will recover from the difference', vnode.owner);
5889
6016
  }
5890
6017
  } // always set the text value to the one from the vnode.
5891
6018
 
5892
6019
 
5893
- node.nodeValue = (_a = vnode.text) !== null && _a !== void 0 ? _a : null;
6020
+ setProperty(node, 'nodeValue', (_a = vnode.text) !== null && _a !== void 0 ? _a : null);
5894
6021
  vnode.elm = node;
5895
6022
  }
5896
6023
 
5897
6024
  function hydrateElement(vnode, node) {
5898
6025
  if (process.env.NODE_ENV !== 'production') {
5899
- // eslint-disable-next-line lwc-internal/no-global-node
5900
- validateNodeType(vnode, node, Node.ELEMENT_NODE);
6026
+ validateNodeType(vnode, node, 1
6027
+ /* ELEMENT */
6028
+ );
5901
6029
  validateElement(vnode, node);
5902
6030
  }
5903
6031
 
@@ -5918,10 +6046,13 @@ function hydrateElement(vnode, node) {
5918
6046
  } = vnode.data;
5919
6047
 
5920
6048
  if (!shared.isUndefined(props) && !shared.isUndefined(props.innerHTML)) {
5921
- if (elm.innerHTML === props.innerHTML) {
5922
- delete props.innerHTML;
6049
+ if (getProperty(elm, 'innerHTML') === props.innerHTML) {
6050
+ // Do a shallow clone since VNodeData may be shared across VNodes due to hoist optimization
6051
+ vnode.data = Object.assign(Object.assign({}, vnode.data), {
6052
+ props: cloneAndOmitKey(props, 'innerHTML')
6053
+ });
5923
6054
  } else {
5924
- logWarn(`Mismatch hydrating element <${elm.tagName.toLowerCase()}>: innerHTML values do not match for element, will recover from the difference`, vnode.owner);
6055
+ logWarn(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: innerHTML values do not match for element, will recover from the difference`, vnode.owner);
5925
6056
  }
5926
6057
  }
5927
6058
  }
@@ -5929,19 +6060,19 @@ function hydrateElement(vnode, node) {
5929
6060
  patchElementPropsAndAttrs(vnode);
5930
6061
 
5931
6062
  if (!isDomManual) {
5932
- hydrateChildren(vnode.elm.childNodes, vnode.children, vnode.owner);
6063
+ hydrateChildren(getChildNodes(vnode.elm), vnode.children, vnode.owner);
5933
6064
  }
5934
6065
  }
5935
6066
 
5936
6067
  function hydrateCustomElement(vnode, node) {
5937
6068
  if (process.env.NODE_ENV !== 'production') {
5938
- // eslint-disable-next-line lwc-internal/no-global-node
5939
- validateNodeType(vnode, node, Node.ELEMENT_NODE);
6069
+ validateNodeType(vnode, node, 1
6070
+ /* ELEMENT */
6071
+ );
5940
6072
  validateElement(vnode, node);
5941
6073
  }
5942
6074
 
5943
6075
  const elm = node;
5944
- vnode.elm = elm;
5945
6076
  const {
5946
6077
  sel,
5947
6078
  mode,
@@ -5953,6 +6084,8 @@ function hydrateCustomElement(vnode, node) {
5953
6084
  owner,
5954
6085
  tagName: sel
5955
6086
  });
6087
+ vnode.elm = elm;
6088
+ vnode.vm = vm;
5956
6089
  allocateChildren(vnode, vm);
5957
6090
  patchElementPropsAndAttrs(vnode); // Insert hook section:
5958
6091
 
@@ -5969,7 +6102,7 @@ function hydrateCustomElement(vnode, node) {
5969
6102
  ) {
5970
6103
  // VM is not rendering in Light DOM, we can proceed and hydrate the slotted content.
5971
6104
  // Note: for Light DOM, this is handled while hydrating the VM
5972
- hydrateChildren(vnode.elm.childNodes, vnode.children, vm);
6105
+ hydrateChildren(getChildNodes(vnode.elm), vnode.children, vm);
5973
6106
  }
5974
6107
 
5975
6108
  hydrateVM(vm);
@@ -5992,7 +6125,7 @@ function hydrateChildren(elmChildren, children, vm) {
5992
6125
 
5993
6126
  if (!shared.isNull(childVnode)) {
5994
6127
  const childNode = elmChildren[childNodeIndex];
5995
- hydrate$1(childVnode, childNode);
6128
+ hydrate(childVnode, childNode);
5996
6129
  childNodeIndex++;
5997
6130
  }
5998
6131
  }
@@ -6008,15 +6141,15 @@ function throwHydrationError() {
6008
6141
  }
6009
6142
 
6010
6143
  function validateNodeType(vnode, node, nodeType) {
6011
- if (node.nodeType !== nodeType) {
6144
+ if (getProperty(node, 'nodeType') !== nodeType) {
6012
6145
  logError('Hydration mismatch: incorrect node type received', vnode.owner);
6013
6146
  shared.assert.fail('Hydration mismatch: incorrect node type received.');
6014
6147
  }
6015
6148
  }
6016
6149
 
6017
6150
  function validateElement(vnode, elm) {
6018
- if (vnode.sel.toLowerCase() !== elm.tagName.toLowerCase()) {
6019
- logError(`Hydration mismatch: expecting element with tag "${vnode.sel.toLowerCase()}" but found "${elm.tagName.toLowerCase()}".`, vnode.owner);
6151
+ if (vnode.sel.toLowerCase() !== getProperty(elm, 'tagName').toLowerCase()) {
6152
+ logError(`Hydration mismatch: expecting element with tag "${vnode.sel.toLowerCase()}" but found "${getProperty(elm, 'tagName').toLowerCase()}".`, vnode.owner);
6020
6153
  throwHydrationError();
6021
6154
  }
6022
6155
 
@@ -6043,7 +6176,7 @@ function validateAttrs(vnode, elm) {
6043
6176
  const elmAttrValue = getAttribute(elm, attrName);
6044
6177
 
6045
6178
  if (String(attrValue) !== elmAttrValue) {
6046
- logError(`Mismatch hydrating element <${elm.tagName.toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, vnode.owner);
6179
+ logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, vnode.owner);
6047
6180
  nodesAreCompatible = false;
6048
6181
  }
6049
6182
  }
@@ -6061,7 +6194,7 @@ function validateClassAttr(vnode, elm) {
6061
6194
  let nodesAreCompatible = true;
6062
6195
  let vnodeClassName;
6063
6196
 
6064
- if (!shared.isUndefined(className) && String(className) !== elm.className) {
6197
+ if (!shared.isUndefined(className) && String(className) !== getProperty(elm, 'className')) {
6065
6198
  // className is used when class is bound to an expr.
6066
6199
  nodesAreCompatible = false;
6067
6200
  vnodeClassName = className;
@@ -6086,7 +6219,7 @@ function validateClassAttr(vnode, elm) {
6086
6219
  }
6087
6220
 
6088
6221
  if (!nodesAreCompatible) {
6089
- logError(`Mismatch hydrating element <${elm.tagName.toLowerCase()}>: attribute "class" has different values, expected "${vnodeClassName}" but found "${elm.className}"`, vnode.owner);
6222
+ logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "class" has different values, expected "${vnodeClassName}" but found "${getProperty(elm, 'className')}"`, vnode.owner);
6090
6223
  }
6091
6224
 
6092
6225
  return nodesAreCompatible;
@@ -6133,7 +6266,7 @@ function validateStyleAttr(vnode, elm) {
6133
6266
 
6134
6267
  if (!nodesAreCompatible) {
6135
6268
  // style is used when class is bound to an expr.
6136
- logError(`Mismatch hydrating element <${elm.tagName.toLowerCase()}>: attribute "style" has different values, expected "${vnodeStyle}" but found "${elmStyle}".`, vnode.owner);
6269
+ logError(`Mismatch hydrating element <${getProperty(elm, 'tagName').toLowerCase()}>: attribute "style" has different values, expected "${vnodeStyle}" but found "${elmStyle}".`, vnode.owner);
6137
6270
  }
6138
6271
 
6139
6272
  return nodesAreCompatible;
@@ -6197,7 +6330,19 @@ function appendVM(vm) {
6197
6330
  rehydrate(vm);
6198
6331
  }
6199
6332
  function hydrateVM(vm) {
6200
- hydrate(vm);
6333
+ if (shared.isTrue(vm.isDirty)) {
6334
+ // manually diffing/patching here.
6335
+ // This routine is:
6336
+ // patchShadowRoot(vm, children);
6337
+ // -> addVnodes.
6338
+ const children = renderComponent(vm);
6339
+ vm.children = children;
6340
+ const vmChildren = vm.renderMode === 0
6341
+ /* Light */
6342
+ ? getChildNodes(vm.elm) : getChildNodes(vm.elm.shadowRoot);
6343
+ hydrateChildren(vmChildren, children, vm);
6344
+ runRenderedCallback(vm);
6345
+ }
6201
6346
  } // just in case the component comes back, with this we guarantee re-rendering it
6202
6347
  // while preventing any attempt to rehydration until after reinsertion.
6203
6348
 
@@ -6347,7 +6492,11 @@ function computeShadowMode(vm) {
6347
6492
  /* Native */
6348
6493
  ;
6349
6494
  } else if (isNativeShadowDefined) {
6350
- if (def.shadowSupportMode === "any"
6495
+ if (features.runtimeFlags.DISABLE_MIXED_SHADOW_MODE) {
6496
+ shadowMode = 1
6497
+ /* Synthetic */
6498
+ ;
6499
+ } else if (def.shadowSupportMode === "any"
6351
6500
  /* Any */
6352
6501
  ) {
6353
6502
  shadowMode = 0
@@ -6425,22 +6574,6 @@ function rehydrate(vm) {
6425
6574
  }
6426
6575
  }
6427
6576
 
6428
- function hydrate(vm) {
6429
- if (shared.isTrue(vm.isDirty)) {
6430
- // manually diffing/patching here.
6431
- // This routine is:
6432
- // patchShadowRoot(vm, children);
6433
- // -> addVnodes.
6434
- const children = renderComponent(vm);
6435
- vm.children = children;
6436
- const vmChildren = vm.renderMode === 0
6437
- /* Light */
6438
- ? vm.elm.childNodes : vm.elm.shadowRoot.childNodes;
6439
- hydrateChildren(vmChildren, children, vm);
6440
- runRenderedCallback(vm);
6441
- }
6442
- }
6443
-
6444
6577
  function patchShadowRoot(vm, newCh) {
6445
6578
  const {
6446
6579
  renderRoot,
@@ -6460,7 +6593,7 @@ function patchShadowRoot(vm, newCh) {
6460
6593
  , vm);
6461
6594
  }, () => {
6462
6595
  // job
6463
- patchChildren(renderRoot, oldCh, newCh);
6596
+ patchChildren(oldCh, newCh, renderRoot);
6464
6597
  }, () => {
6465
6598
  // post
6466
6599
  logOperationEnd(2
@@ -7268,4 +7401,4 @@ exports.swapTemplate = swapTemplate;
7268
7401
  exports.track = track;
7269
7402
  exports.unwrap = unwrap;
7270
7403
  exports.wire = wire;
7271
- /* version: 2.7.4 */
7404
+ /* version: 2.10.0 */