@lwc/template-compiler 2.48.0 → 2.49.1
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/README.md +1 -1
- package/dist/codegen/codegen.d.ts +4 -3
- package/dist/config.d.ts +1 -1
- package/dist/index.cjs.js +52 -31
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +52 -31
- package/dist/index.js.map +1 -1
- package/dist/shared/constants.d.ts +2 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ const { code, warnings } = compile(`<template><h1>Hello World!</h1></template>`,
|
|
|
54
54
|
- `enableDynamicComponents` (boolean, optional, `false` by default) - set to `true` to enable `lwc:is` directive in the template.
|
|
55
55
|
- `preserveHtmlComments` (boolean, optional, `false` by default) - set to `true` to disable the default behavior of stripping HTML comments.
|
|
56
56
|
- `enableStaticContentOptimization` (boolean, optional, `true` by default) - set to `false` to disable static content optimizations.
|
|
57
|
-
- `enableLwcSpread` (boolean, optional, `
|
|
57
|
+
- `enableLwcSpread` (boolean, optional, `true` by default) - Deprecated. Ignored by template-compiler. `lwc:spread` is always enabled.
|
|
58
58
|
- `customRendererConfig` (CustomRendererConfig, optional) - specifies a configuration to use to match elements. Matched elements will get a custom renderer hook in the generated template.
|
|
59
59
|
- `instrumentation` (InstrumentationObject, optional) - instrumentation object to gather metrics and non-error logs for internal use. See the `@lwc/errors` package for details on the interface.
|
|
60
60
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as t from '../shared/estree';
|
|
2
|
-
import { ChildNode, Element, Expression, ComplexExpression, Literal, LWCDirectiveRenderMode, Root, EventListener } from '../shared/types';
|
|
2
|
+
import { ChildNode, Element, Expression, ComplexExpression, Literal, LWCDirectiveRenderMode, Root, EventListener, RefDirective } from '../shared/types';
|
|
3
3
|
import State from '../state';
|
|
4
4
|
export default class CodeGen {
|
|
5
5
|
/** The AST root. */
|
|
@@ -76,7 +76,8 @@ export default class CodeGen {
|
|
|
76
76
|
genTabIndex(children: [t.Expression]): import("estree").CallExpression;
|
|
77
77
|
getMemorizationId(): import("estree").Identifier;
|
|
78
78
|
genBooleanAttributeExpr(bindExpr: t.Expression): import("estree").ConditionalExpression;
|
|
79
|
-
genEventListeners(listeners: EventListener[]): import("estree").
|
|
79
|
+
genEventListeners(listeners: EventListener[]): import("estree").Property;
|
|
80
|
+
genRef(ref: RefDirective): import("estree").Property;
|
|
80
81
|
/**
|
|
81
82
|
* This routine generates an expression that avoids
|
|
82
83
|
* computing the sanitized html of a raw html if it does not change
|
|
@@ -101,5 +102,5 @@ export default class CodeGen {
|
|
|
101
102
|
* - {value[index]} --> {$cmp.value[$cmp.index]}
|
|
102
103
|
*/
|
|
103
104
|
bindExpression(expression: Expression | Literal | ComplexExpression): t.Expression;
|
|
104
|
-
|
|
105
|
+
genStaticElement(element: Element, slotParentName?: string): t.Expression;
|
|
105
106
|
}
|
package/dist/config.d.ts
CHANGED
package/dist/index.cjs.js
CHANGED
|
@@ -58,12 +58,6 @@ class State {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
/*
|
|
62
|
-
* Copyright (c) 2018, salesforce.com, inc.
|
|
63
|
-
* All rights reserved.
|
|
64
|
-
* SPDX-License-Identifier: MIT
|
|
65
|
-
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
|
|
66
|
-
*/
|
|
67
61
|
const SECURE_REGISTER_TEMPLATE_METHOD_NAME = 'registerTemplate';
|
|
68
62
|
const PARSE_FRAGMENT_METHOD_NAME = 'parseFragment';
|
|
69
63
|
const PARSE_SVG_FRAGMENT_METHOD_NAME = 'parseSVGFragment';
|
|
@@ -86,6 +80,8 @@ const DASHED_TAGNAME_ELEMENT_SET = new Set([
|
|
|
86
80
|
'font-face-name',
|
|
87
81
|
'missing-glyph',
|
|
88
82
|
]);
|
|
83
|
+
// Subset of LWC template directives that can safely be statically optimized
|
|
84
|
+
const STATIC_SAFE_DIRECTIVES = new Set(['Ref']);
|
|
89
85
|
|
|
90
86
|
/*
|
|
91
87
|
* Copyright (c) 2018, salesforce.com, inc.
|
|
@@ -186,7 +182,7 @@ function normalizeConfig(config) {
|
|
|
186
182
|
}
|
|
187
183
|
return Object.assign(Object.assign(Object.assign({ preserveHtmlComments: false, experimentalComputedMemberExpression: false,
|
|
188
184
|
// TODO [#3370]: remove experimental template expression flag
|
|
189
|
-
experimentalComplexExpressions: false, experimentalDynamicDirective: false, enableDynamicComponents: false, enableStaticContentOptimization: true, enableLwcSpread:
|
|
185
|
+
experimentalComplexExpressions: false, experimentalDynamicDirective: false, enableDynamicComponents: false, enableStaticContentOptimization: true, enableLwcSpread: true }, config), { customRendererConfig }), { instrumentation });
|
|
190
186
|
}
|
|
191
187
|
|
|
192
188
|
function isIdentifier(node) {
|
|
@@ -3190,9 +3186,6 @@ function applyLwcSpreadDirective(ctx, parsedAttr, element) {
|
|
|
3190
3186
|
if (!lwcSpread) {
|
|
3191
3187
|
return;
|
|
3192
3188
|
}
|
|
3193
|
-
if (!ctx.config.enableLwcSpread) {
|
|
3194
|
-
ctx.throwOnNode(errors.ParserDiagnostics.INVALID_OPTS_LWC_SPREAD, element);
|
|
3195
|
-
}
|
|
3196
3189
|
const { value: lwcSpreadAttr } = lwcSpread;
|
|
3197
3190
|
if (!isExpression$1(lwcSpreadAttr)) {
|
|
3198
3191
|
ctx.throwOnNode(errors.ParserDiagnostics.INVALID_LWC_SPREAD_LITERAL_PROP, element, [`<${tag}>`]);
|
|
@@ -3799,8 +3792,12 @@ function isInIteratorElement(ctx) {
|
|
|
3799
3792
|
return !!(getForOfParent(ctx) || getForEachParent(ctx));
|
|
3800
3793
|
}
|
|
3801
3794
|
|
|
3802
|
-
function
|
|
3803
|
-
//
|
|
3795
|
+
function shouldAddCustomRenderer(element, state) {
|
|
3796
|
+
// Elements of type `ExternalComponent` (e.g., elements with the lwc:external directive)
|
|
3797
|
+
if (state.crDirectives.has('lwc:external') && element.type === 'ExternalComponent') {
|
|
3798
|
+
return true;
|
|
3799
|
+
}
|
|
3800
|
+
// Elements of type `Component` are not allowed to have custom renderer hooks.
|
|
3804
3801
|
// The renderer is cascaded down from the owner(custom element) to all its child nodes who
|
|
3805
3802
|
// do not have a renderer specified.
|
|
3806
3803
|
// lwc:component will resolve to a custom element at runtime.
|
|
@@ -3842,7 +3839,7 @@ function isCustomRendererHookRequired(element, state) {
|
|
|
3842
3839
|
return cachedResult;
|
|
3843
3840
|
}
|
|
3844
3841
|
else {
|
|
3845
|
-
addCustomRenderer =
|
|
3842
|
+
addCustomRenderer = shouldAddCustomRenderer(element, state);
|
|
3846
3843
|
state.crCheckedElements.set(element, addCustomRenderer);
|
|
3847
3844
|
}
|
|
3848
3845
|
}
|
|
@@ -3982,8 +3979,9 @@ function isStaticNode(node) {
|
|
|
3982
3979
|
// TODO [#3313]: re-enable static optimization for SVGs once scope token is always lowercase
|
|
3983
3980
|
return false;
|
|
3984
3981
|
}
|
|
3982
|
+
// it is an element
|
|
3985
3983
|
result && (result = isElement(node));
|
|
3986
|
-
//
|
|
3984
|
+
// all attrs are static-safe
|
|
3987
3985
|
result && (result = attributes.every(({ name, value }) => {
|
|
3988
3986
|
return (isLiteral(value) &&
|
|
3989
3987
|
name !== 'slot' &&
|
|
@@ -3996,11 +3994,22 @@ function isStaticNode(node) {
|
|
|
3996
3994
|
// Check for ScopedFragId
|
|
3997
3995
|
!(isAllowedFragOnlyUrlsXHTML(nodeName, name, namespace) &&
|
|
3998
3996
|
isFragmentOnlyUrl(value.value)));
|
|
3999
|
-
}));
|
|
4000
|
-
|
|
4001
|
-
result && (result =
|
|
3997
|
+
}));
|
|
3998
|
+
// all directives are static-safe
|
|
3999
|
+
result && (result = !directives.some((directive) => !STATIC_SAFE_DIRECTIVES.has(directive.name)));
|
|
4000
|
+
// all properties are static
|
|
4001
|
+
result && (result = properties.every((prop) => isLiteral(prop.value)));
|
|
4002
4002
|
return result;
|
|
4003
4003
|
}
|
|
4004
|
+
function isSafeStaticChild(childNode) {
|
|
4005
|
+
if (!isBaseElement(childNode)) {
|
|
4006
|
+
// don't need to check non-base-element nodes, because they don't have listeners/directives
|
|
4007
|
+
return true;
|
|
4008
|
+
}
|
|
4009
|
+
// Bail out if any children have event listeners or directives. These are only allowed at the top level of a
|
|
4010
|
+
// static fragment, because the engine currently cannot set listeners/refs/etc. on nodes inside a static fragment.
|
|
4011
|
+
return childNode.listeners.length === 0 && childNode.directives.length === 0;
|
|
4012
|
+
}
|
|
4004
4013
|
function collectStaticNodes(node, staticNodes, state) {
|
|
4005
4014
|
let childrenAreStatic = true;
|
|
4006
4015
|
let nodeIsStatic;
|
|
@@ -4015,9 +4024,7 @@ function collectStaticNodes(node, staticNodes, state) {
|
|
|
4015
4024
|
node.children.forEach((childNode) => {
|
|
4016
4025
|
collectStaticNodes(childNode, staticNodes, state);
|
|
4017
4026
|
childrenAreStatic && (childrenAreStatic = staticNodes.has(childNode));
|
|
4018
|
-
|
|
4019
|
-
// static fragment, because the engine currently cannot attach listeners to nodes inside a static fragment.
|
|
4020
|
-
childrenAreStatic && (childrenAreStatic = !isBaseElement(childNode) || childNode.listeners.length === 0);
|
|
4027
|
+
childrenAreStatic && (childrenAreStatic = isSafeStaticChild(childNode));
|
|
4021
4028
|
});
|
|
4022
4029
|
// for IfBlock and ElseifBlock, traverse down the else branch
|
|
4023
4030
|
if (isConditionalParentBlock(node) && node.else) {
|
|
@@ -4464,11 +4471,16 @@ class CodeGen {
|
|
|
4464
4471
|
}
|
|
4465
4472
|
genEventListeners(listeners) {
|
|
4466
4473
|
const listenerObj = Object.fromEntries(listeners.map((listener) => [listener.name, listener]));
|
|
4467
|
-
|
|
4474
|
+
const listenerObjectAST = objectToAST(listenerObj, (key) => {
|
|
4468
4475
|
const componentHandler = this.bindExpression(listenerObj[key].handler);
|
|
4469
4476
|
const handler = this.genBind(componentHandler);
|
|
4470
4477
|
return memorizeHandler(this, componentHandler, handler);
|
|
4471
4478
|
});
|
|
4479
|
+
return property$1(identifier('on'), listenerObjectAST);
|
|
4480
|
+
}
|
|
4481
|
+
genRef(ref) {
|
|
4482
|
+
this.hasRefs = true;
|
|
4483
|
+
return property$1(identifier('ref'), ref.value);
|
|
4472
4484
|
}
|
|
4473
4485
|
/**
|
|
4474
4486
|
* This routine generates an expression that avoids
|
|
@@ -4569,7 +4581,7 @@ class CodeGen {
|
|
|
4569
4581
|
});
|
|
4570
4582
|
return expression;
|
|
4571
4583
|
}
|
|
4572
|
-
|
|
4584
|
+
genStaticElement(element, slotParentName) {
|
|
4573
4585
|
const key = slotParentName !== undefined
|
|
4574
4586
|
? `@${slotParentName}:${this.generateKey()}`
|
|
4575
4587
|
: this.generateKey();
|
|
@@ -4595,9 +4607,20 @@ class CodeGen {
|
|
|
4595
4607
|
expr,
|
|
4596
4608
|
});
|
|
4597
4609
|
const args = [callExpression(identifier$1, []), literal$1(key)];
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4610
|
+
// Only add the third argument (databag) if this element needs it
|
|
4611
|
+
if (element.listeners.length || element.directives.length) {
|
|
4612
|
+
const databagProperties = [];
|
|
4613
|
+
// has event listeners
|
|
4614
|
+
if (element.listeners.length) {
|
|
4615
|
+
databagProperties.push(this.genEventListeners(element.listeners));
|
|
4616
|
+
}
|
|
4617
|
+
// see STATIC_SAFE_DIRECTIVES for what's allowed here
|
|
4618
|
+
for (const directive of element.directives) {
|
|
4619
|
+
if (directive.name === 'Ref') {
|
|
4620
|
+
databagProperties.push(this.genRef(directive));
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
args.push(objectExpression(databagProperties));
|
|
4601
4624
|
}
|
|
4602
4625
|
return this._renderApiCall(RENDER_APIS.staticFragment, args);
|
|
4603
4626
|
}
|
|
@@ -4792,7 +4815,7 @@ function transform(codeGen) {
|
|
|
4792
4815
|
let res;
|
|
4793
4816
|
if (codeGen.staticNodes.has(element) && isElement(element)) {
|
|
4794
4817
|
// do not process children of static nodes.
|
|
4795
|
-
return codeGen.
|
|
4818
|
+
return codeGen.genStaticElement(element, slotParentName);
|
|
4796
4819
|
}
|
|
4797
4820
|
const children = transformChildren(element);
|
|
4798
4821
|
const { name } = element;
|
|
@@ -5186,8 +5209,7 @@ function transform(codeGen) {
|
|
|
5186
5209
|
}
|
|
5187
5210
|
// Properties: lwc:ref directive
|
|
5188
5211
|
if (ref) {
|
|
5189
|
-
data.push(
|
|
5190
|
-
codeGen.hasRefs = true;
|
|
5212
|
+
data.push(codeGen.genRef(ref));
|
|
5191
5213
|
}
|
|
5192
5214
|
if (propsObj.properties.length) {
|
|
5193
5215
|
data.push(property$1(identifier('props'), propsObj));
|
|
@@ -5227,8 +5249,7 @@ function transform(codeGen) {
|
|
|
5227
5249
|
}
|
|
5228
5250
|
// Event handler
|
|
5229
5251
|
if (listeners.length) {
|
|
5230
|
-
|
|
5231
|
-
data.push(property$1(identifier('on'), listenerObjAST));
|
|
5252
|
+
data.push(codeGen.genEventListeners(listeners));
|
|
5232
5253
|
}
|
|
5233
5254
|
// SVG handling
|
|
5234
5255
|
if (element.namespace === shared.SVG_NAMESPACE) {
|
|
@@ -5327,5 +5348,5 @@ function compile(source, config) {
|
|
|
5327
5348
|
exports.compile = compile;
|
|
5328
5349
|
exports.default = compile;
|
|
5329
5350
|
exports.parse = parse;
|
|
5330
|
-
/** version: 2.
|
|
5351
|
+
/** version: 2.49.1 */
|
|
5331
5352
|
//# sourceMappingURL=index.cjs.js.map
|