From 0cc53fb39871b6193ac1852d420d22bfebf821a2 Mon Sep 17 00:00:00 2001 From: Alison Gale Date: Tue, 7 Apr 2020 16:44:28 -0700 Subject: [PATCH] fix(upgrade): update $locationShim to handle Location changes before initialization (#36498) Updates the $locationShim to receive the most recent Location change made, even if it happened before initialize() is called. This is important when AngularJS bootstrapping is deferred and there is a delay between when $locationShim is constructed and when it is initialized. With this change, the $locationShim will correctly reflect any redirects that occurred between construction and initialization. Closes #36492 PR Close #36498 --- packages/common/upgrade/src/location_shim.ts | 40 ++++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/common/upgrade/src/location_shim.ts b/packages/common/upgrade/src/location_shim.ts index 7f03b46c0b..de4d3f3a8a 100644 --- a/packages/common/upgrade/src/location_shim.ts +++ b/packages/common/upgrade/src/location_shim.ts @@ -8,6 +8,7 @@ import {Location, LocationStrategy, PlatformLocation} from '@angular/common'; import {UpgradeModule} from '@angular/upgrade/static'; +import {ReplaySubject} from 'rxjs'; import {UrlCodec} from './params'; import {deepEqual, isAnchor, isPromise} from './utils'; @@ -50,7 +51,7 @@ export class $locationShim { private cachedState: unknown = null; - + private urlChanges = new ReplaySubject<{newUrl: string, newState: unknown}>(1); constructor( $injector: any, private location: Location, private platformLocation: PlatformLocation, @@ -71,6 +72,10 @@ export class $locationShim { this.cacheState(); this.$$state = this.browserState(); + this.location.onUrlChange((newUrl, newState) => { + this.urlChanges.next({newUrl, newState}); + }); + if (isPromise($injector)) { $injector.then($i => this.initialize($i)); } else { @@ -88,7 +93,7 @@ export class $locationShim { return; } - let elm: (Node & ParentNode)|null = event.target; + let elm: (Node&ParentNode)|null = event.target; // traverse the DOM up to find first A tag while (elm && elm.nodeName.toLowerCase() !== 'a') { @@ -124,9 +129,9 @@ export class $locationShim { } }); - this.location.onUrlChange((newUrl, newState) => { - let oldUrl = this.absUrl(); - let oldState = this.$$state; + this.urlChanges.subscribe(({newUrl, newState}) => { + const oldUrl = this.absUrl(); + const oldState = this.$$state; this.$$parse(newUrl); newUrl = this.absUrl(); this.$$state = newState; @@ -286,7 +291,9 @@ export class $locationShim { * This function emulates the $browser.state() function from AngularJS. It will cause * history.state to be cached unless changed with deep equality check. */ - private browserState(): unknown { return this.cachedState; } + private browserState(): unknown { + return this.cachedState; + } private stripBaseUrl(base: string, url: string) { if (url.startsWith(base)) { @@ -446,7 +453,9 @@ export class $locationShim { * // => "http://example.com/#/some/path?foo=bar&baz=xoxo" * ``` */ - absUrl(): string { return this.$$absUrl; } + absUrl(): string { + return this.$$absUrl; + } /** * Retrieves the current URL, or sets a new URL. When setting a URL, @@ -488,7 +497,9 @@ export class $locationShim { * // => "http" * ``` */ - protocol(): string { return this.$$protocol; } + protocol(): string { + return this.$$protocol; + } /** * Retrieves the protocol of the current URL. @@ -509,7 +520,9 @@ export class $locationShim { * // => "example.com:8080" * ``` */ - host(): string { return this.$$host; } + host(): string { + return this.$$host; + } /** * Retrieves the port of the current URL. @@ -520,7 +533,9 @@ export class $locationShim { * // => 80 * ``` */ - port(): number|null { return this.$$port; } + port(): number|null { + return this.$$port; + } /** * Retrieves the path of the current URL, or changes the path and returns a reference to its own @@ -553,7 +568,7 @@ export class $locationShim { } /** - * Retrieves a map of the search parameters of the current URL, or changes a search + * Retrieves a map of the search parameters of the current URL, or changes a search * part and returns a reference to its own instance. * * @@ -576,7 +591,8 @@ export class $locationShim { * If the argument is a hash object containing an array of values, these values will be encoded * as duplicate search parameters in the URL. * - * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, then `paramValue` + * @param {(string|Number|Array|boolean)=} paramValue If `search` is a string or number, + * then `paramValue` * will override only a single search property. * * If `paramValue` is an array, it will override the property of the `search` component of