@angular/build 22.1.0-next.4 → 22.1.0-rc.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.
Files changed (48) hide show
  1. package/package.json +8 -7
  2. package/src/builders/application/chunk-optimizer.js +2 -2
  3. package/src/builders/application/chunk-optimizer.js.map +1 -1
  4. package/src/builders/application/execute-build.js +1 -3
  5. package/src/builders/application/execute-build.js.map +1 -1
  6. package/src/builders/application/inject-debug-ids.js +4 -2
  7. package/src/builders/application/inject-debug-ids.js.map +1 -1
  8. package/src/builders/application/options.js +2 -7
  9. package/src/builders/application/options.js.map +1 -1
  10. package/src/builders/application/schema.d.ts +1 -1
  11. package/src/builders/unit-test/builder.js +0 -3
  12. package/src/builders/unit-test/builder.js.map +1 -1
  13. package/src/builders/unit-test/options.d.ts +2 -2
  14. package/src/builders/unit-test/options.js +15 -5
  15. package/src/builders/unit-test/options.js.map +1 -1
  16. package/src/builders/unit-test/runners/vitest/executor.js +28 -4
  17. package/src/builders/unit-test/runners/vitest/executor.js.map +1 -1
  18. package/src/builders/unit-test/runners/vitest/plugins.js +3 -1
  19. package/src/builders/unit-test/runners/vitest/plugins.js.map +1 -1
  20. package/src/builders/unit-test/schema.d.ts +7 -7
  21. package/src/tools/angular/compilation/aot-compilation.js +11 -1
  22. package/src/tools/angular/compilation/aot-compilation.js.map +1 -1
  23. package/src/tools/babel/plugins/oxc-transform.d.ts +28 -0
  24. package/src/tools/babel/plugins/oxc-transform.js +655 -0
  25. package/src/tools/babel/plugins/oxc-transform.js.map +1 -0
  26. package/src/tools/esbuild/bundler-context.d.ts +10 -0
  27. package/src/tools/esbuild/bundler-context.js +72 -0
  28. package/src/tools/esbuild/bundler-context.js.map +1 -1
  29. package/src/tools/esbuild/global-scripts.js +2 -35
  30. package/src/tools/esbuild/global-scripts.js.map +1 -1
  31. package/src/tools/esbuild/i18n-inliner-worker.js +66 -70
  32. package/src/tools/esbuild/i18n-inliner-worker.js.map +1 -1
  33. package/src/tools/esbuild/javascript-transformer-worker.js +38 -26
  34. package/src/tools/esbuild/javascript-transformer-worker.js.map +1 -1
  35. package/src/tools/sass/rebasing-importer.js +2 -5
  36. package/src/tools/sass/rebasing-importer.js.map +1 -1
  37. package/src/utils/debug-id.d.ts +5 -0
  38. package/src/utils/debug-id.js +11 -3
  39. package/src/utils/debug-id.js.map +1 -1
  40. package/src/utils/index-file/augment-index-html.js +8 -1
  41. package/src/utils/index-file/augment-index-html.js.map +1 -1
  42. package/src/utils/normalize-cache.js +1 -1
  43. package/src/utils/path.d.ts +9 -0
  44. package/src/utils/path.js +17 -0
  45. package/src/utils/path.js.map +1 -1
  46. package/src/utils/source-map.d.ts +7 -0
  47. package/src/utils/source-map.js +84 -0
  48. package/src/utils/source-map.js.map +1 -1
@@ -0,0 +1,655 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.dev/license
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.transform = transform;
14
+ const remapping_1 = __importDefault(require("@ampproject/remapping"));
15
+ const magic_string_1 = require("magic-string");
16
+ const oxc_parser_1 = require("oxc-parser");
17
+ const source_map_1 = require("../../../utils/source-map");
18
+ /**
19
+ * A set of constructor names that are considered to be side-effect free.
20
+ */
21
+ const sideEffectFreeConstructors = new Set(['InjectionToken']);
22
+ /**
23
+ * A set of TypeScript helper function names used by the helper name matcher utility function.
24
+ */
25
+ const tslibHelpers = new Set([
26
+ '__extends',
27
+ '__assign',
28
+ '__rest',
29
+ '__decorate',
30
+ '__param',
31
+ '__esDecorate',
32
+ '__runInitializers',
33
+ '__propKey',
34
+ '__setFunctionName',
35
+ '__metadata',
36
+ '__awaiter',
37
+ '__generator',
38
+ '__exportStar',
39
+ '__values',
40
+ '__read',
41
+ '__privateGet',
42
+ '__privateSet',
43
+ '__privateMethod',
44
+ '__addDisposableResource',
45
+ '__disposeResources',
46
+ ]);
47
+ /**
48
+ * Determines whether an identifier name matches one of the TypeScript helper function names.
49
+ *
50
+ * @param name The identifier name to check.
51
+ * @returns True if the name matches a TypeScript helper name; otherwise, false.
52
+ */
53
+ function isTslibHelperName(name) {
54
+ const nameParts = name.split('$');
55
+ const originalName = nameParts[0];
56
+ if (nameParts.length > 2 || (nameParts.length === 2 && !/^\d+$/.test(nameParts[1]))) {
57
+ return false;
58
+ }
59
+ return tslibHelpers.has(originalName);
60
+ }
61
+ /**
62
+ * A set of Babel helper function names that are intended to cause side effects.
63
+ */
64
+ const babelHelpers = new Set(['_defineProperty']);
65
+ /**
66
+ * Determines whether an identifier name matches one of the Babel helper function names.
67
+ *
68
+ * @param name The identifier name to check.
69
+ * @returns True if the name matches a Babel helper name; otherwise, false.
70
+ */
71
+ function isBabelHelperName(name) {
72
+ return babelHelpers.has(name);
73
+ }
74
+ /**
75
+ * A set of Angular static properties that should be wrapped in pure IIFE statements.
76
+ */
77
+ const angularStaticsToWrap = new Set([
78
+ 'ɵcmp',
79
+ 'ɵdir',
80
+ 'ɵfac',
81
+ 'ɵinj',
82
+ 'ɵmod',
83
+ 'ɵpipe',
84
+ 'ɵprov',
85
+ 'INJECTOR_KEY',
86
+ ]);
87
+ /**
88
+ * A set of Angular metadata decorator functions that can be elided.
89
+ */
90
+ const angularMetadataFunctions = new Set([
91
+ 'ɵsetClassMetadata',
92
+ 'ɵsetClassMetadataAsync',
93
+ 'ɵsetClassDebugInfo',
94
+ ]);
95
+ /**
96
+ * A map of static properties and their matcher predicate functions to check if they
97
+ * can be safely elided from class declarations.
98
+ */
99
+ const angularStaticsToElide = {
100
+ 'ctorParameters'(node) {
101
+ return node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression';
102
+ },
103
+ 'decorators'(node) {
104
+ return node.type === 'ArrayExpression';
105
+ },
106
+ 'propDecorators'(node) {
107
+ return node.type === 'ObjectExpression';
108
+ },
109
+ };
110
+ /**
111
+ * Determines whether an AST node is considered safe for pure evaluation (side-effect free).
112
+ *
113
+ * @param node The AST node to check.
114
+ * @returns True if the node is side-effect free; otherwise, false.
115
+ */
116
+ function isPure(node) {
117
+ switch (node.type) {
118
+ case 'Identifier':
119
+ case 'Literal':
120
+ return true;
121
+ case 'BinaryExpression':
122
+ case 'LogicalExpression':
123
+ return isPure(node.left) && isPure(node.right);
124
+ case 'UnaryExpression':
125
+ return isPure(node.argument);
126
+ case 'MemberExpression':
127
+ return isPure(node.object) && (!node.computed || isPure(node.property));
128
+ case 'ObjectExpression':
129
+ return node.properties.every((p) => p.type === 'Property' && isPure(p.value));
130
+ case 'ArrayExpression':
131
+ return node.elements.every((e) => !e || isPure(e));
132
+ case 'ParenthesizedExpression':
133
+ return isPure(node.expression);
134
+ default:
135
+ return false;
136
+ }
137
+ }
138
+ /**
139
+ * Recursively unwraps any ParenthesizedExpression wrapper nodes to get the inner expression.
140
+ *
141
+ * @param node The potentially parenthesized AST node.
142
+ * @returns The inner non-parenthesized AST node.
143
+ */
144
+ function unwrapParentheses(node) {
145
+ while (node && node.type === 'ParenthesizedExpression') {
146
+ node = node.expression;
147
+ }
148
+ return node;
149
+ }
150
+ /**
151
+ * Determines whether a class static property assignment is safe to be wrapped in a pure IIFE.
152
+ *
153
+ * @param propertyName The name of the property.
154
+ * @param assignmentValue The AST node representing the value assigned.
155
+ * @param code The source code of the file.
156
+ * @returns True if the property can be wrapped safely; otherwise, false.
157
+ */
158
+ function canWrapProperty(propertyName, assignmentValue, code) {
159
+ if (angularStaticsToWrap.has(propertyName)) {
160
+ return true;
161
+ }
162
+ const prefix = code.substring(Math.max(0, assignmentValue.start - 100), assignmentValue.start);
163
+ if (/(\/\*[\s\S]*?(?:@__PURE__|#__PURE__|@pureOrBreakMyCode)[\s\S]*?\*\/)\s*$/.test(prefix)) {
164
+ return true;
165
+ }
166
+ return isPure(assignmentValue);
167
+ }
168
+ /**
169
+ * Analyzes static properties inside a class body to determine if the class has any
170
+ * side-effecting static property initializers.
171
+ *
172
+ * @param classNode The Class AST node.
173
+ * @param code The source code of the file.
174
+ * @returns True if the class static properties are pure and can be wrapped; otherwise, false.
175
+ */
176
+ function analyzeClassStaticProperties(classNode, code) {
177
+ let shouldWrap = false;
178
+ const body = classNode.body.body;
179
+ for (const element of body) {
180
+ if (element.type === 'PropertyDefinition') {
181
+ if (!element.static) {
182
+ continue;
183
+ }
184
+ const key = element.key;
185
+ const value = element.value;
186
+ if (key.type === 'Identifier' && (!value || canWrapProperty(key.name, value, code))) {
187
+ shouldWrap = true;
188
+ }
189
+ else {
190
+ shouldWrap = false;
191
+ break;
192
+ }
193
+ }
194
+ else if (element.type === 'StaticBlock') {
195
+ const blockBody = element.body;
196
+ if (blockBody.length === 0) {
197
+ continue;
198
+ }
199
+ if (blockBody.length > 1) {
200
+ shouldWrap = false;
201
+ break;
202
+ }
203
+ const expressionStatement = blockBody[0];
204
+ if (expressionStatement && expressionStatement.type === 'ExpressionStatement') {
205
+ const assignment = expressionStatement.expression;
206
+ if (assignment &&
207
+ assignment.type === 'AssignmentExpression' &&
208
+ assignment.left.type === 'MemberExpression') {
209
+ const left = assignment.left;
210
+ if (left.object.type === 'ThisExpression' && left.property.type === 'Identifier') {
211
+ if (canWrapProperty(left.property.name, assignment.right, code)) {
212
+ shouldWrap = true;
213
+ continue;
214
+ }
215
+ }
216
+ }
217
+ }
218
+ shouldWrap = false;
219
+ break;
220
+ }
221
+ }
222
+ return shouldWrap;
223
+ }
224
+ /**
225
+ * Executes a single-pass optimized transformation using oxc-parser and magic-string.
226
+ * Performs typescript enum wrapping, static class members elision/wrapping, angular metadata elision,
227
+ * and top-level pure function annotations.
228
+ *
229
+ * @param filename The absolute path of the file being transformed.
230
+ * @param code The string source content of the file.
231
+ * @param options Configuration options specifying which optimization steps to run.
232
+ * @returns The transformed code string and an optional source map.
233
+ */
234
+ // eslint-disable-next-line max-lines-per-function
235
+ function transform(filename, code, options) {
236
+ const { program } = (0, oxc_parser_1.parseSync)(filename, code, { range: true });
237
+ const s = new magic_string_1.MagicString(code);
238
+ const sideEffectFree = options.sideEffects === false;
239
+ const safeAngularPackage = sideEffectFree && /[\\/]node_modules[\\/]@angular[\\/]/.test(filename);
240
+ const topLevelSafeMode = options.topLevelSafeMode ?? false;
241
+ const wrapDecorators = sideEffectFree;
242
+ const pureAnnotate = options.pureAnnotate ?? true;
243
+ /**
244
+ * Scans backwards from the specified start index to check if a pure comment (e.g. `/*@__PURE__*\/`)
245
+ * already precedes the node.
246
+ *
247
+ * @param start The index where the node starts.
248
+ * @returns True if a pure comment is already present; otherwise, false.
249
+ */
250
+ function hasPureComment(start) {
251
+ let i = start - 1;
252
+ while (i >= 0 && /\s/.test(code[i])) {
253
+ i--;
254
+ }
255
+ if (i < 1 || code[i] !== '/' || code[i - 1] !== '*') {
256
+ return false;
257
+ }
258
+ const commentEnd = i + 1;
259
+ const commentStart = code.lastIndexOf('/*', commentEnd);
260
+ if (commentStart === -1) {
261
+ return false;
262
+ }
263
+ const commentContent = code.substring(commentStart + 2, commentEnd - 2);
264
+ return commentContent.includes('@__PURE__') || commentContent.includes('#__PURE__');
265
+ }
266
+ const editedRanges = [];
267
+ /**
268
+ * Records a range in the source code that has been modified, preventing subsequent nested mutations.
269
+ *
270
+ * @param start The start index of the modified range.
271
+ * @param end The end index of the modified range.
272
+ */
273
+ function markEdited(start, end) {
274
+ editedRanges.push({ start, end });
275
+ }
276
+ /**
277
+ * Checks if the specified range falls inside an already modified section of code.
278
+ *
279
+ * @param start The start index of the range.
280
+ * @param end The end index of the range.
281
+ * @returns True if the range is already edited; otherwise, false.
282
+ */
283
+ function isAlreadyEdited(start, end) {
284
+ return editedRanges.some((r) => start >= r.start && end <= r.end);
285
+ }
286
+ // Track function nesting depth and closest function expression wrapper
287
+ let functionDepth = 0;
288
+ let classDepth = 0;
289
+ const functionStack = [];
290
+ /**
291
+ * Scans and rewrites TypeScript emitted enum declarations in the statement block.
292
+ * Wraps enum statements inside a pure IIFE assignable directly to the enum variable.
293
+ *
294
+ * @param body The array of statement AST nodes to process.
295
+ */
296
+ function adjustTypeScriptEnumsInStatements(body) {
297
+ for (let i = 0; i < body.length - 1; i++) {
298
+ const statement = body[i];
299
+ let declStatement = statement;
300
+ if (statement.type === 'ExportNamedDeclaration' &&
301
+ statement.declaration?.type === 'VariableDeclaration') {
302
+ declStatement = statement.declaration;
303
+ }
304
+ if (declStatement.type !== 'VariableDeclaration' ||
305
+ declStatement.kind !== 'var' ||
306
+ declStatement.declarations.length !== 1) {
307
+ continue;
308
+ }
309
+ const decl = declStatement.declarations[0];
310
+ if (decl.init || decl.id.type !== 'Identifier') {
311
+ continue;
312
+ }
313
+ const nextStatement = body[i + 1];
314
+ if (nextStatement.type !== 'ExpressionStatement') {
315
+ continue;
316
+ }
317
+ const nextExpr = unwrapParentheses(nextStatement.expression);
318
+ if (nextExpr.type !== 'CallExpression' || nextExpr.arguments.length !== 1) {
319
+ continue;
320
+ }
321
+ const arg = unwrapParentheses(nextExpr.arguments[0]);
322
+ if (arg.type !== 'LogicalExpression' || arg.operator !== '||') {
323
+ continue;
324
+ }
325
+ const argLeft = unwrapParentheses(arg.left);
326
+ if (argLeft.type !== 'Identifier' || argLeft.name !== decl.id.name) {
327
+ continue;
328
+ }
329
+ const rightCallArgument = unwrapParentheses(arg.right);
330
+ if (rightCallArgument.type !== 'AssignmentExpression') {
331
+ continue;
332
+ }
333
+ const callee = unwrapParentheses(nextExpr.callee);
334
+ if (callee.type !== 'FunctionExpression' ||
335
+ callee.params.length !== 1 ||
336
+ !callee.body ||
337
+ callee.body.type !== 'BlockStatement') {
338
+ continue;
339
+ }
340
+ const param = callee.params[0];
341
+ if (param.type !== 'Identifier') {
342
+ continue;
343
+ }
344
+ const paramName = param.name;
345
+ // Check if all statements in body are pure assignments
346
+ let hasElements = false;
347
+ let allPure = true;
348
+ for (const enumStatement of callee.body.body) {
349
+ if (enumStatement.type !== 'ExpressionStatement') {
350
+ allPure = false;
351
+ break;
352
+ }
353
+ const enumValueAssignment = unwrapParentheses(enumStatement.expression);
354
+ if (enumValueAssignment.type !== 'AssignmentExpression' ||
355
+ !isPure(enumValueAssignment.right)) {
356
+ allPure = false;
357
+ break;
358
+ }
359
+ hasElements = true;
360
+ }
361
+ if (!allPure || !hasElements) {
362
+ continue;
363
+ }
364
+ // 1. Remove only the trailing characters/semicolon of the expression statement
365
+ s.remove(nextExpr.end, nextStatement.end);
366
+ markEdited(nextExpr.end, nextStatement.end);
367
+ // 2. Add return statement inside IIFE body
368
+ s.appendRight(callee.body.end - 1, `; return ${paramName};`);
369
+ // 3. Remove `Name = ` assignment in arguments if it's a simple identifier
370
+ if (rightCallArgument.left.type === 'Identifier') {
371
+ s.overwrite(arg.right.start, arg.right.end, code.substring(rightCallArgument.right.start, rightCallArgument.right.end));
372
+ markEdited(arg.right.start, arg.right.end);
373
+ }
374
+ // 4. Move IIFE to the var initializer
375
+ s.move(nextExpr.start, nextExpr.end, decl.id.end);
376
+ s.appendLeft(decl.id.end, ' = /*#__PURE__*/ ');
377
+ markEdited(nextExpr.start, nextExpr.end);
378
+ }
379
+ }
380
+ /**
381
+ * Scans and rewrites static class member initializers in the statement block.
382
+ * Groups externalized class static assignments into pure wrappers or elides them when safe.
383
+ *
384
+ * @param body The array of statement AST nodes to process.
385
+ */
386
+ function adjustStaticMembersInStatements(body) {
387
+ for (let i = 0; i < body.length; i++) {
388
+ const statement = body[i];
389
+ let classNode = null;
390
+ let isExportDefault = false;
391
+ let isExportNamed = false;
392
+ let isVariableClass = false;
393
+ let classIdName = '';
394
+ if (statement.type === 'ClassDeclaration') {
395
+ classNode = statement;
396
+ classIdName = classNode.id?.name || '';
397
+ }
398
+ else if (statement.type === 'ExportNamedDeclaration' &&
399
+ statement.declaration?.type === 'ClassDeclaration') {
400
+ classNode = statement.declaration;
401
+ classIdName = classNode.id?.name || '';
402
+ isExportNamed = true;
403
+ }
404
+ else if (statement.type === 'ExportDefaultDeclaration' &&
405
+ statement.declaration?.type === 'ClassDeclaration') {
406
+ classNode = statement.declaration;
407
+ classIdName = classNode.id?.name || '';
408
+ isExportDefault = true;
409
+ }
410
+ else if (statement.type === 'VariableDeclaration' && statement.declarations.length === 1) {
411
+ const decl = statement.declarations[0];
412
+ if (decl.init && decl.init.type === 'ClassExpression' && decl.id.type === 'Identifier') {
413
+ classNode = decl.init;
414
+ classIdName = decl.id.name;
415
+ isVariableClass = true;
416
+ }
417
+ }
418
+ if (!classNode || !classIdName) {
419
+ continue;
420
+ }
421
+ const wrapStatementPaths = [];
422
+ let hasPotentialSideEffects = false;
423
+ for (let j = i + 1; j < body.length; j++) {
424
+ const nextStatement = body[j];
425
+ if (nextStatement.type !== 'ExpressionStatement') {
426
+ break;
427
+ }
428
+ const nextExpression = nextStatement.expression;
429
+ // Case 1: __decorate(...)
430
+ if (nextExpression.type === 'CallExpression') {
431
+ if (nextExpression.callee.type !== 'Identifier' ||
432
+ nextExpression.callee.name !== '__decorate') {
433
+ break;
434
+ }
435
+ if (wrapDecorators) {
436
+ wrapStatementPaths.push({ statement: nextStatement, type: 'decorate' });
437
+ }
438
+ else {
439
+ hasPotentialSideEffects = true;
440
+ }
441
+ continue;
442
+ }
443
+ // Case 2: AssignmentExpression
444
+ if (nextExpression.type !== 'AssignmentExpression') {
445
+ break;
446
+ }
447
+ const left = nextExpression.left;
448
+ if (left.type === 'Identifier') {
449
+ if (left.name !== classIdName ||
450
+ nextExpression.right.type !== 'CallExpression' ||
451
+ nextExpression.right.callee.type !== 'Identifier' ||
452
+ nextExpression.right.callee.name !== '__decorate') {
453
+ break;
454
+ }
455
+ if (wrapDecorators) {
456
+ wrapStatementPaths.push({ statement: nextStatement, type: 'decorate' });
457
+ }
458
+ else {
459
+ hasPotentialSideEffects = true;
460
+ }
461
+ continue;
462
+ }
463
+ if (left.type !== 'MemberExpression' ||
464
+ left.object.type !== 'Identifier' ||
465
+ left.object.name !== classIdName ||
466
+ left.property.type !== 'Identifier') {
467
+ break;
468
+ }
469
+ const propertyName = left.property.name;
470
+ const assignmentValue = nextExpression.right;
471
+ if (angularStaticsToElide[propertyName]?.(assignmentValue)) {
472
+ wrapStatementPaths.push({ statement: nextStatement, type: 'elide' });
473
+ }
474
+ else if (canWrapProperty(propertyName, assignmentValue, code)) {
475
+ wrapStatementPaths.push({ statement: nextStatement, type: 'wrap' });
476
+ }
477
+ else {
478
+ hasPotentialSideEffects = true;
479
+ }
480
+ }
481
+ // Check class body static properties
482
+ const shouldWrapClassStaticProperties = analyzeClassStaticProperties(classNode, code);
483
+ // Perform elisions immediately
484
+ for (const item of wrapStatementPaths) {
485
+ if (item.type === 'elide') {
486
+ s.remove(item.statement.start, item.statement.end);
487
+ markEdited(item.statement.start, item.statement.end);
488
+ }
489
+ }
490
+ const activeWrapPaths = wrapStatementPaths.filter((p) => p.type === 'wrap' || p.type === 'decorate');
491
+ if (!hasPotentialSideEffects &&
492
+ (activeWrapPaths.length > 0 || shouldWrapClassStaticProperties)) {
493
+ const lastStatement = activeWrapPaths.length > 0
494
+ ? activeWrapPaths[activeWrapPaths.length - 1].statement
495
+ : classNode;
496
+ if (isExportDefault) {
497
+ // 1. Remove `export default `
498
+ s.overwrite(statement.start, classNode.start, '');
499
+ // 2. Wrap in IIFE
500
+ s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`);
501
+ s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();\nexport { ${classIdName} as default };`);
502
+ }
503
+ else if (isExportNamed) {
504
+ // 1. Export is kept, turn `class` into `let ClassName = IIFE`
505
+ s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`);
506
+ s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`);
507
+ }
508
+ else if (isVariableClass) {
509
+ // Wrap class inside init: `/*#__PURE__*/ (() => { let ClassName = class ClassName {}; return ClassName; })()`
510
+ s.appendLeft(classNode.start, `/*#__PURE__*/ (() => {\nlet ${classIdName} = `);
511
+ const terminator = activeWrapPaths.length === 0 ? ';' : '';
512
+ const iifeClosing = activeWrapPaths.length === 0 ? '})()' : '})();';
513
+ s.appendRight(lastStatement.end, `${terminator}\nreturn ${classIdName};\n${iifeClosing}`);
514
+ }
515
+ else {
516
+ // Standard ClassDeclaration
517
+ s.appendLeft(classNode.start, `let ${classIdName} = /*#__PURE__*/ (() => {\n`);
518
+ s.appendRight(lastStatement.end, `\nreturn ${classIdName};\n})();`);
519
+ }
520
+ markEdited(statement.start, lastStatement.end);
521
+ // Fast-forward outer loop index to skip the statements we wrapped
522
+ i += wrapStatementPaths.length;
523
+ }
524
+ else if (isExportDefault && !hasPotentialSideEffects) {
525
+ // Splitting default export even when not wrapped
526
+ s.overwrite(statement.start, classNode.start, '');
527
+ s.appendRight(classNode.end, `\nexport { ${classIdName} as default };`);
528
+ markEdited(statement.start, classNode.end);
529
+ }
530
+ }
531
+ }
532
+ const visitor = new oxc_parser_1.Visitor({
533
+ ClassDeclaration(node) {
534
+ classDepth++;
535
+ },
536
+ 'ClassDeclaration:exit'() {
537
+ classDepth--;
538
+ },
539
+ ClassExpression(node) {
540
+ classDepth++;
541
+ },
542
+ 'ClassExpression:exit'() {
543
+ classDepth--;
544
+ },
545
+ FunctionDeclaration(node) {
546
+ functionDepth++;
547
+ functionStack.push(node);
548
+ },
549
+ 'FunctionDeclaration:exit'() {
550
+ functionDepth--;
551
+ functionStack.pop();
552
+ },
553
+ FunctionExpression(node) {
554
+ functionDepth++;
555
+ functionStack.push(node);
556
+ },
557
+ 'FunctionExpression:exit'() {
558
+ functionDepth--;
559
+ functionStack.pop();
560
+ },
561
+ ArrowFunctionExpression(node) {
562
+ functionDepth++;
563
+ functionStack.push(node);
564
+ },
565
+ 'ArrowFunctionExpression:exit'() {
566
+ functionDepth--;
567
+ functionStack.pop();
568
+ },
569
+ Program(node) {
570
+ adjustTypeScriptEnumsInStatements(node.body);
571
+ adjustStaticMembersInStatements(node.body);
572
+ },
573
+ BlockStatement(node) {
574
+ adjustTypeScriptEnumsInStatements(node.body);
575
+ adjustStaticMembersInStatements(node.body);
576
+ },
577
+ CallExpression(node) {
578
+ if (isAlreadyEdited(node.start, node.end)) {
579
+ return;
580
+ }
581
+ // 1. Elide Angular Metadata check
582
+ let calleeName;
583
+ if (node.callee.type === 'Identifier') {
584
+ calleeName = node.callee.name;
585
+ }
586
+ else if (node.callee.type === 'MemberExpression' &&
587
+ node.callee.property.type === 'Identifier') {
588
+ calleeName = node.callee.property.name;
589
+ }
590
+ if (calleeName && angularMetadataFunctions.has(calleeName)) {
591
+ const parentFunc = functionStack[functionStack.length - 1];
592
+ if (parentFunc &&
593
+ (parentFunc.type === 'FunctionExpression' ||
594
+ parentFunc.type === 'ArrowFunctionExpression')) {
595
+ s.overwrite(node.start, node.end, 'void 0');
596
+ markEdited(node.start, node.end);
597
+ return;
598
+ }
599
+ }
600
+ // 2. Mark Top-Level Pure Functions check
601
+ if (!pureAnnotate || functionDepth > 0 || classDepth > 0 || topLevelSafeMode) {
602
+ return;
603
+ }
604
+ const callee = unwrapParentheses(node.callee);
605
+ if ((callee.type === 'FunctionExpression' || callee.type === 'ArrowFunctionExpression') &&
606
+ node.arguments.length !== 0) {
607
+ return;
608
+ }
609
+ if (callee.type === 'Identifier' &&
610
+ (isTslibHelperName(callee.name) || isBabelHelperName(callee.name))) {
611
+ return;
612
+ }
613
+ if (!hasPureComment(node.start)) {
614
+ s.appendLeft(node.start, '/*#__PURE__*/ ');
615
+ }
616
+ },
617
+ NewExpression(node) {
618
+ if (!pureAnnotate ||
619
+ functionDepth > 0 ||
620
+ classDepth > 0 ||
621
+ isAlreadyEdited(node.start, node.end)) {
622
+ return;
623
+ }
624
+ if (!topLevelSafeMode) {
625
+ if (!hasPureComment(node.start)) {
626
+ s.appendLeft(node.start, '/*#__PURE__*/ ');
627
+ }
628
+ return;
629
+ }
630
+ const callee = node.callee;
631
+ if (callee.type === 'Identifier' && sideEffectFreeConstructors.has(callee.name)) {
632
+ if (!hasPureComment(node.start)) {
633
+ s.appendLeft(node.start, '/*#__PURE__*/ ');
634
+ }
635
+ }
636
+ },
637
+ });
638
+ visitor.visit(program);
639
+ let map;
640
+ if (options.sourcemap) {
641
+ const rawMap = s.generateMap({ hires: true, source: filename });
642
+ const inputMap = (0, source_map_1.loadInputSourceMap)(filename, code);
643
+ if (inputMap) {
644
+ map = (0, remapping_1.default)([rawMap, inputMap], () => null).toString();
645
+ }
646
+ else {
647
+ map = rawMap.toString();
648
+ }
649
+ }
650
+ return {
651
+ code: s.toString(),
652
+ map,
653
+ };
654
+ }
655
+ //# sourceMappingURL=oxc-transform.js.map