upgrade.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. /**
  2. * @license Angular v8.1.0
  3. * (c) 2010-2019 Google LLC. https://angular.io/
  4. * License: MIT
  5. */
  6. import { __read, __assign, __decorate } from 'tslib';
  7. import { Location, PlatformLocation, LocationStrategy, APP_BASE_HREF, CommonModule, HashLocationStrategy, PathLocationStrategy } from '@angular/common';
  8. import { InjectionToken, Inject, Optional, NgModule } from '@angular/core';
  9. import { UpgradeModule } from '@angular/upgrade/static';
  10. /**
  11. * @license
  12. * Copyright Google Inc. All Rights Reserved.
  13. *
  14. * Use of this source code is governed by an MIT-style license that can be
  15. * found in the LICENSE file at https://angular.io/license
  16. */
  17. function deepEqual(a, b) {
  18. if (a === b) {
  19. return true;
  20. }
  21. else if (!a || !b) {
  22. return false;
  23. }
  24. else {
  25. try {
  26. if ((a.prototype !== b.prototype) || (Array.isArray(a) && Array.isArray(b))) {
  27. return false;
  28. }
  29. return JSON.stringify(a) === JSON.stringify(b);
  30. }
  31. catch (e) {
  32. return false;
  33. }
  34. }
  35. }
  36. function isAnchor(el) {
  37. return el.href !== undefined;
  38. }
  39. function isPromise(obj) {
  40. // allow any Promise/A+ compliant thenable.
  41. // It's up to the caller to ensure that obj.then conforms to the spec
  42. return !!obj && typeof obj.then === 'function';
  43. }
  44. /**
  45. * @license
  46. * Copyright Google Inc. All Rights Reserved.
  47. *
  48. * Use of this source code is governed by an MIT-style license that can be
  49. * found in the LICENSE file at https://angular.io/license
  50. */
  51. var PATH_MATCH = /^([^?#]*)(\?([^#]*))?(#(.*))?$/;
  52. var DOUBLE_SLASH_REGEX = /^\s*[\\/]{2,}/;
  53. var IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
  54. var DEFAULT_PORTS = {
  55. 'http:': 80,
  56. 'https:': 443,
  57. 'ftp:': 21
  58. };
  59. /**
  60. * Location service that provides a drop-in replacement for the $location service
  61. * provided in AngularJS.
  62. *
  63. * @see [Using the Angular Unified Location Service](guide/upgrade#using-the-unified-angular-location-service)
  64. *
  65. * @publicApi
  66. */
  67. var $locationShim = /** @class */ (function () {
  68. function $locationShim($injector, location, platformLocation, urlCodec, locationStrategy) {
  69. var _this = this;
  70. this.location = location;
  71. this.platformLocation = platformLocation;
  72. this.urlCodec = urlCodec;
  73. this.locationStrategy = locationStrategy;
  74. this.initalizing = true;
  75. this.updateBrowser = false;
  76. this.$$absUrl = '';
  77. this.$$url = '';
  78. this.$$host = '';
  79. this.$$replace = false;
  80. this.$$path = '';
  81. this.$$search = '';
  82. this.$$hash = '';
  83. this.$$changeListeners = [];
  84. this.cachedState = null;
  85. this.lastBrowserUrl = '';
  86. // This variable should be used *only* inside the cacheState function.
  87. this.lastCachedState = null;
  88. var initialUrl = this.browserUrl();
  89. var parsedUrl = this.urlCodec.parse(initialUrl);
  90. if (typeof parsedUrl === 'string') {
  91. throw 'Invalid URL';
  92. }
  93. this.$$protocol = parsedUrl.protocol;
  94. this.$$host = parsedUrl.hostname;
  95. this.$$port = parseInt(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
  96. this.$$parseLinkUrl(initialUrl, initialUrl);
  97. this.cacheState();
  98. this.$$state = this.browserState();
  99. if (isPromise($injector)) {
  100. $injector.then(function ($i) { return _this.initialize($i); });
  101. }
  102. else {
  103. this.initialize($injector);
  104. }
  105. }
  106. $locationShim.prototype.initialize = function ($injector) {
  107. var _this = this;
  108. var $rootScope = $injector.get('$rootScope');
  109. var $rootElement = $injector.get('$rootElement');
  110. $rootElement.on('click', function (event) {
  111. if (event.ctrlKey || event.metaKey || event.shiftKey || event.which === 2 ||
  112. event.button === 2) {
  113. return;
  114. }
  115. var elm = event.target;
  116. // traverse the DOM up to find first A tag
  117. while (elm && elm.nodeName.toLowerCase() !== 'a') {
  118. // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
  119. if (elm === $rootElement[0] || !(elm = elm.parentNode)) {
  120. return;
  121. }
  122. }
  123. if (!isAnchor(elm)) {
  124. return;
  125. }
  126. var absHref = elm.href;
  127. var relHref = elm.getAttribute('href');
  128. // Ignore when url is started with javascript: or mailto:
  129. if (IGNORE_URI_REGEXP.test(absHref)) {
  130. return;
  131. }
  132. if (absHref && !elm.getAttribute('target') && !event.isDefaultPrevented()) {
  133. if (_this.$$parseLinkUrl(absHref, relHref)) {
  134. // We do a preventDefault for all urls that are part of the AngularJS application,
  135. // in html5mode and also without, so that we are able to abort navigation without
  136. // getting double entries in the location history.
  137. event.preventDefault();
  138. // update location manually
  139. if (_this.absUrl() !== _this.browserUrl()) {
  140. $rootScope.$apply();
  141. }
  142. }
  143. }
  144. });
  145. this.location.onUrlChange(function (newUrl, newState) {
  146. var oldUrl = _this.absUrl();
  147. var oldState = _this.$$state;
  148. _this.$$parse(newUrl);
  149. newUrl = _this.absUrl();
  150. _this.$$state = newState;
  151. var defaultPrevented = $rootScope.$broadcast('$locationChangeStart', newUrl, oldUrl, newState, oldState)
  152. .defaultPrevented;
  153. // if the location was changed by a `$locationChangeStart` handler then stop
  154. // processing this location change
  155. if (_this.absUrl() !== newUrl)
  156. return;
  157. // If default was prevented, set back to old state. This is the state that was locally
  158. // cached in the $location service.
  159. if (defaultPrevented) {
  160. _this.$$parse(oldUrl);
  161. _this.state(oldState);
  162. _this.setBrowserUrlWithFallback(oldUrl, false, oldState);
  163. }
  164. else {
  165. _this.initalizing = false;
  166. $rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl, newState, oldState);
  167. _this.resetBrowserUpdate();
  168. }
  169. if (!$rootScope.$$phase) {
  170. $rootScope.$digest();
  171. }
  172. });
  173. // update browser
  174. $rootScope.$watch(function () {
  175. if (_this.initalizing || _this.updateBrowser) {
  176. _this.updateBrowser = false;
  177. var oldUrl_1 = _this.browserUrl();
  178. var newUrl = _this.absUrl();
  179. var oldState_1 = _this.browserState();
  180. var currentReplace_1 = _this.$$replace;
  181. var urlOrStateChanged_1 = !_this.urlCodec.areEqual(oldUrl_1, newUrl) || oldState_1 !== _this.$$state;
  182. // Fire location changes one time to on initialization. This must be done on the
  183. // next tick (thus inside $evalAsync()) in order for listeners to be registered
  184. // before the event fires. Mimicing behavior from $locationWatch:
  185. // https://github.com/angular/angular.js/blob/master/src/ng/location.js#L983
  186. if (_this.initalizing || urlOrStateChanged_1) {
  187. _this.initalizing = false;
  188. $rootScope.$evalAsync(function () {
  189. // Get the new URL again since it could have changed due to async update
  190. var newUrl = _this.absUrl();
  191. var defaultPrevented = $rootScope
  192. .$broadcast('$locationChangeStart', newUrl, oldUrl_1, _this.$$state, oldState_1)
  193. .defaultPrevented;
  194. // if the location was changed by a `$locationChangeStart` handler then stop
  195. // processing this location change
  196. if (_this.absUrl() !== newUrl)
  197. return;
  198. if (defaultPrevented) {
  199. _this.$$parse(oldUrl_1);
  200. _this.$$state = oldState_1;
  201. }
  202. else {
  203. // This block doesn't run when initalizing because it's going to perform the update to
  204. // the URL which shouldn't be needed when initalizing.
  205. if (urlOrStateChanged_1) {
  206. _this.setBrowserUrlWithFallback(newUrl, currentReplace_1, oldState_1 === _this.$$state ? null : _this.$$state);
  207. _this.$$replace = false;
  208. }
  209. $rootScope.$broadcast('$locationChangeSuccess', newUrl, oldUrl_1, _this.$$state, oldState_1);
  210. }
  211. });
  212. }
  213. }
  214. _this.$$replace = false;
  215. });
  216. };
  217. $locationShim.prototype.resetBrowserUpdate = function () {
  218. this.$$replace = false;
  219. this.$$state = this.browserState();
  220. this.updateBrowser = false;
  221. this.lastBrowserUrl = this.browserUrl();
  222. };
  223. $locationShim.prototype.browserUrl = function (url, replace, state) {
  224. // In modern browsers `history.state` is `null` by default; treating it separately
  225. // from `undefined` would cause `$browser.url('/foo')` to change `history.state`
  226. // to undefined via `pushState`. Instead, let's change `undefined` to `null` here.
  227. if (typeof state === 'undefined') {
  228. state = null;
  229. }
  230. // setter
  231. if (url) {
  232. var sameState = this.lastHistoryState === state;
  233. // Normalize the inputted URL
  234. url = this.urlCodec.parse(url).href;
  235. // Don't change anything if previous and current URLs and states match.
  236. if (this.lastBrowserUrl === url && sameState) {
  237. return this;
  238. }
  239. this.lastBrowserUrl = url;
  240. this.lastHistoryState = state;
  241. // Remove server base from URL as the Angular APIs for updating URL require
  242. // it to be the path+.
  243. url = this.stripBaseUrl(this.getServerBase(), url) || url;
  244. // Set the URL
  245. if (replace) {
  246. this.locationStrategy.replaceState(state, '', url, '');
  247. }
  248. else {
  249. this.locationStrategy.pushState(state, '', url, '');
  250. }
  251. this.cacheState();
  252. return this;
  253. // getter
  254. }
  255. else {
  256. return this.platformLocation.href;
  257. }
  258. };
  259. $locationShim.prototype.cacheState = function () {
  260. // This should be the only place in $browser where `history.state` is read.
  261. this.cachedState = this.platformLocation.getState();
  262. if (typeof this.cachedState === 'undefined') {
  263. this.cachedState = null;
  264. }
  265. // Prevent callbacks fo fire twice if both hashchange & popstate were fired.
  266. if (deepEqual(this.cachedState, this.lastCachedState)) {
  267. this.cachedState = this.lastCachedState;
  268. }
  269. this.lastCachedState = this.cachedState;
  270. this.lastHistoryState = this.cachedState;
  271. };
  272. /**
  273. * This function emulates the $browser.state() function from AngularJS. It will cause
  274. * history.state to be cached unless changed with deep equality check.
  275. */
  276. $locationShim.prototype.browserState = function () { return this.cachedState; };
  277. $locationShim.prototype.stripBaseUrl = function (base, url) {
  278. if (url.startsWith(base)) {
  279. return url.substr(base.length);
  280. }
  281. return undefined;
  282. };
  283. $locationShim.prototype.getServerBase = function () {
  284. var _a = this.platformLocation, protocol = _a.protocol, hostname = _a.hostname, port = _a.port;
  285. var baseHref = this.locationStrategy.getBaseHref();
  286. var url = protocol + "//" + hostname + (port ? ':' + port : '') + (baseHref || '/');
  287. return url.endsWith('/') ? url : url + '/';
  288. };
  289. $locationShim.prototype.parseAppUrl = function (url) {
  290. if (DOUBLE_SLASH_REGEX.test(url)) {
  291. throw new Error("Bad Path - URL cannot start with double slashes: " + url);
  292. }
  293. var prefixed = (url.charAt(0) !== '/');
  294. if (prefixed) {
  295. url = '/' + url;
  296. }
  297. var match = this.urlCodec.parse(url, this.getServerBase());
  298. if (typeof match === 'string') {
  299. throw new Error("Bad URL - Cannot parse URL: " + url);
  300. }
  301. var path = prefixed && match.pathname.charAt(0) === '/' ? match.pathname.substring(1) : match.pathname;
  302. this.$$path = this.urlCodec.decodePath(path);
  303. this.$$search = this.urlCodec.decodeSearch(match.search);
  304. this.$$hash = this.urlCodec.decodeHash(match.hash);
  305. // make sure path starts with '/';
  306. if (this.$$path && this.$$path.charAt(0) !== '/') {
  307. this.$$path = '/' + this.$$path;
  308. }
  309. };
  310. /**
  311. * Registers listeners for URL changes. This API is used to catch updates performed by the
  312. * AngularJS framework. These changes are a subset of the `$locationChangeStart` and
  313. * `$locationChangeSuccess` events which fire when AngularJS updates its internally-referenced
  314. * version of the browser URL.
  315. *
  316. * It's possible for `$locationChange` events to happen, but for the browser URL
  317. * (window.location) to remain unchanged. This `onChange` callback will fire only when AngularJS
  318. * actually updates the browser URL (window.location).
  319. *
  320. * @param fn The callback function that is triggered for the listener when the URL changes.
  321. * @param err The callback function that is triggered when an error occurs.
  322. */
  323. $locationShim.prototype.onChange = function (fn, err) {
  324. if (err === void 0) { err = function (e) { }; }
  325. this.$$changeListeners.push([fn, err]);
  326. };
  327. /** @internal */
  328. $locationShim.prototype.$$notifyChangeListeners = function (url, state, oldUrl, oldState) {
  329. if (url === void 0) { url = ''; }
  330. if (oldUrl === void 0) { oldUrl = ''; }
  331. this.$$changeListeners.forEach(function (_a) {
  332. var _b = __read(_a, 2), fn = _b[0], err = _b[1];
  333. try {
  334. fn(url, state, oldUrl, oldState);
  335. }
  336. catch (e) {
  337. err(e);
  338. }
  339. });
  340. };
  341. /**
  342. * Parses the provided URL, and sets the current URL to the parsed result.
  343. *
  344. * @param url The URL string.
  345. */
  346. $locationShim.prototype.$$parse = function (url) {
  347. var pathUrl;
  348. if (url.startsWith('/')) {
  349. pathUrl = url;
  350. }
  351. else {
  352. // Remove protocol & hostname if URL starts with it
  353. pathUrl = this.stripBaseUrl(this.getServerBase(), url);
  354. }
  355. if (typeof pathUrl === 'undefined') {
  356. throw new Error("Invalid url \"" + url + "\", missing path prefix \"" + this.getServerBase() + "\".");
  357. }
  358. this.parseAppUrl(pathUrl);
  359. if (!this.$$path) {
  360. this.$$path = '/';
  361. }
  362. this.composeUrls();
  363. };
  364. /**
  365. * Parses the provided URL and its relative URL.
  366. *
  367. * @param url The full URL string.
  368. * @param relHref A URL string relative to the full URL string.
  369. */
  370. $locationShim.prototype.$$parseLinkUrl = function (url, relHref) {
  371. // When relHref is passed, it should be a hash and is handled separately
  372. if (relHref && relHref[0] === '#') {
  373. this.hash(relHref.slice(1));
  374. return true;
  375. }
  376. var rewrittenUrl;
  377. var appUrl = this.stripBaseUrl(this.getServerBase(), url);
  378. if (typeof appUrl !== 'undefined') {
  379. rewrittenUrl = this.getServerBase() + appUrl;
  380. }
  381. else if (this.getServerBase() === url + '/') {
  382. rewrittenUrl = this.getServerBase();
  383. }
  384. // Set the URL
  385. if (rewrittenUrl) {
  386. this.$$parse(rewrittenUrl);
  387. }
  388. return !!rewrittenUrl;
  389. };
  390. $locationShim.prototype.setBrowserUrlWithFallback = function (url, replace, state) {
  391. var oldUrl = this.url();
  392. var oldState = this.$$state;
  393. try {
  394. this.browserUrl(url, replace, state);
  395. // Make sure $location.state() returns referentially identical (not just deeply equal)
  396. // state object; this makes possible quick checking if the state changed in the digest
  397. // loop. Checking deep equality would be too expensive.
  398. this.$$state = this.browserState();
  399. this.$$notifyChangeListeners(url, state, oldUrl, oldState);
  400. }
  401. catch (e) {
  402. // Restore old values if pushState fails
  403. this.url(oldUrl);
  404. this.$$state = oldState;
  405. throw e;
  406. }
  407. };
  408. $locationShim.prototype.composeUrls = function () {
  409. this.$$url = this.urlCodec.normalize(this.$$path, this.$$search, this.$$hash);
  410. this.$$absUrl = this.getServerBase() + this.$$url.substr(1); // remove '/' from front of URL
  411. this.updateBrowser = true;
  412. };
  413. /**
  414. * Retrieves the full URL representation with all segments encoded according to
  415. * rules specified in
  416. * [RFC 3986](http://www.ietf.org/rfc/rfc3986.txt).
  417. *
  418. *
  419. * ```js
  420. * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
  421. * let absUrl = $location.absUrl();
  422. * // => "http://example.com/#/some/path?foo=bar&baz=xoxo"
  423. * ```
  424. */
  425. $locationShim.prototype.absUrl = function () { return this.$$absUrl; };
  426. $locationShim.prototype.url = function (url) {
  427. if (typeof url === 'string') {
  428. if (!url.length) {
  429. url = '/';
  430. }
  431. var match = PATH_MATCH.exec(url);
  432. if (!match)
  433. return this;
  434. if (match[1] || url === '')
  435. this.path(this.urlCodec.decodePath(match[1]));
  436. if (match[2] || match[1] || url === '')
  437. this.search(match[3] || '');
  438. this.hash(match[5] || '');
  439. // Chainable method
  440. return this;
  441. }
  442. return this.$$url;
  443. };
  444. /**
  445. * Retrieves the protocol of the current URL.
  446. *
  447. * ```js
  448. * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
  449. * let protocol = $location.protocol();
  450. * // => "http"
  451. * ```
  452. */
  453. $locationShim.prototype.protocol = function () { return this.$$protocol; };
  454. /**
  455. * Retrieves the protocol of the current URL.
  456. *
  457. * In contrast to the non-AngularJS version `location.host` which returns `hostname:port`, this
  458. * returns the `hostname` portion only.
  459. *
  460. *
  461. * ```js
  462. * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
  463. * let host = $location.host();
  464. * // => "example.com"
  465. *
  466. * // given URL http://user:password@example.com:8080/#/some/path?foo=bar&baz=xoxo
  467. * host = $location.host();
  468. * // => "example.com"
  469. * host = location.host;
  470. * // => "example.com:8080"
  471. * ```
  472. */
  473. $locationShim.prototype.host = function () { return this.$$host; };
  474. /**
  475. * Retrieves the port of the current URL.
  476. *
  477. * ```js
  478. * // given URL http://example.com/#/some/path?foo=bar&baz=xoxo
  479. * let port = $location.port();
  480. * // => 80
  481. * ```
  482. */
  483. $locationShim.prototype.port = function () { return this.$$port; };
  484. $locationShim.prototype.path = function (path) {
  485. if (typeof path === 'undefined') {
  486. return this.$$path;
  487. }
  488. // null path converts to empty string. Prepend with "/" if needed.
  489. path = path !== null ? path.toString() : '';
  490. path = path.charAt(0) === '/' ? path : '/' + path;
  491. this.$$path = path;
  492. this.composeUrls();
  493. return this;
  494. };
  495. $locationShim.prototype.search = function (search, paramValue) {
  496. switch (arguments.length) {
  497. case 0:
  498. return this.$$search;
  499. case 1:
  500. if (typeof search === 'string' || typeof search === 'number') {
  501. this.$$search = this.urlCodec.decodeSearch(search.toString());
  502. }
  503. else if (typeof search === 'object' && search !== null) {
  504. // Copy the object so it's never mutated
  505. search = __assign({}, search);
  506. // remove object undefined or null properties
  507. for (var key in search) {
  508. if (search[key] == null)
  509. delete search[key];
  510. }
  511. this.$$search = search;
  512. }
  513. else {
  514. throw new Error('LocationProvider.search(): First argument must be a string or an object.');
  515. }
  516. break;
  517. default:
  518. if (typeof search === 'string') {
  519. var currentSearch = this.search();
  520. if (typeof paramValue === 'undefined' || paramValue === null) {
  521. delete currentSearch[search];
  522. return this.search(currentSearch);
  523. }
  524. else {
  525. currentSearch[search] = paramValue;
  526. return this.search(currentSearch);
  527. }
  528. }
  529. }
  530. this.composeUrls();
  531. return this;
  532. };
  533. $locationShim.prototype.hash = function (hash) {
  534. if (typeof hash === 'undefined') {
  535. return this.$$hash;
  536. }
  537. this.$$hash = hash !== null ? hash.toString() : '';
  538. this.composeUrls();
  539. return this;
  540. };
  541. /**
  542. * Changes to `$location` during the current `$digest` will replace the current
  543. * history record, instead of adding a new one.
  544. */
  545. $locationShim.prototype.replace = function () {
  546. this.$$replace = true;
  547. return this;
  548. };
  549. $locationShim.prototype.state = function (state) {
  550. if (typeof state === 'undefined') {
  551. return this.$$state;
  552. }
  553. this.$$state = state;
  554. return this;
  555. };
  556. return $locationShim;
  557. }());
  558. /**
  559. * The factory function used to create an instance of the `$locationShim` in Angular,
  560. * and provides an API-compatiable `$locationProvider` for AngularJS.
  561. *
  562. * @publicApi
  563. */
  564. var $locationShimProvider = /** @class */ (function () {
  565. function $locationShimProvider(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
  566. this.ngUpgrade = ngUpgrade;
  567. this.location = location;
  568. this.platformLocation = platformLocation;
  569. this.urlCodec = urlCodec;
  570. this.locationStrategy = locationStrategy;
  571. }
  572. /**
  573. * Factory method that returns an instance of the $locationShim
  574. */
  575. $locationShimProvider.prototype.$get = function () {
  576. return new $locationShim(this.ngUpgrade.$injector, this.location, this.platformLocation, this.urlCodec, this.locationStrategy);
  577. };
  578. /**
  579. * Stub method used to keep API compatible with AngularJS. This setting is configured through
  580. * the LocationUpgradeModule's `config` method in your Angular app.
  581. */
  582. $locationShimProvider.prototype.hashPrefix = function (prefix) {
  583. throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
  584. };
  585. /**
  586. * Stub method used to keep API compatible with AngularJS. This setting is configured through
  587. * the LocationUpgradeModule's `config` method in your Angular app.
  588. */
  589. $locationShimProvider.prototype.html5Mode = function (mode) {
  590. throw new Error('Configure LocationUpgrade through LocationUpgradeModule.config method.');
  591. };
  592. return $locationShimProvider;
  593. }());
  594. /**
  595. * @license
  596. * Copyright Google Inc. All Rights Reserved.
  597. *
  598. * Use of this source code is governed by an MIT-style license that can be
  599. * found in the LICENSE file at https://angular.io/license
  600. */
  601. /**
  602. * A codec for encoding and decoding URL parts.
  603. *
  604. * @publicApi
  605. **/
  606. var UrlCodec = /** @class */ (function () {
  607. function UrlCodec() {
  608. }
  609. return UrlCodec;
  610. }());
  611. /**
  612. * A `UrlCodec` that uses logic from AngularJS to serialize and parse URLs
  613. * and URL parameters.
  614. *
  615. * @publicApi
  616. */
  617. var AngularJSUrlCodec = /** @class */ (function () {
  618. function AngularJSUrlCodec() {
  619. }
  620. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L15
  621. AngularJSUrlCodec.prototype.encodePath = function (path) {
  622. var segments = path.split('/');
  623. var i = segments.length;
  624. while (i--) {
  625. // decode forward slashes to prevent them from being double encoded
  626. segments[i] = encodeUriSegment(segments[i].replace(/%2F/g, '/'));
  627. }
  628. path = segments.join('/');
  629. return _stripIndexHtml((path && path[0] !== '/' && '/' || '') + path);
  630. };
  631. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L42
  632. AngularJSUrlCodec.prototype.encodeSearch = function (search) {
  633. if (typeof search === 'string') {
  634. search = parseKeyValue(search);
  635. }
  636. search = toKeyValue(search);
  637. return search ? '?' + search : '';
  638. };
  639. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L44
  640. AngularJSUrlCodec.prototype.encodeHash = function (hash) {
  641. hash = encodeUriSegment(hash);
  642. return hash ? '#' + hash : '';
  643. };
  644. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L27
  645. AngularJSUrlCodec.prototype.decodePath = function (path, html5Mode) {
  646. if (html5Mode === void 0) { html5Mode = true; }
  647. var segments = path.split('/');
  648. var i = segments.length;
  649. while (i--) {
  650. segments[i] = decodeURIComponent(segments[i]);
  651. if (html5Mode) {
  652. // encode forward slashes to prevent them from being mistaken for path separators
  653. segments[i] = segments[i].replace(/\//g, '%2F');
  654. }
  655. }
  656. return segments.join('/');
  657. };
  658. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L72
  659. AngularJSUrlCodec.prototype.decodeSearch = function (search) { return parseKeyValue(search); };
  660. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/location.js#L73
  661. AngularJSUrlCodec.prototype.decodeHash = function (hash) {
  662. hash = decodeURIComponent(hash);
  663. return hash[0] === '#' ? hash.substring(1) : hash;
  664. };
  665. AngularJSUrlCodec.prototype.normalize = function (pathOrHref, search, hash, baseUrl) {
  666. if (arguments.length === 1) {
  667. var parsed = this.parse(pathOrHref, baseUrl);
  668. if (typeof parsed === 'string') {
  669. return parsed;
  670. }
  671. var serverUrl = parsed.protocol + "://" + parsed.hostname + (parsed.port ? ':' + parsed.port : '');
  672. return this.normalize(this.decodePath(parsed.pathname), this.decodeSearch(parsed.search), this.decodeHash(parsed.hash), serverUrl);
  673. }
  674. else {
  675. var encPath = this.encodePath(pathOrHref);
  676. var encSearch = search && this.encodeSearch(search) || '';
  677. var encHash = hash && this.encodeHash(hash) || '';
  678. var joinedPath = (baseUrl || '') + encPath;
  679. if (!joinedPath.length || joinedPath[0] !== '/') {
  680. joinedPath = '/' + joinedPath;
  681. }
  682. return joinedPath + encSearch + encHash;
  683. }
  684. };
  685. AngularJSUrlCodec.prototype.areEqual = function (valA, valB) { return this.normalize(valA) === this.normalize(valB); };
  686. // https://github.com/angular/angular.js/blob/864c7f0/src/ng/urlUtils.js#L60
  687. AngularJSUrlCodec.prototype.parse = function (url, base) {
  688. try {
  689. var parsed = new URL(url, base);
  690. return {
  691. href: parsed.href,
  692. protocol: parsed.protocol ? parsed.protocol.replace(/:$/, '') : '',
  693. host: parsed.host,
  694. search: parsed.search ? parsed.search.replace(/^\?/, '') : '',
  695. hash: parsed.hash ? parsed.hash.replace(/^#/, '') : '',
  696. hostname: parsed.hostname,
  697. port: parsed.port,
  698. pathname: (parsed.pathname.charAt(0) === '/') ? parsed.pathname : '/' + parsed.pathname
  699. };
  700. }
  701. catch (e) {
  702. throw new Error("Invalid URL (" + url + ") with base (" + base + ")");
  703. }
  704. };
  705. return AngularJSUrlCodec;
  706. }());
  707. function _stripIndexHtml(url) {
  708. return url.replace(/\/index.html$/, '');
  709. }
  710. /**
  711. * Tries to decode the URI component without throwing an exception.
  712. *
  713. * @private
  714. * @param str value potential URI component to check.
  715. * @returns {boolean} True if `value` can be decoded
  716. * with the decodeURIComponent function.
  717. */
  718. function tryDecodeURIComponent(value) {
  719. try {
  720. return decodeURIComponent(value);
  721. }
  722. catch (e) {
  723. // Ignore any invalid uri component.
  724. return undefined;
  725. }
  726. }
  727. /**
  728. * Parses an escaped url query string into key-value pairs. Logic taken from
  729. * https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1382
  730. * @returns {Object.<string,boolean|Array>}
  731. */
  732. function parseKeyValue(keyValue) {
  733. var obj = {};
  734. (keyValue || '').split('&').forEach(function (keyValue) {
  735. var splitPoint, key, val;
  736. if (keyValue) {
  737. key = keyValue = keyValue.replace(/\+/g, '%20');
  738. splitPoint = keyValue.indexOf('=');
  739. if (splitPoint !== -1) {
  740. key = keyValue.substring(0, splitPoint);
  741. val = keyValue.substring(splitPoint + 1);
  742. }
  743. key = tryDecodeURIComponent(key);
  744. if (typeof key !== 'undefined') {
  745. val = typeof val !== 'undefined' ? tryDecodeURIComponent(val) : true;
  746. if (!obj.hasOwnProperty(key)) {
  747. obj[key] = val;
  748. }
  749. else if (Array.isArray(obj[key])) {
  750. obj[key].push(val);
  751. }
  752. else {
  753. obj[key] = [obj[key], val];
  754. }
  755. }
  756. }
  757. });
  758. return obj;
  759. }
  760. /**
  761. * Serializes into key-value pairs. Logic taken from
  762. * https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1409
  763. */
  764. function toKeyValue(obj) {
  765. var parts = [];
  766. var _loop_1 = function (key) {
  767. var value = obj[key];
  768. if (Array.isArray(value)) {
  769. value.forEach(function (arrayValue) {
  770. parts.push(encodeUriQuery(key, true) +
  771. (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
  772. });
  773. }
  774. else {
  775. parts.push(encodeUriQuery(key, true) +
  776. (value === true ? '' : '=' + encodeUriQuery(value, true)));
  777. }
  778. };
  779. for (var key in obj) {
  780. _loop_1(key);
  781. }
  782. return parts.length ? parts.join('&') : '';
  783. }
  784. /**
  785. * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
  786. * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
  787. * segments:
  788. * segment = *pchar
  789. * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
  790. * pct-encoded = "%" HEXDIG HEXDIG
  791. * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
  792. * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
  793. * / "*" / "+" / "," / ";" / "="
  794. *
  795. * Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1437
  796. */
  797. function encodeUriSegment(val) {
  798. return encodeUriQuery(val, true)
  799. .replace(/%26/gi, '&')
  800. .replace(/%3D/gi, '=')
  801. .replace(/%2B/gi, '+');
  802. }
  803. /**
  804. * This method is intended for encoding *key* or *value* parts of query component. We need a custom
  805. * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
  806. * encoded per http://tools.ietf.org/html/rfc3986:
  807. * query = *( pchar / "/" / "?" )
  808. * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
  809. * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
  810. * pct-encoded = "%" HEXDIG HEXDIG
  811. * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
  812. * / "*" / "+" / "," / ";" / "="
  813. *
  814. * Logic from https://github.com/angular/angular.js/blob/864c7f0/src/Angular.js#L1456
  815. */
  816. function encodeUriQuery(val, pctEncodeSpaces) {
  817. if (pctEncodeSpaces === void 0) { pctEncodeSpaces = false; }
  818. return encodeURIComponent(val)
  819. .replace(/%40/gi, '@')
  820. .replace(/%3A/gi, ':')
  821. .replace(/%24/g, '$')
  822. .replace(/%2C/gi, ',')
  823. .replace(/%3B/gi, ';')
  824. .replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
  825. }
  826. /**
  827. * @license
  828. * Copyright Google Inc. All Rights Reserved.
  829. *
  830. * Use of this source code is governed by an MIT-style license that can be
  831. * found in the LICENSE file at https://angular.io/license
  832. */
  833. /**
  834. * A provider token used to configure the location upgrade module.
  835. *
  836. * @publicApi
  837. */
  838. var LOCATION_UPGRADE_CONFIGURATION = new InjectionToken('LOCATION_UPGRADE_CONFIGURATION');
  839. var APP_BASE_HREF_RESOLVED = new InjectionToken('APP_BASE_HREF_RESOLVED');
  840. /**
  841. * `NgModule` used for providing and configuring Angular's Unified Location Service for upgrading.
  842. *
  843. * @see [Using the Unified Angular Location Service](guide/upgrade#using-the-unified-angular-location-service)
  844. *
  845. * @publicApi
  846. */
  847. var LocationUpgradeModule = /** @class */ (function () {
  848. function LocationUpgradeModule() {
  849. }
  850. LocationUpgradeModule_1 = LocationUpgradeModule;
  851. LocationUpgradeModule.config = function (config) {
  852. return {
  853. ngModule: LocationUpgradeModule_1,
  854. providers: [
  855. Location,
  856. {
  857. provide: $locationShim,
  858. useFactory: provide$location,
  859. deps: [UpgradeModule, Location, PlatformLocation, UrlCodec, LocationStrategy]
  860. },
  861. { provide: LOCATION_UPGRADE_CONFIGURATION, useValue: config ? config : {} },
  862. { provide: UrlCodec, useFactory: provideUrlCodec, deps: [LOCATION_UPGRADE_CONFIGURATION] },
  863. {
  864. provide: APP_BASE_HREF_RESOLVED,
  865. useFactory: provideAppBaseHref,
  866. deps: [LOCATION_UPGRADE_CONFIGURATION, [new Inject(APP_BASE_HREF), new Optional()]]
  867. },
  868. {
  869. provide: LocationStrategy,
  870. useFactory: provideLocationStrategy,
  871. deps: [
  872. PlatformLocation,
  873. APP_BASE_HREF_RESOLVED,
  874. LOCATION_UPGRADE_CONFIGURATION,
  875. ]
  876. },
  877. ],
  878. };
  879. };
  880. var LocationUpgradeModule_1;
  881. LocationUpgradeModule = LocationUpgradeModule_1 = __decorate([
  882. NgModule({ imports: [CommonModule] })
  883. ], LocationUpgradeModule);
  884. return LocationUpgradeModule;
  885. }());
  886. function provideAppBaseHref(config, appBaseHref) {
  887. if (config && config.appBaseHref != null) {
  888. return config.appBaseHref;
  889. }
  890. else if (appBaseHref != null) {
  891. return appBaseHref;
  892. }
  893. return '';
  894. }
  895. function provideUrlCodec(config) {
  896. var codec = config && config.urlCodec || AngularJSUrlCodec;
  897. return new codec();
  898. }
  899. function provideLocationStrategy(platformLocation, baseHref, options) {
  900. if (options === void 0) { options = {}; }
  901. return options.useHash ? new HashLocationStrategy(platformLocation, baseHref) :
  902. new PathLocationStrategy(platformLocation, baseHref);
  903. }
  904. function provide$location(ngUpgrade, location, platformLocation, urlCodec, locationStrategy) {
  905. var $locationProvider = new $locationShimProvider(ngUpgrade, location, platformLocation, urlCodec, locationStrategy);
  906. return $locationProvider.$get();
  907. }
  908. /**
  909. * @license
  910. * Copyright Google Inc. All Rights Reserved.
  911. *
  912. * Use of this source code is governed by an MIT-style license that can be
  913. * found in the LICENSE file at https://angular.io/license
  914. */
  915. /**
  916. * @license
  917. * Copyright Google Inc. All Rights Reserved.
  918. *
  919. * Use of this source code is governed by an MIT-style license that can be
  920. * found in the LICENSE file at https://angular.io/license
  921. */
  922. // This file only reexports content of the `src` folder. Keep it that way.
  923. /**
  924. * @license
  925. * Copyright Google Inc. All Rights Reserved.
  926. *
  927. * Use of this source code is governed by an MIT-style license that can be
  928. * found in the LICENSE file at https://angular.io/license
  929. */
  930. /**
  931. * Generated bundle index. Do not edit.
  932. */
  933. export { provide$location as ɵangular_packages_common_upgrade_upgrade_d, provideAppBaseHref as ɵangular_packages_common_upgrade_upgrade_a, provideLocationStrategy as ɵangular_packages_common_upgrade_upgrade_c, provideUrlCodec as ɵangular_packages_common_upgrade_upgrade_b, $locationShim, $locationShimProvider, LOCATION_UPGRADE_CONFIGURATION, LocationUpgradeModule, AngularJSUrlCodec, UrlCodec };
  934. //# sourceMappingURL=upgrade.js.map