Skip to content

refactor: change public const enums to enums#51670

Closed
frigus02 wants to merge 1 commit intoangular:mainfrom
frigus02:const-enums
Closed

refactor: change public const enums to enums#51670
frigus02 wants to merge 1 commit intoangular:mainfrom
frigus02:const-enums

Conversation

@frigus02
Copy link
Contributor

@frigus02 frigus02 commented Sep 6, 2023

Angular recently gained a local compilation mode (see commit 345dd6d). This is intended to be used with the TypeScript compiler option isolatedModules, which bans imports of const enums.

This changes all const enums tagged with @publicapi to regular enums.

Fixes #46240

PR Checklist

PR Type

  • Refactoring (no functional changes, no api changes)

What is the current behavior?

Issue Number: #46240

Importing any of those const enums under isolatedModules results in the error

TS2748: Cannot access ambient const enums when 'isolatedModules' is enabled.

What is the new behavior?

No error.

Does this PR introduce a breaking change?

  • Yes
  • No
  • Maybe. The change won't result in new TypeScript compiler errors. But it changes the JavaScript emit. If projects relied on the inlining behavior of const enums, then this will result in breakages.

@jessicajaniuk jessicajaniuk added area: animations area: router area: core Issues related to the framework runtime labels Sep 6, 2023
@ngbot ngbot bot modified the milestone: Backlog Sep 6, 2023
@jessicajaniuk
Copy link
Contributor

@frigus02 Looks like you'll need to fix your commit messages to match lint requirements.

@frigus02
Copy link
Contributor Author

frigus02 commented Sep 6, 2023

The lint is very picky 🙂. I squashed the commits. Hope that's okay.

Is this change okay in general? Depending on how you see it, this could be a breaking change. But it would be really really really good to have.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one in particular is super sad not to have as const enum, since it has so many variants and therefore quite a code size overhead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Google internal we use Closure Compiler, which inlines enums anyway, so this is not an issue. Do we know what the more popular bundlers & minifiers do? Can they inline enums, too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like esbuild does inline them:

$ cat test.ts
const enum Const { A = 1 }
enum Regular { A = 1 }
console.log(Const.A, Regular.A);
export {};
$ ./node_modules/.bin/esbuild ./test.ts --bundle --minify
(()=>{console.log(1,1);})();

Copy link
Member

@JoostK JoostK Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that is cool! It even works with code splitting enabled in esbuild. It's been supported since 0.14.9.

Copy link
Member

@alxhub alxhub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed-for: global-approvers

Okaying this as a public API change post-freeze for v17. It should have no impact on consumers (besides bundle size, which depends on the inlining behavior and as mentioned in comments, seems to be optimal with esbuild & Closure, at least).

Long-term, relying on const enum semantics seems unnecessary. It should be the optimizer's job to inline constants and remove unused references, not TypeScript's.

@frigus02 frigus02 force-pushed the const-enums branch 2 times, most recently from 977c2af to f541a99 Compare October 19, 2023 08:40
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff caused by enum--- /tmp/old.js 2023-10-19 08:08:33.412077045 +0000 +++ /tmp/new.js 2023-10-19 08:09:01.282909097 +0000 @@ -1,56 +1,66 @@ 'use strict'; (self.webpackChunkanimations = self.webpackChunkanimations || []).push([ ['default-node_modules_angular_animations_fesm2022_animations_mjs'], { - 825: (E, a, h) => { - h.d(a, { - SB: () => y, - X$: () => u, - ZE: () => g, + 825: (w, h, l) => { + l.d(h, { + SB: () => m, + X$: () => _, + ZE: () => S, ZN: () => D, - eR: () => f, - jt: () => d, - k1: () => A, - l3: () => l, - oB: () => c, - vP: () => _ + eR: () => y, + jt: () => c, + k1: () => E, + l3: () => u, + mo: () => i, + oB: () => f, + vP: () => d }); - const l = '*'; - function u(n, t) { + var i = function(s) { + return s[s.State = 0] = 'State', s[s.Transition = 1] = 'Transition', + s[s.Sequence = 2] = 'Sequence', s[s.Group = 3] = 'Group', + s[s.Animate = 4] = 'Animate', s[s.Keyframes = 5] = 'Keyframes', + s[s.Style = 6] = 'Style', s[s.Trigger = 7] = 'Trigger', + s[s.Reference = 8] = 'Reference', s[s.AnimateChild = 9] = 'AnimateChild', + s[s.AnimateRef = 10] = 'AnimateRef', s[s.Query = 11] = 'Query', + s[s.Stagger = 12] = 'Stagger', s + }(i || {}); + const u = '*'; + function _(s, t) { return { - type: 7, name: n, definitions: t, options: {} + type: i.Trigger, name: s, definitions: t, options: {} } } - function d(n, t = null) { + function c(s, t = null) { return { - type: 4, styles: t, timings: n + type: i.Animate, styles: t, timings: s } } - function _(n, t = null) { + function d(s, t = null) { return { - type: 2, steps: n, options: t + type: i.Sequence, steps: s, options: t } } - function c(n) { + function f(s) { return { - type: 6, styles: n, offset: null + type: i.Style, styles: s, offset: null } } - function y(n, t, i) { + function m(s, t, e) { return { - type: 0, name: n, styles: t, options: i + type: i.State, name: s, styles: t, options: e } } - function f(n, t, i = null) { + function y(s, t, e = null) { return { - type: 1, expr: n, animation: t, options: i + type: i.Transition, expr: s, animation: t, options: e } } class D { - constructor(t = 0, i = 0) { + constructor(t = 0, e = 0) { this._onDoneFns = [], this._onStartFns = [], this._onDestroyFns = [], this._originalOnDoneFns = [], this._originalOnStartFns = [], this._started = !1, this._destroyed = !1, this._finished = !1, this._position = 0, this.parentPlayer = null, - this.totalTime = t + i + this.totalTime = t + e } _onFinish() { this._finished || @@ -99,23 +109,23 @@ return this.totalTime ? this._position / this.totalTime : 1 } triggerCallback(t) { - const i = 'start' == t ? this._onStartFns : this._onDoneFns; - i.forEach(e => e()), i.length = 0 + const e = 'start' == t ? this._onStartFns : this._onDoneFns; + e.forEach(n => n()), e.length = 0 } } - class g { + class S { constructor(t) { this._onDoneFns = [], this._onStartFns = [], this._finished = !1, this._started = !1, this._destroyed = !1, this._onDestroyFns = [], this.parentPlayer = null, this.totalTime = 0, this.players = t; - let i = 0, e = 0, s = 0; + let e = 0, n = 0, r = 0; const o = this.players.length; - 0 == o ? queueMicrotask(() => this._onFinish()) : this.players.forEach(r => { - r.onDone(() => {++i == o && this._onFinish()}), - r.onDestroy(() => {++e == o && this._onDestroy()}), - r.onStart(() => {++s == o && this._onStart()}) + 0 == o ? queueMicrotask(() => this._onFinish()) : this.players.forEach(a => { + a.onDone(() => {++e == o && this._onFinish()}), + a.onDestroy(() => {++n == o && this._onDestroy()}), + a.onStart(() => {++r == o && this._onStart()}) }), - this.totalTime = this.players.reduce((r, S) => Math.max(r, S.totalTime), 0) + this.totalTime = this.players.reduce((a, P) => Math.max(a, P.totalTime), 0) } _onFinish() { this._finished || @@ -165,26 +175,26 @@ this._started = !1 } setPosition(t) { - const i = t * this.totalTime; - this.players.forEach(e => { - const s = e.totalTime ? Math.min(1, i / e.totalTime) : 1; - e.setPosition(s) + const e = t * this.totalTime; + this.players.forEach(n => { + const r = n.totalTime ? Math.min(1, e / n.totalTime) : 1; + n.setPosition(r) }) } getPosition() { const t = - this.players.reduce((i, e) => null === i || e.totalTime > i.totalTime ? e : i, null); + this.players.reduce((e, n) => null === e || n.totalTime > e.totalTime ? n : e, null); return null != t ? t.getPosition() : 0 } beforeDestroy() { this.players.forEach(t => {t.beforeDestroy && t.beforeDestroy()}) } triggerCallback(t) { - const i = 'start' == t ? this._onStartFns : this._onDoneFns; - i.forEach(e => e()), i.length = 0 + const e = 'start' == t ? this._onStartFns : this._onDoneFns; + e.forEach(n => n()), e.length = 0 } } - const A = '!' + const E = '!' } } ]); \ No newline at end of file

@frigus02
Copy link
Contributor Author

Thanks for the review, Alex. I rebased and fixed the tests.

@pmvald pmvald added action: merge The PR is ready for merge by the caretaker target: minor This PR is targeted for the next minor release PullApprove: disable labels Oct 19, 2023
Angular recently gained a local compilation mode (see commit
345dd6d). This is intended to be used
with the TypeScript compiler option isolatedModules, which bans imports
of const enums.

This changes all const enums tagged with @publicapi to regular enums.

Fixes angular#46240
@angular-robot angular-robot bot requested a review from alxhub October 25, 2023 15:57
@pmvald pmvald removed the request for review from alxhub October 25, 2023 16:15
@dylhunn
Copy link
Contributor

dylhunn commented Oct 25, 2023

This PR was merged into the repository by commit ebbc7a2.

@dylhunn dylhunn closed this in ebbc7a2 Oct 25, 2023
@frigus02 frigus02 deleted the const-enums branch October 26, 2023 09:17
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Nov 26, 2023
ChellappanRajan pushed a commit to ChellappanRajan/angular that referenced this pull request Jan 23, 2024
Angular recently gained a local compilation mode (see commit
345dd6d). This is intended to be used
with the TypeScript compiler option isolatedModules, which bans imports
of const enums.

This changes all const enums tagged with @publicapi to regular enums.

Fixes angular#46240

PR Close angular#51670
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker area: animations area: core Issues related to the framework runtime area: router PullApprove: disable target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(typings): typescript isolatedModules option not working anymore with 14.0.0

6 participants