Repository navigation
fix(optimizer): wrap classes whose Angular definitions are static members or static blocks - #604
Conversation
…bers or static blocks
The linker writes partial declarations as `static { this.ɵcmp = … }` blocks inside the class, but
AdjustStaticMembers only wrapped classes followed by downleveled assignments (`X.ɵcmp = …`), so no linked
class was wrapped and esbuild kept every class of a library: importing one component of @deepkit/desktop-ui
bundled ~1 MB instead of ~150 KB. Like the Angular CLI's adjust-static-class-members, a class is now also
wrapped when its static properties and single-assignment static blocks hold Angular definitions, values
marked pure, or pure expressions; a later assignment of an impure value to the class prevents wrapping.
Class declarations are found from the AST rather than by looking for `=` in their text (an `=` in the
body stopped any wrapping), `export class` is handled, and the wrapper is inserted around the class instead
of replacing it, so other passes' edits inside it stay valid.
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c070791ec
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Brooooooklyn
left a comment
There was a problem hiding this comment.
Thanks! Follow-up PR with fixes for the Codex findings coming right after this merges.
|
Fixes for the 4 Codex findings are in #619. |
…class A class followed by `A.ɵfac = f` skipped the class body checks, so an impure superclass, computed key, static field or static block was still wrapped. #604 made `static x = register()` wrap this way; the others were already wrapped before it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…re wrapper (#619) * fix(optimizer): keep classes whose definition runs code out of the pure wrapper A private static field, a static block that is not `this.x = …`, an impure superclass or computed key, a static accessor initializer and class decorators all run when the class is defined, so wrapping the class in a pure IIFE let bundlers drop them. Member reads, logical operators and a few globals now count as pure, like the Angular CLI's isPure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optimizer): accept member reads only in superclasses and computed keys A member read can run a getter, so a static value such as `registry.value` keeps the class unwrapped. Superclasses and computed keys such as `i0.Base` and `Symbol.iterator` still count as pure: the Angular CLI does not check those at all. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optimizer): check the class body when Angular statics follow the class A class followed by `A.ɵfac = f` skipped the class body checks, so an impure superclass, computed key, static field or static block was still wrapped. #604 made `static x = register()` wrap this way; the others were already wrapped before it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(optimizer): narrow pure superclasses and keys, and keep decorated members out A superclass must now be a declared name, and a computed key a literal, a declared name or `Symbol.<name>`: reading `ns.Base` can run a getter, and turning an object key into a string can run its `toString`. Decorators on class members run when the class is defined, so those classes stay too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The linker writes a library's partial declarations as static blocks inside the class:
AdjustStaticMembersonly wrapped classes followed by downleveled assignments (TabsComponent.ɵcmp = …), so no linked class was wrapped in a pure IIFE and the bundler kept every class of a library it couldn't prove unused. In an app importing one component of@deepkit/desktop-uithat was ~1 MB of the library instead of ~150 KB.Like the Angular CLI's
adjust-static-class-membersBabel plugin, a class is now also wrapped when its static properties and single-assignment static blocks hold Angular definitions, values marked/* @__PURE__ */, or pure expressions. A later assignment of an impure value to the class still prevents wrapping.Two related fixes in the same pass:
=in their text, where an=anywhere in the body stopped any wrapping;export classis handled too;New tests in
optimizer/adjust_static_members.rs:wraps_class_with_angular_definitions_in_static_blocks,wraps_exported_class_declarations,wraps_pure_static_values,marked_pure_static_values_wrap,wraps_class_declaration_with_assignments_inside,keeps_static_members_with_side_effects,plain_classes_stay.