@lwc/babel-plugin-component 8.24.0 → 8.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import type { types, NodePath } from '@babel/core';
2
2
  import type { DecoratorMeta } from '../index';
3
- import type { BabelTypes } from '../../types';
3
+ import type { BabelTypes, LwcBabelPluginPass } from '../../types';
4
4
  import type { ClassBodyItem } from '../types';
5
- export default function transform(t: BabelTypes, decoratorMetas: DecoratorMeta[], classBodyItems: NodePath<ClassBodyItem>[]): types.ObjectProperty[];
5
+ export default function transform(t: BabelTypes, decoratorMetas: DecoratorMeta[], classBodyItems: NodePath<ClassBodyItem>[], state: LwcBabelPluginPass): types.ObjectProperty[];
6
6
  //# sourceMappingURL=transform.d.ts.map
@@ -7,7 +7,7 @@ export interface DecoratorMeta {
7
7
  name: LwcDecoratorName;
8
8
  propertyName: string;
9
9
  path: NodePath<types.Decorator>;
10
- decoratedNodeType: DecoratorType;
10
+ decoratedNodeType: DecoratorType | null;
11
11
  type?: DecoratorType;
12
12
  }
13
13
  declare function validateImportedLwcDecoratorUsage(engineImportSpecifiers: ImportSpecifier[], state: LwcBabelPluginPass): void;
@@ -1,5 +1,5 @@
1
1
  import type { types } from '@babel/core';
2
2
  import type { DecoratorMeta } from '../index';
3
- import type { BabelTypes } from '../../types';
4
- export default function transform(t: BabelTypes, decoratorMetas: DecoratorMeta[]): types.ObjectProperty[];
3
+ import type { BabelTypes, LwcBabelPluginPass } from '../../types';
4
+ export default function transform(t: BabelTypes, decoratorMetas: DecoratorMeta[], state: LwcBabelPluginPass): types.ObjectProperty[];
5
5
  //# sourceMappingURL=transform.d.ts.map
package/dist/index.cjs.js CHANGED
@@ -229,9 +229,36 @@ function generateError(source, { errorInfo, messageArgs }, state) {
229
229
  error.lwcCode = errorInfo && errorInfo.code;
230
230
  return error;
231
231
  }
232
+ function collectError(source, { errorInfo, messageArgs }, state) {
233
+ const diagnostic = errors.generateCompilerDiagnostic(errorInfo, {
234
+ messageArgs,
235
+ origin: {
236
+ filename: state.filename,
237
+ location: normalizeLocation(source) ?? undefined,
238
+ },
239
+ }, true);
240
+ if (diagnostic.level === errors.DiagnosticLevel.Fatal) {
241
+ throw generateError(source, { errorInfo, messageArgs }, state);
242
+ }
243
+ if (!state.file.metadata.lwcErrors) {
244
+ state.file.metadata.lwcErrors = [];
245
+ }
246
+ state.file.metadata.lwcErrors.push(diagnostic);
247
+ }
248
+ function handleError(source, decoratorErrorOpts, state) {
249
+ if (isErrorRecoveryMode(state)) {
250
+ collectError(source, decoratorErrorOpts, state);
251
+ }
252
+ else {
253
+ throw generateError(source, decoratorErrorOpts, state);
254
+ }
255
+ }
232
256
  function incrementMetricCounter(metric, state) {
233
257
  state.opts.instrumentation?.incrementCounter(metric);
234
258
  }
259
+ function isErrorRecoveryMode(state) {
260
+ return state.file.opts?.parserOpts?.errorRecovery ?? false;
261
+ }
235
262
 
236
263
  /*
237
264
  * Copyright (c) 2023, salesforce.com, inc.
@@ -255,7 +282,7 @@ function validateConflict(path, decorators, state) {
255
282
  const isPublicFieldTracked = decorators.some((decorator) => decorator.name === TRACK_DECORATOR$2 &&
256
283
  decorator.path.parentPath.node === path.parentPath.node);
257
284
  if (isPublicFieldTracked) {
258
- throw generateError(path, {
285
+ handleError(path, {
259
286
  errorInfo: errors.DecoratorErrors.API_AND_TRACK_DECORATOR_CONFLICT,
260
287
  }, state);
261
288
  }
@@ -266,45 +293,45 @@ function isBooleanPropDefaultTrue(property) {
266
293
  }
267
294
  function validatePropertyValue(property, state) {
268
295
  if (isBooleanPropDefaultTrue(property)) {
269
- throw generateError(property, {
296
+ handleError(property, {
270
297
  errorInfo: errors.DecoratorErrors.INVALID_BOOLEAN_PUBLIC_PROPERTY,
271
298
  }, state);
272
299
  }
273
300
  }
274
301
  function validatePropertyName(property, state) {
275
302
  if (property.node.computed) {
276
- throw generateError(property, {
303
+ handleError(property, {
277
304
  errorInfo: errors.DecoratorErrors.PROPERTY_CANNOT_BE_COMPUTED,
278
305
  }, state);
279
306
  }
280
307
  const propertyName = property.get('key.name').node;
281
308
  if (propertyName === 'part') {
282
- throw generateError(property, {
309
+ handleError(property, {
283
310
  errorInfo: errors.DecoratorErrors.PROPERTY_NAME_PART_IS_RESERVED,
284
311
  messageArgs: [propertyName],
285
312
  }, state);
286
313
  }
287
314
  else if (propertyName.startsWith('on')) {
288
- throw generateError(property, {
315
+ handleError(property, {
289
316
  errorInfo: errors.DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_ON,
290
317
  messageArgs: [propertyName],
291
318
  }, state);
292
319
  }
293
320
  else if (propertyName.startsWith('data') && propertyName.length > 4) {
294
- throw generateError(property, {
321
+ handleError(property, {
295
322
  errorInfo: errors.DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_DATA,
296
323
  messageArgs: [propertyName],
297
324
  }, state);
298
325
  }
299
326
  else if (shared.DISALLOWED_PROP_SET.has(propertyName)) {
300
- throw generateError(property, {
327
+ handleError(property, {
301
328
  errorInfo: errors.DecoratorErrors.PROPERTY_NAME_IS_RESERVED,
302
329
  messageArgs: [propertyName],
303
330
  }, state);
304
331
  }
305
332
  else if (shared.AMBIGUOUS_PROP_SET.has(propertyName)) {
306
333
  const camelCased = shared.AMBIGUOUS_PROP_SET.get(propertyName);
307
- throw generateError(property, {
334
+ handleError(property, {
308
335
  errorInfo: errors.DecoratorErrors.PROPERTY_NAME_IS_AMBIGUOUS,
309
336
  messageArgs: [propertyName, camelCased],
310
337
  }, state);
@@ -322,7 +349,7 @@ function validateSingleApiDecoratorOnSetterGetterPair(decorators, state) {
322
349
  const methodPath = path.parentPath;
323
350
  const methodName = methodPath.get('key.name').node;
324
351
  if (visitedMethods.has(methodName)) {
325
- throw generateError(methodPath, {
352
+ handleError(methodPath, {
326
353
  errorInfo: errors.DecoratorErrors.SINGLE_DECORATOR_ON_SETTER_GETTER_PAIR,
327
354
  messageArgs: [methodName],
328
355
  }, state);
@@ -348,7 +375,7 @@ function validateUniqueness(decorators, state) {
348
375
  compareType === DECORATOR_TYPES.SETTER) ||
349
376
  (currentType === DECORATOR_TYPES.SETTER && compareType === DECORATOR_TYPES.GETTER);
350
377
  if (haveSameName && isDifferentProperty && !isGetterSetterPair) {
351
- throw generateError(comparePath, {
378
+ handleError(comparePath, {
352
379
  errorInfo: errors.DecoratorErrors.DUPLICATE_API_PROPERTY,
353
380
  messageArgs: [currentPropertyName],
354
381
  }, state);
@@ -407,8 +434,12 @@ function getSiblingGetSetPairType(propertyName, type, classBodyItems) {
407
434
  return siblingKind === 'get' ? DECORATOR_TYPES.GETTER : DECORATOR_TYPES.SETTER;
408
435
  }
409
436
  }
410
- function computePublicPropsConfig(publicPropertyMetas, classBodyItems) {
437
+ function computePublicPropsConfig(publicPropertyMetas, classBodyItems, state) {
411
438
  return publicPropertyMetas.reduce((acc, { propertyName, decoratedNodeType }) => {
439
+ // This should never happen as we filter null in class visitor and
440
+ // collect appropriate errors in errorRecoveryMode || throw otherwise
441
+ if (isErrorRecoveryMode(state) && !decoratedNodeType)
442
+ return acc;
412
443
  if (!(propertyName in acc)) {
413
444
  acc[propertyName] = {};
414
445
  }
@@ -425,12 +456,12 @@ function computePublicPropsConfig(publicPropertyMetas, classBodyItems) {
425
456
  return acc;
426
457
  }, {});
427
458
  }
428
- function transform$2(t, decoratorMetas, classBodyItems) {
459
+ function transform$2(t, decoratorMetas, classBodyItems, state) {
429
460
  const objectProperties = [];
430
461
  const apiDecoratorMetas = decoratorMetas.filter(isApiDecorator);
431
462
  const publicPropertyMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType !== DECORATOR_TYPES.METHOD);
432
463
  if (publicPropertyMetas.length) {
433
- const propsConfig = computePublicPropsConfig(publicPropertyMetas, classBodyItems);
464
+ const propsConfig = computePublicPropsConfig(publicPropertyMetas, classBodyItems, state);
434
465
  objectProperties.push(t.objectProperty(t.identifier(PUBLIC_PROPS), t.valueToNode(propsConfig)));
435
466
  }
436
467
  const publicMethodMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType === DECORATOR_TYPES.METHOD);
@@ -474,9 +505,10 @@ function isWireDecorator(decorator) {
474
505
  const { TRACK_DECORATOR: TRACK_DECORATOR$1, WIRE_DECORATOR: WIRE_DECORATOR$1, API_DECORATOR } = LWC_PACKAGE_EXPORTS;
475
506
  function validateWireId(id, path, state) {
476
507
  if (!id) {
477
- throw generateError(path, {
508
+ handleError(path, {
478
509
  errorInfo: errors.DecoratorErrors.ADAPTER_SHOULD_BE_FIRST_PARAMETER,
479
510
  }, state);
511
+ return;
480
512
  }
481
513
  let adapter;
482
514
  if (id.isIdentifier()) {
@@ -486,9 +518,10 @@ function validateWireId(id, path, state) {
486
518
  else if (id.isMemberExpression()) {
487
519
  if (id.node.computed) {
488
520
  // @wire(adapter[computed])
489
- throw generateError(id, {
521
+ handleError(id, {
490
522
  errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS,
491
523
  }, state);
524
+ return;
492
525
  }
493
526
  const object = id.get('object');
494
527
  if (object.isIdentifier()) {
@@ -497,73 +530,79 @@ function validateWireId(id, path, state) {
497
530
  }
498
531
  else {
499
532
  // @wire(adapter.foo.bar)
500
- throw generateError(id, {
533
+ handleError(id, {
501
534
  errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS,
502
535
  }, state);
536
+ return;
503
537
  }
504
538
  }
505
539
  else {
506
540
  // @wire(1), @wire('adapter'), @wire(function adapter() {}), etc.
507
- throw generateError(id, {
541
+ handleError(id, {
508
542
  errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
509
543
  }, state);
544
+ return;
510
545
  }
511
546
  // Ensure wire adapter is imported (check for member expression or identifier)
512
547
  const adapterBinding = path.scope.getBinding(adapter.node.name);
513
548
  if (!adapterBinding) {
514
- throw generateError(id, {
549
+ handleError(id, {
515
550
  errorInfo: errors.DecoratorErrors.WIRE_ADAPTER_SHOULD_BE_IMPORTED,
516
551
  messageArgs: [adapter.node.name],
517
552
  }, state);
553
+ return;
518
554
  }
519
555
  // ensure wire adapter is a first parameter
520
556
  if (!adapterBinding.path.isImportSpecifier() &&
521
557
  !adapterBinding.path.isImportDefaultSpecifier()) {
522
- throw generateError(id, {
558
+ handleError(id, {
523
559
  errorInfo: errors.DecoratorErrors.IMPORTED_FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
524
560
  }, state);
525
561
  }
526
562
  }
527
563
  function validateWireConfig(config, path, state) {
528
564
  if (!config.isObjectExpression()) {
529
- throw generateError(config, {
565
+ handleError(config, {
530
566
  errorInfo: errors.DecoratorErrors.CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER,
531
567
  }, state);
532
568
  }
533
- for (const prop of config.get('properties')) {
534
- // Only validate {[computed]: true} object properties; {static: true} props are all valid
535
- // and we ignore {...spreads} and {methods(){}}
536
- if (!prop.isObjectProperty() || !prop.node.computed)
537
- continue;
538
- const key = prop.get('key');
539
- if (key.isIdentifier()) {
540
- // Only allow identifiers that originated from a `const` declaration
541
- const binding = key.scope.getBinding(key.node.name);
542
- // TODO [#3956]: Investigate allowing imported constants
543
- if (binding?.kind === 'const')
544
- continue;
545
- // By default, the identifier `undefined` has no binding (when it's actually undefined),
546
- // but has a binding if it's used as a variable (e.g. `let undefined = "don't do this"`)
547
- if (key.node.name === 'undefined' && !binding)
569
+ const properties = config.get('properties');
570
+ if (Array.isArray(properties)) {
571
+ for (const prop of properties) {
572
+ // Only validate {[computed]: true} object properties; {static: true} props are all valid
573
+ // and we ignore {...spreads} and {methods(){}}
574
+ if (!prop.isObjectProperty() || !prop.node.computed)
548
575
  continue;
549
- }
550
- else if (key.isLiteral()) {
551
- // A literal can be a regexp, template literal, or primitive; only allow primitives
552
- if (key.isTemplateLiteral()) {
553
- // A template literal is not guaranteed to always result in the same value
554
- // (e.g. `${Math.random()}`), so we disallow them entirely.
555
- // TODO [#3956]: Investigate allowing template literals
556
- throw generateError(key, {
557
- errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL,
558
- }, state);
576
+ const key = prop.get('key');
577
+ if (key.isIdentifier()) {
578
+ // Only allow identifiers that originated from a `const` declaration
579
+ const binding = key.scope.getBinding(key.node.name);
580
+ // TODO [#3956]: Investigate allowing imported constants
581
+ if (binding?.kind === 'const')
582
+ continue;
583
+ // By default, the identifier `undefined` has no binding (when it's actually undefined),
584
+ // but has a binding if it's used as a variable (e.g. `let undefined = "don't do this"`)
585
+ if (key.node.name === 'undefined' && !binding)
586
+ continue;
559
587
  }
560
- else if (!key.isRegExpLiteral()) {
561
- continue;
588
+ else if (key.isLiteral()) {
589
+ // A literal can be a regexp, template literal, or primitive; only allow primitives
590
+ if (key.isTemplateLiteral()) {
591
+ // A template literal is not guaranteed to always result in the same value
592
+ // (e.g. `${Math.random()}`), so we disallow them entirely.
593
+ // TODO [#3956]: Investigate allowing template literals
594
+ handleError(key, {
595
+ errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL,
596
+ }, state);
597
+ }
598
+ else if (!key.isRegExpLiteral()) {
599
+ continue;
600
+ }
562
601
  }
602
+ handleError(key, {
603
+ errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL,
604
+ }, state);
563
605
  }
564
- throw generateError(key, {
565
- errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL,
566
- }, state);
567
606
  }
568
607
  }
569
608
  function validateWireParameters(path, state) {
@@ -585,13 +624,13 @@ function validateUsageWithOtherDecorators(path, decorators, state) {
585
624
  if (path !== decorator.path &&
586
625
  decorator.name === WIRE_DECORATOR$1 &&
587
626
  decorator.path.parentPath.node === path.parentPath.node) {
588
- throw generateError(path, {
627
+ handleError(path, {
589
628
  errorInfo: errors.DecoratorErrors.ONE_WIRE_DECORATOR_ALLOWED,
590
629
  }, state);
591
630
  }
592
631
  if ((decorator.name === API_DECORATOR || decorator.name === TRACK_DECORATOR$1) &&
593
632
  decorator.path.parentPath.node === path.parentPath.node) {
594
- throw generateError(path, {
633
+ handleError(path, {
595
634
  errorInfo: errors.DecoratorErrors.CONFLICT_WITH_ANOTHER_DECORATOR,
596
635
  messageArgs: [decorator.name],
597
636
  }, state);
@@ -617,15 +656,26 @@ function isObservedProperty(configProperty) {
617
656
  const propertyValue = configProperty.get('value');
618
657
  return (propertyValue.isStringLiteral() && propertyValue.node.value.startsWith(WIRE_PARAM_PREFIX));
619
658
  }
620
- function getWiredStatic(wireConfig) {
621
- return wireConfig
622
- .get('properties')
659
+ function getWiredStatic(wireConfig, state) {
660
+ const properties = wireConfig.get('properties');
661
+ // Should only occurs in error recovery mode when config validation has already failed
662
+ // Skip processing since the error has been logged upstream
663
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
664
+ return [];
665
+ }
666
+ return properties
623
667
  .filter((property) => !isObservedProperty(property))
624
668
  .map((path) => path.node);
625
669
  }
626
- function getWiredParams(t, wireConfig) {
627
- return wireConfig
628
- .get('properties')
670
+ function getWiredParams(t, wireConfig, state) {
671
+ const properties = wireConfig.get('properties');
672
+ // Should only occur in error recovery mode when config validation has already failed
673
+ // Skip processing since the error has been logged upstream
674
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
675
+ // In error recovery mode, return empty array instead of crashing
676
+ return [];
677
+ }
678
+ return properties
629
679
  .filter((property) => isObservedProperty(property))
630
680
  .map((path) => {
631
681
  // Need to clone deep the observed property to remove the param prefix
@@ -755,7 +805,7 @@ const scopedReferenceLookup = (scope) => (name) => {
755
805
  value,
756
806
  };
757
807
  };
758
- function transform$1(t, decoratorMetas) {
808
+ function transform$1(t, decoratorMetas, state) {
759
809
  const objectProperties = [];
760
810
  const wiredValues = decoratorMetas.filter(isWireDecorator).map(({ path }) => {
761
811
  const [id, config] = path.get('expression.arguments');
@@ -768,8 +818,8 @@ function transform$1(t, decoratorMetas) {
768
818
  isClassMethod,
769
819
  };
770
820
  if (config) {
771
- wiredValue.static = getWiredStatic(config);
772
- wiredValue.params = getWiredParams(t, config);
821
+ wiredValue.static = getWiredStatic(config, state);
822
+ wiredValue.params = getWiredParams(t, config, state);
773
823
  }
774
824
  const referenceLookup = scopedReferenceLookup(path.scope);
775
825
  const isMemberExpression = id.isMemberExpression();
@@ -818,7 +868,7 @@ function isTrackDecorator(decorator) {
818
868
  function validate$1(decorators, state) {
819
869
  decorators.filter(isTrackDecorator).forEach(({ path }) => {
820
870
  if (!path.parentPath.isClassProperty()) {
821
- throw generateError(path, {
871
+ handleError(path, {
822
872
  errorInfo: errors.DecoratorErrors.TRACK_ONLY_ALLOWED_ON_CLASS_PROPERTIES,
823
873
  }, state);
824
874
  }
@@ -879,11 +929,14 @@ function getDecoratedNodeType(decoratorPath, state) {
879
929
  else if (propertyOrMethod.isClassProperty()) {
880
930
  return DECORATOR_TYPES.PROPERTY;
881
931
  }
882
- else {
883
- throw generateError(propertyOrMethod, {
884
- errorInfo: errors.DecoratorErrors.INVALID_DECORATOR_TYPE,
885
- }, state);
886
- }
932
+ handleError(propertyOrMethod, {
933
+ errorInfo: errors.DecoratorErrors.INVALID_DECORATOR_TYPE,
934
+ }, state);
935
+ // We should only be here when we are running in errorRecoveryMode
936
+ // otherwise, the handleError method should already "throw"
937
+ // since, we couldn't determine a node type, we will return a null here
938
+ // so we can filter out this node and attempt to proceed with the compilation process
939
+ return null;
887
940
  }
888
941
  function validateImportedLwcDecoratorUsage(engineImportSpecifiers, state) {
889
942
  engineImportSpecifiers
@@ -906,14 +959,15 @@ function validateImportedLwcDecoratorUsage(engineImportSpecifiers, state) {
906
959
  ? reference.parentPath
907
960
  : reference.parentPath.parentPath;
908
961
  if (!decorator.isDecorator()) {
909
- throw generateError(decorator, {
962
+ handleError(decorator, {
910
963
  errorInfo: errors.DecoratorErrors.IS_NOT_DECORATOR,
911
964
  messageArgs: [name],
912
965
  }, state);
913
966
  }
914
967
  const propertyOrMethod = decorator.parentPath;
915
- if (!propertyOrMethod.isClassProperty() && !propertyOrMethod.isClassMethod()) {
916
- throw generateError(propertyOrMethod, {
968
+ if (propertyOrMethod === null ||
969
+ (!propertyOrMethod.isClassProperty() && !propertyOrMethod.isClassMethod())) {
970
+ handleError(propertyOrMethod === null ? decorator : propertyOrMethod, {
917
971
  errorInfo: errors.DecoratorErrors.IS_NOT_CLASS_PROPERTY_OR_CLASS_METHOD,
918
972
  messageArgs: [name],
919
973
  }, state);
@@ -933,7 +987,7 @@ function validate(decorators, state) {
933
987
  for (const { name, path } of decorators) {
934
988
  const binding = path.scope.getBinding(name);
935
989
  if (binding === undefined || !isImportedFromLwcSource(binding.path)) {
936
- throw generateInvalidDecoratorError(path, state);
990
+ handleInvalidDecoratorError(path, state);
937
991
  }
938
992
  }
939
993
  DECORATOR_TRANSFORMS.forEach(({ validate }) => validate(decorators, state));
@@ -953,7 +1007,7 @@ function removeImportedDecoratorSpecifiers(engineImportSpecifiers) {
953
1007
  }
954
1008
  });
955
1009
  }
956
- function generateInvalidDecoratorError(path, state) {
1010
+ function handleInvalidDecoratorError(path, state) {
957
1011
  const expressionPath = path.get('expression');
958
1012
  const { node } = path;
959
1013
  const { expression } = node;
@@ -965,13 +1019,13 @@ function generateInvalidDecoratorError(path, state) {
965
1019
  name = expression.callee.name;
966
1020
  }
967
1021
  if (name) {
968
- return generateError(path.parentPath, {
1022
+ handleError(path.parentPath, {
969
1023
  errorInfo: errors.DecoratorErrors.INVALID_DECORATOR_WITH_NAME,
970
1024
  messageArgs: [name, AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
971
1025
  }, state);
972
1026
  }
973
1027
  else {
974
- return generateError(path.parentPath, {
1028
+ handleError(path.parentPath, {
975
1029
  errorInfo: errors.DecoratorErrors.INVALID_DECORATOR,
976
1030
  messageArgs: [AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
977
1031
  }, state);
@@ -996,7 +1050,8 @@ function getDecoratorMetadata(decoratorPath, state) {
996
1050
  name = expressionPath.node.callee.name;
997
1051
  }
998
1052
  else {
999
- throw generateInvalidDecoratorError(decoratorPath, state);
1053
+ handleInvalidDecoratorError(decoratorPath, state);
1054
+ return null;
1000
1055
  }
1001
1056
  const propertyName = decoratorPath.parent.key.name;
1002
1057
  const decoratedNodeType = getDecoratedNodeType(decoratorPath, state);
@@ -1007,11 +1062,11 @@ function getDecoratorMetadata(decoratorPath, state) {
1007
1062
  decoratedNodeType,
1008
1063
  };
1009
1064
  }
1010
- function getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems) {
1065
+ function getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state) {
1011
1066
  const list = [
1012
- ...api.transform(t, decoratorMetas, classBodyItems),
1067
+ ...api.transform(t, decoratorMetas, classBodyItems, state),
1013
1068
  ...track.transform(t, decoratorMetas),
1014
- ...wire.transform(t, decoratorMetas),
1069
+ ...wire.transform(t, decoratorMetas, state),
1015
1070
  ];
1016
1071
  const fieldNames = classBodyItems
1017
1072
  .filter((field) => field.isClassProperty({ computed: false, static: false }))
@@ -1049,9 +1104,11 @@ function decorators({ types: t }) {
1049
1104
  return;
1050
1105
  }
1051
1106
  const decoratorPaths = collectDecoratorPaths(classBodyItems);
1052
- const decoratorMetas = decoratorPaths.map((path) => getDecoratorMetadata(path, state));
1107
+ const decoratorMetas = decoratorPaths
1108
+ .map((path) => getDecoratorMetadata(path, state))
1109
+ .filter((meta) => meta !== null);
1053
1110
  validate(decoratorMetas, state);
1054
- const metaPropertyList = getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems);
1111
+ const metaPropertyList = getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state);
1055
1112
  if (metaPropertyList.length === 0) {
1056
1113
  return;
1057
1114
  }
@@ -1142,7 +1199,7 @@ function getImportSource(path) {
1142
1199
  }
1143
1200
  function validateImport(sourcePath, state) {
1144
1201
  if (!sourcePath.isStringLiteral()) {
1145
- throw generateError(sourcePath, {
1202
+ handleError(sourcePath, {
1146
1203
  errorInfo: errors.LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT,
1147
1204
  messageArgs: [String(sourcePath)],
1148
1205
  }, state);
@@ -1289,5 +1346,5 @@ function LwcClassTransform(api) {
1289
1346
  }
1290
1347
 
1291
1348
  exports.default = LwcClassTransform;
1292
- /** version: 8.24.0 */
1349
+ /** version: 8.25.1 */
1293
1350
  //# sourceMappingURL=index.cjs.js.map
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { extname, basename } from 'path';
5
5
  import { addNamed, addDefault } from '@babel/helper-module-imports';
6
6
  import { getAPIVersionFromNumber, generateCustomElementTagName, DISALLOWED_PROP_SET, AMBIGUOUS_PROP_SET, isAPIFeatureEnabled, LWC_VERSION_COMMENT } from '@lwc/shared';
7
- import { generateErrorMessage, DecoratorErrors, CompilerMetrics, LWCClassErrors } from '@lwc/errors';
7
+ import { generateCompilerDiagnostic, DiagnosticLevel, generateErrorMessage, DecoratorErrors, CompilerMetrics, LWCClassErrors } from '@lwc/errors';
8
8
  import lineColumn from 'line-column';
9
9
 
10
10
  /*
@@ -225,9 +225,36 @@ function generateError(source, { errorInfo, messageArgs }, state) {
225
225
  error.lwcCode = errorInfo && errorInfo.code;
226
226
  return error;
227
227
  }
228
+ function collectError(source, { errorInfo, messageArgs }, state) {
229
+ const diagnostic = generateCompilerDiagnostic(errorInfo, {
230
+ messageArgs,
231
+ origin: {
232
+ filename: state.filename,
233
+ location: normalizeLocation(source) ?? undefined,
234
+ },
235
+ }, true);
236
+ if (diagnostic.level === DiagnosticLevel.Fatal) {
237
+ throw generateError(source, { errorInfo, messageArgs }, state);
238
+ }
239
+ if (!state.file.metadata.lwcErrors) {
240
+ state.file.metadata.lwcErrors = [];
241
+ }
242
+ state.file.metadata.lwcErrors.push(diagnostic);
243
+ }
244
+ function handleError(source, decoratorErrorOpts, state) {
245
+ if (isErrorRecoveryMode(state)) {
246
+ collectError(source, decoratorErrorOpts, state);
247
+ }
248
+ else {
249
+ throw generateError(source, decoratorErrorOpts, state);
250
+ }
251
+ }
228
252
  function incrementMetricCounter(metric, state) {
229
253
  state.opts.instrumentation?.incrementCounter(metric);
230
254
  }
255
+ function isErrorRecoveryMode(state) {
256
+ return state.file.opts?.parserOpts?.errorRecovery ?? false;
257
+ }
231
258
 
232
259
  /*
233
260
  * Copyright (c) 2023, salesforce.com, inc.
@@ -251,7 +278,7 @@ function validateConflict(path, decorators, state) {
251
278
  const isPublicFieldTracked = decorators.some((decorator) => decorator.name === TRACK_DECORATOR$2 &&
252
279
  decorator.path.parentPath.node === path.parentPath.node);
253
280
  if (isPublicFieldTracked) {
254
- throw generateError(path, {
281
+ handleError(path, {
255
282
  errorInfo: DecoratorErrors.API_AND_TRACK_DECORATOR_CONFLICT,
256
283
  }, state);
257
284
  }
@@ -262,45 +289,45 @@ function isBooleanPropDefaultTrue(property) {
262
289
  }
263
290
  function validatePropertyValue(property, state) {
264
291
  if (isBooleanPropDefaultTrue(property)) {
265
- throw generateError(property, {
292
+ handleError(property, {
266
293
  errorInfo: DecoratorErrors.INVALID_BOOLEAN_PUBLIC_PROPERTY,
267
294
  }, state);
268
295
  }
269
296
  }
270
297
  function validatePropertyName(property, state) {
271
298
  if (property.node.computed) {
272
- throw generateError(property, {
299
+ handleError(property, {
273
300
  errorInfo: DecoratorErrors.PROPERTY_CANNOT_BE_COMPUTED,
274
301
  }, state);
275
302
  }
276
303
  const propertyName = property.get('key.name').node;
277
304
  if (propertyName === 'part') {
278
- throw generateError(property, {
305
+ handleError(property, {
279
306
  errorInfo: DecoratorErrors.PROPERTY_NAME_PART_IS_RESERVED,
280
307
  messageArgs: [propertyName],
281
308
  }, state);
282
309
  }
283
310
  else if (propertyName.startsWith('on')) {
284
- throw generateError(property, {
311
+ handleError(property, {
285
312
  errorInfo: DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_ON,
286
313
  messageArgs: [propertyName],
287
314
  }, state);
288
315
  }
289
316
  else if (propertyName.startsWith('data') && propertyName.length > 4) {
290
- throw generateError(property, {
317
+ handleError(property, {
291
318
  errorInfo: DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_DATA,
292
319
  messageArgs: [propertyName],
293
320
  }, state);
294
321
  }
295
322
  else if (DISALLOWED_PROP_SET.has(propertyName)) {
296
- throw generateError(property, {
323
+ handleError(property, {
297
324
  errorInfo: DecoratorErrors.PROPERTY_NAME_IS_RESERVED,
298
325
  messageArgs: [propertyName],
299
326
  }, state);
300
327
  }
301
328
  else if (AMBIGUOUS_PROP_SET.has(propertyName)) {
302
329
  const camelCased = AMBIGUOUS_PROP_SET.get(propertyName);
303
- throw generateError(property, {
330
+ handleError(property, {
304
331
  errorInfo: DecoratorErrors.PROPERTY_NAME_IS_AMBIGUOUS,
305
332
  messageArgs: [propertyName, camelCased],
306
333
  }, state);
@@ -318,7 +345,7 @@ function validateSingleApiDecoratorOnSetterGetterPair(decorators, state) {
318
345
  const methodPath = path.parentPath;
319
346
  const methodName = methodPath.get('key.name').node;
320
347
  if (visitedMethods.has(methodName)) {
321
- throw generateError(methodPath, {
348
+ handleError(methodPath, {
322
349
  errorInfo: DecoratorErrors.SINGLE_DECORATOR_ON_SETTER_GETTER_PAIR,
323
350
  messageArgs: [methodName],
324
351
  }, state);
@@ -344,7 +371,7 @@ function validateUniqueness(decorators, state) {
344
371
  compareType === DECORATOR_TYPES.SETTER) ||
345
372
  (currentType === DECORATOR_TYPES.SETTER && compareType === DECORATOR_TYPES.GETTER);
346
373
  if (haveSameName && isDifferentProperty && !isGetterSetterPair) {
347
- throw generateError(comparePath, {
374
+ handleError(comparePath, {
348
375
  errorInfo: DecoratorErrors.DUPLICATE_API_PROPERTY,
349
376
  messageArgs: [currentPropertyName],
350
377
  }, state);
@@ -403,8 +430,12 @@ function getSiblingGetSetPairType(propertyName, type, classBodyItems) {
403
430
  return siblingKind === 'get' ? DECORATOR_TYPES.GETTER : DECORATOR_TYPES.SETTER;
404
431
  }
405
432
  }
406
- function computePublicPropsConfig(publicPropertyMetas, classBodyItems) {
433
+ function computePublicPropsConfig(publicPropertyMetas, classBodyItems, state) {
407
434
  return publicPropertyMetas.reduce((acc, { propertyName, decoratedNodeType }) => {
435
+ // This should never happen as we filter null in class visitor and
436
+ // collect appropriate errors in errorRecoveryMode || throw otherwise
437
+ if (isErrorRecoveryMode(state) && !decoratedNodeType)
438
+ return acc;
408
439
  if (!(propertyName in acc)) {
409
440
  acc[propertyName] = {};
410
441
  }
@@ -421,12 +452,12 @@ function computePublicPropsConfig(publicPropertyMetas, classBodyItems) {
421
452
  return acc;
422
453
  }, {});
423
454
  }
424
- function transform$2(t, decoratorMetas, classBodyItems) {
455
+ function transform$2(t, decoratorMetas, classBodyItems, state) {
425
456
  const objectProperties = [];
426
457
  const apiDecoratorMetas = decoratorMetas.filter(isApiDecorator);
427
458
  const publicPropertyMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType !== DECORATOR_TYPES.METHOD);
428
459
  if (publicPropertyMetas.length) {
429
- const propsConfig = computePublicPropsConfig(publicPropertyMetas, classBodyItems);
460
+ const propsConfig = computePublicPropsConfig(publicPropertyMetas, classBodyItems, state);
430
461
  objectProperties.push(t.objectProperty(t.identifier(PUBLIC_PROPS), t.valueToNode(propsConfig)));
431
462
  }
432
463
  const publicMethodMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType === DECORATOR_TYPES.METHOD);
@@ -470,9 +501,10 @@ function isWireDecorator(decorator) {
470
501
  const { TRACK_DECORATOR: TRACK_DECORATOR$1, WIRE_DECORATOR: WIRE_DECORATOR$1, API_DECORATOR } = LWC_PACKAGE_EXPORTS;
471
502
  function validateWireId(id, path, state) {
472
503
  if (!id) {
473
- throw generateError(path, {
504
+ handleError(path, {
474
505
  errorInfo: DecoratorErrors.ADAPTER_SHOULD_BE_FIRST_PARAMETER,
475
506
  }, state);
507
+ return;
476
508
  }
477
509
  let adapter;
478
510
  if (id.isIdentifier()) {
@@ -482,9 +514,10 @@ function validateWireId(id, path, state) {
482
514
  else if (id.isMemberExpression()) {
483
515
  if (id.node.computed) {
484
516
  // @wire(adapter[computed])
485
- throw generateError(id, {
517
+ handleError(id, {
486
518
  errorInfo: DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS,
487
519
  }, state);
520
+ return;
488
521
  }
489
522
  const object = id.get('object');
490
523
  if (object.isIdentifier()) {
@@ -493,73 +526,79 @@ function validateWireId(id, path, state) {
493
526
  }
494
527
  else {
495
528
  // @wire(adapter.foo.bar)
496
- throw generateError(id, {
529
+ handleError(id, {
497
530
  errorInfo: DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS,
498
531
  }, state);
532
+ return;
499
533
  }
500
534
  }
501
535
  else {
502
536
  // @wire(1), @wire('adapter'), @wire(function adapter() {}), etc.
503
- throw generateError(id, {
537
+ handleError(id, {
504
538
  errorInfo: DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
505
539
  }, state);
540
+ return;
506
541
  }
507
542
  // Ensure wire adapter is imported (check for member expression or identifier)
508
543
  const adapterBinding = path.scope.getBinding(adapter.node.name);
509
544
  if (!adapterBinding) {
510
- throw generateError(id, {
545
+ handleError(id, {
511
546
  errorInfo: DecoratorErrors.WIRE_ADAPTER_SHOULD_BE_IMPORTED,
512
547
  messageArgs: [adapter.node.name],
513
548
  }, state);
549
+ return;
514
550
  }
515
551
  // ensure wire adapter is a first parameter
516
552
  if (!adapterBinding.path.isImportSpecifier() &&
517
553
  !adapterBinding.path.isImportDefaultSpecifier()) {
518
- throw generateError(id, {
554
+ handleError(id, {
519
555
  errorInfo: DecoratorErrors.IMPORTED_FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
520
556
  }, state);
521
557
  }
522
558
  }
523
559
  function validateWireConfig(config, path, state) {
524
560
  if (!config.isObjectExpression()) {
525
- throw generateError(config, {
561
+ handleError(config, {
526
562
  errorInfo: DecoratorErrors.CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER,
527
563
  }, state);
528
564
  }
529
- for (const prop of config.get('properties')) {
530
- // Only validate {[computed]: true} object properties; {static: true} props are all valid
531
- // and we ignore {...spreads} and {methods(){}}
532
- if (!prop.isObjectProperty() || !prop.node.computed)
533
- continue;
534
- const key = prop.get('key');
535
- if (key.isIdentifier()) {
536
- // Only allow identifiers that originated from a `const` declaration
537
- const binding = key.scope.getBinding(key.node.name);
538
- // TODO [#3956]: Investigate allowing imported constants
539
- if (binding?.kind === 'const')
540
- continue;
541
- // By default, the identifier `undefined` has no binding (when it's actually undefined),
542
- // but has a binding if it's used as a variable (e.g. `let undefined = "don't do this"`)
543
- if (key.node.name === 'undefined' && !binding)
565
+ const properties = config.get('properties');
566
+ if (Array.isArray(properties)) {
567
+ for (const prop of properties) {
568
+ // Only validate {[computed]: true} object properties; {static: true} props are all valid
569
+ // and we ignore {...spreads} and {methods(){}}
570
+ if (!prop.isObjectProperty() || !prop.node.computed)
544
571
  continue;
545
- }
546
- else if (key.isLiteral()) {
547
- // A literal can be a regexp, template literal, or primitive; only allow primitives
548
- if (key.isTemplateLiteral()) {
549
- // A template literal is not guaranteed to always result in the same value
550
- // (e.g. `${Math.random()}`), so we disallow them entirely.
551
- // TODO [#3956]: Investigate allowing template literals
552
- throw generateError(key, {
553
- errorInfo: DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL,
554
- }, state);
572
+ const key = prop.get('key');
573
+ if (key.isIdentifier()) {
574
+ // Only allow identifiers that originated from a `const` declaration
575
+ const binding = key.scope.getBinding(key.node.name);
576
+ // TODO [#3956]: Investigate allowing imported constants
577
+ if (binding?.kind === 'const')
578
+ continue;
579
+ // By default, the identifier `undefined` has no binding (when it's actually undefined),
580
+ // but has a binding if it's used as a variable (e.g. `let undefined = "don't do this"`)
581
+ if (key.node.name === 'undefined' && !binding)
582
+ continue;
555
583
  }
556
- else if (!key.isRegExpLiteral()) {
557
- continue;
584
+ else if (key.isLiteral()) {
585
+ // A literal can be a regexp, template literal, or primitive; only allow primitives
586
+ if (key.isTemplateLiteral()) {
587
+ // A template literal is not guaranteed to always result in the same value
588
+ // (e.g. `${Math.random()}`), so we disallow them entirely.
589
+ // TODO [#3956]: Investigate allowing template literals
590
+ handleError(key, {
591
+ errorInfo: DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL,
592
+ }, state);
593
+ }
594
+ else if (!key.isRegExpLiteral()) {
595
+ continue;
596
+ }
558
597
  }
598
+ handleError(key, {
599
+ errorInfo: DecoratorErrors.COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL,
600
+ }, state);
559
601
  }
560
- throw generateError(key, {
561
- errorInfo: DecoratorErrors.COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL,
562
- }, state);
563
602
  }
564
603
  }
565
604
  function validateWireParameters(path, state) {
@@ -581,13 +620,13 @@ function validateUsageWithOtherDecorators(path, decorators, state) {
581
620
  if (path !== decorator.path &&
582
621
  decorator.name === WIRE_DECORATOR$1 &&
583
622
  decorator.path.parentPath.node === path.parentPath.node) {
584
- throw generateError(path, {
623
+ handleError(path, {
585
624
  errorInfo: DecoratorErrors.ONE_WIRE_DECORATOR_ALLOWED,
586
625
  }, state);
587
626
  }
588
627
  if ((decorator.name === API_DECORATOR || decorator.name === TRACK_DECORATOR$1) &&
589
628
  decorator.path.parentPath.node === path.parentPath.node) {
590
- throw generateError(path, {
629
+ handleError(path, {
591
630
  errorInfo: DecoratorErrors.CONFLICT_WITH_ANOTHER_DECORATOR,
592
631
  messageArgs: [decorator.name],
593
632
  }, state);
@@ -613,15 +652,26 @@ function isObservedProperty(configProperty) {
613
652
  const propertyValue = configProperty.get('value');
614
653
  return (propertyValue.isStringLiteral() && propertyValue.node.value.startsWith(WIRE_PARAM_PREFIX));
615
654
  }
616
- function getWiredStatic(wireConfig) {
617
- return wireConfig
618
- .get('properties')
655
+ function getWiredStatic(wireConfig, state) {
656
+ const properties = wireConfig.get('properties');
657
+ // Should only occurs in error recovery mode when config validation has already failed
658
+ // Skip processing since the error has been logged upstream
659
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
660
+ return [];
661
+ }
662
+ return properties
619
663
  .filter((property) => !isObservedProperty(property))
620
664
  .map((path) => path.node);
621
665
  }
622
- function getWiredParams(t, wireConfig) {
623
- return wireConfig
624
- .get('properties')
666
+ function getWiredParams(t, wireConfig, state) {
667
+ const properties = wireConfig.get('properties');
668
+ // Should only occur in error recovery mode when config validation has already failed
669
+ // Skip processing since the error has been logged upstream
670
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
671
+ // In error recovery mode, return empty array instead of crashing
672
+ return [];
673
+ }
674
+ return properties
625
675
  .filter((property) => isObservedProperty(property))
626
676
  .map((path) => {
627
677
  // Need to clone deep the observed property to remove the param prefix
@@ -751,7 +801,7 @@ const scopedReferenceLookup = (scope) => (name) => {
751
801
  value,
752
802
  };
753
803
  };
754
- function transform$1(t, decoratorMetas) {
804
+ function transform$1(t, decoratorMetas, state) {
755
805
  const objectProperties = [];
756
806
  const wiredValues = decoratorMetas.filter(isWireDecorator).map(({ path }) => {
757
807
  const [id, config] = path.get('expression.arguments');
@@ -764,8 +814,8 @@ function transform$1(t, decoratorMetas) {
764
814
  isClassMethod,
765
815
  };
766
816
  if (config) {
767
- wiredValue.static = getWiredStatic(config);
768
- wiredValue.params = getWiredParams(t, config);
817
+ wiredValue.static = getWiredStatic(config, state);
818
+ wiredValue.params = getWiredParams(t, config, state);
769
819
  }
770
820
  const referenceLookup = scopedReferenceLookup(path.scope);
771
821
  const isMemberExpression = id.isMemberExpression();
@@ -814,7 +864,7 @@ function isTrackDecorator(decorator) {
814
864
  function validate$1(decorators, state) {
815
865
  decorators.filter(isTrackDecorator).forEach(({ path }) => {
816
866
  if (!path.parentPath.isClassProperty()) {
817
- throw generateError(path, {
867
+ handleError(path, {
818
868
  errorInfo: DecoratorErrors.TRACK_ONLY_ALLOWED_ON_CLASS_PROPERTIES,
819
869
  }, state);
820
870
  }
@@ -875,11 +925,14 @@ function getDecoratedNodeType(decoratorPath, state) {
875
925
  else if (propertyOrMethod.isClassProperty()) {
876
926
  return DECORATOR_TYPES.PROPERTY;
877
927
  }
878
- else {
879
- throw generateError(propertyOrMethod, {
880
- errorInfo: DecoratorErrors.INVALID_DECORATOR_TYPE,
881
- }, state);
882
- }
928
+ handleError(propertyOrMethod, {
929
+ errorInfo: DecoratorErrors.INVALID_DECORATOR_TYPE,
930
+ }, state);
931
+ // We should only be here when we are running in errorRecoveryMode
932
+ // otherwise, the handleError method should already "throw"
933
+ // since, we couldn't determine a node type, we will return a null here
934
+ // so we can filter out this node and attempt to proceed with the compilation process
935
+ return null;
883
936
  }
884
937
  function validateImportedLwcDecoratorUsage(engineImportSpecifiers, state) {
885
938
  engineImportSpecifiers
@@ -902,14 +955,15 @@ function validateImportedLwcDecoratorUsage(engineImportSpecifiers, state) {
902
955
  ? reference.parentPath
903
956
  : reference.parentPath.parentPath;
904
957
  if (!decorator.isDecorator()) {
905
- throw generateError(decorator, {
958
+ handleError(decorator, {
906
959
  errorInfo: DecoratorErrors.IS_NOT_DECORATOR,
907
960
  messageArgs: [name],
908
961
  }, state);
909
962
  }
910
963
  const propertyOrMethod = decorator.parentPath;
911
- if (!propertyOrMethod.isClassProperty() && !propertyOrMethod.isClassMethod()) {
912
- throw generateError(propertyOrMethod, {
964
+ if (propertyOrMethod === null ||
965
+ (!propertyOrMethod.isClassProperty() && !propertyOrMethod.isClassMethod())) {
966
+ handleError(propertyOrMethod === null ? decorator : propertyOrMethod, {
913
967
  errorInfo: DecoratorErrors.IS_NOT_CLASS_PROPERTY_OR_CLASS_METHOD,
914
968
  messageArgs: [name],
915
969
  }, state);
@@ -929,7 +983,7 @@ function validate(decorators, state) {
929
983
  for (const { name, path } of decorators) {
930
984
  const binding = path.scope.getBinding(name);
931
985
  if (binding === undefined || !isImportedFromLwcSource(binding.path)) {
932
- throw generateInvalidDecoratorError(path, state);
986
+ handleInvalidDecoratorError(path, state);
933
987
  }
934
988
  }
935
989
  DECORATOR_TRANSFORMS.forEach(({ validate }) => validate(decorators, state));
@@ -949,7 +1003,7 @@ function removeImportedDecoratorSpecifiers(engineImportSpecifiers) {
949
1003
  }
950
1004
  });
951
1005
  }
952
- function generateInvalidDecoratorError(path, state) {
1006
+ function handleInvalidDecoratorError(path, state) {
953
1007
  const expressionPath = path.get('expression');
954
1008
  const { node } = path;
955
1009
  const { expression } = node;
@@ -961,13 +1015,13 @@ function generateInvalidDecoratorError(path, state) {
961
1015
  name = expression.callee.name;
962
1016
  }
963
1017
  if (name) {
964
- return generateError(path.parentPath, {
1018
+ handleError(path.parentPath, {
965
1019
  errorInfo: DecoratorErrors.INVALID_DECORATOR_WITH_NAME,
966
1020
  messageArgs: [name, AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
967
1021
  }, state);
968
1022
  }
969
1023
  else {
970
- return generateError(path.parentPath, {
1024
+ handleError(path.parentPath, {
971
1025
  errorInfo: DecoratorErrors.INVALID_DECORATOR,
972
1026
  messageArgs: [AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
973
1027
  }, state);
@@ -992,7 +1046,8 @@ function getDecoratorMetadata(decoratorPath, state) {
992
1046
  name = expressionPath.node.callee.name;
993
1047
  }
994
1048
  else {
995
- throw generateInvalidDecoratorError(decoratorPath, state);
1049
+ handleInvalidDecoratorError(decoratorPath, state);
1050
+ return null;
996
1051
  }
997
1052
  const propertyName = decoratorPath.parent.key.name;
998
1053
  const decoratedNodeType = getDecoratedNodeType(decoratorPath, state);
@@ -1003,11 +1058,11 @@ function getDecoratorMetadata(decoratorPath, state) {
1003
1058
  decoratedNodeType,
1004
1059
  };
1005
1060
  }
1006
- function getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems) {
1061
+ function getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state) {
1007
1062
  const list = [
1008
- ...api.transform(t, decoratorMetas, classBodyItems),
1063
+ ...api.transform(t, decoratorMetas, classBodyItems, state),
1009
1064
  ...track.transform(t, decoratorMetas),
1010
- ...wire.transform(t, decoratorMetas),
1065
+ ...wire.transform(t, decoratorMetas, state),
1011
1066
  ];
1012
1067
  const fieldNames = classBodyItems
1013
1068
  .filter((field) => field.isClassProperty({ computed: false, static: false }))
@@ -1045,9 +1100,11 @@ function decorators({ types: t }) {
1045
1100
  return;
1046
1101
  }
1047
1102
  const decoratorPaths = collectDecoratorPaths(classBodyItems);
1048
- const decoratorMetas = decoratorPaths.map((path) => getDecoratorMetadata(path, state));
1103
+ const decoratorMetas = decoratorPaths
1104
+ .map((path) => getDecoratorMetadata(path, state))
1105
+ .filter((meta) => meta !== null);
1049
1106
  validate(decoratorMetas, state);
1050
- const metaPropertyList = getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems);
1107
+ const metaPropertyList = getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state);
1051
1108
  if (metaPropertyList.length === 0) {
1052
1109
  return;
1053
1110
  }
@@ -1138,7 +1195,7 @@ function getImportSource(path) {
1138
1195
  }
1139
1196
  function validateImport(sourcePath, state) {
1140
1197
  if (!sourcePath.isStringLiteral()) {
1141
- throw generateError(sourcePath, {
1198
+ handleError(sourcePath, {
1142
1199
  errorInfo: LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT,
1143
1200
  messageArgs: [String(sourcePath)],
1144
1201
  }, state);
@@ -1285,5 +1342,5 @@ function LwcClassTransform(api) {
1285
1342
  }
1286
1343
 
1287
1344
  export { LwcClassTransform as default };
1288
- /** version: 8.24.0 */
1345
+ /** version: 8.25.1 */
1289
1346
  //# sourceMappingURL=index.js.map
package/dist/utils.d.ts CHANGED
@@ -18,7 +18,8 @@ declare function isSetterClassMethod(classMethod: NodePath<types.Node>, properti
18
18
  static?: boolean;
19
19
  }): classMethod is NodePath<types.ClassMethod>;
20
20
  declare function getEngineImportSpecifiers(path: NodePath): ImportSpecifier[];
21
- declare function generateError(source: NodePath<types.Node>, { errorInfo, messageArgs }: DecoratorErrorOptions, state: LwcBabelPluginPass): Error;
21
+ declare function handleError(source: NodePath<types.Node>, decoratorErrorOpts: DecoratorErrorOptions, state: LwcBabelPluginPass): void;
22
22
  declare function incrementMetricCounter(metric: CompilerMetrics, state: LwcBabelPluginPass): void;
23
- export { isClassMethod, isGetterClassMethod, isSetterClassMethod, generateError, getEngineImportSpecifiers, incrementMetricCounter, };
23
+ declare function isErrorRecoveryMode(state: LwcBabelPluginPass): boolean;
24
+ export { isClassMethod, isGetterClassMethod, isSetterClassMethod, getEngineImportSpecifiers, handleError, incrementMetricCounter, isErrorRecoveryMode, };
24
25
  //# sourceMappingURL=utils.d.ts.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/babel-plugin-component",
7
- "version": "8.24.0",
7
+ "version": "8.25.1",
8
8
  "description": "Babel plugin to transform a LWC module",
9
9
  "keywords": [
10
10
  "lwc"
@@ -47,8 +47,8 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@babel/helper-module-imports": "7.27.1",
50
- "@lwc/errors": "8.24.0",
51
- "@lwc/shared": "8.24.0",
50
+ "@lwc/errors": "8.25.1",
51
+ "@lwc/shared": "8.25.1",
52
52
  "line-column": "~1.0.2"
53
53
  },
54
54
  "devDependencies": {