diff --git a/packages/angular/build/src/tools/angular/linker/oxc-linker.ts b/packages/angular/build/src/tools/angular/linker/oxc-linker.ts index ddadb9b766f4..467a1332cd97 100644 --- a/packages/angular/build/src/tools/angular/linker/oxc-linker.ts +++ b/packages/angular/build/src/tools/angular/linker/oxc-linker.ts @@ -135,7 +135,7 @@ export function linkWithOxc(filename: string, code: string, options: OxcLinkerOp SHARED_LOGGER, SHARED_AST_HOST, astFactory, - { linkerJitMode: options.jit ?? false }, + { linkerJitMode: options.jit ?? false, sourceMapping: false }, ); const fileLinker = new FileLinker(linkerEnvironment, filename as AbsoluteFsPath, code); diff --git a/packages/angular/build/src/tools/angular/linker/string-ast-factory.ts b/packages/angular/build/src/tools/angular/linker/string-ast-factory.ts index 906056bec1c7..a703856c39bd 100644 --- a/packages/angular/build/src/tools/angular/linker/string-ast-factory.ts +++ b/packages/angular/build/src/tools/angular/linker/string-ast-factory.ts @@ -21,6 +21,8 @@ import type { Parameter, } from '@angular/compiler-cli/src/ngtsc/translator/src/api/ast_factory'; +const OBJECT_LITERAL_PREFIX = '\0obj_'; + /** * An implementation of `AstFactory` that generates JavaScript code strings directly. */ @@ -28,10 +30,10 @@ export class StringAstFactory implements AstFactory { constructor(private readonly sourceCode: string = '') {} private render(expr: unknown): string { + let rendered: string; if (typeof expr === 'string') { - return expr; - } - if ( + rendered = expr; + } else if ( typeof expr === 'object' && expr !== null && typeof (expr as { start?: number; end?: number }).start === 'number' && @@ -39,10 +41,16 @@ export class StringAstFactory implements AstFactory { ) { const { start, end } = expr as { start: number; end: number }; - return this.sourceCode.slice(start, end); + rendered = this.sourceCode.slice(start, end); + } else { + rendered = String(expr); } - return String(expr); + if (rendered.startsWith(OBJECT_LITERAL_PREFIX)) { + return rendered.slice(OBJECT_LITERAL_PREFIX.length); + } + + return rendered; } /** @@ -177,8 +185,11 @@ export class StringAstFactory implements AstFactory { createArrowFunctionExpression(parameters: Parameter[], body: unknown): string { const params = parameters.map((p) => p.name).join(', '); + const isObjectLiteral = typeof body === 'string' && body.startsWith(OBJECT_LITERAL_PREFIX); + const renderedBody = this.render(body); + const formattedBody = isObjectLiteral ? `(${renderedBody})` : renderedBody; - return `(${params}) => ${this.render(body)}`; + return `(${params}) => ${formattedBody}`; } createDynamicImport(url: unknown): string { @@ -218,7 +229,7 @@ export class StringAstFactory implements AstFactory { return `${key}: ${this.render(p.value)}`; }); - return `{\n${props.join(',\n')}\n}`; + return `${OBJECT_LITERAL_PREFIX}{\n${props.join(',\n')}\n}`; } createParenthesizedExpression(expression: unknown): string { diff --git a/packages/angular/build/src/tools/angular/linker/string-ast-factory_spec.ts b/packages/angular/build/src/tools/angular/linker/string-ast-factory_spec.ts index c47de303977f..eb62a358dfcd 100644 --- a/packages/angular/build/src/tools/angular/linker/string-ast-factory_spec.ts +++ b/packages/angular/build/src/tools/angular/linker/string-ast-factory_spec.ts @@ -63,7 +63,7 @@ describe('StringAstFactory', () => { { kind: 'property' as const, propertyName: 'foo', value: '1', quoted: false }, { kind: 'property' as const, propertyName: 'foo-bar', value: '2', quoted: true }, ]; - expect(factory.createObjectLiteral(props)).toBe('{\nfoo: 1,\n"foo-bar": 2\n}'); + expect(factory.createObjectLiteral(props)).toContain('{\nfoo: 1,\n"foo-bar": 2\n}'); }); it('should correctly format object literals with spread properties', () => { @@ -71,7 +71,7 @@ describe('StringAstFactory', () => { { kind: 'property' as const, propertyName: 'foo', value: '1', quoted: false }, { kind: 'spread' as const, expression: 'bar' }, ]; - expect(factory.createObjectLiteral(props)).toBe('{\nfoo: 1,\n...bar\n}'); + expect(factory.createObjectLiteral(props)).toContain('{\nfoo: 1,\n...bar\n}'); }); }); @@ -165,6 +165,21 @@ describe('StringAstFactory', () => { expect(factory.createArrowFunctionExpression(params, 'a + b')).toBe('(a, b) => a + b'); }); + it('should parenthesize object literal expression bodies in arrow functions even when containing semicolons', () => { + const params = [{ name: 'a', type: null }]; + const obj = factory.createObjectLiteral([ + { + kind: 'property', + propertyName: 'factory', + value: '() => { return new Service(); }', + quoted: false, + }, + ]); + expect(factory.createArrowFunctionExpression(params, obj)).toBe( + '(a) => ({\nfactory: () => { return new Service(); }\n})', + ); + }); + it('should format statements', () => { expect(factory.createBlock(['foo();', 'bar();'])).toBe('{\nfoo();\nbar();\n}'); expect(factory.createIfStatement('cond', 'foo();', 'bar();')).toBe( diff --git a/packages/angular/build/src/tools/oxc/adjust-typescript-enums_oxc_spec.ts b/packages/angular/build/src/tools/oxc/adjust-typescript-enums_oxc_spec.ts index fc01eecf991a..c074f315d35f 100644 --- a/packages/angular/build/src/tools/oxc/adjust-typescript-enums_oxc_spec.ts +++ b/packages/angular/build/src/tools/oxc/adjust-typescript-enums_oxc_spec.ts @@ -280,4 +280,24 @@ describe('adjust-typescript-enums oxc-transform implementation', () => { `, }), ); + + it( + 'handles TypeScript enums with chained exports assignment (angular-split / shared-docs pattern)', + testCase({ + input: ` + var Area; + (function (a1) { + a1[a1["areaAfter"] = 0] = "areaAfter"; + a1[a1["preserveOtherCategoryOrder"] = 1] = "preserveOtherCategoryOrder"; + })(Area || (Area = exports.Area = {})); + `, + expected: ` + var Area = /*#__PURE__*/ (function (a1) { + a1[(a1["areaAfter"] = 0)] = "areaAfter"; + a1[(a1["preserveOtherCategoryOrder"] = 1)] = "preserveOtherCategoryOrder"; + return a1; + })(Area || (exports.Area = {})); + `, + }), + ); }); diff --git a/packages/angular/build/src/tools/oxc/oxc-transform.ts b/packages/angular/build/src/tools/oxc/oxc-transform.ts index 1c00bb072ddf..64a5aa74062e 100644 --- a/packages/angular/build/src/tools/oxc/oxc-transform.ts +++ b/packages/angular/build/src/tools/oxc/oxc-transform.ts @@ -421,11 +421,14 @@ export function transform(filename: string, code: string, options: OxcTransformO // 3. Remove `Name = ` assignment in arguments if it's a simple identifier if (rightCallArgument.left.type === 'Identifier') { - s.overwrite( - arg.right.start, - arg.right.end, - code.substring(rightCallArgument.right.start, rightCallArgument.right.end), + let replacement = code.substring( + rightCallArgument.right.start, + rightCallArgument.right.end, ); + if (unwrapParentheses(rightCallArgument.right).type === 'AssignmentExpression') { + replacement = `(${replacement})`; + } + s.overwrite(arg.right.start, arg.right.end, replacement); markEdited(arg.right.start, arg.right.end); }