@lwc/ssr-compiler 8.14.0 → 8.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -9,10 +9,10 @@ var shared = require('@lwc/shared');
9
9
  var astring = require('astring');
10
10
  var estreeToolkit = require('estree-toolkit');
11
11
  var meriyah = require('meriyah');
12
+ var errors = require('@lwc/errors');
12
13
  var immer = require('immer');
13
14
  var node_path = require('node:path');
14
15
  var acorn = require('acorn');
15
- var errors = require('@lwc/errors');
16
16
  var templateCompiler = require('@lwc/template-compiler');
17
17
  var builders = require('estree-toolkit/dist/builders');
18
18
  var types = require('@babel/types');
@@ -588,41 +588,31 @@ function getWireParams(node) {
588
588
  if (decorators.length > 1) {
589
589
  throw generateError(node, errors.DecoratorErrors.ONE_WIRE_DECORATOR_ALLOWED);
590
590
  }
591
- // validate the parameters
591
+ // Before calling this function, we validate that it has exactly one decorator, @wire
592
592
  const wireDecorator = decorators[0].expression;
593
593
  if (!estreeToolkit.is.callExpression(wireDecorator)) {
594
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
595
- throw new Error('todo - invalid usage');
594
+ throw generateError(node, errors.DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER);
596
595
  }
597
596
  const args = wireDecorator.arguments;
598
- if (args.length === 0 || args.length > 2) {
599
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
600
- throw new Error('todo - wrong number of args');
601
- }
602
- const [id, config] = args;
603
- if (estreeToolkit.is.spreadElement(id) || estreeToolkit.is.spreadElement(config)) {
604
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
605
- throw new Error('todo - spread in params');
597
+ if (args.length === 0) {
598
+ throw generateError(node, errors.DecoratorErrors.ADAPTER_SHOULD_BE_FIRST_PARAMETER);
606
599
  }
607
- return [id, config];
600
+ return args;
608
601
  }
609
602
  function validateWireId(id, path) {
610
603
  // name of identifier or object used in member expression (e.g. "foo" for `foo.bar`)
611
604
  let wireAdapterVar;
612
605
  if (estreeToolkit.is.memberExpression(id)) {
613
606
  if (id.computed) {
614
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
615
- throw new Error('todo - FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS');
607
+ throw generateError(path.node, errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS);
616
608
  }
617
609
  if (!estreeToolkit.is.identifier(id.object)) {
618
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
619
- throw new Error('todo - FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS');
610
+ throw generateError(path.node, errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS);
620
611
  }
621
612
  wireAdapterVar = id.object.name;
622
613
  }
623
614
  else if (!estreeToolkit.is.identifier(id)) {
624
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
625
- throw new Error('todo - invalid adapter name');
615
+ throw generateError(path.node, errors.DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER);
626
616
  }
627
617
  else {
628
618
  wireAdapterVar = id.name;
@@ -634,8 +624,7 @@ function validateWireId(id, path) {
634
624
  }
635
625
  function validateWireConfig(config, path) {
636
626
  if (!estreeToolkit.is.objectExpression(config)) {
637
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
638
- throw new Error('todo - CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER');
627
+ throw generateError(path.node, errors.DecoratorErrors.CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER);
639
628
  }
640
629
  for (const property of config.properties) {
641
630
  // Only validate computed object properties because static props are all valid
@@ -657,8 +646,7 @@ function validateWireConfig(config, path) {
657
646
  if (estreeToolkit.is.templateLiteral(key)) {
658
647
  // A template literal is not guaranteed to always result in the same value
659
648
  // (e.g. `${Math.random()}`), so we disallow them entirely.
660
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
661
- throw new Error('todo - COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL');
649
+ throw generateError(path.node, errors.DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL);
662
650
  }
663
651
  else if (!('regex' in key)) {
664
652
  // A literal can be a regexp, template literal, or primitive; only allow primitives
@@ -749,7 +737,6 @@ const bGenerateMarkup = (esTemplate `
749
737
  // These variables may mix with component-authored variables, so should be reasonably unique
750
738
  const __lwcSuperPublicProperties__ = Array.from(Object.getPrototypeOf(${ /* Component class */estreeToolkit.is.identifier})?.__lwcPublicProperties__?.values?.() ?? []);
751
739
  const __lwcPublicProperties__ = new Set(${ /*public properties*/estreeToolkit.is.arrayExpression}.concat(__lwcSuperPublicProperties__));
752
- const __lwcPrivateProperties__ = new Set(${ /*private properties*/estreeToolkit.is.arrayExpression});
753
740
 
754
741
  Object.defineProperty(
755
742
  ${ /* component class */0},
@@ -761,13 +748,13 @@ const bGenerateMarkup = (esTemplate `
761
748
  value: async function* generateMarkup(
762
749
  tagName,
763
750
  props,
764
- attrs,
751
+ attrs,
752
+ parent,
753
+ scopeToken,
754
+ contextfulParent,
765
755
  shadowSlottedContent,
766
756
  lightSlottedContent,
767
757
  scopedSlottedContent,
768
- parent,
769
- scopeToken,
770
- contextfulParent
771
758
  ) {
772
759
  tagName = tagName ?? ${ /*component tag name*/estreeToolkit.is.literal};
773
760
  attrs = attrs ?? Object.create(null);
@@ -782,8 +769,7 @@ const bGenerateMarkup = (esTemplate `
782
769
  instance[__SYMBOL__SET_INTERNALS](
783
770
  props,
784
771
  attrs,
785
- __lwcPublicProperties__,
786
- __lwcPrivateProperties__,
772
+ __lwcPublicProperties__
787
773
  );
788
774
  instance.isConnected = true;
789
775
  if (instance.connectedCallback) {
@@ -852,7 +838,7 @@ const bExposeTemplate = (esTemplate `
852
838
  * - deferring to the template function for yielding child content
853
839
  */
854
840
  function addGenerateMarkupFunction(program, state, tagName, filename) {
855
- const { privateProperties, publicProperties, tmplExplicitImports } = state;
841
+ const { publicProperties, tmplExplicitImports } = state;
856
842
  // The default tag name represents the component name that's passed to the transformer.
857
843
  // This is needed to generate markup for dynamic components which are invoked through
858
844
  // the generateMarkup function on the constructor.
@@ -882,7 +868,7 @@ function addGenerateMarkupFunction(program, state, tagName, filename) {
882
868
  SYMBOL__SET_INTERNALS: '__SYMBOL__SET_INTERNALS',
883
869
  establishContextfulRelationship: '__establishContextfulRelationship',
884
870
  }));
885
- program.body.push(...bGenerateMarkup(classIdentifier, estreeToolkit.builders.arrayExpression([...publicProperties.keys()].map(estreeToolkit.builders.literal)), estreeToolkit.builders.arrayExpression([...privateProperties].map(estreeToolkit.builders.literal)), defaultTagName, connectWireAdapterCode));
871
+ program.body.push(...bGenerateMarkup(classIdentifier, estreeToolkit.builders.arrayExpression([...publicProperties.keys()].map(estreeToolkit.builders.literal)), defaultTagName, connectWireAdapterCode));
886
872
  if (exposeTemplateBlock) {
887
873
  program.body.push(exposeTemplateBlock);
888
874
  }
@@ -1028,8 +1014,7 @@ const visitors = {
1028
1014
  }
1029
1015
  if (experimentalDynamicComponent.strictSpecifier) {
1030
1016
  if (!estreeToolkit.is.literal(path.node?.source) || typeof path.node.source.value !== 'string') {
1031
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1032
- throw new Error('todo - LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT');
1017
+ throw generateError(path.node, errors.LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT);
1033
1018
  }
1034
1019
  }
1035
1020
  const loader = experimentalDynamicComponent.loader;
@@ -1123,7 +1108,7 @@ const visitors = {
1123
1108
  }
1124
1109
  else if (isWireDecorator(decorators[0])) {
1125
1110
  if (node.computed) {
1126
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1111
+ // TODO [W-17758410]: implement
1127
1112
  throw new Error('@wire cannot be used on computed properties in SSR context.');
1128
1113
  }
1129
1114
  const isRealMethod = node.kind === 'method';
@@ -1198,8 +1183,7 @@ const visitors = {
1198
1183
  Identifier(path, _state) {
1199
1184
  const { node } = path;
1200
1185
  if (node?.name.startsWith('__lwc')) {
1201
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1202
- throw new Error(`LWCTODO: identifier name '${node.name}' cannot start with '__lwc'`);
1186
+ throw generateError(node, errors.SsrCompilerErrors.RESERVED_IDENTIFIER_PREFIX);
1203
1187
  }
1204
1188
  },
1205
1189
  };
@@ -1412,6 +1396,7 @@ function getChildAttrsOrProps(attrs, cxt) {
1412
1396
  .map(({ name, value, type }) => {
1413
1397
  // Babel function required to align identifier validation with babel-plugin-component: https://github.com/salesforce/lwc/issues/4826
1414
1398
  const key = types.isValidES3Identifier(name) ? estreeToolkit.builders.identifier(name) : estreeToolkit.builders.literal(name);
1399
+ const nameLower = name.toLowerCase();
1415
1400
  if (value.type === 'Literal' && typeof value.value === 'string') {
1416
1401
  let literalValue = value.value;
1417
1402
  if (name === 'style') {
@@ -1428,6 +1413,12 @@ function getChildAttrsOrProps(attrs, cxt) {
1428
1413
  // https://github.com/salesforce/lwc/blob/574ffbd/packages/%40lwc/template-compiler/src/codegen/index.ts#L445-L448
1429
1414
  literalValue = literalValue.toLowerCase() !== 'false';
1430
1415
  }
1416
+ else if (nameLower === 'tabindex') {
1417
+ // Global HTML "tabindex" attribute is specially massaged into a stringified number
1418
+ // This follows the historical behavior in api.ts:
1419
+ // https://github.com/salesforce/lwc/blob/f34a347/packages/%40lwc/engine-core/src/framework/api.ts#L193-L211
1420
+ literalValue = shared.normalizeTabIndex(literalValue);
1421
+ }
1431
1422
  return estreeToolkit.builders.property('init', key, estreeToolkit.builders.literal(literalValue));
1432
1423
  }
1433
1424
  else if (value.type === 'Literal' && typeof value.value === 'boolean') {
@@ -1442,6 +1433,10 @@ function getChildAttrsOrProps(attrs, cxt) {
1442
1433
  cxt.import('normalizeClass');
1443
1434
  propValue = estreeToolkit.builders.callExpression(estreeToolkit.builders.identifier('normalizeClass'), [propValue]);
1444
1435
  }
1436
+ else if (nameLower === 'tabindex') {
1437
+ cxt.import('normalizeTabIndex');
1438
+ propValue = estreeToolkit.builders.callExpression(estreeToolkit.builders.identifier('normalizeTabIndex'), [propValue]);
1439
+ }
1445
1440
  return estreeToolkit.builders.property('init', key, propValue);
1446
1441
  }
1447
1442
  throw new Error(`Unimplemented child attr IR node type: ${value.type}`);
@@ -1798,13 +1793,13 @@ estreeToolkit.is.statement}
1798
1793
  yield* generateMarkup(
1799
1794
  tagName,
1800
1795
  childProps,
1801
- childAttrs,
1802
- shadowSlottedContent,
1803
- lightSlottedContentMap,
1804
- scopedSlottedContentMap,
1796
+ childAttrs,
1805
1797
  instance,
1806
1798
  scopeToken,
1807
- contextfulParent
1799
+ contextfulParent,
1800
+ shadowSlottedContent,
1801
+ lightSlottedContentMap,
1802
+ scopedSlottedContentMap
1808
1803
  );
1809
1804
  } else {
1810
1805
  yield \`<\${tagName}>\`;
@@ -1864,12 +1859,12 @@ estreeToolkit.is.statement}
1864
1859
  null,
1865
1860
  childProps,
1866
1861
  childAttrs,
1867
- shadowSlottedContent,
1868
- lightSlottedContentMap,
1869
- scopedSlottedContentMap,
1870
1862
  instance,
1871
1863
  scopeToken,
1872
- contextfulParent
1864
+ contextfulParent,
1865
+ shadowSlottedContent,
1866
+ lightSlottedContentMap,
1867
+ scopedSlottedContentMap
1873
1868
  );
1874
1869
  }
1875
1870
  `);
@@ -2571,5 +2566,5 @@ function compileTemplateForSSR(src, filename, options, mode = shared.DEFAULT_SSR
2571
2566
 
2572
2567
  exports.compileComponentForSSR = compileComponentForSSR;
2573
2568
  exports.compileTemplateForSSR = compileTemplateForSSR;
2574
- /** version: 8.14.0 */
2569
+ /** version: 8.15.0 */
2575
2570
  //# sourceMappingURL=index.cjs.js.map
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * Copyright (c) 2025 Salesforce, Inc.
3
3
  */
4
- import { AMBIGUOUS_PROP_SET, DISALLOWED_PROP_SET, LWC_VERSION_COMMENT, normalizeStyleAttributeValue, StringReplace, StringTrim, entries, isUndefined, HTML_NAMESPACE, isVoidElement, isBooleanAttribute, DEFAULT_SSR_MODE, generateCustomElementTagName } from '@lwc/shared';
4
+ import { AMBIGUOUS_PROP_SET, DISALLOWED_PROP_SET, LWC_VERSION_COMMENT, normalizeStyleAttributeValue, normalizeTabIndex, StringReplace, StringTrim, entries, isUndefined, HTML_NAMESPACE, isVoidElement, isBooleanAttribute, DEFAULT_SSR_MODE, generateCustomElementTagName } from '@lwc/shared';
5
5
  import { generate } from 'astring';
6
6
  import { builders, traverse, is } from 'estree-toolkit';
7
7
  import { parseModule } from 'meriyah';
8
+ import { generateCompilerError, DecoratorErrors, SsrCompilerErrors, LWCClassErrors } from '@lwc/errors';
8
9
  import { produce } from 'immer';
9
10
  import { parse as parse$1 } from 'node:path';
10
11
  import { parse } from 'acorn';
11
- import { generateCompilerError, DecoratorErrors } from '@lwc/errors';
12
12
  import { generateScopeTokens, toPropertyName, kebabcaseToCamelcase, parse as parse$2 } from '@lwc/template-compiler';
13
13
  import { builders as builders$1 } from 'estree-toolkit/dist/builders';
14
14
  import { isValidES3Identifier } from '@babel/types';
@@ -584,41 +584,31 @@ function getWireParams(node) {
584
584
  if (decorators.length > 1) {
585
585
  throw generateError(node, DecoratorErrors.ONE_WIRE_DECORATOR_ALLOWED);
586
586
  }
587
- // validate the parameters
587
+ // Before calling this function, we validate that it has exactly one decorator, @wire
588
588
  const wireDecorator = decorators[0].expression;
589
589
  if (!is.callExpression(wireDecorator)) {
590
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
591
- throw new Error('todo - invalid usage');
590
+ throw generateError(node, DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER);
592
591
  }
593
592
  const args = wireDecorator.arguments;
594
- if (args.length === 0 || args.length > 2) {
595
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
596
- throw new Error('todo - wrong number of args');
593
+ if (args.length === 0) {
594
+ throw generateError(node, DecoratorErrors.ADAPTER_SHOULD_BE_FIRST_PARAMETER);
597
595
  }
598
- const [id, config] = args;
599
- if (is.spreadElement(id) || is.spreadElement(config)) {
600
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
601
- throw new Error('todo - spread in params');
602
- }
603
- return [id, config];
596
+ return args;
604
597
  }
605
598
  function validateWireId(id, path) {
606
599
  // name of identifier or object used in member expression (e.g. "foo" for `foo.bar`)
607
600
  let wireAdapterVar;
608
601
  if (is.memberExpression(id)) {
609
602
  if (id.computed) {
610
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
611
- throw new Error('todo - FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS');
603
+ throw generateError(path.node, DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS);
612
604
  }
613
605
  if (!is.identifier(id.object)) {
614
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
615
- throw new Error('todo - FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS');
606
+ throw generateError(path.node, DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS);
616
607
  }
617
608
  wireAdapterVar = id.object.name;
618
609
  }
619
610
  else if (!is.identifier(id)) {
620
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
621
- throw new Error('todo - invalid adapter name');
611
+ throw generateError(path.node, DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER);
622
612
  }
623
613
  else {
624
614
  wireAdapterVar = id.name;
@@ -630,8 +620,7 @@ function validateWireId(id, path) {
630
620
  }
631
621
  function validateWireConfig(config, path) {
632
622
  if (!is.objectExpression(config)) {
633
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
634
- throw new Error('todo - CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER');
623
+ throw generateError(path.node, DecoratorErrors.CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER);
635
624
  }
636
625
  for (const property of config.properties) {
637
626
  // Only validate computed object properties because static props are all valid
@@ -653,8 +642,7 @@ function validateWireConfig(config, path) {
653
642
  if (is.templateLiteral(key)) {
654
643
  // A template literal is not guaranteed to always result in the same value
655
644
  // (e.g. `${Math.random()}`), so we disallow them entirely.
656
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
657
- throw new Error('todo - COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL');
645
+ throw generateError(path.node, DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL);
658
646
  }
659
647
  else if (!('regex' in key)) {
660
648
  // A literal can be a regexp, template literal, or primitive; only allow primitives
@@ -745,7 +733,6 @@ const bGenerateMarkup = (esTemplate `
745
733
  // These variables may mix with component-authored variables, so should be reasonably unique
746
734
  const __lwcSuperPublicProperties__ = Array.from(Object.getPrototypeOf(${ /* Component class */is.identifier})?.__lwcPublicProperties__?.values?.() ?? []);
747
735
  const __lwcPublicProperties__ = new Set(${ /*public properties*/is.arrayExpression}.concat(__lwcSuperPublicProperties__));
748
- const __lwcPrivateProperties__ = new Set(${ /*private properties*/is.arrayExpression});
749
736
 
750
737
  Object.defineProperty(
751
738
  ${ /* component class */0},
@@ -757,13 +744,13 @@ const bGenerateMarkup = (esTemplate `
757
744
  value: async function* generateMarkup(
758
745
  tagName,
759
746
  props,
760
- attrs,
747
+ attrs,
748
+ parent,
749
+ scopeToken,
750
+ contextfulParent,
761
751
  shadowSlottedContent,
762
752
  lightSlottedContent,
763
753
  scopedSlottedContent,
764
- parent,
765
- scopeToken,
766
- contextfulParent
767
754
  ) {
768
755
  tagName = tagName ?? ${ /*component tag name*/is.literal};
769
756
  attrs = attrs ?? Object.create(null);
@@ -778,8 +765,7 @@ const bGenerateMarkup = (esTemplate `
778
765
  instance[__SYMBOL__SET_INTERNALS](
779
766
  props,
780
767
  attrs,
781
- __lwcPublicProperties__,
782
- __lwcPrivateProperties__,
768
+ __lwcPublicProperties__
783
769
  );
784
770
  instance.isConnected = true;
785
771
  if (instance.connectedCallback) {
@@ -848,7 +834,7 @@ const bExposeTemplate = (esTemplate `
848
834
  * - deferring to the template function for yielding child content
849
835
  */
850
836
  function addGenerateMarkupFunction(program, state, tagName, filename) {
851
- const { privateProperties, publicProperties, tmplExplicitImports } = state;
837
+ const { publicProperties, tmplExplicitImports } = state;
852
838
  // The default tag name represents the component name that's passed to the transformer.
853
839
  // This is needed to generate markup for dynamic components which are invoked through
854
840
  // the generateMarkup function on the constructor.
@@ -878,7 +864,7 @@ function addGenerateMarkupFunction(program, state, tagName, filename) {
878
864
  SYMBOL__SET_INTERNALS: '__SYMBOL__SET_INTERNALS',
879
865
  establishContextfulRelationship: '__establishContextfulRelationship',
880
866
  }));
881
- program.body.push(...bGenerateMarkup(classIdentifier, builders.arrayExpression([...publicProperties.keys()].map(builders.literal)), builders.arrayExpression([...privateProperties].map(builders.literal)), defaultTagName, connectWireAdapterCode));
867
+ program.body.push(...bGenerateMarkup(classIdentifier, builders.arrayExpression([...publicProperties.keys()].map(builders.literal)), defaultTagName, connectWireAdapterCode));
882
868
  if (exposeTemplateBlock) {
883
869
  program.body.push(exposeTemplateBlock);
884
870
  }
@@ -1024,8 +1010,7 @@ const visitors = {
1024
1010
  }
1025
1011
  if (experimentalDynamicComponent.strictSpecifier) {
1026
1012
  if (!is.literal(path.node?.source) || typeof path.node.source.value !== 'string') {
1027
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1028
- throw new Error('todo - LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT');
1013
+ throw generateError(path.node, LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT);
1029
1014
  }
1030
1015
  }
1031
1016
  const loader = experimentalDynamicComponent.loader;
@@ -1119,7 +1104,7 @@ const visitors = {
1119
1104
  }
1120
1105
  else if (isWireDecorator(decorators[0])) {
1121
1106
  if (node.computed) {
1122
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1107
+ // TODO [W-17758410]: implement
1123
1108
  throw new Error('@wire cannot be used on computed properties in SSR context.');
1124
1109
  }
1125
1110
  const isRealMethod = node.kind === 'method';
@@ -1194,8 +1179,7 @@ const visitors = {
1194
1179
  Identifier(path, _state) {
1195
1180
  const { node } = path;
1196
1181
  if (node?.name.startsWith('__lwc')) {
1197
- // TODO [#5032]: Harmonize errors thrown in `@lwc/ssr-compiler`
1198
- throw new Error(`LWCTODO: identifier name '${node.name}' cannot start with '__lwc'`);
1182
+ throw generateError(node, SsrCompilerErrors.RESERVED_IDENTIFIER_PREFIX);
1199
1183
  }
1200
1184
  },
1201
1185
  };
@@ -1408,6 +1392,7 @@ function getChildAttrsOrProps(attrs, cxt) {
1408
1392
  .map(({ name, value, type }) => {
1409
1393
  // Babel function required to align identifier validation with babel-plugin-component: https://github.com/salesforce/lwc/issues/4826
1410
1394
  const key = isValidES3Identifier(name) ? builders.identifier(name) : builders.literal(name);
1395
+ const nameLower = name.toLowerCase();
1411
1396
  if (value.type === 'Literal' && typeof value.value === 'string') {
1412
1397
  let literalValue = value.value;
1413
1398
  if (name === 'style') {
@@ -1424,6 +1409,12 @@ function getChildAttrsOrProps(attrs, cxt) {
1424
1409
  // https://github.com/salesforce/lwc/blob/574ffbd/packages/%40lwc/template-compiler/src/codegen/index.ts#L445-L448
1425
1410
  literalValue = literalValue.toLowerCase() !== 'false';
1426
1411
  }
1412
+ else if (nameLower === 'tabindex') {
1413
+ // Global HTML "tabindex" attribute is specially massaged into a stringified number
1414
+ // This follows the historical behavior in api.ts:
1415
+ // https://github.com/salesforce/lwc/blob/f34a347/packages/%40lwc/engine-core/src/framework/api.ts#L193-L211
1416
+ literalValue = normalizeTabIndex(literalValue);
1417
+ }
1427
1418
  return builders.property('init', key, builders.literal(literalValue));
1428
1419
  }
1429
1420
  else if (value.type === 'Literal' && typeof value.value === 'boolean') {
@@ -1438,6 +1429,10 @@ function getChildAttrsOrProps(attrs, cxt) {
1438
1429
  cxt.import('normalizeClass');
1439
1430
  propValue = builders.callExpression(builders.identifier('normalizeClass'), [propValue]);
1440
1431
  }
1432
+ else if (nameLower === 'tabindex') {
1433
+ cxt.import('normalizeTabIndex');
1434
+ propValue = builders.callExpression(builders.identifier('normalizeTabIndex'), [propValue]);
1435
+ }
1441
1436
  return builders.property('init', key, propValue);
1442
1437
  }
1443
1438
  throw new Error(`Unimplemented child attr IR node type: ${value.type}`);
@@ -1794,13 +1789,13 @@ is.statement}
1794
1789
  yield* generateMarkup(
1795
1790
  tagName,
1796
1791
  childProps,
1797
- childAttrs,
1798
- shadowSlottedContent,
1799
- lightSlottedContentMap,
1800
- scopedSlottedContentMap,
1792
+ childAttrs,
1801
1793
  instance,
1802
1794
  scopeToken,
1803
- contextfulParent
1795
+ contextfulParent,
1796
+ shadowSlottedContent,
1797
+ lightSlottedContentMap,
1798
+ scopedSlottedContentMap
1804
1799
  );
1805
1800
  } else {
1806
1801
  yield \`<\${tagName}>\`;
@@ -1860,12 +1855,12 @@ is.statement}
1860
1855
  null,
1861
1856
  childProps,
1862
1857
  childAttrs,
1863
- shadowSlottedContent,
1864
- lightSlottedContentMap,
1865
- scopedSlottedContentMap,
1866
1858
  instance,
1867
1859
  scopeToken,
1868
- contextfulParent
1860
+ contextfulParent,
1861
+ shadowSlottedContent,
1862
+ lightSlottedContentMap,
1863
+ scopedSlottedContentMap
1869
1864
  );
1870
1865
  }
1871
1866
  `);
@@ -2566,5 +2561,5 @@ function compileTemplateForSSR(src, filename, options, mode = DEFAULT_SSR_MODE)
2566
2561
  }
2567
2562
 
2568
2563
  export { compileComponentForSSR, compileTemplateForSSR };
2569
- /** version: 8.14.0 */
2564
+ /** version: 8.15.0 */
2570
2565
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
5
5
  ],
6
6
  "name": "@lwc/ssr-compiler",
7
- "version": "8.14.0",
7
+ "version": "8.15.0",
8
8
  "description": "Compile component for use during server-side rendering",
9
9
  "keywords": [
10
10
  "compiler",
@@ -49,9 +49,9 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@babel/types": "7.26.9",
52
- "@lwc/shared": "8.14.0",
53
- "@lwc/errors": "8.14.0",
54
- "@lwc/template-compiler": "8.14.0",
52
+ "@lwc/shared": "8.15.0",
53
+ "@lwc/errors": "8.15.0",
54
+ "@lwc/template-compiler": "8.15.0",
55
55
  "acorn": "8.14.0",
56
56
  "astring": "^1.9.0",
57
57
  "estree-toolkit": "^1.7.8",
@@ -59,7 +59,7 @@
59
59
  "meriyah": "^5.0.0"
60
60
  },
61
61
  "devDependencies": {
62
- "@lwc/babel-plugin-component": "8.14.0",
62
+ "@lwc/babel-plugin-component": "8.15.0",
63
63
  "@types/estree": "^1.0.6"
64
64
  }
65
65
  }