@lwc/template-compiler 2.48.0 → 2.49.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.
package/dist/index.js CHANGED
@@ -33,12 +33,6 @@ class State {
33
33
  }
34
34
  }
35
35
 
36
- /*
37
- * Copyright (c) 2018, salesforce.com, inc.
38
- * All rights reserved.
39
- * SPDX-License-Identifier: MIT
40
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
41
- */
42
36
  const SECURE_REGISTER_TEMPLATE_METHOD_NAME = 'registerTemplate';
43
37
  const PARSE_FRAGMENT_METHOD_NAME = 'parseFragment';
44
38
  const PARSE_SVG_FRAGMENT_METHOD_NAME = 'parseSVGFragment';
@@ -61,6 +55,8 @@ const DASHED_TAGNAME_ELEMENT_SET = new Set([
61
55
  'font-face-name',
62
56
  'missing-glyph',
63
57
  ]);
58
+ // Subset of LWC template directives that can safely be statically optimized
59
+ const STATIC_SAFE_DIRECTIVES = new Set(['Ref']);
64
60
 
65
61
  /*
66
62
  * Copyright (c) 2018, salesforce.com, inc.
@@ -3774,8 +3770,12 @@ function isInIteratorElement(ctx) {
3774
3770
  return !!(getForOfParent(ctx) || getForEachParent(ctx));
3775
3771
  }
3776
3772
 
3777
- function checkElement(element, state) {
3778
- // Custom elements are not allowed to have a custom renderer hook.
3773
+ function shouldAddCustomRenderer(element, state) {
3774
+ // Elements of type `ExternalComponent` (e.g., elements with the lwc:external directive)
3775
+ if (state.crDirectives.has('lwc:external') && element.type === 'ExternalComponent') {
3776
+ return true;
3777
+ }
3778
+ // Elements of type `Component` are not allowed to have custom renderer hooks.
3779
3779
  // The renderer is cascaded down from the owner(custom element) to all its child nodes who
3780
3780
  // do not have a renderer specified.
3781
3781
  // lwc:component will resolve to a custom element at runtime.
@@ -3817,7 +3817,7 @@ function isCustomRendererHookRequired(element, state) {
3817
3817
  return cachedResult;
3818
3818
  }
3819
3819
  else {
3820
- addCustomRenderer = checkElement(element, state);
3820
+ addCustomRenderer = shouldAddCustomRenderer(element, state);
3821
3821
  state.crCheckedElements.set(element, addCustomRenderer);
3822
3822
  }
3823
3823
  }
@@ -3957,8 +3957,9 @@ function isStaticNode(node) {
3957
3957
  // TODO [#3313]: re-enable static optimization for SVGs once scope token is always lowercase
3958
3958
  return false;
3959
3959
  }
3960
+ // it is an element
3960
3961
  result && (result = isElement(node));
3961
- // it is an element.
3962
+ // all attrs are static-safe
3962
3963
  result && (result = attributes.every(({ name, value }) => {
3963
3964
  return (isLiteral(value) &&
3964
3965
  name !== 'slot' &&
@@ -3971,11 +3972,22 @@ function isStaticNode(node) {
3971
3972
  // Check for ScopedFragId
3972
3973
  !(isAllowedFragOnlyUrlsXHTML(nodeName, name, namespace) &&
3973
3974
  isFragmentOnlyUrl(value.value)));
3974
- })); // all attrs are static
3975
- result && (result = directives.length === 0); // do not have any directive
3976
- result && (result = properties.every((prop) => isLiteral(prop.value))); // all properties are static
3975
+ }));
3976
+ // all directives are static-safe
3977
+ result && (result = !directives.some((directive) => !STATIC_SAFE_DIRECTIVES.has(directive.name)));
3978
+ // all properties are static
3979
+ result && (result = properties.every((prop) => isLiteral(prop.value)));
3977
3980
  return result;
3978
3981
  }
3982
+ function isSafeStaticChild(childNode) {
3983
+ if (!isBaseElement(childNode)) {
3984
+ // don't need to check non-base-element nodes, because they don't have listeners/directives
3985
+ return true;
3986
+ }
3987
+ // Bail out if any children have event listeners or directives. These are only allowed at the top level of a
3988
+ // static fragment, because the engine currently cannot set listeners/refs/etc. on nodes inside a static fragment.
3989
+ return childNode.listeners.length === 0 && childNode.directives.length === 0;
3990
+ }
3979
3991
  function collectStaticNodes(node, staticNodes, state) {
3980
3992
  let childrenAreStatic = true;
3981
3993
  let nodeIsStatic;
@@ -3990,9 +4002,7 @@ function collectStaticNodes(node, staticNodes, state) {
3990
4002
  node.children.forEach((childNode) => {
3991
4003
  collectStaticNodes(childNode, staticNodes, state);
3992
4004
  childrenAreStatic && (childrenAreStatic = staticNodes.has(childNode));
3993
- // Bail out if any children have event listeners. Event listeners are only allowed at the top level of a
3994
- // static fragment, because the engine currently cannot attach listeners to nodes inside a static fragment.
3995
- childrenAreStatic && (childrenAreStatic = !isBaseElement(childNode) || childNode.listeners.length === 0);
4005
+ childrenAreStatic && (childrenAreStatic = isSafeStaticChild(childNode));
3996
4006
  });
3997
4007
  // for IfBlock and ElseifBlock, traverse down the else branch
3998
4008
  if (isConditionalParentBlock(node) && node.else) {
@@ -4439,11 +4449,16 @@ class CodeGen {
4439
4449
  }
4440
4450
  genEventListeners(listeners) {
4441
4451
  const listenerObj = Object.fromEntries(listeners.map((listener) => [listener.name, listener]));
4442
- return objectToAST(listenerObj, (key) => {
4452
+ const listenerObjectAST = objectToAST(listenerObj, (key) => {
4443
4453
  const componentHandler = this.bindExpression(listenerObj[key].handler);
4444
4454
  const handler = this.genBind(componentHandler);
4445
4455
  return memorizeHandler(this, componentHandler, handler);
4446
4456
  });
4457
+ return property$1(identifier('on'), listenerObjectAST);
4458
+ }
4459
+ genRef(ref) {
4460
+ this.hasRefs = true;
4461
+ return property$1(identifier('ref'), ref.value);
4447
4462
  }
4448
4463
  /**
4449
4464
  * This routine generates an expression that avoids
@@ -4544,7 +4559,7 @@ class CodeGen {
4544
4559
  });
4545
4560
  return expression;
4546
4561
  }
4547
- genHoistedElement(element, slotParentName) {
4562
+ genStaticElement(element, slotParentName) {
4548
4563
  const key = slotParentName !== undefined
4549
4564
  ? `@${slotParentName}:${this.generateKey()}`
4550
4565
  : this.generateKey();
@@ -4570,9 +4585,20 @@ class CodeGen {
4570
4585
  expr,
4571
4586
  });
4572
4587
  const args = [callExpression(identifier$1, []), literal$1(key)];
4573
- if (element.listeners.length) {
4574
- const listenerObjectAST = this.genEventListeners(element.listeners);
4575
- args.push(objectExpression([property$1(identifier('on'), listenerObjectAST)]));
4588
+ // Only add the third argument (databag) if this element needs it
4589
+ if (element.listeners.length || element.directives.length) {
4590
+ const databagProperties = [];
4591
+ // has event listeners
4592
+ if (element.listeners.length) {
4593
+ databagProperties.push(this.genEventListeners(element.listeners));
4594
+ }
4595
+ // see STATIC_SAFE_DIRECTIVES for what's allowed here
4596
+ for (const directive of element.directives) {
4597
+ if (directive.name === 'Ref') {
4598
+ databagProperties.push(this.genRef(directive));
4599
+ }
4600
+ }
4601
+ args.push(objectExpression(databagProperties));
4576
4602
  }
4577
4603
  return this._renderApiCall(RENDER_APIS.staticFragment, args);
4578
4604
  }
@@ -4767,7 +4793,7 @@ function transform(codeGen) {
4767
4793
  let res;
4768
4794
  if (codeGen.staticNodes.has(element) && isElement(element)) {
4769
4795
  // do not process children of static nodes.
4770
- return codeGen.genHoistedElement(element, slotParentName);
4796
+ return codeGen.genStaticElement(element, slotParentName);
4771
4797
  }
4772
4798
  const children = transformChildren(element);
4773
4799
  const { name } = element;
@@ -5161,8 +5187,7 @@ function transform(codeGen) {
5161
5187
  }
5162
5188
  // Properties: lwc:ref directive
5163
5189
  if (ref) {
5164
- data.push(property$1(identifier('ref'), ref.value));
5165
- codeGen.hasRefs = true;
5190
+ data.push(codeGen.genRef(ref));
5166
5191
  }
5167
5192
  if (propsObj.properties.length) {
5168
5193
  data.push(property$1(identifier('props'), propsObj));
@@ -5202,8 +5227,7 @@ function transform(codeGen) {
5202
5227
  }
5203
5228
  // Event handler
5204
5229
  if (listeners.length) {
5205
- const listenerObjAST = codeGen.genEventListeners(listeners);
5206
- data.push(property$1(identifier('on'), listenerObjAST));
5230
+ data.push(codeGen.genEventListeners(listeners));
5207
5231
  }
5208
5232
  // SVG handling
5209
5233
  if (element.namespace === SVG_NAMESPACE) {
@@ -5300,5 +5324,5 @@ function compile(source, config) {
5300
5324
  }
5301
5325
 
5302
5326
  export { ElementDirectiveName, LWCDirectiveDomMode, LWCDirectiveRenderMode, LwcTagName, RootDirectiveName, TemplateDirectiveName, compile, compile as default, parse };
5303
- /** version: 2.48.0 */
5327
+ /** version: 2.49.0 */
5304
5328
  //# sourceMappingURL=index.js.map