Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,36 @@ 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.
*/
export class StringAstFactory implements AstFactory<string, unknown, string> {
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' &&
typeof (expr as { end?: number }).end === 'number'
) {
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;
}

/**
Expand Down Expand Up @@ -177,8 +185,11 @@ export class StringAstFactory implements AstFactory<string, unknown, string> {

createArrowFunctionExpression(parameters: Parameter<string>[], 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;
Comment thread
alan-agius4 marked this conversation as resolved.

return `(${params}) => ${this.render(body)}`;
return `(${params}) => ${formattedBody}`;
Comment thread
alan-agius4 marked this conversation as resolved.
}

createDynamicImport(url: unknown): string {
Expand Down Expand Up @@ -218,7 +229,7 @@ export class StringAstFactory implements AstFactory<string, unknown, string> {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ 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', () => {
const props = [
{ 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}');
});
});

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}));
`,
}),
);
});
11 changes: 7 additions & 4 deletions packages/angular/build/src/tools/oxc/oxc-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down