(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["vendor"],{
/***/ "./node_modules/@angular/common/__ivy_ngcc__/fesm2015/common.js":
/*!**********************************************************************!*\
!*** ./node_modules/@angular/common/__ivy_ngcc__/fesm2015/common.js ***!
\**********************************************************************/
/*! exports provided: APP_BASE_HREF, AsyncPipe, CommonModule, CurrencyPipe, DOCUMENT, DatePipe, DecimalPipe, FormStyle, FormatWidth, HashLocationStrategy, I18nPluralPipe, I18nSelectPipe, JsonPipe, KeyValuePipe, LOCATION_INITIALIZED, Location, LocationStrategy, LowerCasePipe, NgClass, NgComponentOutlet, NgForOf, NgForOfContext, NgIf, NgIfContext, NgLocaleLocalization, NgLocalization, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NumberFormatStyle, NumberSymbol, PathLocationStrategy, PercentPipe, PlatformLocation, Plural, SlicePipe, TitleCasePipe, TranslationWidth, UpperCasePipe, VERSION, ViewportScroller, WeekDay, formatCurrency, formatDate, formatNumber, formatPercent, getCurrencySymbol, getLocaleCurrencyCode, getLocaleCurrencyName, getLocaleCurrencySymbol, getLocaleDateFormat, getLocaleDateTimeFormat, getLocaleDayNames, getLocaleDayPeriods, getLocaleDirection, getLocaleEraNames, getLocaleExtraDayPeriodRules, getLocaleExtraDayPeriods, getLocaleFirstDayOfWeek, getLocaleId, getLocaleMonthNames, getLocaleNumberFormat, getLocaleNumberSymbol, getLocalePluralCase, getLocaleTimeFormat, getLocaleWeekEndRange, getNumberOfCurrencyDigits, isPlatformBrowser, isPlatformServer, isPlatformWorkerApp, isPlatformWorkerUi, registerLocaleData, ɵBrowserPlatformLocation, ɵDomAdapter, ɵNullViewportScroller, ɵPLATFORM_BROWSER_ID, ɵPLATFORM_SERVER_ID, ɵPLATFORM_WORKER_APP_ID, ɵPLATFORM_WORKER_UI_ID, ɵangular_packages_common_common_a, ɵangular_packages_common_common_b, ɵangular_packages_common_common_c, ɵangular_packages_common_common_d, ɵangular_packages_common_common_e, ɵangular_packages_common_common_f, ɵgetDOM, ɵparseCookieValue, ɵsetRootDomAdapter */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "APP_BASE_HREF", function() { return APP_BASE_HREF; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AsyncPipe", function() { return AsyncPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommonModule", function() { return CommonModule; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CurrencyPipe", function() { return CurrencyPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DOCUMENT", function() { return DOCUMENT; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DatePipe", function() { return DatePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DecimalPipe", function() { return DecimalPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormStyle", function() { return FormStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FormatWidth", function() { return FormatWidth; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HashLocationStrategy", function() { return HashLocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nPluralPipe", function() { return I18nPluralPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18nSelectPipe", function() { return I18nSelectPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JsonPipe", function() { return JsonPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyValuePipe", function() { return KeyValuePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LOCATION_INITIALIZED", function() { return LOCATION_INITIALIZED; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Location", function() { return Location; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LocationStrategy", function() { return LocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LowerCasePipe", function() { return LowerCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgClass", function() { return NgClass; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgComponentOutlet", function() { return NgComponentOutlet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOf", function() { return NgForOf; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgForOfContext", function() { return NgForOfContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIf", function() { return NgIf; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgIfContext", function() { return NgIfContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocaleLocalization", function() { return NgLocaleLocalization; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgLocalization", function() { return NgLocalization; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPlural", function() { return NgPlural; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgPluralCase", function() { return NgPluralCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgStyle", function() { return NgStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitch", function() { return NgSwitch; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchCase", function() { return NgSwitchCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgSwitchDefault", function() { return NgSwitchDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgTemplateOutlet", function() { return NgTemplateOutlet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberFormatStyle", function() { return NumberFormatStyle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NumberSymbol", function() { return NumberSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PathLocationStrategy", function() { return PathLocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PercentPipe", function() { return PercentPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PlatformLocation", function() { return PlatformLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Plural", function() { return Plural; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SlicePipe", function() { return SlicePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TitleCasePipe", function() { return TitleCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TranslationWidth", function() { return TranslationWidth; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UpperCasePipe", function() { return UpperCasePipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewportScroller", function() { return ViewportScroller; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WeekDay", function() { return WeekDay; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatCurrency", function() { return formatCurrency; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatDate", function() { return formatDate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatNumber", function() { return formatNumber; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formatPercent", function() { return formatPercent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getCurrencySymbol", function() { return getCurrencySymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencyCode", function() { return getLocaleCurrencyCode; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencyName", function() { return getLocaleCurrencyName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleCurrencySymbol", function() { return getLocaleCurrencySymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateFormat", function() { return getLocaleDateFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDateTimeFormat", function() { return getLocaleDateTimeFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayNames", function() { return getLocaleDayNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDayPeriods", function() { return getLocaleDayPeriods; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleDirection", function() { return getLocaleDirection; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleEraNames", function() { return getLocaleEraNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriodRules", function() { return getLocaleExtraDayPeriodRules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleExtraDayPeriods", function() { return getLocaleExtraDayPeriods; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleFirstDayOfWeek", function() { return getLocaleFirstDayOfWeek; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleId", function() { return getLocaleId; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleMonthNames", function() { return getLocaleMonthNames; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberFormat", function() { return getLocaleNumberFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleNumberSymbol", function() { return getLocaleNumberSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocalePluralCase", function() { return getLocalePluralCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleTimeFormat", function() { return getLocaleTimeFormat; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getLocaleWeekEndRange", function() { return getLocaleWeekEndRange; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNumberOfCurrencyDigits", function() { return getNumberOfCurrencyDigits; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformBrowser", function() { return isPlatformBrowser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformServer", function() { return isPlatformServer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerApp", function() { return isPlatformWorkerApp; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isPlatformWorkerUi", function() { return isPlatformWorkerUi; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "registerLocaleData", function() { return registerLocaleData; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵBrowserPlatformLocation", function() { return BrowserPlatformLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵDomAdapter", function() { return DomAdapter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵNullViewportScroller", function() { return NullViewportScroller; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_BROWSER_ID", function() { return PLATFORM_BROWSER_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_SERVER_ID", function() { return PLATFORM_SERVER_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_APP_ID", function() { return PLATFORM_WORKER_APP_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵPLATFORM_WORKER_UI_ID", function() { return PLATFORM_WORKER_UI_ID; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_a", function() { return useBrowserPlatformLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_b", function() { return createBrowserPlatformLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_c", function() { return createLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_d", function() { return provideLocationStrategy; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_e", function() { return COMMON_DIRECTIVES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵangular_packages_common_common_f", function() { return COMMON_PIPES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵgetDOM", function() { return getDOM; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵparseCookieValue", function() { return parseCookieValue; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ɵsetRootDomAdapter", function() { return setRootDomAdapter; });
/* harmony import */ var _angular_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/core */ "./node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js");
/**
* @license Angular v10.0.14
* (c) 2010-2020 Google LLC. https://angular.io/
* License: MIT
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
let _DOM = null;
function getDOM() {
return _DOM;
}
function setDOM(adapter) {
_DOM = adapter;
}
function setRootDomAdapter(adapter) {
if (!_DOM) {
_DOM = adapter;
}
}
/* tslint:disable:requireParameterType */
/**
* Provides DOM operations in an environment-agnostic way.
*
* @security Tread carefully! Interacting with the DOM directly is dangerous and
* can introduce XSS risks.
*/
class DomAdapter {
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A DI Token representing the main rendering context. In a browser this is the DOM Document.
*
* Note: Document might not be available in the Application Context when Application and Rendering
* Contexts are not the same (e.g. when running the application in a Web Worker).
*
* @publicApi
*/
const DOCUMENT = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('DocumentToken');
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*
* `PlatformLocation` encapsulates all calls to DOM APIs, which allows the Router to be
* platform-agnostic.
* This means that we can have different implementation of `PlatformLocation` for the different
* platforms that Angular supports. For example, `@angular/platform-browser` provides an
* implementation specific to the browser environment, while `@angular/platform-server` provides
* one suitable for use with server-side rendering.
*
* The `PlatformLocation` class is used directly by all implementations of {@link LocationStrategy}
* when they need to interact with the DOM APIs like pushState, popState, etc.
*
* {@link LocationStrategy} in turn is used by the {@link Location} service which is used directly
* by the {@link Router} in order to navigate between routes. Since all interactions between {@link
* Router} /
* {@link Location} / {@link LocationStrategy} and DOM APIs flow through the `PlatformLocation`
* class, they are all platform-agnostic.
*
* @publicApi
*/
class PlatformLocation {
}
PlatformLocation.ɵfac = function PlatformLocation_Factory(t) { return new (t || PlatformLocation)(); };
PlatformLocation.ɵprov = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: useBrowserPlatformLocation, token: PlatformLocation, providedIn: "platform" });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PlatformLocation, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"],
args: [{
providedIn: 'platform',
// See #23917
useFactory: useBrowserPlatformLocation
}]
}], null, null); })();
function useBrowserPlatformLocation() {
return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(BrowserPlatformLocation);
}
/**
* @description
* Indicates when a location is initialized.
*
* @publicApi
*/
const LOCATION_INITIALIZED = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('Location Initialized');
/**
* `PlatformLocation` encapsulates all of the direct calls to platform APIs.
* This class should not be used directly by an application developer. Instead, use
* {@link Location}.
*/
class BrowserPlatformLocation extends PlatformLocation {
constructor(_doc) {
super();
this._doc = _doc;
this._init();
}
// This is moved to its own method so that `MockPlatformLocationStrategy` can overwrite it
/** @internal */
_init() {
this.location = getDOM().getLocation();
this._history = getDOM().getHistory();
}
getBaseHrefFromDOM() {
return getDOM().getBaseHref(this._doc);
}
onPopState(fn) {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('popstate', fn, false);
}
onHashChange(fn) {
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false);
}
get href() {
return this.location.href;
}
get protocol() {
return this.location.protocol;
}
get hostname() {
return this.location.hostname;
}
get port() {
return this.location.port;
}
get pathname() {
return this.location.pathname;
}
get search() {
return this.location.search;
}
get hash() {
return this.location.hash;
}
set pathname(newPath) {
this.location.pathname = newPath;
}
pushState(state, title, url) {
if (supportsState()) {
this._history.pushState(state, title, url);
}
else {
this.location.hash = url;
}
}
replaceState(state, title, url) {
if (supportsState()) {
this._history.replaceState(state, title, url);
}
else {
this.location.hash = url;
}
}
forward() {
this._history.forward();
}
back() {
this._history.back();
}
getState() {
return this._history.state;
}
}
BrowserPlatformLocation.ɵfac = function BrowserPlatformLocation_Factory(t) { return new (t || BrowserPlatformLocation)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](DOCUMENT)); };
BrowserPlatformLocation.ɵprov = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: createBrowserPlatformLocation, token: BrowserPlatformLocation, providedIn: "platform" });
BrowserPlatformLocation.ctorParameters = () => [
{ type: undefined, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [DOCUMENT,] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](BrowserPlatformLocation, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"],
args: [{
providedIn: 'platform',
// See #23917
useFactory: createBrowserPlatformLocation
}]
}], function () { return [{ type: undefined, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [DOCUMENT]
}] }]; }, null); })();
function supportsState() {
return !!window.history.pushState;
}
function createBrowserPlatformLocation() {
return new BrowserPlatformLocation(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT));
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Joins two parts of a URL with a slash if needed.
*
* @param start URL string
* @param end URL string
*
*
* @returns The joined URL string.
*/
function joinWithSlash(start, end) {
if (start.length == 0) {
return end;
}
if (end.length == 0) {
return start;
}
let slashes = 0;
if (start.endsWith('/')) {
slashes++;
}
if (end.startsWith('/')) {
slashes++;
}
if (slashes == 2) {
return start + end.substring(1);
}
if (slashes == 1) {
return start + end;
}
return start + '/' + end;
}
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param url URL string.
*
* @returns The URL string, modified if needed.
*/
function stripTrailingSlash(url) {
const match = url.match(/#|\?|$/);
const pathEndIdx = match && match.index || url.length;
const droppedSlashIdx = pathEndIdx - (url[pathEndIdx - 1] === '/' ? 1 : 0);
return url.slice(0, droppedSlashIdx) + url.slice(pathEndIdx);
}
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param params String of URL parameters.
*
* @returns The normalized URL parameters string.
*/
function normalizeQueryParams(params) {
return params && params[0] !== '?' ? '?' + params : params;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Enables the `Location` service to read route state from the browser's URL.
* Angular provides two strategies:
* `HashLocationStrategy` and `PathLocationStrategy`.
*
* Applications should use the `Router` or `Location` services to
* interact with application route state.
*
* For instance, `HashLocationStrategy` produces URLs like
* http://example.com#/foo,
* and `PathLocationStrategy` produces
* http://example.com/foo as an equivalent URL.
*
* See these two classes for more.
*
* @publicApi
*/
class LocationStrategy {
}
LocationStrategy.ɵfac = function LocationStrategy_Factory(t) { return new (t || LocationStrategy)(); };
LocationStrategy.ɵprov = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: provideLocationStrategy, token: LocationStrategy, providedIn: "root" });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LocationStrategy, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"],
args: [{ providedIn: 'root', useFactory: provideLocationStrategy }]
}], null, null); })();
function provideLocationStrategy(platformLocation) {
// See #23917
const location = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT).location;
return new PathLocationStrategy(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(PlatformLocation), location && location.origin || '');
}
/**
* A predefined [DI token](guide/glossary#di-token) for the base href
* to be used with the `PathLocationStrategy`.
* The base href is the URL prefix that should be preserved when generating
* and recognizing URLs.
*
* @usageNotes
*
* The following example shows how to use this token to configure the root app injector
* with a base href value, so that the DI framework can supply the dependency anywhere in the app.
*
* ```typescript
* import {Component, NgModule} from '@angular/core';
* import {APP_BASE_HREF} from '@angular/common';
*
* @NgModule({
* providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]
* })
* class AppModule {}
* ```
*
* @publicApi
*/
const APP_BASE_HREF = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["InjectionToken"]('appBaseHref');
/**
* @description
* A {@link LocationStrategy} used to configure the {@link Location} service to
* represent its state in the
* [path](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax) of the
* browser's URL.
*
* If you're using `PathLocationStrategy`, you must provide a {@link APP_BASE_HREF}
* or add a `` element to the document.
*
* For instance, if you provide an `APP_BASE_HREF` of `'/my/app/'` and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`. To ensure all relative URIs resolve correctly,
* the `` and/or `APP_BASE_HREF` should end with a `/`.
*
* Similarly, if you add `` to the document and call
* `location.go('/foo')`, the browser's URL will become
* `example.com/my/app/foo`.
*
* Note that when using `PathLocationStrategy`, neither the query nor
* the fragment in the `` will be preserved, as outlined
* by the [RFC](https://tools.ietf.org/html/rfc3986#section-5.2.2).
*
* @usageNotes
*
* ### Example
*
* {@example common/location/ts/path_location_component.ts region='LocationComponent'}
*
* @publicApi
*/
class PathLocationStrategy extends LocationStrategy {
constructor(_platformLocation, href) {
super();
this._platformLocation = _platformLocation;
if (href == null) {
href = this._platformLocation.getBaseHrefFromDOM();
}
if (href == null) {
throw new Error(`No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.`);
}
this._baseHref = href;
}
onPopState(fn) {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}
getBaseHref() {
return this._baseHref;
}
prepareExternalUrl(internal) {
return joinWithSlash(this._baseHref, internal);
}
path(includeHash = false) {
const pathname = this._platformLocation.pathname + normalizeQueryParams(this._platformLocation.search);
const hash = this._platformLocation.hash;
return hash && includeHash ? `${pathname}${hash}` : pathname;
}
pushState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.pushState(state, title, externalUrl);
}
replaceState(state, title, url, queryParams) {
const externalUrl = this.prepareExternalUrl(url + normalizeQueryParams(queryParams));
this._platformLocation.replaceState(state, title, externalUrl);
}
forward() {
this._platformLocation.forward();
}
back() {
this._platformLocation.back();
}
}
PathLocationStrategy.ɵfac = function PathLocationStrategy_Factory(t) { return new (t || PathLocationStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PlatformLocation), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](APP_BASE_HREF, 8)); };
PathLocationStrategy.ɵprov = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: PathLocationStrategy, factory: PathLocationStrategy.ɵfac });
PathLocationStrategy.ctorParameters = () => [
{ type: PlatformLocation },
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PathLocationStrategy, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"]
}], function () { return [{ type: PlatformLocation }, { type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"]
}, {
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [APP_BASE_HREF]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @description
* A {@link LocationStrategy} used to configure the {@link Location} service to
* represent its state in the
* [hash fragment](https://en.wikipedia.org/wiki/Uniform_Resource_Locator#Syntax)
* of the browser's URL.
*
* For instance, if you call `location.go('/foo')`, the browser's URL will become
* `example.com#/foo`.
*
* @usageNotes
*
* ### Example
*
* {@example common/location/ts/hash_location_component.ts region='LocationComponent'}
*
* @publicApi
*/
class HashLocationStrategy extends LocationStrategy {
constructor(_platformLocation, _baseHref) {
super();
this._platformLocation = _platformLocation;
this._baseHref = '';
if (_baseHref != null) {
this._baseHref = _baseHref;
}
}
onPopState(fn) {
this._platformLocation.onPopState(fn);
this._platformLocation.onHashChange(fn);
}
getBaseHref() {
return this._baseHref;
}
path(includeHash = false) {
// the hash value is always prefixed with a `#`
// and if it is empty then it will stay empty
let path = this._platformLocation.hash;
if (path == null)
path = '#';
return path.length > 0 ? path.substring(1) : path;
}
prepareExternalUrl(internal) {
const url = joinWithSlash(this._baseHref, internal);
return url.length > 0 ? ('#' + url) : url;
}
pushState(state, title, path, queryParams) {
let url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams));
if (url.length == 0) {
url = this._platformLocation.pathname;
}
this._platformLocation.pushState(state, title, url);
}
replaceState(state, title, path, queryParams) {
let url = this.prepareExternalUrl(path + normalizeQueryParams(queryParams));
if (url.length == 0) {
url = this._platformLocation.pathname;
}
this._platformLocation.replaceState(state, title, url);
}
forward() {
this._platformLocation.forward();
}
back() {
this._platformLocation.back();
}
}
HashLocationStrategy.ɵfac = function HashLocationStrategy_Factory(t) { return new (t || HashLocationStrategy)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PlatformLocation), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](APP_BASE_HREF, 8)); };
HashLocationStrategy.ɵprov = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: HashLocationStrategy, factory: HashLocationStrategy.ɵfac });
HashLocationStrategy.ctorParameters = () => [
{ type: PlatformLocation },
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [APP_BASE_HREF,] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](HashLocationStrategy, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"]
}], function () { return [{ type: PlatformLocation }, { type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Optional"]
}, {
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [APP_BASE_HREF]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @description
*
* A service that applications can use to interact with a browser's URL.
*
* Depending on the `LocationStrategy` used, `Location` persists
* to the URL's path or the URL's hash segment.
*
* @usageNotes
*
* It's better to use the `Router#navigate` service to trigger route changes. Use
* `Location` only if you need to interact with or create normalized URLs outside of
* routing.
*
* `Location` is responsible for normalizing the URL against the application's base href.
* A normalized URL is absolute from the URL host, includes the application's base href, and has no
* trailing slash:
* - `/my/app/user/123` is normalized
* - `my/app/user/123` **is not** normalized
* - `/my/app/user/123/` **is not** normalized
*
* ### Example
*
*
*
* @publicApi
*/
class Location {
constructor(platformStrategy, platformLocation) {
/** @internal */
this._subject = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["EventEmitter"]();
/** @internal */
this._urlChangeListeners = [];
this._platformStrategy = platformStrategy;
const browserBaseHref = this._platformStrategy.getBaseHref();
this._platformLocation = platformLocation;
this._baseHref = stripTrailingSlash(_stripIndexHtml(browserBaseHref));
this._platformStrategy.onPopState((ev) => {
this._subject.emit({
'url': this.path(true),
'pop': true,
'state': ev.state,
'type': ev.type,
});
});
}
/**
* Normalizes the URL path for this location.
*
* @param includeHash True to include an anchor fragment in the path.
*
* @returns The normalized URL path.
*/
// TODO: vsavkin. Remove the boolean flag and always include hash once the deprecated router is
// removed.
path(includeHash = false) {
return this.normalize(this._platformStrategy.path(includeHash));
}
/**
* Reports the current state of the location history.
* @returns The current value of the `history.state` object.
*/
getState() {
return this._platformLocation.getState();
}
/**
* Normalizes the given path and compares to the current normalized path.
*
* @param path The given URL path.
* @param query Query parameters.
*
* @returns True if the given URL path is equal to the current normalized path, false
* otherwise.
*/
isCurrentPathEqualTo(path, query = '') {
return this.path() == this.normalize(path + normalizeQueryParams(query));
}
/**
* Normalizes a URL path by stripping any trailing slashes.
*
* @param url String representing a URL.
*
* @returns The normalized URL string.
*/
normalize(url) {
return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url)));
}
/**
* Normalizes an external URL path.
* If the given URL doesn't begin with a leading slash (`'/'`), adds one
* before normalizing. Adds a hash if `HashLocationStrategy` is
* in use, or the `APP_BASE_HREF` if the `PathLocationStrategy` is in use.
*
* @param url String representing a URL.
*
* @returns A normalized platform-specific URL.
*/
prepareExternalUrl(url) {
if (url && url[0] !== '/') {
url = '/' + url;
}
return this._platformStrategy.prepareExternalUrl(url);
}
// TODO: rename this method to pushState
/**
* Changes the browser's URL to a normalized version of a given URL, and pushes a
* new item onto the platform's history.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*
*/
go(path, query = '', state = null) {
this._platformStrategy.pushState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Changes the browser's URL to a normalized version of the given URL, and replaces
* the top item on the platform's history stack.
*
* @param path URL path to normalize.
* @param query Query parameters.
* @param state Location history state.
*/
replaceState(path, query = '', state = null) {
this._platformStrategy.replaceState(state, '', path, query);
this._notifyUrlChangeListeners(this.prepareExternalUrl(path + normalizeQueryParams(query)), state);
}
/**
* Navigates forward in the platform's history.
*/
forward() {
this._platformStrategy.forward();
}
/**
* Navigates back in the platform's history.
*/
back() {
this._platformStrategy.back();
}
/**
* Registers a URL change listener. Use to catch updates performed by the Angular
* framework that are not detectible through "popstate" or "hashchange" events.
*
* @param fn The change handler function, which take a URL and a location history state.
*/
onUrlChange(fn) {
this._urlChangeListeners.push(fn);
if (!this._urlChangeSubscription) {
this._urlChangeSubscription = this.subscribe(v => {
this._notifyUrlChangeListeners(v.url, v.state);
});
}
}
/** @internal */
_notifyUrlChangeListeners(url = '', state) {
this._urlChangeListeners.forEach(fn => fn(url, state));
}
/**
* Subscribes to the platform's `popState` events.
*
* @param value Event that is triggered when the state history changes.
* @param exception The exception to throw.
*
* @returns Subscribed events.
*/
subscribe(onNext, onThrow, onReturn) {
return this._subject.subscribe({ next: onNext, error: onThrow, complete: onReturn });
}
}
Location.ɵfac = function Location_Factory(t) { return new (t || Location)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](LocationStrategy), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](PlatformLocation)); };
/**
* Normalizes URL parameters by prepending with `?` if needed.
*
* @param params String of URL parameters.
*
* @returns The normalized URL parameters string.
*/
Location.normalizeQueryParams = normalizeQueryParams;
/**
* Joins two parts of a URL with a slash if needed.
*
* @param start URL string
* @param end URL string
*
*
* @returns The joined URL string.
*/
Location.joinWithSlash = joinWithSlash;
/**
* Removes a trailing slash from a URL string if needed.
* Looks for the first occurrence of either `#`, `?`, or the end of the
* line as `/` characters and removes the trailing slash if one exists.
*
* @param url URL string.
*
* @returns The URL string, modified if needed.
*/
Location.stripTrailingSlash = stripTrailingSlash;
Location.ɵprov = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({ factory: createLocation, token: Location, providedIn: "root" });
Location.ctorParameters = () => [
{ type: LocationStrategy },
{ type: PlatformLocation }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](Location, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"],
args: [{
providedIn: 'root',
// See #23917
useFactory: createLocation
}]
}], function () { return [{ type: LocationStrategy }, { type: PlatformLocation }]; }, null); })();
function createLocation() {
return new Location(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(LocationStrategy), Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(PlatformLocation));
}
function _stripBaseHref(baseHref, url) {
return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url;
}
function _stripIndexHtml(url) {
return url.replace(/\/index.html$/, '');
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/** @internal */
const CURRENCIES_EN = {
'ADP': [undefined, undefined, 0],
'AFN': [undefined, undefined, 0],
'ALL': [undefined, undefined, 0],
'AMD': [undefined, undefined, 2],
'AOA': [undefined, 'Kz'],
'ARS': [undefined, '$'],
'AUD': ['A$', '$'],
'BAM': [undefined, 'KM'],
'BBD': [undefined, '$'],
'BDT': [undefined, '৳'],
'BHD': [undefined, undefined, 3],
'BIF': [undefined, undefined, 0],
'BMD': [undefined, '$'],
'BND': [undefined, '$'],
'BOB': [undefined, 'Bs'],
'BRL': ['R$'],
'BSD': [undefined, '$'],
'BWP': [undefined, 'P'],
'BYN': [undefined, 'р.', 2],
'BYR': [undefined, undefined, 0],
'BZD': [undefined, '$'],
'CAD': ['CA$', '$', 2],
'CHF': [undefined, undefined, 2],
'CLF': [undefined, undefined, 4],
'CLP': [undefined, '$', 0],
'CNY': ['CN¥', '¥'],
'COP': [undefined, '$', 2],
'CRC': [undefined, '₡', 2],
'CUC': [undefined, '$'],
'CUP': [undefined, '$'],
'CZK': [undefined, 'Kč', 2],
'DJF': [undefined, undefined, 0],
'DKK': [undefined, 'kr', 2],
'DOP': [undefined, '$'],
'EGP': [undefined, 'E£'],
'ESP': [undefined, '₧', 0],
'EUR': ['€'],
'FJD': [undefined, '$'],
'FKP': [undefined, '£'],
'GBP': ['£'],
'GEL': [undefined, '₾'],
'GIP': [undefined, '£'],
'GNF': [undefined, 'FG', 0],
'GTQ': [undefined, 'Q'],
'GYD': [undefined, '$', 2],
'HKD': ['HK$', '$'],
'HNL': [undefined, 'L'],
'HRK': [undefined, 'kn'],
'HUF': [undefined, 'Ft', 2],
'IDR': [undefined, 'Rp', 2],
'ILS': ['₪'],
'INR': ['₹'],
'IQD': [undefined, undefined, 0],
'IRR': [undefined, undefined, 0],
'ISK': [undefined, 'kr', 0],
'ITL': [undefined, undefined, 0],
'JMD': [undefined, '$'],
'JOD': [undefined, undefined, 3],
'JPY': ['¥', undefined, 0],
'KHR': [undefined, '៛'],
'KMF': [undefined, 'CF', 0],
'KPW': [undefined, '₩', 0],
'KRW': ['₩', undefined, 0],
'KWD': [undefined, undefined, 3],
'KYD': [undefined, '$'],
'KZT': [undefined, '₸'],
'LAK': [undefined, '₭', 0],
'LBP': [undefined, 'L£', 0],
'LKR': [undefined, 'Rs'],
'LRD': [undefined, '$'],
'LTL': [undefined, 'Lt'],
'LUF': [undefined, undefined, 0],
'LVL': [undefined, 'Ls'],
'LYD': [undefined, undefined, 3],
'MGA': [undefined, 'Ar', 0],
'MGF': [undefined, undefined, 0],
'MMK': [undefined, 'K', 0],
'MNT': [undefined, '₮', 2],
'MRO': [undefined, undefined, 0],
'MUR': [undefined, 'Rs', 2],
'MXN': ['MX$', '$'],
'MYR': [undefined, 'RM'],
'NAD': [undefined, '$'],
'NGN': [undefined, '₦'],
'NIO': [undefined, 'C$'],
'NOK': [undefined, 'kr', 2],
'NPR': [undefined, 'Rs'],
'NZD': ['NZ$', '$'],
'OMR': [undefined, undefined, 3],
'PHP': [undefined, '₱'],
'PKR': [undefined, 'Rs', 2],
'PLN': [undefined, 'zł'],
'PYG': [undefined, '₲', 0],
'RON': [undefined, 'lei'],
'RSD': [undefined, undefined, 0],
'RUB': [undefined, '₽'],
'RUR': [undefined, 'р.'],
'RWF': [undefined, 'RF', 0],
'SBD': [undefined, '$'],
'SEK': [undefined, 'kr', 2],
'SGD': [undefined, '$'],
'SHP': [undefined, '£'],
'SLL': [undefined, undefined, 0],
'SOS': [undefined, undefined, 0],
'SRD': [undefined, '$'],
'SSP': [undefined, '£'],
'STD': [undefined, undefined, 0],
'STN': [undefined, 'Db'],
'SYP': [undefined, '£', 0],
'THB': [undefined, '฿'],
'TMM': [undefined, undefined, 0],
'TND': [undefined, undefined, 3],
'TOP': [undefined, 'T$'],
'TRL': [undefined, undefined, 0],
'TRY': [undefined, '₺'],
'TTD': [undefined, '$'],
'TWD': ['NT$', '$', 2],
'TZS': [undefined, undefined, 2],
'UAH': [undefined, '₴'],
'UGX': [undefined, undefined, 0],
'USD': ['$'],
'UYI': [undefined, undefined, 0],
'UYU': [undefined, '$'],
'UYW': [undefined, undefined, 4],
'UZS': [undefined, undefined, 2],
'VEF': [undefined, 'Bs', 2],
'VND': ['₫', undefined, 0],
'VUV': [undefined, undefined, 0],
'XAF': ['FCFA', undefined, 0],
'XCD': ['EC$', '$'],
'XOF': ['CFA', undefined, 0],
'XPF': ['CFPF', undefined, 0],
'XXX': ['¤'],
'YER': [undefined, undefined, 0],
'ZAR': [undefined, 'R'],
'ZMK': [undefined, undefined, 0],
'ZMW': [undefined, 'ZK'],
'ZWD': [undefined, undefined, 0]
};
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Format styles that can be used to represent numbers.
* @see `getLocaleNumberFormat()`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
var NumberFormatStyle;
(function (NumberFormatStyle) {
NumberFormatStyle[NumberFormatStyle["Decimal"] = 0] = "Decimal";
NumberFormatStyle[NumberFormatStyle["Percent"] = 1] = "Percent";
NumberFormatStyle[NumberFormatStyle["Currency"] = 2] = "Currency";
NumberFormatStyle[NumberFormatStyle["Scientific"] = 3] = "Scientific";
})(NumberFormatStyle || (NumberFormatStyle = {}));
/**
* Plurality cases used for translating plurals to different languages.
*
* @see `NgPlural`
* @see `NgPluralCase`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
var Plural;
(function (Plural) {
Plural[Plural["Zero"] = 0] = "Zero";
Plural[Plural["One"] = 1] = "One";
Plural[Plural["Two"] = 2] = "Two";
Plural[Plural["Few"] = 3] = "Few";
Plural[Plural["Many"] = 4] = "Many";
Plural[Plural["Other"] = 5] = "Other";
})(Plural || (Plural = {}));
/**
* Context-dependant translation forms for strings.
* Typically the standalone version is for the nominative form of the word,
* and the format version is used for the genitive case.
* @see [CLDR website](http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles)
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
var FormStyle;
(function (FormStyle) {
FormStyle[FormStyle["Format"] = 0] = "Format";
FormStyle[FormStyle["Standalone"] = 1] = "Standalone";
})(FormStyle || (FormStyle = {}));
/**
* String widths available for translations.
* The specific character widths are locale-specific.
* Examples are given for the word "Sunday" in English.
*
* @publicApi
*/
var TranslationWidth;
(function (TranslationWidth) {
/** 1 character for `en-US`. For example: 'S' */
TranslationWidth[TranslationWidth["Narrow"] = 0] = "Narrow";
/** 3 characters for `en-US`. For example: 'Sun' */
TranslationWidth[TranslationWidth["Abbreviated"] = 1] = "Abbreviated";
/** Full length for `en-US`. For example: "Sunday" */
TranslationWidth[TranslationWidth["Wide"] = 2] = "Wide";
/** 2 characters for `en-US`, For example: "Su" */
TranslationWidth[TranslationWidth["Short"] = 3] = "Short";
})(TranslationWidth || (TranslationWidth = {}));
/**
* String widths available for date-time formats.
* The specific character widths are locale-specific.
* Examples are given for `en-US`.
*
* @see `getLocaleDateFormat()`
* @see `getLocaleTimeFormat()``
* @see `getLocaleDateTimeFormat()`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* @publicApi
*/
var FormatWidth;
(function (FormatWidth) {
/**
* For `en-US`, 'M/d/yy, h:mm a'`
* (Example: `6/15/15, 9:03 AM`)
*/
FormatWidth[FormatWidth["Short"] = 0] = "Short";
/**
* For `en-US`, `'MMM d, y, h:mm:ss a'`
* (Example: `Jun 15, 2015, 9:03:01 AM`)
*/
FormatWidth[FormatWidth["Medium"] = 1] = "Medium";
/**
* For `en-US`, `'MMMM d, y, h:mm:ss a z'`
* (Example: `June 15, 2015 at 9:03:01 AM GMT+1`)
*/
FormatWidth[FormatWidth["Long"] = 2] = "Long";
/**
* For `en-US`, `'EEEE, MMMM d, y, h:mm:ss a zzzz'`
* (Example: `Monday, June 15, 2015 at 9:03:01 AM GMT+01:00`)
*/
FormatWidth[FormatWidth["Full"] = 3] = "Full";
})(FormatWidth || (FormatWidth = {}));
/**
* Symbols that can be used to replace placeholders in number patterns.
* Examples are based on `en-US` values.
*
* @see `getLocaleNumberSymbol()`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
var NumberSymbol;
(function (NumberSymbol) {
/**
* Decimal separator.
* For `en-US`, the dot character.
* Example : 2,345`.`67
*/
NumberSymbol[NumberSymbol["Decimal"] = 0] = "Decimal";
/**
* Grouping separator, typically for thousands.
* For `en-US`, the comma character.
* Example: 2`,`345.67
*/
NumberSymbol[NumberSymbol["Group"] = 1] = "Group";
/**
* List-item separator.
* Example: "one, two, and three"
*/
NumberSymbol[NumberSymbol["List"] = 2] = "List";
/**
* Sign for percentage (out of 100).
* Example: 23.4%
*/
NumberSymbol[NumberSymbol["PercentSign"] = 3] = "PercentSign";
/**
* Sign for positive numbers.
* Example: +23
*/
NumberSymbol[NumberSymbol["PlusSign"] = 4] = "PlusSign";
/**
* Sign for negative numbers.
* Example: -23
*/
NumberSymbol[NumberSymbol["MinusSign"] = 5] = "MinusSign";
/**
* Computer notation for exponential value (n times a power of 10).
* Example: 1.2E3
*/
NumberSymbol[NumberSymbol["Exponential"] = 6] = "Exponential";
/**
* Human-readable format of exponential.
* Example: 1.2x103
*/
NumberSymbol[NumberSymbol["SuperscriptingExponent"] = 7] = "SuperscriptingExponent";
/**
* Sign for permille (out of 1000).
* Example: 23.4‰
*/
NumberSymbol[NumberSymbol["PerMille"] = 8] = "PerMille";
/**
* Infinity, can be used with plus and minus.
* Example: ∞, +∞, -∞
*/
NumberSymbol[NumberSymbol["Infinity"] = 9] = "Infinity";
/**
* Not a number.
* Example: NaN
*/
NumberSymbol[NumberSymbol["NaN"] = 10] = "NaN";
/**
* Symbol used between time units.
* Example: 10:52
*/
NumberSymbol[NumberSymbol["TimeSeparator"] = 11] = "TimeSeparator";
/**
* Decimal separator for currency values (fallback to `Decimal`).
* Example: $2,345.67
*/
NumberSymbol[NumberSymbol["CurrencyDecimal"] = 12] = "CurrencyDecimal";
/**
* Group separator for currency values (fallback to `Group`).
* Example: $2,345.67
*/
NumberSymbol[NumberSymbol["CurrencyGroup"] = 13] = "CurrencyGroup";
})(NumberSymbol || (NumberSymbol = {}));
/**
* The value for each day of the week, based on the `en-US` locale
*
* @publicApi
*/
var WeekDay;
(function (WeekDay) {
WeekDay[WeekDay["Sunday"] = 0] = "Sunday";
WeekDay[WeekDay["Monday"] = 1] = "Monday";
WeekDay[WeekDay["Tuesday"] = 2] = "Tuesday";
WeekDay[WeekDay["Wednesday"] = 3] = "Wednesday";
WeekDay[WeekDay["Thursday"] = 4] = "Thursday";
WeekDay[WeekDay["Friday"] = 5] = "Friday";
WeekDay[WeekDay["Saturday"] = 6] = "Saturday";
})(WeekDay || (WeekDay = {}));
/**
* Retrieves the locale ID from the currently loaded locale.
* The loaded locale could be, for example, a global one rather than a regional one.
* @param locale A locale code, such as `fr-FR`.
* @returns The locale code. For example, `fr`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleId(locale) {
return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale)[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].LocaleId];
}
/**
* Retrieves day period strings for the given locale.
*
* @param locale A locale code for the locale format rules to use.
* @param formStyle The required grammatical form.
* @param width The required character width.
* @returns An array of localized period strings. For example, `[AM, PM]` for `en-US`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleDayPeriods(locale, formStyle, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const amPmData = [
data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DayPeriodsStandalone]
];
const amPm = getLastDefinedValue(amPmData, formStyle);
return getLastDefinedValue(amPm, width);
}
/**
* Retrieves days of the week for the given locale, using the Gregorian calendar.
*
* @param locale A locale code for the locale format rules to use.
* @param formStyle The required grammatical form.
* @param width The required character width.
* @returns An array of localized name strings.
* For example,`[Sunday, Monday, ... Saturday]` for `en-US`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleDayNames(locale, formStyle, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const daysData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DaysStandalone]];
const days = getLastDefinedValue(daysData, formStyle);
return getLastDefinedValue(days, width);
}
/**
* Retrieves months of the year for the given locale, using the Gregorian calendar.
*
* @param locale A locale code for the locale format rules to use.
* @param formStyle The required grammatical form.
* @param width The required character width.
* @returns An array of localized name strings.
* For example, `[January, February, ...]` for `en-US`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleMonthNames(locale, formStyle, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const monthsData = [data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsFormat], data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].MonthsStandalone]];
const months = getLastDefinedValue(monthsData, formStyle);
return getLastDefinedValue(months, width);
}
/**
* Retrieves Gregorian-calendar eras for the given locale.
* @param locale A locale code for the locale format rules to use.
* @param formStyle The required grammatical form.
* @param width The required character width.
* @returns An array of localized era strings.
* For example, `[AD, BC]` for `en-US`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleEraNames(locale, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const erasData = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Eras];
return getLastDefinedValue(erasData, width);
}
/**
* Retrieves the first day of the week for the given locale.
*
* @param locale A locale code for the locale format rules to use.
* @returns A day index number, using the 0-based week-day index for `en-US`
* (Sunday = 0, Monday = 1, ...).
* For example, for `fr-FR`, returns 1 to indicate that the first day is Monday.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleFirstDayOfWeek(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].FirstDayOfWeek];
}
/**
* Range of week days that are considered the week-end for the given locale.
*
* @param locale A locale code for the locale format rules to use.
* @returns The range of day values, `[startDay, endDay]`.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleWeekEndRange(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].WeekendRange];
}
/**
* Retrieves a localized date-value formating string.
*
* @param locale A locale code for the locale format rules to use.
* @param width The format type.
* @returns The localized formating string.
* @see `FormatWidth`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleDateFormat(locale, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateFormat], width);
}
/**
* Retrieves a localized time-value formatting string.
*
* @param locale A locale code for the locale format rules to use.
* @param width The format type.
* @returns The localized formatting string.
* @see `FormatWidth`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* @publicApi
*/
function getLocaleTimeFormat(locale, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return getLastDefinedValue(data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].TimeFormat], width);
}
/**
* Retrieves a localized date-time formatting string.
*
* @param locale A locale code for the locale format rules to use.
* @param width The format type.
* @returns The localized formatting string.
* @see `FormatWidth`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleDateTimeFormat(locale, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const dateTimeFormatData = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].DateTimeFormat];
return getLastDefinedValue(dateTimeFormatData, width);
}
/**
* Retrieves a localized number symbol that can be used to replace placeholders in number formats.
* @param locale The locale code.
* @param symbol The symbol to localize.
* @returns The character for the localized symbol.
* @see `NumberSymbol`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleNumberSymbol(locale, symbol) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
const res = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][symbol];
if (typeof res === 'undefined') {
if (symbol === NumberSymbol.CurrencyDecimal) {
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Decimal];
}
else if (symbol === NumberSymbol.CurrencyGroup) {
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberSymbols][NumberSymbol.Group];
}
}
return res;
}
/**
* Retrieves a number format for a given locale.
*
* Numbers are formatted using patterns, like `#,###.00`. For example, the pattern `#,###.00`
* when used to format the number 12345.678 could result in "12'345,678". That would happen if the
* grouping separator for your language is an apostrophe, and the decimal separator is a comma.
*
* Important: The characters `.` `,` `0` `#` (and others below) are special placeholders
* that stand for the decimal separator, and so on, and are NOT real characters.
* You must NOT "translate" the placeholders. For example, don't change `.` to `,` even though in
* your language the decimal point is written with a comma. The symbols should be replaced by the
* local equivalents, using the appropriate `NumberSymbol` for your language.
*
* Here are the special characters used in number patterns:
*
* | Symbol | Meaning |
* |--------|---------|
* | . | Replaced automatically by the character used for the decimal point. |
* | , | Replaced by the "grouping" (thousands) separator. |
* | 0 | Replaced by a digit (or zero if there aren't enough digits). |
* | # | Replaced by a digit (or nothing if there aren't enough). |
* | ¤ | Replaced by a currency symbol, such as $ or USD. |
* | % | Marks a percent format. The % symbol may change position, but must be retained. |
* | E | Marks a scientific format. The E symbol may change position, but must be retained. |
* | ' | Special characters used as literal characters are quoted with ASCII single quotes. |
*
* @param locale A locale code for the locale format rules to use.
* @param type The type of numeric value to be formatted (such as `Decimal` or `Currency`.)
* @returns The localized format string.
* @see `NumberFormatStyle`
* @see [CLDR website](http://cldr.unicode.org/translation/number-patterns)
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleNumberFormat(locale, type) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].NumberFormats][type];
}
/**
* Retrieves the symbol used to represent the currency for the main country
* corresponding to a given locale. For example, '$' for `en-US`.
*
* @param locale A locale code for the locale format rules to use.
* @returns The localized symbol character,
* or `null` if the main country cannot be determined.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleCurrencySymbol(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencySymbol] || null;
}
/**
* Retrieves the name of the currency for the main country corresponding
* to a given locale. For example, 'US Dollar' for `en-US`.
* @param locale A locale code for the locale format rules to use.
* @returns The currency name,
* or `null` if the main country cannot be determined.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleCurrencyName(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].CurrencyName] || null;
}
/**
* Retrieves the default currency code for the given locale.
*
* The default is defined as the first currency which is still in use.
*
* @param locale The code of the locale whose currency code we want.
* @returns The code of the default currency for the given locale.
*
* @publicApi
*/
function getLocaleCurrencyCode(locale) {
return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocaleCurrencyCode"])(locale);
}
/**
* Retrieves the currency values for a given locale.
* @param locale A locale code for the locale format rules to use.
* @returns The currency values.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*/
function getLocaleCurrencies(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Currencies];
}
/**
* @alias core/ɵgetLocalePluralCase
* @publicApi
*/
const getLocalePluralCase = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵgetLocalePluralCase"];
function checkFullData(data) {
if (!data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData]) {
throw new Error(`Missing extra locale data for the locale "${data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"]
.LocaleId]}". Use "registerLocaleData" to load new data. See the "I18n guide" on angular.io to know more.`);
}
}
/**
* Retrieves locale-specific rules used to determine which day period to use
* when more than one period is defined for a locale.
*
* There is a rule for each defined day period. The
* first rule is applied to the first day period and so on.
* Fall back to AM/PM when no rules are available.
*
* A rule can specify a period as time range, or as a single time value.
*
* This functionality is only available when you have loaded the full locale data.
* See the ["I18n guide"](guide/i18n#i18n-pipes).
*
* @param locale A locale code for the locale format rules to use.
* @returns The rules for the locale, a single time value or array of *from-time, to-time*,
* or null if no periods are available.
*
* @see `getLocaleExtraDayPeriods()`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleExtraDayPeriodRules(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
checkFullData(data);
const rules = data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][2 /* ExtraDayPeriodsRules */] || [];
return rules.map((rule) => {
if (typeof rule === 'string') {
return extractTime(rule);
}
return [extractTime(rule[0]), extractTime(rule[1])];
});
}
/**
* Retrieves locale-specific day periods, which indicate roughly how a day is broken up
* in different languages.
* For example, for `en-US`, periods are morning, noon, afternoon, evening, and midnight.
*
* This functionality is only available when you have loaded the full locale data.
* See the ["I18n guide"](guide/i18n#i18n-pipes).
*
* @param locale A locale code for the locale format rules to use.
* @param formStyle The required grammatical form.
* @param width The required character width.
* @returns The translated day-period strings.
* @see `getLocaleExtraDayPeriodRules()`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLocaleExtraDayPeriods(locale, formStyle, width) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
checkFullData(data);
const dayPeriodsData = [
data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][0 /* ExtraDayPeriodFormats */],
data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].ExtraData][1 /* ExtraDayPeriodStandalone */]
];
const dayPeriods = getLastDefinedValue(dayPeriodsData, formStyle) || [];
return getLastDefinedValue(dayPeriods, width) || [];
}
/**
* Retrieves the writing direction of a specified locale
* @param locale A locale code for the locale format rules to use.
* @publicApi
* @returns 'rtl' or 'ltr'
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*/
function getLocaleDirection(locale) {
const data = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵfindLocaleData"])(locale);
return data[_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵLocaleDataIndex"].Directionality];
}
/**
* Retrieves the first value that is defined in an array, going backwards from an index position.
*
* To avoid repeating the same data (as when the "format" and "standalone" forms are the same)
* add the first value to the locale data arrays, and add other values only if they are different.
*
* @param data The data array to retrieve from.
* @param index A 0-based index into the array to start from.
* @returns The value immediately before the given index position.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getLastDefinedValue(data, index) {
for (let i = index; i > -1; i--) {
if (typeof data[i] !== 'undefined') {
return data[i];
}
}
throw new Error('Locale data API: locale data undefined');
}
/**
* Extracts the hours and minutes from a string like "15:45"
*/
function extractTime(time) {
const [h, m] = time.split(':');
return { hours: +h, minutes: +m };
}
/**
* Retrieves the currency symbol for a given currency code.
*
* For example, for the default `en-US` locale, the code `USD` can
* be represented by the narrow symbol `$` or the wide symbol `US$`.
*
* @param code The currency code.
* @param format The format, `wide` or `narrow`.
* @param locale A locale code for the locale format rules to use.
*
* @returns The symbol, or the currency code if no symbol is available.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getCurrencySymbol(code, format, locale = 'en') {
const currency = getLocaleCurrencies(locale)[code] || CURRENCIES_EN[code] || [];
const symbolNarrow = currency[1 /* SymbolNarrow */];
if (format === 'narrow' && typeof symbolNarrow === 'string') {
return symbolNarrow;
}
return currency[0 /* Symbol */] || code;
}
// Most currencies have cents, that's why the default is 2
const DEFAULT_NB_OF_CURRENCY_DIGITS = 2;
/**
* Reports the number of decimal digits for a given currency.
* The value depends upon the presence of cents in that particular currency.
*
* @param code The currency code.
* @returns The number of decimal digits, typically 0 or 2.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function getNumberOfCurrencyDigits(code) {
let digits;
const currency = CURRENCIES_EN[code];
if (currency) {
digits = currency[2 /* NbOfDigits */];
}
return typeof digits === 'number' ? digits : DEFAULT_NB_OF_CURRENCY_DIGITS;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const ISO8601_DATE_REGEX = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
// 1 2 3 4 5 6 7 8 9 10 11
const NAMED_FORMATS = {};
const DATE_FORMATS_SPLIT = /((?:[^GyMLwWdEabBhHmsSzZO']+)|(?:'(?:[^']|'')*')|(?:G{1,5}|y{1,4}|M{1,5}|L{1,5}|w{1,2}|W{1}|d{1,2}|E{1,6}|a{1,5}|b{1,5}|B{1,5}|h{1,2}|H{1,2}|m{1,2}|s{1,2}|S{1,3}|z{1,4}|Z{1,5}|O{1,4}))([\s\S]*)/;
var ZoneWidth;
(function (ZoneWidth) {
ZoneWidth[ZoneWidth["Short"] = 0] = "Short";
ZoneWidth[ZoneWidth["ShortGMT"] = 1] = "ShortGMT";
ZoneWidth[ZoneWidth["Long"] = 2] = "Long";
ZoneWidth[ZoneWidth["Extended"] = 3] = "Extended";
})(ZoneWidth || (ZoneWidth = {}));
var DateType;
(function (DateType) {
DateType[DateType["FullYear"] = 0] = "FullYear";
DateType[DateType["Month"] = 1] = "Month";
DateType[DateType["Date"] = 2] = "Date";
DateType[DateType["Hours"] = 3] = "Hours";
DateType[DateType["Minutes"] = 4] = "Minutes";
DateType[DateType["Seconds"] = 5] = "Seconds";
DateType[DateType["FractionalSeconds"] = 6] = "FractionalSeconds";
DateType[DateType["Day"] = 7] = "Day";
})(DateType || (DateType = {}));
var TranslationType;
(function (TranslationType) {
TranslationType[TranslationType["DayPeriods"] = 0] = "DayPeriods";
TranslationType[TranslationType["Days"] = 1] = "Days";
TranslationType[TranslationType["Months"] = 2] = "Months";
TranslationType[TranslationType["Eras"] = 3] = "Eras";
})(TranslationType || (TranslationType = {}));
/**
* @ngModule CommonModule
* @description
*
* Formats a date according to locale rules.
*
* @param value The date to format, as a Date, or a number (milliseconds since UTC epoch)
* or an [ISO date-time string](https://www.w3.org/TR/NOTE-datetime).
* @param format The date-time components to include. See `DatePipe` for details.
* @param locale A locale code for the locale format rules to use.
* @param timezone The time zone. A time zone offset from GMT (such as `'+0430'`),
* or a standard UTC/GMT or continental US time zone abbreviation.
* If not specified, uses host system settings.
*
* @returns The formatted date string.
*
* @see `DatePipe`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function formatDate(value, format, locale, timezone) {
let date = toDate(value);
const namedFormat = getNamedFormat(locale, format);
format = namedFormat || format;
let parts = [];
let match;
while (format) {
match = DATE_FORMATS_SPLIT.exec(format);
if (match) {
parts = parts.concat(match.slice(1));
const part = parts.pop();
if (!part) {
break;
}
format = part;
}
else {
parts.push(format);
break;
}
}
let dateTimezoneOffset = date.getTimezoneOffset();
if (timezone) {
dateTimezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
date = convertTimezoneToLocal(date, timezone, true);
}
let text = '';
parts.forEach(value => {
const dateFormatter = getDateFormatter(value);
text += dateFormatter ?
dateFormatter(date, locale, dateTimezoneOffset) :
value === '\'\'' ? '\'' : value.replace(/(^'|'$)/g, '').replace(/''/g, '\'');
});
return text;
}
function getNamedFormat(locale, format) {
const localeId = getLocaleId(locale);
NAMED_FORMATS[localeId] = NAMED_FORMATS[localeId] || {};
if (NAMED_FORMATS[localeId][format]) {
return NAMED_FORMATS[localeId][format];
}
let formatValue = '';
switch (format) {
case 'shortDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Short);
break;
case 'mediumDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Medium);
break;
case 'longDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Long);
break;
case 'fullDate':
formatValue = getLocaleDateFormat(locale, FormatWidth.Full);
break;
case 'shortTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Short);
break;
case 'mediumTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Medium);
break;
case 'longTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Long);
break;
case 'fullTime':
formatValue = getLocaleTimeFormat(locale, FormatWidth.Full);
break;
case 'short':
const shortTime = getNamedFormat(locale, 'shortTime');
const shortDate = getNamedFormat(locale, 'shortDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Short), [shortTime, shortDate]);
break;
case 'medium':
const mediumTime = getNamedFormat(locale, 'mediumTime');
const mediumDate = getNamedFormat(locale, 'mediumDate');
formatValue = formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Medium), [mediumTime, mediumDate]);
break;
case 'long':
const longTime = getNamedFormat(locale, 'longTime');
const longDate = getNamedFormat(locale, 'longDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Long), [longTime, longDate]);
break;
case 'full':
const fullTime = getNamedFormat(locale, 'fullTime');
const fullDate = getNamedFormat(locale, 'fullDate');
formatValue =
formatDateTime(getLocaleDateTimeFormat(locale, FormatWidth.Full), [fullTime, fullDate]);
break;
}
if (formatValue) {
NAMED_FORMATS[localeId][format] = formatValue;
}
return formatValue;
}
function formatDateTime(str, opt_values) {
if (opt_values) {
str = str.replace(/\{([^}]+)}/g, function (match, key) {
return (opt_values != null && key in opt_values) ? opt_values[key] : match;
});
}
return str;
}
function padNumber(num, digits, minusSign = '-', trim, negWrap) {
let neg = '';
if (num < 0 || (negWrap && num <= 0)) {
if (negWrap) {
num = -num + 1;
}
else {
num = -num;
neg = minusSign;
}
}
let strNum = String(num);
while (strNum.length < digits) {
strNum = '0' + strNum;
}
if (trim) {
strNum = strNum.substr(strNum.length - digits);
}
return neg + strNum;
}
function formatFractionalSeconds(milliseconds, digits) {
const strMs = padNumber(milliseconds, 3);
return strMs.substr(0, digits);
}
/**
* Returns a date formatter that transforms a date into its locale digit representation
*/
function dateGetter(name, size, offset = 0, trim = false, negWrap = false) {
return function (date, locale) {
let part = getDatePart(name, date);
if (offset > 0 || part > -offset) {
part += offset;
}
if (name === DateType.Hours) {
if (part === 0 && offset === -12) {
part = 12;
}
}
else if (name === DateType.FractionalSeconds) {
return formatFractionalSeconds(part, size);
}
const localeMinus = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
return padNumber(part, size, localeMinus, trim, negWrap);
};
}
function getDatePart(part, date) {
switch (part) {
case DateType.FullYear:
return date.getFullYear();
case DateType.Month:
return date.getMonth();
case DateType.Date:
return date.getDate();
case DateType.Hours:
return date.getHours();
case DateType.Minutes:
return date.getMinutes();
case DateType.Seconds:
return date.getSeconds();
case DateType.FractionalSeconds:
return date.getMilliseconds();
case DateType.Day:
return date.getDay();
default:
throw new Error(`Unknown DateType value "${part}".`);
}
}
/**
* Returns a date formatter that transforms a date into its locale string representation
*/
function dateStrGetter(name, width, form = FormStyle.Format, extended = false) {
return function (date, locale) {
return getDateTranslation(date, locale, name, width, form, extended);
};
}
/**
* Returns the locale translation of a date for a given form, type and width
*/
function getDateTranslation(date, locale, name, width, form, extended) {
switch (name) {
case TranslationType.Months:
return getLocaleMonthNames(locale, form, width)[date.getMonth()];
case TranslationType.Days:
return getLocaleDayNames(locale, form, width)[date.getDay()];
case TranslationType.DayPeriods:
const currentHours = date.getHours();
const currentMinutes = date.getMinutes();
if (extended) {
const rules = getLocaleExtraDayPeriodRules(locale);
const dayPeriods = getLocaleExtraDayPeriods(locale, form, width);
const index = rules.findIndex(rule => {
if (Array.isArray(rule)) {
// morning, afternoon, evening, night
const [from, to] = rule;
const afterFrom = currentHours >= from.hours && currentMinutes >= from.minutes;
const beforeTo = (currentHours < to.hours ||
(currentHours === to.hours && currentMinutes < to.minutes));
// We must account for normal rules that span a period during the day (e.g. 6am-9am)
// where `from` is less (earlier) than `to`. But also rules that span midnight (e.g.
// 10pm - 5am) where `from` is greater (later!) than `to`.
//
// In the first case the current time must be BOTH after `from` AND before `to`
// (e.g. 8am is after 6am AND before 10am).
//
// In the second case the current time must be EITHER after `from` OR before `to`
// (e.g. 4am is before 5am but not after 10pm; and 11pm is not before 5am but it is
// after 10pm).
if (from.hours < to.hours) {
if (afterFrom && beforeTo) {
return true;
}
}
else if (afterFrom || beforeTo) {
return true;
}
}
else { // noon or midnight
if (rule.hours === currentHours && rule.minutes === currentMinutes) {
return true;
}
}
return false;
});
if (index !== -1) {
return dayPeriods[index];
}
}
// if no rules for the day periods, we use am/pm by default
return getLocaleDayPeriods(locale, form, width)[currentHours < 12 ? 0 : 1];
case TranslationType.Eras:
return getLocaleEraNames(locale, width)[date.getFullYear() <= 0 ? 0 : 1];
default:
// This default case is not needed by TypeScript compiler, as the switch is exhaustive.
// However Closure Compiler does not understand that and reports an error in typed mode.
// The `throw new Error` below works around the problem, and the unexpected: never variable
// makes sure tsc still checks this code is unreachable.
const unexpected = name;
throw new Error(`unexpected translation type ${unexpected}`);
}
}
/**
* Returns a date formatter that transforms a date and an offset into a timezone with ISO8601 or
* GMT format depending on the width (eg: short = +0430, short:GMT = GMT+4, long = GMT+04:30,
* extended = +04:30)
*/
function timeZoneGetter(width) {
return function (date, locale, offset) {
const zone = -1 * offset;
const minusSign = getLocaleNumberSymbol(locale, NumberSymbol.MinusSign);
const hours = zone > 0 ? Math.floor(zone / 60) : Math.ceil(zone / 60);
switch (width) {
case ZoneWidth.Short:
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.ShortGMT:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 1, minusSign);
case ZoneWidth.Long:
return 'GMT' + ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
case ZoneWidth.Extended:
if (offset === 0) {
return 'Z';
}
else {
return ((zone >= 0) ? '+' : '') + padNumber(hours, 2, minusSign) + ':' +
padNumber(Math.abs(zone % 60), 2, minusSign);
}
default:
throw new Error(`Unknown zone width "${width}"`);
}
};
}
const JANUARY = 0;
const THURSDAY = 4;
function getFirstThursdayOfYear(year) {
const firstDayOfYear = (new Date(year, JANUARY, 1)).getDay();
return new Date(year, 0, 1 + ((firstDayOfYear <= THURSDAY) ? THURSDAY : THURSDAY + 7) - firstDayOfYear);
}
function getThursdayThisWeek(datetime) {
return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate() + (THURSDAY - datetime.getDay()));
}
function weekGetter(size, monthBased = false) {
return function (date, locale) {
let result;
if (monthBased) {
const nbDaysBefore1stDayOfMonth = new Date(date.getFullYear(), date.getMonth(), 1).getDay() - 1;
const today = date.getDate();
result = 1 + Math.floor((today + nbDaysBefore1stDayOfMonth) / 7);
}
else {
const firstThurs = getFirstThursdayOfYear(date.getFullYear());
const thisThurs = getThursdayThisWeek(date);
const diff = thisThurs.getTime() - firstThurs.getTime();
result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
}
return padNumber(result, size, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
};
}
const DATE_FORMATS = {};
// Based on CLDR formats:
// See complete list: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
// See also explanations: http://cldr.unicode.org/translation/date-time
// TODO(ocombe): support all missing cldr formats: Y, U, Q, D, F, e, c, j, J, C, A, v, V, X, x
function getDateFormatter(format) {
if (DATE_FORMATS[format]) {
return DATE_FORMATS[format];
}
let formatter;
switch (format) {
// Era name (AD/BC)
case 'G':
case 'GG':
case 'GGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Abbreviated);
break;
case 'GGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Wide);
break;
case 'GGGGG':
formatter = dateStrGetter(TranslationType.Eras, TranslationWidth.Narrow);
break;
// 1 digit representation of the year, e.g. (AD 1 => 1, AD 199 => 199)
case 'y':
formatter = dateGetter(DateType.FullYear, 1, 0, false, true);
break;
// 2 digit representation of the year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yy':
formatter = dateGetter(DateType.FullYear, 2, 0, true, true);
break;
// 3 digit representation of the year, padded (000-999). (e.g. AD 2001 => 01, AD 2010 => 10)
case 'yyy':
formatter = dateGetter(DateType.FullYear, 3, 0, false, true);
break;
// 4 digit representation of the year (e.g. AD 1 => 0001, AD 2010 => 2010)
case 'yyyy':
formatter = dateGetter(DateType.FullYear, 4, 0, false, true);
break;
// Month of the year (1-12), numeric
case 'M':
case 'L':
formatter = dateGetter(DateType.Month, 1, 1);
break;
case 'MM':
case 'LL':
formatter = dateGetter(DateType.Month, 2, 1);
break;
// Month of the year (January, ...), string, format
case 'MMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated);
break;
case 'MMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Wide);
break;
case 'MMMMM':
formatter = dateStrGetter(TranslationType.Months, TranslationWidth.Narrow);
break;
// Month of the year (January, ...), string, standalone
case 'LLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Abbreviated, FormStyle.Standalone);
break;
case 'LLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Wide, FormStyle.Standalone);
break;
case 'LLLLL':
formatter =
dateStrGetter(TranslationType.Months, TranslationWidth.Narrow, FormStyle.Standalone);
break;
// Week of the year (1, ... 52)
case 'w':
formatter = weekGetter(1);
break;
case 'ww':
formatter = weekGetter(2);
break;
// Week of the month (1, ...)
case 'W':
formatter = weekGetter(1, true);
break;
// Day of the month (1-31)
case 'd':
formatter = dateGetter(DateType.Date, 1);
break;
case 'dd':
formatter = dateGetter(DateType.Date, 2);
break;
// Day of the Week
case 'E':
case 'EE':
case 'EEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Abbreviated);
break;
case 'EEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Wide);
break;
case 'EEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Narrow);
break;
case 'EEEEEE':
formatter = dateStrGetter(TranslationType.Days, TranslationWidth.Short);
break;
// Generic period of the day (am-pm)
case 'a':
case 'aa':
case 'aaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated);
break;
case 'aaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide);
break;
case 'aaaaa':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow);
break;
// Extended period of the day (midnight, at night, ...), standalone
case 'b':
case 'bb':
case 'bbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Standalone, true);
break;
case 'bbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Standalone, true);
break;
case 'bbbbb':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Standalone, true);
break;
// Extended period of the day (midnight, night, ...), standalone
case 'B':
case 'BB':
case 'BBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Abbreviated, FormStyle.Format, true);
break;
case 'BBBB':
formatter =
dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Wide, FormStyle.Format, true);
break;
case 'BBBBB':
formatter = dateStrGetter(TranslationType.DayPeriods, TranslationWidth.Narrow, FormStyle.Format, true);
break;
// Hour in AM/PM, (1-12)
case 'h':
formatter = dateGetter(DateType.Hours, 1, -12);
break;
case 'hh':
formatter = dateGetter(DateType.Hours, 2, -12);
break;
// Hour of the day (0-23)
case 'H':
formatter = dateGetter(DateType.Hours, 1);
break;
// Hour in day, padded (00-23)
case 'HH':
formatter = dateGetter(DateType.Hours, 2);
break;
// Minute of the hour (0-59)
case 'm':
formatter = dateGetter(DateType.Minutes, 1);
break;
case 'mm':
formatter = dateGetter(DateType.Minutes, 2);
break;
// Second of the minute (0-59)
case 's':
formatter = dateGetter(DateType.Seconds, 1);
break;
case 'ss':
formatter = dateGetter(DateType.Seconds, 2);
break;
// Fractional second
case 'S':
formatter = dateGetter(DateType.FractionalSeconds, 1);
break;
case 'SS':
formatter = dateGetter(DateType.FractionalSeconds, 2);
break;
case 'SSS':
formatter = dateGetter(DateType.FractionalSeconds, 3);
break;
// Timezone ISO8601 short format (-0430)
case 'Z':
case 'ZZ':
case 'ZZZ':
formatter = timeZoneGetter(ZoneWidth.Short);
break;
// Timezone ISO8601 extended format (-04:30)
case 'ZZZZZ':
formatter = timeZoneGetter(ZoneWidth.Extended);
break;
// Timezone GMT short format (GMT+4)
case 'O':
case 'OO':
case 'OOO':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'z':
case 'zz':
case 'zzz':
formatter = timeZoneGetter(ZoneWidth.ShortGMT);
break;
// Timezone GMT long format (GMT+0430)
case 'OOOO':
case 'ZZZZ':
// Should be location, but fallback to format O instead because we don't have the data yet
case 'zzzz':
formatter = timeZoneGetter(ZoneWidth.Long);
break;
default:
return null;
}
DATE_FORMATS[format] = formatter;
return formatter;
}
function timezoneToOffset(timezone, fallback) {
// Support: IE 9-11 only, Edge 13-15+
// IE/Edge do not "understand" colon (`:`) in timezone
timezone = timezone.replace(/:/g, '');
const requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
}
function addDateMinutes(date, minutes) {
date = new Date(date.getTime());
date.setMinutes(date.getMinutes() + minutes);
return date;
}
function convertTimezoneToLocal(date, timezone, reverse) {
const reverseValue = reverse ? -1 : 1;
const dateTimezoneOffset = date.getTimezoneOffset();
const timezoneOffset = timezoneToOffset(timezone, dateTimezoneOffset);
return addDateMinutes(date, reverseValue * (timezoneOffset - dateTimezoneOffset));
}
/**
* Converts a value to date.
*
* Supported input formats:
* - `Date`
* - number: timestamp
* - string: numeric (e.g. "1234"), ISO and date strings in a format supported by
* [Date.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
* Note: ISO strings without time return a date without timeoffset.
*
* Throws if unable to convert to a date.
*/
function toDate(value) {
if (isDate(value)) {
return value;
}
if (typeof value === 'number' && !isNaN(value)) {
return new Date(value);
}
if (typeof value === 'string') {
value = value.trim();
const parsedNb = parseFloat(value);
// any string that only contains numbers, like "1234" but not like "1234hello"
if (!isNaN(value - parsedNb)) {
return new Date(parsedNb);
}
if (/^(\d{4}-\d{1,2}-\d{1,2})$/.test(value)) {
/* For ISO Strings without time the day, month and year must be extracted from the ISO String
before Date creation to avoid time offset and errors in the new Date.
If we only replace '-' with ',' in the ISO String ("2015,01,01"), and try to create a new
date, some browsers (e.g. IE 9) will throw an invalid Date error.
If we leave the '-' ("2015-01-01") and try to create a new Date("2015-01-01") the timeoffset
is applied.
Note: ISO months are 0 for January, 1 for February, ... */
const [y, m, d] = value.split('-').map((val) => +val);
return new Date(y, m - 1, d);
}
let match;
if (match = value.match(ISO8601_DATE_REGEX)) {
return isoStringToDate(match);
}
}
const date = new Date(value);
if (!isDate(date)) {
throw new Error(`Unable to convert "${value}" into a date`);
}
return date;
}
/**
* Converts a date in ISO8601 to a Date.
* Used instead of `Date.parse` because of browser discrepancies.
*/
function isoStringToDate(match) {
const date = new Date(0);
let tzHour = 0;
let tzMin = 0;
// match[8] means that the string contains "Z" (UTC) or a timezone like "+01:00" or "+0100"
const dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear;
const timeSetter = match[8] ? date.setUTCHours : date.setHours;
// if there is a timezone defined like "+01:00" or "+0100"
if (match[9]) {
tzHour = Number(match[9] + match[10]);
tzMin = Number(match[9] + match[11]);
}
dateSetter.call(date, Number(match[1]), Number(match[2]) - 1, Number(match[3]));
const h = Number(match[4] || 0) - tzHour;
const m = Number(match[5] || 0) - tzMin;
const s = Number(match[6] || 0);
const ms = Math.round(parseFloat('0.' + (match[7] || 0)) * 1000);
timeSetter.call(date, h, m, s, ms);
return date;
}
function isDate(value) {
return value instanceof Date && !isNaN(value.valueOf());
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const NUMBER_FORMAT_REGEXP = /^(\d+)?\.((\d+)(-(\d+))?)?$/;
const MAX_DIGITS = 22;
const DECIMAL_SEP = '.';
const ZERO_CHAR = '0';
const PATTERN_SEP = ';';
const GROUP_SEP = ',';
const DIGIT_CHAR = '#';
const CURRENCY_CHAR = '¤';
const PERCENT_CHAR = '%';
/**
* Transforms a number to a locale string based on a style and a format.
*/
function formatNumberToLocaleString(value, pattern, locale, groupSymbol, decimalSymbol, digitsInfo, isPercent = false) {
let formattedText = '';
let isZero = false;
if (!isFinite(value)) {
formattedText = getLocaleNumberSymbol(locale, NumberSymbol.Infinity);
}
else {
let parsedNumber = parseNumber(value);
if (isPercent) {
parsedNumber = toPercent(parsedNumber);
}
let minInt = pattern.minInt;
let minFraction = pattern.minFrac;
let maxFraction = pattern.maxFrac;
if (digitsInfo) {
const parts = digitsInfo.match(NUMBER_FORMAT_REGEXP);
if (parts === null) {
throw new Error(`${digitsInfo} is not a valid digit info`);
}
const minIntPart = parts[1];
const minFractionPart = parts[3];
const maxFractionPart = parts[5];
if (minIntPart != null) {
minInt = parseIntAutoRadix(minIntPart);
}
if (minFractionPart != null) {
minFraction = parseIntAutoRadix(minFractionPart);
}
if (maxFractionPart != null) {
maxFraction = parseIntAutoRadix(maxFractionPart);
}
else if (minFractionPart != null && minFraction > maxFraction) {
maxFraction = minFraction;
}
}
roundNumber(parsedNumber, minFraction, maxFraction);
let digits = parsedNumber.digits;
let integerLen = parsedNumber.integerLen;
const exponent = parsedNumber.exponent;
let decimals = [];
isZero = digits.every(d => !d);
// pad zeros for small numbers
for (; integerLen < minInt; integerLen++) {
digits.unshift(0);
}
// pad zeros for small numbers
for (; integerLen < 0; integerLen++) {
digits.unshift(0);
}
// extract decimals digits
if (integerLen > 0) {
decimals = digits.splice(integerLen, digits.length);
}
else {
decimals = digits;
digits = [0];
}
// format the integer digits with grouping separators
const groups = [];
if (digits.length >= pattern.lgSize) {
groups.unshift(digits.splice(-pattern.lgSize, digits.length).join(''));
}
while (digits.length > pattern.gSize) {
groups.unshift(digits.splice(-pattern.gSize, digits.length).join(''));
}
if (digits.length) {
groups.unshift(digits.join(''));
}
formattedText = groups.join(getLocaleNumberSymbol(locale, groupSymbol));
// append the decimal digits
if (decimals.length) {
formattedText += getLocaleNumberSymbol(locale, decimalSymbol) + decimals.join('');
}
if (exponent) {
formattedText += getLocaleNumberSymbol(locale, NumberSymbol.Exponential) + '+' + exponent;
}
}
if (value < 0 && !isZero) {
formattedText = pattern.negPre + formattedText + pattern.negSuf;
}
else {
formattedText = pattern.posPre + formattedText + pattern.posSuf;
}
return formattedText;
}
/**
* @ngModule CommonModule
* @description
*
* Formats a number as currency using locale rules.
*
* @param value The number to format.
* @param locale A locale code for the locale format rules to use.
* @param currency A string containing the currency symbol or its name,
* such as "$" or "Canadian Dollar". Used in output string, but does not affect the operation
* of the function.
* @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)
* currency code, such as `USD` for the US dollar and `EUR` for the euro.
* Used to determine the number of digits in the decimal part.
* @param digitInfo Decimal representation options, specified by a string in the following format:
* `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.
*
* @returns The formatted currency value.
*
* @see `formatNumber()`
* @see `DecimalPipe`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function formatCurrency(value, locale, currency, currencyCode, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Currency);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
pattern.minFrac = getNumberOfCurrencyDigits(currencyCode);
pattern.maxFrac = pattern.minFrac;
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.CurrencyGroup, NumberSymbol.CurrencyDecimal, digitsInfo);
return res
.replace(CURRENCY_CHAR, currency)
// if we have 2 time the currency character, the second one is ignored
.replace(CURRENCY_CHAR, '')
// If there is a spacing between currency character and the value and
// the currency character is supressed by passing an empty string, the
// spacing character would remain as part of the string. Then we
// should remove it.
.trim();
}
/**
* @ngModule CommonModule
* @description
*
* Formats a number as a percentage according to locale rules.
*
* @param value The number to format.
* @param locale A locale code for the locale format rules to use.
* @param digitInfo Decimal representation options, specified by a string in the following format:
* `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.
*
* @returns The formatted percentage value.
*
* @see `formatNumber()`
* @see `DecimalPipe`
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
* @publicApi
*
*/
function formatPercent(value, locale, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Percent);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
const res = formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo, true);
return res.replace(new RegExp(PERCENT_CHAR, 'g'), getLocaleNumberSymbol(locale, NumberSymbol.PercentSign));
}
/**
* @ngModule CommonModule
* @description
*
* Formats a number as text, with group sizing, separator, and other
* parameters based on the locale.
*
* @param value The number to format.
* @param locale A locale code for the locale format rules to use.
* @param digitInfo Decimal representation options, specified by a string in the following format:
* `{minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}`. See `DecimalPipe` for more details.
*
* @returns The formatted text string.
* @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n)
*
* @publicApi
*/
function formatNumber(value, locale, digitsInfo) {
const format = getLocaleNumberFormat(locale, NumberFormatStyle.Decimal);
const pattern = parseNumberFormat(format, getLocaleNumberSymbol(locale, NumberSymbol.MinusSign));
return formatNumberToLocaleString(value, pattern, locale, NumberSymbol.Group, NumberSymbol.Decimal, digitsInfo);
}
function parseNumberFormat(format, minusSign = '-') {
const p = {
minInt: 1,
minFrac: 0,
maxFrac: 0,
posPre: '',
posSuf: '',
negPre: '',
negSuf: '',
gSize: 0,
lgSize: 0
};
const patternParts = format.split(PATTERN_SEP);
const positive = patternParts[0];
const negative = patternParts[1];
const positiveParts = positive.indexOf(DECIMAL_SEP) !== -1 ?
positive.split(DECIMAL_SEP) :
[
positive.substring(0, positive.lastIndexOf(ZERO_CHAR) + 1),
positive.substring(positive.lastIndexOf(ZERO_CHAR) + 1)
], integer = positiveParts[0], fraction = positiveParts[1] || '';
p.posPre = integer.substr(0, integer.indexOf(DIGIT_CHAR));
for (let i = 0; i < fraction.length; i++) {
const ch = fraction.charAt(i);
if (ch === ZERO_CHAR) {
p.minFrac = p.maxFrac = i + 1;
}
else if (ch === DIGIT_CHAR) {
p.maxFrac = i + 1;
}
else {
p.posSuf += ch;
}
}
const groups = integer.split(GROUP_SEP);
p.gSize = groups[1] ? groups[1].length : 0;
p.lgSize = (groups[2] || groups[1]) ? (groups[2] || groups[1]).length : 0;
if (negative) {
const trunkLen = positive.length - p.posPre.length - p.posSuf.length, pos = negative.indexOf(DIGIT_CHAR);
p.negPre = negative.substr(0, pos).replace(/'/g, '');
p.negSuf = negative.substr(pos + trunkLen).replace(/'/g, '');
}
else {
p.negPre = minusSign + p.posPre;
p.negSuf = p.posSuf;
}
return p;
}
// Transforms a parsed number into a percentage by multiplying it by 100
function toPercent(parsedNumber) {
// if the number is 0, don't do anything
if (parsedNumber.digits[0] === 0) {
return parsedNumber;
}
// Getting the current number of decimals
const fractionLen = parsedNumber.digits.length - parsedNumber.integerLen;
if (parsedNumber.exponent) {
parsedNumber.exponent += 2;
}
else {
if (fractionLen === 0) {
parsedNumber.digits.push(0, 0);
}
else if (fractionLen === 1) {
parsedNumber.digits.push(0);
}
parsedNumber.integerLen += 2;
}
return parsedNumber;
}
/**
* Parses a number.
* Significant bits of this parse algorithm came from https://github.com/MikeMcl/big.js/
*/
function parseNumber(num) {
let numStr = Math.abs(num) + '';
let exponent = 0, digits, integerLen;
let i, j, zeros;
// Decimal point?
if ((integerLen = numStr.indexOf(DECIMAL_SEP)) > -1) {
numStr = numStr.replace(DECIMAL_SEP, '');
}
// Exponential form?
if ((i = numStr.search(/e/i)) > 0) {
// Work out the exponent.
if (integerLen < 0)
integerLen = i;
integerLen += +numStr.slice(i + 1);
numStr = numStr.substring(0, i);
}
else if (integerLen < 0) {
// There was no decimal point or exponent so it is an integer.
integerLen = numStr.length;
}
// Count the number of leading zeros.
for (i = 0; numStr.charAt(i) === ZERO_CHAR; i++) { /* empty */
}
if (i === (zeros = numStr.length)) {
// The digits are all zero.
digits = [0];
integerLen = 1;
}
else {
// Count the number of trailing zeros
zeros--;
while (numStr.charAt(zeros) === ZERO_CHAR)
zeros--;
// Trailing zeros are insignificant so ignore them
integerLen -= i;
digits = [];
// Convert string to array of digits without leading/trailing zeros.
for (j = 0; i <= zeros; i++, j++) {
digits[j] = Number(numStr.charAt(i));
}
}
// If the number overflows the maximum allowed digits then use an exponent.
if (integerLen > MAX_DIGITS) {
digits = digits.splice(0, MAX_DIGITS - 1);
exponent = integerLen - 1;
integerLen = 1;
}
return { digits, exponent, integerLen };
}
/**
* Round the parsed number to the specified number of decimal places
* This function changes the parsedNumber in-place
*/
function roundNumber(parsedNumber, minFrac, maxFrac) {
if (minFrac > maxFrac) {
throw new Error(`The minimum number of digits after fraction (${minFrac}) is higher than the maximum (${maxFrac}).`);
}
let digits = parsedNumber.digits;
let fractionLen = digits.length - parsedNumber.integerLen;
const fractionSize = Math.min(Math.max(minFrac, fractionLen), maxFrac);
// The index of the digit to where rounding is to occur
let roundAt = fractionSize + parsedNumber.integerLen;
let digit = digits[roundAt];
if (roundAt > 0) {
// Drop fractional digits beyond `roundAt`
digits.splice(Math.max(parsedNumber.integerLen, roundAt));
// Set non-fractional digits beyond `roundAt` to 0
for (let j = roundAt; j < digits.length; j++) {
digits[j] = 0;
}
}
else {
// We rounded to zero so reset the parsedNumber
fractionLen = Math.max(0, fractionLen);
parsedNumber.integerLen = 1;
digits.length = Math.max(1, roundAt = fractionSize + 1);
digits[0] = 0;
for (let i = 1; i < roundAt; i++)
digits[i] = 0;
}
if (digit >= 5) {
if (roundAt - 1 < 0) {
for (let k = 0; k > roundAt; k--) {
digits.unshift(0);
parsedNumber.integerLen++;
}
digits.unshift(1);
parsedNumber.integerLen++;
}
else {
digits[roundAt - 1]++;
}
}
// Pad out with zeros to get the required fraction length
for (; fractionLen < Math.max(0, fractionSize); fractionLen++)
digits.push(0);
let dropTrailingZeros = fractionSize !== 0;
// Minimal length = nb of decimals required + current nb of integers
// Any number besides that is optional and can be removed if it's a trailing 0
const minLen = minFrac + parsedNumber.integerLen;
// Do any carrying, e.g. a digit was rounded up to 10
const carry = digits.reduceRight(function (carry, d, i, digits) {
d = d + carry;
digits[i] = d < 10 ? d : d - 10; // d % 10
if (dropTrailingZeros) {
// Do not keep meaningless fractional trailing zeros (e.g. 15.52000 --> 15.52)
if (digits[i] === 0 && i >= minLen) {
digits.pop();
}
else {
dropTrailingZeros = false;
}
}
return d >= 10 ? 1 : 0; // Math.floor(d / 10);
}, 0);
if (carry) {
digits.unshift(carry);
parsedNumber.integerLen++;
}
}
function parseIntAutoRadix(text) {
const result = parseInt(text);
if (isNaN(result)) {
throw new Error('Invalid integer literal when parsing ' + text);
}
return result;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @publicApi
*/
class NgLocalization {
}
/**
* Returns the plural category for a given value.
* - "=value" when the case exists,
* - the plural category otherwise
*/
function getPluralCategory(value, cases, ngLocalization, locale) {
let key = `=${value}`;
if (cases.indexOf(key) > -1) {
return key;
}
key = ngLocalization.getPluralCategory(value, locale);
if (cases.indexOf(key) > -1) {
return key;
}
if (cases.indexOf('other') > -1) {
return 'other';
}
throw new Error(`No plural message found for value "${value}"`);
}
/**
* Returns the plural case based on the locale
*
* @publicApi
*/
class NgLocaleLocalization extends NgLocalization {
constructor(locale) {
super();
this.locale = locale;
}
getPluralCategory(value, locale) {
const plural = getLocalePluralCase(locale || this.locale)(value);
switch (plural) {
case Plural.Zero:
return 'zero';
case Plural.One:
return 'one';
case Plural.Two:
return 'two';
case Plural.Few:
return 'few';
case Plural.Many:
return 'many';
default:
return 'other';
}
}
}
NgLocaleLocalization.ɵfac = function NgLocaleLocalization_Factory(t) { return new (t || NgLocaleLocalization)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"])); };
NgLocaleLocalization.ɵprov = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"]({ token: NgLocaleLocalization, factory: NgLocaleLocalization.ɵfac });
NgLocaleLocalization.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgLocaleLocalization, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Injectable"]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Register global data to be used internally by Angular. See the
* ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data.
*
* The signature registerLocaleData(data: any, extraData?: any) is deprecated since v5.1
*
* @publicApi
*/
function registerLocaleData(data, localeId, extraData) {
return Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵregisterLocaleData"])(data, localeId, extraData);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function parseCookieValue(cookieStr, name) {
name = encodeURIComponent(name);
for (const cookie of cookieStr.split(';')) {
const eqIndex = cookie.indexOf('=');
const [cookieName, cookieValue] = eqIndex == -1 ? [cookie, ''] : [cookie.slice(0, eqIndex), cookie.slice(eqIndex + 1)];
if (cookieName.trim() === name) {
return decodeURIComponent(cookieValue);
}
}
return null;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
*
* @usageNotes
* ```
* ...
*
* ...
*
* ...
*
* ...
*
* ...
* ```
*
* @description
*
* Adds and removes CSS classes on an HTML element.
*
* The CSS classes are updated as follows, depending on the type of the expression evaluation:
* - `string` - the CSS classes listed in the string (space delimited) are added,
* - `Array` - the CSS classes declared as Array elements are added,
* - `Object` - keys are CSS classes that get added when the expression given in the value
* evaluates to a truthy value, otherwise they are removed.
*
* @publicApi
*/
class NgClass {
constructor(_iterableDiffers, _keyValueDiffers, _ngEl, _renderer) {
this._iterableDiffers = _iterableDiffers;
this._keyValueDiffers = _keyValueDiffers;
this._ngEl = _ngEl;
this._renderer = _renderer;
this._iterableDiffer = null;
this._keyValueDiffer = null;
this._initialClasses = [];
this._rawClass = null;
}
set klass(value) {
this._removeClasses(this._initialClasses);
this._initialClasses = typeof value === 'string' ? value.split(/\s+/) : [];
this._applyClasses(this._initialClasses);
this._applyClasses(this._rawClass);
}
set ngClass(value) {
this._removeClasses(this._rawClass);
this._applyClasses(this._initialClasses);
this._iterableDiffer = null;
this._keyValueDiffer = null;
this._rawClass = typeof value === 'string' ? value.split(/\s+/) : value;
if (this._rawClass) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisListLikeIterable"])(this._rawClass)) {
this._iterableDiffer = this._iterableDiffers.find(this._rawClass).create();
}
else {
this._keyValueDiffer = this._keyValueDiffers.find(this._rawClass).create();
}
}
}
ngDoCheck() {
if (this._iterableDiffer) {
const iterableChanges = this._iterableDiffer.diff(this._rawClass);
if (iterableChanges) {
this._applyIterableChanges(iterableChanges);
}
}
else if (this._keyValueDiffer) {
const keyValueChanges = this._keyValueDiffer.diff(this._rawClass);
if (keyValueChanges) {
this._applyKeyValueChanges(keyValueChanges);
}
}
}
_applyKeyValueChanges(changes) {
changes.forEachAddedItem((record) => this._toggleClass(record.key, record.currentValue));
changes.forEachChangedItem((record) => this._toggleClass(record.key, record.currentValue));
changes.forEachRemovedItem((record) => {
if (record.previousValue) {
this._toggleClass(record.key, false);
}
});
}
_applyIterableChanges(changes) {
changes.forEachAddedItem((record) => {
if (typeof record.item === 'string') {
this._toggleClass(record.item, true);
}
else {
throw new Error(`NgClass can only toggle CSS classes expressed as strings, got ${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(record.item)}`);
}
});
changes.forEachRemovedItem((record) => this._toggleClass(record.item, false));
}
/**
* Applies a collection of CSS classes to the DOM element.
*
* For argument of type Set and Array CSS class names contained in those collections are always
* added.
* For argument of type Map CSS class name in the map's key is toggled based on the value (added
* for truthy and removed for falsy).
*/
_applyClasses(rawClassVal) {
if (rawClassVal) {
if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
rawClassVal.forEach((klass) => this._toggleClass(klass, true));
}
else {
Object.keys(rawClassVal).forEach(klass => this._toggleClass(klass, !!rawClassVal[klass]));
}
}
}
/**
* Removes a collection of CSS classes from the DOM element. This is mostly useful for cleanup
* purposes.
*/
_removeClasses(rawClassVal) {
if (rawClassVal) {
if (Array.isArray(rawClassVal) || rawClassVal instanceof Set) {
rawClassVal.forEach((klass) => this._toggleClass(klass, false));
}
else {
Object.keys(rawClassVal).forEach(klass => this._toggleClass(klass, false));
}
}
}
_toggleClass(klass, enabled) {
klass = klass.trim();
if (klass) {
klass.split(/\s+/g).forEach(klass => {
if (enabled) {
this._renderer.addClass(this._ngEl.nativeElement, klass);
}
else {
this._renderer.removeClass(this._ngEl.nativeElement, klass);
}
});
}
}
}
NgClass.ɵfac = function NgClass_Factory(t) { return new (t || NgClass)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"])); };
NgClass.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgClass, selectors: [["", "ngClass", ""]], inputs: { klass: ["class", "klass"], ngClass: "ngClass" } });
NgClass.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }
];
NgClass.propDecorators = {
klass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['class',] }],
ngClass: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngClass',] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgClass, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngClass]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }]; }, { klass: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"],
args: ['class']
}], ngClass: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"],
args: ['ngClass']
}] }); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Instantiates a single {@link Component} type and inserts its Host View into current View.
* `NgComponentOutlet` provides a declarative approach for dynamic component creation.
*
* `NgComponentOutlet` requires a component type, if a falsy value is set the view will clear and
* any existing component will get destroyed.
*
* @usageNotes
*
* ### Fine tune control
*
* You can control the component creation process by using the following optional attributes:
*
* * `ngComponentOutletInjector`: Optional custom {@link Injector} that will be used as parent for
* the Component. Defaults to the injector of the current view container.
*
* * `ngComponentOutletContent`: Optional list of projectable nodes to insert into the content
* section of the component, if exists.
*
* * `ngComponentOutletNgModuleFactory`: Optional module factory to allow dynamically loading other
* module, then load a component from that module.
*
* ### Syntax
*
* Simple
* ```
*
* ```
*
* Customized injector/content
* ```
*
*
* ```
*
* Customized ngModuleFactory
* ```
*
*
* ```
*
* ### A simple example
*
* {@example common/ngComponentOutlet/ts/module.ts region='SimpleExample'}
*
* A more complete example with additional options:
*
* {@example common/ngComponentOutlet/ts/module.ts region='CompleteExample'}
*
* @publicApi
* @ngModule CommonModule
*/
class NgComponentOutlet {
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
this._componentRef = null;
this._moduleRef = null;
}
ngOnChanges(changes) {
this._viewContainerRef.clear();
this._componentRef = null;
if (this.ngComponentOutlet) {
const elInjector = this.ngComponentOutletInjector || this._viewContainerRef.parentInjector;
if (changes['ngComponentOutletNgModuleFactory']) {
if (this._moduleRef)
this._moduleRef.destroy();
if (this.ngComponentOutletNgModuleFactory) {
const parentModule = elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModuleRef"]);
this._moduleRef = this.ngComponentOutletNgModuleFactory.create(parentModule.injector);
}
else {
this._moduleRef = null;
}
}
const componentFactoryResolver = this._moduleRef ? this._moduleRef.componentFactoryResolver :
elInjector.get(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ComponentFactoryResolver"]);
const componentFactory = componentFactoryResolver.resolveComponentFactory(this.ngComponentOutlet);
this._componentRef = this._viewContainerRef.createComponent(componentFactory, this._viewContainerRef.length, elInjector, this.ngComponentOutletContent);
}
}
ngOnDestroy() {
if (this._moduleRef)
this._moduleRef.destroy();
}
}
NgComponentOutlet.ɵfac = function NgComponentOutlet_Factory(t) { return new (t || NgComponentOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"])); };
NgComponentOutlet.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgComponentOutlet, selectors: [["", "ngComponentOutlet", ""]], inputs: { ngComponentOutlet: "ngComponentOutlet", ngComponentOutletInjector: "ngComponentOutletInjector", ngComponentOutletContent: "ngComponentOutletContent", ngComponentOutletNgModuleFactory: "ngComponentOutletNgModuleFactory" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] });
NgComponentOutlet.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }
];
NgComponentOutlet.propDecorators = {
ngComponentOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletInjector: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletContent: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngComponentOutletNgModuleFactory: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgComponentOutlet, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngComponentOutlet]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }]; }, { ngComponentOutlet: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngComponentOutletInjector: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngComponentOutletContent: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngComponentOutletNgModuleFactory: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @publicApi
*/
class NgForOfContext {
constructor($implicit, ngForOf, index, count) {
this.$implicit = $implicit;
this.ngForOf = ngForOf;
this.index = index;
this.count = count;
}
get first() {
return this.index === 0;
}
get last() {
return this.index === this.count - 1;
}
get even() {
return this.index % 2 === 0;
}
get odd() {
return !this.even;
}
}
/**
* A [structural directive](guide/structural-directives) that renders
* a template for each item in a collection.
* The directive is placed on an element, which becomes the parent
* of the cloned templates.
*
* The `ngForOf` directive is generally used in the
* [shorthand form](guide/structural-directives#the-asterisk--prefix) `*ngFor`.
* In this form, the template to be rendered for each iteration is the content
* of an anchor element containing the directive.
*
* The following example shows the shorthand syntax with some options,
* contained in an `
` element.
*
* ```
*
...
* ```
*
* The shorthand form expands into a long form that uses the `ngForOf` selector
* on an `` element.
* The content of the `` element is the `
` element that held the
* short-form directive.
*
* Here is the expanded version of the short-form example.
*
* ```
*
*
...
*
* ```
*
* Angular automatically expands the shorthand syntax as it compiles the template.
* The context for each embedded view is logically merged to the current component
* context according to its lexical position.
*
* When using the shorthand syntax, Angular allows only [one structural directive
* on an element](guide/structural-directives#one-structural-directive-per-host-element).
* If you want to iterate conditionally, for example,
* put the `*ngIf` on a container element that wraps the `*ngFor` element.
* For futher discussion, see
* [Structural Directives](guide/structural-directives#one-per-element).
*
* @usageNotes
*
* ### Local variables
*
* `NgForOf` provides exported values that can be aliased to local variables.
* For example:
*
* ```
*
* {{i}}/{{users.length}}. {{user}} default
*
* ```
*
* The following exported values can be aliased to local variables:
*
* - `$implicit: T`: The value of the individual items in the iterable (`ngForOf`).
* - `ngForOf: NgIterable`: The value of the iterable expression. Useful when the expression is
* more complex then a property access, for example when using the async pipe (`userStreams |
* async`).
* - `index: number`: The index of the current item in the iterable.
* - `count: number`: The length of the iterable.
* - `first: boolean`: True when the item is the first item in the iterable.
* - `last: boolean`: True when the item is the last item in the iterable.
* - `even: boolean`: True when the item has an even index in the iterable.
* - `odd: boolean`: True when the item has an odd index in the iterable.
*
* ### Change propagation
*
* When the contents of the iterator changes, `NgForOf` makes the corresponding changes to the DOM:
*
* * When an item is added, a new instance of the template is added to the DOM.
* * When an item is removed, its template instance is removed from the DOM.
* * When items are reordered, their respective templates are reordered in the DOM.
*
* Angular uses object identity to track insertions and deletions within the iterator and reproduce
* those changes in the DOM. This has important implications for animations and any stateful
* controls that are present, such as `` elements that accept user input. Inserted rows can
* be animated in, deleted rows can be animated out, and unchanged rows retain any unsaved state
* such as user input.
* For more on animations, see [Transitions and Triggers](guide/transition-and-triggers).
*
* The identities of elements in the iterator can change while the data does not.
* This can happen, for example, if the iterator is produced from an RPC to the server, and that
* RPC is re-run. Even if the data hasn't changed, the second response produces objects with
* different identities, and Angular must tear down the entire DOM and rebuild it (as if all old
* elements were deleted and all new elements inserted).
*
* To avoid this expensive operation, you can customize the default tracking algorithm.
* by supplying the `trackBy` option to `NgForOf`.
* `trackBy` takes a function that has two arguments: `index` and `item`.
* If `trackBy` is given, Angular tracks changes by the return value of the function.
*
* @see [Structural Directives](guide/structural-directives)
* @ngModule CommonModule
* @publicApi
*/
class NgForOf {
constructor(_viewContainer, _template, _differs) {
this._viewContainer = _viewContainer;
this._template = _template;
this._differs = _differs;
this._ngForOf = null;
this._ngForOfDirty = true;
this._differ = null;
}
/**
* The value of the iterable expression, which can be used as a
* [template input variable](guide/structural-directives#template-input-variable).
*/
set ngForOf(ngForOf) {
this._ngForOf = ngForOf;
this._ngForOfDirty = true;
}
/**
* A function that defines how to track changes for items in the iterable.
*
* When items are added, moved, or removed in the iterable,
* the directive must re-render the appropriate DOM nodes.
* To minimize churn in the DOM, only nodes that have changed
* are re-rendered.
*
* By default, the change detector assumes that
* the object instance identifies the node in the iterable.
* When this function is supplied, the directive uses
* the result of calling this function to identify the item node,
* rather than the identity of the object itself.
*
* The function receives two inputs,
* the iteration index and the associated node data.
*/
set ngForTrackBy(fn) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["isDevMode"])() && fn != null && typeof fn !== 'function') {
// TODO(vicb): use a log service once there is a public one available
if (console && console.warn) {
console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
`See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
}
}
this._trackByFn = fn;
}
get ngForTrackBy() {
return this._trackByFn;
}
/**
* A reference to the template that is stamped out for each item in the iterable.
* @see [template reference variable](guide/template-reference-variables)
*/
set ngForTemplate(value) {
// TODO(TS2.1): make TemplateRef>> once we move to TS v2.1
// The current type is too restrictive; a template that just uses index, for example,
// should be acceptable.
if (value) {
this._template = value;
}
}
/**
* Applies the changes when needed.
*/
ngDoCheck() {
if (this._ngForOfDirty) {
this._ngForOfDirty = false;
// React on ngForOf changes only once all inputs have been initialized
const value = this._ngForOf;
if (!this._differ && value) {
try {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
}
catch (_a) {
throw new Error(`Cannot find a differ supporting object '${value}' of type '${getTypeName(value)}'. NgFor only supports binding to Iterables such as Arrays.`);
}
}
}
if (this._differ) {
const changes = this._differ.diff(this._ngForOf);
if (changes)
this._applyChanges(changes);
}
}
_applyChanges(changes) {
const insertTuples = [];
changes.forEachOperation((item, adjustedPreviousIndex, currentIndex) => {
if (item.previousIndex == null) {
// NgForOf is never "null" or "undefined" here because the differ detected
// that a new item needs to be inserted from the iterable. This implies that
// there is an iterable value for "_ngForOf".
const view = this._viewContainer.createEmbeddedView(this._template, new NgForOfContext(null, this._ngForOf, -1, -1), currentIndex === null ? undefined : currentIndex);
const tuple = new RecordViewTuple(item, view);
insertTuples.push(tuple);
}
else if (currentIndex == null) {
this._viewContainer.remove(adjustedPreviousIndex === null ? undefined : adjustedPreviousIndex);
}
else if (adjustedPreviousIndex !== null) {
const view = this._viewContainer.get(adjustedPreviousIndex);
this._viewContainer.move(view, currentIndex);
const tuple = new RecordViewTuple(item, view);
insertTuples.push(tuple);
}
});
for (let i = 0; i < insertTuples.length; i++) {
this._perViewChange(insertTuples[i].view, insertTuples[i].record);
}
for (let i = 0, ilen = this._viewContainer.length; i < ilen; i++) {
const viewRef = this._viewContainer.get(i);
viewRef.context.index = i;
viewRef.context.count = ilen;
viewRef.context.ngForOf = this._ngForOf;
}
changes.forEachIdentityChange((record) => {
const viewRef = this._viewContainer.get(record.currentIndex);
viewRef.context.$implicit = record.item;
});
}
_perViewChange(view, record) {
view.context.$implicit = record.item;
}
/**
* Asserts the correct type of the context for the template that `NgForOf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgForOf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard(dir, ctx) {
return true;
}
}
NgForOf.ɵfac = function NgForOf_Factory(t) { return new (t || NgForOf)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"])); };
NgForOf.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgForOf, selectors: [["", "ngFor", "", "ngForOf", ""]], inputs: { ngForOf: "ngForOf", ngForTrackBy: "ngForTrackBy", ngForTemplate: "ngForTemplate" } });
NgForOf.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }
];
NgForOf.propDecorators = {
ngForOf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngForTrackBy: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngForTemplate: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgForOf, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngFor][ngForOf]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["IterableDiffers"] }]; }, { ngForOf: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngForTrackBy: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngForTemplate: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
class RecordViewTuple {
constructor(record, view) {
this.record = record;
this.view = view;
}
}
function getTypeName(type) {
return type['name'] || typeof type;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A structural directive that conditionally includes a template based on the value of
* an expression coerced to Boolean.
* When the expression evaluates to true, Angular renders the template
* provided in a `then` clause, and when false or null,
* Angular renders the template provided in an optional `else` clause. The default
* template for the `else` clause is blank.
*
* A [shorthand form](guide/structural-directives#the-asterisk--prefix) of the directive,
* `*ngIf="condition"`, is generally used, provided
* as an attribute of the anchor element for the inserted template.
* Angular expands this into a more explicit version, in which the anchor element
* is contained in an `` element.
*
* Simple form with shorthand syntax:
*
* ```
*
Content to render when condition is true.
* ```
*
* Simple form with expanded syntax:
*
* ```
*
Content to render when condition is
* true.
* ```
*
* Form with an "else" block:
*
* ```
*
Content to render when condition is true.
* Content to render when condition is false.
* ```
*
* Shorthand form with "then" and "else" blocks:
*
* ```
*
* Content to render when condition is true.
* Content to render when condition is false.
* ```
*
* Form with storing the value locally:
*
* ```
*
{{value}}
* Content to render when value is null.
* ```
*
* @usageNotes
*
* The `*ngIf` directive is most commonly used to conditionally show an inline template,
* as seen in the following example.
* The default `else` template is blank.
*
* {@example common/ngIf/ts/module.ts region='NgIfSimple'}
*
* ### Showing an alternative template using `else`
*
* To display a template when `expression` evaluates to false, use an `else` template
* binding as shown in the following example.
* The `else` binding points to an `` element labeled `#elseBlock`.
* The template can be defined anywhere in the component view, but is typically placed right after
* `ngIf` for readability.
*
* {@example common/ngIf/ts/module.ts region='NgIfElse'}
*
* ### Using an external `then` template
*
* In the previous example, the then-clause template is specified inline, as the content of the
* tag that contains the `ngIf` directive. You can also specify a template that is defined
* externally, by referencing a labeled `` element. When you do this, you can
* change which template to use at runtime, as shown in the following example.
*
* {@example common/ngIf/ts/module.ts region='NgIfThenElse'}
*
* ### Storing a conditional result in a variable
*
* You might want to show a set of properties from the same object. If you are waiting
* for asynchronous data, the object can be undefined.
* In this case, you can use `ngIf` and store the result of the condition in a local
* variable as shown in the the following example.
*
* {@example common/ngIf/ts/module.ts region='NgIfAs'}
*
* This code uses only one `AsyncPipe`, so only one subscription is created.
* The conditional statement stores the result of `userStream|async` in the local variable `user`.
* You can then bind the local `user` repeatedly.
*
* The conditional displays the data only if `userStream` returns a value,
* so you don't need to use the
* [safe-navigation-operator](guide/template-expression-operators#safe-navigation-operator) (`?.`)
* to guard against null values when accessing properties.
* You can display an alternative template while waiting for the data.
*
* ### Shorthand syntax
*
* The shorthand syntax `*ngIf` expands into two separate template specifications
* for the "then" and "else" clauses. For example, consider the following shorthand statement,
* that is meant to show a loading page while waiting for data to be loaded.
*
* ```
*
* ...
*
*
*
*
Loading...
*
* ```
*
* You can see that the "else" clause references the ``
* with the `#loading` label, and the template for the "then" clause
* is provided as the content of the anchor element.
*
* However, when Angular expands the shorthand syntax, it creates
* another `` tag, with `ngIf` and `ngIfElse` directives.
* The anchor element containing the template for the "then" clause becomes
* the content of this unlabeled `` tag.
*
* ```
*
*
* ...
*
*
*
*
*
Loading...
*
* ```
*
* The presence of the implicit template object has implications for the nesting of
* structural directives. For more on this subject, see
* [Structural Directives](https://angular.io/guide/structural-directives#one-per-element).
*
* @ngModule CommonModule
* @publicApi
*/
class NgIf {
constructor(_viewContainer, templateRef) {
this._viewContainer = _viewContainer;
this._context = new NgIfContext();
this._thenTemplateRef = null;
this._elseTemplateRef = null;
this._thenViewRef = null;
this._elseViewRef = null;
this._thenTemplateRef = templateRef;
}
/**
* The Boolean expression to evaluate as the condition for showing a template.
*/
set ngIf(condition) {
this._context.$implicit = this._context.ngIf = condition;
this._updateView();
}
/**
* A template to show if the condition expression evaluates to true.
*/
set ngIfThen(templateRef) {
assertTemplate('ngIfThen', templateRef);
this._thenTemplateRef = templateRef;
this._thenViewRef = null; // clear previous view if any.
this._updateView();
}
/**
* A template to show if the condition expression evaluates to false.
*/
set ngIfElse(templateRef) {
assertTemplate('ngIfElse', templateRef);
this._elseTemplateRef = templateRef;
this._elseViewRef = null; // clear previous view if any.
this._updateView();
}
_updateView() {
if (this._context.$implicit) {
if (!this._thenViewRef) {
this._viewContainer.clear();
this._elseViewRef = null;
if (this._thenTemplateRef) {
this._thenViewRef =
this._viewContainer.createEmbeddedView(this._thenTemplateRef, this._context);
}
}
}
else {
if (!this._elseViewRef) {
this._viewContainer.clear();
this._thenViewRef = null;
if (this._elseTemplateRef) {
this._elseViewRef =
this._viewContainer.createEmbeddedView(this._elseTemplateRef, this._context);
}
}
}
}
/**
* Asserts the correct type of the context for the template that `NgIf` will render.
*
* The presence of this method is a signal to the Ivy template type-check compiler that the
* `NgIf` structural directive renders its template with a specific context type.
*/
static ngTemplateContextGuard(dir, ctx) {
return true;
}
}
NgIf.ɵfac = function NgIf_Factory(t) { return new (t || NgIf)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"])); };
NgIf.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgIf, selectors: [["", "ngIf", ""]], inputs: { ngIf: "ngIf", ngIfThen: "ngIfThen", ngIfElse: "ngIfElse" } });
NgIf.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }
];
NgIf.propDecorators = {
ngIf: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngIfThen: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngIfElse: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgIf, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngIf]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }]; }, { ngIf: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngIfThen: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngIfElse: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @publicApi
*/
class NgIfContext {
constructor() {
this.$implicit = null;
this.ngIf = null;
}
}
function assertTemplate(property, templateRef) {
const isTemplateRefOrNull = !!(!templateRef || templateRef.createEmbeddedView);
if (!isTemplateRefOrNull) {
throw new Error(`${property} must be a TemplateRef, but received '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(templateRef)}'.`);
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class SwitchView {
constructor(_viewContainerRef, _templateRef) {
this._viewContainerRef = _viewContainerRef;
this._templateRef = _templateRef;
this._created = false;
}
create() {
this._created = true;
this._viewContainerRef.createEmbeddedView(this._templateRef);
}
destroy() {
this._created = false;
this._viewContainerRef.clear();
}
enforceState(created) {
if (created && !this._created) {
this.create();
}
else if (!created && this._created) {
this.destroy();
}
}
}
/**
* @ngModule CommonModule
*
* @description
* The `[ngSwitch]` directive on a container specifies an expression to match against.
* The expressions to match are provided by `ngSwitchCase` directives on views within the container.
* - Every view that matches is rendered.
* - If there are no matches, a view with the `ngSwitchDefault` directive is rendered.
* - Elements within the `[NgSwitch]` statement but outside of any `NgSwitchCase`
* or `ngSwitchDefault` directive are preserved at the location.
*
* @usageNotes
* Define a container element for the directive, and specify the switch expression
* to match against as an attribute:
*
* ```
*
* ```
*
* Within the container, `*ngSwitchCase` statements specify the match expressions
* as attributes. Include `*ngSwitchDefault` as the final case.
*
* ```
*
* ...
* ...
* ...
*
* ```
*
* ### Usage Examples
*
* The following example shows how to use more than one case to display the same view:
*
* ```
*
*
* ...
* ...
* ...
*
* ...
*
* ```
*
* The following example shows how cases can be nested:
* ```
*
* ...
* ...
* ...
*
*
*
*
*
* ...
*
* ```
*
* @publicApi
* @see `NgSwitchCase`
* @see `NgSwitchDefault`
* @see [Structural Directives](guide/structural-directives)
*
*/
class NgSwitch {
constructor() {
this._defaultUsed = false;
this._caseCount = 0;
this._lastCaseCheckIndex = 0;
this._lastCasesMatched = false;
}
set ngSwitch(newValue) {
this._ngSwitch = newValue;
if (this._caseCount === 0) {
this._updateDefaultCases(true);
}
}
/** @internal */
_addCase() {
return this._caseCount++;
}
/** @internal */
_addDefault(view) {
if (!this._defaultViews) {
this._defaultViews = [];
}
this._defaultViews.push(view);
}
/** @internal */
_matchCase(value) {
const matched = value == this._ngSwitch;
this._lastCasesMatched = this._lastCasesMatched || matched;
this._lastCaseCheckIndex++;
if (this._lastCaseCheckIndex === this._caseCount) {
this._updateDefaultCases(!this._lastCasesMatched);
this._lastCaseCheckIndex = 0;
this._lastCasesMatched = false;
}
return matched;
}
_updateDefaultCases(useDefault) {
if (this._defaultViews && useDefault !== this._defaultUsed) {
this._defaultUsed = useDefault;
for (let i = 0; i < this._defaultViews.length; i++) {
const defaultView = this._defaultViews[i];
defaultView.enforceState(useDefault);
}
}
}
}
NgSwitch.ɵfac = function NgSwitch_Factory(t) { return new (t || NgSwitch)(); };
NgSwitch.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgSwitch, selectors: [["", "ngSwitch", ""]], inputs: { ngSwitch: "ngSwitch" } });
NgSwitch.propDecorators = {
ngSwitch: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitch, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngSwitch]' }]
}], function () { return []; }, { ngSwitch: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @ngModule CommonModule
*
* @description
* Provides a switch case expression to match against an enclosing `ngSwitch` expression.
* When the expressions match, the given `NgSwitchCase` template is rendered.
* If multiple match expressions match the switch expression value, all of them are displayed.
*
* @usageNotes
*
* Within a switch container, `*ngSwitchCase` statements specify the match expressions
* as attributes. Include `*ngSwitchDefault` as the final case.
*
* ```
*
* ...
* ...
* ...
*
* ```
*
* Each switch-case statement contains an in-line HTML template or template reference
* that defines the subtree to be selected if the value of the match expression
* matches the value of the switch expression.
*
* Unlike JavaScript, which uses strict equality, Angular uses loose equality.
* This means that the empty string, `""` matches 0.
*
* @publicApi
* @see `NgSwitch`
* @see `NgSwitchDefault`
*
*/
class NgSwitchCase {
constructor(viewContainer, templateRef, ngSwitch) {
this.ngSwitch = ngSwitch;
ngSwitch._addCase();
this._view = new SwitchView(viewContainer, templateRef);
}
/**
* Performs case matching. For internal use only.
*/
ngDoCheck() {
this._view.enforceState(this.ngSwitch._matchCase(this.ngSwitchCase));
}
}
NgSwitchCase.ɵfac = function NgSwitchCase_Factory(t) { return new (t || NgSwitchCase)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgSwitch, 1)); };
NgSwitchCase.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgSwitchCase, selectors: [["", "ngSwitchCase", ""]], inputs: { ngSwitchCase: "ngSwitchCase" } });
NgSwitchCase.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
NgSwitchCase.propDecorators = {
ngSwitchCase: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchCase, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngSwitchCase]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, { type: NgSwitch, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"]
}] }]; }, { ngSwitchCase: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @ngModule CommonModule
*
* @description
*
* Creates a view that is rendered when no `NgSwitchCase` expressions
* match the `NgSwitch` expression.
* This statement should be the final case in an `NgSwitch`.
*
* @publicApi
* @see `NgSwitch`
* @see `NgSwitchCase`
*
*/
class NgSwitchDefault {
constructor(viewContainer, templateRef, ngSwitch) {
ngSwitch._addDefault(new SwitchView(viewContainer, templateRef));
}
}
NgSwitchDefault.ɵfac = function NgSwitchDefault_Factory(t) { return new (t || NgSwitchDefault)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgSwitch, 1)); };
NgSwitchDefault.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgSwitchDefault, selectors: [["", "ngSwitchDefault", ""]] });
NgSwitchDefault.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: NgSwitch, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgSwitchDefault, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngSwitchDefault]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, { type: NgSwitch, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
*
* @usageNotes
* ```
*
* there is nothing
* there is one
* there are a few
*
* ```
*
* @description
*
* Adds / removes DOM sub-trees based on a numeric value. Tailored for pluralization.
*
* Displays DOM sub-trees that match the switch expression value, or failing that, DOM sub-trees
* that match the switch expression's pluralization category.
*
* To use this directive you must provide a container element that sets the `[ngPlural]` attribute
* to a switch expression. Inner elements with a `[ngPluralCase]` will display based on their
* expression:
* - if `[ngPluralCase]` is set to a value starting with `=`, it will only display if the value
* matches the switch expression exactly,
* - otherwise, the view will be treated as a "category match", and will only display if exact
* value matches aren't found and the value maps to its category for the defined locale.
*
* See http://cldr.unicode.org/index/cldr-spec/plural-rules
*
* @publicApi
*/
class NgPlural {
constructor(_localization) {
this._localization = _localization;
this._caseViews = {};
}
set ngPlural(value) {
this._switchValue = value;
this._updateView();
}
addCase(value, switchView) {
this._caseViews[value] = switchView;
}
_updateView() {
this._clearViews();
const cases = Object.keys(this._caseViews);
const key = getPluralCategory(this._switchValue, cases, this._localization);
this._activateView(this._caseViews[key]);
}
_clearViews() {
if (this._activeView)
this._activeView.destroy();
}
_activateView(view) {
if (view) {
this._activeView = view;
this._activeView.create();
}
}
}
NgPlural.ɵfac = function NgPlural_Factory(t) { return new (t || NgPlural)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgLocalization)); };
NgPlural.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgPlural, selectors: [["", "ngPlural", ""]], inputs: { ngPlural: "ngPlural" } });
NgPlural.ctorParameters = () => [
{ type: NgLocalization }
];
NgPlural.propDecorators = {
ngPlural: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPlural, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngPlural]' }]
}], function () { return [{ type: NgLocalization }]; }, { ngPlural: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @ngModule CommonModule
*
* @description
*
* Creates a view that will be added/removed from the parent {@link NgPlural} when the
* given expression matches the plural expression according to CLDR rules.
*
* @usageNotes
* ```
*
* ...
* ...
*
*```
*
* See {@link NgPlural} for more details and example.
*
* @publicApi
*/
class NgPluralCase {
constructor(value, template, viewContainer, ngPlural) {
this.value = value;
const isANumber = !isNaN(Number(value));
ngPlural.addCase(isANumber ? `=${value}` : value, new SwitchView(viewContainer, template));
}
}
NgPluralCase.ɵfac = function NgPluralCase_Factory(t) { return new (t || NgPluralCase)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectAttribute"]('ngPluralCase'), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgPlural, 1)); };
NgPluralCase.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgPluralCase, selectors: [["", "ngPluralCase", ""]] });
NgPluralCase.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Attribute"], args: ['ngPluralCase',] }] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] },
{ type: NgPlural, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgPluralCase, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngPluralCase]' }]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Attribute"],
args: ['ngPluralCase']
}] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["TemplateRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }, { type: NgPlural, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Host"]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
*
* @usageNotes
*
* Set the font of the containing element to the result of an expression.
*
* ```
* ...
* ```
*
* Set the width of the containing element to a pixel value returned by an expression.
*
* ```
* ...
* ```
*
* Set a collection of style values using an expression that returns key-value pairs.
*
* ```
* ...
* ```
*
* @description
*
* An attribute directive that updates styles for the containing HTML element.
* Sets one or more style properties, specified as colon-separated key-value pairs.
* The key is a style name, with an optional `.` suffix
* (such as 'top.px', 'font-style.em').
* The value is an expression to be evaluated.
* The resulting non-null value, expressed in the given unit,
* is assigned to the given style property.
* If the result of evaluation is null, the corresponding style is removed.
*
* @publicApi
*/
class NgStyle {
constructor(_ngEl, _differs, _renderer) {
this._ngEl = _ngEl;
this._differs = _differs;
this._renderer = _renderer;
this._ngStyle = null;
this._differ = null;
}
set ngStyle(values) {
this._ngStyle = values;
if (!this._differ && values) {
this._differ = this._differs.find(values).create();
}
}
ngDoCheck() {
if (this._differ) {
const changes = this._differ.diff(this._ngStyle);
if (changes) {
this._applyChanges(changes);
}
}
}
_setStyle(nameAndUnit, value) {
const [name, unit] = nameAndUnit.split('.');
value = value != null && unit ? `${value}${unit}` : value;
if (value != null) {
this._renderer.setStyle(this._ngEl.nativeElement, name, value);
}
else {
this._renderer.removeStyle(this._ngEl.nativeElement, name);
}
}
_applyChanges(changes) {
changes.forEachRemovedItem((record) => this._setStyle(record.key, null));
changes.forEachAddedItem((record) => this._setStyle(record.key, record.currentValue));
changes.forEachChangedItem((record) => this._setStyle(record.key, record.currentValue));
}
}
NgStyle.ɵfac = function NgStyle_Factory(t) { return new (t || NgStyle)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"])); };
NgStyle.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgStyle, selectors: [["", "ngStyle", ""]], inputs: { ngStyle: "ngStyle" } });
NgStyle.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] },
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }
];
NgStyle.propDecorators = {
ngStyle: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"], args: ['ngStyle',] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgStyle, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngStyle]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ElementRef"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }, { type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Renderer2"] }]; }, { ngStyle: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"],
args: ['ngStyle']
}] }); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
*
* @description
*
* Inserts an embedded view from a prepared `TemplateRef`.
*
* You can attach a context object to the `EmbeddedViewRef` by setting `[ngTemplateOutletContext]`.
* `[ngTemplateOutletContext]` should be an object, the object's keys will be available for binding
* by the local template `let` declarations.
*
* @usageNotes
* ```
*
* ```
*
* Using the key `$implicit` in the context object will set its value as default.
*
* ### Example
*
* {@example common/ngTemplateOutlet/ts/module.ts region='NgTemplateOutlet'}
*
* @publicApi
*/
class NgTemplateOutlet {
constructor(_viewContainerRef) {
this._viewContainerRef = _viewContainerRef;
this._viewRef = null;
/**
* A context object to attach to the {@link EmbeddedViewRef}. This should be an
* object, the object's keys will be available for binding by the local template `let`
* declarations.
* Using the key `$implicit` in the context object will set its value as default.
*/
this.ngTemplateOutletContext = null;
/**
* A string defining the template reference and optionally the context object for the template.
*/
this.ngTemplateOutlet = null;
}
ngOnChanges(changes) {
const recreateView = this._shouldRecreateView(changes);
if (recreateView) {
const viewContainerRef = this._viewContainerRef;
if (this._viewRef) {
viewContainerRef.remove(viewContainerRef.indexOf(this._viewRef));
}
this._viewRef = this.ngTemplateOutlet ?
viewContainerRef.createEmbeddedView(this.ngTemplateOutlet, this.ngTemplateOutletContext) :
null;
}
else if (this._viewRef && this.ngTemplateOutletContext) {
this._updateExistingContext(this.ngTemplateOutletContext);
}
}
/**
* We need to re-create existing embedded view if:
* - templateRef has changed
* - context has changes
*
* We mark context object as changed when the corresponding object
* shape changes (new properties are added or existing properties are removed).
* In other words we consider context with the same properties as "the same" even
* if object reference changes (see https://github.com/angular/angular/issues/13407).
*/
_shouldRecreateView(changes) {
const ctxChange = changes['ngTemplateOutletContext'];
return !!changes['ngTemplateOutlet'] || (ctxChange && this._hasContextShapeChanged(ctxChange));
}
_hasContextShapeChanged(ctxChange) {
const prevCtxKeys = Object.keys(ctxChange.previousValue || {});
const currCtxKeys = Object.keys(ctxChange.currentValue || {});
if (prevCtxKeys.length === currCtxKeys.length) {
for (let propName of currCtxKeys) {
if (prevCtxKeys.indexOf(propName) === -1) {
return true;
}
}
return false;
}
return true;
}
_updateExistingContext(ctx) {
for (let propName of Object.keys(ctx)) {
this._viewRef.context[propName] = this.ngTemplateOutletContext[propName];
}
}
}
NgTemplateOutlet.ɵfac = function NgTemplateOutlet_Factory(t) { return new (t || NgTemplateOutlet)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"])); };
NgTemplateOutlet.ɵdir = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineDirective"]({ type: NgTemplateOutlet, selectors: [["", "ngTemplateOutlet", ""]], inputs: { ngTemplateOutletContext: "ngTemplateOutletContext", ngTemplateOutlet: "ngTemplateOutlet" }, features: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵNgOnChangesFeature"]] });
NgTemplateOutlet.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }
];
NgTemplateOutlet.propDecorators = {
ngTemplateOutletContext: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }],
ngTemplateOutlet: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"] }]
};
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](NgTemplateOutlet, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Directive"],
args: [{ selector: '[ngTemplateOutlet]' }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ViewContainerRef"] }]; }, { ngTemplateOutletContext: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}], ngTemplateOutlet: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Input"]
}] }); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A collection of Angular directives that are likely to be used in each and every Angular
* application.
*/
const COMMON_DIRECTIVES = [
NgClass,
NgComponentOutlet,
NgForOf,
NgIf,
NgTemplateOutlet,
NgStyle,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgPlural,
NgPluralCase,
];
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function invalidPipeArgumentError(type, value) {
return Error(`InvalidPipeArgument: '${value}' for pipe '${Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵstringify"])(type)}'`);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class ObservableStrategy {
createSubscription(async, updateLatestValue) {
return async.subscribe({
next: updateLatestValue,
error: (e) => {
throw e;
}
});
}
dispose(subscription) {
subscription.unsubscribe();
}
onDestroy(subscription) {
subscription.unsubscribe();
}
}
class PromiseStrategy {
createSubscription(async, updateLatestValue) {
return async.then(updateLatestValue, e => {
throw e;
});
}
dispose(subscription) { }
onDestroy(subscription) { }
}
const _promiseStrategy = new PromiseStrategy();
const _observableStrategy = new ObservableStrategy();
/**
* @ngModule CommonModule
* @description
*
* Unwraps a value from an asynchronous primitive.
*
* The `async` pipe subscribes to an `Observable` or `Promise` and returns the latest value it has
* emitted. When a new value is emitted, the `async` pipe marks the component to be checked for
* changes. When the component gets destroyed, the `async` pipe unsubscribes automatically to avoid
* potential memory leaks.
*
* @usageNotes
*
* ### Examples
*
* This example binds a `Promise` to the view. Clicking the `Resolve` button resolves the
* promise.
*
* {@example common/pipes/ts/async_pipe.ts region='AsyncPipePromise'}
*
* It's also possible to use `async` with Observables. The example below binds the `time` Observable
* to the view. The Observable continuously updates the view with the current time.
*
* {@example common/pipes/ts/async_pipe.ts region='AsyncPipeObservable'}
*
* @publicApi
*/
class AsyncPipe {
constructor(_ref) {
this._ref = _ref;
this._latestValue = null;
this._subscription = null;
this._obj = null;
this._strategy = null;
}
ngOnDestroy() {
if (this._subscription) {
this._dispose();
}
}
transform(obj) {
if (!this._obj) {
if (obj) {
this._subscribe(obj);
}
return this._latestValue;
}
if (obj !== this._obj) {
this._dispose();
return this.transform(obj);
}
return this._latestValue;
}
_subscribe(obj) {
this._obj = obj;
this._strategy = this._selectStrategy(obj);
this._subscription = this._strategy.createSubscription(obj, (value) => this._updateLatestValue(obj, value));
}
_selectStrategy(obj) {
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisPromise"])(obj)) {
return _promiseStrategy;
}
if (Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵisObservable"])(obj)) {
return _observableStrategy;
}
throw invalidPipeArgumentError(AsyncPipe, obj);
}
_dispose() {
this._strategy.dispose(this._subscription);
this._latestValue = null;
this._subscription = null;
this._obj = null;
}
_updateLatestValue(async, value) {
if (async === this._obj) {
this._latestValue = value;
this._ref.markForCheck();
}
}
}
AsyncPipe.ɵfac = function AsyncPipe_Factory(t) { return new (t || AsyncPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinjectPipeChangeDetectorRef"]()); };
AsyncPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "async", type: AsyncPipe, pure: false });
AsyncPipe.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](AsyncPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'async', pure: false }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["ChangeDetectorRef"] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Transforms text to all lower case.
*
* @see `UpperCasePipe`
* @see `TitleCasePipe`
* @usageNotes
*
* The following example defines a view that allows the user to enter
* text, and then uses the pipe to convert the input text to all lower case.
*
*
*
* @ngModule CommonModule
* @publicApi
*/
class LowerCasePipe {
/**
* @param value The string to transform to lower case.
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(LowerCasePipe, value);
}
return value.toLowerCase();
}
}
LowerCasePipe.ɵfac = function LowerCasePipe_Factory(t) { return new (t || LowerCasePipe)(); };
LowerCasePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "lowercase", type: LowerCasePipe, pure: true });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](LowerCasePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'lowercase' }]
}], null, null); })();
//
// Regex below matches any Unicode word and compatible with ES5. In ES2018 the same result
// can be achieved by using /\p{L}\S*/gu and also known as Unicode Property Escapes
// (http://2ality.com/2017/07/regexp-unicode-property-escapes.html). Since there is no
// transpilation of this functionality down to ES5 without external tool, the only solution is
// to use already transpiled form. Example can be found here -
// https://mothereff.in/regexpu#input=var+regex+%3D+/%5Cp%7BL%7D/u%3B&unicodePropertyEscape=1
//
const unicodeWordMatch = /(?:[A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF40\uDF42-\uDF49\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D])\S*/g;
/**
* Transforms text to title case.
* Capitalizes the first letter of each word and transforms the
* rest of the word to lower case.
* Words are delimited by any whitespace character, such as a space, tab, or line-feed character.
*
* @see `LowerCasePipe`
* @see `UpperCasePipe`
*
* @usageNotes
* The following example shows the result of transforming various strings into title case.
*
*
*
* @ngModule CommonModule
* @publicApi
*/
class TitleCasePipe {
/**
* @param value The string to transform to title case.
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(TitleCasePipe, value);
}
return value.replace(unicodeWordMatch, (txt => txt[0].toUpperCase() + txt.substr(1).toLowerCase()));
}
}
TitleCasePipe.ɵfac = function TitleCasePipe_Factory(t) { return new (t || TitleCasePipe)(); };
TitleCasePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "titlecase", type: TitleCasePipe, pure: true });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](TitleCasePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'titlecase' }]
}], null, null); })();
/**
* Transforms text to all upper case.
* @see `LowerCasePipe`
* @see `TitleCasePipe`
*
* @ngModule CommonModule
* @publicApi
*/
class UpperCasePipe {
/**
* @param value The string to transform to upper case.
*/
transform(value) {
if (!value)
return value;
if (typeof value !== 'string') {
throw invalidPipeArgumentError(UpperCasePipe, value);
}
return value.toUpperCase();
}
}
UpperCasePipe.ɵfac = function UpperCasePipe_Factory(t) { return new (t || UpperCasePipe)(); };
UpperCasePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "uppercase", type: UpperCasePipe, pure: true });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](UpperCasePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'uppercase' }]
}], null, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// clang-format off
/**
* @ngModule CommonModule
* @description
*
* Formats a date value according to locale rules.
*
* Only the `en-US` locale data comes with Angular. To localize dates
* in another language, you must import the corresponding locale data.
* See the [I18n guide](guide/i18n#i18n-pipes) for more information.
*
* @see `formatDate()`
*
*
* @usageNotes
*
* The result of this pipe is not reevaluated when the input is mutated. To avoid the need to
* reformat the date on every change-detection cycle, treat the date as an immutable object
* and change the reference when the pipe needs to run again.
*
* ### Pre-defined format options
*
* Examples are given in `en-US` locale.
*
* - `'short'`: equivalent to `'M/d/yy, h:mm a'` (`6/15/15, 9:03 AM`).
* - `'medium'`: equivalent to `'MMM d, y, h:mm:ss a'` (`Jun 15, 2015, 9:03:01 AM`).
* - `'long'`: equivalent to `'MMMM d, y, h:mm:ss a z'` (`June 15, 2015 at 9:03:01 AM
* GMT+1`).
* - `'full'`: equivalent to `'EEEE, MMMM d, y, h:mm:ss a zzzz'` (`Monday, June 15, 2015 at
* 9:03:01 AM GMT+01:00`).
* - `'shortDate'`: equivalent to `'M/d/yy'` (`6/15/15`).
* - `'mediumDate'`: equivalent to `'MMM d, y'` (`Jun 15, 2015`).
* - `'longDate'`: equivalent to `'MMMM d, y'` (`June 15, 2015`).
* - `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` (`Monday, June 15, 2015`).
* - `'shortTime'`: equivalent to `'h:mm a'` (`9:03 AM`).
* - `'mediumTime'`: equivalent to `'h:mm:ss a'` (`9:03:01 AM`).
* - `'longTime'`: equivalent to `'h:mm:ss a z'` (`9:03:01 AM GMT+1`).
* - `'fullTime'`: equivalent to `'h:mm:ss a zzzz'` (`9:03:01 AM GMT+01:00`).
*
* ### Custom format options
*
* You can construct a format string using symbols to specify the components
* of a date-time value, as described in the following table.
* Format details depend on the locale.
* Fields marked with (*) are only available in the extra data set for the given locale.
*
* | Field type | Format | Description | Example Value |
* |--------------------|-------------|---------------------------------------------------------------|------------------------------------------------------------|
* | Era | G, GG & GGG | Abbreviated | AD |
* | | GGGG | Wide | Anno Domini |
* | | GGGGG | Narrow | A |
* | Year | y | Numeric: minimum digits | 2, 20, 201, 2017, 20173 |
* | | yy | Numeric: 2 digits + zero padded | 02, 20, 01, 17, 73 |
* | | yyy | Numeric: 3 digits + zero padded | 002, 020, 201, 2017, 20173 |
* | | yyyy | Numeric: 4 digits or more + zero padded | 0002, 0020, 0201, 2017, 20173 |
* | Month | M | Numeric: 1 digit | 9, 12 |
* | | MM | Numeric: 2 digits + zero padded | 09, 12 |
* | | MMM | Abbreviated | Sep |
* | | MMMM | Wide | September |
* | | MMMMM | Narrow | S |
* | Month standalone | L | Numeric: 1 digit | 9, 12 |
* | | LL | Numeric: 2 digits + zero padded | 09, 12 |
* | | LLL | Abbreviated | Sep |
* | | LLLL | Wide | September |
* | | LLLLL | Narrow | S |
* | Week of year | w | Numeric: minimum digits | 1... 53 |
* | | ww | Numeric: 2 digits + zero padded | 01... 53 |
* | Week of month | W | Numeric: 1 digit | 1... 5 |
* | Day of month | d | Numeric: minimum digits | 1 |
* | | dd | Numeric: 2 digits + zero padded | 01 |
* | Week day | E, EE & EEE | Abbreviated | Tue |
* | | EEEE | Wide | Tuesday |
* | | EEEEE | Narrow | T |
* | | EEEEEE | Short | Tu |
* | Period | a, aa & aaa | Abbreviated | am/pm or AM/PM |
* | | aaaa | Wide (fallback to `a` when missing) | ante meridiem/post meridiem |
* | | aaaaa | Narrow | a/p |
* | Period* | B, BB & BBB | Abbreviated | mid. |
* | | BBBB | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |
* | | BBBBB | Narrow | md |
* | Period standalone* | b, bb & bbb | Abbreviated | mid. |
* | | bbbb | Wide | am, pm, midnight, noon, morning, afternoon, evening, night |
* | | bbbbb | Narrow | md |
* | Hour 1-12 | h | Numeric: minimum digits | 1, 12 |
* | | hh | Numeric: 2 digits + zero padded | 01, 12 |
* | Hour 0-23 | H | Numeric: minimum digits | 0, 23 |
* | | HH | Numeric: 2 digits + zero padded | 00, 23 |
* | Minute | m | Numeric: minimum digits | 8, 59 |
* | | mm | Numeric: 2 digits + zero padded | 08, 59 |
* | Second | s | Numeric: minimum digits | 0... 59 |
* | | ss | Numeric: 2 digits + zero padded | 00... 59 |
* | Fractional seconds | S | Numeric: 1 digit | 0... 9 |
* | | SS | Numeric: 2 digits + zero padded | 00... 99 |
* | | SSS | Numeric: 3 digits + zero padded (= milliseconds) | 000... 999 |
* | Zone | z, zz & zzz | Short specific non location format (fallback to O) | GMT-8 |
* | | zzzz | Long specific non location format (fallback to OOOO) | GMT-08:00 |
* | | Z, ZZ & ZZZ | ISO8601 basic format | -0800 |
* | | ZZZZ | Long localized GMT format | GMT-8:00 |
* | | ZZZZZ | ISO8601 extended format + Z indicator for offset 0 (= XXXXX) | -08:00 |
* | | O, OO & OOO | Short localized GMT format | GMT-8 |
* | | OOOO | Long localized GMT format | GMT-08:00 |
*
* Note that timezone correction is not applied to an ISO string that has no time component, such as "2016-09-19"
*
* ### Format examples
*
* These examples transform a date into various formats,
* assuming that `dateObj` is a JavaScript `Date` object for
* year: 2015, month: 6, day: 15, hour: 21, minute: 43, second: 11,
* given in the local time for the `en-US` locale.
*
* ```
* {{ dateObj | date }} // output is 'Jun 15, 2015'
* {{ dateObj | date:'medium' }} // output is 'Jun 15, 2015, 9:43:11 PM'
* {{ dateObj | date:'shortTime' }} // output is '9:43 PM'
* {{ dateObj | date:'mm:ss' }} // output is '43:11'
* ```
*
* ### Usage example
*
* The following component uses a date pipe to display the current date in different formats.
*
* ```
* @Component({
* selector: 'date-pipe',
* template: `
*
Today is {{today | date}}
*
Or if you prefer, {{today | date:'fullDate'}}
*
The time is {{today | date:'h:mm a z'}}
*
`
* })
* // Get the current date and time as a date-time value.
* export class DatePipeComponent {
* today: number = Date.now();
* }
* ```
*
* @publicApi
*/
// clang-format on
class DatePipe {
constructor(locale) {
this.locale = locale;
}
/**
* @param value The date expression: a `Date` object, a number
* (milliseconds since UTC epoch), or an ISO string (https://www.w3.org/TR/NOTE-datetime).
* @param format The date/time components to include, using predefined options or a
* custom format string.
* @param timezone A timezone offset (such as `'+0430'`), or a standard
* UTC/GMT or continental US timezone abbreviation.
* When not supplied, uses the end-user's local system timezone.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
* @returns A date string in the desired format.
*/
transform(value, format = 'mediumDate', timezone, locale) {
if (value == null || value === '' || value !== value)
return null;
try {
return formatDate(value, format, locale || this.locale, timezone);
}
catch (error) {
throw invalidPipeArgumentError(DatePipe, error.message);
}
}
}
DatePipe.ɵfac = function DatePipe_Factory(t) { return new (t || DatePipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"])); };
DatePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "date", type: DatePipe, pure: true });
DatePipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DatePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'date', pure: true }]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]]
}] }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const _INTERPOLATION_REGEXP = /#/g;
/**
* @ngModule CommonModule
* @description
*
* Maps a value to a string that pluralizes the value according to locale rules.
*
* @usageNotes
*
* ### Example
*
* {@example common/pipes/ts/i18n_pipe.ts region='I18nPluralPipeComponent'}
*
* @publicApi
*/
class I18nPluralPipe {
constructor(_localization) {
this._localization = _localization;
}
/**
* @param value the number to be formatted
* @param pluralMap an object that mimics the ICU format, see
* http://userguide.icu-project.org/formatparse/messages.
* @param locale a `string` defining the locale to use (uses the current {@link LOCALE_ID} by
* default).
*/
transform(value, pluralMap, locale) {
if (value == null)
return '';
if (typeof pluralMap !== 'object' || pluralMap === null) {
throw invalidPipeArgumentError(I18nPluralPipe, pluralMap);
}
const key = getPluralCategory(value, Object.keys(pluralMap), this._localization, locale);
return pluralMap[key].replace(_INTERPOLATION_REGEXP, value.toString());
}
}
I18nPluralPipe.ɵfac = function I18nPluralPipe_Factory(t) { return new (t || I18nPluralPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](NgLocalization)); };
I18nPluralPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "i18nPlural", type: I18nPluralPipe, pure: true });
I18nPluralPipe.ctorParameters = () => [
{ type: NgLocalization }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nPluralPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'i18nPlural', pure: true }]
}], function () { return [{ type: NgLocalization }]; }, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
* @description
*
* Generic selector that displays the string that matches the current value.
*
* If none of the keys of the `mapping` match the `value`, then the content
* of the `other` key is returned when present, otherwise an empty string is returned.
*
* @usageNotes
*
* ### Example
*
* {@example common/pipes/ts/i18n_pipe.ts region='I18nSelectPipeComponent'}
*
* @publicApi
*/
class I18nSelectPipe {
/**
* @param value a string to be internationalized.
* @param mapping an object that indicates the text that should be displayed
* for different values of the provided `value`.
*/
transform(value, mapping) {
if (value == null)
return '';
if (typeof mapping !== 'object' || typeof value !== 'string') {
throw invalidPipeArgumentError(I18nSelectPipe, mapping);
}
if (mapping.hasOwnProperty(value)) {
return mapping[value];
}
if (mapping.hasOwnProperty('other')) {
return mapping['other'];
}
return '';
}
}
I18nSelectPipe.ɵfac = function I18nSelectPipe_Factory(t) { return new (t || I18nSelectPipe)(); };
I18nSelectPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "i18nSelect", type: I18nSelectPipe, pure: true });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](I18nSelectPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'i18nSelect', pure: true }]
}], null, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
* @description
*
* Converts a value into its JSON-format representation. Useful for debugging.
*
* @usageNotes
*
* The following component uses a JSON pipe to convert an object
* to JSON format, and displays the string in both formats for comparison.
*
* {@example common/pipes/ts/json_pipe.ts region='JsonPipe'}
*
* @publicApi
*/
class JsonPipe {
/**
* @param value A value of any type to convert into a JSON-format string.
*/
transform(value) {
return JSON.stringify(value, null, 2);
}
}
JsonPipe.ɵfac = function JsonPipe_Factory(t) { return new (t || JsonPipe)(); };
JsonPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "json", type: JsonPipe, pure: false });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](JsonPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'json', pure: false }]
}], null, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function makeKeyValuePair(key, value) {
return { key: key, value: value };
}
/**
* @ngModule CommonModule
* @description
*
* Transforms Object or Map into an array of key value pairs.
*
* The output array will be ordered by keys.
* By default the comparator will be by Unicode point value.
* You can optionally pass a compareFn if your keys are complex types.
*
* @usageNotes
* ### Examples
*
* This examples show how an Object or a Map can be iterated by ngFor with the use of this keyvalue
* pipe.
*
* {@example common/pipes/ts/keyvalue_pipe.ts region='KeyValuePipe'}
*
* @publicApi
*/
class KeyValuePipe {
constructor(differs) {
this.differs = differs;
this.keyValues = [];
}
transform(input, compareFn = defaultComparator) {
if (!input || (!(input instanceof Map) && typeof input !== 'object')) {
return null;
}
if (!this.differ) {
// make a differ for whatever type we've been passed in
this.differ = this.differs.find(input).create();
}
const differChanges = this.differ.diff(input);
if (differChanges) {
this.keyValues = [];
differChanges.forEachItem((r) => {
this.keyValues.push(makeKeyValuePair(r.key, r.currentValue));
});
this.keyValues.sort(compareFn);
}
return this.keyValues;
}
}
KeyValuePipe.ɵfac = function KeyValuePipe_Factory(t) { return new (t || KeyValuePipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"])); };
KeyValuePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "keyvalue", type: KeyValuePipe, pure: false });
KeyValuePipe.ctorParameters = () => [
{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](KeyValuePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'keyvalue', pure: false }]
}], function () { return [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["KeyValueDiffers"] }]; }, null); })();
function defaultComparator(keyValueA, keyValueB) {
const a = keyValueA.key;
const b = keyValueB.key;
// if same exit with 0;
if (a === b)
return 0;
// make sure that undefined are at the end of the sort.
if (a === undefined)
return 1;
if (b === undefined)
return -1;
// make sure that nulls are at the end of the sort.
if (a === null)
return 1;
if (b === null)
return -1;
if (typeof a == 'string' && typeof b == 'string') {
return a < b ? -1 : 1;
}
if (typeof a == 'number' && typeof b == 'number') {
return a - b;
}
if (typeof a == 'boolean' && typeof b == 'boolean') {
return a < b ? -1 : 1;
}
// `a` and `b` are of different types. Compare their string values.
const aString = String(a);
const bString = String(b);
return aString == bString ? 0 : aString < bString ? -1 : 1;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
* @description
*
* Transforms a number into a string,
* formatted according to locale rules that determine group sizing and
* separator, decimal-point character, and other locale-specific
* configurations.
*
* If no parameters are specified, the function rounds off to the nearest value using this
* [rounding method](https://en.wikibooks.org/wiki/Arithmetic/Rounding).
* The behavior differs from that of the JavaScript ```Math.round()``` function.
* In the following case for example, the pipe rounds down where
* ```Math.round()``` rounds up:
*
* ```html
* -2.5 | number:'1.0-0'
* > -3
* Math.round(-2.5)
* > -2
* ```
*
* @see `formatNumber()`
*
* @usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
* ### Example
*
*
*
* @publicApi
*/
class DecimalPipe {
constructor(_locale) {
this._locale = _locale;
}
/**
* @param value The number to be formatted.
* @param digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `3`.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
*/
transform(value, digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
try {
const num = strToNumber(value);
return formatNumber(num, locale, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(DecimalPipe, error.message);
}
}
}
DecimalPipe.ɵfac = function DecimalPipe_Factory(t) { return new (t || DecimalPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"])); };
DecimalPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "number", type: DecimalPipe, pure: true });
DecimalPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](DecimalPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'number' }]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]]
}] }]; }, null); })();
/**
* @ngModule CommonModule
* @description
*
* Transforms a number to a percentage
* string, formatted according to locale rules that determine group sizing and
* separator, decimal-point character, and other locale-specific
* configurations.
*
* @see `formatPercent()`
*
* @usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
*
*
* @publicApi
*/
class PercentPipe {
constructor(_locale) {
this._locale = _locale;
}
/**
*
* @param value The number to be formatted as a percentage.
* @param digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `0`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `0`.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
*/
transform(value, digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
try {
const num = strToNumber(value);
return formatPercent(num, locale, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(PercentPipe, error.message);
}
}
}
PercentPipe.ɵfac = function PercentPipe_Factory(t) { return new (t || PercentPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"])); };
PercentPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "percent", type: PercentPipe, pure: true });
PercentPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](PercentPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'percent' }]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]]
}] }]; }, null); })();
/**
* @ngModule CommonModule
* @description
*
* Transforms a number to a currency string, formatted according to locale rules
* that determine group sizing and separator, decimal-point character,
* and other locale-specific configurations.
*
* {@a currency-code-deprecation}
*
*
* **Deprecation notice:**
*
* The default currency code is currently always `USD` but this is deprecated from v9.
*
* **In v11 the default currency code will be taken from the current locale identified by
* the `LOCAL_ID` token. See the [i18n guide](guide/i18n#setting-up-the-locale-of-your-app) for
* more information.**
*
* If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in
* your application `NgModule`:
*
* ```ts
* {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}
* ```
*
*
*
* @see `getCurrencySymbol()`
* @see `formatCurrency()`
*
* @usageNotes
* The following code shows how the pipe transforms numbers
* into text strings, according to various format specifications,
* where the caller's default locale is `en-US`.
*
*
*
* @publicApi
*/
class CurrencyPipe {
constructor(_locale, _defaultCurrencyCode = 'USD') {
this._locale = _locale;
this._defaultCurrencyCode = _defaultCurrencyCode;
}
/**
*
* @param value The number to be formatted as currency.
* @param currencyCode The [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code,
* such as `USD` for the US dollar and `EUR` for the euro. The default currency code can be
* configured using the `DEFAULT_CURRENCY_CODE` injection token.
* @param display The format for the currency indicator. One of the following:
* - `code`: Show the code (such as `USD`).
* - `symbol`(default): Show the symbol (such as `$`).
* - `symbol-narrow`: Use the narrow symbol for locales that have two symbols for their
* currency.
* For example, the Canadian dollar CAD has the symbol `CA$` and the symbol-narrow `$`. If the
* locale has no narrow symbol, uses the standard symbol for the locale.
* - String: Use the given string value instead of a code or a symbol.
* For example, an empty string will suppress the currency & symbol.
* - Boolean (marked deprecated in v5): `true` for symbol and false for `code`.
*
* @param digitsInfo Decimal representation options, specified by a string
* in the following format:
* {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits}.
* - `minIntegerDigits`: The minimum number of integer digits before the decimal point.
* Default is `1`.
* - `minFractionDigits`: The minimum number of digits after the decimal point.
* Default is `2`.
* - `maxFractionDigits`: The maximum number of digits after the decimal point.
* Default is `2`.
* If not provided, the number will be formatted with the proper amount of digits,
* depending on what the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) specifies.
* For example, the Canadian dollar has 2 digits, whereas the Chilean peso has none.
* @param locale A locale code for the locale format rules to use.
* When not supplied, uses the value of `LOCALE_ID`, which is `en-US` by default.
* See [Setting your app locale](guide/i18n#setting-up-the-locale-of-your-app).
*/
transform(value, currencyCode, display = 'symbol', digitsInfo, locale) {
if (isEmpty(value))
return null;
locale = locale || this._locale;
if (typeof display === 'boolean') {
if (console && console.warn) {
console.warn(`Warning: the currency pipe has been changed in Angular v5. The symbolDisplay option (third parameter) is now a string instead of a boolean. The accepted values are "code", "symbol" or "symbol-narrow".`);
}
display = display ? 'symbol' : 'code';
}
let currency = currencyCode || this._defaultCurrencyCode;
if (display !== 'code') {
if (display === 'symbol' || display === 'symbol-narrow') {
currency = getCurrencySymbol(currency, display === 'symbol' ? 'wide' : 'narrow', locale);
}
else {
currency = display;
}
}
try {
const num = strToNumber(value);
return formatCurrency(num, locale, currency, currencyCode, digitsInfo);
}
catch (error) {
throw invalidPipeArgumentError(CurrencyPipe, error.message);
}
}
}
CurrencyPipe.ɵfac = function CurrencyPipe_Factory(t) { return new (t || CurrencyPipe)(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]), _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdirectiveInject"](_angular_core__WEBPACK_IMPORTED_MODULE_0__["DEFAULT_CURRENCY_CODE"])); };
CurrencyPipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "currency", type: CurrencyPipe, pure: true });
CurrencyPipe.ctorParameters = () => [
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"],] }] },
{ type: String, decorators: [{ type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"], args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["DEFAULT_CURRENCY_CODE"],] }] }
];
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CurrencyPipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'currency' }]
}], function () { return [{ type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["LOCALE_ID"]]
}] }, { type: String, decorators: [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Inject"],
args: [_angular_core__WEBPACK_IMPORTED_MODULE_0__["DEFAULT_CURRENCY_CODE"]]
}] }]; }, null); })();
function isEmpty(value) {
return value == null || value === '' || value !== value;
}
/**
* Transforms a string into a number (if needed).
*/
function strToNumber(value) {
// Convert strings to numbers
if (typeof value === 'string' && !isNaN(Number(value) - parseFloat(value))) {
return Number(value);
}
if (typeof value !== 'number') {
throw new Error(`${value} is not a number`);
}
return value;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @ngModule CommonModule
* @description
*
* Creates a new `Array` or `String` containing a subset (slice) of the elements.
*
* @usageNotes
*
* All behavior is based on the expected behavior of the JavaScript API `Array.prototype.slice()`
* and `String.prototype.slice()`.
*
* When operating on an `Array`, the returned `Array` is always a copy even when all
* the elements are being returned.
*
* When operating on a blank value, the pipe returns the blank value.
*
* ### List Example
*
* This `ngFor` example:
*
* {@example common/pipes/ts/slice_pipe.ts region='SlicePipe_list'}
*
* produces the following:
*
* ```html
*
b
*
c
* ```
*
* ### String Examples
*
* {@example common/pipes/ts/slice_pipe.ts region='SlicePipe_string'}
*
* @publicApi
*/
class SlicePipe {
transform(value, start, end) {
if (value == null)
return value;
if (!this.supports(value)) {
throw invalidPipeArgumentError(SlicePipe, value);
}
return value.slice(start, end);
}
supports(obj) {
return typeof obj === 'string' || Array.isArray(obj);
}
}
SlicePipe.ɵfac = function SlicePipe_Factory(t) { return new (t || SlicePipe)(); };
SlicePipe.ɵpipe = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefinePipe"]({ name: "slice", type: SlicePipe, pure: false });
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](SlicePipe, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["Pipe"],
args: [{ name: 'slice', pure: false }]
}], null, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A collection of Angular pipes that are likely to be used in each and every application.
*/
const COMMON_PIPES = [
AsyncPipe,
UpperCasePipe,
LowerCasePipe,
JsonPipe,
SlicePipe,
DecimalPipe,
PercentPipe,
TitleCasePipe,
CurrencyPipe,
DatePipe,
I18nPluralPipe,
I18nSelectPipe,
KeyValuePipe,
];
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// Note: This does not contain the location providers,
// as they need some platform specific implementations to work.
/**
* Exports all the basic Angular directives and pipes,
* such as `NgIf`, `NgForOf`, `DecimalPipe`, and so on.
* Re-exported by `BrowserModule`, which is included automatically in the root
* `AppModule` when you create a new app with the CLI `new` command.
*
* * The `providers` options configure the NgModule's injector to provide
* localization dependencies to members.
* * The `exports` options make the declared directives and pipes available for import
* by other NgModules.
*
* @publicApi
*/
class CommonModule {
}
CommonModule.ɵmod = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineNgModule"]({ type: CommonModule });
CommonModule.ɵinj = _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjector"]({ factory: function CommonModule_Factory(t) { return new (t || CommonModule)(); }, providers: [
{ provide: NgLocalization, useClass: NgLocaleLocalization },
] });
(function () { (typeof ngJitMode === "undefined" || ngJitMode) && _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵsetNgModuleScope"](CommonModule, { declarations: [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase, AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe], exports: [NgClass, NgComponentOutlet, NgForOf, NgIf, NgTemplateOutlet, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgPlural, NgPluralCase, AsyncPipe, UpperCasePipe, LowerCasePipe, JsonPipe, SlicePipe, DecimalPipe, PercentPipe, TitleCasePipe, CurrencyPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, KeyValuePipe] }); })();
/*@__PURE__*/ (function () { _angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵsetClassMetadata"](CommonModule, [{
type: _angular_core__WEBPACK_IMPORTED_MODULE_0__["NgModule"],
args: [{
declarations: [COMMON_DIRECTIVES, COMMON_PIPES],
exports: [COMMON_DIRECTIVES, COMMON_PIPES],
providers: [
{ provide: NgLocalization, useClass: NgLocaleLocalization },
]
}]
}], null, null); })();
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const PLATFORM_BROWSER_ID = 'browser';
const PLATFORM_SERVER_ID = 'server';
const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
/**
* Returns whether a platform id represents a browser platform.
* @publicApi
*/
function isPlatformBrowser(platformId) {
return platformId === PLATFORM_BROWSER_ID;
}
/**
* Returns whether a platform id represents a server platform.
* @publicApi
*/
function isPlatformServer(platformId) {
return platformId === PLATFORM_SERVER_ID;
}
/**
* Returns whether a platform id represents a web worker app platform.
* @publicApi
*/
function isPlatformWorkerApp(platformId) {
return platformId === PLATFORM_WORKER_APP_ID;
}
/**
* Returns whether a platform id represents a web worker UI platform.
* @publicApi
*/
function isPlatformWorkerUi(platformId) {
return platformId === PLATFORM_WORKER_UI_ID;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @publicApi
*/
const VERSION = new _angular_core__WEBPACK_IMPORTED_MODULE_0__["Version"]('10.0.14');
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Defines a scroll position manager. Implemented by `BrowserViewportScroller`.
*
* @publicApi
*/
class ViewportScroller {
}
// De-sugared tree-shakable injection
// See #23917
/** @nocollapse */
ViewportScroller.ɵprov = Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵdefineInjectable"])({
token: ViewportScroller,
providedIn: 'root',
factory: () => new BrowserViewportScroller(Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(DOCUMENT), window, Object(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵinject"])(_angular_core__WEBPACK_IMPORTED_MODULE_0__["ErrorHandler"]))
});
/**
* Manages the scroll position for a browser window.
*/
class BrowserViewportScroller {
constructor(document, window, errorHandler) {
this.document = document;
this.window = window;
this.errorHandler = errorHandler;
this.offset = () => [0, 0];
}
/**
* Configures the top offset used when scrolling to an anchor.
* @param offset A position in screen coordinates (a tuple with x and y values)
* or a function that returns the top offset position.
*
*/
setOffset(offset) {
if (Array.isArray(offset)) {
this.offset = () => offset;
}
else {
this.offset = offset;
}
}
/**
* Retrieves the current scroll position.
* @returns The position in screen coordinates.
*/
getScrollPosition() {
if (this.supportsScrolling()) {
return [this.window.scrollX, this.window.scrollY];
}
else {
return [0, 0];
}
}
/**
* Sets the scroll position.
* @param position The new position in screen coordinates.
*/
scrollToPosition(position) {
if (this.supportsScrolling()) {
this.window.scrollTo(position[0], position[1]);
}
}
/**
* Scrolls to an anchor element.
* @param anchor The ID of the anchor element.
*/
scrollToAnchor(anchor) {
if (this.supportsScrolling()) {
const elSelected = this.document.getElementById(anchor) || this.document.getElementsByName(anchor)[0];
if (elSelected) {
this.scrollToElement(elSelected);
}
}
}
/**
* Disables automatic scroll restoration provided by the browser.
*/
setHistoryScrollRestoration(scrollRestoration) {
if (this.supportScrollRestoration()) {
const history = this.window.history;
if (history && history.scrollRestoration) {
history.scrollRestoration = scrollRestoration;
}
}
}
scrollToElement(el) {
const rect = el.getBoundingClientRect();
const left = rect.left + this.window.pageXOffset;
const top = rect.top + this.window.pageYOffset;
const offset = this.offset();
this.window.scrollTo(left - offset[0], top - offset[1]);
}
/**
* We only support scroll restoration when we can get a hold of window.
* This means that we do not support this behavior when running in a web worker.
*
* Lifting this restriction right now would require more changes in the dom adapter.
* Since webworkers aren't widely used, we will lift it once RouterScroller is
* battle-tested.
*/
supportScrollRestoration() {
try {
if (!this.window || !this.window.scrollTo) {
return false;
}
// The `scrollRestoration` property could be on the `history` instance or its prototype.
const scrollRestorationDescriptor = getScrollRestorationProperty(this.window.history) ||
getScrollRestorationProperty(Object.getPrototypeOf(this.window.history));
// We can write to the `scrollRestoration` property if it is a writable data field or it has a
// setter function.
return !!scrollRestorationDescriptor &&
!!(scrollRestorationDescriptor.writable || scrollRestorationDescriptor.set);
}
catch (_a) {
return false;
}
}
supportsScrolling() {
try {
return !!this.window.scrollTo;
}
catch (_a) {
return false;
}
}
}
function getScrollRestorationProperty(obj) {
return Object.getOwnPropertyDescriptor(obj, 'scrollRestoration');
}
/**
* Provides an empty implementation of the viewport scroller. This will
* live in @angular/common as it will be used by both platform-server and platform-webworker.
*/
class NullViewportScroller {
/**
* Empty implementation
*/
setOffset(offset) { }
/**
* Empty implementation
*/
getScrollPosition() {
return [0, 0];
}
/**
* Empty implementation
*/
scrollToPosition(position) { }
/**
* Empty implementation
*/
scrollToAnchor(anchor) { }
/**
* Empty implementation
*/
setHistoryScrollRestoration(scrollRestoration) { }
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// This file only reexports content of the `src` folder. Keep it that way.
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Generated bundle index. Do not edit.
*/
//# sourceMappingURL=common.js.map
/***/ }),
/***/ "./node_modules/@angular/compiler/fesm2015/compiler.js":
/*!*************************************************************!*\
!*** ./node_modules/@angular/compiler/fesm2015/compiler.js ***!
\*************************************************************/
/*! exports provided: AST, ASTWithName, ASTWithSource, AbsoluteSourceSpan, AotCompiler, AotSummaryResolver, ArrayType, AssertNotNull, AstMemoryEfficientTransformer, AstPath, AstTransformer, AttrAst, Attribute, Binary, BinaryOperator, BinaryOperatorExpr, BindingPipe, BoundDirectivePropertyAst, BoundElementProperty, BoundElementPropertyAst, BoundEventAst, BoundTextAst, BuiltinMethod, BuiltinType, BuiltinTypeName, BuiltinVar, CONTENT_ATTR, CUSTOM_ELEMENTS_SCHEMA, CastExpr, Chain, ClassField, ClassMethod, ClassStmt, CommaExpr, Comment, CommentStmt, CompileDirectiveMetadata, CompileMetadataResolver, CompileNgModuleMetadata, CompilePipeMetadata, CompileReflector, CompileShallowModuleMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTemplateMetadata, CompiledStylesheet, CompilerConfig, Conditional, ConditionalExpr, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DYNAMIC_TYPE, DeclareFunctionStmt, DeclareVarStmt, DirectiveAst, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, EOF, ERROR_COMPONENT_TYPE, Element, ElementAst, ElementSchemaRegistry, EmbeddedTemplateAst, EmitterVisitorContext, EmptyExpr, Expansion, ExpansionCase, Expression, ExpressionBinding, ExpressionStatement, ExpressionType, ExternalExpr, ExternalReference, Extractor, FunctionCall, FunctionExpr, GeneratedFile, HOST_ATTR, HtmlParser, HtmlTagDefinition, I18NHtmlParser, Identifiers, IfStmt, ImplicitReceiver, InstantiateExpr, Interpolation, InterpolationConfig, InvokeFunctionExpr, InvokeMethodExpr, IvyParser, JSDocCommentStmt, JitCompiler, JitEvaluator, JitSummaryResolver, KeyedRead, KeyedWrite, Lexer, LiteralArray, LiteralArrayExpr, LiteralExpr, LiteralMap, LiteralMapExpr, LiteralPrimitive, MapType, MessageBundle, MethodCall, NAMED_ENTITIES, NGSP_UNICODE, NONE_TYPE, NO_ERRORS_SCHEMA, NgContentAst, NgModuleCompiler, NgModuleResolver, NodeWithI18n, NonNullAssert, NotExpr, NullTemplateVisitor, ParseError, ParseErrorLevel, ParseLocation, ParseSourceFile, ParseSourceSpan, ParseSpan, ParseTreeResult, ParsedEvent, ParsedProperty, ParsedPropertyType, ParsedVariable, Parser, ParserError, PipeResolver, PrefixNot, PropertyRead, PropertyWrite, ProviderAst, ProviderAstType, ProviderMeta, Quote, R3BoundTarget, R3FactoryTarget, R3Identifiers, R3ResolvedDependencyType, R3TargetBinder, ReadKeyExpr, ReadPropExpr, ReadVarExpr, RecursiveAstVisitor, RecursiveTemplateAstVisitor, RecursiveVisitor, ReferenceAst, ResolvedStaticSymbol, ResourceLoader, ReturnStatement, STRING_TYPE, SafeMethodCall, SafePropertyRead, SelectorContext, SelectorListContext, SelectorMatcher, Serializer, SplitInterpolation, Statement, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, StmtModifier, StyleCompiler, StylesCompileDependency, SummaryResolver, TagContentType, TemplateBindingParseResult, TemplateParseError, TemplateParseResult, TemplateParser, Text, TextAst, ThrowStmt, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstContent, TmplAstElement, TmplAstRecursiveVisitor, TmplAstReference, TmplAstTemplate, TmplAstText, TmplAstTextAttribute, TmplAstVariable, Token, TokenType, TransitiveCompileNgModuleMetadata, TreeError, TryCatchStmt, Type, TypeScriptEmitter, TypeofExpr, UrlResolver, VERSION, VariableAst, VariableBinding, Version, ViewCompiler, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, Xliff, Xliff2, Xmb, XmlParser, Xtb, _ParseAST, analyzeAndValidateNgModules, analyzeFile, analyzeFileForInjectables, analyzeNgModules, collectExternalReferences, compileComponentFromMetadata, compileDirectiveFromMetadata, compileFactoryFunction, compileInjectable, compileInjector, compileNgModule, compilePipeFromMetadata, componentFactoryName, computeMsgId, core, createAotCompiler, createAotUrlResolver, createElementCssSelector, createLoweredSymbol, createOfflineCompileUrlResolver, createUrlResolverWithoutPackagePrefix, debugOutputAstAsTypeScript, findNode, flatten, formattedError, getHtmlTagDefinition, getNsPrefix, getParseErrors, getUrlScheme, hostViewClassName, identifierModuleUrl, identifierName, isEmptyExpression, isFormattedError, isIdentifier, isLoweredSymbol, isNgContainer, isNgContent, isNgTemplate, isQuote, isSyntaxError, literalMap, makeBindingParser, mergeAnalyzedFiles, mergeNsAndName, ngModuleJitUrl, parseHostBindings, parseTemplate, preserveWhitespacesDefault, publishFacade, r3JitTypeSourceSpan, removeSummaryDuplicates, rendererTypeName, sanitizeIdentifier, sharedStylesheetJitUrl, splitClasses, splitNsName, syntaxError, templateJitUrl, templateSourceUrl, templateVisitAll, toTypeScript, tokenName, tokenReference, typeSourceSpan, unescapeIdentifier, unwrapResolvedMetadata, verifyHostBindings, viewClassName, visitAll */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AST", function() { return AST; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ASTWithName", function() { return ASTWithName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ASTWithSource", function() { return ASTWithSource; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbsoluteSourceSpan", function() { return AbsoluteSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AotCompiler", function() { return AotCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AotSummaryResolver", function() { return AotSummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ArrayType", function() { return ArrayType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AssertNotNull", function() { return AssertNotNull; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstMemoryEfficientTransformer", function() { return AstMemoryEfficientTransformer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstPath", function() { return AstPath; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AstTransformer", function() { return AstTransformer$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AttrAst", function() { return AttrAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Attribute", function() { return Attribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Binary", function() { return Binary; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BinaryOperator", function() { return BinaryOperator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BinaryOperatorExpr", function() { return BinaryOperatorExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BindingPipe", function() { return BindingPipe; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundDirectivePropertyAst", function() { return BoundDirectivePropertyAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundElementProperty", function() { return BoundElementProperty; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundElementPropertyAst", function() { return BoundElementPropertyAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundEventAst", function() { return BoundEventAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BoundTextAst", function() { return BoundTextAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinMethod", function() { return BuiltinMethod; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinType", function() { return BuiltinType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinTypeName", function() { return BuiltinTypeName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BuiltinVar", function() { return BuiltinVar; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CONTENT_ATTR", function() { return CONTENT_ATTR; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CUSTOM_ELEMENTS_SCHEMA", function() { return CUSTOM_ELEMENTS_SCHEMA; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CastExpr", function() { return CastExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Chain", function() { return Chain; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassField", function() { return ClassField; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassMethod", function() { return ClassMethod; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ClassStmt", function() { return ClassStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommaExpr", function() { return CommaExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Comment", function() { return Comment; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CommentStmt", function() { return CommentStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileDirectiveMetadata", function() { return CompileDirectiveMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileMetadataResolver", function() { return CompileMetadataResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileNgModuleMetadata", function() { return CompileNgModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompilePipeMetadata", function() { return CompilePipeMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileReflector", function() { return CompileReflector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileShallowModuleMetadata", function() { return CompileShallowModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileStylesheetMetadata", function() { return CompileStylesheetMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileSummaryKind", function() { return CompileSummaryKind; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompileTemplateMetadata", function() { return CompileTemplateMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompiledStylesheet", function() { return CompiledStylesheet; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CompilerConfig", function() { return CompilerConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Conditional", function() { return Conditional; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConditionalExpr", function() { return ConditionalExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ConstantPool", function() { return ConstantPool; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CssSelector", function() { return CssSelector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DEFAULT_INTERPOLATION_CONFIG", function() { return DEFAULT_INTERPOLATION_CONFIG; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DYNAMIC_TYPE", function() { return DYNAMIC_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeclareFunctionStmt", function() { return DeclareFunctionStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DeclareVarStmt", function() { return DeclareVarStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveAst", function() { return DirectiveAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveNormalizer", function() { return DirectiveNormalizer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DirectiveResolver", function() { return DirectiveResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DomElementSchemaRegistry", function() { return DomElementSchemaRegistry; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EOF", function() { return EOF; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ERROR_COMPONENT_TYPE", function() { return ERROR_COMPONENT_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Element", function() { return Element$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementAst", function() { return ElementAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ElementSchemaRegistry", function() { return ElementSchemaRegistry; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmbeddedTemplateAst", function() { return EmbeddedTemplateAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmitterVisitorContext", function() { return EmitterVisitorContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "EmptyExpr", function() { return EmptyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Expansion", function() { return Expansion; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpansionCase", function() { return ExpansionCase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Expression", function() { return Expression; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpressionBinding", function() { return ExpressionBinding; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpressionStatement", function() { return ExpressionStatement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExpressionType", function() { return ExpressionType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExternalExpr", function() { return ExternalExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExternalReference", function() { return ExternalReference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Extractor", function() { return Extractor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FunctionCall", function() { return FunctionCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "FunctionExpr", function() { return FunctionExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "GeneratedFile", function() { return GeneratedFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HOST_ATTR", function() { return HOST_ATTR; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HtmlParser", function() { return HtmlParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "HtmlTagDefinition", function() { return HtmlTagDefinition; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "I18NHtmlParser", function() { return I18NHtmlParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Identifiers", function() { return Identifiers; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IfStmt", function() { return IfStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ImplicitReceiver", function() { return ImplicitReceiver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InstantiateExpr", function() { return InstantiateExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interpolation", function() { return Interpolation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InterpolationConfig", function() { return InterpolationConfig; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InvokeFunctionExpr", function() { return InvokeFunctionExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "InvokeMethodExpr", function() { return InvokeMethodExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IvyParser", function() { return IvyParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JSDocCommentStmt", function() { return JSDocCommentStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitCompiler", function() { return JitCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitEvaluator", function() { return JitEvaluator; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "JitSummaryResolver", function() { return JitSummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyedRead", function() { return KeyedRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "KeyedWrite", function() { return KeyedWrite; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Lexer", function() { return Lexer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralArray", function() { return LiteralArray; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralArrayExpr", function() { return LiteralArrayExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralExpr", function() { return LiteralExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralMap", function() { return LiteralMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralMapExpr", function() { return LiteralMapExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "LiteralPrimitive", function() { return LiteralPrimitive; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MapType", function() { return MapType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MessageBundle", function() { return MessageBundle; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MethodCall", function() { return MethodCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NAMED_ENTITIES", function() { return NAMED_ENTITIES; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NGSP_UNICODE", function() { return NGSP_UNICODE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NONE_TYPE", function() { return NONE_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NO_ERRORS_SCHEMA", function() { return NO_ERRORS_SCHEMA; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgContentAst", function() { return NgContentAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgModuleCompiler", function() { return NgModuleCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NgModuleResolver", function() { return NgModuleResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NodeWithI18n", function() { return NodeWithI18n; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NonNullAssert", function() { return NonNullAssert; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NotExpr", function() { return NotExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NullTemplateVisitor", function() { return NullTemplateVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseError", function() { return ParseError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseErrorLevel", function() { return ParseErrorLevel; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseLocation", function() { return ParseLocation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSourceFile", function() { return ParseSourceFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSourceSpan", function() { return ParseSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseSpan", function() { return ParseSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParseTreeResult", function() { return ParseTreeResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedEvent", function() { return ParsedEvent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedProperty", function() { return ParsedProperty; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedPropertyType", function() { return ParsedPropertyType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParsedVariable", function() { return ParsedVariable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Parser", function() { return Parser$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ParserError", function() { return ParserError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PipeResolver", function() { return PipeResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PrefixNot", function() { return PrefixNot; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PropertyRead", function() { return PropertyRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PropertyWrite", function() { return PropertyWrite; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderAst", function() { return ProviderAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderAstType", function() { return ProviderAstType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ProviderMeta", function() { return ProviderMeta; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Quote", function() { return Quote; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3BoundTarget", function() { return R3BoundTarget; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3FactoryTarget", function() { return R3FactoryTarget; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3Identifiers", function() { return Identifiers$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3ResolvedDependencyType", function() { return R3ResolvedDependencyType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "R3TargetBinder", function() { return R3TargetBinder; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadKeyExpr", function() { return ReadKeyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadPropExpr", function() { return ReadPropExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReadVarExpr", function() { return ReadVarExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveAstVisitor", function() { return RecursiveAstVisitor$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveTemplateAstVisitor", function() { return RecursiveTemplateAstVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RecursiveVisitor", function() { return RecursiveVisitor$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReferenceAst", function() { return ReferenceAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ResolvedStaticSymbol", function() { return ResolvedStaticSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ResourceLoader", function() { return ResourceLoader; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ReturnStatement", function() { return ReturnStatement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "STRING_TYPE", function() { return STRING_TYPE; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafeMethodCall", function() { return SafeMethodCall; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SafePropertyRead", function() { return SafePropertyRead; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorContext", function() { return SelectorContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorListContext", function() { return SelectorListContext; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SelectorMatcher", function() { return SelectorMatcher; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Serializer", function() { return Serializer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SplitInterpolation", function() { return SplitInterpolation; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Statement", function() { return Statement; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticReflector", function() { return StaticReflector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbol", function() { return StaticSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbolCache", function() { return StaticSymbolCache; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StaticSymbolResolver", function() { return StaticSymbolResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StmtModifier", function() { return StmtModifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StyleCompiler", function() { return StyleCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "StylesCompileDependency", function() { return StylesCompileDependency; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SummaryResolver", function() { return SummaryResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TagContentType", function() { return TagContentType; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateBindingParseResult", function() { return TemplateBindingParseResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParseError", function() { return TemplateParseError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParseResult", function() { return TemplateParseResult; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TemplateParser", function() { return TemplateParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Text", function() { return Text$3; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TextAst", function() { return TextAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ThrowStmt", function() { return ThrowStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundAttribute", function() { return BoundAttribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundEvent", function() { return BoundEvent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstBoundText", function() { return BoundText; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstContent", function() { return Content; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstElement", function() { return Element; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstRecursiveVisitor", function() { return RecursiveVisitor; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstReference", function() { return Reference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstTemplate", function() { return Template; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstText", function() { return Text; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstTextAttribute", function() { return TextAttribute; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TmplAstVariable", function() { return Variable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TokenType", function() { return TokenType$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TransitiveCompileNgModuleMetadata", function() { return TransitiveCompileNgModuleMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TreeError", function() { return TreeError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TryCatchStmt", function() { return TryCatchStmt; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TypeScriptEmitter", function() { return TypeScriptEmitter; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "TypeofExpr", function() { return TypeofExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UrlResolver", function() { return UrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VERSION", function() { return VERSION$1; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VariableAst", function() { return VariableAst; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "VariableBinding", function() { return VariableBinding; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Version", function() { return Version; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ViewCompiler", function() { return ViewCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WrappedNodeExpr", function() { return WrappedNodeExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WriteKeyExpr", function() { return WriteKeyExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WritePropExpr", function() { return WritePropExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "WriteVarExpr", function() { return WriteVarExpr; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xliff", function() { return Xliff; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xliff2", function() { return Xliff2; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xmb", function() { return Xmb; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "XmlParser", function() { return XmlParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Xtb", function() { return Xtb; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_ParseAST", function() { return _ParseAST; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeAndValidateNgModules", function() { return analyzeAndValidateNgModules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeFile", function() { return analyzeFile; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeFileForInjectables", function() { return analyzeFileForInjectables; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "analyzeNgModules", function() { return analyzeNgModules; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "collectExternalReferences", function() { return collectExternalReferences; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileComponentFromMetadata", function() { return compileComponentFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileDirectiveFromMetadata", function() { return compileDirectiveFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileFactoryFunction", function() { return compileFactoryFunction; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileInjectable", function() { return compileInjectable; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileInjector", function() { return compileInjector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compileNgModule", function() { return compileNgModule; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "compilePipeFromMetadata", function() { return compilePipeFromMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "componentFactoryName", function() { return componentFactoryName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "computeMsgId", function() { return computeMsgId; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "core", function() { return core; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createAotCompiler", function() { return createAotCompiler; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createAotUrlResolver", function() { return createAotUrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createElementCssSelector", function() { return createElementCssSelector; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLoweredSymbol", function() { return createLoweredSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createOfflineCompileUrlResolver", function() { return createOfflineCompileUrlResolver; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createUrlResolverWithoutPackagePrefix", function() { return createUrlResolverWithoutPackagePrefix; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "debugOutputAstAsTypeScript", function() { return debugOutputAstAsTypeScript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "findNode", function() { return findNode; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "flatten", function() { return flatten; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "formattedError", function() { return formattedError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getHtmlTagDefinition", function() { return getHtmlTagDefinition; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNsPrefix", function() { return getNsPrefix; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getParseErrors", function() { return getParseErrors; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getUrlScheme", function() { return getUrlScheme; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hostViewClassName", function() { return hostViewClassName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifierModuleUrl", function() { return identifierModuleUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "identifierName", function() { return identifierName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isEmptyExpression", function() { return isEmptyExpression; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isFormattedError", function() { return isFormattedError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isIdentifier", function() { return isIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isLoweredSymbol", function() { return isLoweredSymbol; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgContainer", function() { return isNgContainer; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgContent", function() { return isNgContent; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isNgTemplate", function() { return isNgTemplate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isQuote", function() { return isQuote; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isSyntaxError", function() { return isSyntaxError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "literalMap", function() { return literalMap; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "makeBindingParser", function() { return makeBindingParser; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeAnalyzedFiles", function() { return mergeAnalyzedFiles; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mergeNsAndName", function() { return mergeNsAndName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ngModuleJitUrl", function() { return ngModuleJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseHostBindings", function() { return parseHostBindings; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parseTemplate", function() { return parseTemplate; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "preserveWhitespacesDefault", function() { return preserveWhitespacesDefault; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "publishFacade", function() { return publishFacade; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "r3JitTypeSourceSpan", function() { return r3JitTypeSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeSummaryDuplicates", function() { return removeSummaryDuplicates; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "rendererTypeName", function() { return rendererTypeName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sanitizeIdentifier", function() { return sanitizeIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sharedStylesheetJitUrl", function() { return sharedStylesheetJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "splitClasses", function() { return splitClasses; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "splitNsName", function() { return splitNsName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateJitUrl", function() { return templateJitUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateSourceUrl", function() { return templateSourceUrl; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "templateVisitAll", function() { return templateVisitAll; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "toTypeScript", function() { return toTypeScript; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tokenName", function() { return tokenName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "tokenReference", function() { return tokenReference; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "typeSourceSpan", function() { return typeSourceSpan; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unescapeIdentifier", function() { return unescapeIdentifier; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "unwrapResolvedMetadata", function() { return unwrapResolvedMetadata; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "verifyHostBindings", function() { return verifyHostBindings; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "viewClassName", function() { return viewClassName; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visitAll", function() { return visitAll$1; });
/**
* @license Angular v10.0.14
* (c) 2010-2020 Google LLC. https://angular.io/
* License: MIT
*/
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var TagContentType;
(function (TagContentType) {
TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
})(TagContentType || (TagContentType = {}));
function splitNsName(elementName) {
if (elementName[0] != ':') {
return [null, elementName];
}
const colonIndex = elementName.indexOf(':', 1);
if (colonIndex == -1) {
throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
}
return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
}
// `` tags work the same regardless the namespace
function isNgContainer(tagName) {
return splitNsName(tagName)[1] === 'ng-container';
}
// `` tags work the same regardless the namespace
function isNgContent(tagName) {
return splitNsName(tagName)[1] === 'ng-content';
}
// `` tags work the same regardless the namespace
function isNgTemplate(tagName) {
return splitNsName(tagName)[1] === 'ng-template';
}
function getNsPrefix(fullName) {
return fullName === null ? null : splitNsName(fullName)[0];
}
function mergeNsAndName(prefix, localName) {
return prefix ? `:${prefix}:${localName}` : localName;
}
// see http://www.w3.org/TR/html51/syntax.html#named-character-references
// see https://html.spec.whatwg.org/multipage/entities.json
// This list is not exhaustive to keep the compiler footprint low.
// The `{` / `ƫ` syntax should be used when the named character reference does not
// exist.
const NAMED_ENTITIES = {
'Aacute': '\u00C1',
'aacute': '\u00E1',
'Acirc': '\u00C2',
'acirc': '\u00E2',
'acute': '\u00B4',
'AElig': '\u00C6',
'aelig': '\u00E6',
'Agrave': '\u00C0',
'agrave': '\u00E0',
'alefsym': '\u2135',
'Alpha': '\u0391',
'alpha': '\u03B1',
'amp': '&',
'and': '\u2227',
'ang': '\u2220',
'apos': '\u0027',
'Aring': '\u00C5',
'aring': '\u00E5',
'asymp': '\u2248',
'Atilde': '\u00C3',
'atilde': '\u00E3',
'Auml': '\u00C4',
'auml': '\u00E4',
'bdquo': '\u201E',
'Beta': '\u0392',
'beta': '\u03B2',
'brvbar': '\u00A6',
'bull': '\u2022',
'cap': '\u2229',
'Ccedil': '\u00C7',
'ccedil': '\u00E7',
'cedil': '\u00B8',
'cent': '\u00A2',
'Chi': '\u03A7',
'chi': '\u03C7',
'circ': '\u02C6',
'clubs': '\u2663',
'cong': '\u2245',
'copy': '\u00A9',
'crarr': '\u21B5',
'cup': '\u222A',
'curren': '\u00A4',
'dagger': '\u2020',
'Dagger': '\u2021',
'darr': '\u2193',
'dArr': '\u21D3',
'deg': '\u00B0',
'Delta': '\u0394',
'delta': '\u03B4',
'diams': '\u2666',
'divide': '\u00F7',
'Eacute': '\u00C9',
'eacute': '\u00E9',
'Ecirc': '\u00CA',
'ecirc': '\u00EA',
'Egrave': '\u00C8',
'egrave': '\u00E8',
'empty': '\u2205',
'emsp': '\u2003',
'ensp': '\u2002',
'Epsilon': '\u0395',
'epsilon': '\u03B5',
'equiv': '\u2261',
'Eta': '\u0397',
'eta': '\u03B7',
'ETH': '\u00D0',
'eth': '\u00F0',
'Euml': '\u00CB',
'euml': '\u00EB',
'euro': '\u20AC',
'exist': '\u2203',
'fnof': '\u0192',
'forall': '\u2200',
'frac12': '\u00BD',
'frac14': '\u00BC',
'frac34': '\u00BE',
'frasl': '\u2044',
'Gamma': '\u0393',
'gamma': '\u03B3',
'ge': '\u2265',
'gt': '>',
'harr': '\u2194',
'hArr': '\u21D4',
'hearts': '\u2665',
'hellip': '\u2026',
'Iacute': '\u00CD',
'iacute': '\u00ED',
'Icirc': '\u00CE',
'icirc': '\u00EE',
'iexcl': '\u00A1',
'Igrave': '\u00CC',
'igrave': '\u00EC',
'image': '\u2111',
'infin': '\u221E',
'int': '\u222B',
'Iota': '\u0399',
'iota': '\u03B9',
'iquest': '\u00BF',
'isin': '\u2208',
'Iuml': '\u00CF',
'iuml': '\u00EF',
'Kappa': '\u039A',
'kappa': '\u03BA',
'Lambda': '\u039B',
'lambda': '\u03BB',
'lang': '\u27E8',
'laquo': '\u00AB',
'larr': '\u2190',
'lArr': '\u21D0',
'lceil': '\u2308',
'ldquo': '\u201C',
'le': '\u2264',
'lfloor': '\u230A',
'lowast': '\u2217',
'loz': '\u25CA',
'lrm': '\u200E',
'lsaquo': '\u2039',
'lsquo': '\u2018',
'lt': '<',
'macr': '\u00AF',
'mdash': '\u2014',
'micro': '\u00B5',
'middot': '\u00B7',
'minus': '\u2212',
'Mu': '\u039C',
'mu': '\u03BC',
'nabla': '\u2207',
'nbsp': '\u00A0',
'ndash': '\u2013',
'ne': '\u2260',
'ni': '\u220B',
'not': '\u00AC',
'notin': '\u2209',
'nsub': '\u2284',
'Ntilde': '\u00D1',
'ntilde': '\u00F1',
'Nu': '\u039D',
'nu': '\u03BD',
'Oacute': '\u00D3',
'oacute': '\u00F3',
'Ocirc': '\u00D4',
'ocirc': '\u00F4',
'OElig': '\u0152',
'oelig': '\u0153',
'Ograve': '\u00D2',
'ograve': '\u00F2',
'oline': '\u203E',
'Omega': '\u03A9',
'omega': '\u03C9',
'Omicron': '\u039F',
'omicron': '\u03BF',
'oplus': '\u2295',
'or': '\u2228',
'ordf': '\u00AA',
'ordm': '\u00BA',
'Oslash': '\u00D8',
'oslash': '\u00F8',
'Otilde': '\u00D5',
'otilde': '\u00F5',
'otimes': '\u2297',
'Ouml': '\u00D6',
'ouml': '\u00F6',
'para': '\u00B6',
'permil': '\u2030',
'perp': '\u22A5',
'Phi': '\u03A6',
'phi': '\u03C6',
'Pi': '\u03A0',
'pi': '\u03C0',
'piv': '\u03D6',
'plusmn': '\u00B1',
'pound': '\u00A3',
'prime': '\u2032',
'Prime': '\u2033',
'prod': '\u220F',
'prop': '\u221D',
'Psi': '\u03A8',
'psi': '\u03C8',
'quot': '\u0022',
'radic': '\u221A',
'rang': '\u27E9',
'raquo': '\u00BB',
'rarr': '\u2192',
'rArr': '\u21D2',
'rceil': '\u2309',
'rdquo': '\u201D',
'real': '\u211C',
'reg': '\u00AE',
'rfloor': '\u230B',
'Rho': '\u03A1',
'rho': '\u03C1',
'rlm': '\u200F',
'rsaquo': '\u203A',
'rsquo': '\u2019',
'sbquo': '\u201A',
'Scaron': '\u0160',
'scaron': '\u0161',
'sdot': '\u22C5',
'sect': '\u00A7',
'shy': '\u00AD',
'Sigma': '\u03A3',
'sigma': '\u03C3',
'sigmaf': '\u03C2',
'sim': '\u223C',
'spades': '\u2660',
'sub': '\u2282',
'sube': '\u2286',
'sum': '\u2211',
'sup': '\u2283',
'sup1': '\u00B9',
'sup2': '\u00B2',
'sup3': '\u00B3',
'supe': '\u2287',
'szlig': '\u00DF',
'Tau': '\u03A4',
'tau': '\u03C4',
'there4': '\u2234',
'Theta': '\u0398',
'theta': '\u03B8',
'thetasym': '\u03D1',
'thinsp': '\u2009',
'THORN': '\u00DE',
'thorn': '\u00FE',
'tilde': '\u02DC',
'times': '\u00D7',
'trade': '\u2122',
'Uacute': '\u00DA',
'uacute': '\u00FA',
'uarr': '\u2191',
'uArr': '\u21D1',
'Ucirc': '\u00DB',
'ucirc': '\u00FB',
'Ugrave': '\u00D9',
'ugrave': '\u00F9',
'uml': '\u00A8',
'upsih': '\u03D2',
'Upsilon': '\u03A5',
'upsilon': '\u03C5',
'Uuml': '\u00DC',
'uuml': '\u00FC',
'weierp': '\u2118',
'Xi': '\u039E',
'xi': '\u03BE',
'Yacute': '\u00DD',
'yacute': '\u00FD',
'yen': '\u00A5',
'yuml': '\u00FF',
'Yuml': '\u0178',
'Zeta': '\u0396',
'zeta': '\u03B6',
'zwj': '\u200D',
'zwnj': '\u200C',
};
// The &ngsp; pseudo-entity is denoting a space. see:
// https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart
const NGSP_UNICODE = '\uE500';
NAMED_ENTITIES['ngsp'] = NGSP_UNICODE;
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class HtmlTagDefinition {
constructor({ closedByChildren, implicitNamespacePrefix, contentType = TagContentType.PARSABLE_DATA, closedByParent = false, isVoid = false, ignoreFirstLf = false } = {}) {
this.closedByChildren = {};
this.closedByParent = false;
this.canSelfClose = false;
if (closedByChildren && closedByChildren.length > 0) {
closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true);
}
this.isVoid = isVoid;
this.closedByParent = closedByParent || isVoid;
this.implicitNamespacePrefix = implicitNamespacePrefix || null;
this.contentType = contentType;
this.ignoreFirstLf = ignoreFirstLf;
}
isClosedByChild(name) {
return this.isVoid || name.toLowerCase() in this.closedByChildren;
}
}
let _DEFAULT_TAG_DEFINITION;
// see http://www.w3.org/TR/html51/syntax.html#optional-tags
// This implementation does not fully conform to the HTML5 spec.
let TAG_DEFINITIONS;
function getHtmlTagDefinition(tagName) {
if (!TAG_DEFINITIONS) {
_DEFAULT_TAG_DEFINITION = new HtmlTagDefinition();
TAG_DEFINITIONS = {
'base': new HtmlTagDefinition({ isVoid: true }),
'meta': new HtmlTagDefinition({ isVoid: true }),
'area': new HtmlTagDefinition({ isVoid: true }),
'embed': new HtmlTagDefinition({ isVoid: true }),
'link': new HtmlTagDefinition({ isVoid: true }),
'img': new HtmlTagDefinition({ isVoid: true }),
'input': new HtmlTagDefinition({ isVoid: true }),
'param': new HtmlTagDefinition({ isVoid: true }),
'hr': new HtmlTagDefinition({ isVoid: true }),
'br': new HtmlTagDefinition({ isVoid: true }),
'source': new HtmlTagDefinition({ isVoid: true }),
'track': new HtmlTagDefinition({ isVoid: true }),
'wbr': new HtmlTagDefinition({ isVoid: true }),
'p': new HtmlTagDefinition({
closedByChildren: [
'address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset',
'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5',
'h6', 'header', 'hgroup', 'hr', 'main', 'nav', 'ol',
'p', 'pre', 'section', 'table', 'ul'
],
closedByParent: true
}),
'thead': new HtmlTagDefinition({ closedByChildren: ['tbody', 'tfoot'] }),
'tbody': new HtmlTagDefinition({ closedByChildren: ['tbody', 'tfoot'], closedByParent: true }),
'tfoot': new HtmlTagDefinition({ closedByChildren: ['tbody'], closedByParent: true }),
'tr': new HtmlTagDefinition({ closedByChildren: ['tr'], closedByParent: true }),
'td': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }),
'th': new HtmlTagDefinition({ closedByChildren: ['td', 'th'], closedByParent: true }),
'col': new HtmlTagDefinition({ isVoid: true }),
'svg': new HtmlTagDefinition({ implicitNamespacePrefix: 'svg' }),
'math': new HtmlTagDefinition({ implicitNamespacePrefix: 'math' }),
'li': new HtmlTagDefinition({ closedByChildren: ['li'], closedByParent: true }),
'dt': new HtmlTagDefinition({ closedByChildren: ['dt', 'dd'] }),
'dd': new HtmlTagDefinition({ closedByChildren: ['dt', 'dd'], closedByParent: true }),
'rb': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }),
'rt': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }),
'rtc': new HtmlTagDefinition({ closedByChildren: ['rb', 'rtc', 'rp'], closedByParent: true }),
'rp': new HtmlTagDefinition({ closedByChildren: ['rb', 'rt', 'rtc', 'rp'], closedByParent: true }),
'optgroup': new HtmlTagDefinition({ closedByChildren: ['optgroup'], closedByParent: true }),
'option': new HtmlTagDefinition({ closedByChildren: ['option', 'optgroup'], closedByParent: true }),
'pre': new HtmlTagDefinition({ ignoreFirstLf: true }),
'listing': new HtmlTagDefinition({ ignoreFirstLf: true }),
'style': new HtmlTagDefinition({ contentType: TagContentType.RAW_TEXT }),
'script': new HtmlTagDefinition({ contentType: TagContentType.RAW_TEXT }),
'title': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT }),
'textarea': new HtmlTagDefinition({ contentType: TagContentType.ESCAPABLE_RAW_TEXT, ignoreFirstLf: true }),
};
}
return TAG_DEFINITIONS[tagName.toLowerCase()] || _DEFAULT_TAG_DEFINITION;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not("
'(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#";
// "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range
// 4: attribute; 5: attribute_string; 6: attribute_value
'(?:\\[([-.\\w*]+)(?:=([\"\']?)([^\\]\"\']*)\\5)?\\])|' + // "[name]", "[name=value]",
// "[name="value"]",
// "[name='value']"
'(\\))|' + // 7: ")"
'(\\s*,\\s*)', // 8: ","
'g');
/**
* A css selector contains an element name,
* css classes and attribute/value pairs with the purpose
* of selecting subsets out of them.
*/
class CssSelector {
constructor() {
this.element = null;
this.classNames = [];
/**
* The selectors are encoded in pairs where:
* - even locations are attribute names
* - odd locations are attribute values.
*
* Example:
* Selector: `[key1=value1][key2]` would parse to:
* ```
* ['key1', 'value1', 'key2', '']
* ```
*/
this.attrs = [];
this.notSelectors = [];
}
static parse(selector) {
const results = [];
const _addResult = (res, cssSel) => {
if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 &&
cssSel.attrs.length == 0) {
cssSel.element = '*';
}
res.push(cssSel);
};
let cssSelector = new CssSelector();
let match;
let current = cssSelector;
let inNot = false;
_SELECTOR_REGEXP.lastIndex = 0;
while (match = _SELECTOR_REGEXP.exec(selector)) {
if (match[1 /* NOT */]) {
if (inNot) {
throw new Error('Nesting :not in a selector is not allowed');
}
inNot = true;
current = new CssSelector();
cssSelector.notSelectors.push(current);
}
const tag = match[2 /* TAG */];
if (tag) {
const prefix = match[3 /* PREFIX */];
if (prefix === '#') {
// #hash
current.addAttribute('id', tag.substr(1));
}
else if (prefix === '.') {
// Class
current.addClassName(tag.substr(1));
}
else {
// Element
current.setElement(tag);
}
}
const attribute = match[4 /* ATTRIBUTE */];
if (attribute) {
current.addAttribute(attribute, match[6 /* ATTRIBUTE_VALUE */]);
}
if (match[7 /* NOT_END */]) {
inNot = false;
current = cssSelector;
}
if (match[8 /* SEPARATOR */]) {
if (inNot) {
throw new Error('Multiple selectors in :not are not supported');
}
_addResult(results, cssSelector);
cssSelector = current = new CssSelector();
}
}
_addResult(results, cssSelector);
return results;
}
isElementSelector() {
return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 &&
this.notSelectors.length === 0;
}
hasElementSelector() {
return !!this.element;
}
setElement(element = null) {
this.element = element;
}
/** Gets a template string for an element that matches the selector. */
getMatchingElementTemplate() {
const tagName = this.element || 'div';
const classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : '';
let attrs = '';
for (let i = 0; i < this.attrs.length; i += 2) {
const attrName = this.attrs[i];
const attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : '';
attrs += ` ${attrName}${attrValue}`;
}
return getHtmlTagDefinition(tagName).isVoid ? `<${tagName}${classAttr}${attrs}/>` :
`<${tagName}${classAttr}${attrs}>${tagName}>`;
}
getAttrs() {
const result = [];
if (this.classNames.length > 0) {
result.push('class', this.classNames.join(' '));
}
return result.concat(this.attrs);
}
addAttribute(name, value = '') {
this.attrs.push(name, value && value.toLowerCase() || '');
}
addClassName(name) {
this.classNames.push(name.toLowerCase());
}
toString() {
let res = this.element || '';
if (this.classNames) {
this.classNames.forEach(klass => res += `.${klass}`);
}
if (this.attrs) {
for (let i = 0; i < this.attrs.length; i += 2) {
const name = this.attrs[i];
const value = this.attrs[i + 1];
res += `[${name}${value ? '=' + value : ''}]`;
}
}
this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`);
return res;
}
}
/**
* Reads a list of CssSelectors and allows to calculate which ones
* are contained in a given CssSelector.
*/
class SelectorMatcher {
constructor() {
this._elementMap = new Map();
this._elementPartialMap = new Map();
this._classMap = new Map();
this._classPartialMap = new Map();
this._attrValueMap = new Map();
this._attrValuePartialMap = new Map();
this._listContexts = [];
}
static createNotMatcher(notSelectors) {
const notMatcher = new SelectorMatcher();
notMatcher.addSelectables(notSelectors, null);
return notMatcher;
}
addSelectables(cssSelectors, callbackCtxt) {
let listContext = null;
if (cssSelectors.length > 1) {
listContext = new SelectorListContext(cssSelectors);
this._listContexts.push(listContext);
}
for (let i = 0; i < cssSelectors.length; i++) {
this._addSelectable(cssSelectors[i], callbackCtxt, listContext);
}
}
/**
* Add an object that can be found later on by calling `match`.
* @param cssSelector A css selector
* @param callbackCtxt An opaque object that will be given to the callback of the `match` function
*/
_addSelectable(cssSelector, callbackCtxt, listContext) {
let matcher = this;
const element = cssSelector.element;
const classNames = cssSelector.classNames;
const attrs = cssSelector.attrs;
const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext);
if (element) {
const isTerminal = attrs.length === 0 && classNames.length === 0;
if (isTerminal) {
this._addTerminal(matcher._elementMap, element, selectable);
}
else {
matcher = this._addPartial(matcher._elementPartialMap, element);
}
}
if (classNames) {
for (let i = 0; i < classNames.length; i++) {
const isTerminal = attrs.length === 0 && i === classNames.length - 1;
const className = classNames[i];
if (isTerminal) {
this._addTerminal(matcher._classMap, className, selectable);
}
else {
matcher = this._addPartial(matcher._classPartialMap, className);
}
}
}
if (attrs) {
for (let i = 0; i < attrs.length; i += 2) {
const isTerminal = i === attrs.length - 2;
const name = attrs[i];
const value = attrs[i + 1];
if (isTerminal) {
const terminalMap = matcher._attrValueMap;
let terminalValuesMap = terminalMap.get(name);
if (!terminalValuesMap) {
terminalValuesMap = new Map();
terminalMap.set(name, terminalValuesMap);
}
this._addTerminal(terminalValuesMap, value, selectable);
}
else {
const partialMap = matcher._attrValuePartialMap;
let partialValuesMap = partialMap.get(name);
if (!partialValuesMap) {
partialValuesMap = new Map();
partialMap.set(name, partialValuesMap);
}
matcher = this._addPartial(partialValuesMap, value);
}
}
}
}
_addTerminal(map, name, selectable) {
let terminalList = map.get(name);
if (!terminalList) {
terminalList = [];
map.set(name, terminalList);
}
terminalList.push(selectable);
}
_addPartial(map, name) {
let matcher = map.get(name);
if (!matcher) {
matcher = new SelectorMatcher();
map.set(name, matcher);
}
return matcher;
}
/**
* Find the objects that have been added via `addSelectable`
* whose css selector is contained in the given css selector.
* @param cssSelector A css selector
* @param matchedCallback This callback will be called with the object handed into `addSelectable`
* @return boolean true if a match was found
*/
match(cssSelector, matchedCallback) {
let result = false;
const element = cssSelector.element;
const classNames = cssSelector.classNames;
const attrs = cssSelector.attrs;
for (let i = 0; i < this._listContexts.length; i++) {
this._listContexts[i].alreadyMatched = false;
}
result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) ||
result;
if (classNames) {
for (let i = 0; i < classNames.length; i++) {
const className = classNames[i];
result =
this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
result =
this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) ||
result;
}
}
if (attrs) {
for (let i = 0; i < attrs.length; i += 2) {
const name = attrs[i];
const value = attrs[i + 1];
const terminalValuesMap = this._attrValueMap.get(name);
if (value) {
result =
this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;
}
result =
this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;
const partialValuesMap = this._attrValuePartialMap.get(name);
if (value) {
result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;
}
result =
this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result;
}
}
return result;
}
/** @internal */
_matchTerminal(map, name, cssSelector, matchedCallback) {
if (!map || typeof name !== 'string') {
return false;
}
let selectables = map.get(name) || [];
const starSelectables = map.get('*');
if (starSelectables) {
selectables = selectables.concat(starSelectables);
}
if (selectables.length === 0) {
return false;
}
let selectable;
let result = false;
for (let i = 0; i < selectables.length; i++) {
selectable = selectables[i];
result = selectable.finalize(cssSelector, matchedCallback) || result;
}
return result;
}
/** @internal */
_matchPartial(map, name, cssSelector, matchedCallback) {
if (!map || typeof name !== 'string') {
return false;
}
const nestedSelector = map.get(name);
if (!nestedSelector) {
return false;
}
// TODO(perf): get rid of recursion and measure again
// TODO(perf): don't pass the whole selector into the recursion,
// but only the not processed parts
return nestedSelector.match(cssSelector, matchedCallback);
}
}
class SelectorListContext {
constructor(selectors) {
this.selectors = selectors;
this.alreadyMatched = false;
}
}
// Store context to pass back selector and context when a selector is matched
class SelectorContext {
constructor(selector, cbContext, listContext) {
this.selector = selector;
this.cbContext = cbContext;
this.listContext = listContext;
this.notSelectors = selector.notSelectors;
}
finalize(cssSelector, callback) {
let result = true;
if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {
const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);
result = !notMatcher.match(cssSelector, null);
}
if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) {
if (this.listContext) {
this.listContext.alreadyMatched = true;
}
callback(this.selector, this.cbContext);
}
return result;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const createInject = makeMetadataFactory('Inject', (token) => ({ token }));
const createInjectionToken = makeMetadataFactory('InjectionToken', (desc) => ({ _desc: desc, ɵprov: undefined }));
const createAttribute = makeMetadataFactory('Attribute', (attributeName) => ({ attributeName }));
const createContentChildren = makeMetadataFactory('ContentChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: false, descendants: false }, data)));
const createContentChild = makeMetadataFactory('ContentChild', (selector, data = {}) => (Object.assign({ selector, first: true, isViewQuery: false, descendants: true }, data)));
const createViewChildren = makeMetadataFactory('ViewChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: true, descendants: true }, data)));
const createViewChild = makeMetadataFactory('ViewChild', (selector, data) => (Object.assign({ selector, first: true, isViewQuery: true, descendants: true }, data)));
const createDirective = makeMetadataFactory('Directive', (dir = {}) => dir);
var ViewEncapsulation;
(function (ViewEncapsulation) {
ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
ViewEncapsulation[ViewEncapsulation["Native"] = 1] = "Native";
ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
})(ViewEncapsulation || (ViewEncapsulation = {}));
var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
const createComponent = makeMetadataFactory('Component', (c = {}) => (Object.assign({ changeDetection: ChangeDetectionStrategy.Default }, c)));
const createPipe = makeMetadataFactory('Pipe', (p) => (Object.assign({ pure: true }, p)));
const createInput = makeMetadataFactory('Input', (bindingPropertyName) => ({ bindingPropertyName }));
const createOutput = makeMetadataFactory('Output', (bindingPropertyName) => ({ bindingPropertyName }));
const createHostBinding = makeMetadataFactory('HostBinding', (hostPropertyName) => ({ hostPropertyName }));
const createHostListener = makeMetadataFactory('HostListener', (eventName, args) => ({ eventName, args }));
const createNgModule = makeMetadataFactory('NgModule', (ngModule) => ngModule);
const createInjectable = makeMetadataFactory('Injectable', (injectable = {}) => injectable);
const CUSTOM_ELEMENTS_SCHEMA = {
name: 'custom-elements'
};
const NO_ERRORS_SCHEMA = {
name: 'no-errors-schema'
};
const createOptional = makeMetadataFactory('Optional');
const createSelf = makeMetadataFactory('Self');
const createSkipSelf = makeMetadataFactory('SkipSelf');
const createHost = makeMetadataFactory('Host');
const Type = Function;
var SecurityContext;
(function (SecurityContext) {
SecurityContext[SecurityContext["NONE"] = 0] = "NONE";
SecurityContext[SecurityContext["HTML"] = 1] = "HTML";
SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE";
SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
SecurityContext[SecurityContext["URL"] = 4] = "URL";
SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
})(SecurityContext || (SecurityContext = {}));
var MissingTranslationStrategy;
(function (MissingTranslationStrategy) {
MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
function makeMetadataFactory(name, props) {
// This must be declared as a function, not a fat arrow, so that ES2015 devmode produces code
// that works with the static_reflector.ts in the ViewEngine compiler.
// In particular, `_registerDecoratorOrConstructor` assumes that the value returned here can be
// new'ed.
function factory(...args) {
const values = props ? props(...args) : {};
return Object.assign({ ngMetadataName: name }, values);
}
factory.isTypeOf = (obj) => obj && obj.ngMetadataName === name;
factory.ngMetadataName = name;
return factory;
}
function parserSelectorToSimpleSelector(selector) {
const classes = selector.classNames && selector.classNames.length ?
[8 /* CLASS */, ...selector.classNames] :
[];
const elementName = selector.element && selector.element !== '*' ? selector.element : '';
return [elementName, ...selector.attrs, ...classes];
}
function parserSelectorToNegativeSelector(selector) {
const classes = selector.classNames && selector.classNames.length ?
[8 /* CLASS */, ...selector.classNames] :
[];
if (selector.element) {
return [
1 /* NOT */ | 4 /* ELEMENT */, selector.element, ...selector.attrs, ...classes
];
}
else if (selector.attrs.length) {
return [1 /* NOT */ | 2 /* ATTRIBUTE */, ...selector.attrs, ...classes];
}
else {
return selector.classNames && selector.classNames.length ?
[1 /* NOT */ | 8 /* CLASS */, ...selector.classNames] :
[];
}
}
function parserSelectorToR3Selector(selector) {
const positive = parserSelectorToSimpleSelector(selector);
const negative = selector.notSelectors && selector.notSelectors.length ?
selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) :
[];
return positive.concat(...negative);
}
function parseSelectorToR3Selector(selector) {
return selector ? CssSelector.parse(selector).map(parserSelectorToR3Selector) : [];
}
var core = /*#__PURE__*/Object.freeze({
__proto__: null,
createInject: createInject,
createInjectionToken: createInjectionToken,
createAttribute: createAttribute,
createContentChildren: createContentChildren,
createContentChild: createContentChild,
createViewChildren: createViewChildren,
createViewChild: createViewChild,
createDirective: createDirective,
get ViewEncapsulation () { return ViewEncapsulation; },
get ChangeDetectionStrategy () { return ChangeDetectionStrategy; },
createComponent: createComponent,
createPipe: createPipe,
createInput: createInput,
createOutput: createOutput,
createHostBinding: createHostBinding,
createHostListener: createHostListener,
createNgModule: createNgModule,
createInjectable: createInjectable,
CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA,
NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA,
createOptional: createOptional,
createSelf: createSelf,
createSkipSelf: createSkipSelf,
createHost: createHost,
Type: Type,
get SecurityContext () { return SecurityContext; },
get MissingTranslationStrategy () { return MissingTranslationStrategy; },
parseSelectorToR3Selector: parseSelectorToR3Selector
});
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
//// Types
var TypeModifier;
(function (TypeModifier) {
TypeModifier[TypeModifier["Const"] = 0] = "Const";
})(TypeModifier || (TypeModifier = {}));
class Type$1 {
constructor(modifiers = null) {
this.modifiers = modifiers;
if (!modifiers) {
this.modifiers = [];
}
}
hasModifier(modifier) {
return this.modifiers.indexOf(modifier) !== -1;
}
}
var BuiltinTypeName;
(function (BuiltinTypeName) {
BuiltinTypeName[BuiltinTypeName["Dynamic"] = 0] = "Dynamic";
BuiltinTypeName[BuiltinTypeName["Bool"] = 1] = "Bool";
BuiltinTypeName[BuiltinTypeName["String"] = 2] = "String";
BuiltinTypeName[BuiltinTypeName["Int"] = 3] = "Int";
BuiltinTypeName[BuiltinTypeName["Number"] = 4] = "Number";
BuiltinTypeName[BuiltinTypeName["Function"] = 5] = "Function";
BuiltinTypeName[BuiltinTypeName["Inferred"] = 6] = "Inferred";
BuiltinTypeName[BuiltinTypeName["None"] = 7] = "None";
})(BuiltinTypeName || (BuiltinTypeName = {}));
class BuiltinType extends Type$1 {
constructor(name, modifiers = null) {
super(modifiers);
this.name = name;
}
visitType(visitor, context) {
return visitor.visitBuiltinType(this, context);
}
}
class ExpressionType extends Type$1 {
constructor(value, modifiers = null, typeParams = null) {
super(modifiers);
this.value = value;
this.typeParams = typeParams;
}
visitType(visitor, context) {
return visitor.visitExpressionType(this, context);
}
}
class ArrayType extends Type$1 {
constructor(of, modifiers = null) {
super(modifiers);
this.of = of;
}
visitType(visitor, context) {
return visitor.visitArrayType(this, context);
}
}
class MapType extends Type$1 {
constructor(valueType, modifiers = null) {
super(modifiers);
this.valueType = valueType || null;
}
visitType(visitor, context) {
return visitor.visitMapType(this, context);
}
}
const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);
const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
const NONE_TYPE = new BuiltinType(BuiltinTypeName.None);
///// Expressions
var BinaryOperator;
(function (BinaryOperator) {
BinaryOperator[BinaryOperator["Equals"] = 0] = "Equals";
BinaryOperator[BinaryOperator["NotEquals"] = 1] = "NotEquals";
BinaryOperator[BinaryOperator["Identical"] = 2] = "Identical";
BinaryOperator[BinaryOperator["NotIdentical"] = 3] = "NotIdentical";
BinaryOperator[BinaryOperator["Minus"] = 4] = "Minus";
BinaryOperator[BinaryOperator["Plus"] = 5] = "Plus";
BinaryOperator[BinaryOperator["Divide"] = 6] = "Divide";
BinaryOperator[BinaryOperator["Multiply"] = 7] = "Multiply";
BinaryOperator[BinaryOperator["Modulo"] = 8] = "Modulo";
BinaryOperator[BinaryOperator["And"] = 9] = "And";
BinaryOperator[BinaryOperator["Or"] = 10] = "Or";
BinaryOperator[BinaryOperator["BitwiseAnd"] = 11] = "BitwiseAnd";
BinaryOperator[BinaryOperator["Lower"] = 12] = "Lower";
BinaryOperator[BinaryOperator["LowerEquals"] = 13] = "LowerEquals";
BinaryOperator[BinaryOperator["Bigger"] = 14] = "Bigger";
BinaryOperator[BinaryOperator["BiggerEquals"] = 15] = "BiggerEquals";
})(BinaryOperator || (BinaryOperator = {}));
function nullSafeIsEquivalent(base, other) {
if (base == null || other == null) {
return base == other;
}
return base.isEquivalent(other);
}
function areAllEquivalent(base, other) {
const len = base.length;
if (len !== other.length) {
return false;
}
for (let i = 0; i < len; i++) {
if (!base[i].isEquivalent(other[i])) {
return false;
}
}
return true;
}
class Expression {
constructor(type, sourceSpan) {
this.type = type || null;
this.sourceSpan = sourceSpan || null;
}
prop(name, sourceSpan) {
return new ReadPropExpr(this, name, null, sourceSpan);
}
key(index, type, sourceSpan) {
return new ReadKeyExpr(this, index, type, sourceSpan);
}
callMethod(name, params, sourceSpan) {
return new InvokeMethodExpr(this, name, params, null, sourceSpan);
}
callFn(params, sourceSpan, pure) {
return new InvokeFunctionExpr(this, params, null, sourceSpan, pure);
}
instantiate(params, type, sourceSpan) {
return new InstantiateExpr(this, params, type, sourceSpan);
}
conditional(trueCase, falseCase = null, sourceSpan) {
return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);
}
equals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);
}
notEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);
}
identical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);
}
notIdentical(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);
}
minus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);
}
plus(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);
}
divide(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);
}
multiply(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);
}
modulo(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);
}
and(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
}
bitwiseAnd(rhs, sourceSpan, parens = true) {
return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens);
}
or(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);
}
lower(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);
}
lowerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);
}
bigger(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);
}
biggerEquals(rhs, sourceSpan) {
return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);
}
isBlank(sourceSpan) {
// Note: We use equals by purpose here to compare to null and undefined in JS.
// We use the typed null to allow strictNullChecks to narrow types.
return this.equals(TYPED_NULL_EXPR, sourceSpan);
}
cast(type, sourceSpan) {
return new CastExpr(this, type, sourceSpan);
}
toStmt() {
return new ExpressionStatement(this, null);
}
}
var BuiltinVar;
(function (BuiltinVar) {
BuiltinVar[BuiltinVar["This"] = 0] = "This";
BuiltinVar[BuiltinVar["Super"] = 1] = "Super";
BuiltinVar[BuiltinVar["CatchError"] = 2] = "CatchError";
BuiltinVar[BuiltinVar["CatchStack"] = 3] = "CatchStack";
})(BuiltinVar || (BuiltinVar = {}));
class ReadVarExpr extends Expression {
constructor(name, type, sourceSpan) {
super(type, sourceSpan);
if (typeof name === 'string') {
this.name = name;
this.builtin = null;
}
else {
this.name = null;
this.builtin = name;
}
}
isEquivalent(e) {
return e instanceof ReadVarExpr && this.name === e.name && this.builtin === e.builtin;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadVarExpr(this, context);
}
set(value) {
if (!this.name) {
throw new Error(`Built in variable ${this.builtin} can not be assigned to.`);
}
return new WriteVarExpr(this.name, value, null, this.sourceSpan);
}
}
class TypeofExpr extends Expression {
constructor(expr, type, sourceSpan) {
super(type, sourceSpan);
this.expr = expr;
}
visitExpression(visitor, context) {
return visitor.visitTypeofExpr(this, context);
}
isEquivalent(e) {
return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);
}
isConstant() {
return this.expr.isConstant();
}
}
class WrappedNodeExpr extends Expression {
constructor(node, type, sourceSpan) {
super(type, sourceSpan);
this.node = node;
}
isEquivalent(e) {
return e instanceof WrappedNodeExpr && this.node === e.node;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWrappedNodeExpr(this, context);
}
}
class WriteVarExpr extends Expression {
constructor(name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.name = name;
this.value = value;
}
isEquivalent(e) {
return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWriteVarExpr(this, context);
}
toDeclStmt(type, modifiers) {
return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
}
toConstDecl() {
return this.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]);
}
}
class WriteKeyExpr extends Expression {
constructor(receiver, index, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.index = index;
this.value = value;
}
isEquivalent(e) {
return e instanceof WriteKeyExpr && this.receiver.isEquivalent(e.receiver) &&
this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWriteKeyExpr(this, context);
}
}
class WritePropExpr extends Expression {
constructor(receiver, name, value, type, sourceSpan) {
super(type || value.type, sourceSpan);
this.receiver = receiver;
this.name = name;
this.value = value;
}
isEquivalent(e) {
return e instanceof WritePropExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name && this.value.isEquivalent(e.value);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitWritePropExpr(this, context);
}
}
var BuiltinMethod;
(function (BuiltinMethod) {
BuiltinMethod[BuiltinMethod["ConcatArray"] = 0] = "ConcatArray";
BuiltinMethod[BuiltinMethod["SubscribeObservable"] = 1] = "SubscribeObservable";
BuiltinMethod[BuiltinMethod["Bind"] = 2] = "Bind";
})(BuiltinMethod || (BuiltinMethod = {}));
class InvokeMethodExpr extends Expression {
constructor(receiver, method, args, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.args = args;
if (typeof method === 'string') {
this.name = method;
this.builtin = null;
}
else {
this.name = null;
this.builtin = method;
}
}
isEquivalent(e) {
return e instanceof InvokeMethodExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name && this.builtin === e.builtin && areAllEquivalent(this.args, e.args);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitInvokeMethodExpr(this, context);
}
}
class InvokeFunctionExpr extends Expression {
constructor(fn, args, type, sourceSpan, pure = false) {
super(type, sourceSpan);
this.fn = fn;
this.args = args;
this.pure = pure;
}
isEquivalent(e) {
return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) &&
areAllEquivalent(this.args, e.args) && this.pure === e.pure;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitInvokeFunctionExpr(this, context);
}
}
class InstantiateExpr extends Expression {
constructor(classExpr, args, type, sourceSpan) {
super(type, sourceSpan);
this.classExpr = classExpr;
this.args = args;
}
isEquivalent(e) {
return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) &&
areAllEquivalent(this.args, e.args);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitInstantiateExpr(this, context);
}
}
class LiteralExpr extends Expression {
constructor(value, type, sourceSpan) {
super(type, sourceSpan);
this.value = value;
}
isEquivalent(e) {
return e instanceof LiteralExpr && this.value === e.value;
}
isConstant() {
return true;
}
visitExpression(visitor, context) {
return visitor.visitLiteralExpr(this, context);
}
}
class LocalizedString extends Expression {
constructor(metaBlock, messageParts, placeHolderNames, expressions, sourceSpan) {
super(STRING_TYPE, sourceSpan);
this.metaBlock = metaBlock;
this.messageParts = messageParts;
this.placeHolderNames = placeHolderNames;
this.expressions = expressions;
}
isEquivalent(e) {
// return e instanceof LocalizedString && this.message === e.message;
return false;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitLocalizedString(this, context);
}
/**
* Serialize the given `meta` and `messagePart` into "cooked" and "raw" strings that can be used
* in a `$localize` tagged string. The format of the metadata is the same as that parsed by
* `parseI18nMeta()`.
*
* @param meta The metadata to serialize
* @param messagePart The first part of the tagged string
*/
serializeI18nHead() {
const MEANING_SEPARATOR = '|';
const ID_SEPARATOR = '@@';
const LEGACY_ID_INDICATOR = '␟';
let metaBlock = this.metaBlock.description || '';
if (this.metaBlock.meaning) {
metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR}${metaBlock}`;
}
if (this.metaBlock.customId) {
metaBlock = `${metaBlock}${ID_SEPARATOR}${this.metaBlock.customId}`;
}
if (this.metaBlock.legacyIds) {
this.metaBlock.legacyIds.forEach(legacyId => {
metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`;
});
}
return createCookedRawString(metaBlock, this.messageParts[0]);
}
/**
* Serialize the given `placeholderName` and `messagePart` into "cooked" and "raw" strings that
* can be used in a `$localize` tagged string.
*
* @param placeholderName The placeholder name to serialize
* @param messagePart The following message string after this placeholder
*/
serializeI18nTemplatePart(partIndex) {
const placeholderName = this.placeHolderNames[partIndex - 1];
const messagePart = this.messageParts[partIndex];
return createCookedRawString(placeholderName, messagePart);
}
}
const escapeSlashes = (str) => str.replace(/\\/g, '\\\\');
const escapeStartingColon = (str) => str.replace(/^:/, '\\:');
const escapeColons = (str) => str.replace(/:/g, '\\:');
const escapeForMessagePart = (str) => str.replace(/`/g, '\\`').replace(/\${/g, '$\\{');
/**
* Creates a `{cooked, raw}` object from the `metaBlock` and `messagePart`.
*
* The `raw` text must have various character sequences escaped:
* * "\" would otherwise indicate that the next character is a control character.
* * "`" and "${" are template string control sequences that would otherwise prematurely indicate
* the end of a message part.
* * ":" inside a metablock would prematurely indicate the end of the metablock.
* * ":" at the start of a messagePart with no metablock would erroneously indicate the start of a
* metablock.
*
* @param metaBlock Any metadata that should be prepended to the string
* @param messagePart The message part of the string
*/
function createCookedRawString(metaBlock, messagePart) {
if (metaBlock === '') {
return {
cooked: messagePart,
raw: escapeForMessagePart(escapeStartingColon(escapeSlashes(messagePart)))
};
}
else {
return {
cooked: `:${metaBlock}:${messagePart}`,
raw: escapeForMessagePart(`:${escapeColons(escapeSlashes(metaBlock))}:${escapeSlashes(messagePart)}`)
};
}
}
class ExternalExpr extends Expression {
constructor(value, type, typeParams = null, sourceSpan) {
super(type, sourceSpan);
this.value = value;
this.typeParams = typeParams;
}
isEquivalent(e) {
return e instanceof ExternalExpr && this.value.name === e.value.name &&
this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitExternalExpr(this, context);
}
}
class ExternalReference {
constructor(moduleName, name, runtime) {
this.moduleName = moduleName;
this.name = name;
this.runtime = runtime;
}
}
class ConditionalExpr extends Expression {
constructor(condition, trueCase, falseCase = null, type, sourceSpan) {
super(type || trueCase.type, sourceSpan);
this.condition = condition;
this.falseCase = falseCase;
this.trueCase = trueCase;
}
isEquivalent(e) {
return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) &&
this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitConditionalExpr(this, context);
}
}
class NotExpr extends Expression {
constructor(condition, sourceSpan) {
super(BOOL_TYPE, sourceSpan);
this.condition = condition;
}
isEquivalent(e) {
return e instanceof NotExpr && this.condition.isEquivalent(e.condition);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitNotExpr(this, context);
}
}
class AssertNotNull extends Expression {
constructor(condition, sourceSpan) {
super(condition.type, sourceSpan);
this.condition = condition;
}
isEquivalent(e) {
return e instanceof AssertNotNull && this.condition.isEquivalent(e.condition);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitAssertNotNullExpr(this, context);
}
}
class CastExpr extends Expression {
constructor(value, type, sourceSpan) {
super(type, sourceSpan);
this.value = value;
}
isEquivalent(e) {
return e instanceof CastExpr && this.value.isEquivalent(e.value);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitCastExpr(this, context);
}
}
class FnParam {
constructor(name, type = null) {
this.name = name;
this.type = type;
}
isEquivalent(param) {
return this.name === param.name;
}
}
class FunctionExpr extends Expression {
constructor(params, statements, type, sourceSpan, name) {
super(type, sourceSpan);
this.params = params;
this.statements = statements;
this.name = name;
}
isEquivalent(e) {
return e instanceof FunctionExpr && areAllEquivalent(this.params, e.params) &&
areAllEquivalent(this.statements, e.statements);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitFunctionExpr(this, context);
}
toDeclStmt(name, modifiers = null) {
return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
}
}
class BinaryOperatorExpr extends Expression {
constructor(operator, lhs, rhs, type, sourceSpan, parens = true) {
super(type || lhs.type, sourceSpan);
this.operator = operator;
this.rhs = rhs;
this.parens = parens;
this.lhs = lhs;
}
isEquivalent(e) {
return e instanceof BinaryOperatorExpr && this.operator === e.operator &&
this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitBinaryOperatorExpr(this, context);
}
}
class ReadPropExpr extends Expression {
constructor(receiver, name, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.name = name;
}
isEquivalent(e) {
return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) &&
this.name === e.name;
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadPropExpr(this, context);
}
set(value) {
return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan);
}
}
class ReadKeyExpr extends Expression {
constructor(receiver, index, type, sourceSpan) {
super(type, sourceSpan);
this.receiver = receiver;
this.index = index;
}
isEquivalent(e) {
return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) &&
this.index.isEquivalent(e.index);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitReadKeyExpr(this, context);
}
set(value) {
return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);
}
}
class LiteralArrayExpr extends Expression {
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
}
isConstant() {
return this.entries.every(e => e.isConstant());
}
isEquivalent(e) {
return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);
}
visitExpression(visitor, context) {
return visitor.visitLiteralArrayExpr(this, context);
}
}
class LiteralMapEntry {
constructor(key, value, quoted) {
this.key = key;
this.value = value;
this.quoted = quoted;
}
isEquivalent(e) {
return this.key === e.key && this.value.isEquivalent(e.value);
}
}
class LiteralMapExpr extends Expression {
constructor(entries, type, sourceSpan) {
super(type, sourceSpan);
this.entries = entries;
this.valueType = null;
if (type) {
this.valueType = type.valueType;
}
}
isEquivalent(e) {
return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);
}
isConstant() {
return this.entries.every(e => e.value.isConstant());
}
visitExpression(visitor, context) {
return visitor.visitLiteralMapExpr(this, context);
}
}
class CommaExpr extends Expression {
constructor(parts, sourceSpan) {
super(parts[parts.length - 1].type, sourceSpan);
this.parts = parts;
}
isEquivalent(e) {
return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);
}
isConstant() {
return false;
}
visitExpression(visitor, context) {
return visitor.visitCommaExpr(this, context);
}
}
const THIS_EXPR = new ReadVarExpr(BuiltinVar.This, null, null);
const SUPER_EXPR = new ReadVarExpr(BuiltinVar.Super, null, null);
const CATCH_ERROR_VAR = new ReadVarExpr(BuiltinVar.CatchError, null, null);
const CATCH_STACK_VAR = new ReadVarExpr(BuiltinVar.CatchStack, null, null);
const NULL_EXPR = new LiteralExpr(null, null, null);
const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null);
//// Statements
var StmtModifier;
(function (StmtModifier) {
StmtModifier[StmtModifier["Final"] = 0] = "Final";
StmtModifier[StmtModifier["Private"] = 1] = "Private";
StmtModifier[StmtModifier["Exported"] = 2] = "Exported";
StmtModifier[StmtModifier["Static"] = 3] = "Static";
})(StmtModifier || (StmtModifier = {}));
class Statement {
constructor(modifiers, sourceSpan) {
this.modifiers = modifiers || [];
this.sourceSpan = sourceSpan || null;
}
hasModifier(modifier) {
return this.modifiers.indexOf(modifier) !== -1;
}
}
class DeclareVarStmt extends Statement {
constructor(name, value, type, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.value = value;
this.type = type || (value && value.type) || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareVarStmt && this.name === stmt.name &&
(this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitDeclareVarStmt(this, context);
}
}
class DeclareFunctionStmt extends Statement {
constructor(name, params, statements, type, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.params = params;
this.statements = statements;
this.type = type || null;
}
isEquivalent(stmt) {
return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) &&
areAllEquivalent(this.statements, stmt.statements);
}
visitStatement(visitor, context) {
return visitor.visitDeclareFunctionStmt(this, context);
}
}
class ExpressionStatement extends Statement {
constructor(expr, sourceSpan) {
super(null, sourceSpan);
this.expr = expr;
}
isEquivalent(stmt) {
return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr);
}
visitStatement(visitor, context) {
return visitor.visitExpressionStmt(this, context);
}
}
class ReturnStatement extends Statement {
constructor(value, sourceSpan) {
super(null, sourceSpan);
this.value = value;
}
isEquivalent(stmt) {
return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value);
}
visitStatement(visitor, context) {
return visitor.visitReturnStmt(this, context);
}
}
class AbstractClassPart {
constructor(type, modifiers) {
this.modifiers = modifiers;
if (!modifiers) {
this.modifiers = [];
}
this.type = type || null;
}
hasModifier(modifier) {
return this.modifiers.indexOf(modifier) !== -1;
}
}
class ClassField extends AbstractClassPart {
constructor(name, type, modifiers = null, initializer) {
super(type, modifiers);
this.name = name;
this.initializer = initializer;
}
isEquivalent(f) {
return this.name === f.name;
}
}
class ClassMethod extends AbstractClassPart {
constructor(name, params, body, type, modifiers = null) {
super(type, modifiers);
this.name = name;
this.params = params;
this.body = body;
}
isEquivalent(m) {
return this.name === m.name && areAllEquivalent(this.body, m.body);
}
}
class ClassGetter extends AbstractClassPart {
constructor(name, body, type, modifiers = null) {
super(type, modifiers);
this.name = name;
this.body = body;
}
isEquivalent(m) {
return this.name === m.name && areAllEquivalent(this.body, m.body);
}
}
class ClassStmt extends Statement {
constructor(name, parent, fields, getters, constructorMethod, methods, modifiers = null, sourceSpan) {
super(modifiers, sourceSpan);
this.name = name;
this.parent = parent;
this.fields = fields;
this.getters = getters;
this.constructorMethod = constructorMethod;
this.methods = methods;
}
isEquivalent(stmt) {
return stmt instanceof ClassStmt && this.name === stmt.name &&
nullSafeIsEquivalent(this.parent, stmt.parent) &&
areAllEquivalent(this.fields, stmt.fields) &&
areAllEquivalent(this.getters, stmt.getters) &&
this.constructorMethod.isEquivalent(stmt.constructorMethod) &&
areAllEquivalent(this.methods, stmt.methods);
}
visitStatement(visitor, context) {
return visitor.visitDeclareClassStmt(this, context);
}
}
class IfStmt extends Statement {
constructor(condition, trueCase, falseCase = [], sourceSpan) {
super(null, sourceSpan);
this.condition = condition;
this.trueCase = trueCase;
this.falseCase = falseCase;
}
isEquivalent(stmt) {
return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) &&
areAllEquivalent(this.trueCase, stmt.trueCase) &&
areAllEquivalent(this.falseCase, stmt.falseCase);
}
visitStatement(visitor, context) {
return visitor.visitIfStmt(this, context);
}
}
class CommentStmt extends Statement {
constructor(comment, multiline = false, sourceSpan) {
super(null, sourceSpan);
this.comment = comment;
this.multiline = multiline;
}
isEquivalent(stmt) {
return stmt instanceof CommentStmt;
}
visitStatement(visitor, context) {
return visitor.visitCommentStmt(this, context);
}
}
class JSDocCommentStmt extends Statement {
constructor(tags = [], sourceSpan) {
super(null, sourceSpan);
this.tags = tags;
}
isEquivalent(stmt) {
return stmt instanceof JSDocCommentStmt && this.toString() === stmt.toString();
}
visitStatement(visitor, context) {
return visitor.visitJSDocCommentStmt(this, context);
}
toString() {
return serializeTags(this.tags);
}
}
class TryCatchStmt extends Statement {
constructor(bodyStmts, catchStmts, sourceSpan) {
super(null, sourceSpan);
this.bodyStmts = bodyStmts;
this.catchStmts = catchStmts;
}
isEquivalent(stmt) {
return stmt instanceof TryCatchStmt && areAllEquivalent(this.bodyStmts, stmt.bodyStmts) &&
areAllEquivalent(this.catchStmts, stmt.catchStmts);
}
visitStatement(visitor, context) {
return visitor.visitTryCatchStmt(this, context);
}
}
class ThrowStmt extends Statement {
constructor(error, sourceSpan) {
super(null, sourceSpan);
this.error = error;
}
isEquivalent(stmt) {
return stmt instanceof TryCatchStmt && this.error.isEquivalent(stmt.error);
}
visitStatement(visitor, context) {
return visitor.visitThrowStmt(this, context);
}
}
class AstTransformer {
transformExpr(expr, context) {
return expr;
}
transformStmt(stmt, context) {
return stmt;
}
visitReadVarExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitWrappedNodeExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitTypeofExpr(expr, context) {
return this.transformExpr(new TypeofExpr(expr.expr.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWriteVarExpr(expr, context) {
return this.transformExpr(new WriteVarExpr(expr.name, expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWriteKeyExpr(expr, context) {
return this.transformExpr(new WriteKeyExpr(expr.receiver.visitExpression(this, context), expr.index.visitExpression(this, context), expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitWritePropExpr(expr, context) {
return this.transformExpr(new WritePropExpr(expr.receiver.visitExpression(this, context), expr.name, expr.value.visitExpression(this, context), expr.type, expr.sourceSpan), context);
}
visitInvokeMethodExpr(ast, context) {
const method = ast.builtin || ast.name;
return this.transformExpr(new InvokeMethodExpr(ast.receiver.visitExpression(this, context), method, this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitInvokeFunctionExpr(ast, context) {
return this.transformExpr(new InvokeFunctionExpr(ast.fn.visitExpression(this, context), this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitInstantiateExpr(ast, context) {
return this.transformExpr(new InstantiateExpr(ast.classExpr.visitExpression(this, context), this.visitAllExpressions(ast.args, context), ast.type, ast.sourceSpan), context);
}
visitLiteralExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitLocalizedString(ast, context) {
return this.transformExpr(new LocalizedString(ast.metaBlock, ast.messageParts, ast.placeHolderNames, this.visitAllExpressions(ast.expressions, context), ast.sourceSpan), context);
}
visitExternalExpr(ast, context) {
return this.transformExpr(ast, context);
}
visitConditionalExpr(ast, context) {
return this.transformExpr(new ConditionalExpr(ast.condition.visitExpression(this, context), ast.trueCase.visitExpression(this, context), ast.falseCase.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitNotExpr(ast, context) {
return this.transformExpr(new NotExpr(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
}
visitAssertNotNullExpr(ast, context) {
return this.transformExpr(new AssertNotNull(ast.condition.visitExpression(this, context), ast.sourceSpan), context);
}
visitCastExpr(ast, context) {
return this.transformExpr(new CastExpr(ast.value.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitFunctionExpr(ast, context) {
return this.transformExpr(new FunctionExpr(ast.params, this.visitAllStatements(ast.statements, context), ast.type, ast.sourceSpan), context);
}
visitBinaryOperatorExpr(ast, context) {
return this.transformExpr(new BinaryOperatorExpr(ast.operator, ast.lhs.visitExpression(this, context), ast.rhs.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitReadPropExpr(ast, context) {
return this.transformExpr(new ReadPropExpr(ast.receiver.visitExpression(this, context), ast.name, ast.type, ast.sourceSpan), context);
}
visitReadKeyExpr(ast, context) {
return this.transformExpr(new ReadKeyExpr(ast.receiver.visitExpression(this, context), ast.index.visitExpression(this, context), ast.type, ast.sourceSpan), context);
}
visitLiteralArrayExpr(ast, context) {
return this.transformExpr(new LiteralArrayExpr(this.visitAllExpressions(ast.entries, context), ast.type, ast.sourceSpan), context);
}
visitLiteralMapExpr(ast, context) {
const entries = ast.entries.map((entry) => new LiteralMapEntry(entry.key, entry.value.visitExpression(this, context), entry.quoted));
const mapType = new MapType(ast.valueType, null);
return this.transformExpr(new LiteralMapExpr(entries, mapType, ast.sourceSpan), context);
}
visitCommaExpr(ast, context) {
return this.transformExpr(new CommaExpr(this.visitAllExpressions(ast.parts, context), ast.sourceSpan), context);
}
visitAllExpressions(exprs, context) {
return exprs.map(expr => expr.visitExpression(this, context));
}
visitDeclareVarStmt(stmt, context) {
const value = stmt.value && stmt.value.visitExpression(this, context);
return this.transformStmt(new DeclareVarStmt(stmt.name, value, stmt.type, stmt.modifiers, stmt.sourceSpan), context);
}
visitDeclareFunctionStmt(stmt, context) {
return this.transformStmt(new DeclareFunctionStmt(stmt.name, stmt.params, this.visitAllStatements(stmt.statements, context), stmt.type, stmt.modifiers, stmt.sourceSpan), context);
}
visitExpressionStmt(stmt, context) {
return this.transformStmt(new ExpressionStatement(stmt.expr.visitExpression(this, context), stmt.sourceSpan), context);
}
visitReturnStmt(stmt, context) {
return this.transformStmt(new ReturnStatement(stmt.value.visitExpression(this, context), stmt.sourceSpan), context);
}
visitDeclareClassStmt(stmt, context) {
const parent = stmt.parent.visitExpression(this, context);
const getters = stmt.getters.map(getter => new ClassGetter(getter.name, this.visitAllStatements(getter.body, context), getter.type, getter.modifiers));
const ctorMethod = stmt.constructorMethod &&
new ClassMethod(stmt.constructorMethod.name, stmt.constructorMethod.params, this.visitAllStatements(stmt.constructorMethod.body, context), stmt.constructorMethod.type, stmt.constructorMethod.modifiers);
const methods = stmt.methods.map(method => new ClassMethod(method.name, method.params, this.visitAllStatements(method.body, context), method.type, method.modifiers));
return this.transformStmt(new ClassStmt(stmt.name, parent, stmt.fields, getters, ctorMethod, methods, stmt.modifiers, stmt.sourceSpan), context);
}
visitIfStmt(stmt, context) {
return this.transformStmt(new IfStmt(stmt.condition.visitExpression(this, context), this.visitAllStatements(stmt.trueCase, context), this.visitAllStatements(stmt.falseCase, context), stmt.sourceSpan), context);
}
visitTryCatchStmt(stmt, context) {
return this.transformStmt(new TryCatchStmt(this.visitAllStatements(stmt.bodyStmts, context), this.visitAllStatements(stmt.catchStmts, context), stmt.sourceSpan), context);
}
visitThrowStmt(stmt, context) {
return this.transformStmt(new ThrowStmt(stmt.error.visitExpression(this, context), stmt.sourceSpan), context);
}
visitCommentStmt(stmt, context) {
return this.transformStmt(stmt, context);
}
visitJSDocCommentStmt(stmt, context) {
return this.transformStmt(stmt, context);
}
visitAllStatements(stmts, context) {
return stmts.map(stmt => stmt.visitStatement(this, context));
}
}
class RecursiveAstVisitor {
visitType(ast, context) {
return ast;
}
visitExpression(ast, context) {
if (ast.type) {
ast.type.visitType(this, context);
}
return ast;
}
visitBuiltinType(type, context) {
return this.visitType(type, context);
}
visitExpressionType(type, context) {
type.value.visitExpression(this, context);
if (type.typeParams !== null) {
type.typeParams.forEach(param => this.visitType(param, context));
}
return this.visitType(type, context);
}
visitArrayType(type, context) {
return this.visitType(type, context);
}
visitMapType(type, context) {
return this.visitType(type, context);
}
visitWrappedNodeExpr(ast, context) {
return ast;
}
visitTypeofExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitReadVarExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitWriteVarExpr(ast, context) {
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitWriteKeyExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.index.visitExpression(this, context);
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitWritePropExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitInvokeMethodExpr(ast, context) {
ast.receiver.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitInvokeFunctionExpr(ast, context) {
ast.fn.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitInstantiateExpr(ast, context) {
ast.classExpr.visitExpression(this, context);
this.visitAllExpressions(ast.args, context);
return this.visitExpression(ast, context);
}
visitLiteralExpr(ast, context) {
return this.visitExpression(ast, context);
}
visitLocalizedString(ast, context) {
return this.visitExpression(ast, context);
}
visitExternalExpr(ast, context) {
if (ast.typeParams) {
ast.typeParams.forEach(type => type.visitType(this, context));
}
return this.visitExpression(ast, context);
}
visitConditionalExpr(ast, context) {
ast.condition.visitExpression(this, context);
ast.trueCase.visitExpression(this, context);
ast.falseCase.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitNotExpr(ast, context) {
ast.condition.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitAssertNotNullExpr(ast, context) {
ast.condition.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitCastExpr(ast, context) {
ast.value.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitFunctionExpr(ast, context) {
this.visitAllStatements(ast.statements, context);
return this.visitExpression(ast, context);
}
visitBinaryOperatorExpr(ast, context) {
ast.lhs.visitExpression(this, context);
ast.rhs.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadPropExpr(ast, context) {
ast.receiver.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitReadKeyExpr(ast, context) {
ast.receiver.visitExpression(this, context);
ast.index.visitExpression(this, context);
return this.visitExpression(ast, context);
}
visitLiteralArrayExpr(ast, context) {
this.visitAllExpressions(ast.entries, context);
return this.visitExpression(ast, context);
}
visitLiteralMapExpr(ast, context) {
ast.entries.forEach((entry) => entry.value.visitExpression(this, context));
return this.visitExpression(ast, context);
}
visitCommaExpr(ast, context) {
this.visitAllExpressions(ast.parts, context);
return this.visitExpression(ast, context);
}
visitAllExpressions(exprs, context) {
exprs.forEach(expr => expr.visitExpression(this, context));
}
visitDeclareVarStmt(stmt, context) {
if (stmt.value) {
stmt.value.visitExpression(this, context);
}
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitDeclareFunctionStmt(stmt, context) {
this.visitAllStatements(stmt.statements, context);
if (stmt.type) {
stmt.type.visitType(this, context);
}
return stmt;
}
visitExpressionStmt(stmt, context) {
stmt.expr.visitExpression(this, context);
return stmt;
}
visitReturnStmt(stmt, context) {
stmt.value.visitExpression(this, context);
return stmt;
}
visitDeclareClassStmt(stmt, context) {
stmt.parent.visitExpression(this, context);
stmt.getters.forEach(getter => this.visitAllStatements(getter.body, context));
if (stmt.constructorMethod) {
this.visitAllStatements(stmt.constructorMethod.body, context);
}
stmt.methods.forEach(method => this.visitAllStatements(method.body, context));
return stmt;
}
visitIfStmt(stmt, context) {
stmt.condition.visitExpression(this, context);
this.visitAllStatements(stmt.trueCase, context);
this.visitAllStatements(stmt.falseCase, context);
return stmt;
}
visitTryCatchStmt(stmt, context) {
this.visitAllStatements(stmt.bodyStmts, context);
this.visitAllStatements(stmt.catchStmts, context);
return stmt;
}
visitThrowStmt(stmt, context) {
stmt.error.visitExpression(this, context);
return stmt;
}
visitCommentStmt(stmt, context) {
return stmt;
}
visitJSDocCommentStmt(stmt, context) {
return stmt;
}
visitAllStatements(stmts, context) {
stmts.forEach(stmt => stmt.visitStatement(this, context));
}
}
function findReadVarNames(stmts) {
const visitor = new _ReadVarVisitor();
visitor.visitAllStatements(stmts, null);
return visitor.varNames;
}
class _ReadVarVisitor extends RecursiveAstVisitor {
constructor() {
super(...arguments);
this.varNames = new Set();
}
visitDeclareFunctionStmt(stmt, context) {
// Don't descend into nested functions
return stmt;
}
visitDeclareClassStmt(stmt, context) {
// Don't descend into nested classes
return stmt;
}
visitReadVarExpr(ast, context) {
if (ast.name) {
this.varNames.add(ast.name);
}
return null;
}
}
function collectExternalReferences(stmts) {
const visitor = new _FindExternalReferencesVisitor();
visitor.visitAllStatements(stmts, null);
return visitor.externalReferences;
}
class _FindExternalReferencesVisitor extends RecursiveAstVisitor {
constructor() {
super(...arguments);
this.externalReferences = [];
}
visitExternalExpr(e, context) {
this.externalReferences.push(e.value);
return super.visitExternalExpr(e, context);
}
}
function applySourceSpanToStatementIfNeeded(stmt, sourceSpan) {
if (!sourceSpan) {
return stmt;
}
const transformer = new _ApplySourceSpanTransformer(sourceSpan);
return stmt.visitStatement(transformer, null);
}
function applySourceSpanToExpressionIfNeeded(expr, sourceSpan) {
if (!sourceSpan) {
return expr;
}
const transformer = new _ApplySourceSpanTransformer(sourceSpan);
return expr.visitExpression(transformer, null);
}
class _ApplySourceSpanTransformer extends AstTransformer {
constructor(sourceSpan) {
super();
this.sourceSpan = sourceSpan;
}
_clone(obj) {
const clone = Object.create(obj.constructor.prototype);
for (let prop of Object.keys(obj)) {
clone[prop] = obj[prop];
}
return clone;
}
transformExpr(expr, context) {
if (!expr.sourceSpan) {
expr = this._clone(expr);
expr.sourceSpan = this.sourceSpan;
}
return expr;
}
transformStmt(stmt, context) {
if (!stmt.sourceSpan) {
stmt = this._clone(stmt);
stmt.sourceSpan = this.sourceSpan;
}
return stmt;
}
}
function variable(name, type, sourceSpan) {
return new ReadVarExpr(name, type, sourceSpan);
}
function importExpr(id, typeParams = null, sourceSpan) {
return new ExternalExpr(id, null, typeParams, sourceSpan);
}
function importType(id, typeParams = null, typeModifiers = null) {
return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
}
function expressionType(expr, typeModifiers = null, typeParams = null) {
return new ExpressionType(expr, typeModifiers, typeParams);
}
function typeofExpr(expr) {
return new TypeofExpr(expr);
}
function literalArr(values, type, sourceSpan) {
return new LiteralArrayExpr(values, type, sourceSpan);
}
function literalMap(values, type = null) {
return new LiteralMapExpr(values.map(e => new LiteralMapEntry(e.key, e.value, e.quoted)), type, null);
}
function not(expr, sourceSpan) {
return new NotExpr(expr, sourceSpan);
}
function assertNotNull(expr, sourceSpan) {
return new AssertNotNull(expr, sourceSpan);
}
function fn(params, body, type, sourceSpan, name) {
return new FunctionExpr(params, body, type, sourceSpan, name);
}
function ifStmt(condition, thenClause, elseClause) {
return new IfStmt(condition, thenClause, elseClause);
}
function literal(value, type, sourceSpan) {
return new LiteralExpr(value, type, sourceSpan);
}
function localizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan) {
return new LocalizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan);
}
function isNull(exp) {
return exp instanceof LiteralExpr && exp.value === null;
}
/*
* Serializes a `Tag` into a string.
* Returns a string like " @foo {bar} baz" (note the leading whitespace before `@foo`).
*/
function tagToString(tag) {
let out = '';
if (tag.tagName) {
out += ` @${tag.tagName}`;
}
if (tag.text) {
if (tag.text.match(/\/\*|\*\//)) {
throw new Error('JSDoc text cannot contain "/*" and "*/"');
}
out += ' ' + tag.text.replace(/@/g, '\\@');
}
return out;
}
function serializeTags(tags) {
if (tags.length === 0)
return '';
let out = '*\n';
for (const tag of tags) {
out += ' *';
// If the tagToString is multi-line, insert " * " prefixes on subsequent lines.
out += tagToString(tag).replace(/\n/g, '\n * ');
out += '\n';
}
out += ' ';
return out;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
function dashCaseToCamelCase(input) {
return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase());
}
function splitAtColon(input, defaultValues) {
return _splitAt(input, ':', defaultValues);
}
function splitAtPeriod(input, defaultValues) {
return _splitAt(input, '.', defaultValues);
}
function _splitAt(input, character, defaultValues) {
const characterIndex = input.indexOf(character);
if (characterIndex == -1)
return defaultValues;
return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()];
}
function visitValue(value, visitor, context) {
if (Array.isArray(value)) {
return visitor.visitArray(value, context);
}
if (isStrictStringMap(value)) {
return visitor.visitStringMap(value, context);
}
if (value == null || typeof value == 'string' || typeof value == 'number' ||
typeof value == 'boolean') {
return visitor.visitPrimitive(value, context);
}
return visitor.visitOther(value, context);
}
function isDefined(val) {
return val !== null && val !== undefined;
}
function noUndefined(val) {
return val === undefined ? null : val;
}
class ValueTransformer {
visitArray(arr, context) {
return arr.map(value => visitValue(value, this, context));
}
visitStringMap(map, context) {
const result = {};
Object.keys(map).forEach(key => {
result[key] = visitValue(map[key], this, context);
});
return result;
}
visitPrimitive(value, context) {
return value;
}
visitOther(value, context) {
return value;
}
}
const SyncAsync = {
assertSync: (value) => {
if (isPromise(value)) {
throw new Error(`Illegal state: value cannot be a promise`);
}
return value;
},
then: (value, cb) => {
return isPromise(value) ? value.then(cb) : cb(value);
},
all: (syncAsyncValues) => {
return syncAsyncValues.some(isPromise) ? Promise.all(syncAsyncValues) : syncAsyncValues;
}
};
function error(msg) {
throw new Error(`Internal Error: ${msg}`);
}
function syntaxError(msg, parseErrors) {
const error = Error(msg);
error[ERROR_SYNTAX_ERROR] = true;
if (parseErrors)
error[ERROR_PARSE_ERRORS] = parseErrors;
return error;
}
const ERROR_SYNTAX_ERROR = 'ngSyntaxError';
const ERROR_PARSE_ERRORS = 'ngParseErrors';
function isSyntaxError(error) {
return error[ERROR_SYNTAX_ERROR];
}
function getParseErrors(error) {
return error[ERROR_PARSE_ERRORS] || [];
}
// Escape characters that have a special meaning in Regular Expressions
function escapeRegExp(s) {
return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
}
const STRING_MAP_PROTO = Object.getPrototypeOf({});
function isStrictStringMap(obj) {
return typeof obj === 'object' && obj !== null && Object.getPrototypeOf(obj) === STRING_MAP_PROTO;
}
function utf8Encode(str) {
let encoded = '';
for (let index = 0; index < str.length; index++) {
let codePoint = str.charCodeAt(index);
// decode surrogate
// see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > (index + 1)) {
const low = str.charCodeAt(index + 1);
if (low >= 0xdc00 && low <= 0xdfff) {
index++;
codePoint = ((codePoint - 0xd800) << 10) + low - 0xdc00 + 0x10000;
}
}
if (codePoint <= 0x7f) {
encoded += String.fromCharCode(codePoint);
}
else if (codePoint <= 0x7ff) {
encoded += String.fromCharCode(((codePoint >> 6) & 0x1F) | 0xc0, (codePoint & 0x3f) | 0x80);
}
else if (codePoint <= 0xffff) {
encoded += String.fromCharCode((codePoint >> 12) | 0xe0, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);
}
else if (codePoint <= 0x1fffff) {
encoded += String.fromCharCode(((codePoint >> 18) & 0x07) | 0xf0, ((codePoint >> 12) & 0x3f) | 0x80, ((codePoint >> 6) & 0x3f) | 0x80, (codePoint & 0x3f) | 0x80);
}
}
return encoded;
}
function stringify(token) {
if (typeof token === 'string') {
return token;
}
if (Array.isArray(token)) {
return '[' + token.map(stringify).join(', ') + ']';
}
if (token == null) {
return '' + token;
}
if (token.overriddenName) {
return `${token.overriddenName}`;
}
if (token.name) {
return `${token.name}`;
}
if (!token.toString) {
return 'object';
}
// WARNING: do not try to `JSON.stringify(token)` here
// see https://github.com/angular/angular/issues/23440
const res = token.toString();
if (res == null) {
return '' + res;
}
const newLineIndex = res.indexOf('\n');
return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
}
/**
* Lazily retrieves the reference value from a forwardRef.
*/
function resolveForwardRef(type) {
if (typeof type === 'function' && type.hasOwnProperty('__forward_ref__')) {
return type();
}
else {
return type;
}
}
/**
* Determine if the argument is shaped like a Promise
*/
function isPromise(obj) {
// allow any Promise/A+ compliant thenable.
// It's up to the caller to ensure that obj.then conforms to the spec
return !!obj && typeof obj.then === 'function';
}
class Version {
constructor(full) {
this.full = full;
const splits = full.split('.');
this.major = splits[0];
this.minor = splits[1];
this.patch = splits.slice(2).join('.');
}
}
const __window = typeof window !== 'undefined' && window;
const __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
self instanceof WorkerGlobalScope && self;
const __global = typeof global !== 'undefined' && global;
// Check __global first, because in Node tests both __global and __window may be defined and _global
// should be __global in that case.
const _global = __global || __window || __self;
function newArray(size, value) {
const list = [];
for (let i = 0; i < size; i++) {
list.push(value);
}
return list;
}
/**
* Partitions a given array into 2 arrays, based on a boolean value returned by the condition
* function.
*
* @param arr Input array that should be partitioned
* @param conditionFn Condition function that is called for each item in a given array and returns a
* boolean value.
*/
function partitionArray(arr, conditionFn) {
const truthy = [];
const falsy = [];
arr.forEach(item => {
(conditionFn(item) ? truthy : falsy).push(item);
});
return [truthy, falsy];
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const CONSTANT_PREFIX = '_c';
/**
* `ConstantPool` tries to reuse literal factories when two or more literals are identical.
* We determine whether literals are identical by creating a key out of their AST using the
* `KeyVisitor`. This constant is used to replace dynamic expressions which can't be safely
* converted into a key. E.g. given an expression `{foo: bar()}`, since we don't know what
* the result of `bar` will be, we create a key that looks like `{foo: }`. Note
* that we use a variable, rather than something like `null` in order to avoid collisions.
*/
const UNKNOWN_VALUE_KEY = variable('');
/**
* Context to use when producing a key.
*
* This ensures we see the constant not the reference variable when producing
* a key.
*/
const KEY_CONTEXT = {};
/**
* Generally all primitive values are excluded from the `ConstantPool`, but there is an exclusion
* for strings that reach a certain length threshold. This constant defines the length threshold for
* strings.
*/
const POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50;
/**
* A node that is a place-holder that allows the node to be replaced when the actual
* node is known.
*
* This allows the constant pool to change an expression from a direct reference to
* a constant to a shared constant. It returns a fix-up node that is later allowed to
* change the referenced expression.
*/
class FixupExpression extends Expression {
constructor(resolved) {
super(resolved.type);
this.resolved = resolved;
this.original = resolved;
}
visitExpression(visitor, context) {
if (context === KEY_CONTEXT) {
// When producing a key we want to traverse the constant not the
// variable used to refer to it.
return this.original.visitExpression(visitor, context);
}
else {
return this.resolved.visitExpression(visitor, context);
}
}
isEquivalent(e) {
return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
}
isConstant() {
return true;
}
fixup(expression) {
this.resolved = expression;
this.shared = true;
}
}
/**
* A constant pool allows a code emitter to share constant in an output context.
*
* The constant pool also supports sharing access to ivy definitions references.
*/
class ConstantPool {
constructor(isClosureCompilerEnabled = false) {
this.isClosureCompilerEnabled = isClosureCompilerEnabled;
this.statements = [];
this.literals = new Map();
this.literalFactories = new Map();
this.injectorDefinitions = new Map();
this.directiveDefinitions = new Map();
this.componentDefinitions = new Map();
this.pipeDefinitions = new Map();
this.nextNameIndex = 0;
}
getConstLiteral(literal, forceShared) {
if ((literal instanceof LiteralExpr && !isLongStringLiteral(literal)) ||
literal instanceof FixupExpression) {
// Do no put simple literals into the constant pool or try to produce a constant for a
// reference to a constant.
return literal;
}
const key = this.keyOf(literal);
let fixup = this.literals.get(key);
let newValue = false;
if (!fixup) {
fixup = new FixupExpression(literal);
this.literals.set(key, fixup);
newValue = true;
}
if ((!newValue && !fixup.shared) || (newValue && forceShared)) {
// Replace the expression with a variable
const name = this.freshName();
let definition;
let usage;
if (this.isClosureCompilerEnabled && isLongStringLiteral(literal)) {
// For string literals, Closure will **always** inline the string at
// **all** usages, duplicating it each time. For large strings, this
// unnecessarily bloats bundle size. To work around this restriction, we
// wrap the string in a function, and call that function for each usage.
// This tricks Closure into using inline logic for functions instead of
// string literals. Function calls are only inlined if the body is small
// enough to be worth it. By doing this, very large strings will be
// shared across multiple usages, rather than duplicating the string at
// each usage site.
//
// const myStr = function() { return "very very very long string"; };
// const usage1 = myStr();
// const usage2 = myStr();
definition = variable(name).set(new FunctionExpr([], // Params.
[
// Statements.
new ReturnStatement(literal),
]));
usage = variable(name).callFn([]);
}
else {
// Just declare and use the variable directly, without a function call
// indirection. This saves a few bytes and avoids an unncessary call.
definition = variable(name).set(literal);
usage = variable(name);
}
this.statements.push(definition.toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]));
fixup.fixup(usage);
}
return fixup;
}
getDefinition(type, kind, ctx, forceShared = false) {
const definitions = this.definitionsOf(kind);
let fixup = definitions.get(type);
let newValue = false;
if (!fixup) {
const property = this.propertyNameOf(kind);
fixup = new FixupExpression(ctx.importExpr(type).prop(property));
definitions.set(type, fixup);
newValue = true;
}
if ((!newValue && !fixup.shared) || (newValue && forceShared)) {
const name = this.freshName();
this.statements.push(variable(name).set(fixup.resolved).toDeclStmt(INFERRED_TYPE, [StmtModifier.Final]));
fixup.fixup(variable(name));
}
return fixup;
}
getLiteralFactory(literal) {
// Create a pure function that builds an array of a mix of constant and variable expressions
if (literal instanceof LiteralArrayExpr) {
const argumentsForKey = literal.entries.map(e => e.isConstant() ? e : UNKNOWN_VALUE_KEY);
const key = this.keyOf(literalArr(argumentsForKey));
return this._getLiteralFactory(key, literal.entries, entries => literalArr(entries));
}
else {
const expressionForKey = literalMap(literal.entries.map(e => ({
key: e.key,
value: e.value.isConstant() ? e.value : UNKNOWN_VALUE_KEY,
quoted: e.quoted
})));
const key = this.keyOf(expressionForKey);
return this._getLiteralFactory(key, literal.entries.map(e => e.value), entries => literalMap(entries.map((value, index) => ({
key: literal.entries[index].key,
value,
quoted: literal.entries[index].quoted
}))));
}
}
_getLiteralFactory(key, values, resultMap) {
let literalFactory = this.literalFactories.get(key);
const literalFactoryArguments = values.filter((e => !e.isConstant()));
if (!literalFactory) {
const resultExpressions = values.map((e, index) => e.isConstant() ? this.getConstLiteral(e, true) : variable(`a${index}`));
const parameters = resultExpressions.filter(isVariable).map(e => new FnParam(e.name, DYNAMIC_TYPE));
const pureFunctionDeclaration = fn(parameters, [new ReturnStatement(resultMap(resultExpressions))], INFERRED_TYPE);
const name = this.freshName();
this.statements.push(variable(name).set(pureFunctionDeclaration).toDeclStmt(INFERRED_TYPE, [
StmtModifier.Final
]));
literalFactory = variable(name);
this.literalFactories.set(key, literalFactory);
}
return { literalFactory, literalFactoryArguments };
}
/**
* Produce a unique name.
*
* The name might be unique among different prefixes if any of the prefixes end in
* a digit so the prefix should be a constant string (not based on user input) and
* must not end in a digit.
*/
uniqueName(prefix) {
return `${prefix}${this.nextNameIndex++}`;
}
definitionsOf(kind) {
switch (kind) {
case 2 /* Component */:
return this.componentDefinitions;
case 1 /* Directive */:
return this.directiveDefinitions;
case 0 /* Injector */:
return this.injectorDefinitions;
case 3 /* Pipe */:
return this.pipeDefinitions;
}
error(`Unknown definition kind ${kind}`);
return this.componentDefinitions;
}
propertyNameOf(kind) {
switch (kind) {
case 2 /* Component */:
return 'ɵcmp';
case 1 /* Directive */:
return 'ɵdir';
case 0 /* Injector */:
return 'ɵinj';
case 3 /* Pipe */:
return 'ɵpipe';
}
error(`Unknown definition kind ${kind}`);
return '';
}
freshName() {
return this.uniqueName(CONSTANT_PREFIX);
}
keyOf(expression) {
return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
}
}
/**
* Visitor used to determine if 2 expressions are equivalent and can be shared in the
* `ConstantPool`.
*
* When the id (string) generated by the visitor is equal, expressions are considered equivalent.
*/
class KeyVisitor {
constructor() {
this.visitWrappedNodeExpr = invalid;
this.visitWriteVarExpr = invalid;
this.visitWriteKeyExpr = invalid;
this.visitWritePropExpr = invalid;
this.visitInvokeMethodExpr = invalid;
this.visitInvokeFunctionExpr = invalid;
this.visitInstantiateExpr = invalid;
this.visitConditionalExpr = invalid;
this.visitNotExpr = invalid;
this.visitAssertNotNullExpr = invalid;
this.visitCastExpr = invalid;
this.visitFunctionExpr = invalid;
this.visitBinaryOperatorExpr = invalid;
this.visitReadPropExpr = invalid;
this.visitReadKeyExpr = invalid;
this.visitCommaExpr = invalid;
this.visitLocalizedString = invalid;
}
visitLiteralExpr(ast) {
return `${typeof ast.value === 'string' ? '"' + ast.value + '"' : ast.value}`;
}
visitLiteralArrayExpr(ast, context) {
return `[${ast.entries.map(entry => entry.visitExpression(this, context)).join(',')}]`;
}
visitLiteralMapExpr(ast, context) {
const mapKey = (entry) => {
const quote = entry.quoted ? '"' : '';
return `${quote}${entry.key}${quote}`;
};
const mapEntry = (entry) => `${mapKey(entry)}:${entry.value.visitExpression(this, context)}`;
return `{${ast.entries.map(mapEntry).join(',')}`;
}
visitExternalExpr(ast) {
return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` :
`EX:${ast.value.runtime.name}`;
}
visitReadVarExpr(node) {
return `VAR:${node.name}`;
}
visitTypeofExpr(node, context) {
return `TYPEOF:${node.expr.visitExpression(this, context)}`;
}
}
function invalid(arg) {
throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
}
function isVariable(e) {
return e instanceof ReadVarExpr;
}
function isLongStringLiteral(expr) {
return expr instanceof LiteralExpr && typeof expr.value === 'string' &&
expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const CORE = '@angular/core';
class Identifiers {
}
Identifiers.ANALYZE_FOR_ENTRY_COMPONENTS = {
name: 'ANALYZE_FOR_ENTRY_COMPONENTS',
moduleName: CORE,
};
Identifiers.ElementRef = { name: 'ElementRef', moduleName: CORE };
Identifiers.NgModuleRef = { name: 'NgModuleRef', moduleName: CORE };
Identifiers.ViewContainerRef = { name: 'ViewContainerRef', moduleName: CORE };
Identifiers.ChangeDetectorRef = {
name: 'ChangeDetectorRef',
moduleName: CORE,
};
Identifiers.QueryList = { name: 'QueryList', moduleName: CORE };
Identifiers.TemplateRef = { name: 'TemplateRef', moduleName: CORE };
Identifiers.Renderer2 = { name: 'Renderer2', moduleName: CORE };
Identifiers.CodegenComponentFactoryResolver = {
name: 'ɵCodegenComponentFactoryResolver',
moduleName: CORE,
};
Identifiers.ComponentFactoryResolver = {
name: 'ComponentFactoryResolver',
moduleName: CORE,
};
Identifiers.ComponentFactory = { name: 'ComponentFactory', moduleName: CORE };
Identifiers.ComponentRef = { name: 'ComponentRef', moduleName: CORE };
Identifiers.NgModuleFactory = { name: 'NgModuleFactory', moduleName: CORE };
Identifiers.createModuleFactory = {
name: 'ɵcmf',
moduleName: CORE,
};
Identifiers.moduleDef = {
name: 'ɵmod',
moduleName: CORE,
};
Identifiers.moduleProviderDef = {
name: 'ɵmpd',
moduleName: CORE,
};
Identifiers.RegisterModuleFactoryFn = {
name: 'ɵregisterModuleFactory',
moduleName: CORE,
};
Identifiers.inject = { name: 'ɵɵinject', moduleName: CORE };
Identifiers.directiveInject = { name: 'ɵɵdirectiveInject', moduleName: CORE };
Identifiers.INJECTOR = { name: 'INJECTOR', moduleName: CORE };
Identifiers.Injector = { name: 'Injector', moduleName: CORE };
Identifiers.ɵɵdefineInjectable = { name: 'ɵɵdefineInjectable', moduleName: CORE };
Identifiers.InjectableDef = { name: 'ɵɵInjectableDef', moduleName: CORE };
Identifiers.ViewEncapsulation = {
name: 'ViewEncapsulation',
moduleName: CORE,
};
Identifiers.ChangeDetectionStrategy = {
name: 'ChangeDetectionStrategy',
moduleName: CORE,
};
Identifiers.SecurityContext = {
name: 'SecurityContext',
moduleName: CORE,
};
Identifiers.LOCALE_ID = { name: 'LOCALE_ID', moduleName: CORE };
Identifiers.TRANSLATIONS_FORMAT = {
name: 'TRANSLATIONS_FORMAT',
moduleName: CORE,
};
Identifiers.inlineInterpolate = {
name: 'ɵinlineInterpolate',
moduleName: CORE,
};
Identifiers.interpolate = { name: 'ɵinterpolate', moduleName: CORE };
Identifiers.EMPTY_ARRAY = { name: 'ɵEMPTY_ARRAY', moduleName: CORE };
Identifiers.EMPTY_MAP = { name: 'ɵEMPTY_MAP', moduleName: CORE };
Identifiers.Renderer = { name: 'Renderer', moduleName: CORE };
Identifiers.viewDef = { name: 'ɵvid', moduleName: CORE };
Identifiers.elementDef = { name: 'ɵeld', moduleName: CORE };
Identifiers.anchorDef = { name: 'ɵand', moduleName: CORE };
Identifiers.textDef = { name: 'ɵted', moduleName: CORE };
Identifiers.directiveDef = { name: 'ɵdid', moduleName: CORE };
Identifiers.providerDef = { name: 'ɵprd', moduleName: CORE };
Identifiers.queryDef = { name: 'ɵqud', moduleName: CORE };
Identifiers.pureArrayDef = { name: 'ɵpad', moduleName: CORE };
Identifiers.pureObjectDef = { name: 'ɵpod', moduleName: CORE };
Identifiers.purePipeDef = { name: 'ɵppd', moduleName: CORE };
Identifiers.pipeDef = { name: 'ɵpid', moduleName: CORE };
Identifiers.nodeValue = { name: 'ɵnov', moduleName: CORE };
Identifiers.ngContentDef = { name: 'ɵncd', moduleName: CORE };
Identifiers.unwrapValue = { name: 'ɵunv', moduleName: CORE };
Identifiers.createRendererType2 = { name: 'ɵcrt', moduleName: CORE };
// type only
Identifiers.RendererType2 = {
name: 'RendererType2',
moduleName: CORE,
};
// type only
Identifiers.ViewDefinition = {
name: 'ɵViewDefinition',
moduleName: CORE,
};
Identifiers.createComponentFactory = { name: 'ɵccf', moduleName: CORE };
Identifiers.setClassMetadata = { name: 'ɵsetClassMetadata', moduleName: CORE };
function createTokenForReference(reference) {
return { identifier: { reference: reference } };
}
function createTokenForExternalReference(reflector, reference) {
return createTokenForReference(reflector.resolveExternalReference(reference));
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A token representing the a reference to a static type.
*
* This token is unique for a filePath and name and can be used as a hash table key.
*/
class StaticSymbol {
constructor(filePath, name, members) {
this.filePath = filePath;
this.name = name;
this.members = members;
}
assertNoMembers() {
if (this.members.length) {
throw new Error(`Illegal state: symbol without members expected, but got ${JSON.stringify(this)}.`);
}
}
}
/**
* A cache of static symbol used by the StaticReflector to return the same symbol for the
* same symbol values.
*/
class StaticSymbolCache {
constructor() {
this.cache = new Map();
}
get(declarationFile, name, members) {
members = members || [];
const memberSuffix = members.length ? `.${members.join('.')}` : '';
const key = `"${declarationFile}".${name}${memberSuffix}`;
let result = this.cache.get(key);
if (!result) {
result = new StaticSymbol(declarationFile, name, members);
this.cache.set(key, result);
}
return result;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// group 0: "[prop] or (event) or @trigger"
// group 1: "prop" from "[prop]"
// group 2: "event" from "(event)"
// group 3: "@trigger" from "@trigger"
const HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))|(\@[-\w]+)$/;
function sanitizeIdentifier(name) {
return name.replace(/\W/g, '_');
}
let _anonymousTypeIndex = 0;
function identifierName(compileIdentifier) {
if (!compileIdentifier || !compileIdentifier.reference) {
return null;
}
const ref = compileIdentifier.reference;
if (ref instanceof StaticSymbol) {
return ref.name;
}
if (ref['__anonymousType']) {
return ref['__anonymousType'];
}
let identifier = stringify(ref);
if (identifier.indexOf('(') >= 0) {
// case: anonymous functions!
identifier = `anonymous_${_anonymousTypeIndex++}`;
ref['__anonymousType'] = identifier;
}
else {
identifier = sanitizeIdentifier(identifier);
}
return identifier;
}
function identifierModuleUrl(compileIdentifier) {
const ref = compileIdentifier.reference;
if (ref instanceof StaticSymbol) {
return ref.filePath;
}
// Runtime type
return `./${stringify(ref)}`;
}
function viewClassName(compType, embeddedTemplateIndex) {
return `View_${identifierName({ reference: compType })}_${embeddedTemplateIndex}`;
}
function rendererTypeName(compType) {
return `RenderType_${identifierName({ reference: compType })}`;
}
function hostViewClassName(compType) {
return `HostView_${identifierName({ reference: compType })}`;
}
function componentFactoryName(compType) {
return `${identifierName({ reference: compType })}NgFactory`;
}
var CompileSummaryKind;
(function (CompileSummaryKind) {
CompileSummaryKind[CompileSummaryKind["Pipe"] = 0] = "Pipe";
CompileSummaryKind[CompileSummaryKind["Directive"] = 1] = "Directive";
CompileSummaryKind[CompileSummaryKind["NgModule"] = 2] = "NgModule";
CompileSummaryKind[CompileSummaryKind["Injectable"] = 3] = "Injectable";
})(CompileSummaryKind || (CompileSummaryKind = {}));
function tokenName(token) {
return token.value != null ? sanitizeIdentifier(token.value) : identifierName(token.identifier);
}
function tokenReference(token) {
if (token.identifier != null) {
return token.identifier.reference;
}
else {
return token.value;
}
}
/**
* Metadata about a stylesheet
*/
class CompileStylesheetMetadata {
constructor({ moduleUrl, styles, styleUrls } = {}) {
this.moduleUrl = moduleUrl || null;
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
}
}
/**
* Metadata regarding compilation of a template.
*/
class CompileTemplateMetadata {
constructor({ encapsulation, template, templateUrl, htmlAst, styles, styleUrls, externalStylesheets, animations, ngContentSelectors, interpolation, isInline, preserveWhitespaces }) {
this.encapsulation = encapsulation;
this.template = template;
this.templateUrl = templateUrl;
this.htmlAst = htmlAst;
this.styles = _normalizeArray(styles);
this.styleUrls = _normalizeArray(styleUrls);
this.externalStylesheets = _normalizeArray(externalStylesheets);
this.animations = animations ? flatten(animations) : [];
this.ngContentSelectors = ngContentSelectors || [];
if (interpolation && interpolation.length != 2) {
throw new Error(`'interpolation' should have a start and an end symbol.`);
}
this.interpolation = interpolation;
this.isInline = isInline;
this.preserveWhitespaces = preserveWhitespaces;
}
toSummary() {
return {
ngContentSelectors: this.ngContentSelectors,
encapsulation: this.encapsulation,
styles: this.styles,
animations: this.animations
};
}
}
/**
* Metadata regarding compilation of a directive.
*/
class CompileDirectiveMetadata {
constructor({ isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners, hostProperties, hostAttributes, providers, viewProviders, queries, guards, viewQueries, entryComponents, template, componentViewType, rendererType, componentFactory }) {
this.isHost = !!isHost;
this.type = type;
this.isComponent = isComponent;
this.selector = selector;
this.exportAs = exportAs;
this.changeDetection = changeDetection;
this.inputs = inputs;
this.outputs = outputs;
this.hostListeners = hostListeners;
this.hostProperties = hostProperties;
this.hostAttributes = hostAttributes;
this.providers = _normalizeArray(providers);
this.viewProviders = _normalizeArray(viewProviders);
this.queries = _normalizeArray(queries);
this.guards = guards;
this.viewQueries = _normalizeArray(viewQueries);
this.entryComponents = _normalizeArray(entryComponents);
this.template = template;
this.componentViewType = componentViewType;
this.rendererType = rendererType;
this.componentFactory = componentFactory;
}
static create({ isHost, type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host, providers, viewProviders, queries, guards, viewQueries, entryComponents, template, componentViewType, rendererType, componentFactory }) {
const hostListeners = {};
const hostProperties = {};
const hostAttributes = {};
if (host != null) {
Object.keys(host).forEach(key => {
const value = host[key];
const matches = key.match(HOST_REG_EXP);
if (matches === null) {
hostAttributes[key] = value;
}
else if (matches[1] != null) {
hostProperties[matches[1]] = value;
}
else if (matches[2] != null) {
hostListeners[matches[2]] = value;
}
});
}
const inputsMap = {};
if (inputs != null) {
inputs.forEach((bindConfig) => {
// canonical syntax: `dirProp: elProp`
// if there is no `:`, use dirProp = elProp
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
inputsMap[parts[0]] = parts[1];
});
}
const outputsMap = {};
if (outputs != null) {
outputs.forEach((bindConfig) => {
// canonical syntax: `dirProp: elProp`
// if there is no `:`, use dirProp = elProp
const parts = splitAtColon(bindConfig, [bindConfig, bindConfig]);
outputsMap[parts[0]] = parts[1];
});
}
return new CompileDirectiveMetadata({
isHost,
type,
isComponent: !!isComponent,
selector,
exportAs,
changeDetection,
inputs: inputsMap,
outputs: outputsMap,
hostListeners,
hostProperties,
hostAttributes,
providers,
viewProviders,
queries,
guards,
viewQueries,
entryComponents,
template,
componentViewType,
rendererType,
componentFactory,
});
}
toSummary() {
return {
summaryKind: CompileSummaryKind.Directive,
type: this.type,
isComponent: this.isComponent,
selector: this.selector,
exportAs: this.exportAs,
inputs: this.inputs,
outputs: this.outputs,
hostListeners: this.hostListeners,
hostProperties: this.hostProperties,
hostAttributes: this.hostAttributes,
providers: this.providers,
viewProviders: this.viewProviders,
queries: this.queries,
guards: this.guards,
viewQueries: this.viewQueries,
entryComponents: this.entryComponents,
changeDetection: this.changeDetection,
template: this.template && this.template.toSummary(),
componentViewType: this.componentViewType,
rendererType: this.rendererType,
componentFactory: this.componentFactory
};
}
}
class CompilePipeMetadata {
constructor({ type, name, pure }) {
this.type = type;
this.name = name;
this.pure = !!pure;
}
toSummary() {
return {
summaryKind: CompileSummaryKind.Pipe,
type: this.type,
name: this.name,
pure: this.pure
};
}
}
class CompileShallowModuleMetadata {
}
/**
* Metadata regarding compilation of a module.
*/
class CompileNgModuleMetadata {
constructor({ type, providers, declaredDirectives, exportedDirectives, declaredPipes, exportedPipes, entryComponents, bootstrapComponents, importedModules, exportedModules, schemas, transitiveModule, id }) {
this.type = type || null;
this.declaredDirectives = _normalizeArray(declaredDirectives);
this.exportedDirectives = _normalizeArray(exportedDirectives);
this.declaredPipes = _normalizeArray(declaredPipes);
this.exportedPipes = _normalizeArray(exportedPipes);
this.providers = _normalizeArray(providers);
this.entryComponents = _normalizeArray(entryComponents);
this.bootstrapComponents = _normalizeArray(bootstrapComponents);
this.importedModules = _normalizeArray(importedModules);
this.exportedModules = _normalizeArray(exportedModules);
this.schemas = _normalizeArray(schemas);
this.id = id || null;
this.transitiveModule = transitiveModule || null;
}
toSummary() {
const module = this.transitiveModule;
return {
summaryKind: CompileSummaryKind.NgModule,
type: this.type,
entryComponents: module.entryComponents,
providers: module.providers,
modules: module.modules,
exportedDirectives: module.exportedDirectives,
exportedPipes: module.exportedPipes
};
}
}
class TransitiveCompileNgModuleMetadata {
constructor() {
this.directivesSet = new Set();
this.directives = [];
this.exportedDirectivesSet = new Set();
this.exportedDirectives = [];
this.pipesSet = new Set();
this.pipes = [];
this.exportedPipesSet = new Set();
this.exportedPipes = [];
this.modulesSet = new Set();
this.modules = [];
this.entryComponentsSet = new Set();
this.entryComponents = [];
this.providers = [];
}
addProvider(provider, module) {
this.providers.push({ provider: provider, module: module });
}
addDirective(id) {
if (!this.directivesSet.has(id.reference)) {
this.directivesSet.add(id.reference);
this.directives.push(id);
}
}
addExportedDirective(id) {
if (!this.exportedDirectivesSet.has(id.reference)) {
this.exportedDirectivesSet.add(id.reference);
this.exportedDirectives.push(id);
}
}
addPipe(id) {
if (!this.pipesSet.has(id.reference)) {
this.pipesSet.add(id.reference);
this.pipes.push(id);
}
}
addExportedPipe(id) {
if (!this.exportedPipesSet.has(id.reference)) {
this.exportedPipesSet.add(id.reference);
this.exportedPipes.push(id);
}
}
addModule(id) {
if (!this.modulesSet.has(id.reference)) {
this.modulesSet.add(id.reference);
this.modules.push(id);
}
}
addEntryComponent(ec) {
if (!this.entryComponentsSet.has(ec.componentType)) {
this.entryComponentsSet.add(ec.componentType);
this.entryComponents.push(ec);
}
}
}
function _normalizeArray(obj) {
return obj || [];
}
class ProviderMeta {
constructor(token, { useClass, useValue, useExisting, useFactory, deps, multi }) {
this.token = token;
this.useClass = useClass || null;
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory || null;
this.dependencies = deps || null;
this.multi = !!multi;
}
}
function flatten(list) {
return list.reduce((flat, item) => {
const flatItem = Array.isArray(item) ? flatten(item) : item;
return flat.concat(flatItem);
}, []);
}
function jitSourceUrl(url) {
// Note: We need 3 "/" so that ng shows up as a separate domain
// in the chrome dev tools.
return url.replace(/(\w+:\/\/[\w:-]+)?(\/+)?/, 'ng:///');
}
function templateSourceUrl(ngModuleType, compMeta, templateMeta) {
let url;
if (templateMeta.isInline) {
if (compMeta.type.reference instanceof StaticSymbol) {
// Note: a .ts file might contain multiple components with inline templates,
// so we need to give them unique urls, as these will be used for sourcemaps.
url = `${compMeta.type.reference.filePath}.${compMeta.type.reference.name}.html`;
}
else {
url = `${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.html`;
}
}
else {
url = templateMeta.templateUrl;
}
return compMeta.type.reference instanceof StaticSymbol ? url : jitSourceUrl(url);
}
function sharedStylesheetJitUrl(meta, id) {
const pathParts = meta.moduleUrl.split(/\/\\/g);
const baseName = pathParts[pathParts.length - 1];
return jitSourceUrl(`css/${id}${baseName}.ngstyle.js`);
}
function ngModuleJitUrl(moduleMeta) {
return jitSourceUrl(`${identifierName(moduleMeta.type)}/module.ngfactory.js`);
}
function templateJitUrl(ngModuleType, compMeta) {
return jitSourceUrl(`${identifierName(ngModuleType)}/${identifierName(compMeta.type)}.ngfactory.js`);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const CORE$1 = '@angular/core';
class Identifiers$1 {
}
/* Methods */
Identifiers$1.NEW_METHOD = 'factory';
Identifiers$1.TRANSFORM_METHOD = 'transform';
Identifiers$1.PATCH_DEPS = 'patchedDeps';
/* Instructions */
Identifiers$1.namespaceHTML = { name: 'ɵɵnamespaceHTML', moduleName: CORE$1 };
Identifiers$1.namespaceMathML = { name: 'ɵɵnamespaceMathML', moduleName: CORE$1 };
Identifiers$1.namespaceSVG = { name: 'ɵɵnamespaceSVG', moduleName: CORE$1 };
Identifiers$1.element = { name: 'ɵɵelement', moduleName: CORE$1 };
Identifiers$1.elementStart = { name: 'ɵɵelementStart', moduleName: CORE$1 };
Identifiers$1.elementEnd = { name: 'ɵɵelementEnd', moduleName: CORE$1 };
Identifiers$1.select = { name: 'ɵɵselect', moduleName: CORE$1 };
Identifiers$1.advance = { name: 'ɵɵadvance', moduleName: CORE$1 };
Identifiers$1.syntheticHostProperty = { name: 'ɵɵsyntheticHostProperty', moduleName: CORE$1 };
Identifiers$1.syntheticHostListener = { name: 'ɵɵsyntheticHostListener', moduleName: CORE$1 };
Identifiers$1.attribute = { name: 'ɵɵattribute', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate1 = { name: 'ɵɵattributeInterpolate1', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate2 = { name: 'ɵɵattributeInterpolate2', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate3 = { name: 'ɵɵattributeInterpolate3', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate4 = { name: 'ɵɵattributeInterpolate4', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate5 = { name: 'ɵɵattributeInterpolate5', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate6 = { name: 'ɵɵattributeInterpolate6', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate7 = { name: 'ɵɵattributeInterpolate7', moduleName: CORE$1 };
Identifiers$1.attributeInterpolate8 = { name: 'ɵɵattributeInterpolate8', moduleName: CORE$1 };
Identifiers$1.attributeInterpolateV = { name: 'ɵɵattributeInterpolateV', moduleName: CORE$1 };
Identifiers$1.classProp = { name: 'ɵɵclassProp', moduleName: CORE$1 };
Identifiers$1.elementContainerStart = { name: 'ɵɵelementContainerStart', moduleName: CORE$1 };
Identifiers$1.elementContainerEnd = { name: 'ɵɵelementContainerEnd', moduleName: CORE$1 };
Identifiers$1.elementContainer = { name: 'ɵɵelementContainer', moduleName: CORE$1 };
Identifiers$1.styleMap = { name: 'ɵɵstyleMap', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate1 = { name: 'ɵɵstyleMapInterpolate1', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate2 = { name: 'ɵɵstyleMapInterpolate2', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate3 = { name: 'ɵɵstyleMapInterpolate3', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate4 = { name: 'ɵɵstyleMapInterpolate4', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate5 = { name: 'ɵɵstyleMapInterpolate5', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate6 = { name: 'ɵɵstyleMapInterpolate6', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate7 = { name: 'ɵɵstyleMapInterpolate7', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolate8 = { name: 'ɵɵstyleMapInterpolate8', moduleName: CORE$1 };
Identifiers$1.styleMapInterpolateV = { name: 'ɵɵstyleMapInterpolateV', moduleName: CORE$1 };
Identifiers$1.classMap = { name: 'ɵɵclassMap', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate1 = { name: 'ɵɵclassMapInterpolate1', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate2 = { name: 'ɵɵclassMapInterpolate2', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate3 = { name: 'ɵɵclassMapInterpolate3', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate4 = { name: 'ɵɵclassMapInterpolate4', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate5 = { name: 'ɵɵclassMapInterpolate5', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate6 = { name: 'ɵɵclassMapInterpolate6', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate7 = { name: 'ɵɵclassMapInterpolate7', moduleName: CORE$1 };
Identifiers$1.classMapInterpolate8 = { name: 'ɵɵclassMapInterpolate8', moduleName: CORE$1 };
Identifiers$1.classMapInterpolateV = { name: 'ɵɵclassMapInterpolateV', moduleName: CORE$1 };
Identifiers$1.styleProp = { name: 'ɵɵstyleProp', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate1 = { name: 'ɵɵstylePropInterpolate1', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate2 = { name: 'ɵɵstylePropInterpolate2', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate3 = { name: 'ɵɵstylePropInterpolate3', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate4 = { name: 'ɵɵstylePropInterpolate4', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate5 = { name: 'ɵɵstylePropInterpolate5', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate6 = { name: 'ɵɵstylePropInterpolate6', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate7 = { name: 'ɵɵstylePropInterpolate7', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolate8 = { name: 'ɵɵstylePropInterpolate8', moduleName: CORE$1 };
Identifiers$1.stylePropInterpolateV = { name: 'ɵɵstylePropInterpolateV', moduleName: CORE$1 };
Identifiers$1.nextContext = { name: 'ɵɵnextContext', moduleName: CORE$1 };
Identifiers$1.templateCreate = { name: 'ɵɵtemplate', moduleName: CORE$1 };
Identifiers$1.text = { name: 'ɵɵtext', moduleName: CORE$1 };
Identifiers$1.enableBindings = { name: 'ɵɵenableBindings', moduleName: CORE$1 };
Identifiers$1.disableBindings = { name: 'ɵɵdisableBindings', moduleName: CORE$1 };
Identifiers$1.getCurrentView = { name: 'ɵɵgetCurrentView', moduleName: CORE$1 };
Identifiers$1.textInterpolate = { name: 'ɵɵtextInterpolate', moduleName: CORE$1 };
Identifiers$1.textInterpolate1 = { name: 'ɵɵtextInterpolate1', moduleName: CORE$1 };
Identifiers$1.textInterpolate2 = { name: 'ɵɵtextInterpolate2', moduleName: CORE$1 };
Identifiers$1.textInterpolate3 = { name: 'ɵɵtextInterpolate3', moduleName: CORE$1 };
Identifiers$1.textInterpolate4 = { name: 'ɵɵtextInterpolate4', moduleName: CORE$1 };
Identifiers$1.textInterpolate5 = { name: 'ɵɵtextInterpolate5', moduleName: CORE$1 };
Identifiers$1.textInterpolate6 = { name: 'ɵɵtextInterpolate6', moduleName: CORE$1 };
Identifiers$1.textInterpolate7 = { name: 'ɵɵtextInterpolate7', moduleName: CORE$1 };
Identifiers$1.textInterpolate8 = { name: 'ɵɵtextInterpolate8', moduleName: CORE$1 };
Identifiers$1.textInterpolateV = { name: 'ɵɵtextInterpolateV', moduleName: CORE$1 };
Identifiers$1.restoreView = { name: 'ɵɵrestoreView', moduleName: CORE$1 };
Identifiers$1.pureFunction0 = { name: 'ɵɵpureFunction0', moduleName: CORE$1 };
Identifiers$1.pureFunction1 = { name: 'ɵɵpureFunction1', moduleName: CORE$1 };
Identifiers$1.pureFunction2 = { name: 'ɵɵpureFunction2', moduleName: CORE$1 };
Identifiers$1.pureFunction3 = { name: 'ɵɵpureFunction3', moduleName: CORE$1 };
Identifiers$1.pureFunction4 = { name: 'ɵɵpureFunction4', moduleName: CORE$1 };
Identifiers$1.pureFunction5 = { name: 'ɵɵpureFunction5', moduleName: CORE$1 };
Identifiers$1.pureFunction6 = { name: 'ɵɵpureFunction6', moduleName: CORE$1 };
Identifiers$1.pureFunction7 = { name: 'ɵɵpureFunction7', moduleName: CORE$1 };
Identifiers$1.pureFunction8 = { name: 'ɵɵpureFunction8', moduleName: CORE$1 };
Identifiers$1.pureFunctionV = { name: 'ɵɵpureFunctionV', moduleName: CORE$1 };
Identifiers$1.pipeBind1 = { name: 'ɵɵpipeBind1', moduleName: CORE$1 };
Identifiers$1.pipeBind2 = { name: 'ɵɵpipeBind2', moduleName: CORE$1 };
Identifiers$1.pipeBind3 = { name: 'ɵɵpipeBind3', moduleName: CORE$1 };
Identifiers$1.pipeBind4 = { name: 'ɵɵpipeBind4', moduleName: CORE$1 };
Identifiers$1.pipeBindV = { name: 'ɵɵpipeBindV', moduleName: CORE$1 };
Identifiers$1.hostProperty = { name: 'ɵɵhostProperty', moduleName: CORE$1 };
Identifiers$1.property = { name: 'ɵɵproperty', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate = { name: 'ɵɵpropertyInterpolate', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate1 = { name: 'ɵɵpropertyInterpolate1', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate2 = { name: 'ɵɵpropertyInterpolate2', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate3 = { name: 'ɵɵpropertyInterpolate3', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate4 = { name: 'ɵɵpropertyInterpolate4', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate5 = { name: 'ɵɵpropertyInterpolate5', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate6 = { name: 'ɵɵpropertyInterpolate6', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate7 = { name: 'ɵɵpropertyInterpolate7', moduleName: CORE$1 };
Identifiers$1.propertyInterpolate8 = { name: 'ɵɵpropertyInterpolate8', moduleName: CORE$1 };
Identifiers$1.propertyInterpolateV = { name: 'ɵɵpropertyInterpolateV', moduleName: CORE$1 };
Identifiers$1.i18n = { name: 'ɵɵi18n', moduleName: CORE$1 };
Identifiers$1.i18nAttributes = { name: 'ɵɵi18nAttributes', moduleName: CORE$1 };
Identifiers$1.i18nExp = { name: 'ɵɵi18nExp', moduleName: CORE$1 };
Identifiers$1.i18nStart = { name: 'ɵɵi18nStart', moduleName: CORE$1 };
Identifiers$1.i18nEnd = { name: 'ɵɵi18nEnd', moduleName: CORE$1 };
Identifiers$1.i18nApply = { name: 'ɵɵi18nApply', moduleName: CORE$1 };
Identifiers$1.i18nPostprocess = { name: 'ɵɵi18nPostprocess', moduleName: CORE$1 };
Identifiers$1.pipe = { name: 'ɵɵpipe', moduleName: CORE$1 };
Identifiers$1.projection = { name: 'ɵɵprojection', moduleName: CORE$1 };
Identifiers$1.projectionDef = { name: 'ɵɵprojectionDef', moduleName: CORE$1 };
Identifiers$1.reference = { name: 'ɵɵreference', moduleName: CORE$1 };
Identifiers$1.inject = { name: 'ɵɵinject', moduleName: CORE$1 };
Identifiers$1.injectAttribute = { name: 'ɵɵinjectAttribute', moduleName: CORE$1 };
Identifiers$1.injectPipeChangeDetectorRef = { name: 'ɵɵinjectPipeChangeDetectorRef', moduleName: CORE$1 };
Identifiers$1.directiveInject = { name: 'ɵɵdirectiveInject', moduleName: CORE$1 };
Identifiers$1.invalidFactory = { name: 'ɵɵinvalidFactory', moduleName: CORE$1 };
Identifiers$1.invalidFactoryDep = { name: 'ɵɵinvalidFactoryDep', moduleName: CORE$1 };
Identifiers$1.templateRefExtractor = { name: 'ɵɵtemplateRefExtractor', moduleName: CORE$1 };
Identifiers$1.resolveWindow = { name: 'ɵɵresolveWindow', moduleName: CORE$1 };
Identifiers$1.resolveDocument = { name: 'ɵɵresolveDocument', moduleName: CORE$1 };
Identifiers$1.resolveBody = { name: 'ɵɵresolveBody', moduleName: CORE$1 };
Identifiers$1.defineComponent = { name: 'ɵɵdefineComponent', moduleName: CORE$1 };
Identifiers$1.setComponentScope = { name: 'ɵɵsetComponentScope', moduleName: CORE$1 };
Identifiers$1.ComponentDefWithMeta = {
name: 'ɵɵComponentDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.FactoryDef = {
name: 'ɵɵFactoryDef',
moduleName: CORE$1,
};
Identifiers$1.defineDirective = {
name: 'ɵɵdefineDirective',
moduleName: CORE$1,
};
Identifiers$1.DirectiveDefWithMeta = {
name: 'ɵɵDirectiveDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.InjectorDef = {
name: 'ɵɵInjectorDef',
moduleName: CORE$1,
};
Identifiers$1.defineInjector = {
name: 'ɵɵdefineInjector',
moduleName: CORE$1,
};
Identifiers$1.NgModuleDefWithMeta = {
name: 'ɵɵNgModuleDefWithMeta',
moduleName: CORE$1,
};
Identifiers$1.ModuleWithProviders = {
name: 'ModuleWithProviders',
moduleName: CORE$1,
};
Identifiers$1.defineNgModule = { name: 'ɵɵdefineNgModule', moduleName: CORE$1 };
Identifiers$1.setNgModuleScope = { name: 'ɵɵsetNgModuleScope', moduleName: CORE$1 };
Identifiers$1.PipeDefWithMeta = { name: 'ɵɵPipeDefWithMeta', moduleName: CORE$1 };
Identifiers$1.definePipe = { name: 'ɵɵdefinePipe', moduleName: CORE$1 };
Identifiers$1.queryRefresh = { name: 'ɵɵqueryRefresh', moduleName: CORE$1 };
Identifiers$1.viewQuery = { name: 'ɵɵviewQuery', moduleName: CORE$1 };
Identifiers$1.staticViewQuery = { name: 'ɵɵstaticViewQuery', moduleName: CORE$1 };
Identifiers$1.staticContentQuery = { name: 'ɵɵstaticContentQuery', moduleName: CORE$1 };
Identifiers$1.loadQuery = { name: 'ɵɵloadQuery', moduleName: CORE$1 };
Identifiers$1.contentQuery = { name: 'ɵɵcontentQuery', moduleName: CORE$1 };
Identifiers$1.NgOnChangesFeature = { name: 'ɵɵNgOnChangesFeature', moduleName: CORE$1 };
Identifiers$1.InheritDefinitionFeature = { name: 'ɵɵInheritDefinitionFeature', moduleName: CORE$1 };
Identifiers$1.CopyDefinitionFeature = { name: 'ɵɵCopyDefinitionFeature', moduleName: CORE$1 };
Identifiers$1.ProvidersFeature = { name: 'ɵɵProvidersFeature', moduleName: CORE$1 };
Identifiers$1.listener = { name: 'ɵɵlistener', moduleName: CORE$1 };
Identifiers$1.getFactoryOf = {
name: 'ɵɵgetFactoryOf',
moduleName: CORE$1,
};
Identifiers$1.getInheritedFactory = {
name: 'ɵɵgetInheritedFactory',
moduleName: CORE$1,
};
// sanitization-related functions
Identifiers$1.sanitizeHtml = { name: 'ɵɵsanitizeHtml', moduleName: CORE$1 };
Identifiers$1.sanitizeStyle = { name: 'ɵɵsanitizeStyle', moduleName: CORE$1 };
Identifiers$1.sanitizeResourceUrl = { name: 'ɵɵsanitizeResourceUrl', moduleName: CORE$1 };
Identifiers$1.sanitizeScript = { name: 'ɵɵsanitizeScript', moduleName: CORE$1 };
Identifiers$1.sanitizeUrl = { name: 'ɵɵsanitizeUrl', moduleName: CORE$1 };
Identifiers$1.sanitizeUrlOrResourceUrl = { name: 'ɵɵsanitizeUrlOrResourceUrl', moduleName: CORE$1 };
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Convert an object map with `Expression` values into a `LiteralMapExpr`.
*/
function mapToMapExpression(map) {
const result = Object.keys(map).map(key => ({
key,
// The assertion here is because really TypeScript doesn't allow us to express that if the
// key is present, it will have a value, but this is true in reality.
value: map[key],
quoted: false,
}));
return literalMap(result);
}
/**
* Convert metadata into an `Expression` in the given `OutputContext`.
*
* This operation will handle arrays, references to symbols, or literal `null` or `undefined`.
*/
function convertMetaToOutput(meta, ctx) {
if (Array.isArray(meta)) {
return literalArr(meta.map(entry => convertMetaToOutput(entry, ctx)));
}
if (meta instanceof StaticSymbol) {
return ctx.importExpr(meta);
}
if (meta == null) {
return literal(meta);
}
throw new Error(`Internal error: Unsupported or unknown metadata: ${meta}`);
}
function typeWithParameters(type, numParams) {
let params = null;
if (numParams > 0) {
params = [];
for (let i = 0; i < numParams; i++) {
params.push(DYNAMIC_TYPE);
}
}
return expressionType(type, null, params);
}
const ANIMATE_SYMBOL_PREFIX = '@';
function prepareSyntheticPropertyName(name) {
return `${ANIMATE_SYMBOL_PREFIX}${name}`;
}
function prepareSyntheticListenerName(name, phase) {
return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
}
function isSyntheticPropertyOrListener(name) {
return name.charAt(0) == ANIMATE_SYMBOL_PREFIX;
}
function getSyntheticPropertyName(name) {
// this will strip out listener phase values...
// @foo.start => @foo
const i = name.indexOf('.');
name = i > 0 ? name.substring(0, i) : name;
if (name.charAt(0) !== ANIMATE_SYMBOL_PREFIX) {
name = ANIMATE_SYMBOL_PREFIX + name;
}
return name;
}
function prepareSyntheticListenerFunctionName(name, phase) {
return `animation_${name}_${phase}`;
}
function jitOnlyGuardedExpression(expr) {
const ngJitMode = new ExternalExpr({ name: 'ngJitMode', moduleName: null });
const jitFlagNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(ngJitMode), literal('undefined'));
const jitFlagUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, jitFlagNotDefined, ngJitMode, /* type */ undefined,
/* sourceSpan */ undefined, true);
return new BinaryOperatorExpr(BinaryOperator.And, jitFlagUndefinedOrTrue, expr);
}
function wrapReference(value) {
const wrapped = new WrappedNodeExpr(value);
return { value: wrapped, type: wrapped };
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const $EOF = 0;
const $BSPACE = 8;
const $TAB = 9;
const $LF = 10;
const $VTAB = 11;
const $FF = 12;
const $CR = 13;
const $SPACE = 32;
const $BANG = 33;
const $DQ = 34;
const $HASH = 35;
const $$ = 36;
const $PERCENT = 37;
const $AMPERSAND = 38;
const $SQ = 39;
const $LPAREN = 40;
const $RPAREN = 41;
const $STAR = 42;
const $PLUS = 43;
const $COMMA = 44;
const $MINUS = 45;
const $PERIOD = 46;
const $SLASH = 47;
const $COLON = 58;
const $SEMICOLON = 59;
const $LT = 60;
const $EQ = 61;
const $GT = 62;
const $QUESTION = 63;
const $0 = 48;
const $7 = 55;
const $9 = 57;
const $A = 65;
const $E = 69;
const $F = 70;
const $X = 88;
const $Z = 90;
const $LBRACKET = 91;
const $BACKSLASH = 92;
const $RBRACKET = 93;
const $CARET = 94;
const $_ = 95;
const $a = 97;
const $b = 98;
const $e = 101;
const $f = 102;
const $n = 110;
const $r = 114;
const $t = 116;
const $u = 117;
const $v = 118;
const $x = 120;
const $z = 122;
const $LBRACE = 123;
const $BAR = 124;
const $RBRACE = 125;
const $NBSP = 160;
const $PIPE = 124;
const $TILDA = 126;
const $AT = 64;
const $BT = 96;
function isWhitespace(code) {
return (code >= $TAB && code <= $SPACE) || (code == $NBSP);
}
function isDigit(code) {
return $0 <= code && code <= $9;
}
function isAsciiLetter(code) {
return code >= $a && code <= $z || code >= $A && code <= $Z;
}
function isAsciiHexDigit(code) {
return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
}
function isNewLine(code) {
return code === $LF || code === $CR;
}
function isOctalDigit(code) {
return $0 <= code && code <= $7;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class ParseLocation {
constructor(file, offset, line, col) {
this.file = file;
this.offset = offset;
this.line = line;
this.col = col;
}
toString() {
return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
}
moveBy(delta) {
const source = this.file.content;
const len = source.length;
let offset = this.offset;
let line = this.line;
let col = this.col;
while (offset > 0 && delta < 0) {
offset--;
delta++;
const ch = source.charCodeAt(offset);
if (ch == $LF) {
line--;
const priorLine = source.substr(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
col = priorLine > 0 ? offset - priorLine : offset;
}
else {
col--;
}
}
while (offset < len && delta > 0) {
const ch = source.charCodeAt(offset);
offset++;
delta--;
if (ch == $LF) {
line++;
col = 0;
}
else {
col++;
}
}
return new ParseLocation(this.file, offset, line, col);
}
// Return the source around the location
// Up to `maxChars` or `maxLines` on each side of the location
getContext(maxChars, maxLines) {
const content = this.file.content;
let startOffset = this.offset;
if (startOffset != null) {
if (startOffset > content.length - 1) {
startOffset = content.length - 1;
}
let endOffset = startOffset;
let ctxChars = 0;
let ctxLines = 0;
while (ctxChars < maxChars && startOffset > 0) {
startOffset--;
ctxChars++;
if (content[startOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
ctxChars = 0;
ctxLines = 0;
while (ctxChars < maxChars && endOffset < content.length - 1) {
endOffset++;
ctxChars++;
if (content[endOffset] == '\n') {
if (++ctxLines == maxLines) {
break;
}
}
}
return {
before: content.substring(startOffset, this.offset),
after: content.substring(this.offset, endOffset + 1),
};
}
return null;
}
}
class ParseSourceFile {
constructor(content, url) {
this.content = content;
this.url = url;
}
}
class ParseSourceSpan {
constructor(start, end, details = null) {
this.start = start;
this.end = end;
this.details = details;
}
toString() {
return this.start.file.content.substring(this.start.offset, this.end.offset);
}
}
var ParseErrorLevel;
(function (ParseErrorLevel) {
ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
})(ParseErrorLevel || (ParseErrorLevel = {}));
class ParseError {
constructor(span, msg, level = ParseErrorLevel.ERROR) {
this.span = span;
this.msg = msg;
this.level = level;
}
contextualMessage() {
const ctx = this.span.start.getContext(100, 3);
return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` :
this.msg;
}
toString() {
const details = this.span.details ? `, ${this.span.details}` : '';
return `${this.contextualMessage()}: ${this.span.start}${details}`;
}
}
function typeSourceSpan(kind, type) {
const moduleUrl = identifierModuleUrl(type);
const sourceFileName = moduleUrl != null ? `in ${kind} ${identifierName(type)} in ${moduleUrl}` :
`in ${kind} ${identifierName(type)}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
}
/**
* Generates Source Span object for a given R3 Type for JIT mode.
*
* @param kind Component or Directive.
* @param typeName name of the Component or Directive.
* @param sourceUrl reference to Component or Directive source.
* @returns instance of ParseSourceSpan that represent a given Component or Directive.
*/
function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
const sourceFile = new ParseSourceFile('', sourceFileName);
return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class Text {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor) {
return visitor.visitText(this);
}
}
class BoundText {
constructor(value, sourceSpan, i18n) {
this.value = value;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitBoundText(this);
}
}
class TextAttribute {
constructor(name, value, sourceSpan, valueSpan, i18n) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitTextAttribute(this);
}
}
class BoundAttribute {
constructor(name, type, securityContext, value, unit, sourceSpan, valueSpan, i18n) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.i18n = i18n;
}
static fromBoundElementProperty(prop, i18n) {
return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.valueSpan, i18n);
}
visit(visitor) {
return visitor.visitBoundAttribute(this);
}
}
class BoundEvent {
constructor(name, type, handler, target, phase, sourceSpan, handlerSpan) {
this.name = name;
this.type = type;
this.handler = handler;
this.target = target;
this.phase = phase;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
}
static fromParsedEvent(event) {
const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null;
const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null;
return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan);
}
visit(visitor) {
return visitor.visitBoundEvent(this);
}
}
class Element {
constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.name = name;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.children = children;
this.references = references;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
// If the element is empty then the source span should include any closing tag
if (children.length === 0 && startSourceSpan && endSourceSpan) {
this.sourceSpan = new ParseSourceSpan(sourceSpan.start, endSourceSpan.end);
}
}
visit(visitor) {
return visitor.visitElement(this);
}
}
class Template {
constructor(tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
this.tagName = tagName;
this.attributes = attributes;
this.inputs = inputs;
this.outputs = outputs;
this.templateAttrs = templateAttrs;
this.children = children;
this.references = references;
this.variables = variables;
this.sourceSpan = sourceSpan;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitTemplate(this);
}
}
class Content {
constructor(selector, attributes, sourceSpan, i18n) {
this.selector = selector;
this.attributes = attributes;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
this.name = 'ng-content';
}
visit(visitor) {
return visitor.visitContent(this);
}
}
class Variable {
constructor(name, value, sourceSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
visit(visitor) {
return visitor.visitVariable(this);
}
}
class Reference {
constructor(name, value, sourceSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
visit(visitor) {
return visitor.visitReference(this);
}
}
class Icu {
constructor(vars, placeholders, sourceSpan, i18n) {
this.vars = vars;
this.placeholders = placeholders;
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
visit(visitor) {
return visitor.visitIcu(this);
}
}
class NullVisitor {
visitElement(element) { }
visitTemplate(template) { }
visitContent(content) { }
visitVariable(variable) { }
visitReference(reference) { }
visitTextAttribute(attribute) { }
visitBoundAttribute(attribute) { }
visitBoundEvent(attribute) { }
visitText(text) { }
visitBoundText(text) { }
visitIcu(icu) { }
}
class RecursiveVisitor {
visitElement(element) {
visitAll(this, element.attributes);
visitAll(this, element.children);
visitAll(this, element.references);
}
visitTemplate(template) {
visitAll(this, template.attributes);
visitAll(this, template.children);
visitAll(this, template.references);
visitAll(this, template.variables);
}
visitContent(content) { }
visitVariable(variable) { }
visitReference(reference) { }
visitTextAttribute(attribute) { }
visitBoundAttribute(attribute) { }
visitBoundEvent(attribute) { }
visitText(text) { }
visitBoundText(text) { }
visitIcu(icu) { }
}
class TransformVisitor {
visitElement(element) {
const newAttributes = transformAll(this, element.attributes);
const newInputs = transformAll(this, element.inputs);
const newOutputs = transformAll(this, element.outputs);
const newChildren = transformAll(this, element.children);
const newReferences = transformAll(this, element.references);
if (newAttributes != element.attributes || newInputs != element.inputs ||
newOutputs != element.outputs || newChildren != element.children ||
newReferences != element.references) {
return new Element(element.name, newAttributes, newInputs, newOutputs, newChildren, newReferences, element.sourceSpan, element.startSourceSpan, element.endSourceSpan);
}
return element;
}
visitTemplate(template) {
const newAttributes = transformAll(this, template.attributes);
const newInputs = transformAll(this, template.inputs);
const newOutputs = transformAll(this, template.outputs);
const newTemplateAttrs = transformAll(this, template.templateAttrs);
const newChildren = transformAll(this, template.children);
const newReferences = transformAll(this, template.references);
const newVariables = transformAll(this, template.variables);
if (newAttributes != template.attributes || newInputs != template.inputs ||
newOutputs != template.outputs || newTemplateAttrs != template.templateAttrs ||
newChildren != template.children || newReferences != template.references ||
newVariables != template.variables) {
return new Template(template.tagName, newAttributes, newInputs, newOutputs, newTemplateAttrs, newChildren, newReferences, newVariables, template.sourceSpan, template.startSourceSpan, template.endSourceSpan);
}
return template;
}
visitContent(content) {
return content;
}
visitVariable(variable) {
return variable;
}
visitReference(reference) {
return reference;
}
visitTextAttribute(attribute) {
return attribute;
}
visitBoundAttribute(attribute) {
return attribute;
}
visitBoundEvent(attribute) {
return attribute;
}
visitText(text) {
return text;
}
visitBoundText(text) {
return text;
}
visitIcu(icu) {
return icu;
}
}
function visitAll(visitor, nodes) {
const result = [];
if (visitor.visit) {
for (const node of nodes) {
const newNode = visitor.visit(node) || node.visit(visitor);
}
}
else {
for (const node of nodes) {
const newNode = node.visit(visitor);
if (newNode) {
result.push(newNode);
}
}
}
return result;
}
function transformAll(visitor, nodes) {
const result = [];
let changed = false;
for (const node of nodes) {
const newNode = node.visit(visitor);
if (newNode) {
result.push(newNode);
}
changed = changed || newNode != node;
}
return changed ? result : nodes;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class Message {
/**
* @param nodes message AST
* @param placeholders maps placeholder names to static content
* @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)
* @param meaning
* @param description
* @param customId
*/
constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) {
this.nodes = nodes;
this.placeholders = placeholders;
this.placeholderToMessage = placeholderToMessage;
this.meaning = meaning;
this.description = description;
this.customId = customId;
this.id = this.customId;
/** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */
this.legacyIds = [];
if (nodes.length) {
this.sources = [{
filePath: nodes[0].sourceSpan.start.file.url,
startLine: nodes[0].sourceSpan.start.line + 1,
startCol: nodes[0].sourceSpan.start.col + 1,
endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
endCol: nodes[0].sourceSpan.start.col + 1
}];
}
else {
this.sources = [];
}
}
}
class Text$1 {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitText(this, context);
}
}
// TODO(vicb): do we really need this node (vs an array) ?
class Container {
constructor(children, sourceSpan) {
this.children = children;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitContainer(this, context);
}
}
class Icu$1 {
constructor(expression, type, cases, sourceSpan) {
this.expression = expression;
this.type = type;
this.cases = cases;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitIcu(this, context);
}
}
class TagPlaceholder {
constructor(tag, attrs, startName, closeName, children, isVoid, sourceSpan) {
this.tag = tag;
this.attrs = attrs;
this.startName = startName;
this.closeName = closeName;
this.children = children;
this.isVoid = isVoid;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitTagPlaceholder(this, context);
}
}
class Placeholder {
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitPlaceholder(this, context);
}
}
class IcuPlaceholder {
constructor(value, name, sourceSpan) {
this.value = value;
this.name = name;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitIcuPlaceholder(this, context);
}
}
// Clone the AST
class CloneVisitor {
visitText(text, context) {
return new Text$1(text.value, text.sourceSpan);
}
visitContainer(container, context) {
const children = container.children.map(n => n.visit(this, context));
return new Container(children, container.sourceSpan);
}
visitIcu(icu, context) {
const cases = {};
Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context));
const msg = new Icu$1(icu.expression, icu.type, cases, icu.sourceSpan);
msg.expressionPlaceholder = icu.expressionPlaceholder;
return msg;
}
visitTagPlaceholder(ph, context) {
const children = ph.children.map(n => n.visit(this, context));
return new TagPlaceholder(ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan);
}
visitPlaceholder(ph, context) {
return new Placeholder(ph.value, ph.name, ph.sourceSpan);
}
visitIcuPlaceholder(ph, context) {
return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
}
}
// Visit all the nodes recursively
class RecurseVisitor {
visitText(text, context) { }
visitContainer(container, context) {
container.children.forEach(child => child.visit(this));
}
visitIcu(icu, context) {
Object.keys(icu.cases).forEach(k => {
icu.cases[k].visit(this);
});
}
visitTagPlaceholder(ph, context) {
ph.children.forEach(child => child.visit(this));
}
visitPlaceholder(ph, context) { }
visitIcuPlaceholder(ph, context) { }
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Return the message id or compute it using the XLIFF1 digest.
*/
function digest(message) {
return message.id || computeDigest(message);
}
/**
* Compute the message id using the XLIFF1 digest.
*/
function computeDigest(message) {
return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
}
/**
* Return the message id or compute it using the XLIFF2/XMB/$localize digest.
*/
function decimalDigest(message) {
return message.id || computeDecimalDigest(message);
}
/**
* Compute the message id using the XLIFF2/XMB/$localize digest.
*/
function computeDecimalDigest(message) {
const visitor = new _SerializerIgnoreIcuExpVisitor();
const parts = message.nodes.map(a => a.visit(visitor, null));
return computeMsgId(parts.join(''), message.meaning);
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* The visitor is also used in the i18n parser tests
*
* @internal
*/
class _SerializerVisitor {
visitText(text, context) {
return text.value;
}
visitContainer(container, context) {
return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
}
visitIcu(icu, context) {
const strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
}
visitTagPlaceholder(ph, context) {
return ph.isVoid ?
`` :
`${ph.children.map(child => child.visit(this)).join(', ')}`;
}
visitPlaceholder(ph, context) {
return ph.value ? `${ph.value}` : ``;
}
visitIcuPlaceholder(ph, context) {
return `${ph.value.visit(this)}`;
}
}
const serializerVisitor = new _SerializerVisitor();
function serializeNodes(nodes) {
return nodes.map(a => a.visit(serializerVisitor, null));
}
/**
* Serialize the i18n ast to something xml-like in order to generate an UID.
*
* Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
*
* @internal
*/
class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
visitIcu(icu, context) {
let strCases = Object.keys(icu.cases).map((k) => `${k} {${icu.cases[k].visit(this)}}`);
// Do not take the expression into account
return `{${icu.type}, ${strCases.join(', ')}}`;
}
}
/**
* Compute the SHA1 of the given string
*
* see http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
*
* WARNING: this function has not been designed not tested with security in mind.
* DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
*/
function sha1(str) {
const utf8 = utf8Encode(str);
const words32 = stringToWords32(utf8, Endian.Big);
const len = utf8.length * 8;
const w = newArray(80);
let a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476, e = 0xc3d2e1f0;
words32[len >> 5] |= 0x80 << (24 - len % 32);
words32[((len + 64 >> 9) << 4) + 15] = len;
for (let i = 0; i < words32.length; i += 16) {
const h0 = a, h1 = b, h2 = c, h3 = d, h4 = e;
for (let j = 0; j < 80; j++) {
if (j < 16) {
w[j] = words32[i + j];
}
else {
w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
}
const fkVal = fk(j, b, c, d);
const f = fkVal[0];
const k = fkVal[1];
const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
e = d;
d = c;
c = rol32(b, 30);
b = a;
a = temp;
}
a = add32(a, h0);
b = add32(b, h1);
c = add32(c, h2);
d = add32(d, h3);
e = add32(e, h4);
}
return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
}
function fk(index, b, c, d) {
if (index < 20) {
return [(b & c) | (~b & d), 0x5a827999];
}
if (index < 40) {
return [b ^ c ^ d, 0x6ed9eba1];
}
if (index < 60) {
return [(b & c) | (b & d) | (c & d), 0x8f1bbcdc];
}
return [b ^ c ^ d, 0xca62c1d6];
}
/**
* Compute the fingerprint of the given string
*
* The output is 64 bit number encoded as a decimal string
*
* based on:
* https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
*/
function fingerprint(str) {
const utf8 = utf8Encode(str);
let hi = hash32(utf8, 0);
let lo = hash32(utf8, 102072);
if (hi == 0 && (lo == 0 || lo == 1)) {
hi = hi ^ 0x130f9bef;
lo = lo ^ -0x6b5f56d8;
}
return [hi, lo];
}
function computeMsgId(msg, meaning = '') {
let msgFingerprint = fingerprint(msg);
if (meaning) {
const meaningFingerprint = fingerprint(meaning);
msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint);
}
const hi = msgFingerprint[0];
const lo = msgFingerprint[1];
return byteStringToDecString(words32ToByteString([hi & 0x7fffffff, lo]));
}
function hash32(str, c) {
let a = 0x9e3779b9, b = 0x9e3779b9;
let i;
const len = str.length;
for (i = 0; i + 12 <= len; i += 12) {
a = add32(a, wordAt(str, i, Endian.Little));
b = add32(b, wordAt(str, i + 4, Endian.Little));
c = add32(c, wordAt(str, i + 8, Endian.Little));
const res = mix(a, b, c);
a = res[0], b = res[1], c = res[2];
}
a = add32(a, wordAt(str, i, Endian.Little));
b = add32(b, wordAt(str, i + 4, Endian.Little));
// the first byte of c is reserved for the length
c = add32(c, len);
c = add32(c, wordAt(str, i + 8, Endian.Little) << 8);
return mix(a, b, c)[2];
}
// clang-format off
function mix(a, b, c) {
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 13;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 8;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 13;
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 12;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 16;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 5;
a = sub32(a, b);
a = sub32(a, c);
a ^= c >>> 3;
b = sub32(b, c);
b = sub32(b, a);
b ^= a << 10;
c = sub32(c, a);
c = sub32(c, b);
c ^= b >>> 15;
return [a, b, c];
}
// clang-format on
// Utils
var Endian;
(function (Endian) {
Endian[Endian["Little"] = 0] = "Little";
Endian[Endian["Big"] = 1] = "Big";
})(Endian || (Endian = {}));
function add32(a, b) {
return add32to64(a, b)[1];
}
function add32to64(a, b) {
const low = (a & 0xffff) + (b & 0xffff);
const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
return [high >>> 16, (high << 16) | (low & 0xffff)];
}
function add64(a, b) {
const ah = a[0], al = a[1];
const bh = b[0], bl = b[1];
const result = add32to64(al, bl);
const carry = result[0];
const l = result[1];
const h = add32(add32(ah, bh), carry);
return [h, l];
}
function sub32(a, b) {
const low = (a & 0xffff) - (b & 0xffff);
const high = (a >> 16) - (b >> 16) + (low >> 16);
return (high << 16) | (low & 0xffff);
}
// Rotate a 32b number left `count` position
function rol32(a, count) {
return (a << count) | (a >>> (32 - count));
}
// Rotate a 64b number left `count` position
function rol64(num, count) {
const hi = num[0], lo = num[1];
const h = (hi << count) | (lo >>> (32 - count));
const l = (lo << count) | (hi >>> (32 - count));
return [h, l];
}
function stringToWords32(str, endian) {
const size = (str.length + 3) >>> 2;
const words32 = [];
for (let i = 0; i < size; i++) {
words32[i] = wordAt(str, i * 4, endian);
}
return words32;
}
function byteAt(str, index) {
return index >= str.length ? 0 : str.charCodeAt(index) & 0xff;
}
function wordAt(str, index, endian) {
let word = 0;
if (endian === Endian.Big) {
for (let i = 0; i < 4; i++) {
word += byteAt(str, index + i) << (24 - 8 * i);
}
}
else {
for (let i = 0; i < 4; i++) {
word += byteAt(str, index + i) << 8 * i;
}
}
return word;
}
function words32ToByteString(words32) {
return words32.reduce((str, word) => str + word32ToByteString(word), '');
}
function word32ToByteString(word) {
let str = '';
for (let i = 0; i < 4; i++) {
str += String.fromCharCode((word >>> 8 * (3 - i)) & 0xff);
}
return str;
}
function byteStringToHexString(str) {
let hex = '';
for (let i = 0; i < str.length; i++) {
const b = byteAt(str, i);
hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16);
}
return hex.toLowerCase();
}
// based on http://www.danvk.org/hex2dec.html (JS can not handle more than 56b)
function byteStringToDecString(str) {
let decimal = '';
let toThePower = '1';
for (let i = str.length - 1; i >= 0; i--) {
decimal = addBigInt(decimal, numberTimesBigInt(byteAt(str, i), toThePower));
toThePower = numberTimesBigInt(256, toThePower);
}
return decimal.split('').reverse().join('');
}
// x and y decimal, lowest significant digit first
function addBigInt(x, y) {
let sum = '';
const len = Math.max(x.length, y.length);
for (let i = 0, carry = 0; i < len || carry; i++) {
const tmpSum = carry + +(x[i] || 0) + +(y[i] || 0);
if (tmpSum >= 10) {
carry = 1;
sum += tmpSum - 10;
}
else {
carry = 0;
sum += tmpSum;
}
}
return sum;
}
function numberTimesBigInt(num, b) {
let product = '';
let bToThePower = b;
for (; num !== 0; num = num >>> 1) {
if (num & 1)
product = addBigInt(product, bToThePower);
bToThePower = addBigInt(bToThePower, bToThePower);
}
return product;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class Serializer {
// Creates a name mapper, see `PlaceholderMapper`
// Returning `null` means that no name mapping is used.
createNameMapper(message) {
return null;
}
}
/**
* A simple mapper that take a function to transform an internal name to a public name
*/
class SimplePlaceholderMapper extends RecurseVisitor {
// create a mapping from the message
constructor(message, mapName) {
super();
this.mapName = mapName;
this.internalToPublic = {};
this.publicToNextId = {};
this.publicToInternal = {};
message.nodes.forEach(node => node.visit(this));
}
toPublicName(internalName) {
return this.internalToPublic.hasOwnProperty(internalName) ?
this.internalToPublic[internalName] :
null;
}
toInternalName(publicName) {
return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] :
null;
}
visitText(text, context) {
return null;
}
visitTagPlaceholder(ph, context) {
this.visitPlaceholderName(ph.startName);
super.visitTagPlaceholder(ph, context);
this.visitPlaceholderName(ph.closeName);
}
visitPlaceholder(ph, context) {
this.visitPlaceholderName(ph.name);
}
visitIcuPlaceholder(ph, context) {
this.visitPlaceholderName(ph.name);
}
// XMB placeholders could only contains A-Z, 0-9 and _
visitPlaceholderName(internalName) {
if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) {
return;
}
let publicName = this.mapName(internalName);
if (this.publicToInternal.hasOwnProperty(publicName)) {
// Create a new XMB when it has already been used
const nextId = this.publicToNextId[publicName];
this.publicToNextId[publicName] = nextId + 1;
publicName = `${publicName}_${nextId}`;
}
else {
this.publicToNextId[publicName] = 1;
}
this.internalToPublic[internalName] = publicName;
this.publicToInternal[publicName] = internalName;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class _Visitor {
visitTag(tag) {
const strAttrs = this._serializeAttributes(tag.attrs);
if (tag.children.length == 0) {
return `<${tag.name}${strAttrs}/>`;
}
const strChildren = tag.children.map(node => node.visit(this));
return `<${tag.name}${strAttrs}>${strChildren.join('')}${tag.name}>`;
}
visitText(text) {
return text.value;
}
visitDeclaration(decl) {
return ``;
}
_serializeAttributes(attrs) {
const strAttrs = Object.keys(attrs).map((name) => `${name}="${attrs[name]}"`).join(' ');
return strAttrs.length > 0 ? ' ' + strAttrs : '';
}
visitDoctype(doctype) {
return ``;
}
}
const _visitor = new _Visitor();
function serialize(nodes) {
return nodes.map((node) => node.visit(_visitor)).join('');
}
class Declaration {
constructor(unescapedAttrs) {
this.attrs = {};
Object.keys(unescapedAttrs).forEach((k) => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) {
return visitor.visitDeclaration(this);
}
}
class Doctype {
constructor(rootTag, dtd) {
this.rootTag = rootTag;
this.dtd = dtd;
}
visit(visitor) {
return visitor.visitDoctype(this);
}
}
class Tag {
constructor(name, unescapedAttrs = {}, children = []) {
this.name = name;
this.children = children;
this.attrs = {};
Object.keys(unescapedAttrs).forEach((k) => {
this.attrs[k] = escapeXml(unescapedAttrs[k]);
});
}
visit(visitor) {
return visitor.visitTag(this);
}
}
class Text$2 {
constructor(unescapedValue) {
this.value = escapeXml(unescapedValue);
}
visit(visitor) {
return visitor.visitText(this);
}
}
class CR extends Text$2 {
constructor(ws = 0) {
super(`\n${new Array(ws + 1).join(' ')}`);
}
}
const _ESCAPED_CHARS = [
[/&/g, '&'],
[/"/g, '"'],
[/'/g, '''],
[//g, '>'],
];
// Escape `_ESCAPED_CHARS` characters in the given text with encoded entities
function escapeXml(text) {
return _ESCAPED_CHARS.reduce((text, entry) => text.replace(entry[0], entry[1]), text);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const _MESSAGES_TAG = 'messagebundle';
const _MESSAGE_TAG = 'msg';
const _PLACEHOLDER_TAG = 'ph';
const _EXAMPLE_TAG = 'ex';
const _SOURCE_TAG = 'source';
const _DOCTYPE = `
`;
class Xmb extends Serializer {
write(messages, locale) {
const exampleVisitor = new ExampleVisitor();
const visitor = new _Visitor$1();
let rootNode = new Tag(_MESSAGES_TAG);
messages.forEach(message => {
const attrs = { id: message.id };
if (message.description) {
attrs['desc'] = message.description;
}
if (message.meaning) {
attrs['meaning'] = message.meaning;
}
let sourceTags = [];
message.sources.forEach((source) => {
sourceTags.push(new Tag(_SOURCE_TAG, {}, [new Text$2(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
});
rootNode.children.push(new CR(2), new Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));
});
rootNode.children.push(new CR());
return serialize([
new Declaration({ version: '1.0', encoding: 'UTF-8' }),
new CR(),
new Doctype(_MESSAGES_TAG, _DOCTYPE),
new CR(),
exampleVisitor.addDefaultExamples(rootNode),
new CR(),
]);
}
load(content, url) {
throw new Error('Unsupported');
}
digest(message) {
return digest$1(message);
}
createNameMapper(message) {
return new SimplePlaceholderMapper(message, toPublicName);
}
}
class _Visitor$1 {
visitText(text, context) {
return [new Text$2(text.value)];
}
visitContainer(container, context) {
const nodes = [];
container.children.forEach((node) => nodes.push(...node.visit(this)));
return nodes;
}
visitIcu(icu, context) {
const nodes = [new Text$2(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
Object.keys(icu.cases).forEach((c) => {
nodes.push(new Text$2(`${c} {`), ...icu.cases[c].visit(this), new Text$2(`} `));
});
nodes.push(new Text$2(`}`));
return nodes;
}
visitTagPlaceholder(ph, context) {
const startTagAsText = new Text$2(`<${ph.tag}>`);
const startEx = new Tag(_EXAMPLE_TAG, {}, [startTagAsText]);
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
const startTagPh = new Tag(_PLACEHOLDER_TAG, { name: ph.startName }, [startEx, startTagAsText]);
if (ph.isVoid) {
// void tags have no children nor closing tags
return [startTagPh];
}
const closeTagAsText = new Text$2(`${ph.tag}>`);
const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeTagAsText]);
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
const closeTagPh = new Tag(_PLACEHOLDER_TAG, { name: ph.closeName }, [closeEx, closeTagAsText]);
return [startTagPh, ...this.serialize(ph.children), closeTagPh];
}
visitPlaceholder(ph, context) {
const interpolationAsText = new Text$2(`{{${ph.value}}}`);
// Example tag needs to be not-empty for TC.
const exTag = new Tag(_EXAMPLE_TAG, {}, [interpolationAsText]);
return [
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
new Tag(_PLACEHOLDER_TAG, { name: ph.name }, [exTag, interpolationAsText])
];
}
visitIcuPlaceholder(ph, context) {
const icuExpression = ph.value.expression;
const icuType = ph.value.type;
const icuCases = Object.keys(ph.value.cases).map((value) => value + ' {...}').join(' ');
const icuAsText = new Text$2(`{${icuExpression}, ${icuType}, ${icuCases}}`);
const exTag = new Tag(_EXAMPLE_TAG, {}, [icuAsText]);
return [
// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
new Tag(_PLACEHOLDER_TAG, { name: ph.name }, [exTag, icuAsText])
];
}
serialize(nodes) {
return [].concat(...nodes.map(node => node.visit(this)));
}
}
function digest$1(message) {
return decimalDigest(message);
}
// TC requires at least one non-empty example on placeholders
class ExampleVisitor {
addDefaultExamples(node) {
node.visit(this);
return node;
}
visitTag(tag) {
if (tag.name === _PLACEHOLDER_TAG) {
if (!tag.children || tag.children.length == 0) {
const exText = new Text$2(tag.attrs['name'] || '...');
tag.children = [new Tag(_EXAMPLE_TAG, {}, [exText])];
}
}
else if (tag.children) {
tag.children.forEach(node => node.visit(this));
}
}
visitText(text) { }
visitDeclaration(decl) { }
visitDoctype(doctype) { }
}
// XMB/XTB placeholders can only contain A-Z, 0-9 and _
function toPublicName(internalName) {
return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
const CLOSURE_TRANSLATION_PREFIX = 'MSG_';
/* Prefix for non-`goog.getMsg` i18n-related vars */
const TRANSLATION_PREFIX = 'I18N_';
/** Name of the i18n attributes **/
const I18N_ATTR = 'i18n';
const I18N_ATTR_PREFIX = 'i18n-';
/** Prefix of var expressions used in ICUs */
const I18N_ICU_VAR_PREFIX = 'VAR_';
/** Prefix of ICU expressions for post processing */
const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
/** Placeholder wrapper for i18n expressions **/
const I18N_PLACEHOLDER_SYMBOL = '�';
function isI18nAttribute(name) {
return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
}
function isI18nRootNode(meta) {
return meta instanceof Message;
}
function isSingleI18nIcu(meta) {
return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu$1;
}
function hasI18nMeta(node) {
return !!node.i18n;
}
function hasI18nAttrs(element) {
return element.attrs.some((attr) => isI18nAttribute(attr.name));
}
function icuFromI18nMessage(message) {
return message.nodes[0];
}
function wrapI18nPlaceholder(content, contextId = 0) {
const blockId = contextId > 0 ? `:${contextId}` : '';
return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;
}
function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) {
if (!strings.length)
return '';
let acc = '';
const lastIdx = strings.length - 1;
for (let i = 0; i < lastIdx; i++) {
acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;
}
acc += strings[lastIdx];
return acc;
}
function getSeqNumberGenerator(startsAt = 0) {
let current = startsAt;
return () => current++;
}
function placeholdersToParams(placeholders) {
const params = {};
placeholders.forEach((values, key) => {
params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);
});
return params;
}
function updatePlaceholderMap(map, name, ...values) {
const current = map.get(name) || [];
current.push(...values);
map.set(name, current);
}
function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) {
const startIdx = bindingStartIndex;
const placeholders = new Map();
const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta;
if (node) {
node
.children
.filter((child) => child instanceof Placeholder)
.forEach((child, idx) => {
const content = wrapI18nPlaceholder(startIdx + idx, contextId);
updatePlaceholderMap(placeholders, child.name, content);
});
}
return placeholders;
}
/**
* Format the placeholder names in a map of placeholders to expressions.
*
* The placeholder names are converted from "internal" format (e.g. `START_TAG_DIV_1`) to "external"
* format (e.g. `startTagDiv_1`).
*
* @param params A map of placeholder names to expressions.
* @param useCamelCase whether to camelCase the placeholder name when formatting.
* @returns A new map of formatted placeholder names to expressions.
*/
function i18nFormatPlaceholderNames(params = {}, useCamelCase) {
const _params = {};
if (params && Object.keys(params).length) {
Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);
}
return _params;
}
/**
* Converts internal placeholder names to public-facing format
* (for example to use in goog.getMsg call).
* Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.
*
* @param name The placeholder name that should be formatted
* @returns Formatted placeholder name
*/
function formatI18nPlaceholderName(name, useCamelCase = true) {
const publicName = toPublicName(name);
if (!useCamelCase) {
return publicName;
}
const chunks = publicName.split('_');
if (chunks.length === 1) {
// if no "_" found - just lowercase the value
return name.toLowerCase();
}
let postfix;
// eject last element if it's a number
if (/^\d+$/.test(chunks[chunks.length - 1])) {
postfix = chunks.pop();
}
let raw = chunks.shift().toLowerCase();
if (chunks.length) {
raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
}
return postfix ? `${raw}_${postfix}` : raw;
}
/**
* Generates a prefix for translation const name.
*
* @param extra Additional local prefix that should be injected into translation var name
* @returns Complete translation const prefix
*/
function getTranslationConstPrefix(extra) {
return `${CLOSURE_TRANSLATION_PREFIX}${extra}`.toUpperCase();
}
/**
* Generate AST to declare a variable. E.g. `var I18N_1;`.
* @param variable the name of the variable to declare.
*/
function declareI18nVariable(variable) {
return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, null, variable.sourceSpan);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
* quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
* bot work in some cases when object keys are mangled by minifier.
*
* TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
* inputs that contain potentially unsafe chars.
*/
const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
/** Name of the temporary to use during data binding */
const TEMPORARY_NAME = '_t';
/** Name of the context parameter passed into a template function */
const CONTEXT_NAME = 'ctx';
/** Name of the RenderFlag passed into a template function */
const RENDER_FLAGS = 'rf';
/** The prefix reference variables */
const REFERENCE_PREFIX = '_r';
/** The name of the implicit context reference */
const IMPLICIT_REFERENCE = '$implicit';
/** Non bindable attribute name **/
const NON_BINDABLE_ATTR = 'ngNonBindable';
/**
* Creates an allocator for a temporary variable.
*
* A variable declaration is added to the statements the first time the allocator is invoked.
*/
function temporaryAllocator(statements, name) {
let temp = null;
return () => {
if (!temp) {
statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
temp = variable(name);
}
return temp;
};
}
function unsupported(feature) {
if (this) {
throw new Error(`Builder ${this.constructor.name} doesn't support ${feature} yet`);
}
throw new Error(`Feature ${feature} is not supported yet`);
}
function invalid$1(arg) {
throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
}
function asLiteral(value) {
if (Array.isArray(value)) {
return literalArr(value.map(asLiteral));
}
return literal(value, INFERRED_TYPE);
}
function conditionallyCreateMapObjectLiteral(keys, keepDeclared) {
if (Object.getOwnPropertyNames(keys).length > 0) {
return mapToExpression(keys, keepDeclared);
}
return null;
}
function mapToExpression(map, keepDeclared) {
return literalMap(Object.getOwnPropertyNames(map).map(key => {
// canonical syntax: `dirProp: publicProp`
// if there is no `:`, use dirProp = elProp
const value = map[key];
let declaredName;
let publicName;
let minifiedName;
if (Array.isArray(value)) {
[publicName, declaredName] = value;
}
else {
[declaredName, publicName] = splitAtColon(key, [key, value]);
}
minifiedName = declaredName;
return {
key: minifiedName,
// put quotes around keys that contain potentially unsafe characters
quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
value: (keepDeclared && publicName !== declaredName) ?
literalArr([asLiteral(publicName), asLiteral(declaredName)]) :
asLiteral(publicName)
};
}));
}
/**
* Remove trailing null nodes as they are implied.
*/
function trimTrailingNulls(parameters) {
while (isNull(parameters[parameters.length - 1])) {
parameters.pop();
}
return parameters;
}
function getQueryPredicate(query, constantPool) {
if (Array.isArray(query.predicate)) {
let predicate = [];
query.predicate.forEach((selector) => {
// Each item in predicates array may contain strings with comma-separated refs
// (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them
// as separate array entities
const selectors = selector.split(',').map(token => literal(token.trim()));
predicate.push(...selectors);
});
return constantPool.getConstLiteral(literalArr(predicate), true);
}
else {
return query.predicate;
}
}
function noop() { }
class DefinitionMap {
constructor() {
this.values = [];
}
set(key, value) {
if (value) {
this.values.push({ key, value, quoted: false });
}
}
toLiteralMap() {
return literalMap(this.values);
}
}
/**
* Extract a map of properties to values for a given element or template node, which can be used
* by the directive matching machinery.
*
* @param elOrTpl the element or template in question
* @return an object set up for directive matching. For attributes on the element/template, this
* object maps a property name to its (static) value. For any bindings, this map simply maps the
* property name to an empty string.
*/
function getAttrsForDirectiveMatching(elOrTpl) {
const attributesMap = {};
if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
}
else {
elOrTpl.attributes.forEach(a => {
if (!isI18nAttribute(a.name)) {
attributesMap[a.name] = a.value;
}
});
elOrTpl.inputs.forEach(i => {
attributesMap[i.name] = '';
});
elOrTpl.outputs.forEach(o => {
attributesMap[o.name] = '';
});
}
return attributesMap;
}
/** Returns a call expression to a chained instruction, e.g. `property(params[0])(params[1])`. */
function chainedInstruction(reference, calls, span) {
let expression = importExpr(reference, null, span);
if (calls.length > 0) {
for (let i = 0; i < calls.length; i++) {
expression = expression.callFn(calls[i], span);
}
}
else {
// Add a blank invocation, in case the `calls` array is empty.
expression = expression.callFn([], span);
}
return expression;
}
/**
* Gets the number of arguments expected to be passed to a generated instruction in the case of
* interpolation instructions.
* @param interpolation An interpolation ast
*/
function getInterpolationArgsLength(interpolation) {
const { expressions, strings } = interpolation;
if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
// If the interpolation has one interpolated value, but the prefix and suffix are both empty
// strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
// `textInterpolate`.
return 1;
}
else {
return expressions.length + strings.length;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var R3FactoryDelegateType;
(function (R3FactoryDelegateType) {
R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
R3FactoryDelegateType[R3FactoryDelegateType["Factory"] = 2] = "Factory";
})(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
var R3FactoryTarget;
(function (R3FactoryTarget) {
R3FactoryTarget[R3FactoryTarget["Directive"] = 0] = "Directive";
R3FactoryTarget[R3FactoryTarget["Component"] = 1] = "Component";
R3FactoryTarget[R3FactoryTarget["Injectable"] = 2] = "Injectable";
R3FactoryTarget[R3FactoryTarget["Pipe"] = 3] = "Pipe";
R3FactoryTarget[R3FactoryTarget["NgModule"] = 4] = "NgModule";
})(R3FactoryTarget || (R3FactoryTarget = {}));
/**
* Resolved type of a dependency.
*
* Occasionally, dependencies will have special significance which is known statically. In that
* case the `R3ResolvedDependencyType` informs the factory generator that a particular dependency
* should be generated specially (usually by calling a special injection function instead of the
* standard one).
*/
var R3ResolvedDependencyType;
(function (R3ResolvedDependencyType) {
/**
* A normal token dependency.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["Token"] = 0] = "Token";
/**
* The dependency is for an attribute.
*
* The token expression is a string representing the attribute name.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["Attribute"] = 1] = "Attribute";
/**
* Injecting the `ChangeDetectorRef` token. Needs special handling when injected into a pipe.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["ChangeDetectorRef"] = 2] = "ChangeDetectorRef";
/**
* An invalid dependency (no token could be determined). An error should be thrown at runtime.
*/
R3ResolvedDependencyType[R3ResolvedDependencyType["Invalid"] = 3] = "Invalid";
})(R3ResolvedDependencyType || (R3ResolvedDependencyType = {}));
/**
* Construct a factory function expression for the given `R3FactoryMetadata`.
*/
function compileFactoryFunction(meta) {
const t = variable('t');
const statements = [];
let ctorDepsType = NONE_TYPE;
// The type to instantiate via constructor invocation. If there is no delegated factory, meaning
// this type is always created by constructor invocation, then this is the type-to-create
// parameter provided by the user (t) if specified, or the current type if not. If there is a
// delegated factory (which is used to create the current type) then this is only the type-to-
// create parameter (t).
const typeForCtor = !isDelegatedMetadata(meta) ?
new BinaryOperatorExpr(BinaryOperator.Or, t, meta.internalType) :
t;
let ctorExpr = null;
if (meta.deps !== null) {
// There is a constructor (either explicitly or implicitly defined).
if (meta.deps !== 'invalid') {
ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.injectFn, meta.target === R3FactoryTarget.Pipe));
ctorDepsType = createCtorDepsType(meta.deps);
}
}
else {
const baseFactory = variable(`ɵ${meta.name}_BaseFactory`);
const getInheritedFactory = importExpr(Identifiers$1.getInheritedFactory);
const baseFactoryStmt = baseFactory
.set(getInheritedFactory.callFn([meta.internalType], /* sourceSpan */ undefined, /* pure */ true))
.toDeclStmt(INFERRED_TYPE, [StmtModifier.Exported, StmtModifier.Final]);
statements.push(baseFactoryStmt);
// There is no constructor, use the base class' factory to construct typeForCtor.
ctorExpr = baseFactory.callFn([typeForCtor]);
}
const ctorExprFinal = ctorExpr;
const body = [];
let retExpr = null;
function makeConditionalFactory(nonCtorExpr) {
const r = variable('r');
body.push(r.set(NULL_EXPR).toDeclStmt());
let ctorStmt = null;
if (ctorExprFinal !== null) {
ctorStmt = r.set(ctorExprFinal).toStmt();
}
else {
ctorStmt = importExpr(Identifiers$1.invalidFactory).callFn([]).toStmt();
}
body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
return r;
}
if (isDelegatedMetadata(meta) && meta.delegateType === R3FactoryDelegateType.Factory) {
const delegateFactory = variable(`ɵ${meta.name}_BaseFactory`);
const getFactoryOf = importExpr(Identifiers$1.getFactoryOf);
if (meta.delegate.isEquivalent(meta.internalType)) {
throw new Error(`Illegal state: compiling factory that delegates to itself`);
}
const delegateFactoryStmt = delegateFactory.set(getFactoryOf.callFn([meta.delegate])).toDeclStmt(INFERRED_TYPE, [
StmtModifier.Exported, StmtModifier.Final
]);
statements.push(delegateFactoryStmt);
retExpr = makeConditionalFactory(delegateFactory.callFn([]));
}
else if (isDelegatedMetadata(meta)) {
// This type is created with a delegated factory. If a type parameter is not specified, call
// the factory instead.
const delegateArgs = injectDependencies(meta.delegateDeps, meta.injectFn, meta.target === R3FactoryTarget.Pipe);
// Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType.
const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ?
InstantiateExpr :
InvokeFunctionExpr)(meta.delegate, delegateArgs);
retExpr = makeConditionalFactory(factoryExpr);
}
else if (isExpressionFactoryMetadata(meta)) {
// TODO(alxhub): decide whether to lower the value here or in the caller
retExpr = makeConditionalFactory(meta.expression);
}
else {
retExpr = ctorExpr;
}
if (retExpr !== null) {
body.push(new ReturnStatement(retExpr));
}
else {
body.push(importExpr(Identifiers$1.invalidFactory).callFn([]).toStmt());
}
return {
factory: fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`),
statements,
type: expressionType(importExpr(Identifiers$1.FactoryDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]))
};
}
function injectDependencies(deps, injectFn, isPipe) {
return deps.map((dep, index) => compileInjectDependency(dep, injectFn, isPipe, index));
}
function compileInjectDependency(dep, injectFn, isPipe, index) {
// Interpret the dependency according to its resolved type.
switch (dep.resolved) {
case R3ResolvedDependencyType.Token:
case R3ResolvedDependencyType.ChangeDetectorRef:
// Build up the injection flags according to the metadata.
const flags = 0 /* Default */ | (dep.self ? 2 /* Self */ : 0) |
(dep.skipSelf ? 4 /* SkipSelf */ : 0) | (dep.host ? 1 /* Host */ : 0) |
(dep.optional ? 8 /* Optional */ : 0);
// If this dependency is optional or otherwise has non-default flags, then additional
// parameters describing how to inject the dependency must be passed to the inject function
// that's being used.
let flagsParam = (flags !== 0 /* Default */ || dep.optional) ? literal(flags) : null;
// We have a separate instruction for injecting ChangeDetectorRef into a pipe.
if (isPipe && dep.resolved === R3ResolvedDependencyType.ChangeDetectorRef) {
return importExpr(Identifiers$1.injectPipeChangeDetectorRef).callFn(flagsParam ? [flagsParam] : []);
}
// Build up the arguments to the injectFn call.
const injectArgs = [dep.token];
if (flagsParam) {
injectArgs.push(flagsParam);
}
return importExpr(injectFn).callFn(injectArgs);
case R3ResolvedDependencyType.Attribute:
// In the case of attributes, the attribute name in question is given as the token.
return importExpr(Identifiers$1.injectAttribute).callFn([dep.token]);
case R3ResolvedDependencyType.Invalid:
return importExpr(Identifiers$1.invalidFactoryDep).callFn([literal(index)]);
default:
return unsupported(`Unknown R3ResolvedDependencyType: ${R3ResolvedDependencyType[dep.resolved]}`);
}
}
function createCtorDepsType(deps) {
let hasTypes = false;
const attributeTypes = deps.map(dep => {
const type = createCtorDepType(dep);
if (type !== null) {
hasTypes = true;
return type;
}
else {
return literal(null);
}
});
if (hasTypes) {
return expressionType(literalArr(attributeTypes));
}
else {
return NONE_TYPE;
}
}
function createCtorDepType(dep) {
const entries = [];
if (dep.resolved === R3ResolvedDependencyType.Attribute) {
if (dep.attribute !== null) {
entries.push({ key: 'attribute', value: dep.attribute, quoted: false });
}
}
if (dep.optional) {
entries.push({ key: 'optional', value: literal(true), quoted: false });
}
if (dep.host) {
entries.push({ key: 'host', value: literal(true), quoted: false });
}
if (dep.self) {
entries.push({ key: 'self', value: literal(true), quoted: false });
}
if (dep.skipSelf) {
entries.push({ key: 'skipSelf', value: literal(true), quoted: false });
}
return entries.length > 0 ? literalMap(entries) : null;
}
/**
* A helper function useful for extracting `R3DependencyMetadata` from a Render2
* `CompileTypeMetadata` instance.
*/
function dependenciesFromGlobalMetadata(type, outputCtx, reflector) {
// Use the `CompileReflector` to look up references to some well-known Angular types. These will
// be compared with the token to statically determine whether the token has significance to
// Angular, and set the correct `R3ResolvedDependencyType` as a result.
const injectorRef = reflector.resolveExternalReference(Identifiers.Injector);
// Iterate through the type's DI dependencies and produce `R3DependencyMetadata` for each of them.
const deps = [];
for (let dependency of type.diDeps) {
if (dependency.token) {
const tokenRef = tokenReference(dependency.token);
let resolved = dependency.isAttribute ?
R3ResolvedDependencyType.Attribute :
R3ResolvedDependencyType.Token;
// In the case of most dependencies, the token will be a reference to a type. Sometimes,
// however, it can be a string, in the case of older Angular code or @Attribute injection.
const token = tokenRef instanceof StaticSymbol ? outputCtx.importExpr(tokenRef) : literal(tokenRef);
// Construct the dependency.
deps.push({
token,
attribute: null,
resolved,
host: !!dependency.isHost,
optional: !!dependency.isOptional,
self: !!dependency.isSelf,
skipSelf: !!dependency.isSkipSelf,
});
}
else {
unsupported('dependency without a token');
}
}
return deps;
}
function isDelegatedMetadata(meta) {
return meta.delegateType !== undefined;
}
function isExpressionFactoryMetadata(meta) {
return meta.expression !== undefined;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function compileInjectable(meta) {
let result = null;
const factoryMeta = {
name: meta.name,
type: meta.type,
internalType: meta.internalType,
typeArgumentCount: meta.typeArgumentCount,
deps: [],
injectFn: Identifiers.inject,
target: R3FactoryTarget.Injectable,
};
if (meta.useClass !== undefined) {
// meta.useClass has two modes of operation. Either deps are specified, in which case `new` is
// used to instantiate the class with dependencies injected, or deps are not specified and
// the factory of the class is used to instantiate it.
//
// A special case exists for useClass: Type where Type is the injectable type itself and no
// deps are specified, in which case 'useClass' is effectively ignored.
const useClassOnSelf = meta.useClass.isEquivalent(meta.internalType);
let deps = undefined;
if (meta.userDeps !== undefined) {
deps = meta.userDeps;
}
if (deps !== undefined) {
// factory: () => new meta.useClass(...deps)
result = compileFactoryFunction(Object.assign(Object.assign({}, factoryMeta), { delegate: meta.useClass, delegateDeps: deps, delegateType: R3FactoryDelegateType.Class }));
}
else if (useClassOnSelf) {
result = compileFactoryFunction(factoryMeta);
}
else {
result = delegateToFactory(meta.type.value, meta.useClass);
}
}
else if (meta.useFactory !== undefined) {
if (meta.userDeps !== undefined) {
result = compileFactoryFunction(Object.assign(Object.assign({}, factoryMeta), { delegate: meta.useFactory, delegateDeps: meta.userDeps || [], delegateType: R3FactoryDelegateType.Function }));
}
else {
result = {
statements: [],
factory: fn([], [new ReturnStatement(meta.useFactory.callFn([]))])
};
}
}
else if (meta.useValue !== undefined) {
// Note: it's safe to use `meta.useValue` instead of the `USE_VALUE in meta` check used for
// client code because meta.useValue is an Expression which will be defined even if the actual
// value is undefined.
result = compileFactoryFunction(Object.assign(Object.assign({}, factoryMeta), { expression: meta.useValue }));
}
else if (meta.useExisting !== undefined) {
// useExisting is an `inject` call on the existing token.
result = compileFactoryFunction(Object.assign(Object.assign({}, factoryMeta), { expression: importExpr(Identifiers.inject).callFn([meta.useExisting]) }));
}
else {
result = delegateToFactory(meta.type.value, meta.internalType);
}
const token = meta.internalType;
const injectableProps = { token, factory: result.factory };
// Only generate providedIn property if it has a non-null value
if (meta.providedIn.value !== null) {
injectableProps.providedIn = meta.providedIn;
}
const expression = importExpr(Identifiers.ɵɵdefineInjectable).callFn([mapToMapExpression(injectableProps)]);
const type = new ExpressionType(importExpr(Identifiers.InjectableDef, [typeWithParameters(meta.type.type, meta.typeArgumentCount)]));
return {
expression,
type,
statements: result.statements,
};
}
function delegateToFactory(type, internalType) {
return {
statements: [],
// If types are the same, we can generate `factory: type.ɵfac`
// If types are different, we have to generate a wrapper function to ensure
// the internal type has been resolved (`factory: function(t) { return type.ɵfac(t); }`)
factory: type.node === internalType.node ?
internalType.prop('ɵfac') :
fn([new FnParam('t', DYNAMIC_TYPE)], [new ReturnStatement(internalType.callMethod('ɵfac', [variable('t')]))])
};
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function assertArrayOfStrings(identifier, value) {
if (value == null) {
return;
}
if (!Array.isArray(value)) {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
for (let i = 0; i < value.length; i += 1) {
if (typeof value[i] !== 'string') {
throw new Error(`Expected '${identifier}' to be an array of strings.`);
}
}
}
const UNUSABLE_INTERPOLATION_REGEXPS = [
/^\s*$/,
/[<>]/,
/^[{}]$/,
/&(#|[a-z])/i,
/^\/\//,
];
function assertInterpolationSymbols(identifier, value) {
if (value != null && !(Array.isArray(value) && value.length == 2)) {
throw new Error(`Expected '${identifier}' to be an array, [start, end].`);
}
else if (value != null) {
const start = value[0];
const end = value[1];
// Check for unusable interpolation symbols
UNUSABLE_INTERPOLATION_REGEXPS.forEach(regexp => {
if (regexp.test(start) || regexp.test(end)) {
throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`);
}
});
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class InterpolationConfig {
constructor(start, end) {
this.start = start;
this.end = end;
}
static fromArray(markers) {
if (!markers) {
return DEFAULT_INTERPOLATION_CONFIG;
}
assertInterpolationSymbols('interpolation', markers);
return new InterpolationConfig(markers[0], markers[1]);
}
}
const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}');
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
const VERSION = 3;
const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
class SourceMapGenerator {
constructor(file = null) {
this.file = file;
this.sourcesContent = new Map();
this.lines = [];
this.lastCol0 = 0;
this.hasMappings = false;
}
// The content is `null` when the content is expected to be loaded using the URL
addSource(url, content = null) {
if (!this.sourcesContent.has(url)) {
this.sourcesContent.set(url, content);
}
return this;
}
addLine() {
this.lines.push([]);
this.lastCol0 = 0;
return this;
}
addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
if (!this.currentLine) {
throw new Error(`A line must be added before mappings can be added`);
}
if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
throw new Error(`Unknown source file "${sourceUrl}"`);
}
if (col0 == null) {
throw new Error(`The column in the generated code must be provided`);
}
if (col0 < this.lastCol0) {
throw new Error(`Mapping should be added in output order`);
}
if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
throw new Error(`The source location must be provided when a source url is provided`);
}
this.hasMappings = true;
this.lastCol0 = col0;
this.currentLine.push({ col0, sourceUrl, sourceLine0, sourceCol0 });
return this;
}
/**
* @internal strip this from published d.ts files due to
* https://github.com/microsoft/TypeScript/issues/36216
*/
get currentLine() {
return this.lines.slice(-1)[0];
}
toJSON() {
if (!this.hasMappings) {
return null;
}
const sourcesIndex = new Map();
const sources = [];
const sourcesContent = [];
Array.from(this.sourcesContent.keys()).forEach((url, i) => {
sourcesIndex.set(url, i);
sources.push(url);
sourcesContent.push(this.sourcesContent.get(url) || null);
});
let mappings = '';
let lastCol0 = 0;
let lastSourceIndex = 0;
let lastSourceLine0 = 0;
let lastSourceCol0 = 0;
this.lines.forEach(segments => {
lastCol0 = 0;
mappings += segments
.map(segment => {
// zero-based starting column of the line in the generated code
let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
lastCol0 = segment.col0;
if (segment.sourceUrl != null) {
// zero-based index into the “sources” list
segAsStr +=
toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
lastSourceIndex = sourcesIndex.get(segment.sourceUrl);
// the zero-based starting line in the original source
segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
lastSourceLine0 = segment.sourceLine0;
// the zero-based starting column in the original source
segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
lastSourceCol0 = segment.sourceCol0;
}
return segAsStr;
})
.join(',');
mappings += ';';
});
mappings = mappings.slice(0, -1);
return {
'file': this.file || '',
'version': VERSION,
'sourceRoot': '',
'sources': sources,
'sourcesContent': sourcesContent,
'mappings': mappings,
};
}
toJsComment() {
return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) :
'';
}
}
function toBase64String(value) {
let b64 = '';
value = utf8Encode(value);
for (let i = 0; i < value.length;) {
const i1 = value.charCodeAt(i++);
const i2 = value.charCodeAt(i++);
const i3 = value.charCodeAt(i++);
b64 += toBase64Digit(i1 >> 2);
b64 += toBase64Digit(((i1 & 3) << 4) | (isNaN(i2) ? 0 : i2 >> 4));
b64 += isNaN(i2) ? '=' : toBase64Digit(((i2 & 15) << 2) | (i3 >> 6));
b64 += isNaN(i2) || isNaN(i3) ? '=' : toBase64Digit(i3 & 63);
}
return b64;
}
function toBase64VLQ(value) {
value = value < 0 ? ((-value) << 1) + 1 : value << 1;
let out = '';
do {
let digit = value & 31;
value = value >> 5;
if (value > 0) {
digit = digit | 32;
}
out += toBase64Digit(digit);
} while (value > 0);
return out;
}
const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function toBase64Digit(value) {
if (value < 0 || value >= 64) {
throw new Error(`Can only encode value in the range [0, 63]`);
}
return B64_DIGITS[value];
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
const _INDENT_WITH = ' ';
const CATCH_ERROR_VAR$1 = variable('error', null, null);
const CATCH_STACK_VAR$1 = variable('stack', null, null);
class _EmittedLine {
constructor(indent) {
this.indent = indent;
this.partsLength = 0;
this.parts = [];
this.srcSpans = [];
}
}
class EmitterVisitorContext {
constructor(_indent) {
this._indent = _indent;
this._classes = [];
this._preambleLineCount = 0;
this._lines = [new _EmittedLine(_indent)];
}
static createRoot() {
return new EmitterVisitorContext(0);
}
/**
* @internal strip this from published d.ts files due to
* https://github.com/microsoft/TypeScript/issues/36216
*/
get _currentLine() {
return this._lines[this._lines.length - 1];
}
println(from, lastPart = '') {
this.print(from || null, lastPart, true);
}
lineIsEmpty() {
return this._currentLine.parts.length === 0;
}
lineLength() {
return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
}
print(from, part, newLine = false) {
if (part.length > 0) {
this._currentLine.parts.push(part);
this._currentLine.partsLength += part.length;
this._currentLine.srcSpans.push(from && from.sourceSpan || null);
}
if (newLine) {
this._lines.push(new _EmittedLine(this._indent));
}
}
removeEmptyLastLine() {
if (this.lineIsEmpty()) {
this._lines.pop();
}
}
incIndent() {
this._indent++;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
decIndent() {
this._indent--;
if (this.lineIsEmpty()) {
this._currentLine.indent = this._indent;
}
}
pushClass(clazz) {
this._classes.push(clazz);
}
popClass() {
return this._classes.pop();
}
get currentClass() {
return this._classes.length > 0 ? this._classes[this._classes.length - 1] : null;
}
toSource() {
return this.sourceLines
.map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '')
.join('\n');
}
toSourceMapGenerator(genFilePath, startsAtLine = 0) {
const map = new SourceMapGenerator(genFilePath);
let firstOffsetMapped = false;
const mapFirstOffsetIfNeeded = () => {
if (!firstOffsetMapped) {
// Add a single space so that tools won't try to load the file from disk.
// Note: We are using virtual urls like `ng:///`, so we have to
// provide a content here.
map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
firstOffsetMapped = true;
}
};
for (let i = 0; i < startsAtLine; i++) {
map.addLine();
mapFirstOffsetIfNeeded();
}
this.sourceLines.forEach((line, lineIdx) => {
map.addLine();
const spans = line.srcSpans;
const parts = line.parts;
let col0 = line.indent * _INDENT_WITH.length;
let spanIdx = 0;
// skip leading parts without source spans
while (spanIdx < spans.length && !spans[spanIdx]) {
col0 += parts[spanIdx].length;
spanIdx++;
}
if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
firstOffsetMapped = true;
}
else {
mapFirstOffsetIfNeeded();
}
while (spanIdx < spans.length) {
const span = spans[spanIdx];
const source = span.start.file;
const sourceLine = span.start.line;
const sourceCol = span.start.col;
map.addSource(source.url, source.content)
.addMapping(col0, source.url, sourceLine, sourceCol);
col0 += parts[spanIdx].length;
spanIdx++;
// assign parts without span or the same span to the previous segment
while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
col0 += parts[spanIdx].length;
spanIdx++;
}
}
});
return map;
}
setPreambleLineCount(count) {
return this._preambleLineCount = count;
}
spanOf(line, column) {
const emittedLine = this._lines[line - this._preambleLineCount];
if (emittedLine) {
let columnsLeft = column - _createIndent(emittedLine.indent).length;
for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
const part = emittedLine.parts[partIndex];
if (part.length > columnsLeft) {
return emittedLine.srcSpans[partIndex];
}
columnsLeft -= part.length;
}
}
return null;
}
/**
* @internal strip this from published d.ts files due to
* https://github.com/microsoft/TypeScript/issues/36216
*/
get sourceLines() {
if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
return this._lines.slice(0, -1);
}
return this._lines;
}
}
class AbstractEmitterVisitor {
constructor(_escapeDollarInStrings) {
this._escapeDollarInStrings = _escapeDollarInStrings;
}
visitExpressionStmt(stmt, ctx) {
stmt.expr.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitReturnStmt(stmt, ctx) {
ctx.print(stmt, `return `);
stmt.value.visitExpression(this, ctx);
ctx.println(stmt, ';');
return null;
}
visitIfStmt(stmt, ctx) {
ctx.print(stmt, `if (`);
stmt.condition.visitExpression(this, ctx);
ctx.print(stmt, `) {`);
const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
if (stmt.trueCase.length <= 1 && !hasElseCase) {
ctx.print(stmt, ` `);
this.visitAllStatements(stmt.trueCase, ctx);
ctx.removeEmptyLastLine();
ctx.print(stmt, ` `);
}
else {
ctx.println();
ctx.incIndent();
this.visitAllStatements(stmt.trueCase, ctx);
ctx.decIndent();
if (hasElseCase) {
ctx.println(stmt, `} else {`);
ctx.incIndent();
this.visitAllStatements(stmt.falseCase, ctx);
ctx.decIndent();
}
}
ctx.println(stmt, `}`);
return null;
}
visitThrowStmt(stmt, ctx) {
ctx.print(stmt, `throw `);
stmt.error.visitExpression(this, ctx);
ctx.println(stmt, `;`);
return null;
}
visitCommentStmt(stmt, ctx) {
if (stmt.multiline) {
ctx.println(stmt, `/* ${stmt.comment} */`);
}
else {
stmt.comment.split('\n').forEach((line) => {
ctx.println(stmt, `// ${line}`);
});
}
return null;
}
visitJSDocCommentStmt(stmt, ctx) {
ctx.println(stmt, `/*${stmt.toString()}*/`);
return null;
}
visitWriteVarExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
ctx.print(expr, `${expr.name} = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitWriteKeyExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
expr.receiver.visitExpression(this, ctx);
ctx.print(expr, `[`);
expr.index.visitExpression(this, ctx);
ctx.print(expr, `] = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitWritePropExpr(expr, ctx) {
const lineWasEmpty = ctx.lineIsEmpty();
if (!lineWasEmpty) {
ctx.print(expr, '(');
}
expr.receiver.visitExpression(this, ctx);
ctx.print(expr, `.${expr.name} = `);
expr.value.visitExpression(this, ctx);
if (!lineWasEmpty) {
ctx.print(expr, ')');
}
return null;
}
visitInvokeMethodExpr(expr, ctx) {
expr.receiver.visitExpression(this, ctx);
let name = expr.name;
if (expr.builtin != null) {
name = this.getBuiltinMethodName(expr.builtin);
if (name == null) {
// some builtins just mean to skip the call.
return null;
}
}
ctx.print(expr, `.${name}(`);
this.visitAllExpressions(expr.args, ctx, `,`);
ctx.print(expr, `)`);
return null;
}
visitInvokeFunctionExpr(expr, ctx) {
expr.fn.visitExpression(this, ctx);
ctx.print(expr, `(`);
this.visitAllExpressions(expr.args, ctx, ',');
ctx.print(expr, `)`);
return null;
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
}
visitTypeofExpr(expr, ctx) {
ctx.print(expr, 'typeof ');
expr.expr.visitExpression(this, ctx);
}
visitReadVarExpr(ast, ctx) {
let varName = ast.name;
if (ast.builtin != null) {
switch (ast.builtin) {
case BuiltinVar.Super:
varName = 'super';
break;
case BuiltinVar.This:
varName = 'this';
break;
case BuiltinVar.CatchError:
varName = CATCH_ERROR_VAR$1.name;
break;
case BuiltinVar.CatchStack:
varName = CATCH_STACK_VAR$1.name;
break;
default:
throw new Error(`Unknown builtin variable ${ast.builtin}`);
}
}
ctx.print(ast, varName);
return null;
}
visitInstantiateExpr(ast, ctx) {
ctx.print(ast, `new `);
ast.classExpr.visitExpression(this, ctx);
ctx.print(ast, `(`);
this.visitAllExpressions(ast.args, ctx, ',');
ctx.print(ast, `)`);
return null;
}
visitLiteralExpr(ast, ctx) {
const value = ast.value;
if (typeof value === 'string') {
ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
}
else {
ctx.print(ast, `${value}`);
}
return null;
}
visitLocalizedString(ast, ctx) {
const head = ast.serializeI18nHead();
ctx.print(ast, '$localize `' + head.raw);
for (let i = 1; i < ast.messageParts.length; i++) {
ctx.print(ast, '${');
ast.expressions[i - 1].visitExpression(this, ctx);
ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);
}
ctx.print(ast, '`');
return null;
}
visitConditionalExpr(ast, ctx) {
ctx.print(ast, `(`);
ast.condition.visitExpression(this, ctx);
ctx.print(ast, '? ');
ast.trueCase.visitExpression(this, ctx);
ctx.print(ast, ': ');
ast.falseCase.visitExpression(this, ctx);
ctx.print(ast, `)`);
return null;
}
visitNotExpr(ast, ctx) {
ctx.print(ast, '!');
ast.condition.visitExpression(this, ctx);
return null;
}
visitAssertNotNullExpr(ast, ctx) {
ast.condition.visitExpression(this, ctx);
return null;
}
visitBinaryOperatorExpr(ast, ctx) {
let opStr;
switch (ast.operator) {
case BinaryOperator.Equals:
opStr = '==';
break;
case BinaryOperator.Identical:
opStr = '===';
break;
case BinaryOperator.NotEquals:
opStr = '!=';
break;
case BinaryOperator.NotIdentical:
opStr = '!==';
break;
case BinaryOperator.And:
opStr = '&&';
break;
case BinaryOperator.BitwiseAnd:
opStr = '&';
break;
case BinaryOperator.Or:
opStr = '||';
break;
case BinaryOperator.Plus:
opStr = '+';
break;
case BinaryOperator.Minus:
opStr = '-';
break;
case BinaryOperator.Divide:
opStr = '/';
break;
case BinaryOperator.Multiply:
opStr = '*';
break;
case BinaryOperator.Modulo:
opStr = '%';
break;
case BinaryOperator.Lower:
opStr = '<';
break;
case BinaryOperator.LowerEquals:
opStr = '<=';
break;
case BinaryOperator.Bigger:
opStr = '>';
break;
case BinaryOperator.BiggerEquals:
opStr = '>=';
break;
default:
throw new Error(`Unknown operator ${ast.operator}`);
}
if (ast.parens)
ctx.print(ast, `(`);
ast.lhs.visitExpression(this, ctx);
ctx.print(ast, ` ${opStr} `);
ast.rhs.visitExpression(this, ctx);
if (ast.parens)
ctx.print(ast, `)`);
return null;
}
visitReadPropExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `.`);
ctx.print(ast, ast.name);
return null;
}
visitReadKeyExpr(ast, ctx) {
ast.receiver.visitExpression(this, ctx);
ctx.print(ast, `[`);
ast.index.visitExpression(this, ctx);
ctx.print(ast, `]`);
return null;
}
visitLiteralArrayExpr(ast, ctx) {
ctx.print(ast, `[`);
this.visitAllExpressions(ast.entries, ctx, ',');
ctx.print(ast, `]`);
return null;
}
visitLiteralMapExpr(ast, ctx) {
ctx.print(ast, `{`);
this.visitAllObjects(entry => {
ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
entry.value.visitExpression(this, ctx);
}, ast.entries, ctx, ',');
ctx.print(ast, `}`);
return null;
}
visitCommaExpr(ast, ctx) {
ctx.print(ast, '(');
this.visitAllExpressions(ast.parts, ctx, ',');
ctx.print(ast, ')');
return null;
}
visitAllExpressions(expressions, ctx, separator) {
this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
}
visitAllObjects(handler, expressions, ctx, separator) {
let incrementedIndent = false;
for (let i = 0; i < expressions.length; i++) {
if (i > 0) {
if (ctx.lineLength() > 80) {
ctx.print(null, separator, true);
if (!incrementedIndent) {
// continuation are marked with double indent.
ctx.incIndent();
ctx.incIndent();
incrementedIndent = true;
}
}
else {
ctx.print(null, separator, false);
}
}
handler(expressions[i]);
}
if (incrementedIndent) {
// continuation are marked with double indent.
ctx.decIndent();
ctx.decIndent();
}
}
visitAllStatements(statements, ctx) {
statements.forEach((stmt) => stmt.visitStatement(this, ctx));
}
}
function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
if (input == null) {
return null;
}
const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
}
else if (match[0] == '\n') {
return '\\n';
}
else if (match[0] == '\r') {
return '\\r';
}
else {
return `\\${match[0]}`;
}
});
const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
return requiresQuotes ? `'${body}'` : body;
}
function _createIndent(count) {
let res = '';
for (let i = 0; i < count; i++) {
res += _INDENT_WITH;
}
return res;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
constructor() {
super(false);
}
visitDeclareClassStmt(stmt, ctx) {
ctx.pushClass(stmt);
this._visitClassConstructor(stmt, ctx);
if (stmt.parent != null) {
ctx.print(stmt, `${stmt.name}.prototype = Object.create(`);
stmt.parent.visitExpression(this, ctx);
ctx.println(stmt, `.prototype);`);
}
stmt.getters.forEach((getter) => this._visitClassGetter(stmt, getter, ctx));
stmt.methods.forEach((method) => this._visitClassMethod(stmt, method, ctx));
ctx.popClass();
return null;
}
_visitClassConstructor(stmt, ctx) {
ctx.print(stmt, `function ${stmt.name}(`);
if (stmt.constructorMethod != null) {
this._visitParams(stmt.constructorMethod.params, ctx);
}
ctx.println(stmt, `) {`);
ctx.incIndent();
if (stmt.constructorMethod != null) {
if (stmt.constructorMethod.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(stmt.constructorMethod.body, ctx);
}
}
ctx.decIndent();
ctx.println(stmt, `}`);
}
_visitClassGetter(stmt, getter, ctx) {
ctx.println(stmt, `Object.defineProperty(${stmt.name}.prototype, '${getter.name}', { get: function() {`);
ctx.incIndent();
if (getter.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(getter.body, ctx);
}
ctx.decIndent();
ctx.println(stmt, `}});`);
}
_visitClassMethod(stmt, method, ctx) {
ctx.print(stmt, `${stmt.name}.prototype.${method.name} = function(`);
this._visitParams(method.params, ctx);
ctx.println(stmt, `) {`);
ctx.incIndent();
if (method.body.length > 0) {
ctx.println(stmt, `var self = this;`);
this.visitAllStatements(method.body, ctx);
}
ctx.decIndent();
ctx.println(stmt, `};`);
}
visitWrappedNodeExpr(ast, ctx) {
throw new Error('Cannot emit a WrappedNodeExpr in Javascript.');
}
visitReadVarExpr(ast, ctx) {
if (ast.builtin === BuiltinVar.This) {
ctx.print(ast, 'self');
}
else if (ast.builtin === BuiltinVar.Super) {
throw new Error(`'super' needs to be handled at a parent ast node, not at the variable level!`);
}
else {
super.visitReadVarExpr(ast, ctx);
}
return null;
}
visitDeclareVarStmt(stmt, ctx) {
ctx.print(stmt, `var ${stmt.name}`);
if (stmt.value) {
ctx.print(stmt, ' = ');
stmt.value.visitExpression(this, ctx);
}
ctx.println(stmt, `;`);
return null;
}
visitCastExpr(ast, ctx) {
ast.value.visitExpression(this, ctx);
return null;
}
visitInvokeFunctionExpr(expr, ctx) {
const fnExpr = expr.fn;
if (fnExpr instanceof ReadVarExpr && fnExpr.builtin === BuiltinVar.Super) {
ctx.currentClass.parent.visitExpression(this, ctx);
ctx.print(expr, `.call(this`);
if (expr.args.length > 0) {
ctx.print(expr, `, `);
this.visitAllExpressions(expr.args, ctx, ',');
}
ctx.print(expr, `)`);
}
else {
super.visitInvokeFunctionExpr(expr, ctx);
}
return null;
}
visitFunctionExpr(ast, ctx) {
ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);
this._visitParams(ast.params, ctx);
ctx.println(ast, `) {`);
ctx.incIndent();
this.visitAllStatements(ast.statements, ctx);
ctx.decIndent();
ctx.print(ast, `}`);
return null;
}
visitDeclareFunctionStmt(stmt, ctx) {
ctx.print(stmt, `function ${stmt.name}(`);
this._visitParams(stmt.params, ctx);
ctx.println(stmt, `) {`);
ctx.incIndent();
this.visitAllStatements(stmt.statements, ctx);
ctx.decIndent();
ctx.println(stmt, `}`);
return null;
}
visitTryCatchStmt(stmt, ctx) {
ctx.println(stmt, `try {`);
ctx.incIndent();
this.visitAllStatements(stmt.bodyStmts, ctx);
ctx.decIndent();
ctx.println(stmt, `} catch (${CATCH_ERROR_VAR$1.name}) {`);
ctx.incIndent();
const catchStmts = [CATCH_STACK_VAR$1.set(CATCH_ERROR_VAR$1.prop('stack')).toDeclStmt(null, [
StmtModifier.Final
])].concat(stmt.catchStmts);
this.visitAllStatements(catchStmts, ctx);
ctx.decIndent();
ctx.println(stmt, `}`);
return null;
}
visitLocalizedString(ast, ctx) {
// The following convoluted piece of code is effectively the downlevelled equivalent of
// ```
// $localize `...`
// ```
// which is effectively like:
// ```
// $localize(__makeTemplateObject(cooked, raw), expression1, expression2, ...);
// ```
//
// The `$localize` function expects a "template object", which is an array of "cooked" strings
// plus a `raw` property that contains an array of "raw" strings.
//
// In some environments a helper function called `__makeTemplateObject(cooked, raw)` might be
// available, in which case we use that. Otherwise we must create our own helper function
// inline.
//
// In the inline function, if `Object.defineProperty` is available we use that to attach the
// `raw` array.
ctx.print(ast, '$localize((this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})(');
const parts = [ast.serializeI18nHead()];
for (let i = 1; i < ast.messageParts.length; i++) {
parts.push(ast.serializeI18nTemplatePart(i));
}
ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.cooked, false)).join(', ')}], `);
ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.raw, false)).join(', ')}])`);
ast.expressions.forEach(expression => {
ctx.print(ast, ', ');
expression.visitExpression(this, ctx);
});
ctx.print(ast, ')');
return null;
}
_visitParams(params, ctx) {
this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ',');
}
getBuiltinMethodName(method) {
let name;
switch (method) {
case BuiltinMethod.ConcatArray:
name = 'concat';
break;
case BuiltinMethod.SubscribeObservable:
name = 'subscribe';
break;
case BuiltinMethod.Bind:
name = 'bind';
break;
default:
throw new Error(`Unknown builtin method: ${method}`);
}
return name;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A helper class to manage the evaluation of JIT generated code.
*/
class JitEvaluator {
/**
*
* @param sourceUrl The URL of the generated code.
* @param statements An array of Angular statement AST nodes to be evaluated.
* @param reflector A helper used when converting the statements to executable code.
* @param createSourceMaps If true then create a source-map for the generated code and include it
* inline as a source-map comment.
* @returns A map of all the variables in the generated code.
*/
evaluateStatements(sourceUrl, statements, reflector, createSourceMaps) {
const converter = new JitEmitterVisitor(reflector);
const ctx = EmitterVisitorContext.createRoot();
// Ensure generated code is in strict mode
if (statements.length > 0 && !isUseStrictStatement(statements[0])) {
statements = [
literal('use strict').toStmt(),
...statements,
];
}
converter.visitAllStatements(statements, ctx);
converter.createReturnStmt(ctx);
return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
}
/**
* Evaluate a piece of JIT generated code.
* @param sourceUrl The URL of this generated code.
* @param ctx A context object that contains an AST of the code to be evaluated.
* @param vars A map containing the names and values of variables that the evaluated code might
* reference.
* @param createSourceMap If true then create a source-map for the generated code and include it
* inline as a source-map comment.
* @returns The result of evaluating the code.
*/
evaluateCode(sourceUrl, ctx, vars, createSourceMap) {
let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
const fnArgNames = [];
const fnArgValues = [];
for (const argName in vars) {
fnArgValues.push(vars[argName]);
fnArgNames.push(argName);
}
if (createSourceMap) {
// using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
// E.g. ```
// function anonymous(a,b,c
// /**/) { ... }```
// We don't want to hard code this fact, so we auto detect it via an empty function first.
const emptyFn = new Function(...fnArgNames.concat('return null;')).toString();
const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
}
const fn = new Function(...fnArgNames.concat(fnBody));
return this.executeFunction(fn, fnArgValues);
}
/**
* Execute a JIT generated function by calling it.
*
* This method can be overridden in tests to capture the functions that are generated
* by this `JitEvaluator` class.
*
* @param fn A function to execute.
* @param args The arguments to pass to the function being executed.
* @returns The return value of the executed function.
*/
executeFunction(fn, args) {
return fn(...args);
}
}
/**
* An Angular AST visitor that converts AST nodes into executable JavaScript code.
*/
class JitEmitterVisitor extends AbstractJsEmitterVisitor {
constructor(reflector) {
super();
this.reflector = reflector;
this._evalArgNames = [];
this._evalArgValues = [];
this._evalExportedVars = [];
}
createReturnStmt(ctx) {
const stmt = new ReturnStatement(new LiteralMapExpr(this._evalExportedVars.map(resultVar => new LiteralMapEntry(resultVar, variable(resultVar), false))));
stmt.visitStatement(this, ctx);
}
getArgs() {
const result = {};
for (let i = 0; i < this._evalArgNames.length; i++) {
result[this._evalArgNames[i]] = this._evalArgValues[i];
}
return result;
}
visitExternalExpr(ast, ctx) {
this._emitReferenceToExternal(ast, this.reflector.resolveExternalReference(ast.value), ctx);
return null;
}
visitWrappedNodeExpr(ast, ctx) {
this._emitReferenceToExternal(ast, ast.node, ctx);
return null;
}
visitDeclareVarStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareVarStmt(stmt, ctx);
}
visitDeclareFunctionStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareFunctionStmt(stmt, ctx);
}
visitDeclareClassStmt(stmt, ctx) {
if (stmt.hasModifier(StmtModifier.Exported)) {
this._evalExportedVars.push(stmt.name);
}
return super.visitDeclareClassStmt(stmt, ctx);
}
_emitReferenceToExternal(ast, value, ctx) {
let id = this._evalArgValues.indexOf(value);
if (id === -1) {
id = this._evalArgValues.length;
this._evalArgValues.push(value);
const name = identifierName({ reference: value }) || 'val';
this._evalArgNames.push(`jit_${name}_${id}`);
}
ctx.print(ast, this._evalArgNames[id]);
}
}
function isUseStrictStatement(statement) {
return statement.isEquivalent(literal('use strict').toStmt());
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Implementation of `CompileReflector` which resolves references to @angular/core
* symbols at runtime, according to a consumer-provided mapping.
*
* Only supports `resolveExternalReference`, all other methods throw.
*/
class R3JitReflector {
constructor(context) {
this.context = context;
}
resolveExternalReference(ref) {
// This reflector only handles @angular/core imports.
if (ref.moduleName !== '@angular/core') {
throw new Error(`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`);
}
if (!this.context.hasOwnProperty(ref.name)) {
throw new Error(`No value provided for @angular/core symbol '${ref.name}'.`);
}
return this.context[ref.name];
}
parameters(typeOrFunc) {
throw new Error('Not implemented.');
}
annotations(typeOrFunc) {
throw new Error('Not implemented.');
}
shallowAnnotations(typeOrFunc) {
throw new Error('Not implemented.');
}
tryAnnotations(typeOrFunc) {
throw new Error('Not implemented.');
}
propMetadata(typeOrFunc) {
throw new Error('Not implemented.');
}
hasLifecycleHook(type, lcProperty) {
throw new Error('Not implemented.');
}
guards(typeOrFunc) {
throw new Error('Not implemented.');
}
componentModuleUrl(type, cmpMetadata) {
throw new Error('Not implemented.');
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function mapEntry(key, value) {
return { key, value, quoted: false };
}
function mapLiteral(obj, quoted = false) {
return literalMap(Object.keys(obj).map(key => ({
key,
quoted,
value: obj[key],
})));
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
*/
function compileNgModule(meta) {
const { internalType, type: moduleType, bootstrap, declarations, imports, exports, schemas, containsForwardDecls, emitInline, id } = meta;
const additionalStatements = [];
const definitionMap = { type: internalType };
// Only generate the keys in the metadata if the arrays have values.
if (bootstrap.length) {
definitionMap.bootstrap = refsToArray(bootstrap, containsForwardDecls);
}
// If requested to emit scope information inline, pass the declarations, imports and exports to
// the `ɵɵdefineNgModule` call. The JIT compilation uses this.
if (emitInline) {
if (declarations.length) {
definitionMap.declarations = refsToArray(declarations, containsForwardDecls);
}
if (imports.length) {
definitionMap.imports = refsToArray(imports, containsForwardDecls);
}
if (exports.length) {
definitionMap.exports = refsToArray(exports, containsForwardDecls);
}
}
// If not emitting inline, the scope information is not passed into `ɵɵdefineNgModule` as it would
// prevent tree-shaking of the declarations, imports and exports references.
else {
const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);
if (setNgModuleScopeCall !== null) {
additionalStatements.push(setNgModuleScopeCall);
}
}
if (schemas && schemas.length) {
definitionMap.schemas = literalArr(schemas.map(ref => ref.value));
}
if (id) {
definitionMap.id = id;
}
const expression = importExpr(Identifiers$1.defineNgModule).callFn([mapToMapExpression(definitionMap)]);
const type = new ExpressionType(importExpr(Identifiers$1.NgModuleDefWithMeta, [
new ExpressionType(moduleType.type), tupleTypeOf(declarations), tupleTypeOf(imports),
tupleTypeOf(exports)
]));
return { expression, type, additionalStatements };
}
/**
* Generates a function call to `ɵɵsetNgModuleScope` with all necessary information so that the
* transitive module scope can be computed during runtime in JIT mode. This call is marked pure
* such that the references to declarations, imports and exports may be elided causing these
* symbols to become tree-shakeable.
*/
function generateSetNgModuleScopeCall(meta) {
const { adjacentType: moduleType, declarations, imports, exports, containsForwardDecls } = meta;
const scopeMap = {};
if (declarations.length) {
scopeMap.declarations = refsToArray(declarations, containsForwardDecls);
}
if (imports.length) {
scopeMap.imports = refsToArray(imports, containsForwardDecls);
}
if (exports.length) {
scopeMap.exports = refsToArray(exports, containsForwardDecls);
}
if (Object.keys(scopeMap).length === 0) {
return null;
}
// setNgModuleScope(...)
const fnCall = new InvokeFunctionExpr(
/* fn */ importExpr(Identifiers$1.setNgModuleScope),
/* args */ [moduleType, mapToMapExpression(scopeMap)]);
// (ngJitMode guard) && setNgModuleScope(...)
const guardedCall = jitOnlyGuardedExpression(fnCall);
// function() { (ngJitMode guard) && setNgModuleScope(...); }
const iife = new FunctionExpr(
/* params */ [],
/* statements */ [guardedCall.toStmt()]);
// (function() { (ngJitMode guard) && setNgModuleScope(...); })()
const iifeCall = new InvokeFunctionExpr(
/* fn */ iife,
/* args */ []);
return iifeCall.toStmt();
}
function compileInjector(meta) {
const result = compileFactoryFunction({
name: meta.name,
type: meta.type,
internalType: meta.internalType,
typeArgumentCount: 0,
deps: meta.deps,
injectFn: Identifiers$1.inject,
target: R3FactoryTarget.NgModule,
});
const definitionMap = {
factory: result.factory,
};
if (meta.providers !== null) {
definitionMap.providers = meta.providers;
}
if (meta.imports.length > 0) {
definitionMap.imports = literalArr(meta.imports);
}
const expression = importExpr(Identifiers$1.defineInjector).callFn([mapToMapExpression(definitionMap)]);
const type = new ExpressionType(importExpr(Identifiers$1.InjectorDef, [new ExpressionType(meta.type.type)]));
return { expression, type, statements: result.statements };
}
// TODO(alxhub): integrate this with `compileNgModule`. Currently the two are separate operations.
function compileNgModuleFromRender2(ctx, ngModule, injectableCompiler) {
const className = identifierName(ngModule.type);
const rawImports = ngModule.rawImports ? [ngModule.rawImports] : [];
const rawExports = ngModule.rawExports ? [ngModule.rawExports] : [];
const injectorDefArg = mapLiteral({
'factory': injectableCompiler.factoryFor({ type: ngModule.type, symbol: ngModule.type.reference }, ctx),
'providers': convertMetaToOutput(ngModule.rawProviders, ctx),
'imports': convertMetaToOutput([...rawImports, ...rawExports], ctx),
});
const injectorDef = importExpr(Identifiers$1.defineInjector).callFn([injectorDefArg]);
ctx.statements.push(new ClassStmt(
/* name */ className,
/* parent */ null,
/* fields */ [new ClassField(
/* name */ 'ɵinj',
/* type */ INFERRED_TYPE,
/* modifiers */ [StmtModifier.Static],
/* initializer */ injectorDef)],
/* getters */ [],
/* constructorMethod */ new ClassMethod(null, [], []),
/* methods */ []));
}
function accessExportScope(module) {
const selectorScope = new ReadPropExpr(module, 'ɵmod');
return new ReadPropExpr(selectorScope, 'exported');
}
function tupleTypeOf(exp) {
const types = exp.map(ref => typeofExpr(ref.type));
return exp.length > 0 ? expressionType(literalArr(types)) : NONE_TYPE;
}
function refsToArray(refs, shouldForwardDeclare) {
const values = literalArr(refs.map(ref => ref.value));
return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
function compilePipeFromMetadata(metadata) {
const definitionMapValues = [];
// e.g. `name: 'myPipe'`
definitionMapValues.push({ key: 'name', value: literal(metadata.pipeName), quoted: false });
// e.g. `type: MyPipe`
definitionMapValues.push({ key: 'type', value: metadata.type.value, quoted: false });
// e.g. `pure: true`
definitionMapValues.push({ key: 'pure', value: literal(metadata.pure), quoted: false });
const expression = importExpr(Identifiers$1.definePipe).callFn([literalMap(definitionMapValues)]);
const type = new ExpressionType(importExpr(Identifiers$1.PipeDefWithMeta, [
typeWithParameters(metadata.type.type, metadata.typeArgumentCount),
new ExpressionType(new LiteralExpr(metadata.pipeName)),
]));
return { expression, type };
}
/**
* Write a pipe definition to the output context.
*/
function compilePipeFromRender2(outputCtx, pipe, reflector) {
const name = identifierName(pipe.type);
if (!name) {
return error(`Cannot resolve the name of ${pipe.type}`);
}
const type = outputCtx.importExpr(pipe.type.reference);
const metadata = {
name,
type: wrapReference(type),
internalType: type,
pipeName: pipe.name,
typeArgumentCount: 0,
deps: dependenciesFromGlobalMetadata(pipe.type, outputCtx, reflector),
pure: pipe.pure,
};
const res = compilePipeFromMetadata(metadata);
const factoryRes = compileFactoryFunction(Object.assign(Object.assign({}, metadata), { injectFn: Identifiers$1.directiveInject, target: R3FactoryTarget.Pipe }));
const definitionField = outputCtx.constantPool.propertyNameOf(3 /* Pipe */);
const ngFactoryDefStatement = new ClassStmt(
/* name */ name,
/* parent */ null,
/* fields */
[new ClassField(
/* name */ 'ɵfac',
/* type */ INFERRED_TYPE,
/* modifiers */ [StmtModifier.Static],
/* initializer */ factoryRes.factory)],
/* getters */ [],
/* constructorMethod */ new ClassMethod(null, [], []),
/* methods */ []);
const pipeDefStatement = new ClassStmt(
/* name */ name,
/* parent */ null,
/* fields */ [new ClassField(
/* name */ definitionField,
/* type */ INFERRED_TYPE,
/* modifiers */ [StmtModifier.Static],
/* initializer */ res.expression)],
/* getters */ [],
/* constructorMethod */ new ClassMethod(null, [], []),
/* methods */ []);
outputCtx.statements.push(ngFactoryDefStatement, pipeDefStatement);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class ParserError {
constructor(message, input, errLocation, ctxLocation) {
this.input = input;
this.errLocation = errLocation;
this.ctxLocation = ctxLocation;
this.message = `Parser Error: ${message} ${errLocation} [${input}] in ${ctxLocation}`;
}
}
class ParseSpan {
constructor(start, end) {
this.start = start;
this.end = end;
}
toAbsolute(absoluteOffset) {
return new AbsoluteSourceSpan(absoluteOffset + this.start, absoluteOffset + this.end);
}
}
class AST {
constructor(span,
/**
* Absolute location of the expression AST in a source code file.
*/
sourceSpan) {
this.span = span;
this.sourceSpan = sourceSpan;
}
visit(visitor, context = null) {
return null;
}
toString() {
return 'AST';
}
}
class ASTWithName extends AST {
constructor(span, sourceSpan, nameSpan) {
super(span, sourceSpan);
this.nameSpan = nameSpan;
}
}
/**
* Represents a quoted expression of the form:
*
* quote = prefix `:` uninterpretedExpression
* prefix = identifier
* uninterpretedExpression = arbitrary string
*
* A quoted expression is meant to be pre-processed by an AST transformer that
* converts it into another AST that no longer contains quoted expressions.
* It is meant to allow third-party developers to extend Angular template
* expression language. The `uninterpretedExpression` part of the quote is
* therefore not interpreted by the Angular's own expression parser.
*/
class Quote extends AST {
constructor(span, sourceSpan, prefix, uninterpretedExpression, location) {
super(span, sourceSpan);
this.prefix = prefix;
this.uninterpretedExpression = uninterpretedExpression;
this.location = location;
}
visit(visitor, context = null) {
return visitor.visitQuote(this, context);
}
toString() {
return 'Quote';
}
}
class EmptyExpr extends AST {
visit(visitor, context = null) {
// do nothing
}
}
class ImplicitReceiver extends AST {
visit(visitor, context = null) {
return visitor.visitImplicitReceiver(this, context);
}
}
/**
* Multiple expressions separated by a semicolon.
*/
class Chain extends AST {
constructor(span, sourceSpan, expressions) {
super(span, sourceSpan);
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitChain(this, context);
}
}
class Conditional extends AST {
constructor(span, sourceSpan, condition, trueExp, falseExp) {
super(span, sourceSpan);
this.condition = condition;
this.trueExp = trueExp;
this.falseExp = falseExp;
}
visit(visitor, context = null) {
return visitor.visitConditional(this, context);
}
}
class PropertyRead extends ASTWithName {
constructor(span, sourceSpan, nameSpan, receiver, name) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitPropertyRead(this, context);
}
}
class PropertyWrite extends ASTWithName {
constructor(span, sourceSpan, nameSpan, receiver, name, value) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitPropertyWrite(this, context);
}
}
class SafePropertyRead extends ASTWithName {
constructor(span, sourceSpan, nameSpan, receiver, name) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
}
visit(visitor, context = null) {
return visitor.visitSafePropertyRead(this, context);
}
}
class KeyedRead extends AST {
constructor(span, sourceSpan, obj, key) {
super(span, sourceSpan);
this.obj = obj;
this.key = key;
}
visit(visitor, context = null) {
return visitor.visitKeyedRead(this, context);
}
}
class KeyedWrite extends AST {
constructor(span, sourceSpan, obj, key, value) {
super(span, sourceSpan);
this.obj = obj;
this.key = key;
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitKeyedWrite(this, context);
}
}
class BindingPipe extends ASTWithName {
constructor(span, sourceSpan, exp, name, args, nameSpan) {
super(span, sourceSpan, nameSpan);
this.exp = exp;
this.name = name;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitPipe(this, context);
}
}
class LiteralPrimitive extends AST {
constructor(span, sourceSpan, value) {
super(span, sourceSpan);
this.value = value;
}
visit(visitor, context = null) {
return visitor.visitLiteralPrimitive(this, context);
}
}
class LiteralArray extends AST {
constructor(span, sourceSpan, expressions) {
super(span, sourceSpan);
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitLiteralArray(this, context);
}
}
class LiteralMap extends AST {
constructor(span, sourceSpan, keys, values) {
super(span, sourceSpan);
this.keys = keys;
this.values = values;
}
visit(visitor, context = null) {
return visitor.visitLiteralMap(this, context);
}
}
class Interpolation extends AST {
constructor(span, sourceSpan, strings, expressions) {
super(span, sourceSpan);
this.strings = strings;
this.expressions = expressions;
}
visit(visitor, context = null) {
return visitor.visitInterpolation(this, context);
}
}
class Binary extends AST {
constructor(span, sourceSpan, operation, left, right) {
super(span, sourceSpan);
this.operation = operation;
this.left = left;
this.right = right;
}
visit(visitor, context = null) {
return visitor.visitBinary(this, context);
}
}
class PrefixNot extends AST {
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitPrefixNot(this, context);
}
}
class NonNullAssert extends AST {
constructor(span, sourceSpan, expression) {
super(span, sourceSpan);
this.expression = expression;
}
visit(visitor, context = null) {
return visitor.visitNonNullAssert(this, context);
}
}
class MethodCall extends ASTWithName {
constructor(span, sourceSpan, nameSpan, receiver, name, args) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitMethodCall(this, context);
}
}
class SafeMethodCall extends ASTWithName {
constructor(span, sourceSpan, nameSpan, receiver, name, args) {
super(span, sourceSpan, nameSpan);
this.receiver = receiver;
this.name = name;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitSafeMethodCall(this, context);
}
}
class FunctionCall extends AST {
constructor(span, sourceSpan, target, args) {
super(span, sourceSpan);
this.target = target;
this.args = args;
}
visit(visitor, context = null) {
return visitor.visitFunctionCall(this, context);
}
}
/**
* Records the absolute position of a text span in a source file, where `start` and `end` are the
* starting and ending byte offsets, respectively, of the text span in a source file.
*/
class AbsoluteSourceSpan {
constructor(start, end) {
this.start = start;
this.end = end;
}
}
class ASTWithSource extends AST {
constructor(ast, source, location, absoluteOffset, errors) {
super(new ParseSpan(0, source === null ? 0 : source.length), new AbsoluteSourceSpan(absoluteOffset, source === null ? absoluteOffset : absoluteOffset + source.length));
this.ast = ast;
this.source = source;
this.location = location;
this.errors = errors;
}
visit(visitor, context = null) {
if (visitor.visitASTWithSource) {
return visitor.visitASTWithSource(this, context);
}
return this.ast.visit(visitor, context);
}
toString() {
return `${this.source} in ${this.location}`;
}
}
class VariableBinding {
/**
* @param sourceSpan entire span of the binding.
* @param key name of the LHS along with its span.
* @param value optional value for the RHS along with its span.
*/
constructor(sourceSpan, key, value) {
this.sourceSpan = sourceSpan;
this.key = key;
this.value = value;
}
}
class ExpressionBinding {
/**
* @param sourceSpan entire span of the binding.
* @param key binding name, like ngForOf, ngForTrackBy, ngIf, along with its
* span. Note that the length of the span may not be the same as
* `key.source.length`. For example,
* 1. key.source = ngFor, key.span is for "ngFor"
* 2. key.source = ngForOf, key.span is for "of"
* 3. key.source = ngForTrackBy, key.span is for "trackBy"
* @param value optional expression for the RHS.
*/
constructor(sourceSpan, key, value) {
this.sourceSpan = sourceSpan;
this.key = key;
this.value = value;
}
}
class RecursiveAstVisitor$1 {
visit(ast, context) {
// The default implementation just visits every node.
// Classes that extend RecursiveAstVisitor should override this function
// to selectively visit the specified node.
ast.visit(this, context);
}
visitBinary(ast, context) {
this.visit(ast.left, context);
this.visit(ast.right, context);
}
visitChain(ast, context) {
this.visitAll(ast.expressions, context);
}
visitConditional(ast, context) {
this.visit(ast.condition, context);
this.visit(ast.trueExp, context);
this.visit(ast.falseExp, context);
}
visitPipe(ast, context) {
this.visit(ast.exp, context);
this.visitAll(ast.args, context);
}
visitFunctionCall(ast, context) {
if (ast.target) {
this.visit(ast.target, context);
}
this.visitAll(ast.args, context);
}
visitImplicitReceiver(ast, context) { }
visitInterpolation(ast, context) {
this.visitAll(ast.expressions, context);
}
visitKeyedRead(ast, context) {
this.visit(ast.obj, context);
this.visit(ast.key, context);
}
visitKeyedWrite(ast, context) {
this.visit(ast.obj, context);
this.visit(ast.key, context);
this.visit(ast.value, context);
}
visitLiteralArray(ast, context) {
this.visitAll(ast.expressions, context);
}
visitLiteralMap(ast, context) {
this.visitAll(ast.values, context);
}
visitLiteralPrimitive(ast, context) { }
visitMethodCall(ast, context) {
this.visit(ast.receiver, context);
this.visitAll(ast.args, context);
}
visitPrefixNot(ast, context) {
this.visit(ast.expression, context);
}
visitNonNullAssert(ast, context) {
this.visit(ast.expression, context);
}
visitPropertyRead(ast, context) {
this.visit(ast.receiver, context);
}
visitPropertyWrite(ast, context) {
this.visit(ast.receiver, context);
this.visit(ast.value, context);
}
visitSafePropertyRead(ast, context) {
this.visit(ast.receiver, context);
}
visitSafeMethodCall(ast, context) {
this.visit(ast.receiver, context);
this.visitAll(ast.args, context);
}
visitQuote(ast, context) { }
// This is not part of the AstVisitor interface, just a helper method
visitAll(asts, context) {
for (const ast of asts) {
this.visit(ast, context);
}
}
}
class AstTransformer$1 {
visitImplicitReceiver(ast, context) {
return ast;
}
visitInterpolation(ast, context) {
return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
}
visitLiteralPrimitive(ast, context) {
return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value);
}
visitPropertyRead(ast, context) {
return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);
}
visitPropertyWrite(ast, context) {
return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name, ast.value.visit(this));
}
visitSafePropertyRead(ast, context) {
return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);
}
visitMethodCall(ast, context) {
return new MethodCall(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name, this.visitAll(ast.args));
}
visitSafeMethodCall(ast, context) {
return new SafeMethodCall(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name, this.visitAll(ast.args));
}
visitFunctionCall(ast, context) {
return new FunctionCall(ast.span, ast.sourceSpan, ast.target.visit(this), this.visitAll(ast.args));
}
visitLiteralArray(ast, context) {
return new LiteralArray(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));
}
visitLiteralMap(ast, context) {
return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, this.visitAll(ast.values));
}
visitBinary(ast, context) {
return new Binary(ast.span, ast.sourceSpan, ast.operation, ast.left.visit(this), ast.right.visit(this));
}
visitPrefixNot(ast, context) {
return new PrefixNot(ast.span, ast.sourceSpan, ast.expression.visit(this));
}
visitNonNullAssert(ast, context) {
return new NonNullAssert(ast.span, ast.sourceSpan, ast.expression.visit(this));
}
visitConditional(ast, context) {
return new Conditional(ast.span, ast.sourceSpan, ast.condition.visit(this), ast.trueExp.visit(this), ast.falseExp.visit(this));
}
visitPipe(ast, context) {
return new BindingPipe(ast.span, ast.sourceSpan, ast.exp.visit(this), ast.name, this.visitAll(ast.args), ast.nameSpan);
}
visitKeyedRead(ast, context) {
return new KeyedRead(ast.span, ast.sourceSpan, ast.obj.visit(this), ast.key.visit(this));
}
visitKeyedWrite(ast, context) {
return new KeyedWrite(ast.span, ast.sourceSpan, ast.obj.visit(this), ast.key.visit(this), ast.value.visit(this));
}
visitAll(asts) {
const res = [];
for (let i = 0; i < asts.length; ++i) {
res[i] = asts[i].visit(this);
}
return res;
}
visitChain(ast, context) {
return new Chain(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));
}
visitQuote(ast, context) {
return new Quote(ast.span, ast.sourceSpan, ast.prefix, ast.uninterpretedExpression, ast.location);
}
}
// A transformer that only creates new nodes if the transformer makes a change or
// a change is made a child node.
class AstMemoryEfficientTransformer {
visitImplicitReceiver(ast, context) {
return ast;
}
visitInterpolation(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions)
return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions);
return ast;
}
visitLiteralPrimitive(ast, context) {
return ast;
}
visitPropertyRead(ast, context) {
const receiver = ast.receiver.visit(this);
if (receiver !== ast.receiver) {
return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);
}
return ast;
}
visitPropertyWrite(ast, context) {
const receiver = ast.receiver.visit(this);
const value = ast.value.visit(this);
if (receiver !== ast.receiver || value !== ast.value) {
return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, value);
}
return ast;
}
visitSafePropertyRead(ast, context) {
const receiver = ast.receiver.visit(this);
if (receiver !== ast.receiver) {
return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);
}
return ast;
}
visitMethodCall(ast, context) {
const receiver = ast.receiver.visit(this);
const args = this.visitAll(ast.args);
if (receiver !== ast.receiver || args !== ast.args) {
return new MethodCall(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, args);
}
return ast;
}
visitSafeMethodCall(ast, context) {
const receiver = ast.receiver.visit(this);
const args = this.visitAll(ast.args);
if (receiver !== ast.receiver || args !== ast.args) {
return new SafeMethodCall(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, args);
}
return ast;
}
visitFunctionCall(ast, context) {
const target = ast.target && ast.target.visit(this);
const args = this.visitAll(ast.args);
if (target !== ast.target || args !== ast.args) {
return new FunctionCall(ast.span, ast.sourceSpan, target, args);
}
return ast;
}
visitLiteralArray(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions) {
return new LiteralArray(ast.span, ast.sourceSpan, expressions);
}
return ast;
}
visitLiteralMap(ast, context) {
const values = this.visitAll(ast.values);
if (values !== ast.values) {
return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, values);
}
return ast;
}
visitBinary(ast, context) {
const left = ast.left.visit(this);
const right = ast.right.visit(this);
if (left !== ast.left || right !== ast.right) {
return new Binary(ast.span, ast.sourceSpan, ast.operation, left, right);
}
return ast;
}
visitPrefixNot(ast, context) {
const expression = ast.expression.visit(this);
if (expression !== ast.expression) {
return new PrefixNot(ast.span, ast.sourceSpan, expression);
}
return ast;
}
visitNonNullAssert(ast, context) {
const expression = ast.expression.visit(this);
if (expression !== ast.expression) {
return new NonNullAssert(ast.span, ast.sourceSpan, expression);
}
return ast;
}
visitConditional(ast, context) {
const condition = ast.condition.visit(this);
const trueExp = ast.trueExp.visit(this);
const falseExp = ast.falseExp.visit(this);
if (condition !== ast.condition || trueExp !== ast.trueExp || falseExp !== ast.falseExp) {
return new Conditional(ast.span, ast.sourceSpan, condition, trueExp, falseExp);
}
return ast;
}
visitPipe(ast, context) {
const exp = ast.exp.visit(this);
const args = this.visitAll(ast.args);
if (exp !== ast.exp || args !== ast.args) {
return new BindingPipe(ast.span, ast.sourceSpan, exp, ast.name, args, ast.nameSpan);
}
return ast;
}
visitKeyedRead(ast, context) {
const obj = ast.obj.visit(this);
const key = ast.key.visit(this);
if (obj !== ast.obj || key !== ast.key) {
return new KeyedRead(ast.span, ast.sourceSpan, obj, key);
}
return ast;
}
visitKeyedWrite(ast, context) {
const obj = ast.obj.visit(this);
const key = ast.key.visit(this);
const value = ast.value.visit(this);
if (obj !== ast.obj || key !== ast.key || value !== ast.value) {
return new KeyedWrite(ast.span, ast.sourceSpan, obj, key, value);
}
return ast;
}
visitAll(asts) {
const res = [];
let modified = false;
for (let i = 0; i < asts.length; ++i) {
const original = asts[i];
const value = original.visit(this);
res[i] = value;
modified = modified || value !== original;
}
return modified ? res : asts;
}
visitChain(ast, context) {
const expressions = this.visitAll(ast.expressions);
if (expressions !== ast.expressions) {
return new Chain(ast.span, ast.sourceSpan, expressions);
}
return ast;
}
visitQuote(ast, context) {
return ast;
}
}
// Bindings
class ParsedProperty {
constructor(name, expression, type, sourceSpan, valueSpan) {
this.name = name;
this.expression = expression;
this.type = type;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;
this.isAnimation = this.type === ParsedPropertyType.ANIMATION;
}
}
var ParsedPropertyType;
(function (ParsedPropertyType) {
ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT";
ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 2] = "ANIMATION";
})(ParsedPropertyType || (ParsedPropertyType = {}));
class ParsedEvent {
// Regular events have a target
// Animation events have a phase
constructor(name, targetOrPhase, type, handler, sourceSpan, handlerSpan) {
this.name = name;
this.targetOrPhase = targetOrPhase;
this.type = type;
this.handler = handler;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
}
}
/**
* ParsedVariable represents a variable declaration in a microsyntax expression.
*/
class ParsedVariable {
constructor(name, value, sourceSpan, keySpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.keySpan = keySpan;
this.valueSpan = valueSpan;
}
}
class BoundElementProperty {
constructor(name, type, securityContext, value, unit, sourceSpan, valueSpan) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class EventHandlerVars {
}
EventHandlerVars.event = variable('$event');
class ConvertActionBindingResult {
constructor(
/**
* Render2 compatible statements,
*/
stmts,
/**
* Variable name used with render2 compatible statements.
*/
allowDefault) {
this.stmts = stmts;
this.allowDefault = allowDefault;
/**
* This is bit of a hack. It converts statements which render2 expects to statements which are
* expected by render3.
*
* Example: `
` will generate:
*
* Render3:
* ```
* const pd_b:any = ((ctx.doSomething($event)) !== false);
* return pd_b;
* ```
*
* but render2 expects:
* ```
* return ctx.doSomething($event);
* ```
*/
// TODO(misko): remove this hack once we no longer support ViewEngine.
this.render3Stmts = stmts.map((statement) => {
if (statement instanceof DeclareVarStmt && statement.name == allowDefault.name &&
statement.value instanceof BinaryOperatorExpr) {
const lhs = statement.value.lhs;
return new ReturnStatement(lhs.value);
}
return statement;
});
}
}
/**
* Converts the given expression AST into an executable output AST, assuming the expression is
* used in an action binding (e.g. an event handler).
*/
function convertActionBinding(localResolver, implicitReceiver, action, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses) {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const actionWithoutBuiltins = convertPropertyBindingBuiltins({
createLiteralArrayConverter: (argCount) => {
// Note: no caching for literal arrays in actions.
return (args) => literalArr(args);
},
createLiteralMapConverter: (keys) => {
// Note: no caching for literal maps in actions.
return (values) => {
const entries = keys.map((k, i) => ({
key: k.key,
value: values[i],
quoted: k.quoted,
}));
return literalMap(entries);
};
},
createPipeConverter: (name) => {
throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`);
}
}, action);
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses);
const actionStmts = [];
flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const lastIndex = actionStmts.length - 1;
let preventDefaultVar = null;
if (lastIndex >= 0) {
const lastStatement = actionStmts[lastIndex];
const returnExpr = convertStmtIntoExpression(lastStatement);
if (returnExpr) {
// Note: We need to cast the result of the method call to dynamic,
// as it might be a void method!
preventDefaultVar = createPreventDefaultVar(bindingId);
actionStmts[lastIndex] =
preventDefaultVar.set(returnExpr.cast(DYNAMIC_TYPE).notIdentical(literal(false)))
.toDeclStmt(null, [StmtModifier.Final]);
}
}
return new ConvertActionBindingResult(actionStmts, preventDefaultVar);
}
function convertPropertyBindingBuiltins(converterFactory, ast) {
return convertBuiltins(converterFactory, ast);
}
class ConvertPropertyBindingResult {
constructor(stmts, currValExpr) {
this.stmts = stmts;
this.currValExpr = currValExpr;
}
}
var BindingForm;
(function (BindingForm) {
// The general form of binding expression, supports all expressions.
BindingForm[BindingForm["General"] = 0] = "General";
// Try to generate a simple binding (no temporaries or statements)
// otherwise generate a general binding
BindingForm[BindingForm["TrySimple"] = 1] = "TrySimple";
// Inlines assignment of temporaries into the generated expression. The result may still
// have statements attached for declarations of temporary variables.
// This is the only relevant form for Ivy, the other forms are only used in ViewEngine.
BindingForm[BindingForm["Expression"] = 2] = "Expression";
})(BindingForm || (BindingForm = {}));
/**
* Converts the given expression AST into an executable output AST, assuming the expression
* is used in property binding. The expression has to be preprocessed via
* `convertPropertyBindingBuiltins`.
*/
function convertPropertyBinding(localResolver, implicitReceiver, expressionWithoutBuiltins, bindingId, form, interpolationFunction) {
if (!localResolver) {
localResolver = new DefaultLocalResolver();
}
const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId, interpolationFunction);
const outputExpr = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
const stmts = getStatementsFromVisitor(visitor, bindingId);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
if (visitor.temporaryCount === 0 && form == BindingForm.TrySimple) {
return new ConvertPropertyBindingResult([], outputExpr);
}
else if (form === BindingForm.Expression) {
return new ConvertPropertyBindingResult(stmts, outputExpr);
}
const currValExpr = createCurrValueExpr(bindingId);
stmts.push(currValExpr.set(outputExpr).toDeclStmt(DYNAMIC_TYPE, [StmtModifier.Final]));
return new ConvertPropertyBindingResult(stmts, currValExpr);
}
/**
* Given some expression, such as a binding or interpolation expression, and a context expression to
* look values up on, visit each facet of the given expression resolving values from the context
* expression such that a list of arguments can be derived from the found values that can be used as
* arguments to an external update instruction.
*
* @param localResolver The resolver to use to look up expressions by name appropriately
* @param contextVariableExpression The expression representing the context variable used to create
* the final argument expressions
* @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to
* be resolved and what arguments list to build.
* @param bindingId A name prefix used to create temporary variable names if they're needed for the
* arguments generated
* @returns An array of expressions that can be passed as arguments to instruction expressions like
* `o.importExpr(R3.propertyInterpolate).callFn(result)`
*/
function convertUpdateArguments(localResolver, contextVariableExpression, expressionWithArgumentsToExtract, bindingId) {
const visitor = new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId, undefined);
const outputExpr = expressionWithArgumentsToExtract.visit(visitor, _Mode.Expression);
if (visitor.usesImplicitReceiver) {
localResolver.notifyImplicitReceiverUse();
}
const stmts = getStatementsFromVisitor(visitor, bindingId);
// Removing the first argument, because it was a length for ViewEngine, not Ivy.
let args = outputExpr.args.slice(1);
if (expressionWithArgumentsToExtract instanceof Interpolation) {
// If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the
// args returned to just the value, because we're going to pass it to a special instruction.
const strings = expressionWithArgumentsToExtract.strings;
if (args.length === 3 && strings[0] === '' && strings[1] === '') {
// Single argument interpolate instructions.
args = [args[1]];
}
else if (args.length >= 19) {
// 19 or more arguments must be passed to the `interpolateV`-style instructions, which accept
// an array of arguments
args = [literalArr(args)];
}
}
return { stmts, args };
}
function getStatementsFromVisitor(visitor, bindingId) {
const stmts = [];
for (let i = 0; i < visitor.temporaryCount; i++) {
stmts.push(temporaryDeclaration(bindingId, i));
}
return stmts;
}
function convertBuiltins(converterFactory, ast) {
const visitor = new _BuiltinAstConverter(converterFactory);
return ast.visit(visitor);
}
function temporaryName(bindingId, temporaryNumber) {
return `tmp_${bindingId}_${temporaryNumber}`;
}
function temporaryDeclaration(bindingId, temporaryNumber) {
return new DeclareVarStmt(temporaryName(bindingId, temporaryNumber), NULL_EXPR);
}
function prependTemporaryDecls(temporaryCount, bindingId, statements) {
for (let i = temporaryCount - 1; i >= 0; i--) {
statements.unshift(temporaryDeclaration(bindingId, i));
}
}
var _Mode;
(function (_Mode) {
_Mode[_Mode["Statement"] = 0] = "Statement";
_Mode[_Mode["Expression"] = 1] = "Expression";
})(_Mode || (_Mode = {}));
function ensureStatementMode(mode, ast) {
if (mode !== _Mode.Statement) {
throw new Error(`Expected a statement, but saw ${ast}`);
}
}
function ensureExpressionMode(mode, ast) {
if (mode !== _Mode.Expression) {
throw new Error(`Expected an expression, but saw ${ast}`);
}
}
function convertToStatementIfNeeded(mode, expr) {
if (mode === _Mode.Statement) {
return expr.toStmt();
}
else {
return expr;
}
}
class _BuiltinAstConverter extends AstTransformer$1 {
constructor(_converterFactory) {
super();
this._converterFactory = _converterFactory;
}
visitPipe(ast, context) {
const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createPipeConverter(ast.name, args.length));
}
visitLiteralArray(ast, context) {
const args = ast.expressions.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralArrayConverter(ast.expressions.length));
}
visitLiteralMap(ast, context) {
const args = ast.values.map(ast => ast.visit(this, context));
return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralMapConverter(ast.keys));
}
}
class _AstToIrVisitor {
constructor(_localResolver, _implicitReceiver, bindingId, interpolationFunction, baseSourceSpan, implicitReceiverAccesses) {
this._localResolver = _localResolver;
this._implicitReceiver = _implicitReceiver;
this.bindingId = bindingId;
this.interpolationFunction = interpolationFunction;
this.baseSourceSpan = baseSourceSpan;
this.implicitReceiverAccesses = implicitReceiverAccesses;
this._nodeMap = new Map();
this._resultMap = new Map();
this._currentTemporary = 0;
this.temporaryCount = 0;
this.usesImplicitReceiver = false;
}
visitBinary(ast, mode) {
let op;
switch (ast.operation) {
case '+':
op = BinaryOperator.Plus;
break;
case '-':
op = BinaryOperator.Minus;
break;
case '*':
op = BinaryOperator.Multiply;
break;
case '/':
op = BinaryOperator.Divide;
break;
case '%':
op = BinaryOperator.Modulo;
break;
case '&&':
op = BinaryOperator.And;
break;
case '||':
op = BinaryOperator.Or;
break;
case '==':
op = BinaryOperator.Equals;
break;
case '!=':
op = BinaryOperator.NotEquals;
break;
case '===':
op = BinaryOperator.Identical;
break;
case '!==':
op = BinaryOperator.NotIdentical;
break;
case '<':
op = BinaryOperator.Lower;
break;
case '>':
op = BinaryOperator.Bigger;
break;
case '<=':
op = BinaryOperator.LowerEquals;
break;
case '>=':
op = BinaryOperator.BiggerEquals;
break;
default:
throw new Error(`Unsupported operation ${ast.operation}`);
}
return convertToStatementIfNeeded(mode, new BinaryOperatorExpr(op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
}
visitChain(ast, mode) {
ensureStatementMode(mode, ast);
return this.visitAll(ast.expressions, mode);
}
visitConditional(ast, mode) {
const value = this._visit(ast.condition, _Mode.Expression);
return convertToStatementIfNeeded(mode, value.conditional(this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span)));
}
visitPipe(ast, mode) {
throw new Error(`Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`);
}
visitFunctionCall(ast, mode) {
const convertedArgs = this.visitAll(ast.args, _Mode.Expression);
let fnResult;
if (ast instanceof BuiltinFunctionCall) {
fnResult = ast.converter(convertedArgs);
}
else {
fnResult = this._visit(ast.target, _Mode.Expression)
.callFn(convertedArgs, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, fnResult);
}
visitImplicitReceiver(ast, mode) {
ensureExpressionMode(mode, ast);
this.usesImplicitReceiver = true;
return this._implicitReceiver;
}
visitInterpolation(ast, mode) {
ensureExpressionMode(mode, ast);
const args = [literal(ast.expressions.length)];
for (let i = 0; i < ast.strings.length - 1; i++) {
args.push(literal(ast.strings[i]));
args.push(this._visit(ast.expressions[i], _Mode.Expression));
}
args.push(literal(ast.strings[ast.strings.length - 1]));
if (this.interpolationFunction) {
return this.interpolationFunction(args);
}
return ast.expressions.length <= 9 ?
importExpr(Identifiers.inlineInterpolate).callFn(args) :
importExpr(Identifiers.interpolate).callFn([
args[0], literalArr(args.slice(1), undefined, this.convertSourceSpan(ast.span))
]);
}
visitKeyedRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
return convertToStatementIfNeeded(mode, this._visit(ast.obj, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
}
}
visitKeyedWrite(ast, mode) {
const obj = this._visit(ast.obj, _Mode.Expression);
const key = this._visit(ast.key, _Mode.Expression);
const value = this._visit(ast.value, _Mode.Expression);
return convertToStatementIfNeeded(mode, obj.key(key).set(value));
}
visitLiteralArray(ast, mode) {
throw new Error(`Illegal State: literal arrays should have been converted into functions`);
}
visitLiteralMap(ast, mode) {
throw new Error(`Illegal State: literal maps should have been converted into functions`);
}
visitLiteralPrimitive(ast, mode) {
// For literal values of null, undefined, true, or false allow type interference
// to infer the type.
const type = ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ?
INFERRED_TYPE :
undefined;
return convertToStatementIfNeeded(mode, literal(ast.value, type, this.convertSourceSpan(ast.span)));
}
_getLocal(name) {
return this._localResolver.getLocal(name);
}
visitMethodCall(ast, mode) {
if (ast.receiver instanceof ImplicitReceiver && ast.name == '$any') {
const args = this.visitAll(ast.args, _Mode.Expression);
if (args.length != 1) {
throw new Error(`Invalid call to $any, expected 1 argument but received ${args.length || 'none'}`);
}
return args[0].cast(DYNAMIC_TYPE, this.convertSourceSpan(ast.span));
}
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
const args = this.visitAll(ast.args, _Mode.Expression);
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
let result = null;
const receiver = this._visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
const varExpr = this._getLocal(ast.name);
if (varExpr) {
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
result = varExpr.callFn(args);
}
this.addImplicitReceiverAccess(ast.name);
}
if (result == null) {
result = receiver.callMethod(ast.name, args, this.convertSourceSpan(ast.span));
}
return convertToStatementIfNeeded(mode, result);
}
}
visitPrefixNot(ast, mode) {
return convertToStatementIfNeeded(mode, not(this._visit(ast.expression, _Mode.Expression)));
}
visitNonNullAssert(ast, mode) {
return convertToStatementIfNeeded(mode, assertNotNull(this._visit(ast.expression, _Mode.Expression)));
}
visitPropertyRead(ast, mode) {
const leftMostSafe = this.leftMostSafeNode(ast);
if (leftMostSafe) {
return this.convertSafeAccess(ast, leftMostSafe, mode);
}
else {
let result = null;
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
const receiver = this._visit(ast.receiver, _Mode.Expression);
if (receiver === this._implicitReceiver) {
result = this._getLocal(ast.name);
if (result) {
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
}
this.addImplicitReceiverAccess(ast.name);
}
if (result == null) {
result = receiver.prop(ast.name);
}
return convertToStatementIfNeeded(mode, result);
}
}
visitPropertyWrite(ast, mode) {
const receiver = this._visit(ast.receiver, _Mode.Expression);
const prevUsesImplicitReceiver = this.usesImplicitReceiver;
let varExpr = null;
if (receiver === this._implicitReceiver) {
const localExpr = this._getLocal(ast.name);
if (localExpr) {
if (localExpr instanceof ReadPropExpr) {
// If the local variable is a property read expression, it's a reference
// to a 'context.property' value and will be used as the target of the
// write expression.
varExpr = localExpr;
// Restore the previous "usesImplicitReceiver" state since the implicit
// receiver has been replaced with a resolved local expression.
this.usesImplicitReceiver = prevUsesImplicitReceiver;
this.addImplicitReceiverAccess(ast.name);
}
else {
// Otherwise it's an error.
const receiver = ast.name;
const value = (ast.value instanceof PropertyRead) ? ast.value.name : undefined;
throw new Error(`Cannot assign value "${value}" to template variable "${receiver}". Template variables are read-only.`);
}
}
}
// If no local expression could be produced, use the original receiver's
// property as the target.
if (varExpr === null) {
varExpr = receiver.prop(ast.name);
}
return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression)));
}
visitSafePropertyRead(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitSafeMethodCall(ast, mode) {
return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
}
visitAll(asts, mode) {
return asts.map(ast => this._visit(ast, mode));
}
visitQuote(ast, mode) {
throw new Error(`Quotes are not supported for evaluation!
Statement: ${ast.uninterpretedExpression} located at ${ast.location}`);
}
_visit(ast, mode) {
const result = this._resultMap.get(ast);
if (result)
return result;
return (this._nodeMap.get(ast) || ast).visit(this, mode);
}
convertSafeAccess(ast, leftMostSafe, mode) {
// If the expression contains a safe access node on the left it needs to be converted to
// an expression that guards the access to the member by checking the receiver for blank. As
// execution proceeds from left to right, the left most part of the expression must be guarded
// first but, because member access is left associative, the right side of the expression is at
// the top of the AST. The desired result requires lifting a copy of the left part of the
// expression up to test it for blank before generating the unguarded version.
// Consider, for example the following expression: a?.b.c?.d.e
// This results in the ast:
// .
// / \
// ?. e
// / \
// . d
// / \
// ?. c
// / \
// a b
// The following tree should be generated:
//
// /---- ? ----\
// / | \
// a /--- ? ---\ null
// / | \
// . . null
// / \ / \
// . c . e
// / \ / \
// a b . d
// / \
// . c
// / \
// a b
//
// Notice that the first guard condition is the left hand of the left most safe access node
// which comes in as leftMostSafe to this routine.
let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression);
let temporary = undefined;
if (this.needsTemporary(leftMostSafe.receiver)) {
// If the expression has method calls or pipes then we need to save the result into a
// temporary variable to avoid calling stateful or impure code more than once.
temporary = this.allocateTemporary();
// Preserve the result in the temporary variable
guardedExpression = temporary.set(guardedExpression);
// Ensure all further references to the guarded expression refer to the temporary instead.
this._resultMap.set(leftMostSafe.receiver, temporary);
}
const condition = guardedExpression.isBlank();
// Convert the ast to an unguarded access to the receiver's member. The map will substitute
// leftMostNode with its unguarded version in the call to `this.visit()`.
if (leftMostSafe instanceof SafeMethodCall) {
this._nodeMap.set(leftMostSafe, new MethodCall(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name, leftMostSafe.args));
}
else {
this._nodeMap.set(leftMostSafe, new PropertyRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name));
}
// Recursively convert the node now without the guarded member access.
const access = this._visit(ast, _Mode.Expression);
// Remove the mapping. This is not strictly required as the converter only traverses each node
// once but is safer if the conversion is changed to traverse the nodes more than once.
this._nodeMap.delete(leftMostSafe);
// If we allocated a temporary, release it.
if (temporary) {
this.releaseTemporary(temporary);
}
// Produce the conditional
return convertToStatementIfNeeded(mode, condition.conditional(literal(null), access));
}
// Given an expression of the form a?.b.c?.d.e then the left most safe node is
// the (a?.b). The . and ?. are left associative thus can be rewritten as:
// ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or
// safe method call as this needs to be transformed initially to:
// a == null ? null : a.c.b.c?.d.e
// then to:
// a == null ? null : a.b.c == null ? null : a.b.c.d.e
leftMostSafeNode(ast) {
const visit = (visitor, ast) => {
return (this._nodeMap.get(ast) || ast).visit(visitor);
};
return ast.visit({
visitBinary(ast) {
return null;
},
visitChain(ast) {
return null;
},
visitConditional(ast) {
return null;
},
visitFunctionCall(ast) {
return null;
},
visitImplicitReceiver(ast) {
return null;
},
visitInterpolation(ast) {
return null;
},
visitKeyedRead(ast) {
return visit(this, ast.obj);
},
visitKeyedWrite(ast) {
return null;
},
visitLiteralArray(ast) {
return null;
},
visitLiteralMap(ast) {
return null;
},
visitLiteralPrimitive(ast) {
return null;
},
visitMethodCall(ast) {
return visit(this, ast.receiver);
},
visitPipe(ast) {
return null;
},
visitPrefixNot(ast) {
return null;
},
visitNonNullAssert(ast) {
return null;
},
visitPropertyRead(ast) {
return visit(this, ast.receiver);
},
visitPropertyWrite(ast) {
return null;
},
visitQuote(ast) {
return null;
},
visitSafeMethodCall(ast) {
return visit(this, ast.receiver) || ast;
},
visitSafePropertyRead(ast) {
return visit(this, ast.receiver) || ast;
}
});
}
// Returns true of the AST includes a method or a pipe indicating that, if the
// expression is used as the target of a safe property or method access then
// the expression should be stored into a temporary variable.
needsTemporary(ast) {
const visit = (visitor, ast) => {
return ast && (this._nodeMap.get(ast) || ast).visit(visitor);
};
const visitSome = (visitor, ast) => {
return ast.some(ast => visit(visitor, ast));
};
return ast.visit({
visitBinary(ast) {
return visit(this, ast.left) || visit(this, ast.right);
},
visitChain(ast) {
return false;
},
visitConditional(ast) {
return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp);
},
visitFunctionCall(ast) {
return true;
},
visitImplicitReceiver(ast) {
return false;
},
visitInterpolation(ast) {
return visitSome(this, ast.expressions);
},
visitKeyedRead(ast) {
return false;
},
visitKeyedWrite(ast) {
return false;
},
visitLiteralArray(ast) {
return true;
},
visitLiteralMap(ast) {
return true;
},
visitLiteralPrimitive(ast) {
return false;
},
visitMethodCall(ast) {
return true;
},
visitPipe(ast) {
return true;
},
visitPrefixNot(ast) {
return visit(this, ast.expression);
},
visitNonNullAssert(ast) {
return visit(this, ast.expression);
},
visitPropertyRead(ast) {
return false;
},
visitPropertyWrite(ast) {
return false;
},
visitQuote(ast) {
return false;
},
visitSafeMethodCall(ast) {
return true;
},
visitSafePropertyRead(ast) {
return false;
}
});
}
allocateTemporary() {
const tempNumber = this._currentTemporary++;
this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount);
return new ReadVarExpr(temporaryName(this.bindingId, tempNumber));
}
releaseTemporary(temporary) {
this._currentTemporary--;
if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) {
throw new Error(`Temporary ${temporary.name} released out of order`);
}
}
/**
* Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`.
*
* `ParseSpan` objects are relative to the start of the expression.
* This method converts these to full `ParseSourceSpan` objects that
* show where the span is within the overall source file.
*
* @param span the relative span to convert.
* @returns a `ParseSourceSpan` for the given span or null if no
* `baseSourceSpan` was provided to this class.
*/
convertSourceSpan(span) {
if (this.baseSourceSpan) {
const start = this.baseSourceSpan.start.moveBy(span.start);
const end = this.baseSourceSpan.start.moveBy(span.end);
return new ParseSourceSpan(start, end);
}
else {
return null;
}
}
/** Adds the name of an AST to the list of implicit receiver accesses. */
addImplicitReceiverAccess(name) {
if (this.implicitReceiverAccesses) {
this.implicitReceiverAccesses.add(name);
}
}
}
function flattenStatements(arg, output) {
if (Array.isArray(arg)) {
arg.forEach((entry) => flattenStatements(entry, output));
}
else {
output.push(arg);
}
}
class DefaultLocalResolver {
notifyImplicitReceiverUse() { }
getLocal(name) {
if (name === EventHandlerVars.event.name) {
return EventHandlerVars.event;
}
return null;
}
}
function createCurrValueExpr(bindingId) {
return variable(`currVal_${bindingId}`); // fix syntax highlighting: `
}
function createPreventDefaultVar(bindingId) {
return variable(`pd_${bindingId}`);
}
function convertStmtIntoExpression(stmt) {
if (stmt instanceof ExpressionStatement) {
return stmt.expr;
}
else if (stmt instanceof ReturnStatement) {
return stmt.value;
}
return null;
}
class BuiltinFunctionCall extends FunctionCall {
constructor(span, sourceSpan, args, converter) {
super(span, sourceSpan, null, args);
this.args = args;
this.converter = converter;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* This file is a port of shadowCSS from webcomponents.js to TypeScript.
*
* Please make sure to keep to edits in sync with the source file.
*
* Source:
* https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
*
* The original file level comment is reproduced below
*/
/*
This is a limited shim for ShadowDOM css styling.
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
The intention here is to support only the styling features which can be
relatively simply implemented. The goal is to allow users to avoid the
most obvious pitfalls and do so without compromising performance significantly.
For ShadowDOM styling that's not covered here, a set of best practices
can be provided that should allow users to accomplish more complex styling.
The following is a list of specific ShadowDOM styling features and a brief
discussion of the approach used to shim.
Shimmed features:
* :host, :host-context: ShadowDOM allows styling of the shadowRoot's host
element using the :host rule. To shim this feature, the :host styles are
reformatted and prefixed with a given scope name and promoted to a
document level stylesheet.
For example, given a scope name of .foo, a rule like this:
:host {
background: red;
}
}
becomes:
.foo {
background: red;
}
* encapsulation: Styles defined within ShadowDOM, apply only to
dom inside the ShadowDOM. Polymer uses one of two techniques to implement
this feature.
By default, rules are prefixed with the host element tag name
as a descendant selector. This ensures styling does not leak out of the 'top'
of the element's ShadowDOM. For example,
div {
font-weight: bold;
}
becomes:
x-foo div {
font-weight: bold;
}
becomes:
Alternatively, if WebComponents.ShadowCSS.strictStyling is set to true then
selectors are scoped by adding an attribute selector suffix to each
simple selector that contains the host element tag name. Each element
in the element's ShadowDOM template is also given the scope attribute.
Thus, these rules match only elements that have the scope attribute.
For example, given a scope name of x-foo, a rule like this:
div {
font-weight: bold;
}
becomes:
div[x-foo] {
font-weight: bold;
}
Note that elements that are dynamically added to a scope must have the scope
selector added to them manually.
* upper/lower bound encapsulation: Styles which are defined outside a
shadowRoot should not cross the ShadowDOM boundary and should not apply
inside a shadowRoot.
This styling behavior is not emulated. Some possible ways to do this that
were rejected due to complexity and/or performance concerns include: (1) reset
every possible property for every possible selector for a given scope name;
(2) re-implement css in javascript.
As an alternative, users should make sure to use selectors
specific to the scope in which they are working.
* ::distributed: This behavior is not emulated. It's often not necessary
to style the contents of a specific insertion point and instead, descendants
of the host element can be styled selectively. Users can also create an
extra node around an insertion point and style that node's contents
via descendent selectors. For example, with a shadowRoot like this:
could become:
Note the use of @polyfill in the comment above a ShadowDOM specific style
declaration. This is a directive to the styling shim to use the selector
in comments in lieu of the next selector when running under polyfill.
*/
class ShadowCss {
constructor() {
this.strictStyling = true;
}
/*
* Shim some cssText with the given selector. Returns cssText that can
* be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
*
* When strictStyling is true:
* - selector is the attribute added to all elements inside the host,
* - hostSelector is the attribute added to the host itself.
*/
shimCssText(cssText, selector, hostSelector = '') {
const commentsWithHash = extractCommentsWithHash(cssText);
cssText = stripComments(cssText);
cssText = this._insertDirectives(cssText);
const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
return [scopedCssText, ...commentsWithHash].join('\n');
}
_insertDirectives(cssText) {
cssText = this._insertPolyfillDirectivesInCssText(cssText);
return this._insertPolyfillRulesInCssText(cssText);
}
/*
* Process styles to convert native ShadowDOM rules that will trip
* up the css parser; we rely on decorating the stylesheet with inert rules.
*
* For example, we convert this rule:
*
* polyfill-next-selector { content: ':host menu-item'; }
* ::content menu-item {
*
* to this:
*
* scopeName menu-item {
*
**/
_insertPolyfillDirectivesInCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
return cssText.replace(_cssContentNextSelectorRe, function (...m) {
return m[2] + '{';
});
}
/*
* Process styles to add rules which will only apply under the polyfill
*
* For example, we convert this rule:
*
* polyfill-rule {
* content: ':host menu-item';
* ...
* }
*
* to this:
*
* scopeName menu-item {...}
*
**/
_insertPolyfillRulesInCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
return cssText.replace(_cssContentRuleRe, (...m) => {
const rule = m[0].replace(m[1], '').replace(m[2], '');
return m[4] + rule;
});
}
/* Ensure styles are scoped. Pseudo-scoping takes a rule like:
*
* .foo {... }
*
* and converts this to
*
* scopeName .foo { ... }
*/
_scopeCssText(cssText, scopeSelector, hostSelector) {
const unscopedRules = this._extractUnscopedRulesFromCssText(cssText);
// replace :host and :host-context -shadowcsshost and -shadowcsshost respectively
cssText = this._insertPolyfillHostInCssText(cssText);
cssText = this._convertColonHost(cssText);
cssText = this._convertColonHostContext(cssText);
cssText = this._convertShadowDOMSelectors(cssText);
if (scopeSelector) {
cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector);
}
cssText = cssText + '\n' + unscopedRules;
return cssText.trim();
}
/*
* Process styles to add rules which will only apply under the polyfill
* and do not process via CSSOM. (CSSOM is destructive to rules on rare
* occasions, e.g. -webkit-calc on Safari.)
* For example, we convert this rule:
*
* @polyfill-unscoped-rule {
* content: 'menu-item';
* ... }
*
* to this:
*
* menu-item {...}
*
**/
_extractUnscopedRulesFromCssText(cssText) {
// Difference with webcomponents.js: does not handle comments
let r = '';
let m;
_cssContentUnscopedRuleRe.lastIndex = 0;
while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
r += rule + '\n\n';
}
return r;
}
/*
* convert a rule like :host(.foo) > .bar { }
*
* to
*
* .foo > .bar
*/
_convertColonHost(cssText) {
return this._convertColonRule(cssText, _cssColonHostRe, this._colonHostPartReplacer);
}
/*
* convert a rule like :host-context(.foo) > .bar { }
*
* to
*
* .foo > .bar, .foo scopeName > .bar { }
*
* and
*
* :host-context(.foo:host) .bar { ... }
*
* to
*
* .foo .bar { ... }
*/
_convertColonHostContext(cssText) {
return this._convertColonRule(cssText, _cssColonHostContextRe, this._colonHostContextPartReplacer);
}
_convertColonRule(cssText, regExp, partReplacer) {
// m[1] = :host(-context), m[2] = contents of (), m[3] rest of rule
return cssText.replace(regExp, function (...m) {
if (m[2]) {
const parts = m[2].split(',');
const r = [];
for (let i = 0; i < parts.length; i++) {
const p = parts[i].trim();
if (!p)
break;
r.push(partReplacer(_polyfillHostNoCombinator, p, m[3]));
}
return r.join(',');
}
else {
return _polyfillHostNoCombinator + m[3];
}
});
}
_colonHostContextPartReplacer(host, part, suffix) {
if (part.indexOf(_polyfillHost) > -1) {
return this._colonHostPartReplacer(host, part, suffix);
}
else {
return host + part + suffix + ', ' + part + ' ' + host + suffix;
}
}
_colonHostPartReplacer(host, part, suffix) {
return host + part.replace(_polyfillHost, '') + suffix;
}
/*
* Convert combinators like ::shadow and pseudo-elements like ::content
* by replacing with space.
*/
_convertShadowDOMSelectors(cssText) {
return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText);
}
// change a selector like 'div' to 'name div'
_scopeSelectors(cssText, scopeSelector, hostSelector) {
return processRules(cssText, (rule) => {
let selector = rule.selector;
let content = rule.content;
if (rule.selector[0] != '@') {
selector =
this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling);
}
else if (rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') ||
rule.selector.startsWith('@page') || rule.selector.startsWith('@document')) {
content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
}
return new CssRule(selector, content);
});
}
_scopeSelector(selector, scopeSelector, hostSelector, strict) {
return selector.split(',')
.map(part => part.trim().split(_shadowDeepSelectors))
.map((deepParts) => {
const [shallowPart, ...otherParts] = deepParts;
const applyScope = (shallowPart) => {
if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
return strict ?
this._applyStrictSelectorScope(shallowPart, scopeSelector, hostSelector) :
this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
}
else {
return shallowPart;
}
};
return [applyScope(shallowPart), ...otherParts].join(' ');
})
.join(', ');
}
_selectorNeedsScoping(selector, scopeSelector) {
const re = this._makeScopeMatcher(scopeSelector);
return !re.test(selector);
}
_makeScopeMatcher(scopeSelector) {
const lre = /\[/g;
const rre = /\]/g;
scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]');
return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
}
_applySelectorScope(selector, scopeSelector, hostSelector) {
// Difference from webcomponents.js: scopeSelector could not be an array
return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector);
}
// scope via name and [is=name]
_applySimpleSelectorScope(selector, scopeSelector, hostSelector) {
// In Android browser, the lastIndex is not reset when the regex is used in String.replace()
_polyfillHostRe.lastIndex = 0;
if (_polyfillHostRe.test(selector)) {
const replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector;
return selector
.replace(_polyfillHostNoCombinatorRe, (hnc, selector) => {
return selector.replace(/([^:]*)(:*)(.*)/, (_, before, colon, after) => {
return before + replaceBy + colon + after;
});
})
.replace(_polyfillHostRe, replaceBy + ' ');
}
return scopeSelector + ' ' + selector;
}
// return a selector with [name] suffix on each simple selector
// e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */
_applyStrictSelectorScope(selector, scopeSelector, hostSelector) {
const isRe = /\[is=([^\]]*)\]/g;
scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]);
const attrName = '[' + scopeSelector + ']';
const _scopeSelectorPart = (p) => {
let scopedP = p.trim();
if (!scopedP) {
return '';
}
if (p.indexOf(_polyfillHostNoCombinator) > -1) {
scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
}
else {
// remove :host since it should be unnecessary
const t = p.replace(_polyfillHostRe, '');
if (t.length > 0) {
const matches = t.match(/([^:]*)(:*)(.*)/);
if (matches) {
scopedP = matches[1] + attrName + matches[2] + matches[3];
}
}
}
return scopedP;
};
const safeContent = new SafeSelector(selector);
selector = safeContent.content();
let scopedSelector = '';
let startIndex = 0;
let res;
const sep = /( |>|\+|~(?!=))\s*/g;
// If a selector appears before :host it should not be shimmed as it
// matches on ancestor elements and not on elements in the host's shadow
// `:host-context(div)` is transformed to
// `-shadowcsshost-no-combinatordiv, div -shadowcsshost-no-combinator`
// the `div` is not part of the component in the 2nd selectors and should not be scoped.
// Historically `component-tag:host` was matching the component so we also want to preserve
// this behavior to avoid breaking legacy apps (it should not match).
// The behavior should be:
// - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything)
// - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a
// `:host-context(tag)`)
const hasHost = selector.indexOf(_polyfillHostNoCombinator) > -1;
// Only scope parts after the first `-shadowcsshost-no-combinator` when it is present
let shouldScope = !hasHost;
while ((res = sep.exec(selector)) !== null) {
const separator = res[1];
const part = selector.slice(startIndex, res.index).trim();
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
scopedSelector += `${scopedPart} ${separator} `;
startIndex = sep.lastIndex;
}
const part = selector.substring(startIndex);
shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
scopedSelector += shouldScope ? _scopeSelectorPart(part) : part;
// replace the placeholders with their original values
return safeContent.restore(scopedSelector);
}
_insertPolyfillHostInCssText(selector) {
return selector.replace(_colonHostContextRe, _polyfillHostContext)
.replace(_colonHostRe, _polyfillHost);
}
}
class SafeSelector {
constructor(selector) {
this.placeholders = [];
this.index = 0;
// Replaces attribute selectors with placeholders.
// The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
selector = selector.replace(/(\[[^\]]*\])/g, (_, keep) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(keep);
this.index++;
return replaceBy;
});
// Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
// WS and "+" would otherwise be interpreted as selector separators.
this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
const replaceBy = `__ph-${this.index}__`;
this.placeholders.push(exp);
this.index++;
return pseudo + replaceBy;
});
}
restore(content) {
return content.replace(/__ph-(\d+)__/g, (ph, index) => this.placeholders[+index]);
}
content() {
return this._content;
}
}
const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim;
const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
const _polyfillHost = '-shadowcsshost';
// note: :host-context pre-processed to -shadowcsshostcontext.
const _polyfillHostContext = '-shadowcsscontext';
const _parenSuffix = ')(?:\\((' +
'(?:\\([^)(]*\\)|[^)(]*)+?' +
')\\))?([^,{]*)';
const _cssColonHostRe = new RegExp('(' + _polyfillHost + _parenSuffix, 'gim');
const _cssColonHostContextRe = new RegExp('(' + _polyfillHostContext + _parenSuffix, 'gim');
const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
const _shadowDOMSelectorsRe = [
/::shadow/g,
/::content/g,
// Deprecated selectors
/\/shadow-deep\//g,
/\/shadow\//g,
];
// The deep combinator is deprecated in the CSS spec
// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
// see https://github.com/angular/angular/pull/17677
const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
const _selectorReSuffix = '([>\\s~+\[.,{:][\\s\\S]*)?$';
const _polyfillHostRe = /-shadowcsshost/gim;
const _colonHostRe = /:host/gim;
const _colonHostContextRe = /:host-context/gim;
const _commentRe = /\/\*\s*[\s\S]*?\*\//g;
function stripComments(input) {
return input.replace(_commentRe, '');
}
const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
function extractCommentsWithHash(input) {
return input.match(_commentWithHashRe) || [];
}
const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
const _curlyRe = /([{}])/g;
const OPEN_CURLY = '{';
const CLOSE_CURLY = '}';
const BLOCK_PLACEHOLDER = '%BLOCK%';
class CssRule {
constructor(selector, content) {
this.selector = selector;
this.content = content;
}
}
function processRules(input, ruleCallback) {
const inputWithEscapedBlocks = escapeBlocks(input);
let nextBlockIndex = 0;
return inputWithEscapedBlocks.escapedString.replace(_ruleRe, function (...m) {
const selector = m[2];
let content = '';
let suffix = m[4];
let contentPrefix = '';
if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) {
content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1);
contentPrefix = '{';
}
const rule = ruleCallback(new CssRule(selector, content));
return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
});
}
class StringWithEscapedBlocks {
constructor(escapedString, blocks) {
this.escapedString = escapedString;
this.blocks = blocks;
}
}
function escapeBlocks(input) {
const inputParts = input.split(_curlyRe);
const resultParts = [];
const escapedBlocks = [];
let bracketCount = 0;
let currentBlockParts = [];
for (let partIndex = 0; partIndex < inputParts.length; partIndex++) {
const part = inputParts[partIndex];
if (part == CLOSE_CURLY) {
bracketCount--;
}
if (bracketCount > 0) {
currentBlockParts.push(part);
}
else {
if (currentBlockParts.length > 0) {
escapedBlocks.push(currentBlockParts.join(''));
resultParts.push(BLOCK_PLACEHOLDER);
currentBlockParts = [];
}
resultParts.push(part);
}
if (part == OPEN_CURLY) {
bracketCount++;
}
}
if (currentBlockParts.length > 0) {
escapedBlocks.push(currentBlockParts.join(''));
resultParts.push(BLOCK_PLACEHOLDER);
}
return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
class StylesCompileDependency {
constructor(name, moduleUrl, setValue) {
this.name = name;
this.moduleUrl = moduleUrl;
this.setValue = setValue;
}
}
class CompiledStylesheet {
constructor(outputCtx, stylesVar, dependencies, isShimmed, meta) {
this.outputCtx = outputCtx;
this.stylesVar = stylesVar;
this.dependencies = dependencies;
this.isShimmed = isShimmed;
this.meta = meta;
}
}
class StyleCompiler {
constructor(_urlResolver) {
this._urlResolver = _urlResolver;
this._shadowCss = new ShadowCss();
}
compileComponent(outputCtx, comp) {
const template = comp.template;
return this._compileStyles(outputCtx, comp, new CompileStylesheetMetadata({
styles: template.styles,
styleUrls: template.styleUrls,
moduleUrl: identifierModuleUrl(comp.type)
}), this.needsStyleShim(comp), true);
}
compileStyles(outputCtx, comp, stylesheet, shim = this.needsStyleShim(comp)) {
return this._compileStyles(outputCtx, comp, stylesheet, shim, false);
}
needsStyleShim(comp) {
return comp.template.encapsulation === ViewEncapsulation.Emulated;
}
_compileStyles(outputCtx, comp, stylesheet, shim, isComponentStylesheet) {
const styleExpressions = stylesheet.styles.map(plainStyle => literal(this._shimIfNeeded(plainStyle, shim)));
const dependencies = [];
stylesheet.styleUrls.forEach((styleUrl) => {
const exprIndex = styleExpressions.length;
// Note: This placeholder will be filled later.
styleExpressions.push(null);
dependencies.push(new StylesCompileDependency(getStylesVarName(null), styleUrl, (value) => styleExpressions[exprIndex] = outputCtx.importExpr(value)));
});
// styles variable contains plain strings and arrays of other styles arrays (recursive),
// so we set its type to dynamic.
const stylesVar = getStylesVarName(isComponentStylesheet ? comp : null);
const stmt = variable(stylesVar)
.set(literalArr(styleExpressions, new ArrayType(DYNAMIC_TYPE, [TypeModifier.Const])))
.toDeclStmt(null, isComponentStylesheet ? [StmtModifier.Final] : [
StmtModifier.Final, StmtModifier.Exported
]);
outputCtx.statements.push(stmt);
return new CompiledStylesheet(outputCtx, stylesVar, dependencies, shim, stylesheet);
}
_shimIfNeeded(style, shim) {
return shim ? this._shadowCss.shimCssText(style, CONTENT_ATTR, HOST_ATTR) : style;
}
}
function getStylesVarName(component) {
let result = `styles`;
if (component) {
result += `_${identifierName(component.type)}`;
}
return result;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A path is an ordered set of elements. Typically a path is to a
* particular offset in a source file. The head of the list is the top
* most node. The tail is the node that contains the offset directly.
*
* For example, the expression `a + b + c` might have an ast that looks
* like:
* +
* / \
* a +
* / \
* b c
*
* The path to the node at offset 9 would be `['+' at 1-10, '+' at 7-10,
* 'c' at 9-10]` and the path the node at offset 1 would be
* `['+' at 1-10, 'a' at 1-2]`.
*/
class AstPath {
constructor(path, position = -1) {
this.path = path;
this.position = position;
}
get empty() {
return !this.path || !this.path.length;
}
get head() {
return this.path[0];
}
get tail() {
return this.path[this.path.length - 1];
}
parentOf(node) {
return node && this.path[this.path.indexOf(node) - 1];
}
childOf(node) {
return this.path[this.path.indexOf(node) + 1];
}
first(ctor) {
for (let i = this.path.length - 1; i >= 0; i--) {
let item = this.path[i];
if (item instanceof ctor)
return item;
}
}
push(node) {
this.path.push(node);
}
pop() {
return this.path.pop();
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class NodeWithI18n {
constructor(sourceSpan, i18n) {
this.sourceSpan = sourceSpan;
this.i18n = i18n;
}
}
class Text$3 extends NodeWithI18n {
constructor(value, sourceSpan, i18n) {
super(sourceSpan, i18n);
this.value = value;
}
visit(visitor, context) {
return visitor.visitText(this, context);
}
}
class Expansion extends NodeWithI18n {
constructor(switchValue, type, cases, sourceSpan, switchValueSourceSpan, i18n) {
super(sourceSpan, i18n);
this.switchValue = switchValue;
this.type = type;
this.cases = cases;
this.switchValueSourceSpan = switchValueSourceSpan;
}
visit(visitor, context) {
return visitor.visitExpansion(this, context);
}
}
class ExpansionCase {
constructor(value, expression, sourceSpan, valueSourceSpan, expSourceSpan) {
this.value = value;
this.expression = expression;
this.sourceSpan = sourceSpan;
this.valueSourceSpan = valueSourceSpan;
this.expSourceSpan = expSourceSpan;
}
visit(visitor, context) {
return visitor.visitExpansionCase(this, context);
}
}
class Attribute extends NodeWithI18n {
constructor(name, value, sourceSpan, valueSpan, i18n) {
super(sourceSpan, i18n);
this.name = name;
this.value = value;
this.valueSpan = valueSpan;
}
visit(visitor, context) {
return visitor.visitAttribute(this, context);
}
}
class Element$1 extends NodeWithI18n {
constructor(name, attrs, children, sourceSpan, startSourceSpan = null, endSourceSpan = null, i18n) {
super(sourceSpan, i18n);
this.name = name;
this.attrs = attrs;
this.children = children;
this.startSourceSpan = startSourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitElement(this, context);
}
}
class Comment {
constructor(value, sourceSpan) {
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitComment(this, context);
}
}
function visitAll$1(visitor, nodes, context = null) {
const result = [];
const visit = visitor.visit ?
(ast) => visitor.visit(ast, context) || ast.visit(visitor, context) :
(ast) => ast.visit(visitor, context);
nodes.forEach(ast => {
const astResult = visit(ast);
if (astResult) {
result.push(astResult);
}
});
return result;
}
class RecursiveVisitor$1 {
constructor() { }
visitElement(ast, context) {
this.visitChildren(context, visit => {
visit(ast.attrs);
visit(ast.children);
});
}
visitAttribute(ast, context) { }
visitText(ast, context) { }
visitComment(ast, context) { }
visitExpansion(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.cases);
});
}
visitExpansionCase(ast, context) { }
visitChildren(context, cb) {
let results = [];
let t = this;
function visit(children) {
if (children)
results.push(visitAll$1(t, children, context));
}
cb(visit);
return Array.prototype.concat.apply([], results);
}
}
function spanOf(ast) {
const start = ast.sourceSpan.start.offset;
let end = ast.sourceSpan.end.offset;
if (ast instanceof Element$1) {
if (ast.endSourceSpan) {
end = ast.endSourceSpan.end.offset;
}
else if (ast.children && ast.children.length) {
end = spanOf(ast.children[ast.children.length - 1]).end;
}
}
return { start, end };
}
function findNode(nodes, position) {
const path = [];
const visitor = new class extends RecursiveVisitor$1 {
visit(ast, context) {
const span = spanOf(ast);
if (span.start <= position && position < span.end) {
path.push(ast);
}
else {
// Returning a value here will result in the children being skipped.
return true;
}
}
};
visitAll$1(visitor, nodes);
return new AstPath(path, position);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var TokenType;
(function (TokenType) {
TokenType[TokenType["TAG_OPEN_START"] = 0] = "TAG_OPEN_START";
TokenType[TokenType["TAG_OPEN_END"] = 1] = "TAG_OPEN_END";
TokenType[TokenType["TAG_OPEN_END_VOID"] = 2] = "TAG_OPEN_END_VOID";
TokenType[TokenType["TAG_CLOSE"] = 3] = "TAG_CLOSE";
TokenType[TokenType["TEXT"] = 4] = "TEXT";
TokenType[TokenType["ESCAPABLE_RAW_TEXT"] = 5] = "ESCAPABLE_RAW_TEXT";
TokenType[TokenType["RAW_TEXT"] = 6] = "RAW_TEXT";
TokenType[TokenType["COMMENT_START"] = 7] = "COMMENT_START";
TokenType[TokenType["COMMENT_END"] = 8] = "COMMENT_END";
TokenType[TokenType["CDATA_START"] = 9] = "CDATA_START";
TokenType[TokenType["CDATA_END"] = 10] = "CDATA_END";
TokenType[TokenType["ATTR_NAME"] = 11] = "ATTR_NAME";
TokenType[TokenType["ATTR_QUOTE"] = 12] = "ATTR_QUOTE";
TokenType[TokenType["ATTR_VALUE"] = 13] = "ATTR_VALUE";
TokenType[TokenType["DOC_TYPE"] = 14] = "DOC_TYPE";
TokenType[TokenType["EXPANSION_FORM_START"] = 15] = "EXPANSION_FORM_START";
TokenType[TokenType["EXPANSION_CASE_VALUE"] = 16] = "EXPANSION_CASE_VALUE";
TokenType[TokenType["EXPANSION_CASE_EXP_START"] = 17] = "EXPANSION_CASE_EXP_START";
TokenType[TokenType["EXPANSION_CASE_EXP_END"] = 18] = "EXPANSION_CASE_EXP_END";
TokenType[TokenType["EXPANSION_FORM_END"] = 19] = "EXPANSION_FORM_END";
TokenType[TokenType["EOF"] = 20] = "EOF";
})(TokenType || (TokenType = {}));
class Token {
constructor(type, parts, sourceSpan) {
this.type = type;
this.parts = parts;
this.sourceSpan = sourceSpan;
}
}
class TokenError extends ParseError {
constructor(errorMsg, tokenType, span) {
super(span, errorMsg);
this.tokenType = tokenType;
}
}
class TokenizeResult {
constructor(tokens, errors, nonNormalizedIcuExpressions) {
this.tokens = tokens;
this.errors = errors;
this.nonNormalizedIcuExpressions = nonNormalizedIcuExpressions;
}
}
function tokenize(source, url, getTagDefinition, options = {}) {
const tokenizer = new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options);
tokenizer.tokenize();
return new TokenizeResult(mergeTextTokens(tokenizer.tokens), tokenizer.errors, tokenizer.nonNormalizedIcuExpressions);
}
const _CR_OR_CRLF_REGEXP = /\r\n?/g;
function _unexpectedCharacterErrorMsg(charCode) {
const char = charCode === $EOF ? 'EOF' : String.fromCharCode(charCode);
return `Unexpected character "${char}"`;
}
function _unknownEntityErrorMsg(entitySrc) {
return `Unknown entity "${entitySrc}" - use the ";" or ";" syntax`;
}
function _unparsableEntityErrorMsg(type, entityStr) {
return `Unable to parse entity "${entityStr}" - ${type} character reference entities must end with ";"`;
}
var CharacterReferenceType;
(function (CharacterReferenceType) {
CharacterReferenceType["HEX"] = "hexadecimal";
CharacterReferenceType["DEC"] = "decimal";
})(CharacterReferenceType || (CharacterReferenceType = {}));
class _ControlFlowError {
constructor(error) {
this.error = error;
}
}
// See http://www.w3.org/TR/html51/syntax.html#writing
class _Tokenizer {
/**
* @param _file The html source file being tokenized.
* @param _getTagDefinition A function that will retrieve a tag definition for a given tag name.
* @param options Configuration of the tokenization.
*/
constructor(_file, _getTagDefinition, options) {
this._getTagDefinition = _getTagDefinition;
this._currentTokenStart = null;
this._currentTokenType = null;
this._expansionCaseStack = [];
this._inInterpolation = false;
this.tokens = [];
this.errors = [];
this.nonNormalizedIcuExpressions = [];
this._tokenizeIcu = options.tokenizeExpansionForms || false;
this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
this._leadingTriviaCodePoints =
options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0);
const range = options.range || { endPos: _file.content.length, startPos: 0, startLine: 0, startCol: 0 };
this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) :
new PlainCharacterCursor(_file, range);
this._preserveLineEndings = options.preserveLineEndings || false;
this._escapedString = options.escapedString || false;
this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
try {
this._cursor.init();
}
catch (e) {
this.handleError(e);
}
}
_processCarriageReturns(content) {
if (this._preserveLineEndings) {
return content;
}
// http://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream
// In order to keep the original position in the source, we can not
// pre-process it.
// Instead CRs are processed right before instantiating the tokens.
return content.replace(_CR_OR_CRLF_REGEXP, '\n');
}
tokenize() {
while (this._cursor.peek() !== $EOF) {
const start = this._cursor.clone();
try {
if (this._attemptCharCode($LT)) {
if (this._attemptCharCode($BANG)) {
if (this._attemptCharCode($LBRACKET)) {
this._consumeCdata(start);
}
else if (this._attemptCharCode($MINUS)) {
this._consumeComment(start);
}
else {
this._consumeDocType(start);
}
}
else if (this._attemptCharCode($SLASH)) {
this._consumeTagClose(start);
}
else {
this._consumeTagOpen(start);
}
}
else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
this._consumeText();
}
}
catch (e) {
this.handleError(e);
}
}
this._beginToken(TokenType.EOF);
this._endToken([]);
}
/**
* @returns whether an ICU token has been created
* @internal
*/
_tokenizeExpansionForm() {
if (this.isExpansionFormStart()) {
this._consumeExpansionFormStart();
return true;
}
if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) {
this._consumeExpansionCaseStart();
return true;
}
if (this._cursor.peek() === $RBRACE) {
if (this._isInExpansionCase()) {
this._consumeExpansionCaseEnd();
return true;
}
if (this._isInExpansionForm()) {
this._consumeExpansionFormEnd();
return true;
}
}
return false;
}
_beginToken(type, start = this._cursor.clone()) {
this._currentTokenStart = start;
this._currentTokenType = type;
}
_endToken(parts, end) {
if (this._currentTokenStart === null) {
throw new TokenError('Programming error - attempted to end a token when there was no start to the token', this._currentTokenType, this._cursor.getSpan(end));
}
if (this._currentTokenType === null) {
throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart));
}
const token = new Token(this._currentTokenType, parts, this._cursor.getSpan(this._currentTokenStart, this._leadingTriviaCodePoints));
this.tokens.push(token);
this._currentTokenStart = null;
this._currentTokenType = null;
return token;
}
_createError(msg, span) {
if (this._isInExpansionForm()) {
msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
}
const error = new TokenError(msg, this._currentTokenType, span);
this._currentTokenStart = null;
this._currentTokenType = null;
return new _ControlFlowError(error);
}
handleError(e) {
if (e instanceof CursorError) {
e = this._createError(e.msg, this._cursor.getSpan(e.cursor));
}
if (e instanceof _ControlFlowError) {
this.errors.push(e.error);
}
else {
throw e;
}
}
_attemptCharCode(charCode) {
if (this._cursor.peek() === charCode) {
this._cursor.advance();
return true;
}
return false;
}
_attemptCharCodeCaseInsensitive(charCode) {
if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) {
this._cursor.advance();
return true;
}
return false;
}
_requireCharCode(charCode) {
const location = this._cursor.clone();
if (!this._attemptCharCode(charCode)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptStr(chars) {
const len = chars.length;
if (this._cursor.charsLeft() < len) {
return false;
}
const initialPosition = this._cursor.clone();
for (let i = 0; i < len; i++) {
if (!this._attemptCharCode(chars.charCodeAt(i))) {
// If attempting to parse the string fails, we want to reset the parser
// to where it was before the attempt
this._cursor = initialPosition;
return false;
}
}
return true;
}
_attemptStrCaseInsensitive(chars) {
for (let i = 0; i < chars.length; i++) {
if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) {
return false;
}
}
return true;
}
_requireStr(chars) {
const location = this._cursor.clone();
if (!this._attemptStr(chars)) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
}
}
_attemptCharCodeUntilFn(predicate) {
while (!predicate(this._cursor.peek())) {
this._cursor.advance();
}
}
_requireCharCodeUntilFn(predicate, len) {
const start = this._cursor.clone();
this._attemptCharCodeUntilFn(predicate);
if (this._cursor.diff(start) < len) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
}
_attemptUntilChar(char) {
while (this._cursor.peek() !== char) {
this._cursor.advance();
}
}
_readChar(decodeEntities) {
if (decodeEntities && this._cursor.peek() === $AMPERSAND) {
return this._decodeEntity();
}
else {
// Don't rely upon reading directly from `_input` as the actual char value
// may have been generated from an escape sequence.
const char = String.fromCodePoint(this._cursor.peek());
this._cursor.advance();
return char;
}
}
_decodeEntity() {
const start = this._cursor.clone();
this._cursor.advance();
if (this._attemptCharCode($HASH)) {
const isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
const codeStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isDigitEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
// Advance cursor to include the peeked character in the string provided to the error
// message.
this._cursor.advance();
const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC;
throw this._createError(_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), this._cursor.getSpan());
}
const strNum = this._cursor.getChars(codeStart);
this._cursor.advance();
try {
const charCode = parseInt(strNum, isHex ? 16 : 10);
return String.fromCharCode(charCode);
}
catch (_a) {
throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
}
}
else {
const nameStart = this._cursor.clone();
this._attemptCharCodeUntilFn(isNamedEntityEnd);
if (this._cursor.peek() != $SEMICOLON) {
this._cursor = nameStart;
return '&';
}
const name = this._cursor.getChars(nameStart);
this._cursor.advance();
const char = NAMED_ENTITIES[name];
if (!char) {
throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
}
return char;
}
}
_consumeRawText(decodeEntities, endMarkerPredicate) {
this._beginToken(decodeEntities ? TokenType.ESCAPABLE_RAW_TEXT : TokenType.RAW_TEXT);
const parts = [];
while (true) {
const tagCloseStart = this._cursor.clone();
const foundEndMarker = endMarkerPredicate();
this._cursor = tagCloseStart;
if (foundEndMarker) {
break;
}
parts.push(this._readChar(decodeEntities));
}
return this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_consumeComment(start) {
this._beginToken(TokenType.COMMENT_START, start);
this._requireCharCode($MINUS);
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr('-->'));
this._beginToken(TokenType.COMMENT_END);
this._requireStr('-->');
this._endToken([]);
}
_consumeCdata(start) {
this._beginToken(TokenType.CDATA_START, start);
this._requireStr('CDATA[');
this._endToken([]);
this._consumeRawText(false, () => this._attemptStr(']]>'));
this._beginToken(TokenType.CDATA_END);
this._requireStr(']]>');
this._endToken([]);
}
_consumeDocType(start) {
this._beginToken(TokenType.DOC_TYPE, start);
const contentStart = this._cursor.clone();
this._attemptUntilChar($GT);
const content = this._cursor.getChars(contentStart);
this._cursor.advance();
this._endToken([content]);
}
_consumePrefixAndName() {
const nameOrPrefixStart = this._cursor.clone();
let prefix = '';
while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
this._cursor.advance();
}
let nameStart;
if (this._cursor.peek() === $COLON) {
prefix = this._cursor.getChars(nameOrPrefixStart);
this._cursor.advance();
nameStart = this._cursor.clone();
}
else {
nameStart = nameOrPrefixStart;
}
this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
const name = this._cursor.getChars(nameStart);
return [prefix, name];
}
_consumeTagOpen(start) {
let tagName;
let prefix;
let openTagToken;
let tokensBeforeTagOpen = this.tokens.length;
const innerStart = this._cursor.clone();
try {
if (!isAsciiLetter(this._cursor.peek())) {
throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
}
openTagToken = this._consumeTagOpenStart(start);
prefix = openTagToken.parts[0];
tagName = openTagToken.parts[1];
this._attemptCharCodeUntilFn(isNotWhitespace);
while (this._cursor.peek() !== $SLASH && this._cursor.peek() !== $GT) {
this._consumeAttributeName();
this._attemptCharCodeUntilFn(isNotWhitespace);
if (this._attemptCharCode($EQ)) {
this._attemptCharCodeUntilFn(isNotWhitespace);
this._consumeAttributeValue();
}
this._attemptCharCodeUntilFn(isNotWhitespace);
}
this._consumeTagOpenEnd();
}
catch (e) {
if (e instanceof _ControlFlowError) {
// When the start tag is invalid (including invalid "attributes"), assume we want a "<"
this._cursor = innerStart;
if (openTagToken) {
this.tokens.length = tokensBeforeTagOpen;
}
// Back to back text tokens are merged at the end
this._beginToken(TokenType.TEXT, start);
this._endToken(['<']);
return;
}
throw e;
}
const contentTokenType = this._getTagDefinition(tagName).contentType;
if (contentTokenType === TagContentType.RAW_TEXT) {
this._consumeRawTextWithTagClose(prefix, tagName, false);
}
else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
this._consumeRawTextWithTagClose(prefix, tagName, true);
}
}
_consumeRawTextWithTagClose(prefix, tagName, decodeEntities) {
const textToken = this._consumeRawText(decodeEntities, () => {
if (!this._attemptCharCode($LT))
return false;
if (!this._attemptCharCode($SLASH))
return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
if (!this._attemptStrCaseInsensitive(tagName))
return false;
this._attemptCharCodeUntilFn(isNotWhitespace);
return this._attemptCharCode($GT);
});
this._beginToken(TokenType.TAG_CLOSE);
this._requireCharCodeUntilFn(code => code === $GT, 3);
this._cursor.advance(); // Consume the `>`
this._endToken([prefix, tagName]);
}
_consumeTagOpenStart(start) {
this._beginToken(TokenType.TAG_OPEN_START, start);
const parts = this._consumePrefixAndName();
return this._endToken(parts);
}
_consumeAttributeName() {
const attrNameStart = this._cursor.peek();
if (attrNameStart === $SQ || attrNameStart === $DQ) {
throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
}
this._beginToken(TokenType.ATTR_NAME);
const prefixAndName = this._consumePrefixAndName();
this._endToken(prefixAndName);
}
_consumeAttributeValue() {
let value;
if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) {
this._beginToken(TokenType.ATTR_QUOTE);
const quoteChar = this._cursor.peek();
this._cursor.advance();
this._endToken([String.fromCodePoint(quoteChar)]);
this._beginToken(TokenType.ATTR_VALUE);
const parts = [];
while (this._cursor.peek() !== quoteChar) {
parts.push(this._readChar(true));
}
value = parts.join('');
this._endToken([this._processCarriageReturns(value)]);
this._beginToken(TokenType.ATTR_QUOTE);
this._cursor.advance();
this._endToken([String.fromCodePoint(quoteChar)]);
}
else {
this._beginToken(TokenType.ATTR_VALUE);
const valueStart = this._cursor.clone();
this._requireCharCodeUntilFn(isNameEnd, 1);
value = this._cursor.getChars(valueStart);
this._endToken([this._processCarriageReturns(value)]);
}
}
_consumeTagOpenEnd() {
const tokenType = this._attemptCharCode($SLASH) ? TokenType.TAG_OPEN_END_VOID : TokenType.TAG_OPEN_END;
this._beginToken(tokenType);
this._requireCharCode($GT);
this._endToken([]);
}
_consumeTagClose(start) {
this._beginToken(TokenType.TAG_CLOSE, start);
this._attemptCharCodeUntilFn(isNotWhitespace);
const prefixAndName = this._consumePrefixAndName();
this._attemptCharCodeUntilFn(isNotWhitespace);
this._requireCharCode($GT);
this._endToken(prefixAndName);
}
_consumeExpansionFormStart() {
this._beginToken(TokenType.EXPANSION_FORM_START);
this._requireCharCode($LBRACE);
this._endToken([]);
this._expansionCaseStack.push(TokenType.EXPANSION_FORM_START);
this._beginToken(TokenType.RAW_TEXT);
const condition = this._readUntil($COMMA);
const normalizedCondition = this._processCarriageReturns(condition);
if (this._escapedString || this._i18nNormalizeLineEndingsInICUs) {
// Either the template is inline or,
// we explicitly want to normalize line endings for this text.
this._endToken([normalizedCondition]);
}
else {
// The expression is in an external template and, for backward compatibility,
// we are not normalizing line endings.
const conditionToken = this._endToken([condition]);
if (normalizedCondition !== condition) {
this.nonNormalizedIcuExpressions.push(conditionToken);
}
}
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(TokenType.RAW_TEXT);
const type = this._readUntil($COMMA);
this._endToken([type]);
this._requireCharCode($COMMA);
this._attemptCharCodeUntilFn(isNotWhitespace);
}
_consumeExpansionCaseStart() {
this._beginToken(TokenType.EXPANSION_CASE_VALUE);
const value = this._readUntil($LBRACE).trim();
this._endToken([value]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._beginToken(TokenType.EXPANSION_CASE_EXP_START);
this._requireCharCode($LBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.push(TokenType.EXPANSION_CASE_EXP_START);
}
_consumeExpansionCaseEnd() {
this._beginToken(TokenType.EXPANSION_CASE_EXP_END);
this._requireCharCode($RBRACE);
this._endToken([]);
this._attemptCharCodeUntilFn(isNotWhitespace);
this._expansionCaseStack.pop();
}
_consumeExpansionFormEnd() {
this._beginToken(TokenType.EXPANSION_FORM_END);
this._requireCharCode($RBRACE);
this._endToken([]);
this._expansionCaseStack.pop();
}
_consumeText() {
const start = this._cursor.clone();
this._beginToken(TokenType.TEXT, start);
const parts = [];
do {
if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
parts.push(this._interpolationConfig.start);
this._inInterpolation = true;
}
else if (this._interpolationConfig && this._inInterpolation &&
this._attemptStr(this._interpolationConfig.end)) {
parts.push(this._interpolationConfig.end);
this._inInterpolation = false;
}
else {
parts.push(this._readChar(true));
}
} while (!this._isTextEnd());
this._endToken([this._processCarriageReturns(parts.join(''))]);
}
_isTextEnd() {
if (this._cursor.peek() === $LT || this._cursor.peek() === $EOF) {
return true;
}
if (this._tokenizeIcu && !this._inInterpolation) {
if (this.isExpansionFormStart()) {
// start of an expansion form
return true;
}
if (this._cursor.peek() === $RBRACE && this._isInExpansionCase()) {
// end of and expansion case
return true;
}
}
return false;
}
_readUntil(char) {
const start = this._cursor.clone();
this._attemptUntilChar(char);
return this._cursor.getChars(start);
}
_isInExpansionCase() {
return this._expansionCaseStack.length > 0 &&
this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
TokenType.EXPANSION_CASE_EXP_START;
}
_isInExpansionForm() {
return this._expansionCaseStack.length > 0 &&
this._expansionCaseStack[this._expansionCaseStack.length - 1] ===
TokenType.EXPANSION_FORM_START;
}
isExpansionFormStart() {
if (this._cursor.peek() !== $LBRACE) {
return false;
}
if (this._interpolationConfig) {
const start = this._cursor.clone();
const isInterpolation = this._attemptStr(this._interpolationConfig.start);
this._cursor = start;
return !isInterpolation;
}
return true;
}
}
function isNotWhitespace(code) {
return !isWhitespace(code) || code === $EOF;
}
function isNameEnd(code) {
return isWhitespace(code) || code === $GT || code === $SLASH ||
code === $SQ || code === $DQ || code === $EQ;
}
function isPrefixEnd(code) {
return (code < $a || $z < code) && (code < $A || $Z < code) &&
(code < $0 || code > $9);
}
function isDigitEntityEnd(code) {
return code == $SEMICOLON || code == $EOF || !isAsciiHexDigit(code);
}
function isNamedEntityEnd(code) {
return code == $SEMICOLON || code == $EOF || !isAsciiLetter(code);
}
function isExpansionCaseStart(peek) {
return peek !== $RBRACE;
}
function compareCharCodeCaseInsensitive(code1, code2) {
return toUpperCaseCharCode(code1) == toUpperCaseCharCode(code2);
}
function toUpperCaseCharCode(code) {
return code >= $a && code <= $z ? code - $a + $A : code;
}
function mergeTextTokens(srcTokens) {
const dstTokens = [];
let lastDstToken = undefined;
for (let i = 0; i < srcTokens.length; i++) {
const token = srcTokens[i];
if (lastDstToken && lastDstToken.type == TokenType.TEXT && token.type == TokenType.TEXT) {
lastDstToken.parts[0] += token.parts[0];
lastDstToken.sourceSpan.end = token.sourceSpan.end;
}
else {
lastDstToken = token;
dstTokens.push(lastDstToken);
}
}
return dstTokens;
}
class PlainCharacterCursor {
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof PlainCharacterCursor) {
this.file = fileOrCursor.file;
this.input = fileOrCursor.input;
this.end = fileOrCursor.end;
const state = fileOrCursor.state;
// Note: avoid using `{...fileOrCursor.state}` here as that has a severe performance penalty.
// In ES5 bundles the object spread operator is translated into the `__assign` helper, which
// is not optimized by VMs as efficiently as a raw object literal. Since this constructor is
// called in tight loops, this difference matters.
this.state = {
peek: state.peek,
offset: state.offset,
line: state.line,
column: state.column,
};
}
else {
if (!range) {
throw new Error('Programming error: the range argument must be provided with a file argument.');
}
this.file = fileOrCursor;
this.input = fileOrCursor.content;
this.end = range.endPos;
this.state = {
peek: -1,
offset: range.startPos,
line: range.startLine,
column: range.startCol,
};
}
}
clone() {
return new PlainCharacterCursor(this);
}
peek() {
return this.state.peek;
}
charsLeft() {
return this.end - this.state.offset;
}
diff(other) {
return this.state.offset - other.state.offset;
}
advance() {
this.advanceState(this.state);
}
init() {
this.updatePeek(this.state);
}
getSpan(start, leadingTriviaCodePoints) {
start = start || this;
let cloned = false;
if (leadingTriviaCodePoints) {
while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) {
if (!cloned) {
start = start.clone();
cloned = true;
}
start.advance();
}
}
return new ParseSourceSpan(new ParseLocation(start.file, start.state.offset, start.state.line, start.state.column), new ParseLocation(this.file, this.state.offset, this.state.line, this.state.column));
}
getChars(start) {
return this.input.substring(start.state.offset, this.state.offset);
}
charAt(pos) {
return this.input.charCodeAt(pos);
}
advanceState(state) {
if (state.offset >= this.end) {
this.state = state;
throw new CursorError('Unexpected character "EOF"', this);
}
const currentChar = this.charAt(state.offset);
if (currentChar === $LF) {
state.line++;
state.column = 0;
}
else if (!isNewLine(currentChar)) {
state.column++;
}
state.offset++;
this.updatePeek(state);
}
updatePeek(state) {
state.peek = state.offset >= this.end ? $EOF : this.charAt(state.offset);
}
}
class EscapedCharacterCursor extends PlainCharacterCursor {
constructor(fileOrCursor, range) {
if (fileOrCursor instanceof EscapedCharacterCursor) {
super(fileOrCursor);
this.internalState = Object.assign({}, fileOrCursor.internalState);
}
else {
super(fileOrCursor, range);
this.internalState = this.state;
}
}
advance() {
this.state = this.internalState;
super.advance();
this.processEscapeSequence();
}
init() {
super.init();
this.processEscapeSequence();
}
clone() {
return new EscapedCharacterCursor(this);
}
getChars(start) {
const cursor = start.clone();
let chars = '';
while (cursor.internalState.offset < this.internalState.offset) {
chars += String.fromCodePoint(cursor.peek());
cursor.advance();
}
return chars;
}
/**
* Process the escape sequence that starts at the current position in the text.
*
* This method is called to ensure that `peek` has the unescaped value of escape sequences.
*/
processEscapeSequence() {
const peek = () => this.internalState.peek;
if (peek() === $BACKSLASH) {
// We have hit an escape sequence so we need the internal state to become independent
// of the external state.
this.internalState = Object.assign({}, this.state);
// Move past the backslash
this.advanceState(this.internalState);
// First check for standard control char sequences
if (peek() === $n) {
this.state.peek = $LF;
}
else if (peek() === $r) {
this.state.peek = $CR;
}
else if (peek() === $v) {
this.state.peek = $VTAB;
}
else if (peek() === $t) {
this.state.peek = $TAB;
}
else if (peek() === $b) {
this.state.peek = $BSPACE;
}
else if (peek() === $f) {
this.state.peek = $FF;
}
// Now consider more complex sequences
else if (peek() === $u) {
// Unicode code-point sequence
this.advanceState(this.internalState); // advance past the `u` char
if (peek() === $LBRACE) {
// Variable length Unicode, e.g. `\x{123}`
this.advanceState(this.internalState); // advance past the `{` char
// Advance past the variable number of hex digits until we hit a `}` char
const digitStart = this.clone();
let length = 0;
while (peek() !== $RBRACE) {
this.advanceState(this.internalState);
length++;
}
this.state.peek = this.decodeHexDigits(digitStart, length);
}
else {
// Fixed length Unicode, e.g. `\u1234`
const digitStart = this.clone();
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 4);
}
}
else if (peek() === $x) {
// Hex char code, e.g. `\x2F`
this.advanceState(this.internalState); // advance past the `x` char
const digitStart = this.clone();
this.advanceState(this.internalState);
this.state.peek = this.decodeHexDigits(digitStart, 2);
}
else if (isOctalDigit(peek())) {
// Octal char code, e.g. `\012`,
let octal = '';
let length = 0;
let previous = this.clone();
while (isOctalDigit(peek()) && length < 3) {
previous = this.clone();
octal += String.fromCodePoint(peek());
this.advanceState(this.internalState);
length++;
}
this.state.peek = parseInt(octal, 8);
// Backup one char
this.internalState = previous.internalState;
}
else if (isNewLine(this.internalState.peek)) {
// Line continuation `\` followed by a new line
this.advanceState(this.internalState); // advance over the newline
this.state = this.internalState;
}
else {
// If none of the `if` blocks were executed then we just have an escaped normal character.
// In that case we just, effectively, skip the backslash from the character.
this.state.peek = this.internalState.peek;
}
}
}
decodeHexDigits(start, length) {
const hex = this.input.substr(start.internalState.offset, length);
const charCode = parseInt(hex, 16);
if (!isNaN(charCode)) {
return charCode;
}
else {
start.state = start.internalState;
throw new CursorError('Invalid hexadecimal escape sequence', start);
}
}
}
class CursorError {
constructor(msg, cursor) {
this.msg = msg;
this.cursor = cursor;
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class TreeError extends ParseError {
constructor(elementName, span, msg) {
super(span, msg);
this.elementName = elementName;
}
static create(elementName, span, msg) {
return new TreeError(elementName, span, msg);
}
}
class ParseTreeResult {
constructor(rootNodes, errors) {
this.rootNodes = rootNodes;
this.errors = errors;
}
}
class Parser {
constructor(getTagDefinition) {
this.getTagDefinition = getTagDefinition;
}
parse(source, url, options) {
const tokenizeResult = tokenize(source, url, this.getTagDefinition, options);
const parser = new _TreeBuilder(tokenizeResult.tokens, this.getTagDefinition);
parser.build();
return new ParseTreeResult(parser.rootNodes, tokenizeResult.errors.concat(parser.errors));
}
}
class _TreeBuilder {
constructor(tokens, getTagDefinition) {
this.tokens = tokens;
this.getTagDefinition = getTagDefinition;
this._index = -1;
this._elementStack = [];
this.rootNodes = [];
this.errors = [];
this._advance();
}
build() {
while (this._peek.type !== TokenType.EOF) {
if (this._peek.type === TokenType.TAG_OPEN_START) {
this._consumeStartTag(this._advance());
}
else if (this._peek.type === TokenType.TAG_CLOSE) {
this._consumeEndTag(this._advance());
}
else if (this._peek.type === TokenType.CDATA_START) {
this._closeVoidElement();
this._consumeCdata(this._advance());
}
else if (this._peek.type === TokenType.COMMENT_START) {
this._closeVoidElement();
this._consumeComment(this._advance());
}
else if (this._peek.type === TokenType.TEXT || this._peek.type === TokenType.RAW_TEXT ||
this._peek.type === TokenType.ESCAPABLE_RAW_TEXT) {
this._closeVoidElement();
this._consumeText(this._advance());
}
else if (this._peek.type === TokenType.EXPANSION_FORM_START) {
this._consumeExpansion(this._advance());
}
else {
// Skip all other tokens...
this._advance();
}
}
}
_advance() {
const prev = this._peek;
if (this._index < this.tokens.length - 1) {
// Note: there is always an EOF token at the end
this._index++;
}
this._peek = this.tokens[this._index];
return prev;
}
_advanceIf(type) {
if (this._peek.type === type) {
return this._advance();
}
return null;
}
_consumeCdata(_startToken) {
this._consumeText(this._advance());
this._advanceIf(TokenType.CDATA_END);
}
_consumeComment(token) {
const text = this._advanceIf(TokenType.RAW_TEXT);
this._advanceIf(TokenType.COMMENT_END);
const value = text != null ? text.parts[0].trim() : null;
this._addToParent(new Comment(value, token.sourceSpan));
}
_consumeExpansion(token) {
const switchValue = this._advance();
const type = this._advance();
const cases = [];
// read =
while (this._peek.type === TokenType.EXPANSION_CASE_VALUE) {
const expCase = this._parseExpansionCase();
if (!expCase)
return; // error
cases.push(expCase);
}
// read the final }
if (this._peek.type !== TokenType.EXPANSION_FORM_END) {
this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`));
return;
}
const sourceSpan = new ParseSourceSpan(token.sourceSpan.start, this._peek.sourceSpan.end);
this._addToParent(new Expansion(switchValue.parts[0], type.parts[0], cases, sourceSpan, switchValue.sourceSpan));
this._advance();
}
_parseExpansionCase() {
const value = this._advance();
// read {
if (this._peek.type !== TokenType.EXPANSION_CASE_EXP_START) {
this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`));
return null;
}
// read until }
const start = this._advance();
const exp = this._collectExpansionExpTokens(start);
if (!exp)
return null;
const end = this._advance();
exp.push(new Token(TokenType.EOF, [], end.sourceSpan));
// parse everything in between { and }
const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
expansionCaseParser.build();
if (expansionCaseParser.errors.length > 0) {
this.errors = this.errors.concat(expansionCaseParser.errors);
return null;
}
const sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end);
const expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end);
return new ExpansionCase(value.parts[0], expansionCaseParser.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
}
_collectExpansionExpTokens(start) {
const exp = [];
const expansionFormStack = [TokenType.EXPANSION_CASE_EXP_START];
while (true) {
if (this._peek.type === TokenType.EXPANSION_FORM_START ||
this._peek.type === TokenType.EXPANSION_CASE_EXP_START) {
expansionFormStack.push(this._peek.type);
}
if (this._peek.type === TokenType.EXPANSION_CASE_EXP_END) {
if (lastOnStack(expansionFormStack, TokenType.EXPANSION_CASE_EXP_START)) {
expansionFormStack.pop();
if (expansionFormStack.length == 0)
return exp;
}
else {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === TokenType.EXPANSION_FORM_END) {
if (lastOnStack(expansionFormStack, TokenType.EXPANSION_FORM_START)) {
expansionFormStack.pop();
}
else {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
}
if (this._peek.type === TokenType.EOF) {
this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
return null;
}
exp.push(this._advance());
}
}
_consumeText(token) {
let text = token.parts[0];
if (text.length > 0 && text[0] == '\n') {
const parent = this._getParentElement();
if (parent != null && parent.children.length == 0 &&
this.getTagDefinition(parent.name).ignoreFirstLf) {
text = text.substring(1);
}
}
if (text.length > 0) {
this._addToParent(new Text$3(text, token.sourceSpan));
}
}
_closeVoidElement() {
const el = this._getParentElement();
if (el && this.getTagDefinition(el.name).isVoid) {
this._elementStack.pop();
}
}
_consumeStartTag(startTagToken) {
const prefix = startTagToken.parts[0];
const name = startTagToken.parts[1];
const attrs = [];
while (this._peek.type === TokenType.ATTR_NAME) {
attrs.push(this._consumeAttr(this._advance()));
}
const fullName = this._getElementFullName(prefix, name, this._getParentElement());
let selfClosing = false;
// Note: There could have been a tokenizer error
// so that we don't get a token for the end tag...
if (this._peek.type === TokenType.TAG_OPEN_END_VOID) {
this._advance();
selfClosing = true;
const tagDef = this.getTagDefinition(fullName);
if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) {
this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
}
}
else if (this._peek.type === TokenType.TAG_OPEN_END) {
this._advance();
selfClosing = false;
}
const end = this._peek.sourceSpan.start;
const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end);
const el = new Element$1(fullName, attrs, [], span, span, undefined);
this._pushElement(el);
if (selfClosing) {
// Elements that are self-closed have their `endSourceSpan` set to the full span, as the
// element start tag also represents the end tag.
this._popElement(fullName, span);
}
}
_pushElement(el) {
const parentEl = this._getParentElement();
if (parentEl && this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
this._elementStack.pop();
}
this._addToParent(el);
this._elementStack.push(el);
}
_consumeEndTag(endTagToken) {
const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
if (this.getTagDefinition(fullName).isVoid) {
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
}
else if (!this._popElement(fullName, endTagToken.sourceSpan)) {
const errMsg = `Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
}
}
_popElement(fullName, endSourceSpan) {
for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
const el = this._elementStack[stackIndex];
if (el.name == fullName) {
// Record the parse span with the element that is being closed. Any elements that are
// removed from the element stack at this point are closed implicitly, so they won't get
// an end source span (as there is no explicit closing element).
el.endSourceSpan = endSourceSpan;
this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex);
return true;
}
if (!this.getTagDefinition(el.name).closedByParent) {
return false;
}
}
return false;
}
_consumeAttr(attrName) {
const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
let end = attrName.sourceSpan.end;
let value = '';
let valueSpan = undefined;
if (this._peek.type === TokenType.ATTR_QUOTE) {
this._advance();
}
if (this._peek.type === TokenType.ATTR_VALUE) {
const valueToken = this._advance();
value = valueToken.parts[0];
end = valueToken.sourceSpan.end;
valueSpan = valueToken.sourceSpan;
}
if (this._peek.type === TokenType.ATTR_QUOTE) {
const quoteToken = this._advance();
end = quoteToken.sourceSpan.end;
}
return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, end), valueSpan);
}
_getParentElement() {
return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
}
_addToParent(node) {
const parent = this._getParentElement();
if (parent != null) {
parent.children.push(node);
}
else {
this.rootNodes.push(node);
}
}
_getElementFullName(prefix, localName, parentElement) {
if (prefix === '') {
prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
if (prefix === '' && parentElement != null) {
prefix = getNsPrefix(parentElement.name);
}
}
return mergeNsAndName(prefix, localName);
}
}
function lastOnStack(stack, element) {
return stack.length > 0 && stack[stack.length - 1] === element;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class HtmlParser extends Parser {
constructor() {
super(getHtmlTagDefinition);
}
parse(source, url, options) {
return super.parse(source, url, options);
}
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']);
// Equivalent to \s with \u00a0 (non-breaking space) excluded.
// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff';
const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`);
const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g');
function hasPreserveWhitespacesAttr(attrs) {
return attrs.some((attr) => attr.name === PRESERVE_WS_ATTR_NAME);
}
/**
* Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
* https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
* In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
* and later on replaced by a space. We are re-implementing the same idea here.
*/
function replaceNgsp(value) {
// lexer is replacing the &ngsp; pseudo-entity with NGSP_UNICODE
return value.replace(new RegExp(NGSP_UNICODE, 'g'), ' ');
}
/**
* This visitor can walk HTML parse tree and remove / trim text nodes using the following rules:
* - consider spaces, tabs and new lines as whitespace characters;
* - drop text nodes consisting of whitespace characters only;
* - for all other text nodes replace consecutive whitespace characters with one space;
* - convert &ngsp; pseudo-entity to a single space;
*
* Removal and trimming of whitespaces have positive performance impact (less code to generate
* while compiling templates, faster view creation). At the same time it can be "destructive"
* in some cases (whitespaces can influence layout). Because of the potential of breaking layout
* this visitor is not activated by default in Angular 5 and people need to explicitly opt-in for
* whitespace removal. The default option for whitespace removal will be revisited in Angular 6
* and might be changed to "on" by default.
*/
class WhitespaceVisitor {
visitElement(element, context) {
if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
// don't descent into elements where we need to preserve whitespaces
// but still visit all attributes to eliminate one used as a market to preserve WS
return new Element$1(element.name, visitAll$1(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
}
return new Element$1(element.name, element.attrs, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
}
visitAttribute(attribute, context) {
return attribute.name !== PRESERVE_WS_ATTR_NAME ? attribute : null;
}
visitText(text, context) {
const isNotBlank = text.value.match(NO_WS_REGEXP);
const hasExpansionSibling = context &&
(context.prev instanceof Expansion || context.next instanceof Expansion);
if (isNotBlank || hasExpansionSibling) {
return new Text$3(replaceNgsp(text.value).replace(WS_REPLACE_REGEXP, ' '), text.sourceSpan, text.i18n);
}
return null;
}
visitComment(comment, context) {
return comment;
}
visitExpansion(expansion, context) {
return expansion;
}
visitExpansionCase(expansionCase, context) {
return expansionCase;
}
}
function removeWhitespaces(htmlAstWithErrors) {
return new ParseTreeResult(visitAll$1(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes), htmlAstWithErrors.errors);
}
function visitAllWithSiblings(visitor, nodes) {
const result = [];
nodes.forEach((ast, i) => {
const context = { prev: nodes[i - 1], next: nodes[i + 1] };
const astResult = ast.visit(visitor, context);
if (astResult) {
result.push(astResult);
}
});
return result;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// http://cldr.unicode.org/index/cldr-spec/plural-rules
const PLURAL_CASES = ['zero', 'one', 'two', 'few', 'many', 'other'];
/**
* Expands special forms into elements.
*
* For example,
*
* ```
* { messages.length, plural,
* =0 {zero}
* =1 {one}
* other {more than one}
* }
* ```
*
* will be expanded into
*
* ```
*
* zero
* one
* more than one
*
* ```
*/
function expandNodes(nodes) {
const expander = new _Expander();
return new ExpansionResult(visitAll$1(expander, nodes), expander.isExpanded, expander.errors);
}
class ExpansionResult {
constructor(nodes, expanded, errors) {
this.nodes = nodes;
this.expanded = expanded;
this.errors = errors;
}
}
class ExpansionError extends ParseError {
constructor(span, errorMsg) {
super(span, errorMsg);
}
}
/**
* Expand expansion forms (plural, select) to directives
*
* @internal
*/
class _Expander {
constructor() {
this.isExpanded = false;
this.errors = [];
}
visitElement(element, context) {
return new Element$1(element.name, element.attrs, visitAll$1(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan);
}
visitAttribute(attribute, context) {
return attribute;
}
visitText(text, context) {
return text;
}
visitComment(comment, context) {
return comment;
}
visitExpansion(icu, context) {
this.isExpanded = true;
return icu.type == 'plural' ? _expandPluralForm(icu, this.errors) :
_expandDefaultForm(icu, this.errors);
}
visitExpansionCase(icuCase, context) {
throw new Error('Should not be reached');
}
}
// Plural forms are expanded to `NgPlural` and `NgPluralCase`s
function _expandPluralForm(ast, errors) {
const children = ast.cases.map(c => {
if (PLURAL_CASES.indexOf(c.value) == -1 && !c.value.match(/^=\d+$/)) {
errors.push(new ExpansionError(c.valueSourceSpan, `Plural cases should be "=" or one of ${PLURAL_CASES.join(', ')}`));
}
const expansionResult = expandNodes(c.expression);
errors.push(...expansionResult.errors);
return new Element$1(`ng-template`, [new Attribute('ngPluralCase', `${c.value}`, c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
const switchAttr = new Attribute('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan);
return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}
// ICU messages (excluding plural form) are expanded to `NgSwitch` and `NgSwitchCase`s
function _expandDefaultForm(ast, errors) {
const children = ast.cases.map(c => {
const expansionResult = expandNodes(c.expression);
errors.push(...expansionResult.errors);
if (c.value === 'other') {
// other is the default case when no values match
return new Element$1(`ng-template`, [new Attribute('ngSwitchDefault', '', c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
}
return new Element$1(`ng-template`, [new Attribute('ngSwitchCase', `${c.value}`, c.valueSourceSpan)], expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
const switchAttr = new Attribute('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan);
return new Element$1('ng-container', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* A segment of text within the template.
*/
class TextAst {
constructor(value, ngContentIndex, sourceSpan) {
this.value = value;
this.ngContentIndex = ngContentIndex;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitText(this, context);
}
}
/**
* A bound expression within the text of a template.
*/
class BoundTextAst {
constructor(value, ngContentIndex, sourceSpan) {
this.value = value;
this.ngContentIndex = ngContentIndex;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitBoundText(this, context);
}
}
/**
* A plain attribute on an element.
*/
class AttrAst {
constructor(name, value, sourceSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitAttr(this, context);
}
}
const BoundPropertyMapping = {
[4 /* Animation */]: 4 /* Animation */,
[1 /* Attribute */]: 1 /* Attribute */,
[2 /* Class */]: 2 /* Class */,
[0 /* Property */]: 0 /* Property */,
[3 /* Style */]: 3 /* Style */,
};
/**
* A binding for an element property (e.g. `[property]="expression"`) or an animation trigger (e.g.
* `[@trigger]="stateExp"`)
*/
class BoundElementPropertyAst {
constructor(name, type, securityContext, value, unit, sourceSpan) {
this.name = name;
this.type = type;
this.securityContext = securityContext;
this.value = value;
this.unit = unit;
this.sourceSpan = sourceSpan;
this.isAnimation = this.type === 4 /* Animation */;
}
static fromBoundProperty(prop) {
const type = BoundPropertyMapping[prop.type];
return new BoundElementPropertyAst(prop.name, type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan);
}
visit(visitor, context) {
return visitor.visitElementProperty(this, context);
}
}
/**
* A binding for an element event (e.g. `(event)="handler()"`) or an animation trigger event (e.g.
* `(@trigger.phase)="callback($event)"`).
*/
class BoundEventAst {
constructor(name, target, phase, handler, sourceSpan, handlerSpan) {
this.name = name;
this.target = target;
this.phase = phase;
this.handler = handler;
this.sourceSpan = sourceSpan;
this.handlerSpan = handlerSpan;
this.fullName = BoundEventAst.calcFullName(this.name, this.target, this.phase);
this.isAnimation = !!this.phase;
}
static calcFullName(name, target, phase) {
if (target) {
return `${target}:${name}`;
}
if (phase) {
return `@${name}.${phase}`;
}
return name;
}
static fromParsedEvent(event) {
const target = event.type === 0 /* Regular */ ? event.targetOrPhase : null;
const phase = event.type === 1 /* Animation */ ? event.targetOrPhase : null;
return new BoundEventAst(event.name, target, phase, event.handler, event.sourceSpan, event.handlerSpan);
}
visit(visitor, context) {
return visitor.visitEvent(this, context);
}
}
/**
* A reference declaration on an element (e.g. `let someName="expression"`).
*/
class ReferenceAst {
constructor(name, value, originalValue, sourceSpan) {
this.name = name;
this.value = value;
this.originalValue = originalValue;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitReference(this, context);
}
}
/**
* A variable declaration on a (e.g. `var-someName="someLocalName"`).
*/
class VariableAst {
constructor(name, value, sourceSpan, valueSpan) {
this.name = name;
this.value = value;
this.sourceSpan = sourceSpan;
this.valueSpan = valueSpan;
}
static fromParsedVariable(v) {
return new VariableAst(v.name, v.value, v.sourceSpan, v.valueSpan);
}
visit(visitor, context) {
return visitor.visitVariable(this, context);
}
}
/**
* An element declaration in a template.
*/
class ElementAst {
constructor(name, attrs, inputs, outputs, references, directives, providers, hasViewContainer, queryMatches, children, ngContentIndex, sourceSpan, endSourceSpan) {
this.name = name;
this.attrs = attrs;
this.inputs = inputs;
this.outputs = outputs;
this.references = references;
this.directives = directives;
this.providers = providers;
this.hasViewContainer = hasViewContainer;
this.queryMatches = queryMatches;
this.children = children;
this.ngContentIndex = ngContentIndex;
this.sourceSpan = sourceSpan;
this.endSourceSpan = endSourceSpan;
}
visit(visitor, context) {
return visitor.visitElement(this, context);
}
}
/**
* A `` element included in an Angular template.
*/
class EmbeddedTemplateAst {
constructor(attrs, outputs, references, variables, directives, providers, hasViewContainer, queryMatches, children, ngContentIndex, sourceSpan) {
this.attrs = attrs;
this.outputs = outputs;
this.references = references;
this.variables = variables;
this.directives = directives;
this.providers = providers;
this.hasViewContainer = hasViewContainer;
this.queryMatches = queryMatches;
this.children = children;
this.ngContentIndex = ngContentIndex;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitEmbeddedTemplate(this, context);
}
}
/**
* A directive property with a bound value (e.g. `*ngIf="condition").
*/
class BoundDirectivePropertyAst {
constructor(directiveName, templateName, value, sourceSpan) {
this.directiveName = directiveName;
this.templateName = templateName;
this.value = value;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitDirectiveProperty(this, context);
}
}
/**
* A directive declared on an element.
*/
class DirectiveAst {
constructor(directive, inputs, hostProperties, hostEvents, contentQueryStartId, sourceSpan) {
this.directive = directive;
this.inputs = inputs;
this.hostProperties = hostProperties;
this.hostEvents = hostEvents;
this.contentQueryStartId = contentQueryStartId;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitDirective(this, context);
}
}
/**
* A provider declared on an element
*/
class ProviderAst {
constructor(token, multiProvider, eager, providers, providerType, lifecycleHooks, sourceSpan, isModule) {
this.token = token;
this.multiProvider = multiProvider;
this.eager = eager;
this.providers = providers;
this.providerType = providerType;
this.lifecycleHooks = lifecycleHooks;
this.sourceSpan = sourceSpan;
this.isModule = isModule;
}
visit(visitor, context) {
// No visit method in the visitor for now...
return null;
}
}
var ProviderAstType;
(function (ProviderAstType) {
ProviderAstType[ProviderAstType["PublicService"] = 0] = "PublicService";
ProviderAstType[ProviderAstType["PrivateService"] = 1] = "PrivateService";
ProviderAstType[ProviderAstType["Component"] = 2] = "Component";
ProviderAstType[ProviderAstType["Directive"] = 3] = "Directive";
ProviderAstType[ProviderAstType["Builtin"] = 4] = "Builtin";
})(ProviderAstType || (ProviderAstType = {}));
/**
* Position where content is to be projected (instance of `` in a template).
*/
class NgContentAst {
constructor(index, ngContentIndex, sourceSpan) {
this.index = index;
this.ngContentIndex = ngContentIndex;
this.sourceSpan = sourceSpan;
}
visit(visitor, context) {
return visitor.visitNgContent(this, context);
}
}
/**
* A visitor that accepts each node but doesn't do anything. It is intended to be used
* as the base class for a visitor that is only interested in a subset of the node types.
*/
class NullTemplateVisitor {
visitNgContent(ast, context) { }
visitEmbeddedTemplate(ast, context) { }
visitElement(ast, context) { }
visitReference(ast, context) { }
visitVariable(ast, context) { }
visitEvent(ast, context) { }
visitElementProperty(ast, context) { }
visitAttr(ast, context) { }
visitBoundText(ast, context) { }
visitText(ast, context) { }
visitDirective(ast, context) { }
visitDirectiveProperty(ast, context) { }
}
/**
* Base class that can be used to build a visitor that visits each node
* in an template ast recursively.
*/
class RecursiveTemplateAstVisitor extends NullTemplateVisitor {
constructor() {
super();
}
// Nodes with children
visitEmbeddedTemplate(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.attrs);
visit(ast.references);
visit(ast.variables);
visit(ast.directives);
visit(ast.providers);
visit(ast.children);
});
}
visitElement(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.attrs);
visit(ast.inputs);
visit(ast.outputs);
visit(ast.references);
visit(ast.directives);
visit(ast.providers);
visit(ast.children);
});
}
visitDirective(ast, context) {
return this.visitChildren(context, visit => {
visit(ast.inputs);
visit(ast.hostProperties);
visit(ast.hostEvents);
});
}
visitChildren(context, cb) {
let results = [];
let t = this;
function visit(children) {
if (children && children.length)
results.push(templateVisitAll(t, children, context));
}
cb(visit);
return Array.prototype.concat.apply([], results);
}
}
/**
* Visit every node in a list of {@link TemplateAst}s with the given {@link TemplateAstVisitor}.
*/
function templateVisitAll(visitor, asts, context = null) {
const result = [];
const visit = visitor.visit ?
(ast) => visitor.visit(ast, context) || ast.visit(visitor, context) :
(ast) => ast.visit(visitor, context);
asts.forEach(ast => {
const astResult = visit(ast);
if (astResult) {
result.push(astResult);
}
});
return result;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class ProviderError extends ParseError {
constructor(message, span) {
super(span, message);
}
}
class ProviderViewContext {
constructor(reflector, component) {
this.reflector = reflector;
this.component = component;
this.errors = [];
this.viewQueries = _getViewQueries(component);
this.viewProviders = new Map();
component.viewProviders.forEach((provider) => {
if (this.viewProviders.get(tokenReference(provider.token)) == null) {
this.viewProviders.set(tokenReference(provider.token), true);
}
});
}
}
class ProviderElementContext {
constructor(viewContext, _parent, _isViewRoot, _directiveAsts, attrs, refs, isTemplate, contentQueryStartId, _sourceSpan) {
this.viewContext = viewContext;
this._parent = _parent;
this._isViewRoot = _isViewRoot;
this._directiveAsts = _directiveAsts;
this._sourceSpan = _sourceSpan;
this._transformedProviders = new Map();
this._seenProviders = new Map();
this._queriedTokens = new Map();
this.transformedHasViewContainer = false;
this._attrs = {};
attrs.forEach((attrAst) => this._attrs[attrAst.name] = attrAst.value);
const directivesMeta = _directiveAsts.map(directiveAst => directiveAst.directive);
this._allProviders =
_resolveProvidersFromDirectives(directivesMeta, _sourceSpan, viewContext.errors);
this._contentQueries = _getContentQueries(contentQueryStartId, directivesMeta);
Array.from(this._allProviders.values()).forEach((provider) => {
this._addQueryReadsTo(provider.token, provider.token, this._queriedTokens);
});
if (isTemplate) {
const templateRefId = createTokenForExternalReference(this.viewContext.reflector, Identifiers.TemplateRef);
this._addQueryReadsTo(templateRefId, templateRefId, this._queriedTokens);
}
refs.forEach((refAst) => {
let defaultQueryValue = refAst.value ||
createTokenForExternalReference(this.viewContext.reflector, Identifiers.ElementRef);
this._addQueryReadsTo({ value: refAst.name }, defaultQueryValue, this._queriedTokens);
});
if (this._queriedTokens.get(this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef))) {
this.transformedHasViewContainer = true;
}
// create the providers that we know are eager first
Array.from(this._allProviders.values()).forEach((provider) => {
const eager = provider.eager || this._queriedTokens.get(tokenReference(provider.token));
if (eager) {
this._getOrCreateLocalProvider(provider.providerType, provider.token, true);
}
});
}
afterElement() {
// collect lazy providers
Array.from(this._allProviders.values()).forEach((provider) => {
this._getOrCreateLocalProvider(provider.providerType, provider.token, false);
});
}
get transformProviders() {
// Note: Maps keep their insertion order.
const lazyProviders = [];
const eagerProviders = [];
this._transformedProviders.forEach(provider => {
if (provider.eager) {
eagerProviders.push(provider);
}
else {
lazyProviders.push(provider);
}
});
return lazyProviders.concat(eagerProviders);
}
get transformedDirectiveAsts() {
const sortedProviderTypes = this.transformProviders.map(provider => provider.token.identifier);
const sortedDirectives = this._directiveAsts.slice();
sortedDirectives.sort((dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
sortedProviderTypes.indexOf(dir2.directive.type));
return sortedDirectives;
}
get queryMatches() {
const allMatches = [];
this._queriedTokens.forEach((matches) => {
allMatches.push(...matches);
});
return allMatches;
}
_addQueryReadsTo(token, defaultValue, queryReadTokens) {
this._getQueriesFor(token).forEach((query) => {
const queryValue = query.meta.read || defaultValue;
const tokenRef = tokenReference(queryValue);
let queryMatches = queryReadTokens.get(tokenRef);
if (!queryMatches) {
queryMatches = [];
queryReadTokens.set(tokenRef, queryMatches);
}
queryMatches.push({ queryId: query.queryId, value: queryValue });
});
}
_getQueriesFor(token) {
const result = [];
let currentEl = this;
let distance = 0;
let queries;
while (currentEl !== null) {
queries = currentEl._contentQueries.get(tokenReference(token));
if (queries) {
result.push(...queries.filter((query) => query.meta.descendants || distance <= 1));
}
if (currentEl._directiveAsts.length > 0) {
distance++;
}
currentEl = currentEl._parent;
}
queries = this.viewContext.viewQueries.get(tokenReference(token));
if (queries) {
result.push(...queries);
}
return result;
}
_getOrCreateLocalProvider(requestingProviderType, token, eager) {
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider ||
((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.PrivateService) ||
((requestingProviderType === ProviderAstType.PrivateService ||
requestingProviderType === ProviderAstType.PublicService) &&
resolvedProvider.providerType === ProviderAstType.Builtin)) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (transformedProviderAst) {
return transformedProviderAst;
}
if (this._seenProviders.get(tokenReference(token)) != null) {
this.viewContext.errors.push(new ProviderError(`Cannot instantiate cyclic dependency! ${tokenName(token)}`, this._sourceSpan));
return null;
}
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps = undefined;
if (provider.useExisting != null) {
const existingDiDep = this._getDependency(resolvedProvider.providerType, { token: provider.useExisting }, eager);
if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token;
}
else {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
}
else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
}
else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(resolvedProvider.providerType, dep, eager));
}
return _transformProvider(provider, {
useExisting: transformedUseExisting,
useValue: transformedUseValue,
deps: transformedDeps
});
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, { eager: eager, providers: transformedProviders });
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
_getLocalDependency(requestingProviderType, dep, eager = false) {
if (dep.isAttribute) {
const attrValue = this._attrs[dep.token.value];
return { isValue: true, value: attrValue == null ? null : attrValue };
}
if (dep.token != null) {
// access builtints
if ((requestingProviderType === ProviderAstType.Directive ||
requestingProviderType === ProviderAstType.Component)) {
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.Renderer) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ElementRef) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ChangeDetectorRef) ||
tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.TemplateRef)) {
return dep;
}
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.ViewContainerRef)) {
this.transformedHasViewContainer = true;
}
}
// access the injector
if (tokenReference(dep.token) ===
this.viewContext.reflector.resolveExternalReference(Identifiers.Injector)) {
return dep;
}
// access providers
if (this._getOrCreateLocalProvider(requestingProviderType, dep.token, eager) != null) {
return dep;
}
}
return null;
}
_getDependency(requestingProviderType, dep, eager = false) {
let currElement = this;
let currEager = eager;
let result = null;
if (!dep.isSkipSelf) {
result = this._getLocalDependency(requestingProviderType, dep, eager);
}
if (dep.isSelf) {
if (!result && dep.isOptional) {
result = { isValue: true, value: null };
}
}
else {
// check parent elements
while (!result && currElement._parent) {
const prevElement = currElement;
currElement = currElement._parent;
if (prevElement._isViewRoot) {
currEager = false;
}
result = currElement._getLocalDependency(ProviderAstType.PublicService, dep, currEager);
}
// check @Host restriction
if (!result) {
if (!dep.isHost || this.viewContext.component.isHost ||
this.viewContext.component.type.reference === tokenReference(dep.token) ||
this.viewContext.viewProviders.get(tokenReference(dep.token)) != null) {
result = dep;
}
else {
result = dep.isOptional ? { isValue: true, value: null } : null;
}
}
}
if (!result) {
this.viewContext.errors.push(new ProviderError(`No provider for ${tokenName(dep.token)}`, this._sourceSpan));
}
return result;
}
}
class NgModuleProviderAnalyzer {
constructor(reflector, ngModule, extraProviders, sourceSpan) {
this.reflector = reflector;
this._transformedProviders = new Map();
this._seenProviders = new Map();
this._errors = [];
this._allProviders = new Map();
ngModule.transitiveModule.modules.forEach((ngModuleType) => {
const ngModuleProvider = { token: { identifier: ngModuleType }, useClass: ngModuleType };
_resolveProviders([ngModuleProvider], ProviderAstType.PublicService, true, sourceSpan, this._errors, this._allProviders, /* isModule */ true);
});
_resolveProviders(ngModule.transitiveModule.providers.map(entry => entry.provider).concat(extraProviders), ProviderAstType.PublicService, false, sourceSpan, this._errors, this._allProviders,
/* isModule */ false);
}
parse() {
Array.from(this._allProviders.values()).forEach((provider) => {
this._getOrCreateLocalProvider(provider.token, provider.eager);
});
if (this._errors.length > 0) {
const errorString = this._errors.join('\n');
throw new Error(`Provider parse errors:\n${errorString}`);
}
// Note: Maps keep their insertion order.
const lazyProviders = [];
const eagerProviders = [];
this._transformedProviders.forEach(provider => {
if (provider.eager) {
eagerProviders.push(provider);
}
else {
lazyProviders.push(provider);
}
});
return lazyProviders.concat(eagerProviders);
}
_getOrCreateLocalProvider(token, eager) {
const resolvedProvider = this._allProviders.get(tokenReference(token));
if (!resolvedProvider) {
return null;
}
let transformedProviderAst = this._transformedProviders.get(tokenReference(token));
if (transformedProviderAst) {
return transformedProviderAst;
}
if (this._seenProviders.get(tokenReference(token)) != null) {
this._errors.push(new ProviderError(`Cannot instantiate cyclic dependency! ${tokenName(token)}`, resolvedProvider.sourceSpan));
return null;
}
this._seenProviders.set(tokenReference(token), true);
const transformedProviders = resolvedProvider.providers.map((provider) => {
let transformedUseValue = provider.useValue;
let transformedUseExisting = provider.useExisting;
let transformedDeps = undefined;
if (provider.useExisting != null) {
const existingDiDep = this._getDependency({ token: provider.useExisting }, eager, resolvedProvider.sourceSpan);
if (existingDiDep.token != null) {
transformedUseExisting = existingDiDep.token;
}
else {
transformedUseExisting = null;
transformedUseValue = existingDiDep.value;
}
}
else if (provider.useFactory) {
const deps = provider.deps || provider.useFactory.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
}
else if (provider.useClass) {
const deps = provider.deps || provider.useClass.diDeps;
transformedDeps =
deps.map((dep) => this._getDependency(dep, eager, resolvedProvider.sourceSpan));
}
return _transformProvider(provider, {
useExisting: transformedUseExisting,
useValue: transformedUseValue,
deps: transformedDeps
});
});
transformedProviderAst =
_transformProviderAst(resolvedProvider, { eager: eager, providers: transformedProviders });
this._transformedProviders.set(tokenReference(token), transformedProviderAst);
return transformedProviderAst;
}
_getDependency(dep, eager = false, requestorSourceSpan) {
let foundLocal = false;
if (!dep.isSkipSelf && dep.token != null) {
// access the injector
if (tokenReference(dep.token) ===
this.reflector.resolveExternalReference(Identifiers.Injector) ||
tokenReference(dep.token) ===
this.reflector.resolveExternalReference(Identifiers.ComponentFactoryResolver)) {
foundLocal = true;
// access providers
}
else if (this._getOrCreateLocalProvider(dep.token, eager) != null) {
foundLocal = true;
}
}
return dep;
}
}
function _transformProvider(provider, { useExisting, useValue, deps }) {
return {
token: provider.token,
useClass: provider.useClass,
useExisting: useExisting,
useFactory: provider.useFactory,
useValue: useValue,
deps: deps,
multi: provider.multi
};
}
function _transformProviderAst(provider, { eager, providers }) {
return new ProviderAst(provider.token, provider.multiProvider, provider.eager || eager, providers, provider.providerType, provider.lifecycleHooks, provider.sourceSpan, provider.isModule);
}
function _resolveProvidersFromDirectives(directives, sourceSpan, targetErrors) {
const providersByToken = new Map();
directives.forEach((directive) => {
const dirProvider = { token: { identifier: directive.type }, useClass: directive.type };
_resolveProviders([dirProvider], directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
});
// Note: directives need to be able to overwrite providers of a component!
const directivesWithComponentFirst = directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent));
directivesWithComponentFirst.forEach((directive) => {
_resolveProviders(directive.providers, ProviderAstType.PublicService, false, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
_resolveProviders(directive.viewProviders, ProviderAstType.PrivateService, false, sourceSpan, targetErrors, providersByToken, /* isModule */ false);
});
return providersByToken;
}
function _resolveProviders(providers, providerType, eager, sourceSpan, targetErrors, targetProvidersByToken, isModule) {
providers.forEach((provider) => {
let resolvedProvider = targetProvidersByToken.get(tokenReference(provider.token));
if (resolvedProvider != null && !!resolvedProvider.multiProvider !== !!provider.multi) {
targetErrors.push(new ProviderError(`Mixing multi and non multi provider is not possible for token ${tokenName(resolvedProvider.token)}`, sourceSpan));
}
if (!resolvedProvider) {
const lifecycleHooks = provider.token.identifier &&
provider.token.identifier.lifecycleHooks ?
provider.token.identifier.lifecycleHooks :
[];
const isUseValue = !(provider.useClass || provider.useExisting || provider.useFactory);
resolvedProvider = new ProviderAst(provider.token, !!provider.multi, eager || isUseValue, [provider], providerType, lifecycleHooks, sourceSpan, isModule);
targetProvidersByToken.set(tokenReference(provider.token), resolvedProvider);
}
else {
if (!provider.multi) {
resolvedProvider.providers.length = 0;
}
resolvedProvider.providers.push(provider);
}
});
}
function _getViewQueries(component) {
// Note: queries start with id 1 so we can use the number in a Bloom filter!
let viewQueryId = 1;
const viewQueries = new Map();
if (component.viewQueries) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, { meta: query, queryId: viewQueryId++ }));
}
return viewQueries;
}
function _getContentQueries(contentQueryStartId, directives) {
let contentQueryId = contentQueryStartId;
const contentQueries = new Map();
directives.forEach((directive, directiveIndex) => {
if (directive.queries) {
directive.queries.forEach((query) => _addQueryToTokenMap(contentQueries, { meta: query, queryId: contentQueryId++ }));
}
});
return contentQueries;
}
function _addQueryToTokenMap(map, query) {
query.meta.selectors.forEach((token) => {
let entry = map.get(tokenReference(token));
if (!entry) {
entry = [];
map.set(tokenReference(token), entry);
}
entry.push(query);
});
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
class StyleWithImports {
constructor(style, styleUrls) {
this.style = style;
this.styleUrls = styleUrls;
}
}
function isStyleUrlResolvable(url) {
if (url == null || url.length === 0 || url[0] == '/')
return false;
const schemeMatch = url.match(URL_WITH_SCHEMA_REGEXP);
return schemeMatch === null || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset';
}
/**
* Rewrites stylesheets by resolving and removing the @import urls that
* are either relative or don't have a `package:` scheme
*/
function extractStyleUrls(resolver, baseUrl, cssText) {
const foundUrls = [];
const modifiedCssText = cssText.replace(CSS_STRIPPABLE_COMMENT_REGEXP, '')
.replace(CSS_IMPORT_REGEXP, (...m) => {
const url = m[1] || m[2];
if (!isStyleUrlResolvable(url)) {
// Do not attempt to resolve non-package absolute URLs with URI
// scheme
return m[0];
}
foundUrls.push(resolver.resolve(baseUrl, url));
return '';
});
return new StyleWithImports(modifiedCssText, foundUrls);
}
const CSS_IMPORT_REGEXP = /@import\s+(?:url\()?\s*(?:(?:['"]([^'"]*))|([^;\)\s]*))[^;]*;?/g;
const CSS_STRIPPABLE_COMMENT_REGEXP = /\/\*(?!#\s*(?:sourceURL|sourceMappingURL)=)[\s\S]+?\*\//g;
const URL_WITH_SCHEMA_REGEXP = /^([^:/?#]+):/;
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const PROPERTY_PARTS_SEPARATOR = '.';
const ATTRIBUTE_PREFIX = 'attr';
const CLASS_PREFIX = 'class';
const STYLE_PREFIX = 'style';
const TEMPLATE_ATTR_PREFIX = '*';
const ANIMATE_PROP_PREFIX = 'animate-';
/**
* Parses bindings in templates and in the directive host area.
*/
class BindingParser {
constructor(_exprParser, _interpolationConfig, _schemaRegistry, pipes, errors) {
this._exprParser = _exprParser;
this._interpolationConfig = _interpolationConfig;
this._schemaRegistry = _schemaRegistry;
this.errors = errors;
this.pipesByName = null;
this._usedPipes = new Map();
// When the `pipes` parameter is `null`, do not check for used pipes
// This is used in IVY when we might not know the available pipes at compile time
if (pipes) {
const pipesByName = new Map();
pipes.forEach(pipe => pipesByName.set(pipe.name, pipe));
this.pipesByName = pipesByName;
}
}
get interpolationConfig() {
return this._interpolationConfig;
}
getUsedPipes() {
return Array.from(this._usedPipes.values());
}
createBoundHostProperties(dirMeta, sourceSpan) {
if (dirMeta.hostProperties) {
const boundProps = [];
Object.keys(dirMeta.hostProperties).forEach(propName => {
const expression = dirMeta.hostProperties[propName];
if (typeof expression === 'string') {
this.parsePropertyBinding(propName, expression, true, sourceSpan, sourceSpan.start.offset, undefined, [], boundProps);
}
else {
this._reportError(`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
});
return boundProps;
}
return null;
}
createDirectiveHostPropertyAsts(dirMeta, elementSelector, sourceSpan) {
const boundProps = this.createBoundHostProperties(dirMeta, sourceSpan);
return boundProps &&
boundProps.map((prop) => this.createBoundElementProperty(elementSelector, prop));
}
createDirectiveHostEventAsts(dirMeta, sourceSpan) {
if (dirMeta.hostListeners) {
const targetEvents = [];
Object.keys(dirMeta.hostListeners).forEach(propName => {
const expression = dirMeta.hostListeners[propName];
if (typeof expression === 'string') {
// TODO: pass a more accurate handlerSpan for this event.
this.parseEvent(propName, expression, sourceSpan, sourceSpan, [], targetEvents);
}
else {
this._reportError(`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
}
});
return targetEvents;
}
return null;
}
parseInterpolation(value, sourceSpan) {
const sourceInfo = sourceSpan.start.toString();
try {
const ast = this._exprParser.parseInterpolation(value, sourceInfo, sourceSpan.start.offset, this._interpolationConfig);
if (ast)
this._reportExpressionParserErrors(ast.errors, sourceSpan);
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, sourceSpan.start.offset);
}
}
/**
* Parses the bindings in a microsyntax expression, and converts them to
* `ParsedProperty` or `ParsedVariable`.
*
* @param tplKey template binding name
* @param tplValue template binding value
* @param sourceSpan span of template binding relative to entire the template
* @param absoluteValueOffset start of the tplValue relative to the entire template
* @param targetMatchableAttrs potential attributes to match in the template
* @param targetProps target property bindings in the template
* @param targetVars target variables in the template
*/
parseInlineTemplateBinding(tplKey, tplValue, sourceSpan, absoluteValueOffset, targetMatchableAttrs, targetProps, targetVars) {
const absoluteKeyOffset = sourceSpan.start.offset + TEMPLATE_ATTR_PREFIX.length;
const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset);
for (const binding of bindings) {
// sourceSpan is for the entire HTML attribute. bindingSpan is for a particular
// binding within the microsyntax expression so it's more narrow than sourceSpan.
const bindingSpan = moveParseSourceSpan(sourceSpan, binding.sourceSpan);
const key = binding.key.source;
const keySpan = moveParseSourceSpan(sourceSpan, binding.key.span);
if (binding instanceof VariableBinding) {
const value = binding.value ? binding.value.source : '$implicit';
const valueSpan = binding.value ? moveParseSourceSpan(sourceSpan, binding.value.span) : undefined;
targetVars.push(new ParsedVariable(key, value, bindingSpan, keySpan, valueSpan));
}
else if (binding.value) {
const valueSpan = moveParseSourceSpan(sourceSpan, binding.value.ast.sourceSpan);
this._parsePropertyAst(key, binding.value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps);
}
else {
targetMatchableAttrs.push([key, '']);
this.parseLiteralAttr(key, null, sourceSpan, absoluteValueOffset, undefined, targetMatchableAttrs, targetProps);
}
}
}
/**
* Parses the bindings in a microsyntax expression, e.g.
* ```
*
* ```
*
* @param tplKey template binding name
* @param tplValue template binding value
* @param sourceSpan span of template binding relative to entire the template
* @param absoluteKeyOffset start of the `tplKey`
* @param absoluteValueOffset start of the `tplValue`
*/
_parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset) {
const sourceInfo = sourceSpan.start.toString();
try {
const bindingsResult = this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceInfo, absoluteKeyOffset, absoluteValueOffset);
this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
bindingsResult.templateBindings.forEach((binding) => {
if (binding.value instanceof ASTWithSource) {
this._checkPipes(binding.value, sourceSpan);
}
});
bindingsResult.warnings.forEach((warning) => {
this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING);
});
return bindingsResult.templateBindings;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return [];
}
}
parseLiteralAttr(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
if (isAnimationLabel(name)) {
name = name.substring(1);
if (value) {
this._reportError(`Assigning animation triggers via @prop="exp" attributes with an expression is invalid.` +
` Use property bindings (e.g. [@prop]="exp") or use an attribute without a value (e.g. @prop) instead.`, sourceSpan, ParseErrorLevel.ERROR);
}
this._parseAnimation(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps);
}
else {
targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, valueSpan));
}
}
parsePropertyBinding(name, expression, isHost, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
if (name.length === 0) {
this._reportError(`Property name is missing in binding`, sourceSpan);
}
let isAnimationProp = false;
if (name.startsWith(ANIMATE_PROP_PREFIX)) {
isAnimationProp = true;
name = name.substring(ANIMATE_PROP_PREFIX.length);
}
else if (isAnimationLabel(name)) {
isAnimationProp = true;
name = name.substring(1);
}
if (isAnimationProp) {
this._parseAnimation(name, expression, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps);
}
else {
this._parsePropertyAst(name, this._parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, valueSpan, targetMatchableAttrs, targetProps);
}
}
parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps) {
const expr = this.parseInterpolation(value, valueSpan || sourceSpan);
if (expr) {
this._parsePropertyAst(name, expr, sourceSpan, valueSpan, targetMatchableAttrs, targetProps);
return true;
}
return false;
}
_parsePropertyAst(name, ast, sourceSpan, valueSpan, targetMatchableAttrs, targetProps) {
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.DEFAULT, sourceSpan, valueSpan));
}
_parseAnimation(name, expression, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps) {
if (name.length === 0) {
this._reportError('Animation trigger is missing', sourceSpan);
}
// This will occur when a @trigger is not paired with an expression.
// For animations it is valid to not have an expression since */void
// states will be applied by angular when the element is attached/detached
const ast = this._parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset);
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, valueSpan));
}
_parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) {
const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown)').toString();
try {
const ast = isHostBinding ?
this._exprParser.parseSimpleBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig) :
this._exprParser.parseBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig);
if (ast)
this._reportExpressionParserErrors(ast.errors, sourceSpan);
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
}
createBoundElementProperty(elementSelector, boundProp, skipValidation = false, mapPropertyName = true) {
if (boundProp.isAnimation) {
return new BoundElementProperty(boundProp.name, 4 /* Animation */, SecurityContext.NONE, boundProp.expression, null, boundProp.sourceSpan, boundProp.valueSpan);
}
let unit = null;
let bindingType = undefined;
let boundPropertyName = null;
const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
let securityContexts = undefined;
// Check for special cases (prefix style, attr, class)
if (parts.length > 1) {
if (parts[0] == ATTRIBUTE_PREFIX) {
boundPropertyName = parts.slice(1).join(PROPERTY_PARTS_SEPARATOR);
if (!skipValidation) {
this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
}
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, boundPropertyName, true);
const nsSeparatorIdx = boundPropertyName.indexOf(':');
if (nsSeparatorIdx > -1) {
const ns = boundPropertyName.substring(0, nsSeparatorIdx);
const name = boundPropertyName.substring(nsSeparatorIdx + 1);
boundPropertyName = mergeNsAndName(ns, name);
}
bindingType = 1 /* Attribute */;
}
else if (parts[0] == CLASS_PREFIX) {
boundPropertyName = parts[1];
bindingType = 2 /* Class */;
securityContexts = [SecurityContext.NONE];
}
else if (parts[0] == STYLE_PREFIX) {
unit = parts.length > 2 ? parts[2] : null;
boundPropertyName = parts[1];
bindingType = 3 /* Style */;
securityContexts = [SecurityContext.STYLE];
}
}
// If not a special case, use the full property name
if (boundPropertyName === null) {
const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name);
boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name;
securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false);
bindingType = 0 /* Property */;
if (!skipValidation) {
this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false);
}
}
return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.valueSpan);
}
parseEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents) {
if (name.length === 0) {
this._reportError(`Event name is missing in binding`, sourceSpan);
}
if (isAnimationLabel(name)) {
name = name.substr(1);
this._parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents);
}
else {
this._parseRegularEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents);
}
}
calcPossibleSecurityContexts(selector, propName, isAttribute) {
const prop = this._schemaRegistry.getMappedPropName(propName);
return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
}
_parseAnimationEvent(name, expression, sourceSpan, handlerSpan, targetEvents) {
const matches = splitAtPeriod(name, [name, '']);
const eventName = matches[0];
const phase = matches[1].toLowerCase();
if (phase) {
switch (phase) {
case 'start':
case 'done':
const ast = this._parseAction(expression, handlerSpan);
targetEvents.push(new ParsedEvent(eventName, phase, 1 /* Animation */, ast, sourceSpan, handlerSpan));
break;
default:
this._reportError(`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, sourceSpan);
break;
}
}
else {
this._reportError(`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, sourceSpan);
}
}
_parseRegularEvent(name, expression, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents) {
// long format: 'target: eventName'
const [target, eventName] = splitAtColon(name, [null, name]);
const ast = this._parseAction(expression, handlerSpan);
targetMatchableAttrs.push([name, ast.source]);
targetEvents.push(new ParsedEvent(eventName, target, 0 /* Regular */, ast, sourceSpan, handlerSpan));
// Don't detect directives for event names for now,
// so don't add the event name to the matchableAttrs
}
_parseAction(value, sourceSpan) {
const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown').toString();
const absoluteOffset = (sourceSpan && sourceSpan.start) ? sourceSpan.start.offset : 0;
try {
const ast = this._exprParser.parseAction(value, sourceInfo, absoluteOffset, this._interpolationConfig);
if (ast) {
this._reportExpressionParserErrors(ast.errors, sourceSpan);
}
if (!ast || ast.ast instanceof EmptyExpr) {
this._reportError(`Empty expressions are not allowed`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
this._checkPipes(ast, sourceSpan);
return ast;
}
catch (e) {
this._reportError(`${e}`, sourceSpan);
return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
}
}
_reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
this.errors.push(new ParseError(sourceSpan, message, level));
}
_reportExpressionParserErrors(errors, sourceSpan) {
for (const error of errors) {
this._reportError(error.message, sourceSpan);
}
}
// Make sure all the used pipes are known in `this.pipesByName`
_checkPipes(ast, sourceSpan) {
if (ast && this.pipesByName) {
const collector = new PipeCollector();
ast.visit(collector);
collector.pipes.forEach((ast, pipeName) => {
const pipeMeta = this.pipesByName.get(pipeName);
if (!pipeMeta) {
this._reportError(`The pipe '${pipeName}' could not be found`, new ParseSourceSpan(sourceSpan.start.moveBy(ast.span.start), sourceSpan.start.moveBy(ast.span.end)));
}
else {
this._usedPipes.set(pipeName, pipeMeta);
}
});
}
}
/**
* @param propName the name of the property / attribute
* @param sourceSpan
* @param isAttr true when binding to an attribute
*/
_validatePropertyOrAttributeName(propName, sourceSpan, isAttr) {
const report = isAttr ? this._schemaRegistry.validateAttribute(propName) :
this._schemaRegistry.validateProperty(propName);
if (report.error) {
this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR);
}
}
}
class PipeCollector extends RecursiveAstVisitor$1 {
constructor() {
super(...arguments);
this.pipes = new Map();
}
visitPipe(ast, context) {
this.pipes.set(ast.name, ast);
ast.exp.visit(this);
this.visitAll(ast.args, context);
return null;
}
}
function isAnimationLabel(name) {
return name[0] == '@';
}
function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
const ctxs = [];
CssSelector.parse(selector).forEach((selector) => {
const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
const notElementNames = new Set(selector.notSelectors.filter(selector => selector.isElementSelector())
.map((selector) => selector.element));
const possibleElementNames = elementNames.filter(elementName => !notElementNames.has(elementName));
ctxs.push(...possibleElementNames.map(elementName => registry.securityContext(elementName, propName, isAttribute)));
});
return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
}
/**
* Compute a new ParseSourceSpan based off an original `sourceSpan` by using
* absolute offsets from the specified `absoluteSpan`.
*
* @param sourceSpan original source span
* @param absoluteSpan absolute source span to move to
*/
function moveParseSourceSpan(sourceSpan, absoluteSpan) {
// The difference of two absolute offsets provide the relative offset
const startDiff = absoluteSpan.start - sourceSpan.start.offset;
const endDiff = absoluteSpan.end - sourceSpan.end.offset;
return new ParseSourceSpan(sourceSpan.start.moveBy(startDiff), sourceSpan.end.moveBy(endDiff));
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const NG_CONTENT_SELECT_ATTR = 'select';
const LINK_ELEMENT = 'link';
const LINK_STYLE_REL_ATTR = 'rel';
const LINK_STYLE_HREF_ATTR = 'href';
const LINK_STYLE_REL_VALUE = 'stylesheet';
const STYLE_ELEMENT = 'style';
const SCRIPT_ELEMENT = 'script';
const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
const NG_PROJECT_AS = 'ngProjectAs';
function preparseElement(ast) {
let selectAttr = null;
let hrefAttr = null;
let relAttr = null;
let nonBindable = false;
let projectAs = '';
ast.attrs.forEach(attr => {
const lcAttrName = attr.name.toLowerCase();
if (lcAttrName == NG_CONTENT_SELECT_ATTR) {
selectAttr = attr.value;
}
else if (lcAttrName == LINK_STYLE_HREF_ATTR) {
hrefAttr = attr.value;
}
else if (lcAttrName == LINK_STYLE_REL_ATTR) {
relAttr = attr.value;
}
else if (attr.name == NG_NON_BINDABLE_ATTR) {
nonBindable = true;
}
else if (attr.name == NG_PROJECT_AS) {
if (attr.value.length > 0) {
projectAs = attr.value;
}
}
});
selectAttr = normalizeNgContentSelect(selectAttr);
const nodeName = ast.name.toLowerCase();
let type = PreparsedElementType.OTHER;
if (isNgContent(nodeName)) {
type = PreparsedElementType.NG_CONTENT;
}
else if (nodeName == STYLE_ELEMENT) {
type = PreparsedElementType.STYLE;
}
else if (nodeName == SCRIPT_ELEMENT) {
type = PreparsedElementType.SCRIPT;
}
else if (nodeName == LINK_ELEMENT && relAttr == LINK_STYLE_REL_VALUE) {
type = PreparsedElementType.STYLESHEET;
}
return new PreparsedElement(type, selectAttr, hrefAttr, nonBindable, projectAs);
}
var PreparsedElementType;
(function (PreparsedElementType) {
PreparsedElementType[PreparsedElementType["NG_CONTENT"] = 0] = "NG_CONTENT";
PreparsedElementType[PreparsedElementType["STYLE"] = 1] = "STYLE";
PreparsedElementType[PreparsedElementType["STYLESHEET"] = 2] = "STYLESHEET";
PreparsedElementType[PreparsedElementType["SCRIPT"] = 3] = "SCRIPT";
PreparsedElementType[PreparsedElementType["OTHER"] = 4] = "OTHER";
})(PreparsedElementType || (PreparsedElementType = {}));
class PreparsedElement {
constructor(type, selectAttr, hrefAttr, nonBindable, projectAs) {
this.type = type;
this.selectAttr = selectAttr;
this.hrefAttr = hrefAttr;
this.nonBindable = nonBindable;
this.projectAs = projectAs;
}
}
function normalizeNgContentSelect(selectAttr) {
if (selectAttr === null || selectAttr.length === 0) {
return '*';
}
return selectAttr;
}
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const BIND_NAME_REGEXP = /^(?:(?:(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.*))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/;
// Group 1 = "bind-"
const KW_BIND_IDX = 1;
// Group 2 = "let-"
const KW_LET_IDX = 2;
// Group 3 = "ref-/#"
const KW_REF_IDX = 3;
// Group 4 = "on-"
const KW_ON_IDX = 4;
// Group 5 = "bindon-"
const KW_BINDON_IDX = 5;
// Group 6 = "@"
const KW_AT_IDX = 6;
// Group 7 = the identifier after "bind-", "let-", "ref-/#", "on-", "bindon-" or "@"
const IDENT_KW_IDX = 7;
// Group 8 = identifier inside [()]
const IDENT_BANANA_BOX_IDX = 8;
// Group 9 = identifier inside []
const IDENT_PROPERTY_IDX = 9;
// Group 10 = identifier inside ()
const IDENT_EVENT_IDX = 10;
const TEMPLATE_ATTR_PREFIX$1 = '*';
const CLASS_ATTR = 'class';
let _TEXT_CSS_SELECTOR;
function TEXT_CSS_SELECTOR() {
if (!_TEXT_CSS_SELECTOR) {
_TEXT_CSS_SELECTOR = CssSelector.parse('*')[0];
}
return _TEXT_CSS_SELECTOR;
}
class TemplateParseError extends ParseError {
constructor(message, span, level) {
super(span, message, level);
}
}
class TemplateParseResult {
constructor(templateAst, usedPipes, errors) {
this.templateAst = templateAst;
this.usedPipes = usedPipes;
this.errors = errors;
}
}
class TemplateParser {
constructor(_config, _reflector, _exprParser, _schemaRegistry, _htmlParser, _console, transforms) {
this._config = _config;
this._reflector = _reflector;
this._exprParser = _exprParser;
this._schemaRegistry = _schemaRegistry;
this._htmlParser = _htmlParser;
this._console = _console;
this.transforms = transforms;
}
get expressionParser() {
return this._exprParser;
}
parse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) {
var _a;
const result = this.tryParse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces);
const warnings = result.errors.filter(error => error.level === ParseErrorLevel.WARNING);
const errors = result.errors.filter(error => error.level === ParseErrorLevel.ERROR);
if (warnings.length > 0) {
(_a = this._console) === null || _a === void 0 ? void 0 : _a.warn(`Template parse warnings:\n${warnings.join('\n')}`);
}
if (errors.length > 0) {
const errorString = errors.join('\n');
throw syntaxError(`Template parse errors:\n${errorString}`, errors);
}
return { template: result.templateAst, pipes: result.usedPipes };
}
tryParse(component, template, directives, pipes, schemas, templateUrl, preserveWhitespaces) {
let htmlParseResult = typeof template === 'string' ?
this._htmlParser.parse(template, templateUrl, {
tokenizeExpansionForms: true,
interpolationConfig: this.getInterpolationConfig(component)
}) :
template;
if (!preserveWhitespaces) {
htmlParseResult = removeWhitespaces(htmlParseResult);
}
return this.tryParseHtml(this.expandHtml(htmlParseResult), component, directives, pipes, schemas);
}
tryParseHtml(htmlAstWithErrors, component, directives, pipes, schemas) {
let result;
const errors = htmlAstWithErrors.errors;
const usedPipes = [];
if (htmlAstWithErrors.rootNodes.length > 0) {
const uniqDirectives = removeSummaryDuplicates(directives);
const uniqPipes = removeSummaryDuplicates(pipes);
const providerViewContext = new ProviderViewContext(this._reflector, component);
let interpolationConfig = undefined;
if (component.template && component.template.interpolation) {
interpolationConfig = {
start: component.template.interpolation[0],
end: component.template.interpolation[1]
};
}
const bindingParser = new BindingParser(this._exprParser, interpolationConfig, this._schemaRegistry, uniqPipes, errors);
const parseVisitor = new TemplateParseVisitor(this._reflector, this._config, providerViewContext, uniqDirectives, bindingParser, this._schemaRegistry, schemas, errors);
result = visitAll$1(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_ELEMENT_CONTEXT);
errors.push(...providerViewContext.errors);
usedPipes.push(...bindingParser.getUsedPipes());
}
else {
result = [];
}
this._assertNoReferenceDuplicationOnTemplate(result, errors);
if (errors.length > 0) {
return new TemplateParseResult(result, usedPipes, errors);
}
if (this.transforms) {
this.transforms.forEach((transform) => {
result = templateVisitAll(transform, result);
});
}
return new TemplateParseResult(result, usedPipes, errors);
}
expandHtml(htmlAstWithErrors, forced = false) {
const errors = htmlAstWithErrors.errors;
if (errors.length == 0 || forced) {
// Transform ICU messages to angular directives
const expandedHtmlAst = expandNodes(htmlAstWithErrors.rootNodes);
errors.push(...expandedHtmlAst.errors);
htmlAstWithErrors = new ParseTreeResult(expandedHtmlAst.nodes, errors);
}
return htmlAstWithErrors;
}
getInterpolationConfig(component) {
if (component.template) {
return InterpolationConfig.fromArray(component.template.interpolation);
}
return undefined;
}
/** @internal */
_assertNoReferenceDuplicationOnTemplate(result, errors) {
const existingReferences = [];
result.filter(element => !!element.references)
.forEach(element => element.references.forEach((reference) => {
const name = reference.name;
if (existingReferences.indexOf(name) < 0) {
existingReferences.push(name);
}
else {
const error = new TemplateParseError(`Reference "#${name}" is defined several times`, reference.sourceSpan, ParseErrorLevel.ERROR);
errors.push(error);
}
}));
}
}
class TemplateParseVisitor {
constructor(reflector, config, providerViewContext, directives, _bindingParser, _schemaRegistry, _schemas, _targetErrors) {
this.reflector = reflector;
this.config = config;
this.providerViewContext = providerViewContext;
this._bindingParser = _bindingParser;
this._schemaRegistry = _schemaRegistry;
this._schemas = _schemas;
this._targetErrors = _targetErrors;
this.selectorMatcher = new SelectorMatcher();
this.directivesIndex = new Map();
this.ngContentCount = 0;
// Note: queries start with id 1 so we can use the number in a Bloom filter!
this.contentQueryStartId = providerViewContext.component.viewQueries.length + 1;
directives.forEach((directive, index) => {
const selector = CssSelector.parse(directive.selector);
this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index);
});
}
visitExpansion(expansion, context) {
return null;
}
visitExpansionCase(expansionCase, context) {
return null;
}
visitText(text, parent) {
const ngContentIndex = parent.findNgContentIndex(TEXT_CSS_SELECTOR());
const valueNoNgsp = replaceNgsp(text.value);
const expr = this._bindingParser.parseInterpolation(valueNoNgsp, text.sourceSpan);
return expr ? new BoundTextAst(expr, ngContentIndex, text.sourceSpan) :
new TextAst(valueNoNgsp, ngContentIndex, text.sourceSpan);
}
visitAttribute(attribute, context) {
return new AttrAst(attribute.name, attribute.value, attribute.sourceSpan);
}
visitComment(comment, context) {
return null;
}
visitElement(element, parent) {
const queryStartIndex = this.contentQueryStartId;
const elName = element.name;
const preparsedElement = preparseElement(element);
if (preparsedElement.type === PreparsedElementType.SCRIPT ||
preparsedElement.type === PreparsedElementType.STYLE) {
// Skipping