@lwc/babel-plugin-component 9.0.2 → 9.0.4-alpha.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 ADDED
@@ -0,0 +1,1516 @@
1
+ /**
2
+ * Copyright (c) 2026 Salesforce, Inc.
3
+ */
4
+ 'use strict';
5
+
6
+ Object.defineProperty(exports, '__esModule', { value: true });
7
+
8
+ var node_path = require('node:path');
9
+ var helperModuleImports = require('@babel/helper-module-imports');
10
+ var shared = require('@lwc/shared');
11
+ var errors = require('@lwc/errors');
12
+ var lineColumn = require('line-column');
13
+
14
+ /*
15
+ * Copyright (c) 2023, salesforce.com, inc.
16
+ * All rights reserved.
17
+ * SPDX-License-Identifier: MIT
18
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
19
+ */
20
+ const LWC_PACKAGE_ALIAS = 'lwc';
21
+ const LWC_PACKAGE_EXPORTS = {
22
+ API_DECORATOR: 'api',
23
+ TRACK_DECORATOR: 'track',
24
+ WIRE_DECORATOR: 'wire',
25
+ };
26
+ const LWC_COMPONENT_PROPERTIES = {
27
+ PUBLIC_PROPS: 'publicProps',
28
+ PUBLIC_METHODS: 'publicMethods',
29
+ WIRE: 'wire',
30
+ TRACK: 'track',
31
+ };
32
+ const DECORATOR_TYPES = {
33
+ PROPERTY: 'property',
34
+ GETTER: 'getter',
35
+ SETTER: 'setter',
36
+ METHOD: 'method',
37
+ };
38
+ const REGISTER_COMPONENT_ID = 'registerComponent';
39
+ const REGISTER_DECORATORS_ID = 'registerDecorators';
40
+ const TEMPLATE_KEY = 'tmpl';
41
+ const COMPONENT_NAME_KEY = 'sel';
42
+ const API_VERSION_KEY = 'apiVersion';
43
+ const COMPONENT_CLASS_ID = '__lwc_component_class_internal';
44
+ const PRIVATE_METHOD_PREFIX = '__lwc_component_class_internal_private_';
45
+ const PRIVATE_METHOD_METADATA_KEY = '__lwcTransformedPrivateMethods';
46
+ const SYNTHETIC_ELEMENT_INTERNALS_KEY = 'enableSyntheticElementInternals';
47
+ const COMPONENT_FEATURE_FLAG_KEY = 'componentFeatureFlag';
48
+
49
+ /*
50
+ * Copyright (c) 2023, salesforce.com, inc.
51
+ * All rights reserved.
52
+ * SPDX-License-Identifier: MIT
53
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
54
+ */
55
+ function getBaseName(classPath) {
56
+ const ext = node_path.extname(classPath);
57
+ return node_path.basename(classPath, ext);
58
+ }
59
+ function importDefaultTemplate(path, state) {
60
+ const { filename } = state.file.opts;
61
+ const componentName = getBaseName(filename);
62
+ return helperModuleImports.addDefault(path, `./${componentName}.html`, {
63
+ nameHint: TEMPLATE_KEY,
64
+ });
65
+ }
66
+ function needsComponentRegistration(path) {
67
+ return ((path.isIdentifier() && path.node.name !== 'undefined' && path.node.name !== 'null') ||
68
+ path.isCallExpression() ||
69
+ path.isClassDeclaration() ||
70
+ path.isConditionalExpression());
71
+ }
72
+ function getComponentRegisteredName(t, state) {
73
+ const { namespace, name } = state.opts;
74
+ const componentName = shared.generateCustomElementTagName(namespace, name);
75
+ return t.stringLiteral(componentName);
76
+ }
77
+ function component ({ types: t }) {
78
+ function createRegisterComponent(declarationPath, state) {
79
+ const registerComponentId = helperModuleImports.addNamed(declarationPath, REGISTER_COMPONENT_ID, LWC_PACKAGE_ALIAS);
80
+ const templateIdentifier = importDefaultTemplate(declarationPath, state);
81
+ // Optionally import feature flag module if provided via compiler options
82
+ let componentFeatureFlagIdentifier;
83
+ if (state.opts.componentFeatureFlagModulePath) {
84
+ componentFeatureFlagIdentifier = helperModuleImports.addDefault(declarationPath, state.opts.componentFeatureFlagModulePath, {
85
+ nameHint: COMPONENT_FEATURE_FLAG_KEY,
86
+ });
87
+ }
88
+ const statementPath = declarationPath.getStatementParent();
89
+ const componentRegisteredName = getComponentRegisteredName(t, state);
90
+ let node = declarationPath.node;
91
+ if (declarationPath.isClassDeclaration()) {
92
+ const hasIdentifier = t.isIdentifier(node.id);
93
+ if (hasIdentifier) {
94
+ statementPath.insertBefore(node);
95
+ node = node.id;
96
+ }
97
+ else {
98
+ // if it does not have an id, we can treat it as a ClassExpression
99
+ t.toExpression(node);
100
+ }
101
+ }
102
+ const apiVersion = shared.getAPIVersionFromNumber(state.opts.apiVersion);
103
+ // Example:
104
+ // registerComponent(cmp, {
105
+ // tmpl: template,
106
+ // sel: 'x-foo',
107
+ // apiVersion: '58'
108
+ // })
109
+ const properties = [
110
+ t.objectProperty(t.identifier(TEMPLATE_KEY), templateIdentifier),
111
+ t.objectProperty(t.identifier(COMPONENT_NAME_KEY), componentRegisteredName),
112
+ // It's important that, at this point, we have an APIVersion rather than just a number.
113
+ // The client needs to trust the server that it's providing an actual known API version
114
+ t.objectProperty(t.identifier(API_VERSION_KEY), t.numericLiteral(apiVersion)),
115
+ ];
116
+ if (componentFeatureFlagIdentifier) {
117
+ properties.push(t.objectProperty(t.identifier(COMPONENT_FEATURE_FLAG_KEY), t.objectExpression([
118
+ t.objectProperty(t.identifier('value'), t.callExpression(t.identifier('Boolean'), [
119
+ componentFeatureFlagIdentifier,
120
+ ])),
121
+ t.objectProperty(t.identifier('path'), t.stringLiteral(state.opts.componentFeatureFlagModulePath)),
122
+ ])));
123
+ }
124
+ // Only include enableSyntheticElementInternals if set to true
125
+ if (state.opts.enableSyntheticElementInternals === true) {
126
+ properties.push(t.objectProperty(t.identifier(SYNTHETIC_ELEMENT_INTERNALS_KEY), t.booleanLiteral(true)));
127
+ }
128
+ const registerComponentExpression = t.callExpression(registerComponentId, [
129
+ node,
130
+ t.objectExpression(properties),
131
+ ]);
132
+ // Example:
133
+ // const __lwc_component_class_internal = registerComponent(cmp, ...);
134
+ // This provides a way to access the component class for other lwc tools
135
+ const classIdentifier = t.identifier(COMPONENT_CLASS_ID);
136
+ declarationPath.parentPath.insertBefore(t.variableDeclaration('const', [
137
+ t.variableDeclarator(classIdentifier, registerComponentExpression),
138
+ ]));
139
+ return classIdentifier;
140
+ }
141
+ return {
142
+ ExportDefaultDeclaration(path, state) {
143
+ const implicitResolution = !state.opts.isExplicitImport;
144
+ if (implicitResolution) {
145
+ const declaration = path.get('declaration');
146
+ if (needsComponentRegistration(declaration)) {
147
+ declaration.replaceWith(createRegisterComponent(declaration, state));
148
+ }
149
+ }
150
+ },
151
+ };
152
+ }
153
+
154
+ /*
155
+ * Copyright (c) 2023, salesforce.com, inc.
156
+ * All rights reserved.
157
+ * SPDX-License-Identifier: MIT
158
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
159
+ */
160
+ function isClassMethod(classMethod, properties = {}) {
161
+ const { kind = 'method', name } = properties;
162
+ return (classMethod.isClassMethod({ kind }) &&
163
+ (!name || classMethod.get('key').isIdentifier({ name })) &&
164
+ (properties.static === undefined || classMethod.node.static === properties.static));
165
+ }
166
+ function isGetterClassMethod(classMethod, properties = {}) {
167
+ return isClassMethod(classMethod, {
168
+ kind: 'get',
169
+ name: properties.name,
170
+ static: properties.static,
171
+ });
172
+ }
173
+ function isSetterClassMethod(classMethod, properties = {}) {
174
+ return isClassMethod(classMethod, {
175
+ kind: 'set',
176
+ name: properties.name,
177
+ static: properties.static,
178
+ });
179
+ }
180
+ function getEngineImportsStatements(path) {
181
+ const programPath = path.isProgram()
182
+ ? path
183
+ : path.findParent((node) => node.isProgram());
184
+ return programPath.get('body').filter((node) => {
185
+ const source = node.get('source');
186
+ return node.isImportDeclaration() && source.isStringLiteral({ value: LWC_PACKAGE_ALIAS });
187
+ });
188
+ }
189
+ function getEngineImportSpecifiers(path) {
190
+ const imports = getEngineImportsStatements(path);
191
+ return (imports
192
+ // Flat-map the specifier list for each import statement
193
+ .flatMap((importStatement) => importStatement.get('specifiers'))
194
+ // Skip ImportDefaultSpecifier and ImportNamespaceSpecifier
195
+ .filter((specifier) => specifier.type === 'ImportSpecifier')
196
+ // Get the list of specifiers with their name
197
+ .map((specifier) => {
198
+ const imported = specifier.get('imported').node
199
+ .name;
200
+ return { name: imported, path: specifier };
201
+ }));
202
+ }
203
+ function normalizeLocation(source) {
204
+ const location = (source.node && (source.node.loc || source.node._loc)) || null;
205
+ if (!location) {
206
+ return null;
207
+ }
208
+ const code = source.hub.getCode();
209
+ if (!code) {
210
+ return {
211
+ line: location.start.line,
212
+ column: location.start.column,
213
+ };
214
+ }
215
+ const lineFinder = lineColumn(code);
216
+ const startOffset = lineFinder.toIndex(location.start.line, location.start.column + 1);
217
+ const endOffset = lineFinder.toIndex(location.end.line, location.end.column) + 1;
218
+ const length = endOffset - startOffset;
219
+ return {
220
+ line: location.start.line,
221
+ column: location.start.column,
222
+ start: startOffset,
223
+ length,
224
+ };
225
+ }
226
+ function generateError(source, { errorInfo, messageArgs }, state) {
227
+ const message = errors.generateErrorMessage(errorInfo, messageArgs);
228
+ const error = source.buildCodeFrameError(message);
229
+ error.filename = state.filename;
230
+ error.loc = normalizeLocation(source);
231
+ error.lwcCode = errorInfo && errorInfo.code;
232
+ return error;
233
+ }
234
+ function collectError(source, { errorInfo, messageArgs }, state) {
235
+ const diagnostic = errors.generateCompilerDiagnostic(errorInfo, {
236
+ messageArgs,
237
+ origin: {
238
+ filename: state.filename,
239
+ location: normalizeLocation(source) ?? undefined,
240
+ },
241
+ }, true);
242
+ if (diagnostic.level === errors.DiagnosticLevel.Fatal) {
243
+ throw generateError(source, { errorInfo, messageArgs }, state);
244
+ }
245
+ if (!state.file.metadata.lwcErrors) {
246
+ state.file.metadata.lwcErrors = [];
247
+ }
248
+ state.file.metadata.lwcErrors.push(diagnostic);
249
+ }
250
+ function handleError(source, decoratorErrorOpts, state) {
251
+ if (isErrorRecoveryMode(state)) {
252
+ collectError(source, decoratorErrorOpts, state);
253
+ }
254
+ else {
255
+ throw generateError(source, decoratorErrorOpts, state);
256
+ }
257
+ }
258
+ function incrementMetricCounter(metric, state) {
259
+ state.opts.instrumentation?.incrementCounter(metric);
260
+ }
261
+ function isErrorRecoveryMode(state) {
262
+ return state.file.opts?.parserOpts?.errorRecovery ?? false;
263
+ }
264
+ /**
265
+ * Copies optional metadata properties between ClassMethod and ClassPrivateMethod nodes.
266
+ * These properties are not accepted by the t.classMethod() / t.classPrivateMethod() builders,
267
+ * so they must be transferred manually after node creation. Both the forward and reverse
268
+ * private-method transforms use this to maintain round-trip parity.
269
+ */
270
+ function copyMethodMetadata(source, target) {
271
+ if (source.returnType != null)
272
+ target.returnType = source.returnType;
273
+ if (source.typeParameters != null)
274
+ target.typeParameters = source.typeParameters;
275
+ if (source.loc != null)
276
+ target.loc = source.loc;
277
+ if (source.abstract != null)
278
+ target.abstract = source.abstract;
279
+ if (source.access != null)
280
+ target.access = source.access;
281
+ if (source.accessibility != null)
282
+ target.accessibility = source.accessibility;
283
+ if (source.optional != null)
284
+ target.optional = source.optional;
285
+ if (source.override != null)
286
+ target.override = source.override;
287
+ }
288
+
289
+ /*
290
+ * Copyright (c) 2023, salesforce.com, inc.
291
+ * All rights reserved.
292
+ * SPDX-License-Identifier: MIT
293
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
294
+ */
295
+ const { API_DECORATOR: API_DECORATOR$2 } = LWC_PACKAGE_EXPORTS;
296
+ function isApiDecorator(decorator) {
297
+ return decorator.name === API_DECORATOR$2;
298
+ }
299
+
300
+ /*
301
+ * Copyright (c) 2023, salesforce.com, inc.
302
+ * All rights reserved.
303
+ * SPDX-License-Identifier: MIT
304
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
305
+ */
306
+ const { TRACK_DECORATOR: TRACK_DECORATOR$2 } = LWC_PACKAGE_EXPORTS;
307
+ function validateConflict(path, decorators, state) {
308
+ const isPublicFieldTracked = decorators.some((decorator) => decorator.name === TRACK_DECORATOR$2 &&
309
+ decorator.path.parentPath.node === path.parentPath.node);
310
+ if (isPublicFieldTracked) {
311
+ handleError(path, {
312
+ errorInfo: errors.DecoratorErrors.API_AND_TRACK_DECORATOR_CONFLICT,
313
+ }, state);
314
+ }
315
+ }
316
+ function isBooleanPropDefaultTrue(property) {
317
+ const propertyValue = property.node.value;
318
+ return propertyValue && propertyValue.type === 'BooleanLiteral' && propertyValue.value;
319
+ }
320
+ function validatePropertyValue(property, state) {
321
+ if (isBooleanPropDefaultTrue(property)) {
322
+ handleError(property, {
323
+ errorInfo: errors.DecoratorErrors.INVALID_BOOLEAN_PUBLIC_PROPERTY,
324
+ }, state);
325
+ }
326
+ }
327
+ function validatePropertyName(property, state) {
328
+ if (property.node.computed) {
329
+ handleError(property, {
330
+ errorInfo: errors.DecoratorErrors.PROPERTY_CANNOT_BE_COMPUTED,
331
+ }, state);
332
+ }
333
+ const propertyName = property.get('key.name').node;
334
+ if (propertyName === 'part') {
335
+ handleError(property, {
336
+ errorInfo: errors.DecoratorErrors.PROPERTY_NAME_PART_IS_RESERVED,
337
+ messageArgs: [propertyName],
338
+ }, state);
339
+ }
340
+ else if (propertyName.startsWith('on')) {
341
+ handleError(property, {
342
+ errorInfo: errors.DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_ON,
343
+ messageArgs: [propertyName],
344
+ }, state);
345
+ }
346
+ else if (propertyName.startsWith('data') && propertyName.length > 4) {
347
+ handleError(property, {
348
+ errorInfo: errors.DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_DATA,
349
+ messageArgs: [propertyName],
350
+ }, state);
351
+ }
352
+ else if (shared.DISALLOWED_PROP_SET.has(propertyName)) {
353
+ handleError(property, {
354
+ errorInfo: errors.DecoratorErrors.PROPERTY_NAME_IS_RESERVED,
355
+ messageArgs: [propertyName],
356
+ }, state);
357
+ }
358
+ else if (shared.AMBIGUOUS_PROP_SET.has(propertyName)) {
359
+ const camelCased = shared.AMBIGUOUS_PROP_SET.get(propertyName);
360
+ handleError(property, {
361
+ errorInfo: errors.DecoratorErrors.PROPERTY_NAME_IS_AMBIGUOUS,
362
+ messageArgs: [propertyName, camelCased],
363
+ }, state);
364
+ }
365
+ }
366
+ function validateSingleApiDecoratorOnSetterGetterPair(decorators, state) {
367
+ // keep track of visited class methods
368
+ const visitedMethods = new Set();
369
+ decorators.forEach((decorator) => {
370
+ const { path, decoratedNodeType } = decorator;
371
+ // since we are validating get/set we only look at @api methods
372
+ if (isApiDecorator(decorator) &&
373
+ (decoratedNodeType === DECORATOR_TYPES.GETTER ||
374
+ decoratedNodeType === DECORATOR_TYPES.SETTER)) {
375
+ const methodPath = path.parentPath;
376
+ const methodName = methodPath.get('key.name').node;
377
+ if (visitedMethods.has(methodName)) {
378
+ handleError(methodPath, {
379
+ errorInfo: errors.DecoratorErrors.SINGLE_DECORATOR_ON_SETTER_GETTER_PAIR,
380
+ messageArgs: [methodName],
381
+ }, state);
382
+ }
383
+ visitedMethods.add(methodName);
384
+ }
385
+ });
386
+ }
387
+ function validateUniqueness(decorators, state) {
388
+ const apiDecorators = decorators.filter(isApiDecorator);
389
+ for (let i = 0; i < apiDecorators.length; i++) {
390
+ const { path: currentPath, type: currentType } = apiDecorators[i];
391
+ const currentPropertyName = currentPath.parentPath.get('key.name').node;
392
+ for (let j = 0; j < apiDecorators.length; j++) {
393
+ const { path: comparePath, type: compareType } = apiDecorators[j];
394
+ const comparePropertyName = comparePath.parentPath.get('key.name')
395
+ .node;
396
+ // We will throw if the considered properties have the same name, and when their
397
+ // are not part of a pair of getter/setter.
398
+ const haveSameName = currentPropertyName === comparePropertyName;
399
+ const isDifferentProperty = currentPath !== comparePath;
400
+ const isGetterSetterPair = (currentType === DECORATOR_TYPES.GETTER &&
401
+ compareType === DECORATOR_TYPES.SETTER) ||
402
+ (currentType === DECORATOR_TYPES.SETTER && compareType === DECORATOR_TYPES.GETTER);
403
+ if (haveSameName && isDifferentProperty && !isGetterSetterPair) {
404
+ handleError(comparePath, {
405
+ errorInfo: errors.DecoratorErrors.DUPLICATE_API_PROPERTY,
406
+ messageArgs: [currentPropertyName],
407
+ }, state);
408
+ }
409
+ }
410
+ }
411
+ }
412
+ function validate$3(decorators, state) {
413
+ const apiDecorators = decorators.filter(isApiDecorator);
414
+ if (apiDecorators.length === 0) {
415
+ return;
416
+ }
417
+ apiDecorators.forEach(({ path, decoratedNodeType }) => {
418
+ validateConflict(path, decorators, state);
419
+ if (decoratedNodeType !== DECORATOR_TYPES.METHOD) {
420
+ const property = path.parentPath;
421
+ validatePropertyName(property, state);
422
+ validatePropertyValue(property, state);
423
+ }
424
+ });
425
+ validateSingleApiDecoratorOnSetterGetterPair(decorators, state);
426
+ validateUniqueness(decorators, state);
427
+ }
428
+
429
+ /*
430
+ * Copyright (c) 2023, salesforce.com, inc.
431
+ * All rights reserved.
432
+ * SPDX-License-Identifier: MIT
433
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
434
+ */
435
+ const { PUBLIC_PROPS, PUBLIC_METHODS } = LWC_COMPONENT_PROPERTIES;
436
+ const PUBLIC_PROP_BIT_MASK = {
437
+ PROPERTY: 0,
438
+ GETTER: 1,
439
+ SETTER: 2,
440
+ };
441
+ function getPropertyBitmask(type) {
442
+ switch (type) {
443
+ case DECORATOR_TYPES.GETTER:
444
+ return PUBLIC_PROP_BIT_MASK.GETTER;
445
+ case DECORATOR_TYPES.SETTER:
446
+ return PUBLIC_PROP_BIT_MASK.SETTER;
447
+ default:
448
+ return PUBLIC_PROP_BIT_MASK.PROPERTY;
449
+ }
450
+ }
451
+ function getSiblingGetSetPairType(propertyName, type, classBodyItems) {
452
+ const siblingKind = type === DECORATOR_TYPES.GETTER ? 'set' : 'get';
453
+ const siblingNode = classBodyItems.find((classBodyItem) => {
454
+ const isClassMethod = classBodyItem.isClassMethod({ kind: siblingKind });
455
+ const isSamePropertyName = classBodyItem.node.key.name ===
456
+ propertyName;
457
+ return isClassMethod && isSamePropertyName;
458
+ });
459
+ if (siblingNode) {
460
+ return siblingKind === 'get' ? DECORATOR_TYPES.GETTER : DECORATOR_TYPES.SETTER;
461
+ }
462
+ }
463
+ function computePublicPropsConfig(publicPropertyMetas, classBodyItems, state) {
464
+ return publicPropertyMetas.reduce((acc, { propertyName, decoratedNodeType }) => {
465
+ // This should never happen as we filter null in class visitor and
466
+ // collect appropriate errors in errorRecoveryMode || throw otherwise
467
+ if (isErrorRecoveryMode(state) && !decoratedNodeType)
468
+ return acc;
469
+ if (!(propertyName in acc)) {
470
+ acc[propertyName] = {};
471
+ }
472
+ acc[propertyName].config |= getPropertyBitmask(decoratedNodeType);
473
+ if (decoratedNodeType === DECORATOR_TYPES.GETTER ||
474
+ decoratedNodeType === DECORATOR_TYPES.SETTER) {
475
+ // With the latest decorator spec, only one of the getter/setter pair needs a decorator.
476
+ // We need to add the proper bitmask for the sibling getter/setter if it exists.
477
+ const pairType = getSiblingGetSetPairType(propertyName, decoratedNodeType, classBodyItems);
478
+ if (pairType) {
479
+ acc[propertyName].config |= getPropertyBitmask(pairType);
480
+ }
481
+ }
482
+ return acc;
483
+ }, {});
484
+ }
485
+ function transform$2(t, decoratorMetas, classBodyItems, state) {
486
+ const objectProperties = [];
487
+ const apiDecoratorMetas = decoratorMetas.filter(isApiDecorator);
488
+ const publicPropertyMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType !== DECORATOR_TYPES.METHOD);
489
+ if (publicPropertyMetas.length) {
490
+ const propsConfig = computePublicPropsConfig(publicPropertyMetas, classBodyItems, state);
491
+ objectProperties.push(t.objectProperty(t.identifier(PUBLIC_PROPS), t.valueToNode(propsConfig)));
492
+ }
493
+ const publicMethodMetas = apiDecoratorMetas.filter(({ decoratedNodeType }) => decoratedNodeType === DECORATOR_TYPES.METHOD);
494
+ if (publicMethodMetas.length) {
495
+ const methodNames = publicMethodMetas.map(({ propertyName }) => propertyName);
496
+ objectProperties.push(t.objectProperty(t.identifier(PUBLIC_METHODS), t.valueToNode(methodNames)));
497
+ }
498
+ return objectProperties;
499
+ }
500
+
501
+ /*
502
+ * Copyright (c) 2023, salesforce.com, inc.
503
+ * All rights reserved.
504
+ * SPDX-License-Identifier: MIT
505
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
506
+ */
507
+ const { API_DECORATOR: API_DECORATOR$1 } = LWC_PACKAGE_EXPORTS;
508
+ var api = {
509
+ name: API_DECORATOR$1,
510
+ validate: validate$3,
511
+ transform: transform$2,
512
+ };
513
+
514
+ /*
515
+ * Copyright (c) 2023, salesforce.com, inc.
516
+ * All rights reserved.
517
+ * SPDX-License-Identifier: MIT
518
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
519
+ */
520
+ const { WIRE_DECORATOR: WIRE_DECORATOR$2 } = LWC_PACKAGE_EXPORTS;
521
+ function isWireDecorator(decorator) {
522
+ return decorator.name === WIRE_DECORATOR$2;
523
+ }
524
+
525
+ /*
526
+ * Copyright (c) 2024, 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
+ const { TRACK_DECORATOR: TRACK_DECORATOR$1, WIRE_DECORATOR: WIRE_DECORATOR$1, API_DECORATOR } = LWC_PACKAGE_EXPORTS;
532
+ function validateWireId(id, path, state) {
533
+ if (!id) {
534
+ handleError(path, {
535
+ errorInfo: errors.DecoratorErrors.ADAPTER_SHOULD_BE_FIRST_PARAMETER,
536
+ }, state);
537
+ return;
538
+ }
539
+ let adapter;
540
+ if (id.isIdentifier()) {
541
+ // @wire(adapter)
542
+ adapter = id;
543
+ }
544
+ else if (id.isMemberExpression()) {
545
+ if (id.node.computed) {
546
+ // @wire(adapter[computed])
547
+ handleError(id, {
548
+ errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_COMPUTED_PROPS,
549
+ }, state);
550
+ return;
551
+ }
552
+ const object = id.get('object');
553
+ if (object.isIdentifier()) {
554
+ // @wire(adapter.foo)
555
+ adapter = object;
556
+ }
557
+ else {
558
+ // @wire(adapter.foo.bar)
559
+ handleError(id, {
560
+ errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_CANNOT_HAVE_NESTED_MEMBER_EXRESSIONS,
561
+ }, state);
562
+ return;
563
+ }
564
+ }
565
+ else {
566
+ // @wire(1), @wire('adapter'), @wire(function adapter() {}), etc.
567
+ handleError(id, {
568
+ errorInfo: errors.DecoratorErrors.FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
569
+ }, state);
570
+ return;
571
+ }
572
+ // Ensure wire adapter is imported (check for member expression or identifier)
573
+ const adapterBinding = path.scope.getBinding(adapter.node.name);
574
+ if (!adapterBinding) {
575
+ handleError(id, {
576
+ errorInfo: errors.DecoratorErrors.WIRE_ADAPTER_SHOULD_BE_IMPORTED,
577
+ messageArgs: [adapter.node.name],
578
+ }, state);
579
+ return;
580
+ }
581
+ // ensure wire adapter is a first parameter
582
+ if (!adapterBinding.path.isImportSpecifier() &&
583
+ !adapterBinding.path.isImportDefaultSpecifier()) {
584
+ handleError(id, {
585
+ errorInfo: errors.DecoratorErrors.IMPORTED_FUNCTION_IDENTIFIER_SHOULD_BE_FIRST_PARAMETER,
586
+ }, state);
587
+ }
588
+ }
589
+ function validateWireConfig(config, path, state) {
590
+ if (!config.isObjectExpression()) {
591
+ handleError(config, {
592
+ errorInfo: errors.DecoratorErrors.CONFIG_OBJECT_SHOULD_BE_SECOND_PARAMETER,
593
+ }, state);
594
+ }
595
+ const properties = config.get('properties');
596
+ if (Array.isArray(properties)) {
597
+ for (const prop of properties) {
598
+ // Only validate {[computed]: true} object properties; {static: true} props are all valid
599
+ // and we ignore {...spreads} and {methods(){}}
600
+ if (!prop.isObjectProperty() || !prop.node.computed)
601
+ continue;
602
+ const key = prop.get('key');
603
+ if (key.isIdentifier()) {
604
+ // Only allow identifiers that originated from a `const` declaration
605
+ const binding = key.scope.getBinding(key.node.name);
606
+ // TODO [#3956]: Investigate allowing imported constants
607
+ if (binding?.kind === 'const')
608
+ continue;
609
+ // By default, the identifier `undefined` has no binding (when it's actually undefined),
610
+ // but has a binding if it's used as a variable (e.g. `let undefined = "don't do this"`)
611
+ if (key.node.name === 'undefined' && !binding)
612
+ continue;
613
+ }
614
+ else if (key.isLiteral()) {
615
+ // A literal can be a regexp, template literal, or primitive; only allow primitives
616
+ if (key.isTemplateLiteral()) {
617
+ // A template literal is not guaranteed to always result in the same value
618
+ // (e.g. `${Math.random()}`), so we disallow them entirely.
619
+ // TODO [#3956]: Investigate allowing template literals
620
+ handleError(key, {
621
+ errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_CANNOT_BE_TEMPLATE_LITERAL,
622
+ }, state);
623
+ }
624
+ else if (!key.isRegExpLiteral()) {
625
+ continue;
626
+ }
627
+ }
628
+ handleError(key, {
629
+ errorInfo: errors.DecoratorErrors.COMPUTED_PROPERTY_MUST_BE_CONSTANT_OR_LITERAL,
630
+ }, state);
631
+ }
632
+ }
633
+ }
634
+ function validateWireParameters(path, state) {
635
+ const expressionArguments = path.get('expression.arguments');
636
+ if (Array.isArray(expressionArguments)) {
637
+ // Multiple arguments: should be [id, config?]
638
+ const [id, config] = expressionArguments;
639
+ validateWireId(id, path, state);
640
+ if (config)
641
+ validateWireConfig(config, path, state);
642
+ }
643
+ else {
644
+ // Single argument: should just be id
645
+ validateWireId(expressionArguments, path, state);
646
+ }
647
+ }
648
+ function validateUsageWithOtherDecorators(path, decorators, state) {
649
+ decorators.forEach((decorator) => {
650
+ if (path !== decorator.path &&
651
+ decorator.name === WIRE_DECORATOR$1 &&
652
+ decorator.path.parentPath.node === path.parentPath.node) {
653
+ handleError(path, {
654
+ errorInfo: errors.DecoratorErrors.ONE_WIRE_DECORATOR_ALLOWED,
655
+ }, state);
656
+ }
657
+ if ((decorator.name === API_DECORATOR || decorator.name === TRACK_DECORATOR$1) &&
658
+ decorator.path.parentPath.node === path.parentPath.node) {
659
+ handleError(path, {
660
+ errorInfo: errors.DecoratorErrors.CONFLICT_WITH_ANOTHER_DECORATOR,
661
+ messageArgs: [decorator.name],
662
+ }, state);
663
+ }
664
+ });
665
+ }
666
+ function validate$2(decorators, state) {
667
+ decorators.filter(isWireDecorator).forEach(({ path }) => {
668
+ validateUsageWithOtherDecorators(path, decorators, state);
669
+ validateWireParameters(path, state);
670
+ });
671
+ }
672
+
673
+ /*
674
+ * Copyright (c) 2024, salesforce.com, inc.
675
+ * All rights reserved.
676
+ * SPDX-License-Identifier: MIT
677
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
678
+ */
679
+ const WIRE_PARAM_PREFIX = '$';
680
+ const WIRE_CONFIG_ARG_NAME = '$cmp';
681
+ function isObservedProperty(configProperty) {
682
+ const propertyValue = configProperty.get('value');
683
+ return (propertyValue.isStringLiteral() && propertyValue.node.value.startsWith(WIRE_PARAM_PREFIX));
684
+ }
685
+ function getWiredStatic(wireConfig, state) {
686
+ const properties = wireConfig.get('properties');
687
+ // Should only occurs in error recovery mode when config validation has already failed
688
+ // Skip processing since the error has been logged upstream
689
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
690
+ return [];
691
+ }
692
+ return properties
693
+ .filter((property) => !isObservedProperty(property))
694
+ .map((path) => path.node);
695
+ }
696
+ function getWiredParams(t, wireConfig, state) {
697
+ const properties = wireConfig.get('properties');
698
+ // Should only occur in error recovery mode when config validation has already failed
699
+ // Skip processing since the error has been logged upstream
700
+ if (isErrorRecoveryMode(state) && !Array.isArray(properties)) {
701
+ // In error recovery mode, return empty array instead of crashing
702
+ return [];
703
+ }
704
+ return properties
705
+ .filter((property) => isObservedProperty(property))
706
+ .map((path) => {
707
+ // Need to clone deep the observed property to remove the param prefix
708
+ const clonedProperty = t.cloneNode(path.node);
709
+ clonedProperty.value.value = clonedProperty.value.value.slice(1);
710
+ return clonedProperty;
711
+ });
712
+ }
713
+ function getGeneratedConfig(t, wiredValue) {
714
+ let counter = 0;
715
+ const configBlockBody = [];
716
+ const configProps = [];
717
+ const generateParameterConfigValue = (memberExprPaths) => {
718
+ // Note: When memberExprPaths ($foo.bar) has an invalid identifier (eg: foo..bar, foo.bar[3])
719
+ // it should (ideally) resolve in a compilation error during validation phase.
720
+ // This is not possible due that platform components may have a param definition which is invalid
721
+ // but passes compilation, and throwing at compile time would break such components.
722
+ // In such cases where the param does not have proper notation, the config generated will use the bracket
723
+ // notation to match the current behavior (that most likely end up resolving that param as undefined).
724
+ const isInvalidMemberExpr = memberExprPaths.some((maybeIdentifier) => !(t.isValidES3Identifier(maybeIdentifier) && maybeIdentifier.length > 0));
725
+ const memberExprPropertyGen = !isInvalidMemberExpr
726
+ ? t.identifier
727
+ : t.StringLiteral;
728
+ if (memberExprPaths.length === 1) {
729
+ return {
730
+ configValueExpression: t.memberExpression(t.identifier(WIRE_CONFIG_ARG_NAME), memberExprPropertyGen(memberExprPaths[0])),
731
+ };
732
+ }
733
+ const varName = 'v' + ++counter;
734
+ const varDeclaration = t.variableDeclaration('let', [
735
+ t.variableDeclarator(t.identifier(varName), t.memberExpression(t.identifier(WIRE_CONFIG_ARG_NAME), memberExprPropertyGen(memberExprPaths[0]), isInvalidMemberExpr)),
736
+ ]);
737
+ // Results in: v != null && ... (v = v.i) != null && ... (v = v.(n-1)) != null
738
+ let conditionTest = t.binaryExpression('!=', t.identifier(varName), t.nullLiteral());
739
+ for (let i = 1, n = memberExprPaths.length; i < n - 1; i++) {
740
+ const nextPropValue = t.assignmentExpression('=', t.identifier(varName), t.memberExpression(t.identifier(varName), memberExprPropertyGen(memberExprPaths[i]), isInvalidMemberExpr));
741
+ conditionTest = t.logicalExpression('&&', conditionTest, t.binaryExpression('!=', nextPropValue, t.nullLiteral()));
742
+ }
743
+ // conditionTest ? v.n : undefined
744
+ const configValueExpression = t.conditionalExpression(conditionTest, t.memberExpression(t.identifier(varName), memberExprPropertyGen(memberExprPaths[memberExprPaths.length - 1]), isInvalidMemberExpr), t.identifier('undefined'));
745
+ return {
746
+ varDeclaration,
747
+ configValueExpression,
748
+ };
749
+ };
750
+ if (wiredValue.static) {
751
+ Array.prototype.push.apply(configProps, wiredValue.static);
752
+ }
753
+ if (wiredValue.params) {
754
+ wiredValue.params.forEach((param) => {
755
+ const memberExprPaths = param.value.value.split('.');
756
+ const paramConfigValue = generateParameterConfigValue(memberExprPaths);
757
+ configProps.push(t.objectProperty(param.key, paramConfigValue.configValueExpression, param.computed));
758
+ if (paramConfigValue.varDeclaration) {
759
+ configBlockBody.push(paramConfigValue.varDeclaration);
760
+ }
761
+ });
762
+ }
763
+ configBlockBody.push(t.returnStatement(t.objectExpression(configProps)));
764
+ const fnExpression = t.functionExpression(null, [t.identifier(WIRE_CONFIG_ARG_NAME)], t.blockStatement(configBlockBody));
765
+ return t.objectProperty(t.identifier('config'), fnExpression);
766
+ }
767
+ function buildWireConfigValue(t, wiredValues) {
768
+ return t.objectExpression(wiredValues.map((wiredValue) => {
769
+ const wireConfig = [];
770
+ if (wiredValue.adapter) {
771
+ wireConfig.push(t.objectProperty(t.identifier('adapter'), wiredValue.adapter.expression));
772
+ }
773
+ if (wiredValue.params) {
774
+ const dynamicParamNames = wiredValue.params.map((p) => {
775
+ if (t.isIdentifier(p.key)) {
776
+ return p.computed ? t.identifier(p.key.name) : t.stringLiteral(p.key.name);
777
+ }
778
+ else if (t.isLiteral(p.key) &&
779
+ // Template literals may contain expressions, so they are not allowed
780
+ !t.isTemplateLiteral(p.key) &&
781
+ // RegExp are not primitives, so they are not allowed
782
+ !t.isRegExpLiteral(p.key)) {
783
+ const value = t.isNullLiteral(p.key) ? null : p.key.value;
784
+ return t.stringLiteral(String(value));
785
+ }
786
+ // If it's not an identifier or primitive literal then it's a computed expression
787
+ throw new TypeError(`Expected object property key to be an identifier or a literal, but instead saw "${p.key.type}".`);
788
+ });
789
+ wireConfig.push(t.objectProperty(t.identifier('dynamic'), t.arrayExpression(dynamicParamNames)));
790
+ }
791
+ if (wiredValue.isClassMethod) {
792
+ wireConfig.push(t.objectProperty(t.identifier('method'), t.numericLiteral(1)));
793
+ }
794
+ wireConfig.push(getGeneratedConfig(t, wiredValue));
795
+ return t.objectProperty(t.identifier(wiredValue.propertyName), t.objectExpression(wireConfig));
796
+ }));
797
+ }
798
+ const SUPPORTED_VALUE_TO_TYPE_MAP = {
799
+ StringLiteral: 'string',
800
+ NumericLiteral: 'number',
801
+ BooleanLiteral: 'boolean',
802
+ };
803
+ const scopedReferenceLookup = (scope) => (name) => {
804
+ const binding = scope.getBinding(name);
805
+ let type;
806
+ let value;
807
+ if (binding) {
808
+ if (binding.kind === 'module') {
809
+ // Resolves module import to the name of the module imported
810
+ // e.g. import { foo } from 'bar' gives value 'bar' for `name == 'foo'
811
+ const parentPathNode = binding.path.parentPath.node;
812
+ if (parentPathNode && parentPathNode.source) {
813
+ type = 'module';
814
+ value = parentPathNode.source.value;
815
+ }
816
+ }
817
+ else if (binding.kind === 'const') {
818
+ // Resolves `const foo = 'text';` references to value 'text', where `name == 'foo'`
819
+ const init = binding.path.node.init;
820
+ if (init &&
821
+ SUPPORTED_VALUE_TO_TYPE_MAP[init.type]) {
822
+ type =
823
+ SUPPORTED_VALUE_TO_TYPE_MAP[init.type];
824
+ value = init
825
+ .value;
826
+ }
827
+ }
828
+ }
829
+ return {
830
+ type,
831
+ value,
832
+ };
833
+ };
834
+ function transform$1(t, decoratorMetas, state) {
835
+ const objectProperties = [];
836
+ const wiredValues = decoratorMetas.filter(isWireDecorator).map(({ path }) => {
837
+ const [id, config] = path.get('expression.arguments');
838
+ const propertyName = path.parentPath.get('key.name').node;
839
+ const isClassMethod = path.parentPath.isClassMethod({
840
+ kind: 'method',
841
+ });
842
+ const wiredValue = {
843
+ propertyName,
844
+ isClassMethod,
845
+ };
846
+ if (config) {
847
+ wiredValue.static = getWiredStatic(config, state);
848
+ wiredValue.params = getWiredParams(t, config, state);
849
+ }
850
+ const referenceLookup = scopedReferenceLookup(path.scope);
851
+ const isMemberExpression = id.isMemberExpression();
852
+ const isIdentifier = id.isIdentifier();
853
+ if (isIdentifier || isMemberExpression) {
854
+ const referenceName = isMemberExpression ? id.node.object.name : id.node.name;
855
+ const reference = referenceLookup(referenceName);
856
+ wiredValue.adapter = {
857
+ name: referenceName,
858
+ expression: t.cloneNode(id.node),
859
+ reference: reference.type === 'module' ? reference.value : undefined,
860
+ };
861
+ }
862
+ return wiredValue;
863
+ });
864
+ if (wiredValues.length) {
865
+ objectProperties.push(t.objectProperty(t.identifier(LWC_COMPONENT_PROPERTIES.WIRE), buildWireConfigValue(t, wiredValues)));
866
+ }
867
+ return objectProperties;
868
+ }
869
+
870
+ /*
871
+ * Copyright (c) 2023, salesforce.com, inc.
872
+ * All rights reserved.
873
+ * SPDX-License-Identifier: MIT
874
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
875
+ */
876
+ const { WIRE_DECORATOR } = LWC_PACKAGE_EXPORTS;
877
+ var wire = {
878
+ name: WIRE_DECORATOR,
879
+ validate: validate$2,
880
+ transform: transform$1,
881
+ };
882
+
883
+ /*
884
+ * Copyright (c) 2023, salesforce.com, inc.
885
+ * All rights reserved.
886
+ * SPDX-License-Identifier: MIT
887
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
888
+ */
889
+ const { TRACK_DECORATOR } = LWC_PACKAGE_EXPORTS;
890
+ const TRACK_PROPERTY_VALUE = 1;
891
+ function isTrackDecorator(decorator) {
892
+ return decorator.name === TRACK_DECORATOR;
893
+ }
894
+ function validate$1(decorators, state) {
895
+ decorators.filter(isTrackDecorator).forEach(({ path }) => {
896
+ if (!path.parentPath.isClassProperty()) {
897
+ handleError(path, {
898
+ errorInfo: errors.DecoratorErrors.TRACK_ONLY_ALLOWED_ON_CLASS_PROPERTIES,
899
+ }, state);
900
+ }
901
+ });
902
+ }
903
+ function transform(t, decoratorMetas) {
904
+ const objectProperties = [];
905
+ const trackDecoratorMetas = decoratorMetas.filter(isTrackDecorator);
906
+ if (trackDecoratorMetas.length) {
907
+ const config = trackDecoratorMetas.reduce((acc, meta) => {
908
+ acc[meta.propertyName] = TRACK_PROPERTY_VALUE;
909
+ return acc;
910
+ }, {});
911
+ objectProperties.push(t.objectProperty(t.identifier(LWC_COMPONENT_PROPERTIES.TRACK), t.valueToNode(config)));
912
+ }
913
+ return objectProperties;
914
+ }
915
+ var track = {
916
+ name: TRACK_DECORATOR,
917
+ transform,
918
+ validate: validate$1,
919
+ };
920
+
921
+ /*
922
+ * Copyright (c) 2023, salesforce.com, inc.
923
+ * All rights reserved.
924
+ * SPDX-License-Identifier: MIT
925
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
926
+ */
927
+ const DECORATOR_TRANSFORMS = [api, wire, track];
928
+ const AVAILABLE_DECORATORS = DECORATOR_TRANSFORMS.map((transform) => transform.name).join(', ');
929
+ function isLwcDecoratorName(name) {
930
+ return DECORATOR_TRANSFORMS.some((transform) => transform.name === name);
931
+ }
932
+ /**
933
+ * Returns a list of all the references to an identifier
934
+ * @param identifier
935
+ */
936
+ function getReferences(identifier) {
937
+ return identifier.scope.getBinding(identifier.node.name).referencePaths;
938
+ }
939
+ /**
940
+ * Returns the type of decorator depdending on the property or method if get applied to
941
+ * @param decoratorPath
942
+ * @param state
943
+ */
944
+ function getDecoratedNodeType(decoratorPath, state) {
945
+ const propertyOrMethod = decoratorPath.parentPath;
946
+ if (isClassMethod(propertyOrMethod)) {
947
+ return DECORATOR_TYPES.METHOD;
948
+ }
949
+ else if (isGetterClassMethod(propertyOrMethod)) {
950
+ return DECORATOR_TYPES.GETTER;
951
+ }
952
+ else if (isSetterClassMethod(propertyOrMethod)) {
953
+ return DECORATOR_TYPES.SETTER;
954
+ }
955
+ else if (propertyOrMethod.isClassProperty()) {
956
+ return DECORATOR_TYPES.PROPERTY;
957
+ }
958
+ handleError(propertyOrMethod, {
959
+ errorInfo: errors.DecoratorErrors.INVALID_DECORATOR_TYPE,
960
+ }, state);
961
+ // We should only be here when we are running in errorRecoveryMode
962
+ // otherwise, the handleError method should already "throw"
963
+ // since, we couldn't determine a node type, we will return a null here
964
+ // so we can filter out this node and attempt to proceed with the compilation process
965
+ return null;
966
+ }
967
+ function validateImportedLwcDecoratorUsage(engineImportSpecifiers, state) {
968
+ engineImportSpecifiers
969
+ .filter(({ name }) => isLwcDecoratorName(name))
970
+ .reduce((acc, { name, path }) => {
971
+ // Get a list of all the local references
972
+ const local = path.get('imported');
973
+ const references = getReferences(local).map((reference) => ({
974
+ name,
975
+ reference,
976
+ }));
977
+ return [...acc, ...references];
978
+ }, [])
979
+ .forEach(({ name, reference }) => {
980
+ // Get the decorator from the identifier
981
+ // If the the decorator is:
982
+ // - an identifier @track : the decorator is the parent of the identifier
983
+ // - a call expression @wire("foo") : the decorator is the grand-parent of the identifier
984
+ const decorator = reference.parentPath.isDecorator()
985
+ ? reference.parentPath
986
+ : reference.parentPath.parentPath;
987
+ if (!decorator.isDecorator()) {
988
+ handleError(decorator, {
989
+ errorInfo: errors.DecoratorErrors.IS_NOT_DECORATOR,
990
+ messageArgs: [name],
991
+ }, state);
992
+ }
993
+ const propertyOrMethod = decorator.parentPath;
994
+ if (propertyOrMethod === null ||
995
+ (!propertyOrMethod.isClassProperty() && !propertyOrMethod.isClassMethod())) {
996
+ handleError(propertyOrMethod === null ? decorator : propertyOrMethod, {
997
+ errorInfo: errors.DecoratorErrors.IS_NOT_CLASS_PROPERTY_OR_CLASS_METHOD,
998
+ messageArgs: [name],
999
+ }, state);
1000
+ }
1001
+ });
1002
+ }
1003
+ function isImportedFromLwcSource(bindingPath) {
1004
+ return (bindingPath.isImportSpecifier() &&
1005
+ bindingPath.parent.source.value === 'lwc');
1006
+ }
1007
+ /**
1008
+ * Validate the usage of decorator by calling each validation function
1009
+ * @param decorators
1010
+ * @param state
1011
+ */
1012
+ function validate(decorators, state) {
1013
+ for (const { name, path } of decorators) {
1014
+ const binding = path.scope.getBinding(name);
1015
+ if (binding === undefined || !isImportedFromLwcSource(binding.path)) {
1016
+ handleInvalidDecoratorError(path, state);
1017
+ }
1018
+ }
1019
+ DECORATOR_TRANSFORMS.forEach(({ validate }) => validate(decorators, state));
1020
+ }
1021
+ /**
1022
+ * Remove import specifiers. It also removes the import statement if the specifier list becomes empty
1023
+ * @param engineImportSpecifiers
1024
+ */
1025
+ function removeImportedDecoratorSpecifiers(engineImportSpecifiers) {
1026
+ engineImportSpecifiers
1027
+ .filter(({ name }) => isLwcDecoratorName(name))
1028
+ .forEach(({ path }) => {
1029
+ const importStatement = path.parentPath;
1030
+ path.remove();
1031
+ if (importStatement.get('specifiers').length === 0) {
1032
+ importStatement.remove();
1033
+ }
1034
+ });
1035
+ }
1036
+ function handleInvalidDecoratorError(path, state) {
1037
+ const expressionPath = path.get('expression');
1038
+ const { node } = path;
1039
+ const { expression } = node;
1040
+ let name;
1041
+ if (expressionPath.isIdentifier()) {
1042
+ name = expression.name;
1043
+ }
1044
+ else if (expressionPath.isCallExpression()) {
1045
+ name = expression.callee.name;
1046
+ }
1047
+ if (name) {
1048
+ handleError(path.parentPath, {
1049
+ errorInfo: errors.DecoratorErrors.INVALID_DECORATOR_WITH_NAME,
1050
+ messageArgs: [name, AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
1051
+ }, state);
1052
+ }
1053
+ else {
1054
+ handleError(path.parentPath, {
1055
+ errorInfo: errors.DecoratorErrors.INVALID_DECORATOR,
1056
+ messageArgs: [AVAILABLE_DECORATORS, LWC_PACKAGE_ALIAS],
1057
+ }, state);
1058
+ }
1059
+ }
1060
+ function collectDecoratorPaths(bodyItems) {
1061
+ return bodyItems.reduce((acc, bodyItem) => {
1062
+ const decorators = bodyItem.get('decorators');
1063
+ if (decorators && decorators.length) {
1064
+ acc.push(...decorators);
1065
+ }
1066
+ return acc;
1067
+ }, []);
1068
+ }
1069
+ function getDecoratorMetadata(decoratorPath, state) {
1070
+ const expressionPath = decoratorPath.get('expression');
1071
+ let name;
1072
+ if (expressionPath.isIdentifier()) {
1073
+ name = expressionPath.node.name;
1074
+ }
1075
+ else if (expressionPath.isCallExpression()) {
1076
+ name = expressionPath.node.callee.name;
1077
+ }
1078
+ else {
1079
+ handleInvalidDecoratorError(decoratorPath, state);
1080
+ return null;
1081
+ }
1082
+ const propertyName = decoratorPath.parent.key.name;
1083
+ const decoratedNodeType = getDecoratedNodeType(decoratorPath, state);
1084
+ return {
1085
+ name,
1086
+ propertyName,
1087
+ path: decoratorPath,
1088
+ decoratedNodeType,
1089
+ };
1090
+ }
1091
+ function getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state) {
1092
+ const list = [
1093
+ ...api.transform(t, decoratorMetas, classBodyItems, state),
1094
+ ...track.transform(t, decoratorMetas),
1095
+ ...wire.transform(t, decoratorMetas, state),
1096
+ ];
1097
+ const fieldNames = classBodyItems
1098
+ .filter((field) => field.isClassProperty({ computed: false, static: false }))
1099
+ .filter((field) => !field.node.decorators)
1100
+ .map((field) => field.node.key.name);
1101
+ if (fieldNames.length) {
1102
+ list.push(t.objectProperty(t.identifier('fields'), t.valueToNode(fieldNames)));
1103
+ }
1104
+ return list;
1105
+ }
1106
+ function decorators({ types: t }) {
1107
+ function createRegisterDecoratorsCallExpression(path, classExpression, props) {
1108
+ const id = helperModuleImports.addNamed(path, REGISTER_DECORATORS_ID, LWC_PACKAGE_ALIAS);
1109
+ return t.callExpression(id, [classExpression, t.objectExpression(props)]);
1110
+ }
1111
+ // Babel reinvokes visitors for node reinsertion so we use this to avoid an infinite loop.
1112
+ const visitedClasses = new WeakSet();
1113
+ return {
1114
+ Class(path, state) {
1115
+ const { node } = path;
1116
+ if (visitedClasses.has(node)) {
1117
+ return;
1118
+ }
1119
+ visitedClasses.add(node);
1120
+ const classBodyItems = path.get('body.body');
1121
+ if (classBodyItems.length === 0) {
1122
+ return;
1123
+ }
1124
+ if (node.superClass === null &&
1125
+ shared.isAPIFeatureEnabled(4 /* APIFeature.SKIP_UNNECESSARY_REGISTER_DECORATORS */, shared.getAPIVersionFromNumber(state.opts.apiVersion))) {
1126
+ // Any class exposing a field *must* extend either LightningElement or some other superclass.
1127
+ // Even in the case of superclasses and mixins that expose fields, those must extend something as well.
1128
+ // So we can skip classes without a superclass to avoid adding unnecessary registerDecorators calls.
1129
+ // However, we only do this in later API versions to avoid a breaking change.
1130
+ return;
1131
+ }
1132
+ const decoratorPaths = collectDecoratorPaths(classBodyItems);
1133
+ const decoratorMetas = decoratorPaths
1134
+ .map((path) => getDecoratorMetadata(path, state))
1135
+ .filter((meta) => meta !== null);
1136
+ validate(decoratorMetas, state);
1137
+ const metaPropertyList = getMetadataObjectPropertyList(t, decoratorMetas, classBodyItems, state);
1138
+ if (metaPropertyList.length === 0) {
1139
+ return;
1140
+ }
1141
+ decoratorPaths.forEach((path) => path.remove());
1142
+ const isAnonymousClassDeclaration = path.isClassDeclaration() && !path.get('id').isIdentifier();
1143
+ const shouldTransformAsClassExpression = path.isClassExpression() || isAnonymousClassDeclaration;
1144
+ if (shouldTransformAsClassExpression) {
1145
+ // Example:
1146
+ // export default class extends LightningElement {}
1147
+ // Output:
1148
+ // export default registerDecorators(class extends LightningElement {});
1149
+ // if it does not have an id, we can treat it as a ClassExpression
1150
+ const classExpression = t.toExpression(node);
1151
+ path.replaceWith(createRegisterDecoratorsCallExpression(path, classExpression, metaPropertyList));
1152
+ }
1153
+ else {
1154
+ // Example: export default class NamedClass extends LightningElement {}
1155
+ // Output:
1156
+ // export default class NamedClass extends LightningElement {}
1157
+ // registerDecorators(NamedClass);
1158
+ // Note: This will be further transformed
1159
+ const statementPath = path.getStatementParent();
1160
+ statementPath.insertAfter(t.expressionStatement(createRegisterDecoratorsCallExpression(path, node.id, metaPropertyList)));
1161
+ }
1162
+ },
1163
+ };
1164
+ }
1165
+
1166
+ /*
1167
+ * Copyright (c) 2023, salesforce.com, inc.
1168
+ * All rights reserved.
1169
+ * SPDX-License-Identifier: MIT
1170
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1171
+ */
1172
+ function getImportSource(path) {
1173
+ return path.parentPath.get('arguments.0');
1174
+ }
1175
+ function validateImport(sourcePath, state) {
1176
+ if (!sourcePath.isStringLiteral()) {
1177
+ handleError(sourcePath, {
1178
+ errorInfo: errors.LWCClassErrors.INVALID_DYNAMIC_IMPORT_SOURCE_STRICT,
1179
+ messageArgs: [String(sourcePath)],
1180
+ }, state);
1181
+ }
1182
+ }
1183
+ /**
1184
+ * Expected API for this plugin:
1185
+ * { dynamicImports: { loader: string, strictSpecifier: boolean } }
1186
+ */
1187
+ function dynamicImports () {
1188
+ function getLoaderRef(path, loaderName, state) {
1189
+ if (!state.loaderRef) {
1190
+ state.loaderRef = helperModuleImports.addNamed(path, 'load', loaderName);
1191
+ }
1192
+ return state.loaderRef;
1193
+ }
1194
+ function addDynamicImportDependency(dependency, state) {
1195
+ // TODO [#3444]: state.dynamicImports seems unused and can probably be deleted
1196
+ if (!state.dynamicImports) {
1197
+ state.dynamicImports = [];
1198
+ }
1199
+ if (!state.dynamicImports.includes(dependency)) {
1200
+ state.dynamicImports.push(dependency);
1201
+ }
1202
+ }
1203
+ return {
1204
+ Import(path, state) {
1205
+ const { dynamicImports } = state.opts;
1206
+ if (!dynamicImports) {
1207
+ return;
1208
+ }
1209
+ const { loader, strictSpecifier } = dynamicImports;
1210
+ const sourcePath = getImportSource(path);
1211
+ if (strictSpecifier) {
1212
+ validateImport(sourcePath, state);
1213
+ }
1214
+ if (loader) {
1215
+ const loaderId = getLoaderRef(path, loader, state);
1216
+ path.replaceWith(loaderId);
1217
+ incrementMetricCounter(errors.CompilerMetrics.DynamicImportTransform, state);
1218
+ }
1219
+ if (sourcePath.isStringLiteral()) {
1220
+ addDynamicImportDependency(sourcePath.node.value, state);
1221
+ }
1222
+ },
1223
+ };
1224
+ }
1225
+
1226
+ /*
1227
+ * Copyright (c) 2023, salesforce.com, inc.
1228
+ * All rights reserved.
1229
+ * SPDX-License-Identifier: MIT
1230
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1231
+ */
1232
+ function scopeCssImports ({ types: t }, path) {
1233
+ const programPath = path.isProgram() ? path : path.findParent((node) => node.isProgram());
1234
+ programPath.get('body').forEach((node) => {
1235
+ if (node.isImportDeclaration()) {
1236
+ const source = node.get('source');
1237
+ if (source.type === 'StringLiteral' && source.node.value.endsWith('.scoped.css')) {
1238
+ source.replaceWith(t.stringLiteral(source.node.value + '?scoped=true'));
1239
+ }
1240
+ }
1241
+ });
1242
+ }
1243
+
1244
+ /*
1245
+ * Copyright (c) 2023, salesforce.com, inc.
1246
+ * All rights reserved.
1247
+ * SPDX-License-Identifier: MIT
1248
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1249
+ */
1250
+ function compilerVersionNumber({ types: t }) {
1251
+ return {
1252
+ ClassBody(path) {
1253
+ if (path.parent.superClass === null) {
1254
+ // Components *must* extend from either LightningElement or some other superclass (e.g. a mixin).
1255
+ // We can skip classes without a superclass to avoid adding unnecessary comments.
1256
+ return;
1257
+ }
1258
+ // If the class body is empty, we want an inner comment. Otherwise we want it after the last child
1259
+ // of the class body. In either case, we want it right before the `}` at the end of the function body.
1260
+ if (path.node.body.length > 0) {
1261
+ // E.g. `class Foo extends Lightning Element { /*LWC compiler v1.2.3*/ }`
1262
+ t.addComment(path.node.body[path.node.body.length - 1], 'trailing', shared.LWC_VERSION_COMMENT,
1263
+ /* line */ false);
1264
+ }
1265
+ else {
1266
+ // E.g. `class Foo extends Lightning Element { bar = 'baz'; /*LWC compiler v1.2.3*/ }`
1267
+ t.addComment(path.node, 'inner', shared.LWC_VERSION_COMMENT, /* line */ false);
1268
+ }
1269
+ },
1270
+ };
1271
+ }
1272
+
1273
+ /*
1274
+ * Copyright (c) 2025, salesforce.com, inc.
1275
+ * All rights reserved.
1276
+ * SPDX-License-Identifier: MIT
1277
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1278
+ */
1279
+ // We only transform kind: 'method'. Other kinds ('get', 'set', 'constructor') are left alone.
1280
+ const METHOD_KIND = 'method';
1281
+ /**
1282
+ * Standalone Babel plugin that transforms private method identifiers from
1283
+ * `#privateMethod` to `__lwc_component_class_internal_private_privateMethod`.
1284
+ *
1285
+ * This must be registered BEFORE the main LWC class transform plugin so that
1286
+ * private methods are converted to regular methods before decorator and class
1287
+ * property processing.
1288
+ *
1289
+ * Uses Program > path.traverse() rather than a top-level ClassPrivateMethod visitor
1290
+ * because the reverse transform has a ClassMethod visitor in the same Babel pass.
1291
+ * A direct ClassPrivateMethod visitor would replace nodes that the reverse transform
1292
+ * immediately converts back, creating an infinite loop. The manual traverse ensures
1293
+ * all forward replacements complete before the reverse visitor sees any ClassMethod.
1294
+ */
1295
+ function privateMethodTransform({ types: t, }) {
1296
+ return {
1297
+ visitor: {
1298
+ Program(path, state) {
1299
+ const transformedNames = new Set();
1300
+ // Phase 1: Collect base names of all private methods (kind: 'method')
1301
+ // so that Phase 2 can transform invocations even for forward references
1302
+ // (call site visited before the method definition).
1303
+ const privateMethodBaseNames = new Set();
1304
+ path.traverse({
1305
+ ClassPrivateMethod(methodPath) {
1306
+ const key = methodPath.get('key');
1307
+ if (key.isPrivateName() && methodPath.node.kind === METHOD_KIND) {
1308
+ privateMethodBaseNames.add(key.node.id.name);
1309
+ }
1310
+ },
1311
+ });
1312
+ // Phase 2: Transform definitions and invocations
1313
+ path.traverse({
1314
+ ClassPrivateMethod(methodPath, methodState) {
1315
+ const key = methodPath.get('key');
1316
+ if (!key.isPrivateName()) {
1317
+ return;
1318
+ }
1319
+ if (methodPath.node.kind !== METHOD_KIND) {
1320
+ handleError(methodPath, {
1321
+ errorInfo: errors.DecoratorErrors.UNSUPPORTED_PRIVATE_MEMBER,
1322
+ messageArgs: ['accessor methods'],
1323
+ }, methodState);
1324
+ return;
1325
+ }
1326
+ const node = methodPath.node;
1327
+ // Reject private methods with decorators (e.g. @api, @track, @wire)
1328
+ if (node.decorators && node.decorators.length > 0) {
1329
+ handleError(methodPath, {
1330
+ errorInfo: errors.DecoratorErrors.DECORATOR_ON_PRIVATE_METHOD,
1331
+ }, methodState);
1332
+ return;
1333
+ }
1334
+ const privateName = key.node.id.name;
1335
+ const transformedName = `${PRIVATE_METHOD_PREFIX}${privateName}`;
1336
+ const keyReplacement = t.identifier(transformedName);
1337
+ // Create a new ClassMethod node to replace the ClassPrivateMethod
1338
+ // https://babeljs.io/docs/babel-types#classmethod
1339
+ const classMethod = t.classMethod(METHOD_KIND, keyReplacement, node.params, node.body, node.computed, node.static, node.generator, node.async);
1340
+ copyMethodMetadata(node, classMethod);
1341
+ // Replace the entire ClassPrivateMethod node with the new ClassMethod node
1342
+ // (we can't just replace the key of type PrivateName with type Identifier)
1343
+ methodPath.replaceWith(classMethod);
1344
+ transformedNames.add(transformedName);
1345
+ },
1346
+ MemberExpression(memberPath) {
1347
+ const property = memberPath.node.property;
1348
+ if (t.isPrivateName(property)) {
1349
+ const baseName = property.id.name;
1350
+ if (privateMethodBaseNames.has(baseName)) {
1351
+ const prefixedName = `${PRIVATE_METHOD_PREFIX}${baseName}`;
1352
+ memberPath
1353
+ .get('property')
1354
+ .replaceWith(t.identifier(prefixedName));
1355
+ }
1356
+ }
1357
+ },
1358
+ ClassPrivateProperty(propPath, propState) {
1359
+ handleError(propPath, {
1360
+ errorInfo: errors.DecoratorErrors.UNSUPPORTED_PRIVATE_MEMBER,
1361
+ messageArgs: ['fields'],
1362
+ }, propState);
1363
+ },
1364
+ }, state);
1365
+ state.file.metadata[PRIVATE_METHOD_METADATA_KEY] = transformedNames;
1366
+ },
1367
+ },
1368
+ };
1369
+ }
1370
+
1371
+ /*
1372
+ * Copyright (c) 2025, salesforce.com, inc.
1373
+ * All rights reserved.
1374
+ * SPDX-License-Identifier: MIT
1375
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1376
+ */
1377
+ /**
1378
+ * Standalone Babel plugin that reverses the private method transformation by converting
1379
+ * methods with prefix {@link PRIVATE_METHOD_PREFIX} back to ClassPrivateMethod nodes,
1380
+ * and restoring prefixed MemberExpression properties back to PrivateName nodes.
1381
+ *
1382
+ * This must be registered AFTER @babel/plugin-transform-class-properties so that
1383
+ * class properties are fully transformed before private methods are restored.
1384
+ *
1385
+ * Round-trip parity: to match {@link ./private-method-transform.ts}, this transform must copy the same
1386
+ * properties from ClassMethod onto ClassPrivateMethod when present: returnType, typeParameters, loc,
1387
+ * abstract, access, accessibility, optional, override (plus async, generator, computed from the builder).
1388
+ *
1389
+ * @see {@link ./private-method-transform.ts} for original transformation
1390
+ */
1391
+ function reversePrivateMethodTransform({ types: t, }) {
1392
+ // Scoped to this plugin instance's closure. Safe as long as each Babel run creates a
1393
+ // fresh plugin via LwcReversePrivateMethodTransform(); would accumulate across files if
1394
+ // the same instance were ever reused.
1395
+ const reverseTransformedNames = new Set();
1396
+ return {
1397
+ visitor: {
1398
+ ClassMethod(path, state) {
1399
+ const key = path.get('key');
1400
+ // kind: 'method' | 'get' | 'set' - only 'method' is in scope.
1401
+ if (key.isIdentifier() && path.node.kind === 'method') {
1402
+ const methodName = key.node.name;
1403
+ if (methodName.startsWith(PRIVATE_METHOD_PREFIX)) {
1404
+ const forwardTransformedNames = state.file.metadata[PRIVATE_METHOD_METADATA_KEY];
1405
+ // If the method was not transformed by the forward pass, it is a
1406
+ // user-defined method that collides with the reserved prefix.
1407
+ if (!forwardTransformedNames || !forwardTransformedNames.has(methodName)) {
1408
+ const message = errors.DecoratorErrors.PRIVATE_METHOD_NAME_COLLISION.message.replace('{0}', methodName);
1409
+ throw path.buildCodeFrameError(message);
1410
+ }
1411
+ const originalPrivateName = methodName.replace(PRIVATE_METHOD_PREFIX, '');
1412
+ const node = path.node;
1413
+ const classPrivateMethod = t.classPrivateMethod('method', t.privateName(t.identifier(originalPrivateName)), node.params, node.body, node.static);
1414
+ // Properties the t.classPrivateMethod() builder doesn't accept
1415
+ classPrivateMethod.async = node.async;
1416
+ classPrivateMethod.generator = node.generator;
1417
+ classPrivateMethod.computed = node.computed;
1418
+ copyMethodMetadata(node, classPrivateMethod);
1419
+ path.replaceWith(classPrivateMethod);
1420
+ reverseTransformedNames.add(methodName);
1421
+ }
1422
+ }
1423
+ },
1424
+ MemberExpression(path, state) {
1425
+ const property = path.node.property;
1426
+ if (!t.isIdentifier(property) || !property.name.startsWith(PRIVATE_METHOD_PREFIX)) {
1427
+ return;
1428
+ }
1429
+ const forwardTransformedNames = state.file.metadata[PRIVATE_METHOD_METADATA_KEY];
1430
+ if (!forwardTransformedNames || !forwardTransformedNames.has(property.name)) {
1431
+ return;
1432
+ }
1433
+ const originalName = property.name.replace(PRIVATE_METHOD_PREFIX, '');
1434
+ path.get('property').replaceWith(t.privateName(t.identifier(originalName)));
1435
+ },
1436
+ // After all nodes have been visited, verify that every method the forward transform
1437
+ // renamed was also restored by the reverse transform. A mismatch here means an
1438
+ // intermediate plugin (e.g. @babel/plugin-transform-class-properties) removed or
1439
+ // renamed a prefixed method, leaving a mangled name in the final output.
1440
+ Program: {
1441
+ exit(_path, state) {
1442
+ const forwardTransformedNames = state.file.metadata[PRIVATE_METHOD_METADATA_KEY];
1443
+ if (!forwardTransformedNames) {
1444
+ return;
1445
+ }
1446
+ const missingFromReverse = [];
1447
+ for (const name of forwardTransformedNames) {
1448
+ if (!reverseTransformedNames.has(name)) {
1449
+ missingFromReverse.push(name);
1450
+ }
1451
+ }
1452
+ if (missingFromReverse.length > 0) {
1453
+ throw new Error(`Private method transform count mismatch: ` +
1454
+ `forward transformed ${forwardTransformedNames.size} method(s), ` +
1455
+ `but reverse transformed ${reverseTransformedNames.size}. ` +
1456
+ `Missing reverse transforms for: ${missingFromReverse.join(', ')}`);
1457
+ }
1458
+ },
1459
+ },
1460
+ },
1461
+ };
1462
+ }
1463
+
1464
+ /*
1465
+ * Copyright (c) 2023, salesforce.com, inc.
1466
+ * All rights reserved.
1467
+ * SPDX-License-Identifier: MIT
1468
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
1469
+ */
1470
+ /**
1471
+ * The transform is done in 2 passes:
1472
+ * - First, apply in a single AST traversal the decorators and the component transformation.
1473
+ * - Then, in a second path transform class properties using the official babel plugin "babel-plugin-transform-class-properties".
1474
+ * @param api
1475
+ */
1476
+ function LwcClassTransform(api) {
1477
+ const { ExportDefaultDeclaration: transformCreateRegisterComponent } = component(api);
1478
+ const { Class: transformDecorators } = decorators(api);
1479
+ const { Import: transformDynamicImports } = dynamicImports();
1480
+ const { ClassBody: addCompilerVersionNumber } = compilerVersionNumber(api);
1481
+ return {
1482
+ manipulateOptions(opts, parserOpts) {
1483
+ parserOpts.plugins.push('classProperties', [
1484
+ 'decorators',
1485
+ { decoratorsBeforeExport: true },
1486
+ ]);
1487
+ },
1488
+ visitor: {
1489
+ // The LWC babel plugin is incompatible with other plugins. To get around this, we run the LWC babel plugin
1490
+ // first by running all its traversals from this Program visitor.
1491
+ Program: {
1492
+ enter(path, state) {
1493
+ const engineImportSpecifiers = getEngineImportSpecifiers(path);
1494
+ // Validate the usage of LWC decorators.
1495
+ validateImportedLwcDecoratorUsage(engineImportSpecifiers, state);
1496
+ // Add ?scoped=true to *.scoped.css imports
1497
+ scopeCssImports(api, path);
1498
+ },
1499
+ exit(path) {
1500
+ const engineImportSpecifiers = getEngineImportSpecifiers(path);
1501
+ removeImportedDecoratorSpecifiers(engineImportSpecifiers);
1502
+ },
1503
+ },
1504
+ Import: transformDynamicImports,
1505
+ Class: transformDecorators,
1506
+ ClassBody: addCompilerVersionNumber,
1507
+ ExportDefaultDeclaration: transformCreateRegisterComponent,
1508
+ },
1509
+ };
1510
+ }
1511
+
1512
+ exports.LwcPrivateMethodTransform = privateMethodTransform;
1513
+ exports.LwcReversePrivateMethodTransform = reversePrivateMethodTransform;
1514
+ exports.default = LwcClassTransform;
1515
+ /** version: 9.0.4-alpha.0 */
1516
+ //# sourceMappingURL=index.cjs.map