@lwc/engine-core 2.5.1 → 2.5.2-canary1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine-core.cjs.js +303 -7
- package/dist/engine-core.js +304 -9
- package/package.json +4 -4
- package/types/3rdparty/snabbdom/types.d.ts +1 -0
- package/types/framework/hooks.d.ts +3 -0
- package/types/framework/main.d.ts +1 -1
- package/types/framework/renderer.d.ts +1 -0
- package/types/framework/vm.d.ts +2 -0
package/dist/engine-core.cjs.js
CHANGED
|
@@ -4012,7 +4012,6 @@ function setScopeTokenClassIfNecessary(elm, owner) {
|
|
|
4012
4012
|
owner.renderer.getClassList(elm).add(token);
|
|
4013
4013
|
}
|
|
4014
4014
|
}
|
|
4015
|
-
|
|
4016
4015
|
function updateNodeHook(oldVnode, vnode) {
|
|
4017
4016
|
const {
|
|
4018
4017
|
elm,
|
|
@@ -4076,6 +4075,16 @@ function createElmHook(vnode) {
|
|
|
4076
4075
|
modComputedClassName.create(vnode);
|
|
4077
4076
|
modComputedStyle.create(vnode);
|
|
4078
4077
|
}
|
|
4078
|
+
function hydrateElmHook(vnode) {
|
|
4079
|
+
modEvents.create(vnode); // Attrs are already on the element.
|
|
4080
|
+
// modAttrs.create(vnode);
|
|
4081
|
+
|
|
4082
|
+
modProps.create(vnode); // Already set.
|
|
4083
|
+
// modStaticClassName.create(vnode);
|
|
4084
|
+
// modStaticStyle.create(vnode);
|
|
4085
|
+
// modComputedClassName.create(vnode);
|
|
4086
|
+
// modComputedStyle.create(vnode);
|
|
4087
|
+
}
|
|
4079
4088
|
function fallbackElmHook(elm, vnode) {
|
|
4080
4089
|
const {
|
|
4081
4090
|
owner
|
|
@@ -4240,6 +4249,172 @@ function createChildrenHook(vnode) {
|
|
|
4240
4249
|
}
|
|
4241
4250
|
}
|
|
4242
4251
|
}
|
|
4252
|
+
|
|
4253
|
+
function isElementNode(node) {
|
|
4254
|
+
// @todo: should the hydrate be part of engine-dom? can we move hydrate out of the hooks?
|
|
4255
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4256
|
+
return node.nodeType === Node.ELEMENT_NODE;
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4259
|
+
function vnodesAndElementHaveCompatibleAttrs(vnode, elm) {
|
|
4260
|
+
const {
|
|
4261
|
+
data: {
|
|
4262
|
+
attrs = {}
|
|
4263
|
+
},
|
|
4264
|
+
owner: {
|
|
4265
|
+
renderer
|
|
4266
|
+
}
|
|
4267
|
+
} = vnode;
|
|
4268
|
+
let nodesAreCompatible = true; // Validate attributes, though we could always recovery from those by running the update mods.
|
|
4269
|
+
// Note: intentionally ONLY matching vnodes.attrs to elm.attrs, in case SSR is adding extra attributes.
|
|
4270
|
+
|
|
4271
|
+
for (const [attrName, attrValue] of Object.entries(attrs)) {
|
|
4272
|
+
const elmAttrValue = renderer.getAttribute(elm, attrName);
|
|
4273
|
+
|
|
4274
|
+
if (attrValue !== elmAttrValue) {
|
|
4275
|
+
logError(`Error hydrating element: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, vnode.owner);
|
|
4276
|
+
nodesAreCompatible = false;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
return nodesAreCompatible;
|
|
4281
|
+
}
|
|
4282
|
+
|
|
4283
|
+
function vnodesAndElementHaveCompatibleClass(vnode, elm) {
|
|
4284
|
+
const {
|
|
4285
|
+
data: {
|
|
4286
|
+
className,
|
|
4287
|
+
classMap
|
|
4288
|
+
},
|
|
4289
|
+
owner: {
|
|
4290
|
+
renderer
|
|
4291
|
+
}
|
|
4292
|
+
} = vnode;
|
|
4293
|
+
let nodesAreCompatible = true;
|
|
4294
|
+
|
|
4295
|
+
if (!shared.isUndefined(className) && className !== elm.className) {
|
|
4296
|
+
// @todo: not sure if the above comparison is correct, maybe we should normalize to classlist
|
|
4297
|
+
// className is used when class is bound to an expr.
|
|
4298
|
+
logError(`Mismatch hydrating element: attribute "class" has different values, expected "${className}" but found "${elm.className}"`, vnode.owner);
|
|
4299
|
+
nodesAreCompatible = false;
|
|
4300
|
+
} else if (!shared.isUndefined(classMap)) {
|
|
4301
|
+
// classMap is used when class is set to static value.
|
|
4302
|
+
// @todo: there might be a simpler method to do this.
|
|
4303
|
+
const classList = renderer.getClassList(elm);
|
|
4304
|
+
let hasClassMismatch = false;
|
|
4305
|
+
let computedClassName = ''; // all classes from the vnode should be in the element.classList
|
|
4306
|
+
|
|
4307
|
+
for (const name in classMap) {
|
|
4308
|
+
computedClassName += ' ' + name;
|
|
4309
|
+
|
|
4310
|
+
if (!classList.contains(name)) {
|
|
4311
|
+
nodesAreCompatible = false;
|
|
4312
|
+
hasClassMismatch = true;
|
|
4313
|
+
}
|
|
4314
|
+
} // all classes from element.classList should be in the vnode classMap
|
|
4315
|
+
|
|
4316
|
+
|
|
4317
|
+
classList.forEach(name => {
|
|
4318
|
+
if (!classMap[name]) {
|
|
4319
|
+
nodesAreCompatible = false;
|
|
4320
|
+
hasClassMismatch = true;
|
|
4321
|
+
}
|
|
4322
|
+
});
|
|
4323
|
+
|
|
4324
|
+
if (hasClassMismatch) {
|
|
4325
|
+
logError(`Mismatch hydrating element: attribute "class" has different values, expected "${computedClassName.trim()}" but found "${elm.className}"`, vnode.owner);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
return nodesAreCompatible;
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4332
|
+
function vnodesAndElementHaveCompatibleStyle(vnode, elm) {
|
|
4333
|
+
const {
|
|
4334
|
+
data: {
|
|
4335
|
+
style,
|
|
4336
|
+
styleDecls
|
|
4337
|
+
},
|
|
4338
|
+
owner: {
|
|
4339
|
+
renderer
|
|
4340
|
+
}
|
|
4341
|
+
} = vnode;
|
|
4342
|
+
const elmStyle = renderer.getAttribute(elm, 'style');
|
|
4343
|
+
let nodesAreCompatible = true; // @todo: question: would it be the same or is there a chance that the browser tweak the result of elm.setAttribute('style', ...)?
|
|
4344
|
+
// ex: such "str" exist that after elm.setAttribute('style', str), elm.getAttribute('style') !== str.
|
|
4345
|
+
|
|
4346
|
+
if (!shared.isUndefined(style) && style !== elmStyle) {
|
|
4347
|
+
// style is used when class is bound to an expr.
|
|
4348
|
+
logError(`Mismatch hydrating element: attribute "style" has different values, expected "${style}" but found "${elmStyle}".`, vnode.owner);
|
|
4349
|
+
nodesAreCompatible = false;
|
|
4350
|
+
} else if (!shared.isUndefined(styleDecls)) {
|
|
4351
|
+
// styleMap is used when class is set to static value.
|
|
4352
|
+
for (let i = 0; i < styleDecls.length; i++) {
|
|
4353
|
+
const [prop, value, important] = styleDecls[i];
|
|
4354
|
+
const elmPropValue = elm.style.getPropertyValue(prop);
|
|
4355
|
+
const elmPropPriority = elm.style.getPropertyPriority(prop);
|
|
4356
|
+
|
|
4357
|
+
if (value !== elmPropValue || important !== (elmPropPriority === 'important')) {
|
|
4358
|
+
nodesAreCompatible = false;
|
|
4359
|
+
}
|
|
4360
|
+
} // questions: is there a way to check that only those props in styleMap are set in the element?
|
|
4361
|
+
// how to generate the style?
|
|
4362
|
+
|
|
4363
|
+
|
|
4364
|
+
logError('Error hydrating element: attribute "style" has different values.', vnode.owner);
|
|
4365
|
+
}
|
|
4366
|
+
|
|
4367
|
+
return nodesAreCompatible;
|
|
4368
|
+
}
|
|
4369
|
+
|
|
4370
|
+
function throwHydrationError() {
|
|
4371
|
+
// @todo: maybe create a type for these type of hydration errors
|
|
4372
|
+
shared.assert.fail('Server rendered elements do not match client side generated elements');
|
|
4373
|
+
}
|
|
4374
|
+
|
|
4375
|
+
function hydrateChildrenHook(elmChildren, children, vm) {
|
|
4376
|
+
var _a;
|
|
4377
|
+
|
|
4378
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4379
|
+
const filteredVNodes = shared.ArrayFilter.call(children, vnode => !!vnode);
|
|
4380
|
+
|
|
4381
|
+
if (elmChildren.length !== filteredVNodes.length) {
|
|
4382
|
+
logError(`Hydration mismatch: incorrect number of rendered elements, expected ${filteredVNodes.length} but found ${elmChildren.length}.`, vm);
|
|
4383
|
+
throwHydrationError();
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
|
|
4387
|
+
let elmCurrentChildIdx = 0;
|
|
4388
|
+
|
|
4389
|
+
for (let j = 0, n = children.length; j < n; j++) {
|
|
4390
|
+
const ch = children[j];
|
|
4391
|
+
|
|
4392
|
+
if (ch != null) {
|
|
4393
|
+
const childNode = elmChildren[elmCurrentChildIdx];
|
|
4394
|
+
|
|
4395
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4396
|
+
// VComments and VTexts validation is handled in their hooks
|
|
4397
|
+
if (isElementNode(childNode)) {
|
|
4398
|
+
if (((_a = ch.sel) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== childNode.tagName.toLowerCase()) {
|
|
4399
|
+
logError(`Hydration mismatch: expecting element with tag "${ch.sel}" but found "${childNode.tagName}".`, vm);
|
|
4400
|
+
throwHydrationError();
|
|
4401
|
+
} // Note: props are not yet set
|
|
4402
|
+
|
|
4403
|
+
|
|
4404
|
+
const isVNodeAndElementCompatible = vnodesAndElementHaveCompatibleAttrs(ch, childNode) && vnodesAndElementHaveCompatibleClass(ch, childNode) && vnodesAndElementHaveCompatibleStyle(ch, childNode);
|
|
4405
|
+
|
|
4406
|
+
if (!isVNodeAndElementCompatible) {
|
|
4407
|
+
logError(`Hydration mismatch: incompatible attributes for element with tag "${childNode.tagName}".`, vm);
|
|
4408
|
+
throwHydrationError();
|
|
4409
|
+
}
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
ch.hook.hydrate(ch, childNode);
|
|
4414
|
+
elmCurrentChildIdx++;
|
|
4415
|
+
}
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4243
4418
|
function updateCustomElmHook(oldVnode, vnode) {
|
|
4244
4419
|
// Attrs need to be applied to element before props
|
|
4245
4420
|
// IE11 will wipe out value on radio inputs if value
|
|
@@ -4336,7 +4511,27 @@ const TextHook = {
|
|
|
4336
4511
|
update: updateNodeHook,
|
|
4337
4512
|
insert: insertNodeHook,
|
|
4338
4513
|
move: insertNodeHook,
|
|
4339
|
-
remove: removeNodeHook
|
|
4514
|
+
remove: removeNodeHook,
|
|
4515
|
+
hydrate: (vNode, node) => {
|
|
4516
|
+
var _a; // @todo tests.
|
|
4517
|
+
|
|
4518
|
+
|
|
4519
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4520
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4521
|
+
if (node.nodeType !== Node.TEXT_NODE) {
|
|
4522
|
+
logError('Hydration mismatch: incorrect node type received', vNode.owner);
|
|
4523
|
+
shared.assert.fail('Hydration mismatch: incorrect node type received.');
|
|
4524
|
+
}
|
|
4525
|
+
|
|
4526
|
+
if (node.nodeValue !== vNode.text) {
|
|
4527
|
+
logError('Hydration mismatch: text values do not match, will recover from the difference', vNode.owner);
|
|
4528
|
+
}
|
|
4529
|
+
} // always set the text value to the one from the vnode.
|
|
4530
|
+
|
|
4531
|
+
|
|
4532
|
+
node.nodeValue = (_a = vNode.text) !== null && _a !== void 0 ? _a : null;
|
|
4533
|
+
vNode.elm = node;
|
|
4534
|
+
}
|
|
4340
4535
|
};
|
|
4341
4536
|
const CommentHook = {
|
|
4342
4537
|
create: vnode => {
|
|
@@ -4354,7 +4549,23 @@ const CommentHook = {
|
|
|
4354
4549
|
update: updateNodeHook,
|
|
4355
4550
|
insert: insertNodeHook,
|
|
4356
4551
|
move: insertNodeHook,
|
|
4357
|
-
remove: removeNodeHook
|
|
4552
|
+
remove: removeNodeHook,
|
|
4553
|
+
hydrate: (vNode, node) => {
|
|
4554
|
+
var _a; // @todo tests.
|
|
4555
|
+
|
|
4556
|
+
|
|
4557
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4558
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4559
|
+
if (node.nodeType !== Node.COMMENT_NODE) {
|
|
4560
|
+
logError('Hydration mismatch: incorrect node type received', vNode.owner);
|
|
4561
|
+
shared.assert.fail('Hydration mismatch: incorrect node type received.');
|
|
4562
|
+
}
|
|
4563
|
+
} // always set the text value to the one from the vnode.
|
|
4564
|
+
|
|
4565
|
+
|
|
4566
|
+
node.nodeValue = (_a = vNode.text) !== null && _a !== void 0 ? _a : null;
|
|
4567
|
+
vNode.elm = node;
|
|
4568
|
+
}
|
|
4358
4569
|
}; // insert is called after update, which is used somewhere else (via a module)
|
|
4359
4570
|
// to mark the vm as inserted, that means we cannot use update as the main channel
|
|
4360
4571
|
// to rehydrate when dirty, because sometimes the element is not inserted just yet,
|
|
@@ -4394,6 +4605,12 @@ const ElementHook = {
|
|
|
4394
4605
|
remove: (vnode, parentNode) => {
|
|
4395
4606
|
removeNodeHook(vnode, parentNode);
|
|
4396
4607
|
removeElmHook(vnode);
|
|
4608
|
+
},
|
|
4609
|
+
hydrate: (vnode, node) => {
|
|
4610
|
+
vnode.elm = node;
|
|
4611
|
+
hydrateElmHook(vnode); // hydrate children hook
|
|
4612
|
+
|
|
4613
|
+
hydrateChildrenHook(vnode.elm.childNodes, vnode.children, vnode.owner);
|
|
4397
4614
|
}
|
|
4398
4615
|
};
|
|
4399
4616
|
const CustomElementHook = {
|
|
@@ -4485,6 +4702,52 @@ const CustomElementHook = {
|
|
|
4485
4702
|
// will take care of disconnecting any child VM attached to its shadow as well.
|
|
4486
4703
|
removeVM(vm);
|
|
4487
4704
|
}
|
|
4705
|
+
},
|
|
4706
|
+
hydrate: (vnode, elm) => {
|
|
4707
|
+
// the element is created, but the vm is not
|
|
4708
|
+
const {
|
|
4709
|
+
sel,
|
|
4710
|
+
mode,
|
|
4711
|
+
ctor,
|
|
4712
|
+
owner
|
|
4713
|
+
} = vnode;
|
|
4714
|
+
const def = getComponentInternalDef(ctor);
|
|
4715
|
+
createVM(elm, def, {
|
|
4716
|
+
mode,
|
|
4717
|
+
owner,
|
|
4718
|
+
tagName: sel,
|
|
4719
|
+
renderer: owner.renderer
|
|
4720
|
+
});
|
|
4721
|
+
vnode.elm = elm;
|
|
4722
|
+
const vm = getAssociatedVMIfPresent(elm);
|
|
4723
|
+
|
|
4724
|
+
if (vm) {
|
|
4725
|
+
allocateChildrenHook(vnode, vm);
|
|
4726
|
+
}
|
|
4727
|
+
|
|
4728
|
+
hydrateElmHook(vnode); // Insert hook section:
|
|
4729
|
+
|
|
4730
|
+
if (vm) {
|
|
4731
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4732
|
+
shared.assert.isTrue(vm.state === 0
|
|
4733
|
+
/* created */
|
|
4734
|
+
, `${vm} cannot be recycled.`);
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
runConnectedCallback(vm);
|
|
4738
|
+
}
|
|
4739
|
+
|
|
4740
|
+
if (!(vm && vm.renderMode === 0
|
|
4741
|
+
/* Light */
|
|
4742
|
+
)) {
|
|
4743
|
+
// VM is not rendering in Light DOM, we can proceed and hydrate the slotted content.
|
|
4744
|
+
// Note: for Light DOM, this is handled while hydrating the VM
|
|
4745
|
+
hydrateChildrenHook(vnode.elm.childNodes, vnode.children, vm);
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
if (vm) {
|
|
4749
|
+
hydrateVM(vm);
|
|
4750
|
+
}
|
|
4488
4751
|
}
|
|
4489
4752
|
};
|
|
4490
4753
|
|
|
@@ -5135,7 +5398,7 @@ function createStylesheet(vm, stylesheets) {
|
|
|
5135
5398
|
for (let i = 0; i < stylesheets.length; i++) {
|
|
5136
5399
|
renderer.insertGlobalStylesheet(stylesheets[i]);
|
|
5137
5400
|
}
|
|
5138
|
-
} else if (renderer.ssr) {
|
|
5401
|
+
} else if (renderer.ssr || renderer.isHydrating) {
|
|
5139
5402
|
// native shadow or light DOM, SSR
|
|
5140
5403
|
const combinedStylesheetContent = shared.ArrayJoin.call(stylesheets, '\n');
|
|
5141
5404
|
return createInlineStyleVNode(combinedStylesheetContent);
|
|
@@ -5321,9 +5584,9 @@ function validateLightDomTemplate(template, vm) {
|
|
|
5321
5584
|
if (vm.renderMode === 0
|
|
5322
5585
|
/* Light */
|
|
5323
5586
|
) {
|
|
5324
|
-
shared.assert.isTrue(template.renderMode === 'light', `Light DOM components can't render shadow DOM templates. Add an 'lwc:render-mode="light"' directive
|
|
5587
|
+
shared.assert.isTrue(template.renderMode === 'light', `Light DOM components can't render shadow DOM templates. Add an 'lwc:render-mode="light"' directive to the root template tag of ${getComponentTag(vm)}.`);
|
|
5325
5588
|
} else {
|
|
5326
|
-
shared.assert.isTrue(shared.isUndefined(template.renderMode), `Shadow DOM components template can't render light DOM templates. Either remove the 'lwc:render-mode' directive or set it to 'lwc:render-mode="shadow"`);
|
|
5589
|
+
shared.assert.isTrue(shared.isUndefined(template.renderMode), `Shadow DOM components template can't render light DOM templates. Either remove the 'lwc:render-mode' directive from ${getComponentTag(vm)} or set it to 'lwc:render-mode="shadow"`);
|
|
5327
5590
|
}
|
|
5328
5591
|
}
|
|
5329
5592
|
|
|
@@ -5732,12 +5995,28 @@ function connectRootElement(elm) {
|
|
|
5732
5995
|
/* GlobalHydrate */
|
|
5733
5996
|
, vm);
|
|
5734
5997
|
}
|
|
5998
|
+
function hydrateRootElement(elm) {
|
|
5999
|
+
const vm = getAssociatedVM(elm); // Usually means moving the element from one place to another, which is observable via
|
|
6000
|
+
// life-cycle hooks.
|
|
6001
|
+
|
|
6002
|
+
if (vm.state === 1
|
|
6003
|
+
/* connected */
|
|
6004
|
+
) {
|
|
6005
|
+
disconnectRootElement(elm);
|
|
6006
|
+
}
|
|
6007
|
+
|
|
6008
|
+
runConnectedCallback(vm);
|
|
6009
|
+
hydrateVM(vm); // should we hydrate the root children? light dom case.
|
|
6010
|
+
}
|
|
5735
6011
|
function disconnectRootElement(elm) {
|
|
5736
6012
|
const vm = getAssociatedVM(elm);
|
|
5737
6013
|
resetComponentStateWhenRemoved(vm);
|
|
5738
6014
|
}
|
|
5739
6015
|
function appendVM(vm) {
|
|
5740
6016
|
rehydrate(vm);
|
|
6017
|
+
}
|
|
6018
|
+
function hydrateVM(vm) {
|
|
6019
|
+
hydrate(vm);
|
|
5741
6020
|
} // just in case the component comes back, with this we guarantee re-rendering it
|
|
5742
6021
|
// while preventing any attempt to rehydration until after reinsertion.
|
|
5743
6022
|
|
|
@@ -5962,6 +6241,22 @@ function rehydrate(vm) {
|
|
|
5962
6241
|
}
|
|
5963
6242
|
}
|
|
5964
6243
|
|
|
6244
|
+
function hydrate(vm) {
|
|
6245
|
+
if (shared.isTrue(vm.isDirty)) {
|
|
6246
|
+
// manually diffing/patching here.
|
|
6247
|
+
// This routine is:
|
|
6248
|
+
// patchShadowRoot(vm, children);
|
|
6249
|
+
// -> addVnodes.
|
|
6250
|
+
const children = renderComponent(vm);
|
|
6251
|
+
vm.children = children;
|
|
6252
|
+
const vmChildren = vm.renderMode === 0
|
|
6253
|
+
/* Light */
|
|
6254
|
+
? vm.elm.childNodes : vm.elm.shadowRoot.childNodes;
|
|
6255
|
+
hydrateChildrenHook(vmChildren, children, vm);
|
|
6256
|
+
runRenderedCallback(vm);
|
|
6257
|
+
}
|
|
6258
|
+
}
|
|
6259
|
+
|
|
5965
6260
|
function patchShadowRoot(vm, newCh) {
|
|
5966
6261
|
const {
|
|
5967
6262
|
children: oldCh
|
|
@@ -6788,6 +7083,7 @@ exports.getAssociatedVMIfPresent = getAssociatedVMIfPresent;
|
|
|
6788
7083
|
exports.getComponentDef = getComponentDef;
|
|
6789
7084
|
exports.getComponentInternalDef = getComponentInternalDef;
|
|
6790
7085
|
exports.getUpgradableConstructor = getUpgradableConstructor;
|
|
7086
|
+
exports.hydrateRootElement = hydrateRootElement;
|
|
6791
7087
|
exports.isComponentConstructor = isComponentConstructor;
|
|
6792
7088
|
exports.readonly = readonly;
|
|
6793
7089
|
exports.register = register;
|
|
@@ -6801,4 +7097,4 @@ exports.swapTemplate = swapTemplate;
|
|
|
6801
7097
|
exports.track = track;
|
|
6802
7098
|
exports.unwrap = unwrap;
|
|
6803
7099
|
exports.wire = wire;
|
|
6804
|
-
/* version: 2.5.
|
|
7100
|
+
/* version: 2.5.2-canary1 */
|
package/dist/engine-core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* proxy-compat-disable */
|
|
2
|
-
import { seal, create, isFunction as isFunction$1, ArrayPush as ArrayPush$1, isUndefined as isUndefined$1, ArrayIndexOf, ArraySplice, StringToLowerCase, ArrayJoin, isNull, assign, assert, keys, StringCharCodeAt, isString, StringSlice, freeze, defineProperties, forEach, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, getPropertyDescriptor, isObject, AriaPropNameToAttrNameMap, defineProperty, KEY__SYNTHETIC_MODE, toString as toString$1, isFalse, isTrue, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, htmlPropertyToAttribute, ArraySlice, hasOwnProperty as hasOwnProperty$1, noop, isArray as isArray$1, isNumber, StringReplace, KEY__SHADOW_RESOLVER, KEY__SCOPED_CSS, ArrayUnshift, isFrozen } from '@lwc/shared';
|
|
2
|
+
import { seal, create, isFunction as isFunction$1, ArrayPush as ArrayPush$1, isUndefined as isUndefined$1, ArrayIndexOf, ArraySplice, StringToLowerCase, ArrayJoin, isNull, assign, assert, keys, StringCharCodeAt, isString, StringSlice, freeze, defineProperties, forEach, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, getPropertyDescriptor, isObject, AriaPropNameToAttrNameMap, defineProperty, KEY__SYNTHETIC_MODE, toString as toString$1, isFalse, isTrue, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, htmlPropertyToAttribute, ArraySlice, hasOwnProperty as hasOwnProperty$1, ArrayFilter, noop, isArray as isArray$1, isNumber, StringReplace, KEY__SHADOW_RESOLVER, KEY__SCOPED_CSS, ArrayUnshift, isFrozen } from '@lwc/shared';
|
|
3
3
|
import { runtimeFlags } from '@lwc/features';
|
|
4
4
|
export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
|
|
5
5
|
|
|
@@ -4009,7 +4009,6 @@ function setScopeTokenClassIfNecessary(elm, owner) {
|
|
|
4009
4009
|
owner.renderer.getClassList(elm).add(token);
|
|
4010
4010
|
}
|
|
4011
4011
|
}
|
|
4012
|
-
|
|
4013
4012
|
function updateNodeHook(oldVnode, vnode) {
|
|
4014
4013
|
const {
|
|
4015
4014
|
elm,
|
|
@@ -4073,6 +4072,16 @@ function createElmHook(vnode) {
|
|
|
4073
4072
|
modComputedClassName.create(vnode);
|
|
4074
4073
|
modComputedStyle.create(vnode);
|
|
4075
4074
|
}
|
|
4075
|
+
function hydrateElmHook(vnode) {
|
|
4076
|
+
modEvents.create(vnode); // Attrs are already on the element.
|
|
4077
|
+
// modAttrs.create(vnode);
|
|
4078
|
+
|
|
4079
|
+
modProps.create(vnode); // Already set.
|
|
4080
|
+
// modStaticClassName.create(vnode);
|
|
4081
|
+
// modStaticStyle.create(vnode);
|
|
4082
|
+
// modComputedClassName.create(vnode);
|
|
4083
|
+
// modComputedStyle.create(vnode);
|
|
4084
|
+
}
|
|
4076
4085
|
function fallbackElmHook(elm, vnode) {
|
|
4077
4086
|
const {
|
|
4078
4087
|
owner
|
|
@@ -4237,6 +4246,172 @@ function createChildrenHook(vnode) {
|
|
|
4237
4246
|
}
|
|
4238
4247
|
}
|
|
4239
4248
|
}
|
|
4249
|
+
|
|
4250
|
+
function isElementNode(node) {
|
|
4251
|
+
// @todo: should the hydrate be part of engine-dom? can we move hydrate out of the hooks?
|
|
4252
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4253
|
+
return node.nodeType === Node.ELEMENT_NODE;
|
|
4254
|
+
}
|
|
4255
|
+
|
|
4256
|
+
function vnodesAndElementHaveCompatibleAttrs(vnode, elm) {
|
|
4257
|
+
const {
|
|
4258
|
+
data: {
|
|
4259
|
+
attrs = {}
|
|
4260
|
+
},
|
|
4261
|
+
owner: {
|
|
4262
|
+
renderer
|
|
4263
|
+
}
|
|
4264
|
+
} = vnode;
|
|
4265
|
+
let nodesAreCompatible = true; // Validate attributes, though we could always recovery from those by running the update mods.
|
|
4266
|
+
// Note: intentionally ONLY matching vnodes.attrs to elm.attrs, in case SSR is adding extra attributes.
|
|
4267
|
+
|
|
4268
|
+
for (const [attrName, attrValue] of Object.entries(attrs)) {
|
|
4269
|
+
const elmAttrValue = renderer.getAttribute(elm, attrName);
|
|
4270
|
+
|
|
4271
|
+
if (attrValue !== elmAttrValue) {
|
|
4272
|
+
logError(`Error hydrating element: attribute "${attrName}" has different values, expected "${attrValue}" but found "${elmAttrValue}"`, vnode.owner);
|
|
4273
|
+
nodesAreCompatible = false;
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
|
|
4277
|
+
return nodesAreCompatible;
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
function vnodesAndElementHaveCompatibleClass(vnode, elm) {
|
|
4281
|
+
const {
|
|
4282
|
+
data: {
|
|
4283
|
+
className,
|
|
4284
|
+
classMap
|
|
4285
|
+
},
|
|
4286
|
+
owner: {
|
|
4287
|
+
renderer
|
|
4288
|
+
}
|
|
4289
|
+
} = vnode;
|
|
4290
|
+
let nodesAreCompatible = true;
|
|
4291
|
+
|
|
4292
|
+
if (!isUndefined$1(className) && className !== elm.className) {
|
|
4293
|
+
// @todo: not sure if the above comparison is correct, maybe we should normalize to classlist
|
|
4294
|
+
// className is used when class is bound to an expr.
|
|
4295
|
+
logError(`Mismatch hydrating element: attribute "class" has different values, expected "${className}" but found "${elm.className}"`, vnode.owner);
|
|
4296
|
+
nodesAreCompatible = false;
|
|
4297
|
+
} else if (!isUndefined$1(classMap)) {
|
|
4298
|
+
// classMap is used when class is set to static value.
|
|
4299
|
+
// @todo: there might be a simpler method to do this.
|
|
4300
|
+
const classList = renderer.getClassList(elm);
|
|
4301
|
+
let hasClassMismatch = false;
|
|
4302
|
+
let computedClassName = ''; // all classes from the vnode should be in the element.classList
|
|
4303
|
+
|
|
4304
|
+
for (const name in classMap) {
|
|
4305
|
+
computedClassName += ' ' + name;
|
|
4306
|
+
|
|
4307
|
+
if (!classList.contains(name)) {
|
|
4308
|
+
nodesAreCompatible = false;
|
|
4309
|
+
hasClassMismatch = true;
|
|
4310
|
+
}
|
|
4311
|
+
} // all classes from element.classList should be in the vnode classMap
|
|
4312
|
+
|
|
4313
|
+
|
|
4314
|
+
classList.forEach(name => {
|
|
4315
|
+
if (!classMap[name]) {
|
|
4316
|
+
nodesAreCompatible = false;
|
|
4317
|
+
hasClassMismatch = true;
|
|
4318
|
+
}
|
|
4319
|
+
});
|
|
4320
|
+
|
|
4321
|
+
if (hasClassMismatch) {
|
|
4322
|
+
logError(`Mismatch hydrating element: attribute "class" has different values, expected "${computedClassName.trim()}" but found "${elm.className}"`, vnode.owner);
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
|
|
4326
|
+
return nodesAreCompatible;
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
function vnodesAndElementHaveCompatibleStyle(vnode, elm) {
|
|
4330
|
+
const {
|
|
4331
|
+
data: {
|
|
4332
|
+
style,
|
|
4333
|
+
styleDecls
|
|
4334
|
+
},
|
|
4335
|
+
owner: {
|
|
4336
|
+
renderer
|
|
4337
|
+
}
|
|
4338
|
+
} = vnode;
|
|
4339
|
+
const elmStyle = renderer.getAttribute(elm, 'style');
|
|
4340
|
+
let nodesAreCompatible = true; // @todo: question: would it be the same or is there a chance that the browser tweak the result of elm.setAttribute('style', ...)?
|
|
4341
|
+
// ex: such "str" exist that after elm.setAttribute('style', str), elm.getAttribute('style') !== str.
|
|
4342
|
+
|
|
4343
|
+
if (!isUndefined$1(style) && style !== elmStyle) {
|
|
4344
|
+
// style is used when class is bound to an expr.
|
|
4345
|
+
logError(`Mismatch hydrating element: attribute "style" has different values, expected "${style}" but found "${elmStyle}".`, vnode.owner);
|
|
4346
|
+
nodesAreCompatible = false;
|
|
4347
|
+
} else if (!isUndefined$1(styleDecls)) {
|
|
4348
|
+
// styleMap is used when class is set to static value.
|
|
4349
|
+
for (let i = 0; i < styleDecls.length; i++) {
|
|
4350
|
+
const [prop, value, important] = styleDecls[i];
|
|
4351
|
+
const elmPropValue = elm.style.getPropertyValue(prop);
|
|
4352
|
+
const elmPropPriority = elm.style.getPropertyPriority(prop);
|
|
4353
|
+
|
|
4354
|
+
if (value !== elmPropValue || important !== (elmPropPriority === 'important')) {
|
|
4355
|
+
nodesAreCompatible = false;
|
|
4356
|
+
}
|
|
4357
|
+
} // questions: is there a way to check that only those props in styleMap are set in the element?
|
|
4358
|
+
// how to generate the style?
|
|
4359
|
+
|
|
4360
|
+
|
|
4361
|
+
logError('Error hydrating element: attribute "style" has different values.', vnode.owner);
|
|
4362
|
+
}
|
|
4363
|
+
|
|
4364
|
+
return nodesAreCompatible;
|
|
4365
|
+
}
|
|
4366
|
+
|
|
4367
|
+
function throwHydrationError() {
|
|
4368
|
+
// @todo: maybe create a type for these type of hydration errors
|
|
4369
|
+
assert.fail('Server rendered elements do not match client side generated elements');
|
|
4370
|
+
}
|
|
4371
|
+
|
|
4372
|
+
function hydrateChildrenHook(elmChildren, children, vm) {
|
|
4373
|
+
var _a;
|
|
4374
|
+
|
|
4375
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4376
|
+
const filteredVNodes = ArrayFilter.call(children, vnode => !!vnode);
|
|
4377
|
+
|
|
4378
|
+
if (elmChildren.length !== filteredVNodes.length) {
|
|
4379
|
+
logError(`Hydration mismatch: incorrect number of rendered elements, expected ${filteredVNodes.length} but found ${elmChildren.length}.`, vm);
|
|
4380
|
+
throwHydrationError();
|
|
4381
|
+
}
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
let elmCurrentChildIdx = 0;
|
|
4385
|
+
|
|
4386
|
+
for (let j = 0, n = children.length; j < n; j++) {
|
|
4387
|
+
const ch = children[j];
|
|
4388
|
+
|
|
4389
|
+
if (ch != null) {
|
|
4390
|
+
const childNode = elmChildren[elmCurrentChildIdx];
|
|
4391
|
+
|
|
4392
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4393
|
+
// VComments and VTexts validation is handled in their hooks
|
|
4394
|
+
if (isElementNode(childNode)) {
|
|
4395
|
+
if (((_a = ch.sel) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== childNode.tagName.toLowerCase()) {
|
|
4396
|
+
logError(`Hydration mismatch: expecting element with tag "${ch.sel}" but found "${childNode.tagName}".`, vm);
|
|
4397
|
+
throwHydrationError();
|
|
4398
|
+
} // Note: props are not yet set
|
|
4399
|
+
|
|
4400
|
+
|
|
4401
|
+
const isVNodeAndElementCompatible = vnodesAndElementHaveCompatibleAttrs(ch, childNode) && vnodesAndElementHaveCompatibleClass(ch, childNode) && vnodesAndElementHaveCompatibleStyle(ch, childNode);
|
|
4402
|
+
|
|
4403
|
+
if (!isVNodeAndElementCompatible) {
|
|
4404
|
+
logError(`Hydration mismatch: incompatible attributes for element with tag "${childNode.tagName}".`, vm);
|
|
4405
|
+
throwHydrationError();
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4410
|
+
ch.hook.hydrate(ch, childNode);
|
|
4411
|
+
elmCurrentChildIdx++;
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4414
|
+
}
|
|
4240
4415
|
function updateCustomElmHook(oldVnode, vnode) {
|
|
4241
4416
|
// Attrs need to be applied to element before props
|
|
4242
4417
|
// IE11 will wipe out value on radio inputs if value
|
|
@@ -4333,7 +4508,27 @@ const TextHook = {
|
|
|
4333
4508
|
update: updateNodeHook,
|
|
4334
4509
|
insert: insertNodeHook,
|
|
4335
4510
|
move: insertNodeHook,
|
|
4336
|
-
remove: removeNodeHook
|
|
4511
|
+
remove: removeNodeHook,
|
|
4512
|
+
hydrate: (vNode, node) => {
|
|
4513
|
+
var _a; // @todo tests.
|
|
4514
|
+
|
|
4515
|
+
|
|
4516
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4517
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4518
|
+
if (node.nodeType !== Node.TEXT_NODE) {
|
|
4519
|
+
logError('Hydration mismatch: incorrect node type received', vNode.owner);
|
|
4520
|
+
assert.fail('Hydration mismatch: incorrect node type received.');
|
|
4521
|
+
}
|
|
4522
|
+
|
|
4523
|
+
if (node.nodeValue !== vNode.text) {
|
|
4524
|
+
logError('Hydration mismatch: text values do not match, will recover from the difference', vNode.owner);
|
|
4525
|
+
}
|
|
4526
|
+
} // always set the text value to the one from the vnode.
|
|
4527
|
+
|
|
4528
|
+
|
|
4529
|
+
node.nodeValue = (_a = vNode.text) !== null && _a !== void 0 ? _a : null;
|
|
4530
|
+
vNode.elm = node;
|
|
4531
|
+
}
|
|
4337
4532
|
};
|
|
4338
4533
|
const CommentHook = {
|
|
4339
4534
|
create: vnode => {
|
|
@@ -4351,7 +4546,23 @@ const CommentHook = {
|
|
|
4351
4546
|
update: updateNodeHook,
|
|
4352
4547
|
insert: insertNodeHook,
|
|
4353
4548
|
move: insertNodeHook,
|
|
4354
|
-
remove: removeNodeHook
|
|
4549
|
+
remove: removeNodeHook,
|
|
4550
|
+
hydrate: (vNode, node) => {
|
|
4551
|
+
var _a; // @todo tests.
|
|
4552
|
+
|
|
4553
|
+
|
|
4554
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4555
|
+
// eslint-disable-next-line lwc-internal/no-global-node
|
|
4556
|
+
if (node.nodeType !== Node.COMMENT_NODE) {
|
|
4557
|
+
logError('Hydration mismatch: incorrect node type received', vNode.owner);
|
|
4558
|
+
assert.fail('Hydration mismatch: incorrect node type received.');
|
|
4559
|
+
}
|
|
4560
|
+
} // always set the text value to the one from the vnode.
|
|
4561
|
+
|
|
4562
|
+
|
|
4563
|
+
node.nodeValue = (_a = vNode.text) !== null && _a !== void 0 ? _a : null;
|
|
4564
|
+
vNode.elm = node;
|
|
4565
|
+
}
|
|
4355
4566
|
}; // insert is called after update, which is used somewhere else (via a module)
|
|
4356
4567
|
// to mark the vm as inserted, that means we cannot use update as the main channel
|
|
4357
4568
|
// to rehydrate when dirty, because sometimes the element is not inserted just yet,
|
|
@@ -4391,6 +4602,12 @@ const ElementHook = {
|
|
|
4391
4602
|
remove: (vnode, parentNode) => {
|
|
4392
4603
|
removeNodeHook(vnode, parentNode);
|
|
4393
4604
|
removeElmHook(vnode);
|
|
4605
|
+
},
|
|
4606
|
+
hydrate: (vnode, node) => {
|
|
4607
|
+
vnode.elm = node;
|
|
4608
|
+
hydrateElmHook(vnode); // hydrate children hook
|
|
4609
|
+
|
|
4610
|
+
hydrateChildrenHook(vnode.elm.childNodes, vnode.children, vnode.owner);
|
|
4394
4611
|
}
|
|
4395
4612
|
};
|
|
4396
4613
|
const CustomElementHook = {
|
|
@@ -4482,6 +4699,52 @@ const CustomElementHook = {
|
|
|
4482
4699
|
// will take care of disconnecting any child VM attached to its shadow as well.
|
|
4483
4700
|
removeVM(vm);
|
|
4484
4701
|
}
|
|
4702
|
+
},
|
|
4703
|
+
hydrate: (vnode, elm) => {
|
|
4704
|
+
// the element is created, but the vm is not
|
|
4705
|
+
const {
|
|
4706
|
+
sel,
|
|
4707
|
+
mode,
|
|
4708
|
+
ctor,
|
|
4709
|
+
owner
|
|
4710
|
+
} = vnode;
|
|
4711
|
+
const def = getComponentInternalDef(ctor);
|
|
4712
|
+
createVM(elm, def, {
|
|
4713
|
+
mode,
|
|
4714
|
+
owner,
|
|
4715
|
+
tagName: sel,
|
|
4716
|
+
renderer: owner.renderer
|
|
4717
|
+
});
|
|
4718
|
+
vnode.elm = elm;
|
|
4719
|
+
const vm = getAssociatedVMIfPresent(elm);
|
|
4720
|
+
|
|
4721
|
+
if (vm) {
|
|
4722
|
+
allocateChildrenHook(vnode, vm);
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
hydrateElmHook(vnode); // Insert hook section:
|
|
4726
|
+
|
|
4727
|
+
if (vm) {
|
|
4728
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4729
|
+
assert.isTrue(vm.state === 0
|
|
4730
|
+
/* created */
|
|
4731
|
+
, `${vm} cannot be recycled.`);
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4734
|
+
runConnectedCallback(vm);
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
if (!(vm && vm.renderMode === 0
|
|
4738
|
+
/* Light */
|
|
4739
|
+
)) {
|
|
4740
|
+
// VM is not rendering in Light DOM, we can proceed and hydrate the slotted content.
|
|
4741
|
+
// Note: for Light DOM, this is handled while hydrating the VM
|
|
4742
|
+
hydrateChildrenHook(vnode.elm.childNodes, vnode.children, vm);
|
|
4743
|
+
}
|
|
4744
|
+
|
|
4745
|
+
if (vm) {
|
|
4746
|
+
hydrateVM(vm);
|
|
4747
|
+
}
|
|
4485
4748
|
}
|
|
4486
4749
|
};
|
|
4487
4750
|
|
|
@@ -5132,7 +5395,7 @@ function createStylesheet(vm, stylesheets) {
|
|
|
5132
5395
|
for (let i = 0; i < stylesheets.length; i++) {
|
|
5133
5396
|
renderer.insertGlobalStylesheet(stylesheets[i]);
|
|
5134
5397
|
}
|
|
5135
|
-
} else if (renderer.ssr) {
|
|
5398
|
+
} else if (renderer.ssr || renderer.isHydrating) {
|
|
5136
5399
|
// native shadow or light DOM, SSR
|
|
5137
5400
|
const combinedStylesheetContent = ArrayJoin.call(stylesheets, '\n');
|
|
5138
5401
|
return createInlineStyleVNode(combinedStylesheetContent);
|
|
@@ -5318,9 +5581,9 @@ function validateLightDomTemplate(template, vm) {
|
|
|
5318
5581
|
if (vm.renderMode === 0
|
|
5319
5582
|
/* Light */
|
|
5320
5583
|
) {
|
|
5321
|
-
assert.isTrue(template.renderMode === 'light', `Light DOM components can't render shadow DOM templates. Add an 'lwc:render-mode="light"' directive
|
|
5584
|
+
assert.isTrue(template.renderMode === 'light', `Light DOM components can't render shadow DOM templates. Add an 'lwc:render-mode="light"' directive to the root template tag of ${getComponentTag(vm)}.`);
|
|
5322
5585
|
} else {
|
|
5323
|
-
assert.isTrue(isUndefined$1(template.renderMode), `Shadow DOM components template can't render light DOM templates. Either remove the 'lwc:render-mode' directive or set it to 'lwc:render-mode="shadow"`);
|
|
5586
|
+
assert.isTrue(isUndefined$1(template.renderMode), `Shadow DOM components template can't render light DOM templates. Either remove the 'lwc:render-mode' directive from ${getComponentTag(vm)} or set it to 'lwc:render-mode="shadow"`);
|
|
5324
5587
|
}
|
|
5325
5588
|
}
|
|
5326
5589
|
|
|
@@ -5729,12 +5992,28 @@ function connectRootElement(elm) {
|
|
|
5729
5992
|
/* GlobalHydrate */
|
|
5730
5993
|
, vm);
|
|
5731
5994
|
}
|
|
5995
|
+
function hydrateRootElement(elm) {
|
|
5996
|
+
const vm = getAssociatedVM(elm); // Usually means moving the element from one place to another, which is observable via
|
|
5997
|
+
// life-cycle hooks.
|
|
5998
|
+
|
|
5999
|
+
if (vm.state === 1
|
|
6000
|
+
/* connected */
|
|
6001
|
+
) {
|
|
6002
|
+
disconnectRootElement(elm);
|
|
6003
|
+
}
|
|
6004
|
+
|
|
6005
|
+
runConnectedCallback(vm);
|
|
6006
|
+
hydrateVM(vm); // should we hydrate the root children? light dom case.
|
|
6007
|
+
}
|
|
5732
6008
|
function disconnectRootElement(elm) {
|
|
5733
6009
|
const vm = getAssociatedVM(elm);
|
|
5734
6010
|
resetComponentStateWhenRemoved(vm);
|
|
5735
6011
|
}
|
|
5736
6012
|
function appendVM(vm) {
|
|
5737
6013
|
rehydrate(vm);
|
|
6014
|
+
}
|
|
6015
|
+
function hydrateVM(vm) {
|
|
6016
|
+
hydrate(vm);
|
|
5738
6017
|
} // just in case the component comes back, with this we guarantee re-rendering it
|
|
5739
6018
|
// while preventing any attempt to rehydration until after reinsertion.
|
|
5740
6019
|
|
|
@@ -5959,6 +6238,22 @@ function rehydrate(vm) {
|
|
|
5959
6238
|
}
|
|
5960
6239
|
}
|
|
5961
6240
|
|
|
6241
|
+
function hydrate(vm) {
|
|
6242
|
+
if (isTrue(vm.isDirty)) {
|
|
6243
|
+
// manually diffing/patching here.
|
|
6244
|
+
// This routine is:
|
|
6245
|
+
// patchShadowRoot(vm, children);
|
|
6246
|
+
// -> addVnodes.
|
|
6247
|
+
const children = renderComponent(vm);
|
|
6248
|
+
vm.children = children;
|
|
6249
|
+
const vmChildren = vm.renderMode === 0
|
|
6250
|
+
/* Light */
|
|
6251
|
+
? vm.elm.childNodes : vm.elm.shadowRoot.childNodes;
|
|
6252
|
+
hydrateChildrenHook(vmChildren, children, vm);
|
|
6253
|
+
runRenderedCallback(vm);
|
|
6254
|
+
}
|
|
6255
|
+
}
|
|
6256
|
+
|
|
5962
6257
|
function patchShadowRoot(vm, newCh) {
|
|
5963
6258
|
const {
|
|
5964
6259
|
children: oldCh
|
|
@@ -6762,5 +7057,5 @@ function readonly(obj) {
|
|
|
6762
7057
|
return reactiveMembrane.getReadOnlyProxy(obj);
|
|
6763
7058
|
}
|
|
6764
7059
|
|
|
6765
|
-
export { LightningElement, profilerControl as __unstable__ProfilerControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, getAssociatedVMIfPresent, getComponentDef, getComponentInternalDef, getUpgradableConstructor, isComponentConstructor, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
|
|
6766
|
-
/* version: 2.5.
|
|
7060
|
+
export { LightningElement, profilerControl as __unstable__ProfilerControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, getAssociatedVMIfPresent, getComponentDef, getComponentInternalDef, getUpgradableConstructor, hydrateRootElement, isComponentConstructor, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
|
|
7061
|
+
/* version: 2.5.2-canary1 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lwc/engine-core",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.2-canary1",
|
|
4
4
|
"description": "Core LWC engine APIs.",
|
|
5
5
|
"homepage": "https://lwc.dev/",
|
|
6
6
|
"repository": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"types/"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@lwc/features": "2.5.
|
|
28
|
-
"@lwc/shared": "2.5.
|
|
27
|
+
"@lwc/features": "2.5.2-canary1",
|
|
28
|
+
"@lwc/shared": "2.5.2-canary1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"observable-membrane": "1.0.1"
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "9704f323be88e79bbffb964e4805e6cbf18556ec"
|
|
37
37
|
}
|
|
@@ -70,6 +70,7 @@ export interface Hooks<N extends VNode> {
|
|
|
70
70
|
move: (vNode: N, parentNode: Node, referenceNode: Node | null) => void;
|
|
71
71
|
update: (oldVNode: N, vNode: N) => void;
|
|
72
72
|
remove: (vNode: N, parentNode: Node) => void;
|
|
73
|
+
hydrate: (vNode: N, node: Node) => void;
|
|
73
74
|
}
|
|
74
75
|
export interface Module<N extends VNode> {
|
|
75
76
|
create?: (vNode: N) => void;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { VM } from './vm';
|
|
2
2
|
import { VNode, VCustomElement, VElement, VNodes } from '../3rdparty/snabbdom/types';
|
|
3
|
+
export declare function hydrateNodeHook(vNode: VNode, node: Node): void;
|
|
3
4
|
export declare function updateNodeHook(oldVnode: VNode, vnode: VNode): void;
|
|
4
5
|
export declare function insertNodeHook(vnode: VNode, parentNode: Node, referenceNode: Node | null): void;
|
|
5
6
|
export declare function removeNodeHook(vnode: VNode, parentNode: Node): void;
|
|
6
7
|
export declare function createElmHook(vnode: VElement): void;
|
|
8
|
+
export declare function hydrateElmHook(vnode: VElement): void;
|
|
7
9
|
export declare function fallbackElmHook(elm: Element, vnode: VElement): void;
|
|
8
10
|
export declare function updateElmHook(oldVnode: VElement, vnode: VElement): void;
|
|
9
11
|
export declare function updateChildrenHook(oldVnode: VElement, vnode: VElement): void;
|
|
@@ -11,6 +13,7 @@ export declare function allocateChildrenHook(vnode: VCustomElement, vm: VM): voi
|
|
|
11
13
|
export declare function createViewModelHook(elm: HTMLElement, vnode: VCustomElement): void;
|
|
12
14
|
export declare function createCustomElmHook(vnode: VCustomElement): void;
|
|
13
15
|
export declare function createChildrenHook(vnode: VElement): void;
|
|
16
|
+
export declare function hydrateChildrenHook(elmChildren: NodeListOf<ChildNode>, children: VNodes, vm?: VM): void;
|
|
14
17
|
export declare function updateCustomElmHook(oldVnode: VCustomElement, vnode: VCustomElement): void;
|
|
15
18
|
export declare function removeElmHook(vnode: VElement): void;
|
|
16
19
|
export declare function markAsDynamicChildren(children: VNodes): void;
|
|
@@ -7,7 +7,7 @@ export { default as wire } from './decorators/wire';
|
|
|
7
7
|
export { readonly } from './readonly';
|
|
8
8
|
export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
|
|
9
9
|
export { getComponentInternalDef } from './def';
|
|
10
|
-
export { createVM, connectRootElement, disconnectRootElement, getAssociatedVMIfPresent, } from './vm';
|
|
10
|
+
export { createVM, connectRootElement, disconnectRootElement, getAssociatedVMIfPresent, hydrateRootElement, } from './vm';
|
|
11
11
|
export { registerComponent } from './component';
|
|
12
12
|
export { registerTemplate } from './secure-template';
|
|
13
13
|
export { registerDecorators } from './decorators/register';
|
|
@@ -2,6 +2,7 @@ export declare type HostNode = any;
|
|
|
2
2
|
export declare type HostElement = any;
|
|
3
3
|
export interface Renderer<N = HostNode, E = HostElement> {
|
|
4
4
|
ssr: boolean;
|
|
5
|
+
readonly isHydrating: boolean;
|
|
5
6
|
isNativeShadowDefined: boolean;
|
|
6
7
|
isSyntheticShadowDefined: boolean;
|
|
7
8
|
insert(node: N, parent: E, anchor: N | null): void;
|
package/types/framework/vm.d.ts
CHANGED
|
@@ -118,8 +118,10 @@ export interface VM<N = HostNode, E = HostElement> {
|
|
|
118
118
|
declare type VMAssociable = HostNode | LightningElement;
|
|
119
119
|
export declare function rerenderVM(vm: VM): void;
|
|
120
120
|
export declare function connectRootElement(elm: any): void;
|
|
121
|
+
export declare function hydrateRootElement(elm: any): void;
|
|
121
122
|
export declare function disconnectRootElement(elm: any): void;
|
|
122
123
|
export declare function appendVM(vm: VM): void;
|
|
124
|
+
export declare function hydrateVM(vm: VM): void;
|
|
123
125
|
export declare function removeVM(vm: VM): void;
|
|
124
126
|
export declare function createVM<HostNode, HostElement>(elm: HostElement, def: ComponentDef, options: {
|
|
125
127
|
mode: ShadowRootMode;
|