@lwc/engine-core 2.3.7 → 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 +461 -82
- package/dist/engine-core.js +462 -84
- 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/stylesheet.d.ts +2 -2
- package/types/framework/template.d.ts +3 -11
- package/types/framework/vm.d.ts +10 -4
package/dist/engine-core.cjs.js
CHANGED
|
@@ -2312,12 +2312,6 @@ const LightningElement = function () {
|
|
|
2312
2312
|
associateVM(component, vm);
|
|
2313
2313
|
associateVM(elm, vm);
|
|
2314
2314
|
|
|
2315
|
-
if (!features.runtimeFlags.ENABLE_LIGHT_DOM_COMPONENTS) {
|
|
2316
|
-
shared.assert.isTrue(def.renderMode !== 0
|
|
2317
|
-
/* Light */
|
|
2318
|
-
, `${def.name || 'Anonymous class'} is an invalid LWC component. Light DOM components are not available in this environment.`);
|
|
2319
|
-
}
|
|
2320
|
-
|
|
2321
2315
|
if (vm.renderMode === 1
|
|
2322
2316
|
/* Shadow */
|
|
2323
2317
|
) {
|
|
@@ -2949,18 +2943,33 @@ function createObservedFieldPropertyDescriptor(key) {
|
|
|
2949
2943
|
|
|
2950
2944
|
function getClassDescriptorType(descriptor) {
|
|
2951
2945
|
if (shared.isFunction(descriptor.value)) {
|
|
2952
|
-
return
|
|
2946
|
+
return "method"
|
|
2947
|
+
/* Method */
|
|
2948
|
+
;
|
|
2953
2949
|
} else if (shared.isFunction(descriptor.set) || shared.isFunction(descriptor.get)) {
|
|
2954
|
-
return
|
|
2950
|
+
return "accessor"
|
|
2951
|
+
/* Accessor */
|
|
2952
|
+
;
|
|
2955
2953
|
} else {
|
|
2956
|
-
return
|
|
2954
|
+
return "field"
|
|
2955
|
+
/* Field */
|
|
2956
|
+
;
|
|
2957
2957
|
}
|
|
2958
2958
|
}
|
|
2959
2959
|
|
|
2960
2960
|
function validateObservedField(Ctor, fieldName, descriptor) {
|
|
2961
2961
|
if (!shared.isUndefined(descriptor)) {
|
|
2962
2962
|
const type = getClassDescriptorType(descriptor);
|
|
2963
|
-
|
|
2963
|
+
const message = `Invalid observed ${fieldName} field. Found a duplicate ${type} with the same name.`; // [W-9927596] Ideally we always throw an error when detecting duplicate observed field.
|
|
2964
|
+
// This branch is only here for backward compatibility reasons.
|
|
2965
|
+
|
|
2966
|
+
if (type === "accessor"
|
|
2967
|
+
/* Accessor */
|
|
2968
|
+
) {
|
|
2969
|
+
logError(message);
|
|
2970
|
+
} else {
|
|
2971
|
+
shared.assert.fail(message);
|
|
2972
|
+
}
|
|
2964
2973
|
}
|
|
2965
2974
|
}
|
|
2966
2975
|
|
|
@@ -2987,7 +2996,16 @@ function validateMethodDecoratedWithWire(Ctor, methodName, descriptor) {
|
|
|
2987
2996
|
function validateFieldDecoratedWithApi(Ctor, fieldName, descriptor) {
|
|
2988
2997
|
if (!shared.isUndefined(descriptor)) {
|
|
2989
2998
|
const type = getClassDescriptorType(descriptor);
|
|
2990
|
-
|
|
2999
|
+
const message = `Invalid @api ${fieldName} field. Found a duplicate ${type} with the same name.`; // [W-9927596] Ideally we always throw an error when detecting duplicate public properties.
|
|
3000
|
+
// This branch is only here for backward compatibility reasons.
|
|
3001
|
+
|
|
3002
|
+
if (type === "accessor"
|
|
3003
|
+
/* Accessor */
|
|
3004
|
+
) {
|
|
3005
|
+
logError(message);
|
|
3006
|
+
} else {
|
|
3007
|
+
shared.assert.fail(message);
|
|
3008
|
+
}
|
|
2991
3009
|
}
|
|
2992
3010
|
}
|
|
2993
3011
|
|
|
@@ -3050,9 +3068,16 @@ function registerDecorators(Ctor, meta) {
|
|
|
3050
3068
|
// field declaration
|
|
3051
3069
|
if (process.env.NODE_ENV !== 'production') {
|
|
3052
3070
|
validateFieldDecoratedWithApi(Ctor, fieldName, descriptor);
|
|
3053
|
-
}
|
|
3071
|
+
} // [W-9927596] If a component has both a public property and a private setter/getter
|
|
3072
|
+
// with the same name, the property is defined as a public accessor. This branch is
|
|
3073
|
+
// only here for backward compatibility reasons.
|
|
3074
|
+
|
|
3054
3075
|
|
|
3055
|
-
descriptor
|
|
3076
|
+
if (!shared.isUndefined(descriptor) && !shared.isUndefined(descriptor.get)) {
|
|
3077
|
+
descriptor = createPublicAccessorDescriptor(fieldName, descriptor);
|
|
3078
|
+
} else {
|
|
3079
|
+
descriptor = createPublicPropertyDescriptor(fieldName);
|
|
3080
|
+
}
|
|
3056
3081
|
}
|
|
3057
3082
|
|
|
3058
3083
|
apiFields[fieldName] = descriptor;
|
|
@@ -3132,9 +3157,16 @@ function registerDecorators(Ctor, meta) {
|
|
|
3132
3157
|
|
|
3133
3158
|
if (process.env.NODE_ENV !== 'production') {
|
|
3134
3159
|
validateObservedField(Ctor, fieldName, descriptor);
|
|
3135
|
-
}
|
|
3160
|
+
} // [W-9927596] Only mark a field as observed whenever it isn't a duplicated public nor
|
|
3161
|
+
// tracked property. This is only here for backward compatibility purposes.
|
|
3162
|
+
|
|
3163
|
+
|
|
3164
|
+
const isDuplicatePublicProp = !shared.isUndefined(publicProps) && fieldName in publicProps;
|
|
3165
|
+
const isDuplicateTrackedProp = !shared.isUndefined(track) && fieldName in track;
|
|
3136
3166
|
|
|
3137
|
-
|
|
3167
|
+
if (!isDuplicatePublicProp && !isDuplicateTrackedProp) {
|
|
3168
|
+
observedFields[fieldName] = createObservedFieldPropertyDescriptor(fieldName);
|
|
3169
|
+
}
|
|
3138
3170
|
}
|
|
3139
3171
|
}
|
|
3140
3172
|
|
|
@@ -3966,8 +3998,20 @@ function observeElementChildNodes(elm) {
|
|
|
3966
3998
|
|
|
3967
3999
|
function setElementShadowToken(elm, token) {
|
|
3968
4000
|
elm.$shadowToken$ = token;
|
|
3969
|
-
}
|
|
4001
|
+
} // Set the scope token class for *.scoped.css styles
|
|
3970
4002
|
|
|
4003
|
+
|
|
4004
|
+
function setScopeTokenClassIfNecessary(elm, owner) {
|
|
4005
|
+
const {
|
|
4006
|
+
cmpTemplate,
|
|
4007
|
+
context
|
|
4008
|
+
} = owner;
|
|
4009
|
+
const token = cmpTemplate === null || cmpTemplate === void 0 ? void 0 : cmpTemplate.stylesheetToken;
|
|
4010
|
+
|
|
4011
|
+
if (!shared.isUndefined(token) && context.hasScopedStyles) {
|
|
4012
|
+
owner.renderer.getClassList(elm).add(token);
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
3971
4015
|
function updateNodeHook(oldVnode, vnode) {
|
|
3972
4016
|
const {
|
|
3973
4017
|
elm,
|
|
@@ -4031,10 +4075,21 @@ function createElmHook(vnode) {
|
|
|
4031
4075
|
modComputedClassName.create(vnode);
|
|
4032
4076
|
modComputedStyle.create(vnode);
|
|
4033
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
|
+
}
|
|
4034
4088
|
function fallbackElmHook(elm, vnode) {
|
|
4035
4089
|
const {
|
|
4036
4090
|
owner
|
|
4037
4091
|
} = vnode;
|
|
4092
|
+
setScopeTokenClassIfNecessary(elm, owner);
|
|
4038
4093
|
|
|
4039
4094
|
if (owner.shadowMode === 1
|
|
4040
4095
|
/* Synthetic */
|
|
@@ -4045,7 +4100,7 @@ function fallbackElmHook(elm, vnode) {
|
|
|
4045
4100
|
}
|
|
4046
4101
|
} = vnode;
|
|
4047
4102
|
const {
|
|
4048
|
-
|
|
4103
|
+
stylesheetToken
|
|
4049
4104
|
} = owner.context;
|
|
4050
4105
|
|
|
4051
4106
|
if (!shared.isUndefined(context) && !shared.isUndefined(context.lwc) && context.lwc.dom === "manual"
|
|
@@ -4057,7 +4112,7 @@ function fallbackElmHook(elm, vnode) {
|
|
|
4057
4112
|
// into each element from the template, so they can be styled accordingly.
|
|
4058
4113
|
|
|
4059
4114
|
|
|
4060
|
-
setElementShadowToken(elm,
|
|
4115
|
+
setElementShadowToken(elm, stylesheetToken);
|
|
4061
4116
|
}
|
|
4062
4117
|
|
|
4063
4118
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -4142,16 +4197,17 @@ function createViewModelHook(elm, vnode) {
|
|
|
4142
4197
|
ctor,
|
|
4143
4198
|
owner
|
|
4144
4199
|
} = vnode;
|
|
4200
|
+
setScopeTokenClassIfNecessary(elm, owner);
|
|
4145
4201
|
|
|
4146
4202
|
if (owner.shadowMode === 1
|
|
4147
4203
|
/* Synthetic */
|
|
4148
4204
|
) {
|
|
4149
4205
|
const {
|
|
4150
|
-
|
|
4206
|
+
stylesheetToken
|
|
4151
4207
|
} = owner.context; // when running in synthetic shadow mode, we need to set the shadowToken value
|
|
4152
4208
|
// into each element from the template, so they can be styled accordingly.
|
|
4153
4209
|
|
|
4154
|
-
setElementShadowToken(elm,
|
|
4210
|
+
setElementShadowToken(elm, stylesheetToken);
|
|
4155
4211
|
}
|
|
4156
4212
|
|
|
4157
4213
|
const def = getComponentInternalDef(ctor);
|
|
@@ -4193,6 +4249,172 @@ function createChildrenHook(vnode) {
|
|
|
4193
4249
|
}
|
|
4194
4250
|
}
|
|
4195
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
|
+
}
|
|
4196
4418
|
function updateCustomElmHook(oldVnode, vnode) {
|
|
4197
4419
|
// Attrs need to be applied to element before props
|
|
4198
4420
|
// IE11 will wipe out value on radio inputs if value
|
|
@@ -4289,7 +4511,27 @@ const TextHook = {
|
|
|
4289
4511
|
update: updateNodeHook,
|
|
4290
4512
|
insert: insertNodeHook,
|
|
4291
4513
|
move: insertNodeHook,
|
|
4292
|
-
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
|
+
}
|
|
4293
4535
|
};
|
|
4294
4536
|
const CommentHook = {
|
|
4295
4537
|
create: vnode => {
|
|
@@ -4307,7 +4549,23 @@ const CommentHook = {
|
|
|
4307
4549
|
update: updateNodeHook,
|
|
4308
4550
|
insert: insertNodeHook,
|
|
4309
4551
|
move: insertNodeHook,
|
|
4310
|
-
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
|
+
}
|
|
4311
4569
|
}; // insert is called after update, which is used somewhere else (via a module)
|
|
4312
4570
|
// to mark the vm as inserted, that means we cannot use update as the main channel
|
|
4313
4571
|
// to rehydrate when dirty, because sometimes the element is not inserted just yet,
|
|
@@ -4347,6 +4605,12 @@ const ElementHook = {
|
|
|
4347
4605
|
remove: (vnode, parentNode) => {
|
|
4348
4606
|
removeNodeHook(vnode, parentNode);
|
|
4349
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);
|
|
4350
4614
|
}
|
|
4351
4615
|
};
|
|
4352
4616
|
const CustomElementHook = {
|
|
@@ -4438,6 +4702,52 @@ const CustomElementHook = {
|
|
|
4438
4702
|
// will take care of disconnecting any child VM attached to its shadow as well.
|
|
4439
4703
|
removeVM(vm);
|
|
4440
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
|
+
}
|
|
4441
4751
|
}
|
|
4442
4752
|
};
|
|
4443
4753
|
|
|
@@ -4926,6 +5236,10 @@ var api = /*#__PURE__*/Object.freeze({
|
|
|
4926
5236
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
4927
5237
|
*/
|
|
4928
5238
|
|
|
5239
|
+
function makeHostToken(token) {
|
|
5240
|
+
return `${token}-host`;
|
|
5241
|
+
}
|
|
5242
|
+
|
|
4929
5243
|
function createInlineStyleVNode(content) {
|
|
4930
5244
|
return h('style', {
|
|
4931
5245
|
key: 'style',
|
|
@@ -4935,59 +5249,100 @@ function createInlineStyleVNode(content) {
|
|
|
4935
5249
|
}, [t(content)]);
|
|
4936
5250
|
}
|
|
4937
5251
|
|
|
4938
|
-
function
|
|
5252
|
+
function updateStylesheetToken(vm, template) {
|
|
4939
5253
|
const {
|
|
4940
5254
|
elm,
|
|
4941
5255
|
context,
|
|
4942
5256
|
renderer,
|
|
4943
|
-
renderMode
|
|
5257
|
+
renderMode,
|
|
5258
|
+
shadowMode
|
|
4944
5259
|
} = vm;
|
|
4945
5260
|
const {
|
|
4946
5261
|
stylesheets: newStylesheets,
|
|
4947
|
-
|
|
5262
|
+
stylesheetToken: newStylesheetToken
|
|
4948
5263
|
} = template;
|
|
4949
|
-
|
|
5264
|
+
const isSyntheticShadow = renderMode === 1
|
|
5265
|
+
/* Shadow */
|
|
5266
|
+
&& shadowMode === 1
|
|
5267
|
+
/* Synthetic */
|
|
5268
|
+
;
|
|
5269
|
+
const {
|
|
5270
|
+
hasScopedStyles
|
|
5271
|
+
} = context;
|
|
5272
|
+
let newToken;
|
|
5273
|
+
let newHasTokenInClass;
|
|
5274
|
+
let newHasTokenInAttribute; // Reset the styling token applied to the host element.
|
|
4950
5275
|
|
|
4951
|
-
const
|
|
5276
|
+
const {
|
|
5277
|
+
stylesheetToken: oldToken,
|
|
5278
|
+
hasTokenInClass: oldHasTokenInClass,
|
|
5279
|
+
hasTokenInAttribute: oldHasTokenInAttribute
|
|
5280
|
+
} = context;
|
|
4952
5281
|
|
|
4953
|
-
if (
|
|
4954
|
-
renderer.
|
|
5282
|
+
if (oldHasTokenInClass) {
|
|
5283
|
+
renderer.getClassList(elm).remove(makeHostToken(oldToken));
|
|
5284
|
+
}
|
|
5285
|
+
|
|
5286
|
+
if (oldHasTokenInAttribute) {
|
|
5287
|
+
renderer.removeAttribute(elm, makeHostToken(oldToken));
|
|
4955
5288
|
} // Apply the new template styling token to the host element, if the new template has any
|
|
4956
|
-
// associated stylesheets.
|
|
5289
|
+
// associated stylesheets. In the case of light DOM, also ensure there is at least one scoped stylesheet.
|
|
4957
5290
|
|
|
4958
5291
|
|
|
4959
|
-
if (!shared.isUndefined(newStylesheets) && newStylesheets.length !== 0
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
4963
|
-
|
|
5292
|
+
if (!shared.isUndefined(newStylesheets) && newStylesheets.length !== 0) {
|
|
5293
|
+
newToken = newStylesheetToken;
|
|
5294
|
+
} // Set the new styling token on the host element
|
|
5295
|
+
|
|
5296
|
+
|
|
5297
|
+
if (!shared.isUndefined(newToken)) {
|
|
5298
|
+
if (hasScopedStyles) {
|
|
5299
|
+
renderer.getClassList(elm).add(makeHostToken(newToken));
|
|
5300
|
+
newHasTokenInClass = true;
|
|
5301
|
+
}
|
|
4964
5302
|
|
|
4965
|
-
|
|
4966
|
-
|
|
5303
|
+
if (isSyntheticShadow) {
|
|
5304
|
+
renderer.setAttribute(elm, makeHostToken(newToken), '');
|
|
5305
|
+
newHasTokenInAttribute = true;
|
|
5306
|
+
}
|
|
4967
5307
|
} // Update the styling tokens present on the context object.
|
|
4968
5308
|
|
|
4969
5309
|
|
|
4970
|
-
context.
|
|
4971
|
-
context.
|
|
5310
|
+
context.stylesheetToken = newToken;
|
|
5311
|
+
context.hasTokenInClass = newHasTokenInClass;
|
|
5312
|
+
context.hasTokenInAttribute = newHasTokenInAttribute;
|
|
4972
5313
|
}
|
|
4973
5314
|
|
|
4974
|
-
function evaluateStylesheetsContent(stylesheets,
|
|
5315
|
+
function evaluateStylesheetsContent(stylesheets, stylesheetToken, vm) {
|
|
4975
5316
|
const content = [];
|
|
4976
5317
|
|
|
4977
5318
|
for (let i = 0; i < stylesheets.length; i++) {
|
|
4978
5319
|
let stylesheet = stylesheets[i];
|
|
4979
5320
|
|
|
4980
5321
|
if (shared.isArray(stylesheet)) {
|
|
4981
|
-
shared.ArrayPush.apply(content, evaluateStylesheetsContent(stylesheet,
|
|
5322
|
+
shared.ArrayPush.apply(content, evaluateStylesheetsContent(stylesheet, stylesheetToken, vm));
|
|
4982
5323
|
} else {
|
|
4983
5324
|
if (process.env.NODE_ENV !== 'production') {
|
|
4984
5325
|
// in dev-mode, we support hot swapping of stylesheet, which means that
|
|
4985
5326
|
// the component instance might be attempting to use an old version of
|
|
4986
5327
|
// the stylesheet, while internally, we have a replacement for it.
|
|
4987
5328
|
stylesheet = getStyleOrSwappedStyle(stylesheet);
|
|
4988
|
-
}
|
|
5329
|
+
} // Use the actual `:host` selector if we're rendering global CSS for light DOM, or if we're rendering
|
|
5330
|
+
// native shadow DOM. Synthetic shadow DOM never uses `:host`.
|
|
5331
|
+
|
|
4989
5332
|
|
|
4990
|
-
|
|
5333
|
+
const isScopedCss = stylesheet[shared.KEY__SCOPED_CSS];
|
|
5334
|
+
const useActualHostSelector = vm.renderMode === 0
|
|
5335
|
+
/* Light */
|
|
5336
|
+
? !isScopedCss : vm.shadowMode === 0
|
|
5337
|
+
/* Native */
|
|
5338
|
+
; // Apply the scope token only if the stylesheet itself is scoped, or if we're rendering synthetic shadow.
|
|
5339
|
+
|
|
5340
|
+
const scopeToken = isScopedCss || vm.shadowMode === 1
|
|
5341
|
+
/* Synthetic */
|
|
5342
|
+
&& vm.renderMode === 1
|
|
5343
|
+
/* Shadow */
|
|
5344
|
+
? stylesheetToken : undefined;
|
|
5345
|
+
shared.ArrayPush.call(content, stylesheet(useActualHostSelector, scopeToken));
|
|
4991
5346
|
}
|
|
4992
5347
|
}
|
|
4993
5348
|
|
|
@@ -4997,34 +5352,12 @@ function evaluateStylesheetsContent(stylesheets, hostSelector, shadowSelector, n
|
|
|
4997
5352
|
function getStylesheetsContent(vm, template) {
|
|
4998
5353
|
const {
|
|
4999
5354
|
stylesheets,
|
|
5000
|
-
|
|
5355
|
+
stylesheetToken
|
|
5001
5356
|
} = template;
|
|
5002
|
-
const {
|
|
5003
|
-
renderMode,
|
|
5004
|
-
shadowMode
|
|
5005
|
-
} = vm;
|
|
5006
5357
|
let content = [];
|
|
5007
5358
|
|
|
5008
5359
|
if (!shared.isUndefined(stylesheets) && stylesheets.length !== 0) {
|
|
5009
|
-
|
|
5010
|
-
let shadowSelector; // Scoping with the tokens is only necessary for synthetic shadow. For both
|
|
5011
|
-
// light DOM elements and native shadow, we just render the CSS as-is.
|
|
5012
|
-
|
|
5013
|
-
if (renderMode === 1
|
|
5014
|
-
/* Shadow */
|
|
5015
|
-
&& shadowMode === 1
|
|
5016
|
-
/* Synthetic */
|
|
5017
|
-
&& !shared.isUndefined(stylesheetTokens)) {
|
|
5018
|
-
hostSelector = `[${stylesheetTokens.hostAttribute}]`;
|
|
5019
|
-
shadowSelector = `[${stylesheetTokens.shadowAttribute}]`;
|
|
5020
|
-
} else {
|
|
5021
|
-
hostSelector = '';
|
|
5022
|
-
shadowSelector = '';
|
|
5023
|
-
}
|
|
5024
|
-
|
|
5025
|
-
content = evaluateStylesheetsContent(stylesheets, hostSelector, shadowSelector, shadowMode === 0
|
|
5026
|
-
/* Native */
|
|
5027
|
-
);
|
|
5360
|
+
content = evaluateStylesheetsContent(stylesheets, stylesheetToken, vm);
|
|
5028
5361
|
}
|
|
5029
5362
|
|
|
5030
5363
|
return content;
|
|
@@ -5065,7 +5398,7 @@ function createStylesheet(vm, stylesheets) {
|
|
|
5065
5398
|
for (let i = 0; i < stylesheets.length; i++) {
|
|
5066
5399
|
renderer.insertGlobalStylesheet(stylesheets[i]);
|
|
5067
5400
|
}
|
|
5068
|
-
} else if (renderer.ssr) {
|
|
5401
|
+
} else if (renderer.ssr || renderer.isHydrating) {
|
|
5069
5402
|
// native shadow or light DOM, SSR
|
|
5070
5403
|
const combinedStylesheetContent = shared.ArrayJoin.call(stylesheets, '\n');
|
|
5071
5404
|
return createInlineStyleVNode(combinedStylesheetContent);
|
|
@@ -5251,9 +5584,9 @@ function validateLightDomTemplate(template, vm) {
|
|
|
5251
5584
|
if (vm.renderMode === 0
|
|
5252
5585
|
/* Light */
|
|
5253
5586
|
) {
|
|
5254
|
-
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)}.`);
|
|
5255
5588
|
} else {
|
|
5256
|
-
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"`);
|
|
5257
5590
|
}
|
|
5258
5591
|
}
|
|
5259
5592
|
|
|
@@ -5282,8 +5615,7 @@ function evaluateTemplate(vm, html) {
|
|
|
5282
5615
|
context,
|
|
5283
5616
|
cmpSlots,
|
|
5284
5617
|
cmpTemplate,
|
|
5285
|
-
tro
|
|
5286
|
-
shadowMode
|
|
5618
|
+
tro
|
|
5287
5619
|
} = vm;
|
|
5288
5620
|
tro.observe(() => {
|
|
5289
5621
|
// Reset the cache memoizer for template when needed.
|
|
@@ -5308,15 +5640,12 @@ function evaluateTemplate(vm, html) {
|
|
|
5308
5640
|
|
|
5309
5641
|
vm.cmpTemplate = html; // Create a brand new template cache for the swapped templated.
|
|
5310
5642
|
|
|
5311
|
-
context.tplCache = shared.create(null); //
|
|
5643
|
+
context.tplCache = shared.create(null); // Set the computeHasScopedStyles property in the context, to avoid recomputing it repeatedly.
|
|
5312
5644
|
|
|
5313
|
-
|
|
5314
|
-
/* Synthetic */
|
|
5315
|
-
) {
|
|
5316
|
-
updateSyntheticShadowAttributes(vm, html);
|
|
5317
|
-
} // Evaluate, create stylesheet and cache the produced VNode for future
|
|
5318
|
-
// re-rendering.
|
|
5645
|
+
context.hasScopedStyles = computeHasScopedStyles(html); // Update the scoping token on the host element.
|
|
5319
5646
|
|
|
5647
|
+
updateStylesheetToken(vm, html); // Evaluate, create stylesheet and cache the produced VNode for future
|
|
5648
|
+
// re-rendering.
|
|
5320
5649
|
|
|
5321
5650
|
const stylesheetsContent = getStylesheetsContent(vm, html);
|
|
5322
5651
|
context.styleVNode = stylesheetsContent.length === 0 ? null : createStylesheet(vm, stylesheetsContent);
|
|
@@ -5358,6 +5687,21 @@ function evaluateTemplate(vm, html) {
|
|
|
5358
5687
|
|
|
5359
5688
|
return vnodes;
|
|
5360
5689
|
}
|
|
5690
|
+
function computeHasScopedStyles(template) {
|
|
5691
|
+
const {
|
|
5692
|
+
stylesheets
|
|
5693
|
+
} = template;
|
|
5694
|
+
|
|
5695
|
+
if (!shared.isUndefined(stylesheets)) {
|
|
5696
|
+
for (let i = 0; i < stylesheets.length; i++) {
|
|
5697
|
+
if (shared.isTrue(stylesheets[i][shared.KEY__SCOPED_CSS])) {
|
|
5698
|
+
return true;
|
|
5699
|
+
}
|
|
5700
|
+
}
|
|
5701
|
+
}
|
|
5702
|
+
|
|
5703
|
+
return false;
|
|
5704
|
+
}
|
|
5361
5705
|
|
|
5362
5706
|
/*
|
|
5363
5707
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -5651,12 +5995,28 @@ function connectRootElement(elm) {
|
|
|
5651
5995
|
/* GlobalHydrate */
|
|
5652
5996
|
, vm);
|
|
5653
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
|
+
}
|
|
5654
6011
|
function disconnectRootElement(elm) {
|
|
5655
6012
|
const vm = getAssociatedVM(elm);
|
|
5656
6013
|
resetComponentStateWhenRemoved(vm);
|
|
5657
6014
|
}
|
|
5658
6015
|
function appendVM(vm) {
|
|
5659
6016
|
rehydrate(vm);
|
|
6017
|
+
}
|
|
6018
|
+
function hydrateVM(vm) {
|
|
6019
|
+
hydrate(vm);
|
|
5660
6020
|
} // just in case the component comes back, with this we guarantee re-rendering it
|
|
5661
6021
|
// while preventing any attempt to rehydration until after reinsertion.
|
|
5662
6022
|
|
|
@@ -5747,8 +6107,10 @@ function createVM(elm, def, options) {
|
|
|
5747
6107
|
renderMode: def.renderMode,
|
|
5748
6108
|
shadowMode: null,
|
|
5749
6109
|
context: {
|
|
5750
|
-
|
|
5751
|
-
|
|
6110
|
+
stylesheetToken: undefined,
|
|
6111
|
+
hasTokenInClass: undefined,
|
|
6112
|
+
hasTokenInAttribute: undefined,
|
|
6113
|
+
hasScopedStyles: undefined,
|
|
5752
6114
|
styleVNode: null,
|
|
5753
6115
|
tplCache: EmptyObject,
|
|
5754
6116
|
wiredConnecting: EmptyArray,
|
|
@@ -5879,6 +6241,22 @@ function rehydrate(vm) {
|
|
|
5879
6241
|
}
|
|
5880
6242
|
}
|
|
5881
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
|
+
|
|
5882
6260
|
function patchShadowRoot(vm, newCh) {
|
|
5883
6261
|
const {
|
|
5884
6262
|
children: oldCh
|
|
@@ -6705,6 +7083,7 @@ exports.getAssociatedVMIfPresent = getAssociatedVMIfPresent;
|
|
|
6705
7083
|
exports.getComponentDef = getComponentDef;
|
|
6706
7084
|
exports.getComponentInternalDef = getComponentInternalDef;
|
|
6707
7085
|
exports.getUpgradableConstructor = getUpgradableConstructor;
|
|
7086
|
+
exports.hydrateRootElement = hydrateRootElement;
|
|
6708
7087
|
exports.isComponentConstructor = isComponentConstructor;
|
|
6709
7088
|
exports.readonly = readonly;
|
|
6710
7089
|
exports.register = register;
|
|
@@ -6718,4 +7097,4 @@ exports.swapTemplate = swapTemplate;
|
|
|
6718
7097
|
exports.track = track;
|
|
6719
7098
|
exports.unwrap = unwrap;
|
|
6720
7099
|
exports.wire = wire;
|
|
6721
|
-
/* version: 2.
|
|
7100
|
+
/* version: 2.5.2-canary1 */
|