@lwc/ssr-compiler 8.2.0 → 8.3.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.cjs.js CHANGED
@@ -11,22 +11,11 @@ var meriyah = require('meriyah');
11
11
  var shared = require('@lwc/shared');
12
12
  var acorn = require('acorn');
13
13
  var immer = require('immer');
14
+ var node_path = require('node:path');
14
15
  var templateCompiler = require('@lwc/template-compiler');
15
16
  var builders = require('estree-toolkit/dist/builders');
16
17
  var util = require('util');
17
18
 
18
- /*
19
- * Copyright (c) 2024, Salesforce, Inc.
20
- * All rights reserved.
21
- * SPDX-License-Identifier: MIT
22
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
23
- */
24
- /**
25
- * Imports from `lwc` that are allowed in the SSR runtime context.
26
- * Every listed item should be a top-level export from `@lwc/ssr-runtime`.
27
- */
28
- const allowedLwcImports = new Set(['LightningElement']);
29
-
30
19
  /*
31
20
  * Copyright (c) 2024, salesforce.com, inc.
32
21
  * All rights reserved.
@@ -50,14 +39,6 @@ function replaceLwcImport(path, state) {
50
39
  state.lightningElementIdentifier = specifier.local.name;
51
40
  break;
52
41
  }
53
- if (specifier.type === 'ImportSpecifier' && specifier.imported.type === 'Identifier') {
54
- if (!allowedLwcImports.has(specifier.imported.name)) {
55
- throw new Error(`Cannot import "${specifier.imported.name}" in SSR context.`);
56
- }
57
- if (specifier.imported.name === 'LightningElement') {
58
- state.lightningElementIdentifier = specifier.local.name;
59
- }
60
- }
61
42
  }
62
43
  path.replaceWith(estreeToolkit.builders.importDeclaration(path.node.specifiers, estreeToolkit.builders.literal('@lwc/ssr-runtime')));
63
44
  }
@@ -94,19 +75,29 @@ function catalogTmplImport(path, state) {
94
75
  * SPDX-License-Identifier: MIT
95
76
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
96
77
  */
78
+ /** Placeholder value to use to opt out of validation. */
79
+ const NO_VALIDATION = false;
97
80
  const PLACEHOLDER_PREFIX = `__ESTEMPLATE_${Math.random().toString().slice(2)}_PLACEHOLDER__`;
81
+ const getReplacementNode = (state, placeholderId, nodeType) => {
82
+ const key = Number(placeholderId.slice(PLACEHOLDER_PREFIX.length));
83
+ const nodeCount = state.replacementNodes.length;
84
+ if (key >= nodeCount) {
85
+ throw new Error(`Cannot use index ${key} when only ${nodeCount} values have been provided.`);
86
+ }
87
+ const validateReplacement = state.placeholderToValidator.get(key);
88
+ const replacementNode = state.replacementNodes[key];
89
+ if (validateReplacement &&
90
+ !(Array.isArray(replacementNode)
91
+ ? replacementNode.every(validateReplacement)
92
+ : validateReplacement(replacementNode))) {
93
+ throw new Error(`Validation failed for templated node of type ${nodeType}`);
94
+ }
95
+ return replacementNode;
96
+ };
98
97
  const visitors$1 = {
99
98
  Identifier(path, state) {
100
99
  if (path.node?.name.startsWith(PLACEHOLDER_PREFIX)) {
101
- const key = path.node.name.slice(PLACEHOLDER_PREFIX.length);
102
- const validateReplacement = state.placeholderToValidator.get(key);
103
- const replacementNode = state.replacementNodes[key];
104
- if (validateReplacement &&
105
- !(Array.isArray(replacementNode)
106
- ? replacementNode.every(validateReplacement)
107
- : validateReplacement(replacementNode))) {
108
- throw new Error(`Validation failed for templated node of type ${path.node.type}`);
109
- }
100
+ const replacementNode = getReplacementNode(state, path.node.name, path.node.type);
110
101
  if (replacementNode === null) {
111
102
  path.remove();
112
103
  }
@@ -115,7 +106,7 @@ const visitors$1 = {
115
106
  path.remove();
116
107
  }
117
108
  else {
118
- if (path.parentPath.node.type === 'ExpressionStatement') {
109
+ if (path.parentPath?.node?.type === 'ExpressionStatement') {
119
110
  path.parentPath.replaceWithMultiple(replacementNode);
120
111
  }
121
112
  else {
@@ -131,27 +122,34 @@ const visitors$1 = {
131
122
  Literal(path, state) {
132
123
  if (typeof path.node?.value === 'string' &&
133
124
  path.node.value.startsWith(PLACEHOLDER_PREFIX)) {
134
- const key = path.node.value.slice(PLACEHOLDER_PREFIX.length);
135
- const validateReplacement = state.placeholderToValidator.get(key);
136
- const replacementNode = state.replacementNodes[key];
137
- if (validateReplacement && !validateReplacement(replacementNode)) {
138
- throw new Error(`Validation failed for templated node of type ${path.node.type}`);
139
- }
125
+ // A literal can only be replaced with a single node
126
+ const replacementNode = getReplacementNode(state, path.node.value, path.node.type);
140
127
  path.replaceWith(replacementNode);
141
128
  }
142
129
  },
143
130
  };
144
- function esTemplateImpl(javascriptSegments, validatorFns, wrap, unwrap) {
131
+ function esTemplateImpl(javascriptSegments, validators, wrap, unwrap) {
145
132
  let placeholderCount = 0;
146
133
  let parsableCode = javascriptSegments[0];
147
- validatorFns.reverse();
148
134
  const placeholderToValidator = new Map();
149
- for (const segment of javascriptSegments.slice(1)) {
150
- const validatorFn = validatorFns.pop();
151
- if (validatorFn) {
152
- placeholderToValidator.set(placeholderCount.toString(), validatorFn);
135
+ for (let i = 1; i < javascriptSegments.length; i += 1) {
136
+ const segment = javascriptSegments[i];
137
+ const validator = validators[i - 1]; // always one less value than strings in template literals
138
+ if (typeof validator === 'function' || validator === NO_VALIDATION) {
139
+ // Template slot will be filled by a *new* argument passed to the generated function
140
+ if (validator !== NO_VALIDATION) {
141
+ placeholderToValidator.set(placeholderCount, validator);
142
+ }
143
+ parsableCode += `${PLACEHOLDER_PREFIX}${placeholderCount}`;
144
+ placeholderCount += 1;
145
+ }
146
+ else {
147
+ // Template slot uses a *previously defined* argument passed to the generated function
148
+ if (validator >= placeholderCount) {
149
+ throw new Error(`Reference to argument ${validator} at index ${i} cannot be used. Only ${placeholderCount - 1} arguments have been defined.`);
150
+ }
151
+ parsableCode += `${PLACEHOLDER_PREFIX}${validator}`;
153
152
  }
154
- parsableCode += `${PLACEHOLDER_PREFIX}${placeholderCount++}`;
155
153
  parsableCode += segment;
156
154
  }
157
155
  if (wrap) {
@@ -183,16 +181,30 @@ function esTemplateImpl(javascriptSegments, validatorFns, wrap, unwrap) {
183
181
  placeholderToValidator,
184
182
  replacementNodes,
185
183
  }));
186
- return unwrap ? unwrap(result) : result;
184
+ return (unwrap ? unwrap(result) : result);
187
185
  };
188
186
  }
189
- function esTemplate(javascriptSegments, ...validatorFns) {
190
- return esTemplateImpl(javascriptSegments, validatorFns);
187
+ /**
188
+ * Template literal tag that generates a builder function. Like estree's `builders`, but for more
189
+ * complex structures. The template values should be estree `is` validators or a back reference to
190
+ * a previous slot (to re-use the referenced value).
191
+ *
192
+ * To have the generated function return a particular node type, the generic comes _after_ the
193
+ * template literal. Kinda weird, but it's necessary to infer the types of the template values.
194
+ * (If it were at the start, we'd need to explicitly provide _all_ type params. Tedious!)
195
+ * @example
196
+ * const bSum = esTemplate`(${is.identifier}, ${is.identifier}) => ${0} + ${1}`<EsArrowFunctionExpression>
197
+ * const sumFuncNode = bSum(b.identifier('a'), b.identifier('b'))
198
+ * // `sumFuncNode` is an AST node representing `(a, b) => a + b`
199
+ */
200
+ function esTemplate(javascriptSegments, ...Validators) {
201
+ return esTemplateImpl(javascriptSegments, Validators);
191
202
  }
192
- function esTemplateWithYield(javascriptSegments, ...validatorFns) {
203
+ /** Similar to {@linkcode esTemplate}, but supports `yield` expressions. */
204
+ function esTemplateWithYield(javascriptSegments, ...validators) {
193
205
  const wrap = (code) => `function* placeholder() {${code}}`;
194
206
  const unwrap = (node) => node.body.body.length === 1 ? node.body.body[0] : node.body.body;
195
- return esTemplateImpl(javascriptSegments, validatorFns, wrap, unwrap);
207
+ return esTemplateImpl(javascriptSegments, validators, wrap, unwrap);
196
208
  }
197
209
 
198
210
  /*
@@ -201,12 +213,12 @@ function esTemplateWithYield(javascriptSegments, ...validatorFns) {
201
213
  * SPDX-License-Identifier: MIT
202
214
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
203
215
  */
204
- const bDefaultStyleImport = esTemplate `
216
+ const bDefaultStyleImport = (esTemplate `
205
217
  import defaultStylesheets from '${estreeToolkit.is.literal}';
206
- `;
207
- const bDefaultScopedStyleImport = esTemplate `
218
+ `);
219
+ const bDefaultScopedStyleImport = (esTemplate `
208
220
  import defaultScopedStylesheets from '${estreeToolkit.is.literal}';
209
- `;
221
+ `);
210
222
  function catalogStyleImport(path, state) {
211
223
  const specifier = path.node.specifiers[0];
212
224
  if (typeof path.node.source.value !== 'string' ||
@@ -244,14 +256,20 @@ function catalogStaticStylesheets(ids, state) {
244
256
  * SPDX-License-Identifier: MIT
245
257
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
246
258
  */
247
- const isStringLiteral = (node) => estreeToolkit.is.literal(node) && typeof node.value === 'string';
248
- const isIdentOrRenderCall = (node) => estreeToolkit.is.identifier(node) ||
249
- (estreeToolkit.is.callExpression(node) &&
250
- estreeToolkit.is.memberExpression(node.callee) &&
251
- estreeToolkit.is.identifier(node.callee.property) &&
252
- node.callee.property.name === 'render');
259
+ const isStringLiteral = (node) => {
260
+ return estreeToolkit.is.literal(node) && typeof node.value === 'string';
261
+ };
262
+ /** Returns `true` if the node is an identifier or `<something>.render()`. */
263
+ const isIdentOrRenderCall = (node) => {
264
+ return (estreeToolkit.is.identifier(node) ||
265
+ (estreeToolkit.is.callExpression(node) &&
266
+ estreeToolkit.is.memberExpression(node.callee) &&
267
+ estreeToolkit.is.identifier(node.callee.property) &&
268
+ node.callee.property.name === 'render'));
269
+ };
270
+ /** Extends a validator to return `true` if the node is `null`. */
253
271
  function isNullableOf(validator) {
254
- return (node) => node === null || (validator && validator(node));
272
+ return (node) => node === null || validator(node);
255
273
  }
256
274
 
257
275
  /*
@@ -260,9 +278,9 @@ function isNullableOf(validator) {
260
278
  * SPDX-License-Identifier: MIT
261
279
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
262
280
  */
263
- const bImportDeclaration = esTemplate `
281
+ const bImportDeclaration = (esTemplate `
264
282
  import ${estreeToolkit.is.identifier} from "${isStringLiteral}";
265
- `;
283
+ `);
266
284
 
267
285
  /*
268
286
  * Copyright (c) 2024, salesforce.com, inc.
@@ -270,31 +288,40 @@ const bImportDeclaration = esTemplate `
270
288
  * SPDX-License-Identifier: MIT
271
289
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
272
290
  */
273
- const bGenerateMarkup = esTemplate `
291
+ const bGenerateMarkup = (esTemplate `
274
292
  export async function* generateMarkup(tagName, props, attrs, slotted) {
275
293
  attrs = attrs ?? {};
276
294
  ${isNullableOf(estreeToolkit.is.expressionStatement)};
277
295
  const instance = new ${estreeToolkit.is.identifier}({
278
296
  tagName: tagName.toUpperCase(),
279
297
  });
280
- instance.__internal__setState(props, __REFLECTED_PROPS__, attrs);
298
+ instance[__SYMBOL__SET_INTERNALS](props, __REFLECTED_PROPS__, attrs);
281
299
  instance.isConnected = true;
282
- instance.connectedCallback?.();
300
+ if (instance.connectedCallback) {
301
+ __mutationTracker.enable(instance);
302
+ instance.connectedCallback();
303
+ __mutationTracker.disable(instance);
304
+ }
283
305
  const tmplFn = ${isIdentOrRenderCall} ?? __fallbackTmpl;
284
306
  yield \`<\${tagName}\`;
285
307
  yield tmplFn.stylesheetScopeTokenHostClass ?? '';
286
- yield *__renderAttrs(instance, attrs)
308
+ yield* __renderAttrs(instance, attrs)
287
309
  yield '>';
288
- yield* tmplFn(props, attrs, slotted, ${estreeToolkit.is.identifier}, instance);
310
+ yield* tmplFn(props, attrs, slotted, ${1}, instance);
289
311
  yield \`</\${tagName}>\`;
290
312
  }
291
- `;
292
- const bInsertFallbackTmplImport = esTemplate `
293
- import { fallbackTmpl as __fallbackTmpl, renderAttrs as __renderAttrs } from '@lwc/ssr-runtime';
294
- `;
295
- const bCreateReflectedPropArr = esTemplate `
313
+ `);
314
+ const bInsertFallbackTmplImport = (esTemplate `
315
+ import {
316
+ fallbackTmpl as __fallbackTmpl,
317
+ mutationTracker as __mutationTracker,
318
+ renderAttrs as __renderAttrs,
319
+ SYMBOL__SET_INTERNALS as __SYMBOL__SET_INTERNALS,
320
+ } from '@lwc/ssr-runtime';
321
+ `);
322
+ const bCreateReflectedPropArr = (esTemplate `
296
323
  const __REFLECTED_PROPS__ = ${estreeToolkit.is.arrayExpression};
297
- `;
324
+ `);
298
325
  function bReflectedAttrsObj(reflectedPropNames) {
299
326
  // This will build getter properties for each reflected property. It'll look
300
327
  // something like this:
@@ -345,7 +372,7 @@ function addGenerateMarkupExport(program, state, filename) {
345
372
  ? estreeToolkit.builders.callExpression(estreeToolkit.builders.memberExpression(estreeToolkit.builders.identifier('instance'), estreeToolkit.builders.identifier('render')), [])
346
373
  : estreeToolkit.builders.identifier('tmpl');
347
374
  if (!tmplExplicitImports) {
348
- const defaultTmplPath = filename.replace(/\.js$/, '.html');
375
+ const defaultTmplPath = `./${node_path.basename(filename, 'js')}html`;
349
376
  program.body.unshift(bImportDeclaration(estreeToolkit.builders.identifier('tmpl'), estreeToolkit.builders.literal(defaultTmplPath)));
350
377
  }
351
378
  let attrsAugmentation = null;
@@ -355,7 +382,7 @@ function addGenerateMarkupExport(program, state, filename) {
355
382
  const reflectedPropArr = estreeToolkit.builders.arrayExpression([...state.reflectedPropsInPlay].map((propName) => estreeToolkit.builders.literal(propName)));
356
383
  program.body.unshift(bInsertFallbackTmplImport());
357
384
  program.body.push(bCreateReflectedPropArr(reflectedPropArr));
358
- program.body.push(bGenerateMarkup(attrsAugmentation, classIdentifier, renderCall, classIdentifier));
385
+ program.body.push(bGenerateMarkup(attrsAugmentation, classIdentifier, renderCall));
359
386
  }
360
387
 
361
388
  /*
@@ -485,33 +512,1199 @@ function compileJS(src, filename) {
485
512
  };
486
513
  }
487
514
 
515
+ /**
516
+ * Copyright (c) 2024 Salesforce, Inc.
517
+ */
518
+ /*
519
+ * Copyright (c) 2024, Salesforce, Inc.
520
+ * All rights reserved.
521
+ * SPDX-License-Identifier: MIT
522
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
523
+ */
524
+
525
+ /*
526
+ * Copyright (c) 2018, salesforce.com, inc.
527
+ * All rights reserved.
528
+ * SPDX-License-Identifier: MIT
529
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
530
+ */
531
+ var DiagnosticLevel;
532
+ (function (DiagnosticLevel) {
533
+ /** Unexpected error, parsing error, bundling error */
534
+ DiagnosticLevel[DiagnosticLevel["Fatal"] = 0] = "Fatal";
535
+ /** Linting error with error level, invalid external reference, invalid import, invalid transform */
536
+ DiagnosticLevel[DiagnosticLevel["Error"] = 1] = "Error";
537
+ /** Linting error with warning level, usage of an API to be deprecated */
538
+ DiagnosticLevel[DiagnosticLevel["Warning"] = 2] = "Warning";
539
+ /** Logging messages */
540
+ DiagnosticLevel[DiagnosticLevel["Log"] = 3] = "Log";
541
+ })(DiagnosticLevel || (DiagnosticLevel = {}));
542
+
488
543
  /*
489
544
  * Copyright (c) 2024, Salesforce, Inc.
490
545
  * All rights reserved.
491
546
  * SPDX-License-Identifier: MIT
492
547
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
493
548
  */
494
- const bStylesheetTokenDeclaration = esTemplate `
549
+ /*
550
+ * For the next available error code, reference (and update!) the value in ./index.ts
551
+ */
552
+ ({
553
+ code: 1001,
554
+ message: 'Unexpected compilation error: {0}',
555
+ level: DiagnosticLevel.Error,
556
+ url: '',
557
+ });
558
+ ({
559
+ INVALID_COMPAT_PROPERTY: {
560
+ code: 1013,
561
+ message: 'Expected a boolean for outputConfig.compat, received "{0}".',
562
+ level: DiagnosticLevel.Error,
563
+ url: '',
564
+ },
565
+ INVALID_ENV_ENTRY_VALUE: {
566
+ code: 1014,
567
+ message: 'Expected a string for outputConfig.env["{0}"], received "{1}".',
568
+ level: DiagnosticLevel.Error,
569
+ url: '',
570
+ },
571
+ INVALID_ENV_PROPERTY: {
572
+ code: 1015,
573
+ message: 'Expected an object for outputConfig.env, received "{0}".',
574
+ level: DiagnosticLevel.Error,
575
+ url: '',
576
+ },
577
+ INVALID_FILES_PROPERTY: {
578
+ code: 1016,
579
+ message: 'Expected an object with files to be compiled.',
580
+ level: DiagnosticLevel.Error,
581
+ url: '',
582
+ },
583
+ INVALID_NAME_PROPERTY: {
584
+ code: 1018,
585
+ message: 'Expected a string for name, received "{0}".',
586
+ level: DiagnosticLevel.Error,
587
+ url: '',
588
+ },
589
+ INVALID_NAMESPACE_PROPERTY: {
590
+ code: 1019,
591
+ message: 'Expected a string for namespace, received "{0}".',
592
+ level: DiagnosticLevel.Error,
593
+ url: '',
594
+ },
595
+ INVALID_SOURCEMAP_PROPERTY: {
596
+ code: 1021,
597
+ message: 'Expected a boolean value or \'inline\' for outputConfig.sourcemap, received "{0}".',
598
+ level: DiagnosticLevel.Error,
599
+ url: '',
600
+ },
601
+ MISSING_OPTIONS_OBJECT: {
602
+ code: 1023,
603
+ message: 'Expected options object, received "{0}".',
604
+ level: DiagnosticLevel.Error,
605
+ url: '',
606
+ },
607
+ UNEXPECTED_FILE_CONTENT: {
608
+ code: 1024,
609
+ message: 'Unexpected file content for "{0}". Expected a string, received "{1}".',
610
+ level: DiagnosticLevel.Error,
611
+ url: '',
612
+ },
613
+ UNKNOWN_ENV_ENTRY_KEY: {
614
+ code: 1025,
615
+ message: 'Unknown entry "{0}" in outputConfig.env.',
616
+ level: DiagnosticLevel.Error,
617
+ url: '',
618
+ },
619
+ });
620
+ ({
621
+ MODULE_RESOLUTION_ERROR: {
622
+ code: 1002,
623
+ message: 'Error in module resolution: {0}',
624
+ level: DiagnosticLevel.Warning,
625
+ url: '',
626
+ },
627
+ IMPORTEE_RESOLUTION_FAILED: {
628
+ code: 1010,
629
+ message: 'Failed to resolve entry for module "{0}".',
630
+ level: DiagnosticLevel.Error,
631
+ url: '',
632
+ },
633
+ IMPORTEE_RESOLUTION_FROM_IMPORTER_FAILED: {
634
+ code: 1011,
635
+ message: 'Failed to resolve import "{0}" from "{1}". Please add "{2}" file to the component folder.',
636
+ level: DiagnosticLevel.Error,
637
+ url: '',
638
+ },
639
+ NONEXISTENT_FILE: {
640
+ code: 1004,
641
+ message: 'No such file {0}',
642
+ level: DiagnosticLevel.Error,
643
+ url: '',
644
+ },
645
+ FOLDER_NAME_STARTS_WITH_CAPITAL_LETTER: {
646
+ code: 1116,
647
+ message: 'Illegal folder name "{0}". The folder name must start with a lowercase character: "{1}".',
648
+ level: DiagnosticLevel.Error,
649
+ url: '',
650
+ },
651
+ FOLDER_AND_FILE_NAME_CASE_MISMATCH: {
652
+ code: 1117,
653
+ message: 'Failed to resolve "{0}". The file name must case match the component folder name "{1}".',
654
+ level: DiagnosticLevel.Error,
655
+ url: '',
656
+ },
657
+ IMPORT_AND_FILE_NAME_CASE_MISMATCH: {
658
+ code: 1118,
659
+ message: 'Failed to resolve "{0}" from "{1}". Did you mean "{2}"?',
660
+ level: DiagnosticLevel.Error,
661
+ url: '',
662
+ },
663
+ RELATIVE_DYNAMIC_IMPORT: {
664
+ code: 1120,
665
+ message: 'Illegal usage of the dynamic import syntax with a relative path.',
666
+ level: DiagnosticLevel.Error,
667
+ url: '',
668
+ },
669
+ });
670
+ ({
671
+ CSS_TRANSFORMER_ERROR: {
672
+ code: 1009,
673
+ message: '{0}',
674
+ level: DiagnosticLevel.Error,
675
+ url: '',
676
+ },
677
+ CSS_IN_HTML_ERROR: {
678
+ code: 1026,
679
+ message: 'An error occurred parsing inline CSS. {0}',
680
+ level: DiagnosticLevel.Error,
681
+ url: '',
682
+ },
683
+ HTML_TRANSFORMER_ERROR: {
684
+ code: 1008,
685
+ message: '{0}',
686
+ level: DiagnosticLevel.Error,
687
+ url: '',
688
+ },
689
+ INVALID_ID: {
690
+ code: 1027,
691
+ message: 'Expect a string for id. Received {0}',
692
+ level: DiagnosticLevel.Error,
693
+ url: '',
694
+ },
695
+ INVALID_SOURCE: {
696
+ code: 1006,
697
+ message: 'Expect a string for source. Received {0}',
698
+ level: DiagnosticLevel.Error,
699
+ url: '',
700
+ },
701
+ JS_TRANSFORMER_ERROR: {
702
+ code: 1007,
703
+ message: '{0}',
704
+ level: DiagnosticLevel.Error,
705
+ url: '',
706
+ },
707
+ NO_AVAILABLE_TRANSFORMER: {
708
+ code: 1005,
709
+ message: 'No available transformer for "{0}"',
710
+ level: DiagnosticLevel.Error,
711
+ url: '',
712
+ },
713
+ JS_TRANSFORMER_DECORATOR_ERROR: {
714
+ code: 1198,
715
+ message: 'Decorators like @api, @track, and @wire are only supported in LightningElement classes. {0}',
716
+ level: DiagnosticLevel.Error,
717
+ url: '',
718
+ },
719
+ });
720
+
721
+ /*
722
+ * Copyright (c) 2024, Salesforce, Inc.
723
+ * All rights reserved.
724
+ * SPDX-License-Identifier: MIT
725
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
726
+ */
727
+ /*
728
+ * For the next available error code, reference (and update!) the value in ./index.ts
729
+ */
730
+ ({
731
+ INVALID_DYNAMIC_IMPORT_SOURCE_STRICT: {
732
+ code: 1121,
733
+ message: 'Invalid import. The argument "{0}" must be a stringLiteral for dynamic imports when strict mode is enabled.',
734
+ url: '',
735
+ level: DiagnosticLevel.Error,
736
+ },
737
+ });
738
+ ({
739
+ ADAPTER_SHOULD_BE_FIRST_PARAMETER: {
740
+ code: 1092,
741
+ message: '@wire expects an adapter as first parameter. @wire(adapter: WireAdapter, config?: any).',
742
+ level: DiagnosticLevel.Error,
743
+ url: '',
744
+ },
745
+ API_AND_TRACK_DECORATOR_CONFLICT: {
746
+ code: 1093,
747
+ message: '@api method or property cannot be used with @track',
748
+ level: DiagnosticLevel.Error,
749
+ url: '',
750
+ },
751
+ CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER: {
752
+ code: 1094,
753
+ message: '@wire expects a configuration object expression as second parameter.',
754
+ level: DiagnosticLevel.Error,
755
+ url: '',
756
+ },
757
+ CONFLICT_WITH_ANOTHER_DECORATOR: {
758
+ code: 1095,
759
+ message: '@wire method or property cannot be used with @{0}',
760
+ level: DiagnosticLevel.Error,
761
+ url: '',
762
+ },
763
+ DUPLICATE_API_PROPERTY: {
764
+ code: 1096,
765
+ message: 'Duplicate @api property "{0}".',
766
+ level: DiagnosticLevel.Error,
767
+ url: '',
768
+ },
769
+ FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER: {
770
+ code: 1097,
771
+ message: '@wire expects a function identifier as first parameter.',
772
+ level: DiagnosticLevel.Error,
773
+ url: '',
774
+ },
775
+ IMPORTED_FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER: {
776
+ code: 1098,
777
+ message: '@wire expects a function identifier to be imported as first parameter.',
778
+ level: DiagnosticLevel.Error,
779
+ url: '',
780
+ },
781
+ INVALID_BOOLEAN_PUBLIC_PROPERTY: {
782
+ code: 1099,
783
+ message: 'Boolean public property must default to false.',
784
+ level: DiagnosticLevel.Error,
785
+ url: '',
786
+ },
787
+ INVALID_DECORATOR: {
788
+ code: 1100,
789
+ message: 'Invalid decorator usage. Supported decorators ({0}) should be imported from "{1}"',
790
+ level: DiagnosticLevel.Error,
791
+ url: '',
792
+ },
793
+ INVALID_DECORATOR_TYPE: {
794
+ code: 1101,
795
+ message: 'Invalid property of field type',
796
+ level: DiagnosticLevel.Error,
797
+ url: '',
798
+ },
799
+ INVALID_DECORATOR_WITH_NAME: {
800
+ code: 1102,
801
+ message: 'Invalid \'{0}\' decorator usage. Supported decorators ({1}) should be imported from "{2}"',
802
+ level: DiagnosticLevel.Error,
803
+ url: '',
804
+ },
805
+ IS_NOT_CLASS_PROPERTY_OR_CLASS_METHOD: {
806
+ code: 1103,
807
+ message: '"@{0}" can only be applied on class properties',
808
+ level: DiagnosticLevel.Error,
809
+ url: '',
810
+ },
811
+ IS_NOT_DECORATOR: {
812
+ code: 1104,
813
+ message: '"{0}" can only be used as a class decorator',
814
+ level: DiagnosticLevel.Error,
815
+ url: '',
816
+ },
817
+ ONE_WIRE_DECORATOR_ALLOWED: {
818
+ code: 1105,
819
+ message: 'Method or property can only have 1 @wire decorator',
820
+ level: DiagnosticLevel.Error,
821
+ url: '',
822
+ },
823
+ PROPERTY_CANNOT_BE_COMPUTED: {
824
+ code: 1106,
825
+ message: '@api cannot be applied to a computed property, getter, setter or method.',
826
+ level: DiagnosticLevel.Error,
827
+ url: '',
828
+ },
829
+ PROPERTY_NAME_CANNOT_START_WITH_DATA: {
830
+ code: 1107,
831
+ message: 'Invalid property name "{0}". Properties starting with "data" are reserved attributes.',
832
+ level: DiagnosticLevel.Error,
833
+ url: '',
834
+ },
835
+ PROPERTY_NAME_CANNOT_START_WITH_ON: {
836
+ code: 1108,
837
+ message: 'Invalid property name "{0}". Properties starting with "on" are reserved for event handlers.',
838
+ level: DiagnosticLevel.Error,
839
+ url: '',
840
+ },
841
+ PROPERTY_NAME_IS_AMBIGUOUS: {
842
+ code: 1109,
843
+ message: 'Ambiguous attribute name "{0}". "{0}" will never be called from template because its corresponding property is camel cased. Consider renaming to "{1}".',
844
+ level: DiagnosticLevel.Error,
845
+ url: '',
846
+ },
847
+ PROPERTY_NAME_IS_RESERVED: {
848
+ code: 1110,
849
+ message: 'Invalid property name "{0}". "{0}" is a reserved attribute.',
850
+ level: DiagnosticLevel.Error,
851
+ url: '',
852
+ },
853
+ PROPERTY_NAME_PART_IS_RESERVED: {
854
+ code: 1111,
855
+ message: 'Invalid property name "{0}". "part" is a future reserved attribute for web components.',
856
+ level: DiagnosticLevel.Error,
857
+ url: '',
858
+ },
859
+ SINGLE_DECORATOR_ON_SETTER_GETTER_PAIR: {
860
+ code: 1112,
861
+ message: '@api get {0} and @api set {0} detected in class declaration. Only one of the two needs to be decorated with @api.',
862
+ level: DiagnosticLevel.Error,
863
+ url: '',
864
+ },
865
+ TRACK_ONLY_ALLOWED_ON_CLASS_PROPERTIES: {
866
+ code: 1113,
867
+ message: '@track decorator can only be applied to class properties.',
868
+ level: DiagnosticLevel.Error,
869
+ url: '',
870
+ },
871
+ WIRE_ADAPTER_SHOULD_BE_IMPORTED: {
872
+ code: 1119,
873
+ message: 'Failed to resolve @wire adapter "{0}". Ensure it is imported.',
874
+ level: DiagnosticLevel.Error,
875
+ url: '',
876
+ },
877
+ FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS: {
878
+ code: 1131,
879
+ message: '@wire identifier cannot contain computed properties',
880
+ level: DiagnosticLevel.Error,
881
+ url: '',
882
+ },
883
+ FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS: {
884
+ code: 1132,
885
+ message: '@wire identifier cannot contain nested member expressions',
886
+ level: DiagnosticLevel.Error,
887
+ url: '',
888
+ },
889
+ COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL: {
890
+ code: 1199,
891
+ message: 'Cannot use a template literal as a computed property key. Instead, use a string or extract the value to a constant.',
892
+ level: DiagnosticLevel.Error,
893
+ url: '',
894
+ },
895
+ COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL: {
896
+ code: 1200,
897
+ message: 'Computed property in @wire config must be a constant or primitive literal.',
898
+ level: DiagnosticLevel.Error,
899
+ url: '',
900
+ },
901
+ });
902
+
903
+ /*
904
+ * Copyright (c) 2024, Salesforce, Inc.
905
+ * All rights reserved.
906
+ * SPDX-License-Identifier: MIT
907
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
908
+ */
909
+ /*
910
+ * For the next available error code, reference (and update!) the value in ./index.ts
911
+ */
912
+ ({
913
+ INVALID_TEMPLATE: {
914
+ code: 1003,
915
+ message: 'Invalid template',
916
+ level: DiagnosticLevel.Error,
917
+ url: '',
918
+ },
919
+ OPTIONS_MUST_BE_OBJECT: {
920
+ code: 1028,
921
+ message: 'Compiler options must be an object',
922
+ level: DiagnosticLevel.Error,
923
+ url: '',
924
+ },
925
+ UNKNOWN_IF_MODIFIER: {
926
+ code: 1029,
927
+ message: 'Unknown if modifier {0}',
928
+ level: DiagnosticLevel.Error,
929
+ url: '',
930
+ },
931
+ UNKNOWN_OPTION_PROPERTY: {
932
+ code: 1030,
933
+ message: 'Unknown option property {0}',
934
+ level: DiagnosticLevel.Error,
935
+ url: '',
936
+ },
937
+ DUPLICATE_ELEMENT_ENTRY: {
938
+ code: 1150,
939
+ message: 'customRendererConfig contains duplicate entry for {0} element tag',
940
+ level: DiagnosticLevel.Error,
941
+ url: '',
942
+ },
943
+ CUSTOM_ELEMENT_TAG_DISALLOWED: {
944
+ code: 1151,
945
+ message: 'customRendererConfig should not contain a custom element tag, but found {0}',
946
+ level: DiagnosticLevel.Error,
947
+ url: '',
948
+ },
949
+ });
950
+ ({
951
+ AMBIGUOUS_ATTRIBUTE_VALUE: {
952
+ code: 1034,
953
+ message: 'Ambiguous attribute value {0}. ' +
954
+ 'If you want to make it a valid identifier you should remove the surrounding quotes {1}. ' +
955
+ 'If you want to make it a string you should escape it {2}.',
956
+ level: DiagnosticLevel.Error,
957
+ url: '',
958
+ },
959
+ AMBIGUOUS_ATTRIBUTE_VALUE_STRING: {
960
+ code: 1035,
961
+ message: 'Ambiguous attribute value {0}. If you want to make it a string you should escape it {1}',
962
+ level: DiagnosticLevel.Error,
963
+ url: '',
964
+ },
965
+ BOOLEAN_ATTRIBUTE_FALSE: {
966
+ code: 1036,
967
+ message: 'To not set a boolean attribute, try <{0}> instead of <{0} {1}="{2}">. ' +
968
+ 'To represent a false value, the attribute has to be omitted altogether.',
969
+ level: DiagnosticLevel.Error,
970
+ url: '',
971
+ },
972
+ BOOLEAN_ATTRIBUTE_TRUE: {
973
+ code: 1037,
974
+ message: 'To set a boolean attributes, try <{0} {1}> instead of <{0} {1}="{2}">. ' +
975
+ 'If the attribute is present, its value must either be the empty string ' +
976
+ "or a value that is an ASCII case -insensitive match for the attribute's canonical name " +
977
+ 'with no leading or trailing whitespace.',
978
+ level: DiagnosticLevel.Error,
979
+ url: '',
980
+ },
981
+ COMPUTED_PROPERTY_ACCESS_NOT_ALLOWED: {
982
+ code: 1038,
983
+ message: "Template expression doesn't allow computed property access",
984
+ level: DiagnosticLevel.Error,
985
+ url: '',
986
+ },
987
+ DIRECTIVE_SHOULD_BE_EXPRESSION: {
988
+ code: 1039,
989
+ message: '{0} directive is expected to be an expression',
990
+ level: DiagnosticLevel.Error,
991
+ url: '',
992
+ },
993
+ INVALID_ID_ATTRIBUTE: {
994
+ code: 1040,
995
+ message: 'Invalid id value "{0}". Id values must not contain any whitespace.',
996
+ level: DiagnosticLevel.Error,
997
+ url: '',
998
+ },
999
+ INVALID_STATIC_ID_IN_ITERATION: {
1000
+ code: 1041,
1001
+ message: 'Static id values are not allowed in iterators. Id values must be unique within a template and must therefore be computed with an expression.',
1002
+ level: DiagnosticLevel.Warning,
1003
+ url: '',
1004
+ },
1005
+ DUPLICATE_ID_FOUND: {
1006
+ code: 1042,
1007
+ message: 'Duplicate id value "{0}" detected. Id values must be unique within a template.',
1008
+ level: DiagnosticLevel.Error,
1009
+ url: '',
1010
+ },
1011
+ EVENT_HANDLER_SHOULD_BE_EXPRESSION: {
1012
+ code: 1043,
1013
+ message: 'Event handler should be an expression',
1014
+ level: DiagnosticLevel.Error,
1015
+ url: '',
1016
+ },
1017
+ FOR_EACH_AND_FOR_ITEM_DIRECTIVES_SHOULD_BE_TOGETHER: {
1018
+ code: 1044,
1019
+ message: 'for:each and for:item directives should be associated together.',
1020
+ level: DiagnosticLevel.Error,
1021
+ url: '',
1022
+ },
1023
+ FOR_EACH_DIRECTIVE_SHOULD_BE_EXPRESSION: {
1024
+ code: 1045,
1025
+ message: 'for:each directive is expected to be a expression.',
1026
+ level: DiagnosticLevel.Error,
1027
+ url: '',
1028
+ },
1029
+ FOR_INDEX_DIRECTIVE_SHOULD_BE_STRING: {
1030
+ code: 1046,
1031
+ message: 'for:index directive is expected to be a string.',
1032
+ level: DiagnosticLevel.Error,
1033
+ url: '',
1034
+ },
1035
+ FOR_ITEM_DIRECTIVE_SHOULD_BE_STRING: {
1036
+ code: 1047,
1037
+ message: 'for:item directive is expected to be a string.',
1038
+ level: DiagnosticLevel.Error,
1039
+ url: '',
1040
+ },
1041
+ FORBIDDEN_IFRAME_SRCDOC_ATTRIBUTE: {
1042
+ code: 1048,
1043
+ message: 'srcdoc attribute is disallowed on <iframe> for security reasons',
1044
+ level: DiagnosticLevel.Error,
1045
+ url: '',
1046
+ },
1047
+ FORBIDDEN_SVG_NAMESPACE_IN_TEMPLATE: {
1048
+ code: 1049,
1049
+ message: "Forbidden svg namespace tag found in template: '<{0}>' tag is not allowed within <svg>",
1050
+ level: DiagnosticLevel.Error,
1051
+ url: '',
1052
+ },
1053
+ FORBIDDEN_MATHML_NAMESPACE_IN_TEMPLATE: {
1054
+ code: 1050,
1055
+ message: "Forbidden MathML namespace tag found in template: '<{0}>' tag is not allowed within <math>",
1056
+ level: DiagnosticLevel.Error,
1057
+ url: '',
1058
+ },
1059
+ FORBIDDEN_TAG_ON_TEMPLATE: {
1060
+ code: 1051,
1061
+ message: "Forbidden tag found in template: '<{0}>' tag is not allowed.",
1062
+ level: DiagnosticLevel.Error,
1063
+ url: '',
1064
+ },
1065
+ GENERIC_PARSING_ERROR: {
1066
+ code: 1052,
1067
+ message: 'Error parsing attribute: {0}',
1068
+ level: DiagnosticLevel.Error,
1069
+ url: '',
1070
+ },
1071
+ IDENTIFIER_PARSING_ERROR: {
1072
+ code: 1053,
1073
+ message: 'Error parsing identifier: {0}',
1074
+ level: DiagnosticLevel.Error,
1075
+ url: '',
1076
+ },
1077
+ IF_DIRECTIVE_SHOULD_BE_EXPRESSION: {
1078
+ code: 1054,
1079
+ message: 'If directive should be an expression',
1080
+ level: DiagnosticLevel.Error,
1081
+ url: '',
1082
+ },
1083
+ INVALID_ATTRIBUTE_CASE: {
1084
+ code: 1055,
1085
+ message: '{0} is not valid attribute for {1}. All attributes name should be all lowercase.',
1086
+ level: DiagnosticLevel.Error,
1087
+ url: '',
1088
+ },
1089
+ INVALID_EVENT_NAME: {
1090
+ code: 1056,
1091
+ message: 'Invalid event type "{0}". Event type must begin with a lower-case alphabetic character and contain only lower-case alphabetic characters, underscores, and numeric characters',
1092
+ level: DiagnosticLevel.Error,
1093
+ url: '',
1094
+ },
1095
+ INVALID_HTML_ATTRIBUTE: {
1096
+ code: 1057,
1097
+ message: '{0} is not valid attribute for {1}. For more information refer to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/{1}',
1098
+ level: DiagnosticLevel.Warning,
1099
+ url: '',
1100
+ },
1101
+ INVALID_HTML_SYNTAX: {
1102
+ code: 1058,
1103
+ message: 'Invalid HTML syntax: {0}. For more information, ' +
1104
+ 'please visit https://html.spec.whatwg.org/multipage/parsing.html#parse-error-{0}',
1105
+ level: DiagnosticLevel.Error,
1106
+ url: '',
1107
+ },
1108
+ INVALID_IDENTIFIER: {
1109
+ code: 1059,
1110
+ message: '{0} is not a valid identifier',
1111
+ level: DiagnosticLevel.Error,
1112
+ url: '',
1113
+ },
1114
+ INVALID_NODE: {
1115
+ code: 1060,
1116
+ message: "Template expression doesn't allow {0}",
1117
+ level: DiagnosticLevel.Error,
1118
+ url: '',
1119
+ },
1120
+ INVALID_TABINDEX_ATTRIBUTE: {
1121
+ code: 1061,
1122
+ message: 'The attribute "tabindex" can only be set to "0" or "-1".',
1123
+ level: DiagnosticLevel.Error,
1124
+ url: '',
1125
+ },
1126
+ DEPRECATED_IS_ATTRIBUTE_CANNOT_BE_EXPRESSION: {
1127
+ code: 1062,
1128
+ message: '"is" attribute value can\'t be an expression',
1129
+ level: DiagnosticLevel.Error,
1130
+ url: '',
1131
+ },
1132
+ IS_ATTRIBUTE_NOT_SUPPORTED: {
1133
+ code: 1063,
1134
+ message: '"is" attribute is disallowed',
1135
+ level: DiagnosticLevel.Error,
1136
+ url: '',
1137
+ },
1138
+ KEY_ATTRIBUTE_SHOULD_BE_EXPRESSION: {
1139
+ code: 1064,
1140
+ message: 'Key attribute value should be an expression',
1141
+ level: DiagnosticLevel.Error,
1142
+ url: '',
1143
+ },
1144
+ KEY_SHOULDNT_REFERENCE_FOR_EACH_INDEX: {
1145
+ code: 1065,
1146
+ message: 'Invalid key value for element <{0}>. Key cannot reference for:each index {1}',
1147
+ level: DiagnosticLevel.Error,
1148
+ url: '',
1149
+ },
1150
+ KEY_SHOULDNT_REFERENCE_ITERATOR_INDEX: {
1151
+ code: 1066,
1152
+ message: 'Invalid key value for element <{0}>. Key cannot reference iterator index',
1153
+ level: DiagnosticLevel.Error,
1154
+ url: '',
1155
+ },
1156
+ MISSING_KEY_IN_ITERATOR: {
1157
+ code: 1071,
1158
+ message: 'Missing key for element <{0}> inside of iterator. Elements within iterators must have a unique, computed key value.',
1159
+ level: DiagnosticLevel.Error,
1160
+ url: '',
1161
+ },
1162
+ MISSING_ROOT_TEMPLATE_TAG: {
1163
+ code: 1072,
1164
+ message: 'Missing root template tag',
1165
+ level: DiagnosticLevel.Error,
1166
+ url: '',
1167
+ },
1168
+ MODIFYING_ITERATORS_NOT_ALLOWED: {
1169
+ code: 1073,
1170
+ message: "Template expression doesn't allow to modify iterators",
1171
+ level: DiagnosticLevel.Error,
1172
+ url: '',
1173
+ },
1174
+ MULTIPLE_EXPRESSIONS: {
1175
+ code: 1074,
1176
+ message: 'Multiple expressions found',
1177
+ level: DiagnosticLevel.Error,
1178
+ url: '',
1179
+ },
1180
+ MULTIPLE_ROOTS_FOUND: {
1181
+ code: 1075,
1182
+ message: 'Multiple roots found',
1183
+ level: DiagnosticLevel.Error,
1184
+ url: '',
1185
+ },
1186
+ NAME_ON_SLOT_CANNOT_BE_EXPRESSION: {
1187
+ code: 1076,
1188
+ message: "Name attribute on slot tag can't be an expression.",
1189
+ level: DiagnosticLevel.Error,
1190
+ url: '',
1191
+ },
1192
+ NO_DIRECTIVE_FOUND_ON_TEMPLATE: {
1193
+ code: 1077,
1194
+ message: 'Invalid template tag. A directive is expected to be associated with the template tag.',
1195
+ level: DiagnosticLevel.Error,
1196
+ url: '',
1197
+ },
1198
+ NO_MATCHING_CLOSING_TAGS: {
1199
+ code: 1078,
1200
+ message: '<{0}> has no matching closing tag.',
1201
+ level: DiagnosticLevel.Error,
1202
+ url: '',
1203
+ },
1204
+ ROOT_TAG_SHOULD_BE_TEMPLATE: {
1205
+ code: 1079,
1206
+ message: 'Expected root tag to be template, found {0}',
1207
+ level: DiagnosticLevel.Error,
1208
+ url: '',
1209
+ },
1210
+ ROOT_TEMPLATE_HAS_UNKNOWN_ATTRIBUTES: {
1211
+ code: 1080,
1212
+ message: 'Root template has unknown or disallowed attributes: {0}',
1213
+ level: DiagnosticLevel.Error,
1214
+ url: '',
1215
+ },
1216
+ // TODO [#3100]: Update message to point to external documentation once available.
1217
+ SLOT_TAG_CANNOT_HAVE_DIRECTIVES: {
1218
+ code: 1082,
1219
+ message: "<slot> tag can't be associated with {0} template directives.",
1220
+ level: DiagnosticLevel.Error,
1221
+ url: '',
1222
+ },
1223
+ TEMPLATE_EXPRESSION_PARSING_ERROR: {
1224
+ code: 1083,
1225
+ message: 'Error parsing template expression: {0}',
1226
+ level: DiagnosticLevel.Error,
1227
+ url: '',
1228
+ },
1229
+ UNEXPECTED_IF_MODIFIER: {
1230
+ code: 1084,
1231
+ message: 'Unexpected if modifier {0}',
1232
+ level: DiagnosticLevel.Error,
1233
+ url: '',
1234
+ },
1235
+ LWC_DOM_INVALID_VALUE: {
1236
+ code: 1085,
1237
+ message: 'Invalid value for "lwc:dom". \'lwc:dom\' can only be set to {0}',
1238
+ level: DiagnosticLevel.Error,
1239
+ url: '',
1240
+ },
1241
+ LWC_DOM_INVALID_CONTENTS: {
1242
+ code: 1086,
1243
+ message: 'Invalid contents for element with "lwc:dom". Element must be empty',
1244
+ level: DiagnosticLevel.Error,
1245
+ url: '',
1246
+ },
1247
+ LWC_DOM_INVALID_CUSTOM_ELEMENT: {
1248
+ code: 1087,
1249
+ message: 'Invalid directive "lwc:dom" on element {0}. "lwc:dom" cannot be added to a custom element',
1250
+ level: DiagnosticLevel.Error,
1251
+ url: '',
1252
+ },
1253
+ LWC_DOM_INVALID_SLOT_ELEMENT: {
1254
+ code: 1088,
1255
+ message: 'Invalid directive "lwc:dom" on <slot>.. "lwc:dom" cannot be added to a <slot>',
1256
+ level: DiagnosticLevel.Error,
1257
+ url: '',
1258
+ },
1259
+ STYLE_TAG_NOT_ALLOWED_IN_TEMPLATE: {
1260
+ code: 1122,
1261
+ message: "The <style> element is disallowed inside the template. Please add css rules into '.css' file of your component bundle.",
1262
+ level: DiagnosticLevel.Error,
1263
+ url: '',
1264
+ },
1265
+ UNKNOWN_HTML_TAG_IN_TEMPLATE: {
1266
+ code: 1123,
1267
+ message: "Unknown html tag '<{0}>'. For more information refer to https://developer.mozilla.org/en-US/docs/Web/HTML/Element and https://developer.mozilla.org/en-US/docs/Web/SVG/Element",
1268
+ level: DiagnosticLevel.Warning,
1269
+ url: '',
1270
+ },
1271
+ ATTRIBUTE_NAME_STARTS_WITH_INVALID_CHARACTER: {
1272
+ code: 1124,
1273
+ message: '{0} is not valid attribute for {1}. Attribute name must start with an underscore, dollar sign, or an optional hyphen character followed by an alphabetic character.',
1274
+ level: DiagnosticLevel.Error,
1275
+ url: '',
1276
+ },
1277
+ ATTRIBUTE_NAME_MUST_END_WITH_ALPHA_NUMERIC_CHARACTER: {
1278
+ code: 1125,
1279
+ message: '{0} is not valid attribute for {1}. Attribute name must end with alpha-numeric character.',
1280
+ level: DiagnosticLevel.Error,
1281
+ url: '',
1282
+ },
1283
+ UNKNOWN_LWC_DIRECTIVE: {
1284
+ code: 1127,
1285
+ message: 'Invalid directive "{0}" on element {1}.',
1286
+ level: DiagnosticLevel.Error,
1287
+ url: '',
1288
+ },
1289
+ INVALID_OPTS_LWC_DYNAMIC: {
1290
+ code: 1128,
1291
+ message: 'Invalid lwc:dynamic usage. The LWC dynamic directive must be enabled in order to use this feature.',
1292
+ level: DiagnosticLevel.Error,
1293
+ url: '',
1294
+ },
1295
+ INVALID_LWC_DYNAMIC_ON_NATIVE_ELEMENT: {
1296
+ code: 1129,
1297
+ message: 'Invalid lwc:dynamic usage on element "{0}". This directive can only be used in a custom element.',
1298
+ level: DiagnosticLevel.Error,
1299
+ url: '',
1300
+ },
1301
+ INVALID_LWC_DYNAMIC_LITERAL_PROP: {
1302
+ code: 1130,
1303
+ message: 'Invalid lwc:dynamic usage on element "{0}". The directive binding must be an expression.',
1304
+ level: DiagnosticLevel.Error,
1305
+ url: '',
1306
+ },
1307
+ LWC_RENDER_MODE_INVALID_VALUE: {
1308
+ code: 1133,
1309
+ message: 'Invalid value for "lwc:render-mode". \'lwc:render-mode\' can only be set to "shadow", or "light"',
1310
+ level: DiagnosticLevel.Error,
1311
+ url: '',
1312
+ },
1313
+ LWC_LIGHT_SLOT_INVALID_ATTRIBUTES: {
1314
+ code: 1134,
1315
+ message: "Invalid attribute(s) '{0}' on slot. Slots in Light DOM templates (which have 'lwc:render-mode' directive) can only have [{1}] attributes",
1316
+ level: DiagnosticLevel.Error,
1317
+ url: '',
1318
+ },
1319
+ LWC_DOM_INVALID_IN_LIGHT_DOM: {
1320
+ code: 1135,
1321
+ message: "Invalid directive 'lwc:dom' on element {0}. 'lwc:dom' is not necessary in Light DOM components.",
1322
+ level: DiagnosticLevel.Error,
1323
+ url: '',
1324
+ },
1325
+ INVALID_FOR_EACH_WITH_ITERATOR: {
1326
+ code: 1136,
1327
+ message: "Invalid usage for 'for:each' and '{0}' directives on the same element.",
1328
+ level: DiagnosticLevel.Error,
1329
+ url: '',
1330
+ },
1331
+ NO_DUPLICATE_SLOTS: {
1332
+ code: 1137,
1333
+ message: 'Invalid duplicate slot ({0}).',
1334
+ level: DiagnosticLevel.Warning,
1335
+ url: '',
1336
+ },
1337
+ NO_SLOTS_IN_ITERATOR: {
1338
+ code: 1138,
1339
+ message: 'Invalid slot ({0}). A slot cannot appear inside of an iterator.',
1340
+ level: DiagnosticLevel.Warning,
1341
+ url: '',
1342
+ },
1343
+ LWC_LIGHT_SLOT_INVALID_EVENT_LISTENER: {
1344
+ code: 1139,
1345
+ message: "Invalid event listener '{0}' on slot. Slots in Light DOM templates cannot have event listeners.",
1346
+ level: DiagnosticLevel.Error,
1347
+ url: '',
1348
+ },
1349
+ LWC_INNER_HTML_INVALID_CUSTOM_ELEMENT: {
1350
+ code: 1140,
1351
+ message: 'Invalid lwc:inner-html usage on element "{0}". The directive can\'t be used on a custom element or special LWC managed elements denoted with lwc:*.',
1352
+ level: DiagnosticLevel.Error,
1353
+ url: '',
1354
+ },
1355
+ LWC_INNER_HTML_INVALID_ELEMENT: {
1356
+ code: 1141,
1357
+ message: 'Invalid lwc:inner-html usage on element "{0}". The directive can\'t be used on a slot or a template element.',
1358
+ level: DiagnosticLevel.Error,
1359
+ url: '',
1360
+ },
1361
+ LWC_INNER_HTML_INVALID_CONTENTS: {
1362
+ code: 1142,
1363
+ message: 'Invalid lwc:inner-html usage on element "{0}". The directive can\'t be used on an element with content.',
1364
+ level: DiagnosticLevel.Error,
1365
+ url: '',
1366
+ },
1367
+ LWC_INNER_HTML_INVALID_VALUE: {
1368
+ code: 1143,
1369
+ message: 'Invalid lwc:inner-html usage on element "{0}". The directive binding can only be an expression or a string.',
1370
+ level: DiagnosticLevel.Error,
1371
+ url: '',
1372
+ },
1373
+ INVALID_HTML_RECOVERY: {
1374
+ code: 1144,
1375
+ message: 'Invalid HTML detected, "<{0}>" was automatically inserted within "<{1}>"; the compiled template may not match the template source.',
1376
+ level: DiagnosticLevel.Warning,
1377
+ url: '',
1378
+ },
1379
+ INVALID_TEMPLATE_ATTRIBUTE: {
1380
+ code: 1145,
1381
+ message: 'Invalid attributes detected on template. The following attributes are not supported on template tags in LWC: {0}. For more information, ' +
1382
+ 'please visit https://sfdc.co/template-directives',
1383
+ level: DiagnosticLevel.Warning,
1384
+ url: '',
1385
+ },
1386
+ PRESERVE_COMMENTS_MUST_BE_BOOLEAN: {
1387
+ code: 1146,
1388
+ message: 'lwc:preserve-comments must be a boolean attribute.',
1389
+ level: DiagnosticLevel.Error,
1390
+ url: '',
1391
+ },
1392
+ DUPLICATE_ATTR_PROP_TRANSFORM: {
1393
+ code: 1147,
1394
+ message: 'Found multiple HTML attributes mapping to the same JavaScript property. "{0}" and "{1}" both map to "{2}".',
1395
+ level: DiagnosticLevel.Warning,
1396
+ url: '',
1397
+ },
1398
+ INVALID_HTML_SYNTAX_WARNING: {
1399
+ code: 1148,
1400
+ message: 'Invalid HTML syntax: {0}. This will not be supported in future versions of LWC. For more information, ' +
1401
+ 'please visit https://html.spec.whatwg.org/multipage/parsing.html#parse-error-{0}',
1402
+ level: DiagnosticLevel.Warning,
1403
+ url: '',
1404
+ },
1405
+ KEY_SHOULD_BE_IN_ITERATION: {
1406
+ code: 1149,
1407
+ message: 'Invalid key attribute on element <{0}>. The key attribute should be applied to an element with for:each or iterator:*, or to a direct child of a <template> element with for:each or iterator:*. This key will be ignored, and may throw an error in future versions of LWC.',
1408
+ level: DiagnosticLevel.Warning,
1409
+ url: '',
1410
+ },
1411
+ INVALID_TEMPLATE_WARNING: {
1412
+ code: 1153,
1413
+ message: 'Non-root template elements must contain valid LWC template directive attributes. Otherwise, the template and its children will be ignored. ' +
1414
+ 'For more information please visit https://sfdc.co/template-directives',
1415
+ level: DiagnosticLevel.Warning,
1416
+ url: '',
1417
+ },
1418
+ INVALID_LWC_SPREAD_LITERAL_PROP: {
1419
+ code: 1155,
1420
+ message: 'Invalid lwc:spread usage on element "{0}". The directive binding must be an expression.',
1421
+ level: DiagnosticLevel.Error,
1422
+ url: '',
1423
+ },
1424
+ LWC_REF_INVALID_ELEMENT: {
1425
+ code: 1156,
1426
+ message: 'Invalid lwc:ref usage on element "{0}". The directive can\'t be used on a slot or a template element.',
1427
+ level: DiagnosticLevel.Error,
1428
+ url: '',
1429
+ },
1430
+ LWC_REF_INVALID_VALUE: {
1431
+ code: 1157,
1432
+ message: 'Invalid lwc:ref usage on element "{0}". The directive binding must be a non-empty string.',
1433
+ level: DiagnosticLevel.Error,
1434
+ url: '',
1435
+ },
1436
+ LWC_REF_INVALID_LOCATION_INSIDE_ITERATION: {
1437
+ code: 1158,
1438
+ message: 'Invalid lwc:ref usage on element "{0}". lwc:ref cannot be used inside for:each or an iterator.',
1439
+ level: DiagnosticLevel.Error,
1440
+ url: '',
1441
+ },
1442
+ IF_BLOCK_DIRECTIVE_SHOULD_BE_EXPRESSION: {
1443
+ code: 1159,
1444
+ message: 'lwc:if directive value should be an expression',
1445
+ level: DiagnosticLevel.Error,
1446
+ url: '',
1447
+ },
1448
+ ELSEIF_BLOCK_DIRECTIVE_SHOULD_BE_EXPRESSION: {
1449
+ code: 1160,
1450
+ message: 'lwc:elseif directive value should be an expression',
1451
+ level: DiagnosticLevel.Error,
1452
+ url: '',
1453
+ },
1454
+ ELSE_BLOCK_DIRECTIVE_CANNOT_HAVE_VALUE: {
1455
+ code: 1161,
1456
+ message: 'lwc:else directive cannot have a value',
1457
+ level: DiagnosticLevel.Error,
1458
+ url: '',
1459
+ },
1460
+ INVALID_IF_BLOCK_DIRECTIVE_WITH_CONDITIONAL: {
1461
+ code: 1162,
1462
+ message: "Invalid usage of 'lwc:if' and '{0}' directives on the same element.",
1463
+ level: DiagnosticLevel.Error,
1464
+ url: '',
1465
+ },
1466
+ INVALID_ELSEIF_BLOCK_DIRECTIVE_WITH_CONDITIONAL: {
1467
+ code: 1163,
1468
+ message: "Invalid usage of 'lwc:elseif' and '{0}' directives on the same element.",
1469
+ level: DiagnosticLevel.Error,
1470
+ url: '',
1471
+ },
1472
+ INVALID_ELSE_BLOCK_DIRECTIVE_WITH_CONDITIONAL: {
1473
+ code: 1164,
1474
+ message: "Invalid usage of 'lwc:else' and '{0}' directives on the same element.",
1475
+ level: DiagnosticLevel.Error,
1476
+ url: '',
1477
+ },
1478
+ LWC_IF_SCOPE_NOT_FOUND: {
1479
+ code: 1165,
1480
+ message: "'{0}' directive must be used immediately after an element with 'lwc:if' or 'lwc:elseif'. No such element found.",
1481
+ level: DiagnosticLevel.Error,
1482
+ url: '',
1483
+ },
1484
+ LWC_IF_CANNOT_BE_USED_WITH_IF_DIRECTIVE: {
1485
+ code: 1166,
1486
+ message: "'{0}' directive cannot be used with 'lwc:if', 'lwc:elseif', or 'lwc:else directives on the same element.",
1487
+ level: DiagnosticLevel.Error,
1488
+ url: '',
1489
+ },
1490
+ SCOPED_SLOT_BIND_IN_LIGHT_DOM_ONLY: {
1491
+ code: 1169,
1492
+ message: 'Invalid lwc:slot-bind usage on <slot> element. Scoped slots usage is allowed in Light DOM templates only.',
1493
+ level: DiagnosticLevel.Error,
1494
+ url: '',
1495
+ },
1496
+ INVALID_LWC_SLOT_BIND_LITERAL_PROP: {
1497
+ code: 1170,
1498
+ message: 'Invalid lwc:slot-bind usage on element {0}. The directive binding must be an expression.',
1499
+ level: DiagnosticLevel.Error,
1500
+ url: '',
1501
+ },
1502
+ INVALID_LWC_SLOT_BIND_NON_SLOT_ELEMENT: {
1503
+ code: 1171,
1504
+ message: 'Invalid lwc:slot-bind usage on element {0}. The directive can be used on a <slot> element only.',
1505
+ level: DiagnosticLevel.Error,
1506
+ url: '',
1507
+ },
1508
+ NO_DUPLICATE_SCOPED_SLOT: {
1509
+ code: 1172,
1510
+ message: 'Invalid duplicate scoped slots ({0})',
1511
+ level: DiagnosticLevel.Error,
1512
+ url: '',
1513
+ },
1514
+ NO_MIXED_SLOT_TYPES: {
1515
+ code: 1173,
1516
+ message: 'Mixing slot types disallowed for same ({0}) slot.',
1517
+ level: DiagnosticLevel.Error,
1518
+ url: '',
1519
+ },
1520
+ SLOT_DATA_VALUE_SHOULD_BE_STRING: {
1521
+ code: 1174,
1522
+ message: 'lwc:slot-data attribute value is expected to be a string.',
1523
+ level: DiagnosticLevel.Error,
1524
+ url: '',
1525
+ },
1526
+ SCOPED_SLOT_DATA_ON_TEMPLATE_ONLY: {
1527
+ code: 1176,
1528
+ message: 'lwc:slot-data directive can be used on <template> elements only.',
1529
+ level: DiagnosticLevel.Error,
1530
+ url: '',
1531
+ },
1532
+ NON_ELEMENT_SCOPED_SLOT_CONTENT: {
1533
+ code: 1177,
1534
+ message: '<template> tag with lwc:slot-data directive cannot contain a comment or text node as a direct child.',
1535
+ level: DiagnosticLevel.Error,
1536
+ url: '',
1537
+ },
1538
+ INVALID_PARENT_OF_LWC_SLOT_DATA: {
1539
+ code: 1178,
1540
+ message: '<template> tag with lwc:slot-data directive must be the direct child of a custom element.',
1541
+ level: DiagnosticLevel.Error,
1542
+ url: '',
1543
+ },
1544
+ SCOPED_SLOTDATA_CANNOT_BE_COMBINED_WITH_OTHER_DIRECTIVE: {
1545
+ code: 1179,
1546
+ message: 'lwc:slot-data directive cannot be combined with other directives on the same <template> tag.',
1547
+ level: DiagnosticLevel.Error,
1548
+ url: '',
1549
+ },
1550
+ INVALID_LWC_EXTERNAL_ON_NON_CUSTOM_ELEMENT: {
1551
+ code: 1180,
1552
+ message: 'Invalid lwc:external directive usage: {0}. This directive can only be used on custom elements.',
1553
+ level: DiagnosticLevel.Error,
1554
+ url: '',
1555
+ },
1556
+ INVALID_LWC_EXTERNAL_VALUE: {
1557
+ code: 1181,
1558
+ message: 'Invalid lwc:external directive usage: {0}. This directive is a boolean attribute and should not have a value.',
1559
+ level: DiagnosticLevel.Error,
1560
+ url: '',
1561
+ },
1562
+ SINGLE_IF_DIRECTIVE_ALLOWED: {
1563
+ code: 1182,
1564
+ message: `Multiple if: directives found on '{0}'. Only one if: directive is allowed; the rest are ignored.`,
1565
+ level: DiagnosticLevel.Warning,
1566
+ url: '',
1567
+ },
1568
+ LWC_COMPONENT_TAG_WITHOUT_IS_DIRECTIVE: {
1569
+ code: 1183,
1570
+ message: `<lwc:component> must have an 'lwc:is' attribute.`,
1571
+ level: DiagnosticLevel.Error,
1572
+ url: '',
1573
+ },
1574
+ UNSUPPORTED_LWC_TAG_NAME: {
1575
+ code: 1184,
1576
+ message: '{0} is not a special LWC tag name and will be treated as an HTML element.',
1577
+ level: DiagnosticLevel.Warning,
1578
+ url: '',
1579
+ },
1580
+ INVALID_LWC_IS_DIRECTIVE_VALUE: {
1581
+ code: 1185,
1582
+ message: 'Invalid lwc:is usage for value {0}. The value assigned to lwc:is must be an expression.',
1583
+ level: DiagnosticLevel.Error,
1584
+ url: '',
1585
+ },
1586
+ LWC_IS_INVALID_ELEMENT: {
1587
+ code: 1186,
1588
+ message: 'Invalid lwc:is usage for element {0}. The directive can only be used with <lwc:component>',
1589
+ level: DiagnosticLevel.Error,
1590
+ url: '',
1591
+ },
1592
+ DEPRECATED_LWC_DYNAMIC_ATTRIBUTE: {
1593
+ code: 1187,
1594
+ message: `The lwc:dynamic directive is deprecated and will be removed in a future release. Please use lwc:is instead.`,
1595
+ level: DiagnosticLevel.Warning,
1596
+ url: '',
1597
+ },
1598
+ INVALID_OPTS_LWC_ENABLE_DYNAMIC_COMPONENTS: {
1599
+ code: 1188,
1600
+ message: 'Invalid dynamic components usage, lwc:component and lwc:is can only be used when dynamic components have been enabled.',
1601
+ level: DiagnosticLevel.Error,
1602
+ url: '',
1603
+ },
1604
+ // TODO [#3370]: remove this error if template expressions is removed
1605
+ INVALID_EXPR_ARROW_FN_PARAM: {
1606
+ code: 1189,
1607
+ message: "Template expression doesn't allow {0} in arrow function params.",
1608
+ level: DiagnosticLevel.Error,
1609
+ url: '',
1610
+ },
1611
+ // TODO [#3370]: remove this error if template expressions is removed
1612
+ INVALID_EXPR_STATEMENTS_PROHIBITED: {
1613
+ code: 1190,
1614
+ message: 'Statements are disallowed in template expressions.',
1615
+ level: DiagnosticLevel.Error,
1616
+ url: '',
1617
+ },
1618
+ // TODO [#3370]: remove this error if template expressions is removed
1619
+ INVALID_EXPR_MUTATION_OUTSIDE_ARROW: {
1620
+ code: 1191,
1621
+ message: 'Field mutations are only permitted within arrow functions.',
1622
+ level: DiagnosticLevel.Error,
1623
+ url: '',
1624
+ },
1625
+ // TODO [#3370]: remove this error if template expressions is removed
1626
+ INVALID_EXPR_DELETE_OP: {
1627
+ code: 1192,
1628
+ message: 'Use of the delete operator is prohibited within template expressions.',
1629
+ level: DiagnosticLevel.Error,
1630
+ url: '',
1631
+ },
1632
+ // TODO [#3370]: remove this error if template expressions is removed
1633
+ INVALID_EXPR_ARROW_FN_BODY: {
1634
+ code: 1193,
1635
+ message: 'The body of arrow functions in template expressions must be an expression.',
1636
+ level: DiagnosticLevel.Error,
1637
+ url: '',
1638
+ },
1639
+ // TODO [#3370]: remove this error if template expressions is removed
1640
+ INVALID_EXPR_ARROW_FN_KIND: {
1641
+ code: 1194,
1642
+ message: 'Arrow functions in template expressions cannot be {0}.',
1643
+ level: DiagnosticLevel.Error,
1644
+ url: '',
1645
+ },
1646
+ // TODO [#3370]: remove this error if template expressions is removed
1647
+ INVALID_EXPR_EARLY_STAGE_FEATURE: {
1648
+ code: 1195,
1649
+ message: 'Early-stage JS features are disallowed in template expressions.',
1650
+ level: DiagnosticLevel.Error,
1651
+ url: '',
1652
+ },
1653
+ // TODO [#3370]: remove this error if template expressions is removed
1654
+ INVALID_EXPR_PROHIBITED_NODE_TYPE: {
1655
+ code: 1196,
1656
+ message: 'Use of {0} is disallowed within template expressions.',
1657
+ level: DiagnosticLevel.Error,
1658
+ url: '',
1659
+ },
1660
+ // TODO [#3370]: remove this error if template expressions is removed
1661
+ INVALID_EXPR_COMMENTS_DISALLOWED: {
1662
+ code: 1197,
1663
+ message: 'Use of comments is disallowed within template expressions.',
1664
+ level: DiagnosticLevel.Error,
1665
+ url: '',
1666
+ },
1667
+ });
1668
+
1669
+ /**
1670
+ * Pattern modeled after @lwc/engine-core's reporting.ts system
1671
+ */
1672
+ var CompilerMetrics;
1673
+ (function (CompilerMetrics) {
1674
+ CompilerMetrics["LWCDynamicDirective"] = "lwc-dynamic-directive";
1675
+ CompilerMetrics["LWCRenderModeDirective"] = "lwc-render-mode-directive";
1676
+ CompilerMetrics["LWCSpreadDirective"] = "lwc-spread-directive";
1677
+ CompilerMetrics["DynamicImportTransform"] = "dynamic-import-transform";
1678
+ })(CompilerMetrics || (CompilerMetrics = {}));
1679
+ /** version: 8.3.0 */
1680
+
1681
+ /*
1682
+ * Copyright (c) 2024, Salesforce, Inc.
1683
+ * All rights reserved.
1684
+ * SPDX-License-Identifier: MIT
1685
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1686
+ */
1687
+ const bStylesheetTokenDeclaration = (esTemplate `
495
1688
  const stylesheetScopeToken = '${estreeToolkit.is.literal}';
496
- `;
1689
+ `);
497
1690
  const bAdditionalDeclarations = [
498
- esTemplate `
1691
+ (esTemplate `
499
1692
  const hasScopedStylesheets = defaultScopedStylesheets && defaultScopedStylesheets.length > 0;
500
- `,
501
- esTemplate `
1693
+ `),
1694
+ (esTemplate `
502
1695
  const stylesheetScopeTokenClass = hasScopedStylesheets ? \` class="\${stylesheetScopeToken}"\` : '';
503
- `,
504
- esTemplate `
1696
+ `),
1697
+ (esTemplate `
505
1698
  const stylesheetScopeTokenHostClass = hasScopedStylesheets ? \` class="\${stylesheetScopeToken}-host"\` : '';
506
- `,
507
- esTemplate `
1699
+ `),
1700
+ (esTemplate `
508
1701
  const stylesheetScopeTokenClassPrefix = hasScopedStylesheets ? (stylesheetScopeToken + ' ') : '';
509
- `,
1702
+ `),
510
1703
  ];
511
1704
  // Scope tokens are associated with a given template. This is assigned here so that it can be used in `generateMarkup`.
512
- const tmplAssignmentBlock = esTemplate `
1705
+ const tmplAssignmentBlock = (esTemplate `
513
1706
  ${estreeToolkit.is.identifier}.stylesheetScopeTokenHostClass = stylesheetScopeTokenHostClass;
514
- `;
1707
+ `);
515
1708
  function addScopeTokenDeclarations(program, filename, namespace, componentName) {
516
1709
  const { scopeToken } = templateCompiler.generateScopeTokens(filename, namespace, componentName);
517
1710
  program.body.unshift(bStylesheetTokenDeclaration(builders.builders.literal(scopeToken)), ...bAdditionalDeclarations.map((declaration) => declaration()));
@@ -524,9 +1717,9 @@ function addScopeTokenDeclarations(program, filename, namespace, componentName)
524
1717
  * SPDX-License-Identifier: MIT
525
1718
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
526
1719
  */
527
- const bImportHtmlEscape = esTemplate `
1720
+ const bImportHtmlEscape = (esTemplate `
528
1721
  import { htmlEscape } from '@lwc/shared';
529
- `;
1722
+ `);
530
1723
  const importHtmlEscapeKey = 'import:htmlEscape';
531
1724
  // This is a mostly-correct regular expression will only match if the entire string
532
1725
  // provided is a valid ECMAScript identifier. Its imperfections lie in the fact that
@@ -612,14 +1805,16 @@ function expressionIrToEs(node, cxt) {
612
1805
  * SPDX-License-Identifier: MIT
613
1806
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
614
1807
  */
615
- const bYieldFromChildGenerator = esTemplateWithYield `
1808
+ const bYieldFromChildGenerator = (esTemplateWithYield `
616
1809
  {
617
1810
  const childProps = ${estreeToolkit.is.objectExpression};
618
1811
  const childAttrs = ${estreeToolkit.is.objectExpression};
619
- const childSlottedContentGenerators = {};
620
- yield* ${estreeToolkit.is.identifier}(${estreeToolkit.is.literal}, childProps, childAttrs, childSlottedContentGenerators);
1812
+ async function* childSlottedContentGenerator() {
1813
+ ${estreeToolkit.is.statement}
1814
+ };
1815
+ yield* ${estreeToolkit.is.identifier}(${estreeToolkit.is.literal}, childProps, childAttrs, childSlottedContentGenerator);
621
1816
  }
622
- `;
1817
+ `);
623
1818
  const bImportGenerateMarkup = (localName, importPath) => estreeToolkit.builders.importDeclaration([estreeToolkit.builders.importSpecifier(estreeToolkit.builders.identifier('generateMarkup'), estreeToolkit.builders.identifier(localName))], estreeToolkit.builders.literal(importPath));
624
1819
  function getChildAttrsOrProps(attrs, cxt) {
625
1820
  const objectAttrsOrProps = attrs.map((attr) => {
@@ -664,7 +1859,7 @@ const Component = function Component(node, cxt) {
664
1859
  const childTagName = node.name;
665
1860
  const attributes = [...node.attributes, ...reflectAriaPropsAsAttrs(node.properties)];
666
1861
  return [
667
- bYieldFromChildGenerator(getChildAttrsOrProps(node.properties, cxt), getChildAttrsOrProps(attributes, cxt), estreeToolkit.builders.identifier(childGeneratorLocalName), estreeToolkit.builders.literal(childTagName)),
1862
+ bYieldFromChildGenerator(getChildAttrsOrProps(node.properties, cxt), getChildAttrsOrProps(attributes, cxt), optimizeAdjacentYieldStmts(irChildrenToEs(node.children, cxt)), estreeToolkit.builders.identifier(childGeneratorLocalName), estreeToolkit.builders.literal(childTagName)),
668
1863
  ];
669
1864
  };
670
1865
 
@@ -675,7 +1870,7 @@ const Component = function Component(node, cxt) {
675
1870
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
676
1871
  */
677
1872
  const bYield$1 = (expr) => estreeToolkit.builders.expressionStatement(estreeToolkit.builders.yieldExpression(expr));
678
- const bConditionalLiveYield = esTemplateWithYield `
1873
+ const bConditionalLiveYield = (esTemplateWithYield `
679
1874
  {
680
1875
  const prefix = (${ /* isClass */estreeToolkit.is.literal} && stylesheetScopeTokenClassPrefix) || '';
681
1876
  const attrOrPropValue = ${estreeToolkit.is.expression};
@@ -687,13 +1882,13 @@ const bConditionalLiveYield = esTemplateWithYield `
687
1882
  }
688
1883
  }
689
1884
  }
690
- `;
691
- const bStringLiteralYield = esTemplateWithYield `
1885
+ `);
1886
+ const bStringLiteralYield = (esTemplateWithYield `
692
1887
  {
693
1888
  const prefix = (${ /* isClass */estreeToolkit.is.literal} && stylesheetScopeTokenClassPrefix) || '';
694
1889
  yield ' ' + ${estreeToolkit.is.literal} + '="' + prefix + "${estreeToolkit.is.literal}" + '"'
695
1890
  }
696
- `;
1891
+ `);
697
1892
  function yieldAttrOrPropLiteralValue(name, valueNode, isClass) {
698
1893
  const { value, type } = valueNode;
699
1894
  if (typeof value === 'string') {
@@ -741,6 +1936,7 @@ function reorderAttributes(attrs, props) {
741
1936
  return [classAttr, styleAttr, ...boringAttrs, ...props, slotAttr].filter((el) => el !== null);
742
1937
  }
743
1938
  const Element = function Element(node, cxt) {
1939
+ const innerHtmlDirective = node.type === 'Element' && node.directives.find((dir) => dir.name === 'InnerHTML');
744
1940
  const attrsAndProps = reorderAttributes(node.attributes, node.properties);
745
1941
  let hasClassAttribute = false;
746
1942
  const yieldAttrsAndProps = attrsAndProps.flatMap((attr) => {
@@ -761,13 +1957,27 @@ const Element = function Element(node, cxt) {
761
1957
  if (shared.isVoidElement(node.name, shared.HTML_NAMESPACE)) {
762
1958
  return [bYield$1(estreeToolkit.builders.literal(`<${node.name}`)), ...yieldAttrsAndProps, bYield$1(estreeToolkit.builders.literal(`>`))];
763
1959
  }
1960
+ let childContent;
1961
+ // An element can have children or lwc:inner-html, but not both
1962
+ // If it has both, the template compiler will throw an error before reaching here
1963
+ if (node.children.length) {
1964
+ childContent = irChildrenToEs(node.children, cxt);
1965
+ }
1966
+ else if (innerHtmlDirective) {
1967
+ const value = innerHtmlDirective.value;
1968
+ const unsanitizedHtmlExpression = value.type === 'Literal' ? estreeToolkit.builders.literal(value.value) : expressionIrToEs(value, cxt);
1969
+ childContent = [bYield$1(unsanitizedHtmlExpression)];
1970
+ }
1971
+ else {
1972
+ childContent = [];
1973
+ }
764
1974
  return [
765
1975
  bYield$1(estreeToolkit.builders.literal(`<${node.name}`)),
766
1976
  // If we haven't already prefixed the scope token to an existing class, add an explicit class here
767
1977
  ...(hasClassAttribute ? [] : [bYield$1(estreeToolkit.builders.identifier('stylesheetScopeTokenClass'))]),
768
1978
  ...yieldAttrsAndProps,
769
1979
  bYield$1(estreeToolkit.builders.literal(`>`)),
770
- ...irChildrenToEs(node.children, cxt),
1980
+ ...childContent,
771
1981
  bYield$1(estreeToolkit.builders.literal(`</${node.name}>`)),
772
1982
  ].filter(Boolean);
773
1983
  };
@@ -785,11 +1995,11 @@ function getRootIdentifier$1(node) {
785
1995
  const rootMemberExpression = getRootMemberExpression$1(node);
786
1996
  return estreeToolkit.is.identifier(rootMemberExpression?.object) ? rootMemberExpression.object : null;
787
1997
  }
788
- const bForOfYieldFrom$1 = esTemplate `
1998
+ const bForOfYieldFrom$1 = (esTemplate `
789
1999
  for (let [${estreeToolkit.is.identifier}, ${estreeToolkit.is.identifier}] of Object.entries(${estreeToolkit.is.expression} ?? {})) {
790
2000
  ${estreeToolkit.is.statement};
791
2001
  }
792
- `;
2002
+ `);
793
2003
  const ForEach = function ForEach(node, cxt) {
794
2004
  const forItemId = node.item.name;
795
2005
  const forIndexId = node.index?.name ?? '__unused__';
@@ -823,14 +2033,14 @@ function getRootIdentifier(node) {
823
2033
  const rootMemberExpression = getRootMemberExpression(node);
824
2034
  return estreeToolkit.is.identifier(rootMemberExpression?.object) ? rootMemberExpression.object : null;
825
2035
  }
826
- const bForOfYieldFrom = esTemplate `
2036
+ const bForOfYieldFrom = (esTemplate `
827
2037
  for (let ${estreeToolkit.is.identifier} of toIteratorDirective(${estreeToolkit.is.expression} ?? [])) {
828
2038
  ${estreeToolkit.is.statement};
829
2039
  }
830
- `;
831
- const bToIteratorDirectiveImport = esTemplate `
2040
+ `);
2041
+ const bToIteratorDirectiveImport = (esTemplate `
832
2042
  import { toIteratorDirective } from '@lwc/ssr-runtime';
833
- `;
2043
+ `);
834
2044
  const ForOf = function ForEach(node, cxt) {
835
2045
  const id = node.iterator.name;
836
2046
  cxt.pushLocalVars([id]);
@@ -889,6 +2099,54 @@ const IfBlock = function IfBlock(node, cxt) {
889
2099
  return [bIfStatement(node, cxt)];
890
2100
  };
891
2101
 
2102
+ /*
2103
+ * Copyright (c) 2024, salesforce.com, inc.
2104
+ * All rights reserved.
2105
+ * SPDX-License-Identifier: MIT
2106
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
2107
+ */
2108
+ const bConditionalSlot = (esTemplateWithYield `
2109
+ if (isLightDom) {
2110
+ // start bookend HTML comment
2111
+ yield '<!---->';
2112
+
2113
+ const generator = slottedContent[${ /* slotName */estreeToolkit.is.expression} ?? ""];
2114
+ if (generator) {
2115
+ yield* generator();
2116
+ } else {
2117
+ // If we're in this else block, then the generator _must_ have yielded
2118
+ // something. It's impossible for a slottedContent["foo"] to exist
2119
+ // without the generator yielding at least a text node / element.
2120
+ // FIXME: how does this work with comments and lwc:preserve-comments?
2121
+ // TODO: default/fallback slot content
2122
+ ${ /* slot fallback content */estreeToolkit.is.statement}
2123
+ }
2124
+
2125
+ // end bookend HTML comment
2126
+ yield '<!---->';
2127
+ } else {
2128
+ ${ /* slot element AST */estreeToolkit.is.statement}
2129
+ }
2130
+ `);
2131
+ const Slot = function Slot(node, ctx) {
2132
+ const nameAttrValue = node.attributes.find((attr) => attr.name === 'name')?.value;
2133
+ let slotName;
2134
+ if (!nameAttrValue) {
2135
+ slotName = estreeToolkit.builders.literal('');
2136
+ }
2137
+ else if (nameAttrValue.type === 'Literal') {
2138
+ const name = typeof nameAttrValue.value === 'string' ? nameAttrValue.value : '';
2139
+ slotName = estreeToolkit.builders.literal(name);
2140
+ }
2141
+ else {
2142
+ slotName = estreeToolkit.builders.memberExpression(estreeToolkit.builders.literal('instance'), nameAttrValue);
2143
+ }
2144
+ // FIXME: avoid serializing the slot's children twice
2145
+ const slotAst = Element(node, ctx);
2146
+ const slotChildren = irChildrenToEs(node.children, ctx);
2147
+ return [bConditionalSlot(slotName, slotChildren, slotAst)];
2148
+ };
2149
+
892
2150
  /*
893
2151
  * Copyright (c) 2024, salesforce.com, inc.
894
2152
  * All rights reserved.
@@ -896,16 +2154,16 @@ const IfBlock = function IfBlock(node, cxt) {
896
2154
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
897
2155
  */
898
2156
  const bYield = (expr) => estreeToolkit.builders.expressionStatement(estreeToolkit.builders.yieldExpression(expr));
899
- const bYieldEscapedString = esTemplateWithYield `
2157
+ const bYieldEscapedString = (esTemplateWithYield `
900
2158
  const ${estreeToolkit.is.identifier} = ${estreeToolkit.is.expression};
901
- if (typeof ${estreeToolkit.is.identifier} === 'string') {
902
- yield (${estreeToolkit.is.literal} && ${estreeToolkit.is.identifier} === '') ? '\\u200D' : htmlEscape(${estreeToolkit.is.identifier});
903
- } else if (typeof ${estreeToolkit.is.identifier} === 'number') {
904
- yield ${estreeToolkit.is.identifier}.toString();
2159
+ if (typeof ${0} === 'string') {
2160
+ yield (${estreeToolkit.is.literal} && ${0} === '') ? '\\u200D' : htmlEscape(${0});
2161
+ } else if (typeof ${0} === 'number') {
2162
+ yield ${0}.toString();
905
2163
  } else {
906
- yield htmlEscape((${estreeToolkit.is.identifier} ?? '').toString());
2164
+ yield ${0} ? htmlEscape(${0}.toString()) : '\\u200D';
907
2165
  }
908
- `;
2166
+ `);
909
2167
  function isLiteral(node) {
910
2168
  return node.type === 'Literal';
911
2169
  }
@@ -918,7 +2176,7 @@ const Text = function Text(node, cxt) {
918
2176
  const valueToYield = expressionIrToEs(node.value, cxt);
919
2177
  cxt.hoist(bImportHtmlEscape(), importHtmlEscapeKey);
920
2178
  const tempVariable = estreeToolkit.builders.identifier(cxt.getUniqueVar());
921
- return bYieldEscapedString(tempVariable, valueToYield, tempVariable, isIsolatedTextNode, tempVariable, tempVariable, tempVariable, tempVariable, tempVariable);
2179
+ return bYieldEscapedString(tempVariable, valueToYield, isIsolatedTextNode);
922
2180
  };
923
2181
 
924
2182
  /*
@@ -1003,7 +2261,7 @@ const transformers = {
1003
2261
  // lwc:elseif cannot exist without an lwc:elseif (IfBlock); this gets handled by that transformer
1004
2262
  ElseBlock: defaultTransformer,
1005
2263
  ScopedSlotFragment: defaultTransformer,
1006
- Slot: defaultTransformer,
2264
+ Slot,
1007
2265
  Lwc: defaultTransformer,
1008
2266
  };
1009
2267
  function irChildrenToEs(children, cxt) {
@@ -1017,6 +2275,9 @@ function irChildrenToEs(children, cxt) {
1017
2275
  return result;
1018
2276
  }
1019
2277
  function irToEs(node, cxt) {
2278
+ if ('directives' in node && node.directives.some((d) => d.name === 'Dynamic')) {
2279
+ throw new Error('The lwc:dynamic directive is not supported for SSR. Use <lwc:component> instead.');
2280
+ }
1020
2281
  const transformer = transformers[node.type];
1021
2282
  return transformer(node, cxt);
1022
2283
  }
@@ -1035,13 +2296,14 @@ function templateIrToEsTree(node, contextOpts) {
1035
2296
  * SPDX-License-Identifier: MIT
1036
2297
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1037
2298
  */
1038
- const isBool = (node) => estreeToolkit.is.literal(node) && typeof node.value === 'boolean';
1039
- const bStyleValidationImport = esTemplate `
2299
+ const bStyleValidationImport = (esTemplate `
1040
2300
  import { validateStyleTextContents } from '@lwc/ssr-runtime';
1041
- `;
1042
- const bExportTemplate = esTemplate `
1043
- export default async function* tmpl(props, attrs, slotted, Cmp, instance) {
1044
- if (!${isBool} && Cmp.renderMode !== 'light') {
2301
+ `);
2302
+ // TODO [#4663]: Render mode mismatch between template and compiler should throw.
2303
+ const bExportTemplate = (esTemplate `
2304
+ export default async function* tmpl(props, attrs, slottedContent, Cmp, instance) {
2305
+ const isLightDom = Cmp.renderMode === 'light';
2306
+ if (!isLightDom) {
1045
2307
  yield \`<template shadowrootmode="open"\${Cmp.delegatesFocus ? ' shadowrootdelegatesfocus' : ''}>\`
1046
2308
  }
1047
2309
 
@@ -1063,29 +2325,54 @@ const bExportTemplate = esTemplate `
1063
2325
 
1064
2326
  ${estreeToolkit.is.statement};
1065
2327
 
1066
- if (!${isBool} && Cmp.renderMode !== 'light') {
2328
+ if (!isLightDom) {
1067
2329
  yield '</template>';
1068
2330
  }
2331
+
2332
+ if (slottedContent) {
2333
+ yield* slottedContent();
2334
+ }
1069
2335
  }
1070
- `;
2336
+ `);
1071
2337
  function compileTemplate(src, filename, options) {
1072
- const { root, warnings } = templateCompiler.parse(src);
2338
+ const { root, warnings } = templateCompiler.parse(src, {
2339
+ // `options` is from @lwc/compiler, and may have flags that @lwc/template-compiler doesn't
2340
+ // know about, so we must explicitly extract the relevant props.
2341
+ name: options.name,
2342
+ namespace: options.namespace,
2343
+ customRendererConfig: options.customRendererConfig,
2344
+ experimentalComputedMemberExpression: options.experimentalComputedMemberExpression,
2345
+ experimentalComplexExpressions: options.experimentalComplexExpressions,
2346
+ enableDynamicComponents: options.enableDynamicComponents,
2347
+ preserveHtmlComments: options.preserveHtmlComments,
2348
+ enableStaticContentOptimization: options.enableStaticContentOptimization,
2349
+ instrumentation: options.instrumentation,
2350
+ apiVersion: options.apiVersion,
2351
+ disableSyntheticShadowSupport: options.disableSyntheticShadowSupport,
2352
+ // TODO [#3331]: remove usage of lwc:dynamic in 246
2353
+ experimentalDynamicDirective: options.experimentalDynamicDirective,
2354
+ });
1073
2355
  if (!root || warnings.length) {
2356
+ let fatal = !root;
1074
2357
  for (const warning of warnings) {
1075
2358
  // eslint-disable-next-line no-console
1076
2359
  console.error('Cannot compile:', warning.message);
2360
+ if (warning.level === DiagnosticLevel.Fatal ||
2361
+ warning.level === DiagnosticLevel.Error) {
2362
+ fatal = true;
2363
+ }
2364
+ }
2365
+ // || !root is just used here to make TypeScript happy
2366
+ if (fatal || !root) {
2367
+ throw new Error('Template compilation failure; see warnings in the console.');
1077
2368
  }
1078
- throw new Error('Template compilation failure; see warnings in the console.');
1079
2369
  }
1080
- const tmplRenderMode = root.directives.find((directive) => directive.name === 'RenderMode')?.value?.value ??
1081
- 'shadow';
1082
- const astShadowModeBool = tmplRenderMode === 'light' ? estreeToolkit.builders.literal(true) : estreeToolkit.builders.literal(false);
1083
2370
  const preserveComments = !!root.directives.find((directive) => directive.name === 'PreserveComments')?.value?.value;
1084
2371
  const { hoisted, statements } = templateIrToEsTree(root, { preserveComments });
1085
2372
  const moduleBody = [
1086
2373
  ...hoisted,
1087
2374
  bStyleValidationImport(),
1088
- bExportTemplate(astShadowModeBool, optimizeAdjacentYieldStmts(statements), astShadowModeBool),
2375
+ bExportTemplate(optimizeAdjacentYieldStmts(statements)),
1089
2376
  ];
1090
2377
  const program = estreeToolkit.builders.program(moduleBody, 'module');
1091
2378
  addScopeTokenDeclarations(program, filename, options.namespace, options.name);
@@ -1113,5 +2400,5 @@ function compileTemplateForSSR(src, filename, options) {
1113
2400
 
1114
2401
  exports.compileComponentForSSR = compileComponentForSSR;
1115
2402
  exports.compileTemplateForSSR = compileTemplateForSSR;
1116
- /** version: 8.2.0 */
2403
+ /** version: 8.3.0 */
1117
2404
  //# sourceMappingURL=index.cjs.js.map