@angular-wave/angular.ts 0.7.5 → 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.
Files changed (174) hide show
  1. package/@types/animations/raf-scheduler.d.ts +2 -2
  2. package/@types/animations/shared.d.ts +0 -1
  3. package/@types/core/compile/attributes.d.ts +3 -3
  4. package/@types/core/compile/compile.d.ts +1 -1
  5. package/@types/core/di/injector.d.ts +0 -1
  6. package/@types/core/di/internal-injector.d.ts +1 -0
  7. package/@types/core/di/ng-module.d.ts +5 -0
  8. package/@types/core/filter/filter.d.ts +11 -13
  9. package/@types/core/sanitize/sanitize-uri.d.ts +3 -6
  10. package/@types/core/scope/scope.d.ts +1 -3
  11. package/@types/directive/attrs/attrs.d.ts +7 -1
  12. package/@types/directive/events/events.d.ts +9 -3
  13. package/@types/directive/http/http.d.ts +6 -2
  14. package/@types/directive/include/include.d.ts +2 -2
  15. package/@types/directive/input/input.d.ts +2 -12
  16. package/@types/directive/messages/messages.d.ts +9 -48
  17. package/@types/directive/model/model.d.ts +3 -3
  18. package/@types/directive/options/options.d.ts +13 -20
  19. package/@types/directive/setter/setter.d.ts +2 -2
  20. package/@types/directive/switch/switch.d.ts +1 -0
  21. package/@types/directive/transclude/transclude.d.ts +10 -6
  22. package/@types/interface.d.ts +54 -18
  23. package/@types/router/common/glob.d.ts +5 -1
  24. package/@types/router/directives/view-directive.d.ts +2 -19
  25. package/@types/router/globals.d.ts +1 -2
  26. package/@types/router/state/state-registry.d.ts +1 -2
  27. package/@types/router/url/url-service.d.ts +7 -9
  28. package/@types/services/anchor-scroll.d.ts +1 -1
  29. package/@types/{core → services/exception}/exception-handler.d.ts +4 -4
  30. package/@types/{core/error-handler.d.ts → services/exception/interface.d.ts} +1 -1
  31. package/@types/services/http/http.d.ts +0 -2
  32. package/@types/services/http/interface.d.ts +2 -2
  33. package/@types/services/http-backend/http-backend.d.ts +13 -21
  34. package/@types/services/location/interface.d.ts +8 -0
  35. package/@types/{core → services}/location/location.d.ts +52 -12
  36. package/@types/{core → services}/sce/sce.d.ts +1 -1
  37. package/@types/services/template-cache/interface.d.ts +8 -2
  38. package/@types/services/template-cache/template-cache.d.ts +1 -1
  39. package/@types/services/template-request.d.ts +1 -1
  40. package/@types/shared/cache.d.ts +0 -2
  41. package/@types/shared/dom.d.ts +6 -0
  42. package/@types/shared/test-utils.d.ts +1 -0
  43. package/@types/shared/url-utils/interface.d.ts +47 -0
  44. package/@types/{core → shared}/url-utils/url-utils.d.ts +26 -13
  45. package/@types/shared/utils.d.ts +23 -0
  46. package/Makefile +3 -2
  47. package/dist/angular-ts.esm.js +1188 -1364
  48. package/dist/angular-ts.umd.js +1188 -1364
  49. package/dist/angular-ts.umd.min.js +1 -1
  50. package/docs/assets/scss/index.scss +12 -0
  51. package/docs/content/_index.md +15 -4
  52. package/docs/content/docs/directive/bind.md +72 -0
  53. package/docs/content/docs/directive/click.md +3 -0
  54. package/docs/content/docs/directive/dblclick.md +3 -0
  55. package/docs/content/docs/directive/get.md +203 -0
  56. package/docs/content/docs/directive/keydown.md +38 -0
  57. package/docs/content/docs/directive/keyup.md +38 -0
  58. package/docs/content/docs/directive/load.md +43 -0
  59. package/docs/content/docs/provider/templateCacheProvider.md +66 -1
  60. package/docs/content/docs/service/templateCache.md +2 -2
  61. package/docs/layouts/partials/hooks/head-end.html +1 -1
  62. package/docs/layouts/shortcodes/showcss.html +2 -0
  63. package/docs/static/examples/ng-bind/ng-bind.html +9 -0
  64. package/docs/static/examples/ng-keydown/ng-keydown.html +9 -0
  65. package/docs/static/examples/ng-keyup/ng-keyup.html +9 -0
  66. package/docs/static/examples/ng-load/ng-load.html +8 -0
  67. package/docs/static/typedoc/assets/hierarchy.js +1 -1
  68. package/docs/static/typedoc/assets/navigation.js +1 -1
  69. package/docs/static/typedoc/assets/search.js +1 -1
  70. package/docs/static/typedoc/classes/NgModule.html +32 -0
  71. package/docs/static/typedoc/classes/TemplateCacheProvider.html +1 -1
  72. package/docs/static/typedoc/hierarchy.html +1 -1
  73. package/docs/static/typedoc/index.html +1 -1
  74. package/docs/static/typedoc/interfaces/Directive.html +5 -4
  75. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +1 -1
  76. package/docs/static/typedoc/interfaces/HttpResponse.html +2 -3
  77. package/docs/static/typedoc/interfaces/Provider.html +15 -10
  78. package/docs/static/typedoc/interfaces/RequestConfig.html +1 -1
  79. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +1 -1
  80. package/docs/static/typedoc/interfaces/TemplateCache.html +7 -0
  81. package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +1 -0
  82. package/docs/static/typedoc/types/DirectiveFactory.html +1 -2
  83. package/docs/static/typedoc/types/DirectiveFactoryFn.html +1 -0
  84. package/docs/static/typedoc/types/HttpResponseStatus.html +1 -0
  85. package/docs/static/typedoc/types/{TemplateCache.html → SwapModeType.html} +1 -1
  86. package/docs/static/typedoc/variables/SwapMode.html +11 -0
  87. package/legacy.d.ts +0 -14
  88. package/package.json +1 -3
  89. package/src/animations/animate-children-directive.js +2 -2
  90. package/src/animations/raf-scheduler.js +1 -1
  91. package/src/animations/shared.js +0 -9
  92. package/src/core/compile/attributes.js +1 -1
  93. package/src/core/compile/compile.js +3 -3
  94. package/src/core/di/injector.js +4 -17
  95. package/src/core/di/internal-injector.js +4 -1
  96. package/src/core/di/ng-module.js +12 -27
  97. package/src/core/filter/filter.js +28 -28
  98. package/src/core/parse/interpreter.js +32 -38
  99. package/src/core/sanitize/sanitize-uri.js +3 -3
  100. package/src/core/scope/scope.js +2 -7
  101. package/src/directive/attrs/attrs.js +7 -4
  102. package/src/directive/bind/bind.js +16 -4
  103. package/src/directive/bind/bind.spec.js +13 -0
  104. package/src/directive/events/events.js +7 -3
  105. package/src/directive/events/events.md +0 -41
  106. package/src/directive/http/delete.spec.js +2 -0
  107. package/src/directive/http/get.spec.js +280 -3
  108. package/src/directive/http/http.js +100 -12
  109. package/src/directive/http/http.test.js +2 -2
  110. package/src/directive/http/post.spec.js +2 -0
  111. package/src/directive/http/put.spec.js +2 -0
  112. package/src/directive/include/include.js +7 -7
  113. package/src/directive/input/input.js +6 -28
  114. package/src/directive/messages/messages.js +5 -1
  115. package/src/directive/model/model.js +1 -1
  116. package/src/directive/options/options.js +454 -464
  117. package/src/directive/repeat/repeat.js +175 -153
  118. package/src/directive/setter/setter.js +13 -15
  119. package/src/directive/setter/setter.spec.js +39 -16
  120. package/src/directive/switch/switch.js +1 -0
  121. package/src/directive/switch/switch.spec.js +1 -1
  122. package/src/directive/transclude/transclude.js +87 -89
  123. package/src/injection-tokens.js +1 -1
  124. package/src/interface.ts +68 -19
  125. package/src/loader.js +4 -9
  126. package/src/public.js +9 -15
  127. package/src/router/common/glob.js +5 -0
  128. package/src/router/directives/state-directives.js +4 -6
  129. package/src/router/directives/state-directives.spec.js +1 -1
  130. package/src/router/directives/view-directive.js +9 -1
  131. package/src/router/globals.js +0 -1
  132. package/src/router/state/state-registry.js +0 -1
  133. package/src/router/state-filters.js +2 -2
  134. package/src/router/url/url-service.js +5 -9
  135. package/src/services/anchor-scroll.html +0 -7
  136. package/src/services/anchor-scroll.js +2 -2
  137. package/src/{core → services/exception}/exception-handler.js +2 -2
  138. package/src/{core/error-handler.ts → services/exception/interface.ts} +1 -1
  139. package/src/services/http/http.js +2 -13
  140. package/src/services/http/interface.ts +2 -2
  141. package/src/services/http-backend/http-backend.js +4 -14
  142. package/src/services/http-backend/http-backend.spec.js +1 -4
  143. package/src/services/location/interface.ts +8 -0
  144. package/src/{core → services}/location/location.html +4 -1
  145. package/src/{core → services}/location/location.js +129 -27
  146. package/src/{core → services}/location/location.spec.js +2 -2
  147. package/src/{core → services}/location/location.test.js +1 -1
  148. package/src/{core → services}/sce/sce.html +1 -1
  149. package/src/{core → services}/sce/sce.js +9 -3
  150. package/src/{core → services}/sce/sce.spec.js +2 -3
  151. package/src/{core → services}/sce/sce.test.js +1 -1
  152. package/src/services/template-cache/interface.ts +8 -2
  153. package/src/services/template-cache/template-cache.js +3 -1
  154. package/src/services/template-cache/template-cache.spec.js +72 -0
  155. package/src/services/template-request.js +2 -1
  156. package/src/shared/cache.js +0 -2
  157. package/src/shared/dom.js +10 -0
  158. package/src/shared/test-utils.js +1 -0
  159. package/src/shared/url-utils/interface.ts +56 -0
  160. package/src/{core → shared}/url-utils/url-utils.html +4 -1
  161. package/src/{core → shared}/url-utils/url-utils.js +26 -23
  162. package/src/{core → shared}/url-utils/url-utils.spec.js +0 -8
  163. package/src/{core → shared}/url-utils/url-utils.test.js +1 -1
  164. package/src/shared/utils.js +47 -1
  165. package/utils/express.js +9 -1
  166. package/@types/core/task-tracker-factory.d.ts +0 -76
  167. package/@types/services/browser.d.ts +0 -101
  168. package/docs/static/typedoc/types/SwapInsertPosition.html +0 -2
  169. package/jsdoc.json +0 -22
  170. package/src/core/task-tracker-factory.js +0 -145
  171. package/src/services/browser.js +0 -212
  172. /package/src/{core → services}/location/location.md +0 -0
  173. /package/src/{core → services}/sce/sce.md +0 -0
  174. /package/src/{core → shared}/url-utils/url-utils.md +0 -0
@@ -29,7 +29,7 @@ export class AnchorScrollProvider {
29
29
  "$rootScope",
30
30
  /**
31
31
  *
32
- * @param {import('../core/location/location.js').Location} $location
32
+ * @param {import('../services/location/location.js').Location} $location
33
33
  * @param {import('../core/scope/scope.js').Scope} $rootScope
34
34
  * @returns
35
35
  */
@@ -128,7 +128,7 @@ export class AnchorScrollProvider {
128
128
  // skip the initial scroll if $location.hash is empty
129
129
  if (newVal === oldVal && newVal === "") return;
130
130
 
131
- const action = () => $rootScope.$evalAsync(scroll);
131
+ const action = () => Promise.resolve().then(scroll);
132
132
  if (document.readyState === "complete") {
133
133
  // Force the action to be run async for consistent behavior
134
134
  // from the action's point of view
@@ -42,9 +42,9 @@
42
42
  * @see {@link angular.ErrorHandler AngularTS ErrorHandler}
43
43
  */
44
44
 
45
- /** @typedef {import('../services/log/interface.ts').LogService} LogService */
45
+ /** @typedef {import('../log/interface.ts').LogService} LogService */
46
46
 
47
- /** @typedef {import("./error-handler.ts").ErrorHandler} ErrorHandler */
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 ErrorHandler = (exception: Error, cause?: string) => void;
7
+ export type Interface = (exception: Error, cause?: string) => void;
@@ -1,4 +1,4 @@
1
- import { urlIsAllowedOriginFactory } from "../../core/url-utils/url-utils.js";
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 ($browser, $httpBackend, $rootScope, $injector, $sce) {
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
- /** Added in AngularJS 1.6.6 */
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 "../../core/url-utils/url-utils.js";
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($browser) {
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 || $browser.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
- let $injector = createInjector(["ng"]);
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 type="module" src="/src/core/location/location.spec.js"></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 "../url-utils/url-utils.js";
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 {import('../url-utils/url-utils').HttpProtocol} */
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 {import("../url-utils/url-utils").HttpProtocol} protocol of current URL
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('../scope/scope.js').Scope} $rootScope
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, $browser, $rootElement) => {
741
+ ($rootScope, $rootElement) => {
636
742
  /** @type {Location} */
637
743
  let $location;
638
744
  let LocationMode;
639
- const baseHref = $browser.baseHref(); // if base[href] is undefined, it defaults to ''
640
- const initialUrl = /** @type {string} */ ($browser.url());
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 = $browser.state();
771
+ $location.$$state = this.state();
666
772
 
667
773
  const IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
668
774
 
669
- function setBrowserUrlWithFallback(url, state) {
775
+ const setBrowserUrlWithFallback = (url, state) => {
670
776
  const oldUrl = $location.url();
671
777
  const oldState = $location.$$state;
672
778
  try {
673
- $browser.url(url, state);
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 = $browser.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,20 +864,20 @@ export class LocationProvider {
762
864
 
763
865
  // rewrite hashbang url <> html5 url
764
866
  if ($location.absUrl() !== initialUrl) {
765
- $browser.url($location.absUrl(), true);
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
- $browser.onUrlChange((newUrl, newState) => {
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;
775
877
  return;
776
878
  }
777
879
 
778
- $rootScope.$evalAsync(() => {
880
+ Promise.resolve().then(() => {
779
881
  const oldUrl = $location.absUrl();
780
882
  const oldState = $location.$$state;
781
883
  let defaultPrevented;
@@ -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} */ ($browser.url());
915
+ const oldUrl = /** @type {string} */ (this.getUrl());
814
916
  const newUrl = $location.absUrl();
815
- const oldState = $browser.state();
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 "../di/injector.js";
7
+ import { createInjector } from "../../core/di/injector.js";
8
8
 
9
9
  describe("$location", () => {
10
10
  let module;
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from "@playwright/test";
2
2
 
3
- const TEST_URL = "src/core/location/location.html";
3
+ const TEST_URL = "src/services/location/location.html";
4
4
 
5
5
  test("unit tests contain no errors", async ({ page }) => {
6
6
  await page.goto(TEST_URL);
@@ -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/core/sce/sce.spec.js"></script>
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 "./../url-utils/url-utils.js";
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("../error-handler.ts").ErrorHandler } ErrorHandler */
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 "../di/injector.js";
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", () => {
@@ -1,6 +1,6 @@
1
1
  import { test, expect } from "@playwright/test";
2
2
 
3
- const TEST_URL = "src/core/sce/sce.html";
3
+ const TEST_URL = "src/services/sce/sce.html";
4
4
 
5
5
  test("unit tests contain no errors", async ({ page }) => {
6
6
  await page.goto(TEST_URL);
@@ -1,4 +1,10 @@
1
1
  /**
2
- * A cache for mapping template names to their respective content.
2
+ * A cache interface for mapping template urls to their XHR responses.
3
3
  */
4
- export type TemplateCache = Map<string, string>;
4
+ export interface TemplateCache {
5
+ get(key: string): any | undefined;
6
+ set(key: string, value: any): this;
7
+ has(key: string): boolean;
8
+ delete(key: string): boolean;
9
+ clear(): void;
10
+ }
@@ -9,5 +9,7 @@ export class TemplateCacheProvider {
9
9
  /**
10
10
  * @returns {import('./interface.ts').TemplateCache}
11
11
  */
12
- $get = () => this.cache;
12
+ $get() {
13
+ return this.cache;
14
+ }
13
15
  }
@@ -59,4 +59,76 @@ describe("$templateCache", () => {
59
59
  "<p>This is the content of the template</p>",
60
60
  );
61
61
  });
62
+
63
+ it("can be swapped for localStorage", async () => {
64
+ dealoc(el);
65
+ angular = new Angular();
66
+ angular.module("customStorage", []).config(($templateCacheProvider) => {
67
+ templateCacheProvider = $templateCacheProvider;
68
+ templateCacheProvider.cache = new LocalStorageMap();
69
+ templateCacheProvider.cache.set("test", "hello");
70
+ });
71
+ angular
72
+ .bootstrap(el, ["customStorage"])
73
+ .invoke((_$templateCache_, _$compile_, _$rootScope_) => {
74
+ templateCache = _$templateCache_;
75
+ $compile = _$compile_;
76
+ $scope = _$rootScope_;
77
+ });
78
+
79
+ expect(templateCache instanceof LocalStorageMap).toBeTrue();
80
+ el.innerHTML = `
81
+ <div ng-include="'test'">test</div>
82
+ `;
83
+ expect(el.innerText).toEqual("test");
84
+ $compile(el)($scope);
85
+ await wait();
86
+ expect(el.innerText).toEqual("hello");
87
+ expect(window.localStorage.getItem("test")).toEqual("hello");
88
+ });
62
89
  });
90
+
91
+ class LocalStorageMap {
92
+ constructor(prefix = "") {
93
+ this.prefix = prefix;
94
+ }
95
+
96
+ _key(key) {
97
+ return `${this.prefix}${key}`;
98
+ }
99
+
100
+ get(key) {
101
+ const raw = localStorage.getItem(this._key(key));
102
+ if (raw === null) return undefined;
103
+ try {
104
+ return JSON.parse(raw);
105
+ } catch {
106
+ return raw;
107
+ }
108
+ }
109
+
110
+ set(key, value) {
111
+ localStorage.setItem(this._key(key), value);
112
+ return this;
113
+ }
114
+
115
+ has(key) {
116
+ return localStorage.getItem(this._key(key)) !== null;
117
+ }
118
+
119
+ delete(key) {
120
+ localStorage.removeItem(this._key(key));
121
+ return true;
122
+ }
123
+
124
+ clear() {
125
+ const toRemove = [];
126
+ for (let i = 0; i < localStorage.length; i++) {
127
+ const k = localStorage.key(i);
128
+ if (k && k.startsWith(this.prefix)) {
129
+ toRemove.push(k);
130
+ }
131
+ }
132
+ toRemove.forEach((k) => localStorage.removeItem(k));
133
+ }
134
+ }