@angular-wave/angular.ts 0.7.7 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/animations/raf-scheduler.d.ts +2 -2
- package/@types/animations/shared.d.ts +0 -1
- package/@types/core/compile/attributes.d.ts +3 -3
- package/@types/core/compile/compile.d.ts +1 -1
- package/@types/core/di/injector.d.ts +0 -1
- package/@types/core/di/internal-injector.d.ts +1 -0
- package/@types/core/di/ng-module.d.ts +5 -0
- package/@types/core/filter/filter.d.ts +11 -13
- package/@types/core/sanitize/sanitize-uri.d.ts +3 -6
- package/@types/core/scope/scope.d.ts +1 -1
- package/@types/directive/attrs/attrs.d.ts +7 -1
- package/@types/directive/events/events.d.ts +9 -3
- package/@types/directive/http/http.d.ts +6 -2
- package/@types/directive/include/include.d.ts +2 -2
- package/@types/directive/input/input.d.ts +2 -12
- package/@types/directive/messages/messages.d.ts +9 -48
- package/@types/directive/model/model.d.ts +3 -3
- package/@types/directive/options/options.d.ts +13 -20
- package/@types/directive/switch/switch.d.ts +1 -0
- package/@types/directive/transclude/transclude.d.ts +10 -6
- package/@types/interface.d.ts +54 -18
- package/@types/router/common/glob.d.ts +5 -1
- package/@types/router/directives/view-directive.d.ts +2 -19
- package/@types/router/globals.d.ts +1 -2
- package/@types/router/state/state-registry.d.ts +1 -2
- package/@types/router/url/url-service.d.ts +7 -9
- package/@types/services/anchor-scroll.d.ts +1 -1
- package/@types/{core → services/exception}/exception-handler.d.ts +4 -4
- package/@types/{core/error-handler.d.ts → services/exception/interface.d.ts} +1 -1
- package/@types/services/http/http.d.ts +0 -2
- package/@types/services/http/interface.d.ts +2 -2
- package/@types/services/http-backend/http-backend.d.ts +13 -21
- package/@types/services/location/interface.d.ts +8 -0
- package/@types/{core → services}/location/location.d.ts +52 -12
- package/@types/{core → services}/sce/sce.d.ts +1 -1
- package/@types/services/template-cache/interface.d.ts +8 -2
- package/@types/services/template-cache/template-cache.d.ts +1 -1
- package/@types/services/template-request.d.ts +1 -1
- package/@types/shared/cache.d.ts +0 -2
- package/@types/shared/dom.d.ts +6 -0
- package/@types/shared/test-utils.d.ts +1 -0
- package/@types/shared/url-utils/interface.d.ts +47 -0
- package/@types/{core → shared}/url-utils/url-utils.d.ts +26 -13
- package/@types/shared/utils.d.ts +15 -0
- package/Makefile +3 -2
- package/dist/angular-ts.esm.js +982 -1190
- package/dist/angular-ts.umd.js +982 -1190
- package/dist/angular-ts.umd.min.js +1 -1
- package/docs/content/docs/directive/bind.md +9 -7
- package/docs/content/docs/directive/get.md +203 -0
- package/docs/content/docs/provider/templateCacheProvider.md +66 -1
- package/docs/content/docs/service/templateCache.md +2 -2
- package/docs/layouts/partials/hooks/head-end.html +1 -1
- package/docs/layouts/shortcodes/showcss.html +2 -0
- package/docs/static/examples/ng-bind/ng-bind.html +2 -2
- package/docs/static/typedoc/assets/hierarchy.js +1 -1
- package/docs/static/typedoc/assets/navigation.js +1 -1
- package/docs/static/typedoc/assets/search.js +1 -1
- package/docs/static/typedoc/classes/NgModule.html +32 -0
- package/docs/static/typedoc/classes/TemplateCacheProvider.html +1 -1
- package/docs/static/typedoc/hierarchy.html +1 -1
- package/docs/static/typedoc/index.html +1 -1
- package/docs/static/typedoc/interfaces/Directive.html +5 -4
- package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +1 -1
- package/docs/static/typedoc/interfaces/HttpResponse.html +2 -3
- package/docs/static/typedoc/interfaces/Provider.html +15 -10
- package/docs/static/typedoc/interfaces/RequestConfig.html +1 -1
- package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +1 -1
- package/docs/static/typedoc/interfaces/TemplateCache.html +7 -0
- package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +1 -0
- package/docs/static/typedoc/types/DirectiveFactory.html +1 -2
- package/docs/static/typedoc/types/DirectiveFactoryFn.html +1 -0
- package/docs/static/typedoc/types/HttpResponseStatus.html +1 -0
- package/docs/static/typedoc/types/{TemplateCache.html → SwapModeType.html} +1 -1
- package/docs/static/typedoc/variables/SwapMode.html +11 -0
- package/legacy.d.ts +0 -10
- package/package.json +1 -3
- package/src/animations/animate-children-directive.js +2 -2
- package/src/animations/raf-scheduler.js +1 -1
- package/src/animations/shared.js +0 -9
- package/src/core/compile/attributes.js +1 -1
- package/src/core/compile/compile.js +3 -3
- package/src/core/di/injector.js +4 -17
- package/src/core/di/internal-injector.js +4 -1
- package/src/core/di/ng-module.js +12 -27
- package/src/core/filter/filter.js +28 -28
- package/src/core/parse/interpreter.js +32 -38
- package/src/core/sanitize/sanitize-uri.js +3 -3
- package/src/core/scope/scope.js +2 -2
- package/src/directive/attrs/attrs.js +7 -4
- package/src/directive/events/events.js +6 -2
- package/src/directive/http/delete.spec.js +2 -0
- package/src/directive/http/get.spec.js +280 -3
- package/src/directive/http/http.js +100 -12
- package/src/directive/http/http.test.js +2 -2
- package/src/directive/http/post.spec.js +2 -0
- package/src/directive/http/put.spec.js +2 -0
- package/src/directive/include/include.js +7 -7
- package/src/directive/input/input.js +6 -28
- package/src/directive/messages/messages.js +4 -0
- package/src/directive/model/model.js +1 -1
- package/src/directive/options/options.js +454 -464
- package/src/directive/setter/setter.js +12 -14
- package/src/directive/setter/setter.spec.js +39 -16
- package/src/directive/switch/switch.js +1 -0
- package/src/directive/transclude/transclude.js +87 -89
- package/src/injection-tokens.js +1 -1
- package/src/interface.ts +68 -19
- package/src/loader.js +4 -9
- package/src/public.js +9 -15
- package/src/router/common/glob.js +5 -0
- package/src/router/directives/state-directives.spec.js +1 -1
- package/src/router/directives/view-directive.js +9 -1
- package/src/router/globals.js +0 -1
- package/src/router/state/state-registry.js +0 -1
- package/src/router/state-filters.js +2 -2
- package/src/router/url/url-service.js +5 -9
- package/src/services/anchor-scroll.html +0 -7
- package/src/services/anchor-scroll.js +1 -1
- package/src/{core → services/exception}/exception-handler.js +2 -2
- package/src/{core/error-handler.ts → services/exception/interface.ts} +1 -1
- package/src/services/http/http.js +2 -13
- package/src/services/http/interface.ts +2 -2
- package/src/services/http-backend/http-backend.js +4 -14
- package/src/services/http-backend/http-backend.spec.js +1 -4
- package/src/services/location/interface.ts +8 -0
- package/src/{core → services}/location/location.html +4 -1
- package/src/{core → services}/location/location.js +128 -26
- package/src/{core → services}/location/location.spec.js +2 -2
- package/src/{core → services}/location/location.test.js +1 -1
- package/src/{core → services}/sce/sce.html +1 -1
- package/src/{core → services}/sce/sce.js +9 -3
- package/src/{core → services}/sce/sce.spec.js +2 -3
- package/src/{core → services}/sce/sce.test.js +1 -1
- package/src/services/template-cache/interface.ts +8 -2
- package/src/services/template-cache/template-cache.js +3 -1
- package/src/services/template-cache/template-cache.spec.js +72 -0
- package/src/services/template-request.js +2 -1
- package/src/shared/cache.js +0 -2
- package/src/shared/dom.js +10 -0
- package/src/shared/test-utils.js +1 -0
- package/src/shared/url-utils/interface.ts +56 -0
- package/src/{core → shared}/url-utils/url-utils.html +4 -1
- package/src/{core → shared}/url-utils/url-utils.js +26 -23
- package/src/{core → shared}/url-utils/url-utils.spec.js +0 -8
- package/src/{core → shared}/url-utils/url-utils.test.js +1 -1
- package/src/shared/utils.js +28 -0
- package/utils/express.js +9 -1
- package/@types/core/task-tracker-factory.d.ts +0 -76
- package/@types/services/browser.d.ts +0 -101
- package/docs/static/typedoc/types/SwapInsertPosition.html +0 -2
- package/jsdoc.json +0 -22
- package/src/core/task-tracker-factory.js +0 -145
- package/src/services/browser.js +0 -212
- /package/src/{core → services}/location/location.md +0 -0
- /package/src/{core → services}/sce/sce.md +0 -0
- /package/src/{core → shared}/url-utils/url-utils.md +0 -0
|
@@ -143,11 +143,20 @@ import { getLocals } from "../state/state-registry.js";
|
|
|
143
143
|
* });
|
|
144
144
|
* ```
|
|
145
145
|
*/
|
|
146
|
+
|
|
147
|
+
/** @type {import("../../interface.js").AnnotatedDirectiveFactory} */
|
|
146
148
|
export let ngView = [
|
|
147
149
|
"$view",
|
|
148
150
|
"$animate",
|
|
149
151
|
"$ngViewScroll",
|
|
150
152
|
"$interpolate",
|
|
153
|
+
/**
|
|
154
|
+
* @param {*} $view
|
|
155
|
+
* @param {*} $animate
|
|
156
|
+
* @param {*} $ngViewScroll
|
|
157
|
+
* @param {*} $interpolate
|
|
158
|
+
* @returns {import("../../interface.js").Directive}
|
|
159
|
+
*/
|
|
151
160
|
function $ViewDirective($view, $animate, $ngViewScroll, $interpolate) {
|
|
152
161
|
function getRenderer() {
|
|
153
162
|
return {
|
|
@@ -178,7 +187,6 @@ export let ngView = [
|
|
|
178
187
|
};
|
|
179
188
|
const directive = {
|
|
180
189
|
count: 0,
|
|
181
|
-
|
|
182
190
|
terminal: true,
|
|
183
191
|
priority: 400,
|
|
184
192
|
transclude: "element",
|
package/src/router/globals.js
CHANGED
|
@@ -14,7 +14,6 @@ import { $injectTokens, provider } from "../../injection-tokens.js";
|
|
|
14
14
|
*
|
|
15
15
|
* This API is found at `$stateRegistry` ([[UIRouter.stateRegistry]])
|
|
16
16
|
*
|
|
17
|
-
* @implements {ServiceProvider}
|
|
18
17
|
*/
|
|
19
18
|
export class StateRegistryProvider {
|
|
20
19
|
static $inject = provider([
|
|
@@ -16,7 +16,7 @@ export function $IsStateFilter($state) {
|
|
|
16
16
|
const isFilter = function (state, params, options) {
|
|
17
17
|
return $state.is(state, params, options);
|
|
18
18
|
};
|
|
19
|
-
|
|
19
|
+
isFilter.$stateful = true;
|
|
20
20
|
return isFilter;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
@@ -37,6 +37,6 @@ export function $IncludedByStateFilter($state) {
|
|
|
37
37
|
const includesFilter = function (state, params, options) {
|
|
38
38
|
return $state.includes(state, params, options);
|
|
39
39
|
};
|
|
40
|
-
|
|
40
|
+
includesFilter.$stateful = true;
|
|
41
41
|
return includesFilter;
|
|
42
42
|
}
|
|
@@ -12,6 +12,7 @@ import { stripLastPathElement } from "../../shared/strings.js";
|
|
|
12
12
|
import { UrlMatcher } from "./url-matcher.js";
|
|
13
13
|
import { ParamFactory } from "../params/param-factory.js";
|
|
14
14
|
import { UrlRuleFactory } from "./url-rule.js";
|
|
15
|
+
import { getBaseHref } from "../../shared/dom.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* API for URL management
|
|
@@ -25,7 +26,7 @@ export class UrlService {
|
|
|
25
26
|
];
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
* @param {import("../../
|
|
29
|
+
* @param {import("../../services/location/location").LocationProvider} $locationProvider
|
|
29
30
|
* @param {import("../../router/state/state-service.js").StateProvider} stateService
|
|
30
31
|
* @param globals
|
|
31
32
|
* @param {import("../../router/url/url-config.js").UrlConfigProvider} urlConfigProvider
|
|
@@ -34,9 +35,7 @@ export class UrlService {
|
|
|
34
35
|
this.stateService = stateService;
|
|
35
36
|
this.stateService.urlService = this; // circular wiring
|
|
36
37
|
this.$locationProvider = $locationProvider;
|
|
37
|
-
|
|
38
38
|
this.$location = undefined;
|
|
39
|
-
this.$browser = undefined;
|
|
40
39
|
|
|
41
40
|
/** Provides services related to the URL */
|
|
42
41
|
this.urlRuleFactory = new UrlRuleFactory(this, this.stateService, globals);
|
|
@@ -89,18 +88,15 @@ export class UrlService {
|
|
|
89
88
|
|
|
90
89
|
$get = [
|
|
91
90
|
"$location",
|
|
92
|
-
"$browser",
|
|
93
91
|
"$rootScope",
|
|
94
92
|
/**
|
|
95
93
|
*
|
|
96
|
-
* @param {import('../../
|
|
97
|
-
* @param {import('../../services/browser.js').Browser} $browser
|
|
94
|
+
* @param {import('../../services/location/location.js').Location} $location
|
|
98
95
|
* @param {import('../../core/scope/scope.js').Scope} $rootScope
|
|
99
96
|
* @returns {UrlService}
|
|
100
97
|
*/
|
|
101
|
-
($location, $
|
|
98
|
+
($location, $rootScope) => {
|
|
102
99
|
this.$location = $location;
|
|
103
|
-
this.$browser = $browser;
|
|
104
100
|
$rootScope.$on("$locationChangeSuccess", (evt) => {
|
|
105
101
|
this._urlListeners.forEach((fn) => {
|
|
106
102
|
fn(evt);
|
|
@@ -124,7 +120,7 @@ export class UrlService {
|
|
|
124
120
|
baseHref() {
|
|
125
121
|
return (
|
|
126
122
|
this._baseHref ||
|
|
127
|
-
(this._baseHref =
|
|
123
|
+
(this._baseHref = getBaseHref() || window.location.pathname)
|
|
128
124
|
);
|
|
129
125
|
}
|
|
130
126
|
|
|
@@ -3,14 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8" />
|
|
5
5
|
<title>AngularTS Test Runner</title>
|
|
6
|
-
|
|
7
6
|
<link rel="shortcut icon" type="image/png" href="/images/favicon.ico" />
|
|
8
|
-
|
|
9
|
-
<!--
|
|
10
|
-
<script src="https://cdn.jsdelivr.net/npm/angular@1.8.3/angular.js"></script>
|
|
11
|
-
<script src="https://cdn.jsdelivr.net/npm/angular-animate@1.8.3/angular-animate.js"></script>
|
|
12
|
-
<script>window.angular.module("test", [])</script> -->
|
|
13
|
-
|
|
14
7
|
<script type="module" src="/src/index.js"></script>
|
|
15
8
|
<script>
|
|
16
9
|
document.addEventListener("DOMContentLoaded", () => {
|
|
@@ -29,7 +29,7 @@ export class AnchorScrollProvider {
|
|
|
29
29
|
"$rootScope",
|
|
30
30
|
/**
|
|
31
31
|
*
|
|
32
|
-
* @param {import('../
|
|
32
|
+
* @param {import('../services/location/location.js').Location} $location
|
|
33
33
|
* @param {import('../core/scope/scope.js').Scope} $rootScope
|
|
34
34
|
* @returns
|
|
35
35
|
*/
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
* @see {@link angular.ErrorHandler AngularTS ErrorHandler}
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
/** @typedef {import('../
|
|
45
|
+
/** @typedef {import('../log/interface.ts').LogService} LogService */
|
|
46
46
|
|
|
47
|
-
/** @typedef {import("./
|
|
47
|
+
/** @typedef {import("./interface.ts").Interface} ErrorHandler */
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Provider for `$exceptionHandler` service. Delegates uncaught exceptions to `$log.error()` by default.
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* @param exception - The exception associated with the error.
|
|
5
5
|
* @param [cause] - Optional information about the context in which the error was thrown.
|
|
6
6
|
*/
|
|
7
|
-
export type
|
|
7
|
+
export type Interface = (exception: Error, cause?: string) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { urlIsAllowedOriginFactory } from "../../
|
|
1
|
+
import { urlIsAllowedOriginFactory } from "../../shared/url-utils/url-utils.js";
|
|
2
2
|
import {
|
|
3
3
|
minErr,
|
|
4
4
|
isObject,
|
|
@@ -377,21 +377,17 @@ export function HttpProvider() {
|
|
|
377
377
|
});
|
|
378
378
|
|
|
379
379
|
this.$get = [
|
|
380
|
-
"$browser",
|
|
381
380
|
"$httpBackend",
|
|
382
|
-
"$rootScope",
|
|
383
381
|
"$injector",
|
|
384
382
|
"$sce",
|
|
385
383
|
/**
|
|
386
384
|
*
|
|
387
|
-
* @param {*} $browser
|
|
388
385
|
* @param {*} $httpBackend
|
|
389
|
-
* @param {import("../../core/scope/scope.js").Scope} $rootScope
|
|
390
386
|
* @param {import("../../core/di/internal-injector.js").InjectorService} $injector
|
|
391
387
|
* @param {*} $sce
|
|
392
388
|
* @returns
|
|
393
389
|
*/
|
|
394
|
-
function ($
|
|
390
|
+
function ($httpBackend, $injector, $sce) {
|
|
395
391
|
/**
|
|
396
392
|
* @type {Map<string, string>}
|
|
397
393
|
*/
|
|
@@ -461,8 +457,6 @@ export function HttpProvider() {
|
|
|
461
457
|
? $injector.get(config.paramSerializer)
|
|
462
458
|
: config.paramSerializer;
|
|
463
459
|
|
|
464
|
-
$browser.$$incOutstandingRequestCount("$http");
|
|
465
|
-
|
|
466
460
|
const requestInterceptors = [];
|
|
467
461
|
const responseInterceptors = [];
|
|
468
462
|
let promise = Promise.resolve(config);
|
|
@@ -486,7 +480,6 @@ export function HttpProvider() {
|
|
|
486
480
|
promise = chainInterceptors(promise, requestInterceptors);
|
|
487
481
|
promise = promise.then(serverRequest);
|
|
488
482
|
promise = chainInterceptors(promise, responseInterceptors);
|
|
489
|
-
promise = promise.finally(completeOutstandingRequest);
|
|
490
483
|
|
|
491
484
|
return promise;
|
|
492
485
|
|
|
@@ -503,10 +496,6 @@ export function HttpProvider() {
|
|
|
503
496
|
return promise;
|
|
504
497
|
}
|
|
505
498
|
|
|
506
|
-
function completeOutstandingRequest() {
|
|
507
|
-
$browser.$$completeOutstandingRequest(() => {}, "$http");
|
|
508
|
-
}
|
|
509
|
-
|
|
510
499
|
function executeHeaderFns(headers, config) {
|
|
511
500
|
let headerContent;
|
|
512
501
|
const processedHeaders = {};
|
|
@@ -139,14 +139,14 @@ export interface RequestConfig extends RequestShortcutConfig {
|
|
|
139
139
|
| undefined;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
export type HttpResponseStatus = "complete" | "error" | "timeout" | "abort";
|
|
142
143
|
export interface HttpResponse<T> {
|
|
143
144
|
data: T;
|
|
144
145
|
status: number;
|
|
145
146
|
headers: HttpHeadersGetter;
|
|
146
147
|
config: RequestConfig;
|
|
147
148
|
statusText: string;
|
|
148
|
-
|
|
149
|
-
xhrStatus: "complete" | "error" | "timeout" | "abort";
|
|
149
|
+
xhrStatus: HttpResponseStatus;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
export type HttpPromise<T> = Promise<HttpResponse<T>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { urlResolve } from "../../
|
|
1
|
+
import { trimEmptyHash, urlResolve } from "../../shared/url-utils/url-utils.js";
|
|
2
2
|
import { isDefined, isPromiseLike, isUndefined } from "../../shared/utils.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -19,24 +19,14 @@ import { isDefined, isPromiseLike, isUndefined } from "../../shared/utils.js";
|
|
|
19
19
|
*/
|
|
20
20
|
export class HttpBackendProvider {
|
|
21
21
|
constructor() {
|
|
22
|
-
this.$get = [
|
|
23
|
-
"$browser",
|
|
24
|
-
/**
|
|
25
|
-
* @param {import('../browser.js').Browser} $browser
|
|
26
|
-
* @returns
|
|
27
|
-
*/
|
|
28
|
-
function ($browser) {
|
|
29
|
-
return createHttpBackend($browser);
|
|
30
|
-
},
|
|
31
|
-
];
|
|
22
|
+
this.$get = [() => createHttpBackend()];
|
|
32
23
|
}
|
|
33
24
|
}
|
|
34
25
|
|
|
35
26
|
/**
|
|
36
|
-
* @param {import('../browser.js').Browser} $browser
|
|
37
27
|
* @returns
|
|
38
28
|
*/
|
|
39
|
-
export function createHttpBackend(
|
|
29
|
+
export function createHttpBackend() {
|
|
40
30
|
// TODO(vojta): fix the signature
|
|
41
31
|
return function (
|
|
42
32
|
method,
|
|
@@ -50,7 +40,7 @@ export function createHttpBackend($browser) {
|
|
|
50
40
|
eventHandlers,
|
|
51
41
|
uploadEventHandlers,
|
|
52
42
|
) {
|
|
53
|
-
url = url ||
|
|
43
|
+
url = url || trimEmptyHash(window.location.href);
|
|
54
44
|
|
|
55
45
|
const xhr = new XMLHttpRequest();
|
|
56
46
|
let abortedByTimeout = false;
|
|
@@ -5,7 +5,6 @@ import sinon from "sinon";
|
|
|
5
5
|
|
|
6
6
|
describe("$httpBackend", () => {
|
|
7
7
|
let $backend;
|
|
8
|
-
let $browser;
|
|
9
8
|
let xhr;
|
|
10
9
|
let callback;
|
|
11
10
|
let requests;
|
|
@@ -18,9 +17,7 @@ describe("$httpBackend", () => {
|
|
|
18
17
|
requests.push(req);
|
|
19
18
|
};
|
|
20
19
|
angular = window.angular = new Angular();
|
|
21
|
-
|
|
22
|
-
$browser = $injector.get("$browser");
|
|
23
|
-
$backend = createHttpBackend($browser);
|
|
20
|
+
$backend = createHttpBackend();
|
|
24
21
|
callback = jasmine.createSpy("done");
|
|
25
22
|
});
|
|
26
23
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A callback function that gets called when the browser URL or state changes.
|
|
3
|
+
*
|
|
4
|
+
* @param url - The new URL after the change (with trailing `#` removed).
|
|
5
|
+
* @param state - The new history state associated with the URL (`history.state`).
|
|
6
|
+
* @returns void
|
|
7
|
+
*/
|
|
8
|
+
export type UrlChangeListener = (url: string, state: History["state"]) => void;
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
<script src="/jasmine/jasmine-html.js"></script>
|
|
12
12
|
<script src="/jasmine/boot0.js"></script>
|
|
13
13
|
<script src="/jasmine/boot1.js"></script>
|
|
14
|
-
<script
|
|
14
|
+
<script
|
|
15
|
+
type="module"
|
|
16
|
+
src="/src/services/location/location.spec.js"
|
|
17
|
+
></script>
|
|
15
18
|
</head>
|
|
16
19
|
<body>
|
|
17
20
|
<div id="app"></div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { urlResolve } from "
|
|
1
|
+
import { trimEmptyHash, urlResolve } from "../../shared/url-utils/url-utils.js";
|
|
2
2
|
import {
|
|
3
3
|
encodeUriSegment,
|
|
4
4
|
isBoolean,
|
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
parseKeyValue,
|
|
12
12
|
toInt,
|
|
13
13
|
toKeyValue,
|
|
14
|
+
equals,
|
|
14
15
|
} from "../../shared/utils.js";
|
|
16
|
+
import { getBaseHref } from "../../shared/dom.js";
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* @typedef {Object} DefaultPorts
|
|
@@ -78,7 +80,7 @@ export class Location {
|
|
|
78
80
|
*/
|
|
79
81
|
this.$$replace = false;
|
|
80
82
|
|
|
81
|
-
/** @type {
|
|
83
|
+
/** @type {string} */
|
|
82
84
|
this.$$protocol = parsedUrl.protocol;
|
|
83
85
|
|
|
84
86
|
/** @type {string} */
|
|
@@ -145,7 +147,7 @@ export class Location {
|
|
|
145
147
|
/**
|
|
146
148
|
*
|
|
147
149
|
* Return protocol of current URL.
|
|
148
|
-
* @return {
|
|
150
|
+
* @return {string} protocol of current URL
|
|
149
151
|
*/
|
|
150
152
|
protocol() {
|
|
151
153
|
return this.$$protocol;
|
|
@@ -446,12 +448,13 @@ export class LocationHtml5Url extends Location {
|
|
|
446
448
|
* This object is exposed as $location service when developer doesn't opt into html5 mode.
|
|
447
449
|
* It also serves as the base class for html5 mode fallback on legacy browsers.
|
|
448
450
|
*
|
|
449
|
-
* @constructor
|
|
450
|
-
* @param {string} appBase application base URL
|
|
451
|
-
* @param {string} appBaseNoFile application base URL stripped of any filename
|
|
452
|
-
* @param {string} hashPrefix hashbang prefix
|
|
453
451
|
*/
|
|
454
452
|
export class LocationHashbangUrl extends Location {
|
|
453
|
+
/**
|
|
454
|
+
* @param {string} appBase application base URL
|
|
455
|
+
* @param {string} appBaseNoFile application base URL stripped of any filename
|
|
456
|
+
* @param {string} hashPrefix hashbang prefix
|
|
457
|
+
*/
|
|
455
458
|
constructor(appBase, appBaseNoFile, hashPrefix) {
|
|
456
459
|
super(appBase, appBaseNoFile);
|
|
457
460
|
this.hashPrefix = hashPrefix;
|
|
@@ -562,6 +565,111 @@ export class LocationProvider {
|
|
|
562
565
|
requireBase: true,
|
|
563
566
|
rewriteLinks: true,
|
|
564
567
|
};
|
|
568
|
+
|
|
569
|
+
/** @type {Array<import("./interface.js").UrlChangeListener>} */
|
|
570
|
+
this.urlChangeListeners = [];
|
|
571
|
+
this.urlChangeInit = false;
|
|
572
|
+
|
|
573
|
+
/** @type {History['state']} */
|
|
574
|
+
this.cachedState = null;
|
|
575
|
+
/** @typeof {History.state} */
|
|
576
|
+
this.lastHistoryState = null;
|
|
577
|
+
/** @type {string} */
|
|
578
|
+
this.lastBrowserUrl = window.location.href;
|
|
579
|
+
this.cacheState();
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/// ///////////////////////////////////////////////////////////
|
|
583
|
+
// URL API
|
|
584
|
+
/// ///////////////////////////////////////////////////////////
|
|
585
|
+
|
|
586
|
+
setUrl(url, state) {
|
|
587
|
+
if (state === undefined) {
|
|
588
|
+
state = null;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// setter
|
|
592
|
+
if (url) {
|
|
593
|
+
url = urlResolve(url).href;
|
|
594
|
+
|
|
595
|
+
if (this.lastBrowserUrl === url && this.lastHistoryState === state) {
|
|
596
|
+
return this;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
this.lastBrowserUrl = url;
|
|
600
|
+
this.lastHistoryState = state;
|
|
601
|
+
history.pushState(state, "", url);
|
|
602
|
+
this.cacheState();
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Returns the current URL with any empty hash (`#`) removed.
|
|
608
|
+
* @return {string}
|
|
609
|
+
*/
|
|
610
|
+
getUrl() {
|
|
611
|
+
return trimEmptyHash(window.location.href);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Returns the cached state.
|
|
616
|
+
* @returns {History['state']} The cached state.
|
|
617
|
+
*/
|
|
618
|
+
state() {
|
|
619
|
+
return this.cachedState;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Caches the current state.
|
|
624
|
+
*
|
|
625
|
+
* @private
|
|
626
|
+
*/
|
|
627
|
+
cacheState() {
|
|
628
|
+
const currentState = history.state ?? null;
|
|
629
|
+
if (!equals(currentState, this.lastCachedState)) {
|
|
630
|
+
this.cachedState = currentState;
|
|
631
|
+
this.lastCachedState = currentState;
|
|
632
|
+
this.lastHistoryState = currentState;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Fires the state or URL change event.
|
|
638
|
+
*
|
|
639
|
+
* @private
|
|
640
|
+
*/
|
|
641
|
+
fireStateOrUrlChange() {
|
|
642
|
+
const prevLastHistoryState = this.lastHistoryState;
|
|
643
|
+
this.cacheState();
|
|
644
|
+
if (
|
|
645
|
+
this.lastBrowserUrl === this.getUrl() &&
|
|
646
|
+
prevLastHistoryState === this.cachedState
|
|
647
|
+
) {
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
this.lastBrowserUrl = this.getUrl();
|
|
651
|
+
this.lastHistoryState = this.cachedState;
|
|
652
|
+
this.urlChangeListeners.forEach((listener) => {
|
|
653
|
+
listener(trimEmptyHash(window.location.href), this.cachedState);
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Registers a callback to be called when the URL changes.
|
|
659
|
+
*
|
|
660
|
+
* @param {import("./interface.js").UrlChangeListener} callback - The callback function to register.
|
|
661
|
+
* @returns void
|
|
662
|
+
*/
|
|
663
|
+
onUrlChange(callback) {
|
|
664
|
+
if (!this.urlChangeInit) {
|
|
665
|
+
window.addEventListener("popstate", this.fireStateOrUrlChange.bind(this));
|
|
666
|
+
window.addEventListener(
|
|
667
|
+
"hashchange",
|
|
668
|
+
this.fireStateOrUrlChange.bind(this),
|
|
669
|
+
);
|
|
670
|
+
this.urlChangeInit = true;
|
|
671
|
+
}
|
|
672
|
+
this.urlChangeListeners.push(callback);
|
|
565
673
|
}
|
|
566
674
|
|
|
567
675
|
/**
|
|
@@ -623,21 +731,19 @@ export class LocationProvider {
|
|
|
623
731
|
|
|
624
732
|
$get = [
|
|
625
733
|
"$rootScope",
|
|
626
|
-
"$browser",
|
|
627
734
|
"$rootElement",
|
|
628
735
|
/**
|
|
629
736
|
*
|
|
630
|
-
* @param {import('
|
|
631
|
-
* @param {import('../../services/browser').Browser} $browser
|
|
737
|
+
* @param {import('../../core/scope/scope.js').Scope} $rootScope
|
|
632
738
|
* @param {Element} $rootElement
|
|
633
739
|
* @returns
|
|
634
740
|
*/
|
|
635
|
-
($rootScope, $
|
|
741
|
+
($rootScope, $rootElement) => {
|
|
636
742
|
/** @type {Location} */
|
|
637
743
|
let $location;
|
|
638
744
|
let LocationMode;
|
|
639
|
-
const baseHref =
|
|
640
|
-
const initialUrl =
|
|
745
|
+
const baseHref = getBaseHref(); // if base[href] is undefined, it defaults to ''
|
|
746
|
+
const initialUrl = trimEmptyHash(window.location.href);
|
|
641
747
|
let appBase;
|
|
642
748
|
|
|
643
749
|
if (this.getHtml5Mode().enabled) {
|
|
@@ -662,20 +768,20 @@ export class LocationProvider {
|
|
|
662
768
|
);
|
|
663
769
|
$location.$$parseLinkUrl(initialUrl, initialUrl);
|
|
664
770
|
|
|
665
|
-
$location.$$state =
|
|
771
|
+
$location.$$state = this.state();
|
|
666
772
|
|
|
667
773
|
const IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
|
|
668
774
|
|
|
669
|
-
|
|
775
|
+
const setBrowserUrlWithFallback = (url, state) => {
|
|
670
776
|
const oldUrl = $location.url();
|
|
671
777
|
const oldState = $location.$$state;
|
|
672
778
|
try {
|
|
673
|
-
|
|
779
|
+
this.setUrl(url, state);
|
|
674
780
|
|
|
675
781
|
// Make sure $location.state() returns referentially identical (not just deeply equal)
|
|
676
782
|
// state object; this makes possible quick checking if the state changed in the digest
|
|
677
783
|
// loop. Checking deep equality would be too expensive.
|
|
678
|
-
$location.$$state =
|
|
784
|
+
$location.$$state = this.state();
|
|
679
785
|
} catch (e) {
|
|
680
786
|
// Restore old values if pushState fails
|
|
681
787
|
$location.url(/** @type {string} */ (oldUrl));
|
|
@@ -683,7 +789,7 @@ export class LocationProvider {
|
|
|
683
789
|
|
|
684
790
|
throw e;
|
|
685
791
|
}
|
|
686
|
-
}
|
|
792
|
+
};
|
|
687
793
|
|
|
688
794
|
$rootElement.addEventListener(
|
|
689
795
|
"click",
|
|
@@ -751,10 +857,6 @@ export class LocationProvider {
|
|
|
751
857
|
// in html5mode and also without, so that we are able to abort navigation without
|
|
752
858
|
// getting double entries in the location history.
|
|
753
859
|
event.preventDefault();
|
|
754
|
-
// update location manually
|
|
755
|
-
// if ($location.absUrl() !== $browser.url()) {
|
|
756
|
-
// $rootScope.$apply();
|
|
757
|
-
// }
|
|
758
860
|
}
|
|
759
861
|
}
|
|
760
862
|
},
|
|
@@ -762,13 +864,13 @@ export class LocationProvider {
|
|
|
762
864
|
|
|
763
865
|
// rewrite hashbang url <> html5 url
|
|
764
866
|
if ($location.absUrl() !== initialUrl) {
|
|
765
|
-
|
|
867
|
+
this.setUrl($location.absUrl(), true);
|
|
766
868
|
}
|
|
767
869
|
|
|
768
870
|
let initializing = true;
|
|
769
871
|
|
|
770
872
|
// update $location when $browser url changes
|
|
771
|
-
|
|
873
|
+
this.onUrlChange((newUrl, newState) => {
|
|
772
874
|
if (!startsWith(newUrl, appBaseNoFile)) {
|
|
773
875
|
// If we are navigating outside of the app then force a reload
|
|
774
876
|
window.location.href = newUrl;
|
|
@@ -810,9 +912,9 @@ export class LocationProvider {
|
|
|
810
912
|
if (initializing || $location.$$urlUpdatedByLocation) {
|
|
811
913
|
$location.$$urlUpdatedByLocation = false;
|
|
812
914
|
|
|
813
|
-
const oldUrl = /** @type {string} */ (
|
|
915
|
+
const oldUrl = /** @type {string} */ (this.getUrl());
|
|
814
916
|
const newUrl = $location.absUrl();
|
|
815
|
-
const oldState =
|
|
917
|
+
const oldState = this.state();
|
|
816
918
|
const urlOrStateChanged =
|
|
817
919
|
!urlsEqual(oldUrl, newUrl) ||
|
|
818
920
|
($location.$$html5 && oldState !== $location.$$state);
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
LocationHtml5Url,
|
|
3
3
|
LocationHashbangUrl,
|
|
4
4
|
LocationProvider,
|
|
5
|
-
} from "./location";
|
|
5
|
+
} from "./location.js";
|
|
6
6
|
import { Angular } from "../../loader.js";
|
|
7
|
-
import { createInjector } from "
|
|
7
|
+
import { createInjector } from "../../core/di/injector.js";
|
|
8
8
|
|
|
9
9
|
describe("$location", () => {
|
|
10
10
|
let module;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<script src="/jasmine/jasmine-html.js"></script>
|
|
12
12
|
<script src="/jasmine/boot0.js"></script>
|
|
13
13
|
<script src="/jasmine/boot1.js"></script>
|
|
14
|
-
<script type="module" src="/src/
|
|
14
|
+
<script type="module" src="/src/services/sce/sce.spec.js"></script>
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="app"></div>
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
urlIsSameOrigin,
|
|
3
3
|
urlIsSameOriginAsBaseUrl,
|
|
4
4
|
urlResolve,
|
|
5
|
-
} from "
|
|
5
|
+
} from "../../shared/url-utils/url-utils.js";
|
|
6
6
|
import {
|
|
7
7
|
hasOwn,
|
|
8
8
|
isFunction,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
|
|
17
17
|
import { snakeToCamel } from "../../shared/dom.js";
|
|
18
18
|
|
|
19
|
-
/** @typedef {import("../
|
|
19
|
+
/** @typedef {import("../exception/interface.ts").Interface } ErrorHandler */
|
|
20
20
|
|
|
21
21
|
const $sceMinErr = minErr("$sce");
|
|
22
22
|
|
|
@@ -72,6 +72,7 @@ export function adjustMatcher(matcher) {
|
|
|
72
72
|
.replace(/\\\*/g, "[^:/.?&;]*");
|
|
73
73
|
return new RegExp(`^${matcher}$`);
|
|
74
74
|
}
|
|
75
|
+
|
|
75
76
|
if (isRegExp(matcher)) {
|
|
76
77
|
// The only other type of matcher allowed is a Regexp.
|
|
77
78
|
// Match entire URL / disallow partial matches.
|
|
@@ -333,6 +334,11 @@ export class SceDelegateProvider {
|
|
|
333
334
|
htmlSanitizer = $injector.get("$sanitize");
|
|
334
335
|
}
|
|
335
336
|
|
|
337
|
+
/**
|
|
338
|
+
* @param {string|RegExp} matcher
|
|
339
|
+
* @param {import("../../shared/url-utils/interface").ParsedUrl} parsedUrl
|
|
340
|
+
* @return {boolean}
|
|
341
|
+
*/
|
|
336
342
|
function matchUrl(matcher, parsedUrl) {
|
|
337
343
|
if (matcher === "self") {
|
|
338
344
|
return (
|
|
@@ -340,7 +346,7 @@ export class SceDelegateProvider {
|
|
|
340
346
|
);
|
|
341
347
|
}
|
|
342
348
|
// definitely a regex. See adjustMatchers()
|
|
343
|
-
return !!matcher.exec(parsedUrl.href);
|
|
349
|
+
return !!(/** @type {RegExp} */ (matcher).exec(parsedUrl.href));
|
|
344
350
|
}
|
|
345
351
|
|
|
346
352
|
function isResourceUrlAllowedByPolicy(url) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { createInjector } from "
|
|
2
|
-
|
|
1
|
+
import { createInjector } from "../../core/di/injector.js";
|
|
3
2
|
import { Angular } from "../../loader.js";
|
|
4
|
-
import { adjustMatcher } from "./sce";
|
|
3
|
+
import { adjustMatcher } from "./sce.js";
|
|
5
4
|
import { wait } from "../../shared/test-utils.js";
|
|
6
5
|
|
|
7
6
|
describe("SCE", () => {
|