Skip to content

vite: async/await is not lowered for zone.js, so fakeAsync/tick cannot control awaits #641

Closed

Description

@edbzn

Summary

@oxc-angular/vite leaves async/await native. zone.js can't patch native await, so in a zone-based app (and in zone-based tests) fakeAsync + tick()/flushMicrotasks() no longer drive code that awaits, and change detection after an await relies on the native promise instead of a zone task. The Angular CLI (esbuild supported: { 'async-await': false } when zone.js is in the polyfills) and Analog (supportedBrowsers → Angular's JavaScriptTransformer) both lower async to generators for this reason.

We hit it moving ~160 Vitest projects from @analogjs/vite-plugin-angular to @oxc-angular/vite: specs like the one below started failing.

Reproduction

// service.ts
@Injectable({ providedIn: 'root' })
export class AuthService {
  constructor(private cognito: Cognito) {}
  async logout() {
    await this.cognito.signOutRedirectUrl();
    await this.cognito.signOut();
  }
}

// service.spec.ts (zone.js + TestBed)
it('signs out', fakeAsync(() => {
  service.logout();
  flushMicrotasks();
  expect(cognito.signOut).toHaveBeenCalled(); // fails with @oxc-angular/vite, passes with Analog / Angular CLI
}));

Actual

signOut is never called inside the fakeAsync zone: the second await resumes on a native microtask the zone doesn't track.

Expected (Angular CLI / Analog)

async functions are emitted as generators (__async(this, null, function* () { ... })), so flushMicrotasks() runs both awaits and the assertion passes.

Notes

  • feat(napi): transformForBrowser - TypeScript with Angular's settings, async lowered for zone.js #607 adds transformForBrowser with exactly this lowering (lowerAsync), but the Vite plugin doesn't call it. Wiring it into the plugin's transform when zone.js is in use (or behind an option) would close this.
  • Workaround today: Vite esbuild: { supported: { 'async-await': false } }. Under Vitest it also needs esbuild's var __async helper rewritten to a function declaration, because vi.mock hoisting moves async mock factories above it (__async is not a function).

Activity

  1. added a commit that references this issue on Oct 27, 2026
    b27594d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions