Skip to content

Commit 329d270

Browse files
committed
Remove browser update from watcher
1 parent a1ac764 commit 329d270

File tree

5 files changed

+88
-80
lines changed

5 files changed

+88
-80
lines changed

src/core/location/location.js

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { JQLite } from "../../shared/jqlite/jqlite";
22
import { urlResolve } from "../url-utils/url-utils";
33
import {
44
encodeUriSegment,
5-
isBoolean,
65
isDefined,
76
isNumber,
87
isObject,
@@ -330,7 +329,6 @@ export class Location {
330329
// so the modification window is narrow.
331330
this.$$state = isUndefined(state) ? null : state;
332331
this.$$urlUpdatedByLocation = true;
333-
334332
return this;
335333
}
336334

@@ -544,26 +542,28 @@ export class LocationHashbangUrl extends Location {
544542
}
545543
}
546544

547-
export function LocationProvider() {
548-
let hashPrefix = "!";
549-
const html5Mode = {
550-
enabled: false,
551-
requireBase: true,
552-
rewriteLinks: true,
553-
};
545+
export class LocationProvider {
546+
constructor() {
547+
this.hashPrefixValue = "!";
548+
this.html5ModeConfig = {
549+
enabled: false,
550+
requireBase: true,
551+
rewriteLinks: true,
552+
};
553+
}
554554

555555
/**
556556
* The default value for the prefix is `'!'`.
557-
* @param {string=} prefix Prefix for hash part (containing path and search)
558-
* @returns {*} current value if used as getter or itself (chaining) if used as setter
557+
* @param {string=} prefix - Prefix for hash part (containing path and search)
558+
* @returns {string|LocationProvider} current value if used as getter or itself (chaining) if used as setter
559559
*/
560-
this.hashPrefix = function (prefix) {
561-
if (isDefined(prefix)) {
562-
hashPrefix = prefix;
560+
hashPrefix(prefix) {
561+
if (typeof prefix !== "undefined") {
562+
this.hashPrefixValue = prefix;
563563
return this;
564564
}
565-
return hashPrefix;
566-
};
565+
return this.hashPrefixValue;
566+
}
567567

568568
/**
569569
* @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
@@ -585,30 +585,29 @@ export function LocationProvider() {
585585
*
586586
* @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
587587
*/
588-
this.html5Mode = function (mode) {
589-
if (isBoolean(mode)) {
590-
html5Mode.enabled = mode;
588+
html5Mode(mode) {
589+
if (typeof mode === "boolean") {
590+
this.html5ModeConfig.enabled = mode;
591591
return this;
592592
}
593-
if (isObject(mode)) {
594-
if (isBoolean(mode.enabled)) {
595-
html5Mode.enabled = mode.enabled;
596-
}
597593

598-
if (isBoolean(mode.requireBase)) {
599-
html5Mode.requireBase = mode.requireBase;
600-
}
601-
602-
if (isBoolean(mode.rewriteLinks) || isString(mode.rewriteLinks)) {
603-
html5Mode.rewriteLinks = mode.rewriteLinks;
594+
if (typeof mode === "object") {
595+
if (typeof mode.enabled === "boolean")
596+
this.html5ModeConfig.enabled = mode.enabled;
597+
if (typeof mode.requireBase === "boolean")
598+
this.html5ModeConfig.requireBase = mode.requireBase;
599+
if (
600+
typeof mode.rewriteLinks === "boolean" ||
601+
typeof mode.rewriteLinks === "string"
602+
) {
603+
this.html5ModeConfig.rewriteLinks = mode.rewriteLinks;
604604
}
605-
606605
return this;
607606
}
608-
return html5Mode;
609-
};
607+
return this.html5ModeConfig;
608+
}
610609

611-
this.$get = [
610+
$get = [
612611
"$rootScope",
613612
"$browser",
614613
"$rootElement",
@@ -627,8 +626,8 @@ export function LocationProvider() {
627626
const initialUrl = /** @type {string} */ ($browser.url());
628627
let appBase;
629628

630-
if (html5Mode.enabled) {
631-
if (!baseHref && html5Mode.requireBase) {
629+
if (this.html5Mode.enabled) {
630+
if (!baseHref && this.html5Mode.requireBase) {
632631
throw $locationMinErr(
633632
"nobase",
634633
"$location in HTML5 mode requires a <base> tag to be present!",
@@ -642,7 +641,11 @@ export function LocationProvider() {
642641
}
643642
const appBaseNoFile = stripFile(appBase);
644643

645-
$location = new LocationMode(appBase, appBaseNoFile, `#${hashPrefix}`);
644+
$location = new LocationMode(
645+
appBase,
646+
appBaseNoFile,
647+
`#${this.hashPrefix}`,
648+
);
646649
$location.$$parseLinkUrl(initialUrl, initialUrl);
647650

648651
$location.$$state = $browser.state();
@@ -669,7 +672,7 @@ export function LocationProvider() {
669672
}
670673

671674
$rootElement.on("click", (event) => {
672-
const { rewriteLinks } = html5Mode;
675+
const { rewriteLinks } = this.html5Mode;
673676
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
674677
// currently we open nice url link and redirect then
675678

@@ -772,7 +775,7 @@ export function LocationProvider() {
772775
});
773776

774777
// update browser
775-
$rootScope.$watch(() => {
778+
function browserUpdate() {
776779
if (initializing || $location.$$urlUpdatedByLocation) {
777780
$location.$$urlUpdatedByLocation = false;
778781

@@ -820,7 +823,9 @@ export function LocationProvider() {
820823

821824
// we don't need to return anything because $evalAsync will make the digest loop dirty when
822825
// there is a change
823-
});
826+
}
827+
828+
setTimeout(() => browserUpdate());
824829

825830
return $location;
826831

@@ -832,6 +837,7 @@ export function LocationProvider() {
832837
$location.$$state,
833838
oldState,
834839
);
840+
browserUpdate();
835841
}
836842
},
837843
];

src/core/url-utils/url-utils.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe("urlUtils", () => {
6565

6666
expectIsSameOrigin("path", true);
6767

68-
const origin = urlResolve(document.location.href);
68+
const origin = urlResolve(window.location.href);
6969
expectIsSameOrigin(`//${origin.host}/path`, true);
7070

7171
// Different domain.

src/router/state/state.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { test, expect } from "@playwright/test";
22

3-
const TEST_URL = "src/router/state/state.html";
3+
const TEST_URL = "src/router/state/state.html?random=false";
44

55
test("unit tests contain no errors", async ({ page }) => {
66
await page.goto(TEST_URL);

src/services/browser.js

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,12 @@ export class Browser {
110110
* @private
111111
*/
112112
cacheState() {
113-
this.cachedState = history.state;
114-
this.cachedState = this.cachedState === undefined ? null : this.cachedState;
115-
116-
if (equals(this.cachedState, this.lastCachedState)) {
117-
this.cachedState = this.lastCachedState;
113+
const currentState = history.state ?? null;
114+
if (!equals(currentState, this.lastCachedState)) {
115+
this.cachedState = currentState;
116+
this.lastCachedState = currentState;
117+
this.lastHistoryState = currentState;
118118
}
119-
120-
this.lastCachedState = this.cachedState;
121-
this.lastHistoryState = this.cachedState;
122119
}
123120

124121
/**

types/core/location/location.d.ts

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,3 @@
1-
export function LocationProvider(): void;
2-
export class LocationProvider {
3-
/**
4-
* The default value for the prefix is `'!'`.
5-
* @param {string=} prefix Prefix for hash part (containing path and search)
6-
* @returns {*} current value if used as getter or itself (chaining) if used as setter
7-
*/
8-
hashPrefix: (prefix?: string | undefined) => any;
9-
/**
10-
* @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
11-
* If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
12-
* properties:
13-
* - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
14-
* change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
15-
* support `pushState`.
16-
* - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
17-
* whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
18-
* true, and a base tag is not present, an error will be thrown when `$location` is injected.
19-
* See the {@link guide/$location $location guide for more information}
20-
* - **rewriteLinks** - `{boolean|string}` - (default: `true`) When html5Mode is enabled,
21-
* enables/disables URL rewriting for relative links. If set to a string, URL rewriting will
22-
* only happen on links with an attribute that matches the given string. For example, if set
23-
* to `'internal-link'`, then the URL will only be rewritten for `<a internal-link>` links.
24-
* Note that [attribute name normalization](guide/directive#normalization) does not apply
25-
* here, so `'internalLink'` will **not** match `'internal-link'`.
26-
*
27-
* @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
28-
*/
29-
html5Mode: (mode?: (boolean | any) | undefined) => any;
30-
$get: (string | (($rootScope: import("../scope/scope").Scope, $browser: import("../../services/browser").Browser, $rootElement: JQLite) => Location))[];
31-
}
321
/**
332
*
343
* @param {string} base
@@ -276,6 +245,42 @@ export class LocationHashbangUrl extends Location {
276245
*/
277246
$$parseLinkUrl(url: string): boolean;
278247
}
248+
export class LocationProvider {
249+
hashPrefixValue: string;
250+
html5ModeConfig: {
251+
enabled: boolean;
252+
requireBase: boolean;
253+
rewriteLinks: boolean;
254+
};
255+
/**
256+
* The default value for the prefix is `'!'`.
257+
* @param {string=} prefix - Prefix for hash part (containing path and search)
258+
* @returns {string|LocationProvider} current value if used as getter or itself (chaining) if used as setter
259+
*/
260+
hashPrefix(prefix?: string | undefined): string | LocationProvider;
261+
/**
262+
* @param {(boolean|Object)=} mode If boolean, sets `html5Mode.enabled` to value.
263+
* If object, sets `enabled`, `requireBase` and `rewriteLinks` to respective values. Supported
264+
* properties:
265+
* - **enabled** – `{boolean}` – (default: false) If true, will rely on `history.pushState` to
266+
* change urls where supported. Will fall back to hash-prefixed paths in browsers that do not
267+
* support `pushState`.
268+
* - **requireBase** - `{boolean}` - (default: `true`) When html5Mode is enabled, specifies
269+
* whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
270+
* true, and a base tag is not present, an error will be thrown when `$location` is injected.
271+
* See the {@link guide/$location $location guide for more information}
272+
* - **rewriteLinks** - `{boolean|string}` - (default: `true`) When html5Mode is enabled,
273+
* enables/disables URL rewriting for relative links. If set to a string, URL rewriting will
274+
* only happen on links with an attribute that matches the given string. For example, if set
275+
* to `'internal-link'`, then the URL will only be rewritten for `<a internal-link>` links.
276+
* Note that [attribute name normalization](guide/directive#normalization) does not apply
277+
* here, so `'internalLink'` will **not** match `'internal-link'`.
278+
*
279+
* @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
280+
*/
281+
html5Mode(mode?: (boolean | any) | undefined): any;
282+
$get: (string | (($rootScope: import("../scope/scope").Scope, $browser: import("../../services/browser").Browser, $rootElement: JQLite) => Location))[];
283+
}
279284
export type DefaultPorts = {
280285
http: number;
281286
https: number;

0 commit comments

Comments
 (0)