Skip to content

Commit e9cf8c7

Browse files
Api version limit for complex template expressions (#5520)
* feat: added ability to toggle experimentalComplexExpressions in ssr fixtures * chore: disable * feat: ssr cte support * fix: ssr coverage * chore: revert test change * fix: additional testing around ssr specific codepaths * fix: additional testing around ssr specific codepaths * feat: api specific errors, tests * fix: bundlesize * fix: retain original switch logic * fix: review comments
1 parent 4eb2987 commit e9cf8c7

File tree

31 files changed

+221
-49
lines changed

31 files changed

+221
-49
lines changed

packages/@lwc/errors/src/compiler/error-info/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
66
*/
77
/**
8-
* Next error code: 1209
8+
* Next error code: 1211
99
*/
1010

1111
export * from './compiler';

packages/@lwc/errors/src/compiler/error-info/template-transform.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -980,19 +980,35 @@ export const ParserDiagnostics = {
980980
url: '',
981981
},
982982

983-
COMPUTED_PROPERTY_ACCESS_NOT_ALLOWED_COMPLEX: {
983+
COMPUTED_PROPERTY_ACCESS_NOT_ALLOWED_CTE_UNQUOTED: {
984984
code: 1207,
985985
message:
986986
'Template expression doesn\'t allow computed property access unless the expression is surrounded by quotes: "{0}"',
987987
level: DiagnosticLevel.Error,
988988
url: '',
989989
},
990990

991-
INVALID_NODE_COMPLEX: {
991+
INVALID_NODE_CTE_UNQUOTED: {
992992
code: 1208,
993993
message:
994994
'Template expression doesn\'t allow {0} unless the expression is surrounded by quotes: "{1}"',
995995
level: DiagnosticLevel.Error,
996996
url: '',
997997
},
998+
999+
COMPUTED_PROPERTY_ACCESS_NOT_ALLOWED_CTE_API_VERSION: {
1000+
code: 1209,
1001+
message:
1002+
"Template expression doesn't allow computed property access. The current component API version ({1}) is insufficient and must be increased to at least {2} for this type of expression.",
1003+
level: DiagnosticLevel.Error,
1004+
url: '',
1005+
},
1006+
1007+
INVALID_NODE_CTE_API_VERSION: {
1008+
code: 1210,
1009+
message:
1010+
"Template expression doesn't allow {0}. The current component API version ({1}) is insufficient and must be increased to at least {2} for this type of expression.",
1011+
level: DiagnosticLevel.Error,
1012+
url: '',
1013+
},
9981014
};

packages/@lwc/shared/src/api-version.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export const enum APIVersion {
1414
V61_250_SUMMER_24 = 61,
1515
V62_252_WINTER_25 = 62,
1616
V63_254_SPRING_25 = 63,
17+
V64_256_SUMMER_25 = 64,
18+
V65_258_WINTER_26 = 65,
19+
V66_260_SPRING_26 = 66,
1720
}
1821

1922
// These must be updated when the enum is updated.
@@ -27,6 +30,9 @@ const allVersions = [
2730
APIVersion.V61_250_SUMMER_24,
2831
APIVersion.V62_252_WINTER_25,
2932
APIVersion.V63_254_SPRING_25,
33+
APIVersion.V64_256_SUMMER_25,
34+
APIVersion.V65_258_WINTER_26,
35+
APIVersion.V66_260_SPRING_26,
3036
];
3137
const allVersionsSet = /*@__PURE__@*/ new Set(allVersions);
3238
export const LOWEST_API_VERSION = allVersions[0];
@@ -118,31 +124,38 @@ export const enum APIFeature {
118124
}
119125

120126
/**
121-
*
122127
* @param apiVersionFeature
123-
* @param apiVersion
124128
*/
125-
export function isAPIFeatureEnabled(
126-
apiVersionFeature: APIFeature,
127-
apiVersion: APIVersion
128-
): boolean {
129+
export function minApiVersion(apiVersionFeature: APIFeature): APIVersion {
129130
switch (apiVersionFeature) {
130131
case APIFeature.LOWERCASE_SCOPE_TOKENS:
131132
case APIFeature.TREAT_ALL_PARSE5_ERRORS_AS_ERRORS:
132-
return apiVersion >= APIVersion.V59_246_WINTER_24;
133+
return APIVersion.V59_246_WINTER_24;
133134
case APIFeature.DISABLE_OBJECT_REST_SPREAD_TRANSFORMATION:
134135
case APIFeature.SKIP_UNNECESSARY_REGISTER_DECORATORS:
135136
case APIFeature.USE_COMMENTS_FOR_FRAGMENT_BOOKENDS:
136137
case APIFeature.USE_FRAGMENTS_FOR_LIGHT_DOM_SLOTS:
137-
return apiVersion >= APIVersion.V60_248_SPRING_24;
138+
return APIVersion.V60_248_SPRING_24;
138139
case APIFeature.ENABLE_ELEMENT_INTERNALS_AND_FACE:
139140
case APIFeature.USE_LIGHT_DOM_SLOT_FORWARDING:
140-
return apiVersion >= APIVersion.V61_250_SUMMER_24;
141+
return APIVersion.V61_250_SUMMER_24;
141142
case APIFeature.ENABLE_THIS_DOT_HOST_ELEMENT:
142143
case APIFeature.ENABLE_THIS_DOT_STYLE:
143144
case APIFeature.TEMPLATE_CLASS_NAME_OBJECT_BINDING:
144-
return apiVersion >= APIVersion.V62_252_WINTER_25;
145+
return APIVersion.V62_252_WINTER_25;
145146
case APIFeature.ENABLE_COMPLEX_TEMPLATE_EXPRESSIONS:
146-
return apiVersion >= APIVersion.V63_254_SPRING_25;
147+
return APIVersion.V66_260_SPRING_26;
147148
}
148149
}
150+
151+
/**
152+
*
153+
* @param apiVersionFeature
154+
* @param apiVersion
155+
*/
156+
export function isAPIFeatureEnabled(
157+
apiVersionFeature: APIFeature,
158+
apiVersion: APIVersion
159+
): boolean {
160+
return apiVersion >= minApiVersion(apiVersionFeature);
161+
}

packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ async function compileFixture({
6161
}: {
6262
entry: string;
6363
dirname: string;
64-
experimentalComplexExpressions: boolean;
64+
experimentalComplexExpressions: boolean | undefined;
6565
}) {
6666
const modulesDir = path.resolve(dirname, './modules');
6767
const outputFile = path.resolve(dirname, './dist/compiled-experimental-ssr.js');

packages/@lwc/ssr-compiler/src/compile-template/expression.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
66
*/
77
import { bindExpression } from '@lwc/template-compiler';
8+
import { APIFeature, isAPIFeatureEnabled } from '@lwc/shared';
89
import type {
910
ComplexExpression as IrComplexExpression,
1011
Expression as IrExpression,
@@ -18,11 +19,17 @@ export function expressionIrToEs(
1819
node: IrExpression | IrComplexExpression,
1920
cxt: TransformerContext
2021
): EsExpression {
22+
const isComplexTemplateExpressionEnabled =
23+
cxt.templateOptions.experimentalComplexExpressions &&
24+
isAPIFeatureEnabled(
25+
APIFeature.ENABLE_COMPLEX_TEMPLATE_EXPRESSIONS,
26+
cxt.templateOptions.apiVersion
27+
);
2128
return bindExpression(
2229
node as IrComplexExpression,
23-
(n: EsIdentifier) => cxt.isLocalVar((n as EsIdentifier).name),
30+
(n: EsIdentifier) => cxt.isLocalVar(n.name),
2431
'instance',
25-
cxt.templateOptions.experimentalComplexExpressions
32+
isComplexTemplateExpressionEnabled
2633
);
2734
}
2835

packages/@lwc/ssr-compiler/src/compile-template/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ export default function compileTemplate(
116116
(directive) => directive.name === 'PreserveComments'
117117
)?.value?.value;
118118
const experimentalComplexExpressions = Boolean(options.experimentalComplexExpressions);
119+
const apiVersion = Number(options.apiVersion);
119120

120121
const { addImport, getImports, statements, cxt } = templateIrToEsTree(root, {
121122
preserveComments,
122123
experimentalComplexExpressions,
124+
apiVersion,
123125
});
124126
addImport(['renderStylesheets', 'hasScopedStaticStylesheets']);
125127
for (const [imports, source] of getStylesheetImports(filename)) {

packages/@lwc/ssr-compiler/src/compile-template/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@ export interface TransformerContext {
4848
export interface TemplateOpts {
4949
preserveComments: boolean;
5050
experimentalComplexExpressions: boolean;
51+
apiVersion: number;
5152
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<section>
3+
<x-child foo="{foo()}"></x-child>
4+
</section>
5+
</template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"experimentalComplexExpressions": true,
3+
"apiVersion": 59
4+
}

0 commit comments

Comments
 (0)