`ɵzoneWrap` ignores a handler passed as an observer object, and holds a wrapped promise forever once its injector is destroyed
Mantenedores costumam responder em até 3 dias
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 25/100
- Tipo de issue
- Bug
- Clareza
- Claramente especificada
- Status de atividade
- Estagnada
- Stack de tecnologia
- angular, firebase, typescript
- Domínio
- frontend
Direção de pesquisa
Start by reading src/zones.ts, where ɵzoneWrap handles callbacks and promises. Reproduce the observer-object and destroyed-injector cases described in the issue, then check that object handlers receive the same task, injection-context and zone behavior as function handlers, and that wrapped promises settle after injector destruction. A linked pull request is already open.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Version info
Angular: 22.2
Firebase: 12.19.0
AngularFire: 22.0.0-rc.0, and main
Description
Two defects in ɵzoneWrap (src/zones.ts), the function the generated @angular/fire/* wrappers go through.
1. A handler passed as an object is not wrapped. Firebase accepts a subscription handler either as a function, onSnapshot(ref, snapshot => ...), or as an observer object, onSnapshot(ref, { next: snapshot => ... }). The wrapper rewrites an argument only when typeof is 'function', so the object form reaches the SDK untouched:
- No pending task is registered, so server rendering does not wait for the first value.
inject()throws inside the handler, because nothing re-enters the injection context.- In a zone.js app the handler runs outside the Angular zone, because the wrapper calls Firebase inside
runOutsideAngularand then never brings the object's members back in. The unwrapped Firebase call made from in-zone code keeps its handler in the zone, so the wrapper makes the object form worse than not wrapping at all.
Eleven wrapped functions accept the object form: onAuthStateChanged, onIdTokenChanged, onTokenChanged, onSnapshot, onSnapshotResume, onSnapshotsInSync, onMessage, onRegistered, onUnregistered, onConfigUpdate (which accepts only the object form) and data-connect's subscribe (whose object uses onNext, onErr and onComplete). The three messaging functions are generated with blockUntilFirst: false, so the pending task point does not apply to them.
2. A wrapped promise never settles after its injector is destroyed.
- When a wrapped call returns a Promise, the wrapper resolves its own promise through
runInInjectionContext(injector, () => run(() => resolve(value))). - Neither layer reaches the caller: a
.thencallback runs as a later microtask after the injection context is torn down, and zone.js runs it in the zone where.thenwas attached, not whereresolvewas called. - The one thing the layers do is throw:
runInInjectionContextchecksassertNotDestroyed, so when the Firebase promise settles afterApplicationRef.destroy()or aTestBedreset, the callback throwsNG0205beforeresolveruns and the caller's promise never settles.
How to reproduce these conditions
On a zone.js Angular 22.2 app and a zoneless one, against the Firestore emulator, call the real functions through ɵzoneWrap the way a constructor does, inside the Angular zone and an injection context, and record inside the handler whether a pending task was registered, whether inject() works and whether NgZone.isInAngularZone() is true:
onSnapshot(ref, { next, error })andonSnapshotsInSync(firestore, { next, error }): no task in either app,inject()throws in both, and in the zone.js app the handler runs outside the Angular zone. A plain property written from the handler does not render there, in a component with default change detection.onSnapshot(ref, next), the function form: one task, released when the handler ran,inject()works, and in the zone.js app the handler runs inside the zone.- The unwrapped
onSnapshotwith either form of handler, called from the same place:inject()throws, but in the zone.js app the handler stays inside the zone.
For the promise defect, a spec: wrap a function that resolves after 20 ms with ɵzoneWrap(fn, true), call it inside TestBed.runInInjectionContext, call TestBed.resetTestingModule(), then await the returned promise. It never settles and the spec times out after 5 seconds.
Expected behavior
A handler passed as an observer object gets what a handler passed as a function gets: the pending task, the Angular zone and a working inject(). A wrapped promise settles whenever the Firebase promise settles.
Actual behavior
The object form gets none of the three, and a wrapped promise that settles after its injector is destroyed never settles.
- Linguagem predominante
- TypeScript
- Estrelas
- 7.8k
- Forks
- 2.2k
- Merge médio
- 2d 12h
- PRs com merge (30d)
- 24
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Tem um modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de angular/angularfire
-
Document the 22.0.0-rc.1 changesTalvez já em andamento @armando-navarro assumiu há 3 dias. Abertacomp: docs type: chore
Dificuldade 3/5 Meio dia Facilidade para iniciantes 18/100
angular/angularfire#3834 ·
Mantenedores costumam responder em até 3 dias
-
comp: compat comp: ssr comp: zones type: feature version: current (v17+)
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 74/100
angular/angularfire#3832 ·
Mantenedores costumam responder em até 3 dias
-
Accept firebase 13 in @angular/fire 22Talvez já em andamento @armando-navarro assumiu há 3 dias. Abertacomp: core comp: schematics type: feature
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 25/100
angular/angularfire#3830 ·
Mantenedores costumam responder em até 3 dias
-
Eleven wrapped callbacks and remote-config `isSupported` hold the app unstable until something that may never happenTalvez já em andamento @armando-navarro assumiu há 4 dias. Abertacomp: app-check comp: core comp: database comp: remote-config comp: ssr comp: zones type: bug version: current (v17+)
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 48/100
angular/angularfire#3826 ·
Mantenedores costumam responder em até 3 dias
-
comp: compat comp: firestore comp: storage type: chore
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 48/100
angular/angularfire#3822 ·
Mantenedores costumam responder em até 3 dias
Todas as issues de angular/angularfire
Issues semelhantes
-
ci-cd desktop size:low telemetry-improvement telemetry-round-1
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 66/100
vfarcic/dot-agent-deck#2079 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
Mantenedores costumam responder em até 1 dia
-
Broken links in the docsAberta
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 83/100
Mantenedores costumam responder em até 1 dia
-
status:in-linear
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100
n8n-io/n8n#43006 · 3 comentários ·
Mantenedores costumam responder em até 1 dia
-
🔊 a11y
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 82/100
betagouv/mon-entreprise#4726 ·
Mantenedores costumam responder em até 9 dias