@lwc/engine-core 2.14.2 → 2.15.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.
@@ -3182,6 +3182,9 @@ function patch(n1, n2, renderer) {
3182
3182
  // VComment has no special capability, fallback to the owner's renderer
3183
3183
  patchComment(n1, n2, renderer);
3184
3184
  break;
3185
+ case 4 /* Static */:
3186
+ n2.elm = n1.elm;
3187
+ break;
3185
3188
  case 2 /* Element */:
3186
3189
  patchElement(n1, n2, (_a = n2.data.renderer) !== null && _a !== void 0 ? _a : renderer);
3187
3190
  break;
@@ -3201,6 +3204,10 @@ function mount(node, parent, renderer, anchor) {
3201
3204
  // VComment has no special capability, fallback to the owner's renderer
3202
3205
  mountComment(node, parent, anchor, renderer);
3203
3206
  break;
3207
+ case 4 /* Static */:
3208
+ // VStatic cannot have a custom renderer associated to them, using owner's renderer
3209
+ mountStatic(node, parent, anchor, renderer);
3210
+ break;
3204
3211
  case 2 /* Element */:
3205
3212
  // If the vnode data has a renderer override use it, else fallback to owner's renderer
3206
3213
  mountElement(node, parent, anchor, (_a = node.data.renderer) !== null && _a !== void 0 ? _a : renderer);
@@ -3256,6 +3263,24 @@ function patchElement(n1, n2, renderer) {
3256
3263
  patchElementPropsAndAttrs$1(n1, n2, renderer);
3257
3264
  patchChildren(n1.children, n2.children, elm, renderer);
3258
3265
  }
3266
+ function mountStatic(vnode, parent, anchor, renderer) {
3267
+ const { owner } = vnode;
3268
+ const { cloneNode, isSyntheticShadowDefined } = renderer;
3269
+ const elm = (vnode.elm = cloneNode(vnode.fragment, true));
3270
+ linkNodeToShadow(elm, owner, renderer);
3271
+ // Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
3272
+ const { renderMode, shadowMode } = owner;
3273
+ if (isSyntheticShadowDefined) {
3274
+ if (shadowMode === 1 /* Synthetic */ || renderMode === 0 /* Light */) {
3275
+ elm[shared.KEY__SHADOW_STATIC] = true;
3276
+ }
3277
+ }
3278
+ if (process.env.NODE_ENV !== 'production') {
3279
+ const isLight = renderMode === 0 /* Light */;
3280
+ patchElementWithRestrictions(elm, { isPortal: false, isLight });
3281
+ }
3282
+ insertNode(elm, parent, anchor, renderer);
3283
+ }
3259
3284
  function mountCustomElement(vnode, parent, anchor, renderer) {
3260
3285
  const { sel, owner } = vnode;
3261
3286
  const UpgradableConstructor = getUpgradableConstructor(sel, renderer);
@@ -3724,6 +3749,17 @@ const SymbolIterator = Symbol.iterator;
3724
3749
  function addVNodeToChildLWC(vnode) {
3725
3750
  shared.ArrayPush.call(getVMBeingRendered().velements, vnode);
3726
3751
  }
3752
+ // [st]atic node
3753
+ function st(fragment, key) {
3754
+ return {
3755
+ type: 4 /* Static */,
3756
+ sel: undefined,
3757
+ key,
3758
+ elm: undefined,
3759
+ fragment,
3760
+ owner: getVMBeingRendered(),
3761
+ };
3762
+ }
3727
3763
  // [h]tml node
3728
3764
  function h(sel, data, children = EmptyArray) {
3729
3765
  const vmBeingRendered = getVMBeingRendered();
@@ -4113,6 +4149,7 @@ const api = shared.freeze({
4113
4149
  co,
4114
4150
  dc,
4115
4151
  ti,
4152
+ st,
4116
4153
  gid,
4117
4154
  fid,
4118
4155
  shc,
@@ -4264,8 +4301,7 @@ function createStylesheet(vm, stylesheets) {
4264
4301
  // This works in the client, because the stylesheets are created, and cached in the VM
4265
4302
  // the first time the VM renders.
4266
4303
  // native shadow or light DOM, SSR
4267
- const combinedStylesheetContent = shared.ArrayJoin.call(stylesheets, '\n');
4268
- return createInlineStyleVNode(combinedStylesheetContent);
4304
+ return shared.ArrayMap.call(stylesheets, createInlineStyleVNode);
4269
4305
  }
4270
4306
  else {
4271
4307
  // native shadow or light DOM, DOM renderer
@@ -4433,6 +4469,59 @@ function validateLightDomTemplate(template, vm) {
4433
4469
  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"`);
4434
4470
  }
4435
4471
  }
4472
+ function buildParseFragmentFn(createFragmentFn) {
4473
+ return (strings, ...keys) => {
4474
+ const cache = shared.create(null);
4475
+ return function () {
4476
+ const { context: { hasScopedStyles, stylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
4477
+ const hasStyleToken = !shared.isUndefined(stylesheetToken);
4478
+ const isSyntheticShadow = shadowMode === 1 /* Synthetic */;
4479
+ let cacheKey = 0;
4480
+ if (hasStyleToken && hasScopedStyles) {
4481
+ cacheKey |= 1 /* HAS_SCOPED_STYLE */;
4482
+ }
4483
+ if (hasStyleToken && isSyntheticShadow) {
4484
+ cacheKey |= 2 /* SHADOW_MODE_SYNTHETIC */;
4485
+ }
4486
+ if (!shared.isUndefined(cache[cacheKey])) {
4487
+ return cache[cacheKey];
4488
+ }
4489
+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '';
4490
+ const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetToken}"` : '';
4491
+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '';
4492
+ let htmlFragment = '';
4493
+ for (let i = 0, n = keys.length; i < n; i++) {
4494
+ switch (keys[i]) {
4495
+ case 0: // styleToken in existing class attr
4496
+ htmlFragment += strings[i] + classToken;
4497
+ break;
4498
+ case 1: // styleToken for added class attr
4499
+ htmlFragment += strings[i] + classAttrToken;
4500
+ break;
4501
+ case 2: // styleToken as attr
4502
+ htmlFragment += strings[i] + attrToken;
4503
+ break;
4504
+ case 3: // ${1}${2}
4505
+ htmlFragment += strings[i] + classAttrToken + attrToken;
4506
+ break;
4507
+ }
4508
+ }
4509
+ htmlFragment += strings[strings.length - 1];
4510
+ cache[cacheKey] = createFragmentFn(htmlFragment, renderer);
4511
+ return cache[cacheKey];
4512
+ };
4513
+ };
4514
+ }
4515
+ // Note: at the moment this code executes, we don't have a renderer yet.
4516
+ const parseFragment = buildParseFragmentFn((html, renderer) => {
4517
+ const { createFragment } = renderer;
4518
+ return createFragment(html);
4519
+ });
4520
+ const parseSVGFragment = buildParseFragmentFn((html, renderer) => {
4521
+ const { createFragment, getFirstChild } = renderer;
4522
+ const fragment = createFragment('<svg>' + html + '</svg>');
4523
+ return getFirstChild(fragment);
4524
+ });
4436
4525
  function evaluateTemplate(vm, html) {
4437
4526
  if (process.env.NODE_ENV !== 'production') {
4438
4527
  shared.assert.isTrue(shared.isFunction(html), `evaluateTemplate() second argument must be an imported template instead of ${shared.toString(html)}`);
@@ -4479,7 +4568,7 @@ function evaluateTemplate(vm, html) {
4479
4568
  // Evaluate, create stylesheet and cache the produced VNode for future
4480
4569
  // re-rendering.
4481
4570
  const stylesheetsContent = getStylesheetsContent(vm, html);
4482
- context.styleVNode =
4571
+ context.styleVNodes =
4483
4572
  stylesheetsContent.length === 0
4484
4573
  ? null
4485
4574
  : createStylesheet(vm, stylesheetsContent);
@@ -4496,9 +4585,9 @@ function evaluateTemplate(vm, html) {
4496
4585
  // Set the global flag that template is being updated
4497
4586
  isUpdatingTemplate = true;
4498
4587
  vnodes = html.call(undefined, api, component, cmpSlots, context.tplCache);
4499
- const { styleVNode } = context;
4500
- if (!shared.isNull(styleVNode)) {
4501
- shared.ArrayUnshift.call(vnodes, styleVNode);
4588
+ const { styleVNodes } = context;
4589
+ if (!shared.isNull(styleVNodes)) {
4590
+ shared.ArrayUnshift.apply(vnodes, styleVNodes);
4502
4591
  }
4503
4592
  });
4504
4593
  }, () => {
@@ -4863,7 +4952,7 @@ function createVM(elm, ctor, renderer, options) {
4863
4952
  hasTokenInClass: undefined,
4864
4953
  hasTokenInAttribute: undefined,
4865
4954
  hasScopedStyles: undefined,
4866
- styleVNode: null,
4955
+ styleVNodes: null,
4867
4956
  tplCache: EmptyObject,
4868
4957
  wiredConnecting: EmptyArray,
4869
4958
  wiredDisconnecting: EmptyArray
@@ -5787,6 +5876,10 @@ function hydrateNode(node, vnode, renderer) {
5787
5876
  // VComment has no special capability, fallback to the owner's renderer
5788
5877
  hydratedNode = hydrateComment(node, vnode, renderer);
5789
5878
  break;
5879
+ case 4 /* Static */:
5880
+ // VStatic are cacheable and cannot have custom renderer associated to them
5881
+ hydratedNode = hydrateStaticElement(node, vnode, renderer);
5882
+ break;
5790
5883
  case 2 /* Element */:
5791
5884
  hydratedNode = hydrateElement(node, vnode, (_a = vnode.data.renderer) !== null && _a !== void 0 ? _a : renderer);
5792
5885
  break;
@@ -5830,6 +5923,13 @@ function hydrateComment(node, vnode, renderer) {
5830
5923
  vnode.elm = node;
5831
5924
  return node;
5832
5925
  }
5926
+ function hydrateStaticElement(elm, vnode, renderer) {
5927
+ if (!areCompatibleNodes(vnode.fragment, elm, vnode, renderer)) {
5928
+ return handleMismatch(elm, vnode, renderer);
5929
+ }
5930
+ vnode.elm = elm;
5931
+ return elm;
5932
+ }
5833
5933
  function hydrateElement(elm, vnode, renderer) {
5834
5934
  if (!hasCorrectNodeType(vnode, elm, 1 /* ELEMENT */, renderer) ||
5835
5935
  !isMatchingElement(vnode, elm, renderer)) {
@@ -6065,6 +6165,39 @@ function validateStyleAttr(vnode, elm, renderer) {
6065
6165
  }
6066
6166
  return nodesAreCompatible;
6067
6167
  }
6168
+ function areCompatibleNodes(client, ssr, vnode, renderer) {
6169
+ const { getProperty, getAttribute } = renderer;
6170
+ if (getProperty(client, 'nodeType') === 3 /* TEXT */) {
6171
+ if (!hasCorrectNodeType(vnode, ssr, 3 /* TEXT */, renderer)) {
6172
+ return false;
6173
+ }
6174
+ return getProperty(client, 'nodeValue') === getProperty(ssr, 'nodeValue');
6175
+ }
6176
+ if (getProperty(client, 'nodeType') === 8 /* COMMENT */) {
6177
+ if (!hasCorrectNodeType(vnode, ssr, 8 /* COMMENT */, renderer)) {
6178
+ return false;
6179
+ }
6180
+ return getProperty(client, 'nodeValue') === getProperty(ssr, 'nodeValue');
6181
+ }
6182
+ if (!hasCorrectNodeType(vnode, ssr, 1 /* ELEMENT */, renderer)) {
6183
+ return false;
6184
+ }
6185
+ let isCompatibleElements = true;
6186
+ if (getProperty(client, 'tagName') !== getProperty(ssr, 'tagName')) {
6187
+ if (process.env.NODE_ENV !== 'production') {
6188
+ logError(`Hydration mismatch: expecting element with tag "${getProperty(client, 'tagName').toLowerCase()}" but found "${getProperty(ssr, 'tagName').toLowerCase()}".`, vnode.owner);
6189
+ }
6190
+ return false;
6191
+ }
6192
+ const clientAttrsNames = getProperty(client, 'getAttributeNames').call(client);
6193
+ clientAttrsNames.forEach((attrName) => {
6194
+ if (getAttribute(client, attrName) !== getAttribute(ssr, attrName)) {
6195
+ logError(`Mismatch hydrating element <${getProperty(client, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${getAttribute(client, attrName)}" but found "${getAttribute(ssr, attrName)}"`, vnode.owner);
6196
+ isCompatibleElements = false;
6197
+ }
6198
+ });
6199
+ return isCompatibleElements;
6200
+ }
6068
6201
 
6069
6202
  /*
6070
6203
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6224,6 +6357,8 @@ exports.getComponentHtmlPrototype = getComponentHtmlPrototype;
6224
6357
  exports.getUpgradableConstructor = getUpgradableConstructor;
6225
6358
  exports.hydrateRoot = hydrateRoot;
6226
6359
  exports.isComponentConstructor = isComponentConstructor;
6360
+ exports.parseFragment = parseFragment;
6361
+ exports.parseSVGFragment = parseSVGFragment;
6227
6362
  exports.readonly = readonly;
6228
6363
  exports.register = register;
6229
6364
  exports.registerComponent = registerComponent;
@@ -6237,4 +6372,4 @@ exports.swapTemplate = swapTemplate;
6237
6372
  exports.track = track;
6238
6373
  exports.unwrap = unwrap;
6239
6374
  exports.wire = wire;
6240
- /* version: 2.14.2 */
6375
+ /* version: 2.15.0 */
@@ -1,7 +1,7 @@
1
1
  /* proxy-compat-disable */
2
2
  import { runtimeFlags } from '@lwc/features';
3
3
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
4
- import { seal, create, isFunction as isFunction$1, ArrayPush as ArrayPush$1, isUndefined as isUndefined$1, ArrayIndexOf, ArraySplice, StringToLowerCase, ArrayJoin, isNull, isFrozen, defineProperty, hasOwnProperty as hasOwnProperty$1, assign, forEach, keys, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, isObject, assert, KEY__SYNTHETIC_MODE, toString as toString$1, isFalse, isTrue, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, freeze, htmlPropertyToAttribute, ArraySlice, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, SVG_NAMESPACE, KEY__SHADOW_RESOLVER, isArray as isArray$1, isNumber, StringReplace, KEY__SCOPED_CSS, noop, ArrayUnshift, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift, ArrayPop } from '@lwc/shared';
4
+ import { seal, create, isFunction as isFunction$1, ArrayPush as ArrayPush$1, isUndefined as isUndefined$1, ArrayIndexOf, ArraySplice, StringToLowerCase, ArrayJoin, isNull, isFrozen, defineProperty, hasOwnProperty as hasOwnProperty$1, assign, forEach, keys, AriaPropNameToAttrNameMap, getPropertyDescriptor, defineProperties, getOwnPropertyNames as getOwnPropertyNames$1, getPrototypeOf as getPrototypeOf$1, setPrototypeOf, isObject, assert, KEY__SYNTHETIC_MODE, toString as toString$1, isFalse, isTrue, getOwnPropertyDescriptor as getOwnPropertyDescriptor$1, LWC_VERSION_COMMENT_REGEX, LWC_VERSION, freeze, htmlPropertyToAttribute, ArraySlice, StringCharCodeAt, XML_NAMESPACE, XLINK_NAMESPACE, isString, StringSlice, SVG_NAMESPACE, KEY__SHADOW_STATIC, KEY__SHADOW_RESOLVER, isArray as isArray$1, isNumber, StringReplace, ArrayMap, KEY__SCOPED_CSS, noop, ArrayUnshift, ArrayCopyWithin, ArrayFill, ArraySort, ArrayReverse, ArrayShift, ArrayPop } from '@lwc/shared';
5
5
 
6
6
  /*
7
7
  * Copyright (c) 2018, salesforce.com, inc.
@@ -3179,6 +3179,9 @@ function patch(n1, n2, renderer) {
3179
3179
  // VComment has no special capability, fallback to the owner's renderer
3180
3180
  patchComment(n1, n2, renderer);
3181
3181
  break;
3182
+ case 4 /* Static */:
3183
+ n2.elm = n1.elm;
3184
+ break;
3182
3185
  case 2 /* Element */:
3183
3186
  patchElement(n1, n2, (_a = n2.data.renderer) !== null && _a !== void 0 ? _a : renderer);
3184
3187
  break;
@@ -3198,6 +3201,10 @@ function mount(node, parent, renderer, anchor) {
3198
3201
  // VComment has no special capability, fallback to the owner's renderer
3199
3202
  mountComment(node, parent, anchor, renderer);
3200
3203
  break;
3204
+ case 4 /* Static */:
3205
+ // VStatic cannot have a custom renderer associated to them, using owner's renderer
3206
+ mountStatic(node, parent, anchor, renderer);
3207
+ break;
3201
3208
  case 2 /* Element */:
3202
3209
  // If the vnode data has a renderer override use it, else fallback to owner's renderer
3203
3210
  mountElement(node, parent, anchor, (_a = node.data.renderer) !== null && _a !== void 0 ? _a : renderer);
@@ -3253,6 +3260,24 @@ function patchElement(n1, n2, renderer) {
3253
3260
  patchElementPropsAndAttrs$1(n1, n2, renderer);
3254
3261
  patchChildren(n1.children, n2.children, elm, renderer);
3255
3262
  }
3263
+ function mountStatic(vnode, parent, anchor, renderer) {
3264
+ const { owner } = vnode;
3265
+ const { cloneNode, isSyntheticShadowDefined } = renderer;
3266
+ const elm = (vnode.elm = cloneNode(vnode.fragment, true));
3267
+ linkNodeToShadow(elm, owner, renderer);
3268
+ // Marks this node as Static to propagate the shadow resolver. must happen after elm is assigned to the proper shadow
3269
+ const { renderMode, shadowMode } = owner;
3270
+ if (isSyntheticShadowDefined) {
3271
+ if (shadowMode === 1 /* Synthetic */ || renderMode === 0 /* Light */) {
3272
+ elm[KEY__SHADOW_STATIC] = true;
3273
+ }
3274
+ }
3275
+ if (process.env.NODE_ENV !== 'production') {
3276
+ const isLight = renderMode === 0 /* Light */;
3277
+ patchElementWithRestrictions(elm, { isPortal: false, isLight });
3278
+ }
3279
+ insertNode(elm, parent, anchor, renderer);
3280
+ }
3256
3281
  function mountCustomElement(vnode, parent, anchor, renderer) {
3257
3282
  const { sel, owner } = vnode;
3258
3283
  const UpgradableConstructor = getUpgradableConstructor(sel, renderer);
@@ -3721,6 +3746,17 @@ const SymbolIterator = Symbol.iterator;
3721
3746
  function addVNodeToChildLWC(vnode) {
3722
3747
  ArrayPush$1.call(getVMBeingRendered().velements, vnode);
3723
3748
  }
3749
+ // [st]atic node
3750
+ function st(fragment, key) {
3751
+ return {
3752
+ type: 4 /* Static */,
3753
+ sel: undefined,
3754
+ key,
3755
+ elm: undefined,
3756
+ fragment,
3757
+ owner: getVMBeingRendered(),
3758
+ };
3759
+ }
3724
3760
  // [h]tml node
3725
3761
  function h(sel, data, children = EmptyArray) {
3726
3762
  const vmBeingRendered = getVMBeingRendered();
@@ -4110,6 +4146,7 @@ const api = freeze({
4110
4146
  co,
4111
4147
  dc,
4112
4148
  ti,
4149
+ st,
4113
4150
  gid,
4114
4151
  fid,
4115
4152
  shc,
@@ -4261,8 +4298,7 @@ function createStylesheet(vm, stylesheets) {
4261
4298
  // This works in the client, because the stylesheets are created, and cached in the VM
4262
4299
  // the first time the VM renders.
4263
4300
  // native shadow or light DOM, SSR
4264
- const combinedStylesheetContent = ArrayJoin.call(stylesheets, '\n');
4265
- return createInlineStyleVNode(combinedStylesheetContent);
4301
+ return ArrayMap.call(stylesheets, createInlineStyleVNode);
4266
4302
  }
4267
4303
  else {
4268
4304
  // native shadow or light DOM, DOM renderer
@@ -4430,6 +4466,59 @@ function validateLightDomTemplate(template, vm) {
4430
4466
  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"`);
4431
4467
  }
4432
4468
  }
4469
+ function buildParseFragmentFn(createFragmentFn) {
4470
+ return (strings, ...keys) => {
4471
+ const cache = create(null);
4472
+ return function () {
4473
+ const { context: { hasScopedStyles, stylesheetToken }, shadowMode, renderer, } = getVMBeingRendered();
4474
+ const hasStyleToken = !isUndefined$1(stylesheetToken);
4475
+ const isSyntheticShadow = shadowMode === 1 /* Synthetic */;
4476
+ let cacheKey = 0;
4477
+ if (hasStyleToken && hasScopedStyles) {
4478
+ cacheKey |= 1 /* HAS_SCOPED_STYLE */;
4479
+ }
4480
+ if (hasStyleToken && isSyntheticShadow) {
4481
+ cacheKey |= 2 /* SHADOW_MODE_SYNTHETIC */;
4482
+ }
4483
+ if (!isUndefined$1(cache[cacheKey])) {
4484
+ return cache[cacheKey];
4485
+ }
4486
+ const classToken = hasScopedStyles && hasStyleToken ? ' ' + stylesheetToken : '';
4487
+ const classAttrToken = hasScopedStyles && hasStyleToken ? ` class="${stylesheetToken}"` : '';
4488
+ const attrToken = hasStyleToken && isSyntheticShadow ? ' ' + stylesheetToken : '';
4489
+ let htmlFragment = '';
4490
+ for (let i = 0, n = keys.length; i < n; i++) {
4491
+ switch (keys[i]) {
4492
+ case 0: // styleToken in existing class attr
4493
+ htmlFragment += strings[i] + classToken;
4494
+ break;
4495
+ case 1: // styleToken for added class attr
4496
+ htmlFragment += strings[i] + classAttrToken;
4497
+ break;
4498
+ case 2: // styleToken as attr
4499
+ htmlFragment += strings[i] + attrToken;
4500
+ break;
4501
+ case 3: // ${1}${2}
4502
+ htmlFragment += strings[i] + classAttrToken + attrToken;
4503
+ break;
4504
+ }
4505
+ }
4506
+ htmlFragment += strings[strings.length - 1];
4507
+ cache[cacheKey] = createFragmentFn(htmlFragment, renderer);
4508
+ return cache[cacheKey];
4509
+ };
4510
+ };
4511
+ }
4512
+ // Note: at the moment this code executes, we don't have a renderer yet.
4513
+ const parseFragment = buildParseFragmentFn((html, renderer) => {
4514
+ const { createFragment } = renderer;
4515
+ return createFragment(html);
4516
+ });
4517
+ const parseSVGFragment = buildParseFragmentFn((html, renderer) => {
4518
+ const { createFragment, getFirstChild } = renderer;
4519
+ const fragment = createFragment('<svg>' + html + '</svg>');
4520
+ return getFirstChild(fragment);
4521
+ });
4433
4522
  function evaluateTemplate(vm, html) {
4434
4523
  if (process.env.NODE_ENV !== 'production') {
4435
4524
  assert.isTrue(isFunction$1(html), `evaluateTemplate() second argument must be an imported template instead of ${toString$1(html)}`);
@@ -4476,7 +4565,7 @@ function evaluateTemplate(vm, html) {
4476
4565
  // Evaluate, create stylesheet and cache the produced VNode for future
4477
4566
  // re-rendering.
4478
4567
  const stylesheetsContent = getStylesheetsContent(vm, html);
4479
- context.styleVNode =
4568
+ context.styleVNodes =
4480
4569
  stylesheetsContent.length === 0
4481
4570
  ? null
4482
4571
  : createStylesheet(vm, stylesheetsContent);
@@ -4493,9 +4582,9 @@ function evaluateTemplate(vm, html) {
4493
4582
  // Set the global flag that template is being updated
4494
4583
  isUpdatingTemplate = true;
4495
4584
  vnodes = html.call(undefined, api, component, cmpSlots, context.tplCache);
4496
- const { styleVNode } = context;
4497
- if (!isNull(styleVNode)) {
4498
- ArrayUnshift.call(vnodes, styleVNode);
4585
+ const { styleVNodes } = context;
4586
+ if (!isNull(styleVNodes)) {
4587
+ ArrayUnshift.apply(vnodes, styleVNodes);
4499
4588
  }
4500
4589
  });
4501
4590
  }, () => {
@@ -4860,7 +4949,7 @@ function createVM(elm, ctor, renderer, options) {
4860
4949
  hasTokenInClass: undefined,
4861
4950
  hasTokenInAttribute: undefined,
4862
4951
  hasScopedStyles: undefined,
4863
- styleVNode: null,
4952
+ styleVNodes: null,
4864
4953
  tplCache: EmptyObject,
4865
4954
  wiredConnecting: EmptyArray,
4866
4955
  wiredDisconnecting: EmptyArray
@@ -5784,6 +5873,10 @@ function hydrateNode(node, vnode, renderer) {
5784
5873
  // VComment has no special capability, fallback to the owner's renderer
5785
5874
  hydratedNode = hydrateComment(node, vnode, renderer);
5786
5875
  break;
5876
+ case 4 /* Static */:
5877
+ // VStatic are cacheable and cannot have custom renderer associated to them
5878
+ hydratedNode = hydrateStaticElement(node, vnode, renderer);
5879
+ break;
5787
5880
  case 2 /* Element */:
5788
5881
  hydratedNode = hydrateElement(node, vnode, (_a = vnode.data.renderer) !== null && _a !== void 0 ? _a : renderer);
5789
5882
  break;
@@ -5827,6 +5920,13 @@ function hydrateComment(node, vnode, renderer) {
5827
5920
  vnode.elm = node;
5828
5921
  return node;
5829
5922
  }
5923
+ function hydrateStaticElement(elm, vnode, renderer) {
5924
+ if (!areCompatibleNodes(vnode.fragment, elm, vnode, renderer)) {
5925
+ return handleMismatch(elm, vnode, renderer);
5926
+ }
5927
+ vnode.elm = elm;
5928
+ return elm;
5929
+ }
5830
5930
  function hydrateElement(elm, vnode, renderer) {
5831
5931
  if (!hasCorrectNodeType(vnode, elm, 1 /* ELEMENT */, renderer) ||
5832
5932
  !isMatchingElement(vnode, elm, renderer)) {
@@ -6062,6 +6162,39 @@ function validateStyleAttr(vnode, elm, renderer) {
6062
6162
  }
6063
6163
  return nodesAreCompatible;
6064
6164
  }
6165
+ function areCompatibleNodes(client, ssr, vnode, renderer) {
6166
+ const { getProperty, getAttribute } = renderer;
6167
+ if (getProperty(client, 'nodeType') === 3 /* TEXT */) {
6168
+ if (!hasCorrectNodeType(vnode, ssr, 3 /* TEXT */, renderer)) {
6169
+ return false;
6170
+ }
6171
+ return getProperty(client, 'nodeValue') === getProperty(ssr, 'nodeValue');
6172
+ }
6173
+ if (getProperty(client, 'nodeType') === 8 /* COMMENT */) {
6174
+ if (!hasCorrectNodeType(vnode, ssr, 8 /* COMMENT */, renderer)) {
6175
+ return false;
6176
+ }
6177
+ return getProperty(client, 'nodeValue') === getProperty(ssr, 'nodeValue');
6178
+ }
6179
+ if (!hasCorrectNodeType(vnode, ssr, 1 /* ELEMENT */, renderer)) {
6180
+ return false;
6181
+ }
6182
+ let isCompatibleElements = true;
6183
+ if (getProperty(client, 'tagName') !== getProperty(ssr, 'tagName')) {
6184
+ if (process.env.NODE_ENV !== 'production') {
6185
+ logError(`Hydration mismatch: expecting element with tag "${getProperty(client, 'tagName').toLowerCase()}" but found "${getProperty(ssr, 'tagName').toLowerCase()}".`, vnode.owner);
6186
+ }
6187
+ return false;
6188
+ }
6189
+ const clientAttrsNames = getProperty(client, 'getAttributeNames').call(client);
6190
+ clientAttrsNames.forEach((attrName) => {
6191
+ if (getAttribute(client, attrName) !== getAttribute(ssr, attrName)) {
6192
+ logError(`Mismatch hydrating element <${getProperty(client, 'tagName').toLowerCase()}>: attribute "${attrName}" has different values, expected "${getAttribute(client, attrName)}" but found "${getAttribute(ssr, attrName)}"`, vnode.owner);
6193
+ isCompatibleElements = false;
6194
+ }
6195
+ });
6196
+ return isCompatibleElements;
6197
+ }
6065
6198
 
6066
6199
  /*
6067
6200
  * Copyright (c) 2018, salesforce.com, inc.
@@ -6198,5 +6331,5 @@ function getComponentConstructor(elm) {
6198
6331
  return ctor;
6199
6332
  }
6200
6333
 
6201
- export { LightningElement, profilerControl as __unstable__ProfilerControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, getUpgradableConstructor, hydrateRoot, isComponentConstructor, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
6202
- /* version: 2.14.2 */
6334
+ export { LightningElement, profilerControl as __unstable__ProfilerControl, api$1 as api, connectRootElement, createContextProvider, createVM, disconnectRootElement, freezeTemplate, getAssociatedVMIfPresent, getComponentConstructor, getComponentDef, getComponentHtmlPrototype, getUpgradableConstructor, hydrateRoot, isComponentConstructor, parseFragment, parseSVGFragment, readonly, register, registerComponent, registerDecorators, registerTemplate, sanitizeAttribute, setHooks, swapComponent, swapStyle, swapTemplate, track, unwrap, wire };
6335
+ /* version: 2.15.0 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lwc/engine-core",
3
- "version": "2.14.2",
3
+ "version": "2.15.0",
4
4
  "description": "Core LWC engine APIs.",
5
5
  "homepage": "https://lwc.dev/",
6
6
  "repository": {
@@ -25,8 +25,8 @@
25
25
  "types/"
26
26
  ],
27
27
  "dependencies": {
28
- "@lwc/features": "2.14.2",
29
- "@lwc/shared": "2.14.2"
28
+ "@lwc/features": "2.15.0",
29
+ "@lwc/shared": "2.15.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "observable-membrane": "2.0.0"
@@ -1,6 +1,7 @@
1
1
  import { SlotSet } from './vm';
2
2
  import { LightningElementConstructor } from './base-lightning-element';
3
- import { VNode, VNodes, VElement, VText, VCustomElement, VComment, VElementData } from './vnodes';
3
+ import { VNode, VNodes, VElement, VText, VCustomElement, VComment, VElementData, VStatic, Key } from './vnodes';
4
+ declare function st(fragment: Element, key: Key): VStatic;
4
5
  declare function h(sel: string, data: VElementData, children?: VNodes): VElement;
5
6
  declare function ti(value: any): number;
6
7
  declare function s(slotName: string, data: VElementData, children: VNodes, slotset: SlotSet | undefined): VElement | VNodes;
@@ -40,6 +41,7 @@ declare const api: Readonly<{
40
41
  co: typeof co;
41
42
  dc: typeof dc;
42
43
  ti: typeof ti;
44
+ st: typeof st;
43
45
  gid: typeof gid;
44
46
  fid: typeof fid;
45
47
  shc: typeof shc;
@@ -8,6 +8,7 @@ export { readonly } from './readonly';
8
8
  export { setFeatureFlag, setFeatureFlagForTest } from '@lwc/features';
9
9
  export { getComponentHtmlPrototype } from './def';
10
10
  export { createVM, connectRootElement, disconnectRootElement, getAssociatedVMIfPresent, } from './vm';
11
+ export { parseFragment, parseSVGFragment } from './template';
11
12
  export { hydrateRoot } from './hydration';
12
13
  export { registerComponent } from './component';
13
14
  export { registerTemplate } from './secure-template';
@@ -10,6 +10,8 @@ export interface RendererAPI {
10
10
  isHydrating: () => boolean;
11
11
  insert: (node: N, parent: E, anchor: N | null) => void;
12
12
  remove: (node: N, parent: E) => void;
13
+ cloneNode: (node: N, deep: boolean) => N;
14
+ createFragment: (html: string) => N | null;
13
15
  createElement: (tagName: string, namespace?: string) => E;
14
16
  createText: (content: string) => N;
15
17
  createComment: (content: string) => N;
@@ -14,4 +14,4 @@ export declare type StylesheetFactory = (stylesheetToken: string | undefined, us
14
14
  export declare type TemplateStylesheetFactories = Array<StylesheetFactory | TemplateStylesheetFactories>;
15
15
  export declare function updateStylesheetToken(vm: VM, template: Template): void;
16
16
  export declare function getStylesheetsContent(vm: VM, template: Template): string[];
17
- export declare function createStylesheet(vm: VM, stylesheets: string[]): VNode | null;
17
+ export declare function createStylesheet(vm: VM, stylesheets: string[]): VNode[] | null;
@@ -16,4 +16,6 @@ export interface Template {
16
16
  export declare let isUpdatingTemplate: boolean;
17
17
  export declare function getVMBeingRendered(): VM | null;
18
18
  export declare function setVMBeingRendered(vm: VM | null): void;
19
+ export declare const parseFragment: (strings: string[], ...keys: number[]) => () => Element;
20
+ export declare const parseSVGFragment: (strings: string[], ...keys: number[]) => () => Element;
19
21
  export declare function evaluateTemplate(vm: VM, html: Template): VNodes;
@@ -41,8 +41,8 @@ export interface Context {
41
41
  hasTokenInAttribute: boolean | undefined;
42
42
  /** Whether or not light DOM scoped styles are present in the stylesheets. */
43
43
  hasScopedStyles: boolean | undefined;
44
- /** The VNode injected in all the shadow trees to apply the associated component stylesheets. */
45
- styleVNode: VNode | null;
44
+ /** The VNodes injected in all the shadow trees to apply the associated component stylesheets. */
45
+ styleVNodes: VNode[] | null;
46
46
  /** Object used by the template function to store information that can be reused between
47
47
  * different render cycle of the same template. */
48
48
  tplCache: TemplateCache;
@@ -5,9 +5,10 @@ export declare const enum VNodeType {
5
5
  Text = 0,
6
6
  Comment = 1,
7
7
  Element = 2,
8
- CustomElement = 3
8
+ CustomElement = 3,
9
+ Static = 4
9
10
  }
10
- export declare type VNode = VText | VComment | VElement | VCustomElement;
11
+ export declare type VNode = VText | VComment | VElement | VCustomElement | VStatic;
11
12
  export declare type VParentElement = VElement | VCustomElement;
12
13
  export declare type VNodes = Readonly<Array<VNode | null>>;
13
14
  export interface BaseVNode {
@@ -17,6 +18,12 @@ export interface BaseVNode {
17
18
  key: Key | undefined;
18
19
  owner: VM;
19
20
  }
21
+ export interface VStatic extends BaseVNode {
22
+ type: VNodeType.Static;
23
+ sel: undefined;
24
+ key: Key;
25
+ fragment: Element;
26
+ }
20
27
  export interface VText extends BaseVNode {
21
28
  type: VNodeType.Text;
22
29
  sel: undefined;