Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): build optimizer support for non s…
Browse files Browse the repository at this point in the history
…pec-compliant ES2022 class static properties

The build optimizer's static field pass will now additionally wrap classes that contain side effect free TypeScript ES2022 static class properties.

This is needed to update APF to ship ES2022, which have `useDefineForClassFields` set to `false`.

(cherry picked from commit 3978891)
  • Loading branch information
alan-agius4 authored and clydin committed Mar 7, 2023
1 parent dfd03aa commit eb22f63
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
Expand Up @@ -205,6 +205,7 @@ const exportDefaultAnalysis = new WeakMap<types.Class, ReturnType<typeof analyze
*
* @returns A babel plugin object instance.
*/
// eslint-disable-next-line max-lines-per-function
export default function (): PluginObj {
return {
visitor: {
Expand Down Expand Up @@ -278,6 +279,47 @@ export default function (): PluginObj {
shouldWrap = false;
break;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} else if ((element as any).isStaticBlock()) {
// Only need to analyze static blocks
const body = element.get('body');

if (Array.isArray(body) && body.length > 1) {
// Not safe to wrap
shouldWrap = false;
break;
}

const expression = body.find((n: NodePath<types.Node>) =>
n.isExpressionStatement(),
) as NodePath<types.ExpressionStatement> | undefined;

const assignmentExpression = expression?.get('expression');
if (assignmentExpression?.isAssignmentExpression()) {
const left = assignmentExpression.get('left');
if (!left.isMemberExpression()) {
continue;
}

if (!left.get('object').isThisExpression()) {
// Not safe to wrap
shouldWrap = false;
break;
}

const element = left.get('property');
const right = assignmentExpression.get('right');
if (
element.isIdentifier() &&
(!right.isExpression() || canWrapProperty(element.node.name, right))
) {
shouldWrap = true;
} else {
// Not safe to wrap
shouldWrap = false;
break;
}
}
}
}
if (!shouldWrap) {
Expand Down
Expand Up @@ -669,6 +669,42 @@ describe('adjust-static-class-members Babel plugin', () => {
});
});

it('wraps class with Angular ɵfac static block (ES2022 + useDefineForClassFields: false)', () => {
testCase({
input: `
class CommonModule {
static { this.ɵfac = function CommonModule_Factory(t) { return new (t || CommonModule)(); }; }
static { this.ɵmod = ɵngcc0.ɵɵdefineNgModule({ type: CommonModule }); }
}
`,
expected: `
let CommonModule = /*#__PURE__*/ (() => {
class CommonModule {
static {
this.ɵfac = function CommonModule_Factory(t) {
return new (t || CommonModule)();
};
}
static {
this.ɵmod = ɵngcc0.ɵɵdefineNgModule({
type: CommonModule,
});
}
}
return CommonModule;
})();
`,
});
});

it('does not wrap class with side effect full static block (ES2022 + useDefineForClassFields: false)', () => {
testCaseNoChange(`
class CommonModule {
static { globalThis.bar = 1 }
}
`);
});

it('wraps class with Angular ɵmod static field', () => {
testCase({
input: `
Expand Down

0 comments on commit eb22f63

Please sign in to comment.