angular: Multi data providers do not work correctly on safari 15.5

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

router

Is this a regression?

I don’t know that.

Description

On my website Angular calls two data providers like this:

const routes: Routes = [
  {
    path: '',
    component: PostComponent,
    resolve: {
      result1: ApiPostLeadResolver,
      result2: ApiPostBodyResolver,
    },
  };

In Google Chrome this code works correctly and in console you can see this two requests, but in Safari 15.5, Angular 13.3.8 calls only ApiPostLeadResolver and incorrectly set the result to this.activatedRoute.snapshot.data.result2.

Please provide a link to a minimal reproduction of the bug

I can’t provide link to a minimal reproduction because here need use backend. But if you open website with DevTools in Chrome and in Safari you can see different during running HTTP requests to resolve the data providers.

Please provide the exception or error you saw

No exception

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

Angular CLI: 13.3.8
Node: 16.15.1
Package Manager: yarn 1.22.1
OS: linux x64

Angular: undefined
... 

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.1303.8
@angular-devkit/core         13.3.8
@angular-devkit/schematics   13.3.8
@schematics/angular          13.3.8
typescript                   4.7.4

Anything else?

This issue is actually reopened from this. @atscott closed it without explaining what information is missing.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 18 (16 by maintainers)

Most upvoted comments

I can reproduce using Safari 15.4, but I’m still unclear on where the culprit is. It’s not multi resolvers, that’s working as expected. The issue is timing sensitive, as putting a breakpoint in the resolver avoids the issue (so the HTTP requests are further apart), but when the issue does occur you’ll observe the following:

image

Concretely, the response body of the first request is reused wholesale for the second request. This seems like a Safari bug, in particular because the URLs are the same and only the Content-Type header differs. It could also be a common/http issue, but then I’d expect this to also occur on Chrome (but since it’s timing sensitive in the first place this is hard to diagnose).

It’s extremely hard to debug the live site as it’s optimized code and a minimum reproduction would be best. I do believe that @angular/router can be removed from the equation, as it should be irrelevant according to my observations thus far.

One thing you could try is to vary the URLs of both endpoints (introduce a second endpoint that you use for the HTML rich content); if that solves the issue then it becomes more likely that this is a race condition in Safari’s resource cache (although disabling the resource cache didn’t seem to matter)

As for Angular I’m going to close this, as there’s no indication that this is an Angular bug.

The best thing would be to create a minimum repro (ideally without Angular to keep it small) that simulates the same scenario (using XMLHttpRequest); if that reproduces in Safari then this should ideally be reported with WebKit.

@KostyaTretyak and @lsap, I do understand that there might be an issue. But unfortunately without a minimal reproduction that showcases the problem this is not actionable from our end.

Providing a URL of a live application for us to debug, will definitely not going to work out for a number of reasons;

  1. The application has a lot of code, which will take significant time to understand
  2. We don’t understand the business logic of your application
  3. The bundle code is minified and obfuscate.

Hence to why a minimal reproduction is paramount.

@KostyaTretyak, I am unable to replicate this locally. Screenshot 2022-07-01 at 13 30 46

You shouldn’t be needing the backend for a minimal repro, you can easily mock/simulate an HTTP operations.

import { of } from 'rxjs';
import { delay, first } from 'rxjs/operators';

of({/*response mock */}).pipe(
  delay(1000),
  first(),
);