`ɵzoneWrap` ignores a handler passed as an observer object, and holds a wrapped promise forever once its injector is destroyed
Maintainer thường phản hồi trong vòng 3 ngày
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- angular, firebase, typescript
- Lĩnh vực
- frontend
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- TypeScript
- Star
- 7.8k
- Fork
- 2.2k
- Merge trung bình
- 2 ngày 12 giờ
- Pull request đã merge (30 ngày)
- 24
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của angular/angularfire
-
Document the 22.0.0-rc.1 changesCó thể đã có người làm @armando-navarro đã nhận 3 ngày trước. Đang mởcomp: docs type: chore
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 18/100
angular/angularfire#3834 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
comp: compat comp: ssr comp: zones type: feature version: current (v17+)
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 74/100
angular/angularfire#3832 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Accept firebase 13 in @angular/fire 22Có thể đã có người làm @armando-navarro đã nhận 4 ngày trước. Đang mởcomp: core comp: schematics type: feature
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
angular/angularfire#3830 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
Eleven wrapped callbacks and remote-config `isSupported` hold the app unstable until something that may never happenCó thể đã có người làm @armando-navarro đã nhận 5 ngày trước. Đang mởcomp: app-check comp: core comp: database comp: remote-config comp: ssr comp: zones type: bug version: current (v17+)
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
angular/angularfire#3826 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
comp: compat comp: firestore comp: storage type: chore
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
angular/angularfire#3822 ·
Maintainer thường phản hồi trong vòng 3 ngày
Tất cả issue của angular/angularfire
Issue tương tự
-
needs investigation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 60/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Makefile names visualizer gate targets that do not exist; the TS packages have no test runnerĐang mởarea:visualizer tech-debt
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 66/100
jmbarzee/temporal-architect#292 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
riverqueue/river#1576 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
colbymchenry/codegraph#3228 ·
Maintainer thường phản hồi trong vòng 1 ngày