question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`ViewRef#onDestroy` throws an error in a ctor context

See original GitHub issue

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

Already Chau said, ViewRef#onDestroy is untouchable if the app is ONLY in dev mode. https://twitter.com/Nartc1410/status/1527274445056126978

Repro: https://stackblitz.com/edit/angular-ivy-9mzqjg?file=src/main.ts

I’m not sure these are related, injecting ViewRef by inject() is impossible in the ctor context.

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/angular-ivy-9mzqjg?file=src/main.ts

Please provide the exception or error you saw

Error: Uncaught (in promise): TypeError: Cannot add property 0, object is not extensible
TypeError: Cannot add property 0, object is not extensible
at TCleanup.push (<anonymous>)
at listenerInternal (https://angular-ivy-9mzqjg.stackblitz.io/turbo_modules/@angular/core@14.0.0-rc.1/fesm2015/core.mjs:15439:38)

Please provide the environment you discovered this bug in (run ng version)

Angular v14.0.0-rc1

Anything else?

No response

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:3
  • Comments:10 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
AndrewKushnircommented, Jun 6, 2022

@lacolaco we had a conversation about this issue with the team. The ChangeDetectorRef class doesn’t provide the onDestroy method as a public API, so in your example code you are using private APIs (by casting the ChangeDetectorRef to ViewRef). Since there is no public API to trigger the problem, I’m closing the ticket.

3reactions
AndrewKushnircommented, May 24, 2022

@lacolaco thanks for reporting the issue and providing a repro.

I’ve simplified the repro a bit further and found out that the issue is not related to the inject function, but related to the timing of the onDestroy call. Here is a minimal repro:

https://stackblitz.com/edit/angular-ivy-jd7sx8?file=src%2Fapp%2Fapp.component.ts

The runtime code assumes that when the ViewRef.onDestroy function is invoked (typically in users code), the template is already processed and an internal data structure (responsible for storing the cleanup functions) becomes frozen as a way to avoid any accidental modifications (to retain the same shape of the structure, which is important for runtime performance):

https://github.com/angular/angular/blob/c3205d0962f1ff0d2dd4fa26c70372f6fe80f5e3/packages/core/src/render3/instructions/shared.ts#L820-L826

However, this assumption is incorrect when the ViewRef.onDestroy is called from within a constructor (which happens in my repro) or during a class property initialization (which happens in the repro that you provided). I think that Object.freeze operation should have an additional check (possibly the tView.firstCreatePass check).

As a possible solution, you can try to delay the onDestroy call (for example, by wrapping it into Promise.resolve().then(() => ref.onDestroy( ... ))) - that’d allow component’s template to be fully processed before the Object.freeze is invoked.

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found